Implement the word_calculator method to return the correct scrabble word score. The scores are already set up to be use and are managed within dictionaries:
two = ['d', 'g']
three = ['b', 'c', 'm', 'p']
four = ['f', 'h', 'v', 'w', 'y']
five = ['k']
eight = ['j', 'x']
ten = ['q', 'z']
with having these list, i need to produce a function def word_calculator(word): where i need to pass a string to the method. the parameter zoo should return 12, and bus should return 5.
Can anyone help me to produce the function please?
This, like many problems in computer science, is much easier to do if you use a better data-structure.
As you have it, you will have to loop over all six lists for each letter, check if the letter is in each of them, and then hard code the score for each list programmatically so that you can add it to some total. That's a lot of work, and a lot of messy code.
However, you could use a dictionary instead. A dictionary lets you map any value to any other value. So, for example
x = {"A": 1, "B": 3}
Means that x["A"] is 1, and that x["B"] is 3, etc.
Lets imagine we had a dictionary containing the mapping of every letter to its scrabble value:
scores = {"A": 1, "B": 3, "C": 3, "D": 2, "E": 1, "F": 4, "G": 2, "H": 4, "I": 1, "J": 8, "K": 5, "L": 1, "M": 3, "N": 1, "O": 1, "P": 3, "Q": 1, "R": 1, "S": 1, "T": 1, "U": 1, "V": 4, "W": 4, "X": 8, "Y": 4, "Z": 10}
How would we find the word score for "ZOO"? We would need to:
Loop through every letter
Find the score for the letter (e.g. scores[letter])
Add the score to some running total
For example,
total = 0
for letter in "ZOO" :
total = total + score[letter]
print(total) # Prints 12
If you want to be fancy, this can also be done all on the one line using a list comprehension:
sum([scores[letter] for letter in "ZOO"])
Further reading:
https://docs.python.org/3/tutorial/datastructures.html
(explains dictionaries very well, and also talks about list comprehensions)
# the dictionary of scores to letter lists
score_letters = {
2: ['d', 'g'],
3: ['b', 'c', 'm', 'p'],
4: ['f', 'h', 'v', 'w', 'y'],
5: ['k'],
8: ['j', 'x'],
10: ['q', 'z']
}
# use `score_letters` to make a list from letters to score values
letter_scores = {letter: score for score, letters in score_letters.items() for letter in letters}
# equivalent to:
# letter_scores={}
# for score, letters in score_letters.items():
# for letter in letters:
# letter_scores[letter] = score
print('letter_scores =', letter_scores)
def word_calculator(word):
# sum the scores of each letter in the word
# `letter_scores.get(letter, 1)` means
# "get the value associated with the
# key `letter`, or if there is no such
# key in the dictionary, use the
# default value 1"
return sum(letter_scores.get(letter, 1) for letter in word)
print('zoo', word_calculator('zoo'))
print('bus', word_calculator('bus'))
Related
I hope you are doing well. I'm working on a dictionary program:
strEntry = str(input("Enter a string: ").upper())
strEntry = strEntry.replace(",", "")
strEntry = strEntry.replace(" ", "")
print('')
def freq_finder(strFinder):
dict = {}
for i in strFinder:
keys = dict.keys()
if i in keys:
dict[i] += 1
else:
dict[i] = 1
return dict
newDic = freq_finder(strEntry)
print(newDic)
newLetter = str(input("Choose a letter: ").upper())
if newLetter in newDic.values():
print("Number of occurrence of", message.count(newLetter))
newDic.pop(newLetter)
print("Dictinary after that letter removed:", newDic)
else:
print("Letter not in dictionary")
sortedDic = sorted(newDic)
print(sortedDic)
Everything works fine before this part:
newLetter = str(input("Choose a letter: ").upper())
if newLetter in newDic.values():
print("Number of occurrence of", message.count(newLetter))
newDic.pop(newLetter)
print("Dictinary after that letter removed:", newDic)
else:
print("Letter not in dictionary")
I'm trying to figure out how to check whether the letter is in the dictionary. If it is not, display the message “Letter not in dictionary”. Otherwise, display the frequency count of that letter, remove the letter from the dictionary and display the dictionary after that letter has been removed.
It should look something like this:
Enter a string: Magee, Mississippi
Dictionary: {'M': 2, 'A': 1, 'G': 1, 'E': 2, 'I': 4, 'S': 4, 'P': 2}
Choose a letter: s
Frequency count of that letter: 4
Dictionary after that letter removed: {'M': 2, 'A': 1, 'G': 1, 'E': 2, 'I': 4, 'P': 2}
Letters sorted: ['A', 'E', 'G', 'I', 'M', 'P']
I would highly appreciate it if you could tell me what's wrong and how to fix it.
Check for the keys, not the value (Because the Value is a number, not a letter) -
if newLetter in newDic: # Or if newLetter in list(newDic.keys())
print("Number of occurrence of", message.count(newLetter))
For this - Dictionary: {'M': 2, 'A': 1, 'G': 1, 'E': 2, 'I': 4, 'S': 4, 'P': 2}, you could use Collections.Counter instead
I'm working on a problem given to us by our professor and I can't get it to work how I want it to work. I should preface this by saying I'm a beginner with Python.
Essentially I'm to write a function that given a string returns the same string as a list with the objects of the list being different versions of the given string.
For example: Hello should return;
Hello
hEllo
heLlo
helLo
hellO
However we aren't allowed to use python's built in functions that can determine whether a character is upper or lower case such as upper() or lower() and having only really done any "programming" in MatLab prior to this and some OpenCV I'm looking for some help with getting started.
What I've tried so far is something like this:
def randRetur(menBok,dicT):
menBok = list(menBok)
for i,j in enumerate(menBok):
if menBok[i] in dicT.values():
scrambledPws.append(menBok)
else:
scrambledPws.append(dicT[j])
return scrambledPws
where my Dictionary maps lowercase letters to uppercase and scrambledPws is simply an empty list to start off with.
However this doesn't quite give me what I want but rather everything is capitalized in the first object of the list, which is where my understanding of how pythons handling of a for loop is very different to me from how for example MatLab handles it. I'm therefore more hoping for some guidance rather than how to do it, as I'm trying to learn.
The solution is very simple, I turned the string to a list and change the index of that list containing the character to its uppercase version. And then I turned the list back to a string and added it to combos. Then I returned the list of combos.
My explanation is not very good, sorry. But hopefully the code explains it better.
def scrambleString(string):
letters = { # Create a dictionary containing all the letters and their uppercase
"a": "A",
"b": "B",
"c": "C",
"d": "D",
"e": "E",
"f": "F",
"g": "G",
"h": "H",
"i": "I",
"j": "J",
"k": "K",
"l": "L",
"m": "M",
"n": "N",
"o": "O",
"p": "P",
"q": "Q",
"r": "R",
"s": "S",
"t": "T",
"u": "U",
"v": "V",
"w": "W",
"x": "X",
"y": "Y",
"z": "Z"
}
combos = []
for index, char in enumerate(string):
newString = list(string) # I turned the string into a list for easier manipulation
# The line below swaps the index of string to uppercase
newString[index] = letters[char]
returnString = "" # This is just to the list to a string
for i in newString:
returnString += i
combos.append(returnString) # Appends that scrambledString to a combo
return combos
see below
The idea is to use 2 dicts that will support lower to upper & upper to lower
l2u = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'E', 'f': 'F', 'g': 'G', 'h': 'H', 'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L', 'm': 'M', 'n': 'N', 'o': 'O', 'p': 'P', 'q': 'Q', 'r': 'R', 's': 'S', 't': 'T', 'u': 'U', 'v': 'V', 'w': 'W', 'x': 'X', 'y': 'Y', 'z': 'Z'}
u2l = {'A': 'a', 'B': 'b', 'C': 'c', 'D': 'd', 'E': 'e', 'F': 'f', 'G': 'g', 'H': 'h', 'I': 'i', 'J': 'j', 'K': 'k', 'L': 'l', 'M': 'm', 'N': 'n', 'O': 'o', 'P': 'p', 'Q': 'q', 'R': 'r', 'S': 's', 'T': 't', 'U': 'u', 'V': 'v', 'W': 'w', 'X': 'x', 'Y': 'y', 'Z': 'z'}
def get_str_versions(string):
result = []
for x in range(len(string)):
if string[x] in l2u:
result.append(string[0:x] + l2u[string[x]] + string[x+1:])
else:
result.append(string[0:x] + u2l[string[x]] + string[x+1:])
return result
print(get_str_versions('Hello'))
output
['hello', 'HEllo', 'HeLlo', 'HelLo', 'HellO']
This question has multiple parts, I can help with one part of it. For this part,
given some character, you need to return the uppercase variant, without using
the string method upper(). I am not sure the CPython implementation, but the
Ruby one is here:
https://github.com/ruby/ruby/blob/fb3c711d/regenc.c#L970-L977
Here is a simple implementation of that in Python:
def up(s_in):
n_out = ord(s_in) + ord('A') - ord('a')
return chr(n_out)
The input should be a single character, with output being the upper variant.
Note that this will only work on ASCII characters.
If you are not even allowed to use functions such as ord, which would allow you to check for case using the ascii table, you can manually map all printable characters (a-z) to an alternative-case version, save it into a dictionary, then add the reversed mapping (upper-case to lower-case) to the dictionary, then loop over all characters in a given word using index increment method (but even then, are you allowed to use len?).
For each iteration, you create a new string and then replace the current index in a string with a look-up alternative from the dictionary we created earlier.
CASE_MAPPING_ONE_SIDED = { "a": "A",
"b": "B",
"c": "C",
"d": "D",
"e": "E",
"f": "F",
"g": "G",
"h": "H",
"i": "I",
"j": "J",
"k": "K",
"l": "L",
"m": "M",
"n": "N",
"o": "O",
"p": "P",
"q": "Q",
"r": "R",
"s": "S",
"t": "T",
"u": "U",
"v": "V",
"w": "W", }
CASE_MAPPING = {}
# Map all lower-case characters to upper-case and also save it in the dictionary
for lower_ch in CASE_MAPPING_ONE_SIDED:
upper_ch = CASE_MAPPING_ONE_SIDED[lower_ch]
CASE_MAPPING[lower_ch] = upper_ch
CASE_MAPPING[upper_ch] = lower_ch
def alternative_versions(s):
res = [s]
i = 0
while i < len(s):
alt = s[:i]
# Replace the ith character with an alternative version
alt += CASE_MAPPING[s[i]]
alt += s[i+1:]
res.append(alt)
i += 1
return res
print(alternative_versions("Hello"))
here is some code (hope im not late because we had power go out):
from random import randint
uppercase = ['H', 'E', 'L', 'L', 'O']
lowercase = ['h', 'e', 'l', 'l', 'o']
random = randint(0, len(uppercase) - 1)
lowercase[random] = uppercase[random]
print(''.join(lowercase))
I assume the input string contains alphabets only.
def to_upper(ch):
return ch if (65 <= ord(ch) <= 90) else chr(ord(ch) - 32)
def capitalize(s):
diff = ord('a') - ord('A')
lower_case_word = ""
for ch in s:
if 65 <= ord(ch) <= 90: #Caps letter
lower_case_word = lower_case_word + chr(ord(ch)+diff)
else:
lower_case_word = lower_case_word + ch
for i in range(len(s)):
yield lower_case_word[:i] + to_upper(s[i]) + lower_case_word[i+1:]
for word in ("Hello", "myTest"):
print(list(capitalize(word)))
[Hello', 'hEllo', 'heLlo', 'helLo', 'hellO']
['Mytest', 'mYtest', 'myTest', 'mytEst', 'myteSt', 'mytesT']
I'm trying to create a Python function that uses the Caesar cipher to encrypt a message.
So far, the code I have is
letter = input("Enter a letter: ")
def alphabet_position(letter):
alphabet_pos = {'A':0, 'a':0, 'B':1, 'b':1, 'C':2, 'c':2, 'D':3,
'd':3, 'E':4, 'e':4, 'F':5, 'f':5, 'G':6, 'g':6,
'H':7, 'h':7, 'I':8, 'i':8, 'J':9, 'j':9, 'K':10,
'k':10, 'L':11, 'l':11, 'M':12, 'm':12, 'N': 13,
'n':13, 'O':14, 'o':14, 'P':15, 'p':15, 'Q':16,
'q':16, 'R':17, 'r':17, 'S':18, 's':18, 'T':19,
't':19, 'U':20, 'u':20, 'V':21, 'v':21, 'W':22,
'w':22, 'X':23, 'x':23, 'Y':24, 'y':24, 'Z':25, 'z':25 }
pos = alphabet_pos[letter]
return pos
When I try to run my code, it will ask for the letter but it doesn't return anything after that
Please help if you have any suggestions.
you would need to access your dictionary in a different way:
pos = alphabet_pos.get(letter)
return pos
and then you can finally call the function.
alphabet_position(letter)
You can define two dictionaries, one the reverse of the other. You need to be careful on a few aspects:
Whether case is important. If it's not, use str.casefold as below.
What happens when you roll off the end of the alphabet, e.g. 13th letter after "z". Below we assume you start from the beginning again.
Don't type out the alphabet manually. You can use the string module.
Here's a demo:
letter = input("Enter a letter: ")
from string import ascii_lowercase
def get_next(letter, n):
pos_alpha = dict(enumerate(ascii_lowercase))
alpha_pos = {v: k for k, v in pos_alpha.items()}
return pos_alpha[alpha_pos[letter.casefold()] + n % 26]
get_next(letter, 13)
Enter a letter: a
'n'
If you need a entirely new encoded dict
import string
import numpy as np, random
letters = string.ascii_uppercase
d=dict(zip(list(letters),range(0,len(letters))))
encoded_dic={}
def get_caesar_value(v, by=13):
return(v+by)%26
for k,v in d.items():
encoded_dic[k]=chr(65+get_caesar_value(v))
print(encoded_dic)
Output:
{'A': 'N', 'C': 'P', 'B': 'O', 'E': 'R', 'D': 'Q', 'G': 'T', 'F': 'S', 'I': 'V', 'H': 'U', 'K': 'X', 'J': 'W', 'M': 'Z', 'L': 'Y', 'O': 'B', 'N': 'A', 'Q': 'D', 'P': 'C', 'S': 'F', 'R': 'E', 'U': 'H', 'T': 'G', 'W': 'J', 'V': 'I', 'Y': 'L', 'X': 'K', 'Z': 'M'}
The code you have only maps letters to a position. We'll rewrite it and make a rotate function.
Code
import string
import itertools as it
LOOKUP = {
**{x:i for i, x in enumerate(string.ascii_lowercase)},
**{x:i for i, x in enumerate(string.ascii_uppercase)}
}
def abc_position(letter):
"""Return the alpha position of a letter."""
return LOOKUP[letter]
def rotate(letter, shift=13):
"""Return a letter shifted some positions to the right; recycle at the end."""
iterable = it.cycle(string.ascii_lowercase)
start = it.dropwhile(lambda x: x != letter.casefold(), iterable)
# Advance the iterator
for i, x in zip(range(shift+1), start):
res = x
if letter.isupper():
return res.upper()
return res
Tests
func = abc_position
assert func("a") == 0
assert func("A") == 0
assert func("c") == 2
assert func("z") == 25
func = rotate
assert func("h") == "u"
assert func("a", 0) == "a"
assert func("A", 0) == "A"
assert func("a", 2) == "c"
assert func("c", 3) == "f"
assert func("A", 2) == "C"
assert func("a", 26) == "a"
# Restart after "z"
assert func("z", 1) == "a"
assert func("Z", 1) == "A"
Demo
>>> letter = input("Enter a letter: ")
Enter a letter: h
>>> rot = rotate(letter, 13)
>>> rot
'u'
>>> abc_position(rot)
20
Here we rotated the letter "h" 13 positions, got a letter and then determined the position of this resultant letter in the normal string of abc's.
Details
abc_position()
This function was rewritten to lookup the position of a letter. It merges two dictionaries:
one that enumerates a lowercase ascii letters
one that enumerates a uppercase ascii letters
The string module has this letters already.
rotate()
This function only rotates lowercase letters; uppercase letters are translated from the lowercase position. The string of letters is rotated by making an infinite cycle (an iterator) of lowercase letters.
The cycle is first advanced to start at the desired letter. This is done by dropping all letters that don't look like the one passed in.
Then it is advanced in a loop some number of times equal to shift. The loop is just one way to consume or move the iterator ahead. We only care about the last letter, not the ones in between. This letter is returned, either lower or uppercase.
Since a letter is returned (not a position), you can now use your abc_position() function to find it's normal position.
Alternatives
Other rotation functions can substitute rotate():
import codecs
def rot13(letter):
return codecs.encode(letter, "rot13")
def rot13(letter):
table = str.maketrans(
"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz",
"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
return str.translate(letter, table)
However, these options are constrained to rot13, while rotate() can be shifted by any number. Note: rot26 will cycle back to the beginning, e.g. rotate("a", 26) -> a.
See also this post on how to make true rot13 cipher.
See also docs on itertools.cycle and itertools.dropwhile.
You can do it with quick calculations from ord and chr functions instead:
def encrypt(letter):
return chr((ord(letter.lower()) - ord('a') + 13) % 26 + ord('a'))
so that:
print(encrypt('a'))
print(encrypt('o'))
outputs:
n
b
I have a list that contains dictionaries with Letters and Frequencies. Basically, I have 53 dictionaries each for every alphabet (lowercase and uppercase) and space.
adict = {'Letter':'a', 'Frequency':0}
bdict = {'Letter':'b', 'Frequency':0}
cdict = {'Letter':'c', 'Frequency':0}
If you input a word, it will scan the word and update the frequency for its corresponding letter.
for ex in range(0, len(temp)):
if temp[count] == 'a': adict['Frequency']+=1
elif temp[count] == 'b': bdict['Frequency']+=1
elif temp[count] == 'c': cdict['Frequency']+=1
For example, I enter the word "Hello", The letters H,e,l,l,o is detected and its frequencies updated. Non zero frequencies will be transferred to a new list.
if adict['Frequency'] != 0 : newArr.append(adict)
if bdict['Frequency'] != 0 : newArr.append(bdict)
if cdict['Frequency'] != 0 : newArr.append(cdict)
After this, I had the newArr sorted by Frequency and transferred to a new list called finalArr. Below is a sample list contents for the word "Hello"
{'Letter': 'H', 'Frequency': 1}
{'Letter': 'e', 'Frequency': 1}
{'Letter': 'o', 'Frequency': 1}
{'Letter': 'l', 'Frequency': 2}
Now what I want is to transfer only the key values to 2 seperate lists; letterArr and numArr. How do I do this? my desired output is:
letterArr = [H,e,o,l]
numArr = [1,1,1,2]
Why don't you just use a collections.Counter? For example:
from collections import Counter
from operator import itemgetter
word = input('Enter a word: ')
c = Counter(word)
letter_arr, num_arr = zip(*sorted(c.items(), key=itemgetter(1,0)))
print(letter_arr)
print(num_arr)
Note the use of sorted() to sort by increasing frequency. itemgetter() is used to reverse the sort order so that the sort is performed first on the frequency, and then on the letter. The sorted frequencies are then separated using zip() on the unpacked list.
Demo
Enter a word: Hello
('H', 'e', 'o', 'l')
(1, 1, 1, 2)
The results are tuples, but you can convert to lists if you want with list(letter_arr) and list(num_arr).
I have a hard time understanding your data structure choice for this problem.
Why don't you just go with a dictionary like this:
frequencies = { 'H': 1, 'e': 1, 'l': 2, 'o': 1 }
Which is even easier to implement with a Counter:
from collections import Counter
frequencies = Counter("Hello")
print(frequencies)
>>> Counter({ 'H': 1, 'e': 1, 'l': 2, 'o': 1 })
Then to add another word, you'd simply have to use the updatemethod:
frequencies.update("How")
print(frequencies)
>>> Counter({'l': 2, 'H': 2, 'o': 2, 'w': 1, 'e': 1})
Finally, to get your 2 arrays, you can do:
letterArr, numArr = zip(*frequencies.items())
This will give you tuples though, if you really need lists, just do: list(letterArr)
You wanted a simple answer without further todo like zip, collections, itemgetter etc. This does the minimum to get it done, 3 lines in a loop.
finalArr= [{'Letter': 'H', 'Frequency': 1},
{'Letter': 'e', 'Frequency': 1},
{'Letter': 'o', 'Frequency': 1},
{'Letter': 'l', 'Frequency': 2}]
letterArr = []
numArr = []
for i in range(len(finalArr)):
letterArr.append(finalArr[i]['Letter'])
numArr.append(finalArr[i]['Frequency'])
print letterArr
print numArr
Output is
['H', 'e', 'o', 'l']
[1, 1, 1, 2]
Is there a better way the write this code. While there are no errors it seems that its printing all the letters I typed sorted into a list.
I want to print the common letters in a string, even if more than one.
Here is what I Have
mystr = input("Enter a string:")
s = list(mystr)
letter_counter = {}
for word in mystr:
if word in letter_counter:
letter_counter[word] += 1
else:
letter_counter[word] = 1
user_letter = sorted(letter_counter, key = letter_counter.get, reverse = True)
number_1 = user_letter[:2]
print(number_1)
The only way I can print the correct letters is by setting a limit on
number_1 = user_letter[:2]
For example if I enter the following:
mystr = input("Thomas Jones")
in the code the printed
output would be
print(number_1)
[o], [s]
Which is right but if the limit was set to from 2 to 3
number_1 = user_letter[:3]
It will print [o] [s] [a] there is only one a it shouldn't be there.
I want it so that any amount the of words the user inputs it will show the correct repeated letter without the limiter.
I'm liberality stuck I have no idea how to correct this
from collections import Counter
[letter for letter,count in Counter("Thomas Jones").items() if count > 1]
Your code produces
letter_counter = {'a': 1, ' ': 1, 'e': 1, 'h': 1, 'J': 1, 'm': 1, 'o': 2, 'n': 1, 's': 2, 'T': 1}
user_letter = ['o', 's', 'a', ' ', 'e', 'h', 'J', 'm', 'n', 'T']
which is all correct.
If you only want the repetitive letters, try
user_letter = [letter for letter in letter_counter if letter_counter[letter] > 1]
or something similar.