Scrambling strings with random.shuffle in Python 3.x - python

Hello I'm new to programming and have been teaching myself Python through various means for the past year.I have been lurking here for a while and have gotten a lot of help but now i have a specific problem:
Im working on a word scramble game and i ran into a snag.
Python 3.x code
def scrambler(word):
word_to_scramble = list(word)
random.shuffle(word_to_scramble)
new_word = ''.join(word_to_scramble)
return new_word
Now the code above works as desired, but occasionally it will return the original word i fed into the scrambler function.
My question is: Is there a way to ensure that the string returned is always different than the one given.
I attempted to use the scrambler function inside itself with a while loop, which would crash the script and give me an error stating the recursion limit had been reached.
Any help would be greatly appreciated.

If you're hitting the recursion limit, then it's likely that you're trying to scramble a 1-character word. However, it's quite easy to remove the recursion in this problem ...:
def _scrambler(word):
word_to_scramble = list(word)
random.shuffle(word_to_scramble)
new_word = ''.join(word_to_scramble)
return new_word
def scrambler(word):
new_word = _scrambler(word)
while new_word == word and len(word) > 1:
new_word = _scrambler(word)
return new_word
I've added a len(word) > 1 check so this should eventually give you a different word than what you put in if it is possible to do so.

hope you enjoy with programming Chris.
well if u test like this...
from random import shuffle
word='test'
def scrambler(word):
word_to_scramble = list(word)
shuffle(word_to_scramble)
new_word = ''.join(word_to_scramble)
return new_word
print(scrambler(word))
u will get the word test in ~ <25th try as i did ...(cant be sure because its not realy random)
so u can just put some if statement in your function. and if new_world is same as word u can just recall the function again... and it doesn't need any loop. its like some recursive base function.
something like this...
enter code here
from random import shuffle
word = 'test'
def scrambler(word):
word_to_scramble = list(word)
shuffle(word_to_scramble)
new_word = ''.join(word_to_scramble)
#print (new_word) if u want to check what is going on ...
if new_word == word:
scrambler(word)
elif new_word != word:
return new_word
print(new_word)
scrambler(word)

Related

Python Question Relating to Finding Anagram from Dictionary

I am struggling with this project that I am working on.
Edit: I want the program to find 2 words from the dictionary that are the anagram of the input word(s). The way I wanted to approach this program is by using counter(input()) and then looping through the dictionary content twice (finding first word anagram then the next). The loop would take every word from the dictionary, counter(that word) and see if it is <= counter(input word). Once the program finds first anagram, it adds that word to candidate and proceeds to second loop to find the second word.
To put to simple words, if I input a word (or a phrase), I would like the program to run through a dictionary text file (which I have saved) and find two words from the dictionary that becomes anagram to my input. For instance, if I input "dormitory" the program output should be "dirty room" and if input "a gentleman", output "elegant man". Here is what I have done so far:
from pathlib import Path
from collections import Counter
my_dictionary = open(Path.home() / 'dictionary.txt')
my_words = my_dictionary.read().strip().split('\n')
my_dictionary.close()
letter_number = 0
my_word = []
print('Please type in your phrase:')
word = input()
word = word.replace(" ","")
word_map = Counter(word.lower())
for a_word in my_words:
test = ''
candidate = ''
test_word = Counter(a_word.lower())
for letter in test_word:
if test_word[letter] <= word_map[letter]:
test += letter
if Counter(test) == test_word:
candidate += a_word.lower()
for a_word in my_words:
test = ''
test_word = Counter(a_word.lower())
for letter in test_word:
if test_word[letter] <= word_map[letter]:
test += letter
if Counter(test) == test_word:
candidate += a_word.lower()
if Counter(candidate) == word_map:
my_word.append(candidate)
print(my_word)
For some reason I am getting nothing from the output.
I cannot get any result after I put my input.
I also have tried to use del. command for getting rid of the word counter of first word from dictionary then proceed to find a second word from the dictionary but that didn't work either.
In summary, there must be some wrong place in the codes that flaws the program to not give any output.
Please help me figure out my mistake and error.
Thanks in advance.
Code can be optimized as follows:
# script.py
from pathlib import Path
from collections import Counter
filename = 'dictionary.txt'
my_words = Path.home().joinpath(filename).read_text().strip().splitlines()
word = input('Please type in your phrase:\n').replace(" ","")
word_counter = Counter(word.lower())
def parse(my_words=my_words):
matches = []
for a_word in my_words:
a_word_counter = Counter(a_word.lower())
if all(c <= word_counter[w] for c in a_word_counter.values()):
matches.append(a_word)
return matches
def exactly_parse(my_words=my_words):
return [w for w in my_words if Counter(w) == word_counter]
my_word = parse()
print(my_word)
Let's say content of dictionary.txt:
$ cat dictionary.txt
how
are
you
fine
thanks
input word is how
What's the expected output? how
$ python script.py
Please type in your phrase:
how
['how']
$ python script.py
Please type in your phrase:
thanksyou
['you', 'thanks']

Find frequency for a specific word in a given string

I have created some code in Python to find the top frequency word in a string. I am pretty new in Python and ask for your help to see if I could code this better and more effectively. (code below returns the frequency of the specified word). Since I am a beginning Python dev I have the feeling my code is unnecessarily long and could be written much better, only good thing is that the code works. But want to learn how I could do it better. I also don't know if my class WordCounter makes sense with it's attributes....
class WordCounter:
def __init__(self, word, frequency):
self.word = word
self.frequency = frequency
# calculate_frequency_for_word should return the frequency of the specified word
def frequency_specific_word(text: str, word: str) -> int:
lookup_word = word #this contains the specified word to search for
incoming_string = [word.lower() for word in text.split() if word.isalpha()]
count = 0 #count is increased when the specified word is found in the string
i=0 #this is used as counter for the index
j=0 #the loop will run from j=0 till the length on the incoming_string
length = len(incoming_string) #checking the length of incoming_string
while j < length:
j += 1
if lookup_word in incoming_string[i]: #Specified word is found, add 1 to count
count += 1
incoming_string[i] = incoming_string[i + 1] #move to next word in incoming string
else:
incoming_string[i] #Specified word not found, do nothing
#print("No," + lookup_word + " not found in List : " + incoming_string[i])
i += 1
return count
print("The word 'try' found " +str(WordCounter.frequency_specific_word("Your help is much appreciated, this code could be done much better I think, much much better", "much"))+" times in text\n")
You can try the list.count() method:
>>> s = "Your help is much appreciated, this code could be done much better I think, much much better"
>>> s.lower().split().count('much')
4
To eliminate punctuation, you can use the built-in re module:
>>> import re
>>> s = "Your help is much appreciated, this code could be done much better I think, much much better"
>>> re.findall(r'\b\w+\b', s.lower()).count('much')
4

How to create a function that will find all palingrams in a dictionary (including i and a)?

I'm currently stuck on a problem where I have to find all palingrams in a list. I made one piece of code, however it was not efficient at all and took around 3 and a half hours to finish. I needed to find something that is more time effect.
Right now I am currently stuck with this chunk of code:
import sys
def load(file):
"""Open a text file & turn contents into a list of lowercase strings."""
try:
with open(file) as in_file:
loaded_txt = in_file.read().strip().split('\n')
loaded_txt = [x.lower() for x in loaded_txt]
return loaded_txt
except IOError as e:
print("{}\nError opening {}. Terminating program.".format(e, file),
file=sys.stderr)
sys.exit(1)
def find_palingrams():
pali_list = []
for word in word_list:
if end > 1:
for i in range(end):
if word[i:] == rev_word[:end-i] and rev_word[end-i:] in word_list:
pali_list.append((word, rev_word[end-i:]))
if word[i:] == rev_word[end-i:] and rev_word[:end-i] in word_list:
pali_list.append((rev_word[end-i:], word))
return sorted(pali_list)
I'm having issues with this because it does not print specific outputs that I am looking for. It is printing words, but it is excluding cases such as "aa aa", "a ba", "a baba" etc. There is something that I am not seeing that is causing single letters to not be included fully. I am aware of the end > 1, however even with an attempt to change that I am met with confusion.
Could anyone shed some light?
I guess you mean Palindrome words.
An easier way to check if a word is palindrome:
>>> word = "level"
>>> word == word[::-1]
True
You may wanna use that cleaner way, and then add the word based on the test result:
if word == word[::-1]:
# add it to the list

Printing Parallel Tuples in python

I'm trying to make a word guessing program and I'm having trouble printing parallel tuples. I need to print the "secret word" with the corresponding hint, but the code that I wrote doesn't work. I can't figure out where I'm going wrong.
Any help would be appreciated :)
This is my code so far:
import random
Words = ("wallet","canine")
Hints = ("Portable money holder","Man's best friend")
vowels = "aeiouy"
secret_word = random.choice(Words)
new_word = ""
for letter in secret_word:
if letter in vowels:
new_word += '_'
else:
new_word += letter
maxIndex = len(Words)
for i in range(1):
random_int = random.randrange(maxIndex)
print(new_word,"\t\t\t",Hints[random_int])
The issue here is that random_int is, as defined, random. As a result you'll randomly get the right result sometimes.
A quick fix is by using the tuple.index method, get the index of the element inside the tuple Words and then use that index on Hints to get the corresponding word, your print statement looking like:
print(new_word,"\t\t\t",Hints[Words.index(secret_word)])
This does the trick but is clunky. Python has a data structure called a dictionary with which you can map one value to another. This could make your life easier in the long run. To create a dictionary from the two tuples we can zip them together:
mapping = dict(zip(Words, Hints))
and create a structure that looks like:
{'canine': "Man's best friend", 'wallet': 'Portable money holder'}
This helps.
Another detail you could fix is in how you create the new_word; instead of looping you can use a comprehension to create the respective letters and then join these on the empty string "" to create the resulting string:
new_word = "".join("_" if letter in vowels else letter for letter in secret_word)
with exactly the same effect. Now, since you also have the dictionary mapping, getting the respective hint is easy, just supply the key new_word to mapping and it'll return the key.
A revised version of your code looks like this:
import random
Words = ("wallet", "canine")
Hints = ("Portable money holder", "Man's best friend")
mapping = dict(zip(Words, Hints))
vowels = "aeiouy"
secret_word = random.choice(Words)
new_word = "".join("_" if letter in vowels else letter for letter in secret_word)
print(new_word,"\t\t\t", d[secret_word])

Creating a word scrambler but it won't work, need help as a beginner

Beginner python coder here, keep things simple, please.
So, I need this code below to scramble two letters without scrambling the first or last letters. Everything seems to work right up until the scrambler() function.
from random import randint
def wordScramble(string):
stringArray = string.split()
for word in stringArray:
if len(word) >= 4:
letter = randint(1,len(word)-2)
point = letter
while point == letter:
point = randint(1, len(word)-2)
word = switcher(word,letter,point)
' '.join(stringArray)
return stringArray
def switcher(word,letter,point):
word = list(word)
word[letter],word[point]=word[point],word[letter]
return word
print(wordScramble("I can't wait to see how this turns itself out"))
The outcome is always:
I can't wait to see how this turns itself out
Since you are a beginner, I tried to change your code as little as possible. Mostly you are expecting changes to word to change the contents or your list stringArray. The comments mark the changes and reasons.
from random import randint
def wordScramble(myString): # avoid name clashes with python modules
stringArray = myString.split()
for i, word in enumerate(stringArray): # keep the index so we can update the list
if len(word) >= 4:
letter = randint(1,len(word)-2)
point = letter
while point == letter:
point = randint(1, len(word)-2)
stringArray[i] = switcher(word,letter,point) # update the array
return ' '.join(stringArray) # return the result of the join
def switcher(word,letter,point):
word = list(word)
word[letter],word[point]=word[point],word[letter]
return ''.join(word) # return word back as a string
print(wordScramble("I can't wait to see how this turns itself out"))
Because there had to be a cleaner (and better documented) way to do this:
from random import sample
def wordScramble(sentence):
# Split sentence into words; apply switcher to each; rejoin into a sentence
return ' '.join([switcher(x) for x in sentence.split()])
def switcher(word):
if len(word) <= 3: # Don't bother if not enough letters to scramble
return word
# Pick 2 positions from interior of word
a,b = sorted(sample( xrange(1,len(word)-1), 2 ))
# Re-assemble word with out 2 positions swapped using bits before, between & after them
return word[:a] + word[b] + word[a+1:b] + word[a] + word[b+1:]
print wordScramble("I can't wait to see how this turns itself out")

Categories

Resources