How to sort dictionary values from Highest to lowest? - python

My question would be how I withdraw winner based on highest score?
since u cant sort in dictionaries
i tried this with lists, but then name wouldnt appear, only the score...
a = {'name_a':0}
b = {'name_b':0}
c = {'name_c':0}
d = {'name_d':0}
e = {'name_e':0}
print("Each time someone scores a point, the letter of his name is typed in lowercase. If someone loses a point, the letter of his name is typed in uppercase")
score = input('Enter series of charachters indicating who scored a poitn: ')
for i in score:
if i == 'a':
a['name_a'] += 1
if i == 'A':
a['name_a'] -= 1
if i == 'b':
b['name_b'] += 1
if i == 'B':
b['name_b'] -= 1
if i == 'c':
c['name_c'] += 1
if i == 'C':
c['name_c'] -= 1
if i == 'd':
d['name_d'] += 1
if i == 'D':
d['name_d'] -= 1
if i == 'e':
e['name_e'] += 1
if i == 'E':
e['name_e'] -= 1
print(a,b,c,d,e)
print('Winner is: ', )

This will work:
max((i, name) for d in (a,b,c,d,e) for name, i in d.items())[1]

you probably want to use a single dict, instead of one for each, like such:
scores = {
'a': 0,
'b': 0,
'c': 0,
'd': 0,
'e': 0,
}
And then you can keep track of the highest scoring player as points are calculated:
point_scored = input('Enter series of charachters indicating who scored a point: ')
for i in point_scored:
if not scores.get(i) is None:
scores[i] += 1
elif not scores.get(i.lower()) is None:
scores[i.lower()] -= 1
else:
print(str(i) + ' is not a valid player...')
winner = max(scores, key=scores.get)
print(scores)
print('Winner is ' + winner)

max_key = ""
max_val = 0
for key, value in d.items():
if (value > max_val):
max_val = value
max_key = key
Is this what you mean?

i found the answer
winner = (sorted(d.items(), key = lambda x: int(x[1]), reverse = True))

Related

Debugging code for Roman to Integer on leetcode

I decided to do the Roman to Integer leetcode in python 3, however I can't get my code to pass all of their tests. I'm getting 3583/3999 passed tests.
here's my code:
class Solution:
def romanToInt(self, s: str) -> int:
count = 0
if "IV" in s:
count += 4
s = s.replace("IV", "")
elif "IX" in s:
count += 9
s = s.replace("IX", "")
elif "XL" in s:
count += 40
s = s.replace("XL", "")
elif "XC" in s:
count += 90
s = s.replace("XC", "")
elif "CD" in s:
count += 400
s = s.replace("CD", "")
elif "CM" in s:
count += 900
s = s.replace("CM", "")
for c in s:
if c == 'I':
count += 1
elif c == 'V':
count += 5
elif c == 'X':
count += 10
elif c == 'L':
count += 50
elif c == 'C':
count += 100
elif c == 'D':
count += 500
elif c == 'M':
count += 1000
return count
not totally sure what's wrong, I'm aware this isn't the most efficient way of doing it, but I just want to get the code to work
I tried debugging it and changed some things around.

Making dictionary item frequency

I want to know why it's not counting the element ?
I made an key then in each iteration it should increase the value.
def isAnagram( s, t):
if len(s) != len(t):
return False
d_1 = {}
d_2 = {}
for i in range(len(s)):
d_1[s[i]] =+ 1
d_2[t[i]] =+ 1
print(d_1)
print(d_2)
return True if d_1 == d_2 else False
s = 'aabb'
t = 'bbaa'
print(isAnagram(s,t))
OUTPUT :
d_1 = {'a': 1, 'b': 1}
d_2 = {'b': 1, 'a': 1}
First, you have an error, to add value to the variable you need to do
d_1[s[i]] += 1
d_2[t[i]] += 1
Second, the function fails because you need to define the key and value before modifying the value.
Working function:
def isAnagram( s, t):
if len(s) != len(t):
return False
d_1 = {}
d_2 = {}
for i in range(len(s)):
try: # checking if the character in the dictionary exists
d_1[s[i]]
except KeyError:
d_1[s[i]] = 0
try: # checking if the character in the dictionary exists
d_2[t[i]]
except KeyError:
d_2[t[i]] = 0
d_1[s[i]] += 1
d_2[t[i]] += 1
print(d_1)
print(d_2)
return True if d_1 == d_2 else False
s = 'aabb'
t = 'bbaa'
print(isAnagram(s,t))
as mentioned in comments. you should use += instead of =+.
+= means adding the value to the previous value stored. while
=+ here means = (assigning the value)
def isAnagram(s, t):
if len(s) != len(t):
return False
d_1 = {}
d_2 = {}
for i in range(len(s)):
d_1[s[i]] += 1
d_2[t[i]] += 1
print(d_1)
print(d_2)
return True if d_1 == d_2 else False
s = 'aabb'
t = 'bbaa'
print(isAnagram(s,t))
add a .lower() to Domagoj's answer to be case-insensitive.
so this will also work:
s = 'Betrug'.lower()
t = 'Erbgut'.lower()
{'b': 1, 'e': 1, 't': 1, 'r': 1, 'u': 1, 'g': 1}
{'e': 1, 'r': 1, 'b': 1, 'g': 1, 'u': 1, 't': 1}
True
Don’t reinvent the wheel!
from collections import Counter
def isAnagram(s, t):
return Counter(s) == Counter(t)
s = "aabb"
t = "bbaa"
print(isAnagram(s,t)) # => True

Get NameError when printing out the result, but I've assigned a variable to it

seq = 'TGCCTTGGGCACCATGCAGTACCAAACGGAACGATAGTG'
for nucleotide in seq:
if nucleotide == 'A':
a_nt = seq.count('A')
elif nucleotide == 'G':
g_nt = seq.count('G')
elif nucleotide == 'C':
c_nt = seq.count('C')
elif nucleotide == 'T':
t_nt = seq.count('T')
elif nucleotide == 'N':
n_nt = seq.count('N')
else:
sys.exit("Did not code")
print(a_nt, g_nt, c_nt, t_nt, n_nt)
Error:
NameError: name 'n_nt' is not defined. Did you mean: 'a_nt'?
If the nucleotide is not in 'AGCTN', sys.exit("no this code").
Even counts of N is zero, it should be printed out.
If I print out a, g, c, and t, it works well. But n_nt is not working.
Just count everything without the for loop, then all variables are set, even if zero:
seq = 'TGCCTTGGGCACCATGCAGTACCAAACGGAACGATAGTG'
a_nt = seq.count('A')
g_nt = seq.count('G')
c_nt = seq.count('C')
t_nt = seq.count('T')
n_nt = seq.count('N')
print(a_nt, g_nt, c_nt, t_nt, n_nt)
# or more efficient
from collections import Counter
counts = Counter(seq)
for letter in 'AGCTN':
print(counts[letter], end=' ')
Output:
11 11 10 7 0
11 11 10 7 0
I suggest using collections.Counter
from collections import Counter
possible_nucleotides = ["A", "G", "C", "N", "T"]
seq = "TGCCTTGGGCACCATGCAGTACCAAACGGAACGATAGTG"
seq_counts = Counter(seq)
missing_nucleotides = {x: 0 for x in set(possible_nucleotides) - set(seq_counts.keys())}
seq_counts.update(missing_nucleotides)
then seq_counts will look like this:
Counter({'G': 11, 'A': 11, 'C': 10, 'T': 7, 'N': 0})
Keep in mind that updating Counter is purely optional as trying to access specific key will return 0 if not present

How to ignore a specific character in a string, and later use it?

Previously I asked a question as to how to separate characters in a string according to capital letters, or spaces. It was immediately answered. Working on the same piece of code and now I was wondering if it is possible to read an input and ignore integers, and later use it.
For example if the string is H2O, times the value of H twice and then add the value of O.
How to read two characters from an input string?
^^That's the link to my previous question I asked on same code, if useful.
import re
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067, 'O': 15.9994,'F':
18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0}
TotalMass=0
elements=[ ]
mol=input("Enter a molecule:")
elements = re.findall('[A-Z][^A-Z]*', mol)
for a in elements:
if a == int:
element=None
atomicMass=atomMass_Table.get(a)
TotalMass=TotalMass+atomicMass
print (TotalMass)
Hope I'm not being too confusing :)
There are two solutions for you. I don't understand the solution of Thomas, but alec's solution is acceptable. However, it can't work if you have something like "C12H22O11". I give a solution which can fix it, take a look.
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067,
'O': 15.9994,'F': 18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0, 'd': 0}
TotalMass=0
elements=[ ]
mol=input("Enter a molecule:")
if not mol[-1].isdigit():
mol += '1'
mol += 'd'
number = []
for a in mol:
if a.isdigit():
number.append(a)
else:
if not number:
value = atomMass_Table.get(a)
else:
TotalMass += value * int(''.join(number))
value = atomMass_Table.get(a)
number = []
print (TotalMass)
The solution for H2O is 18.01534 and C12H22O11 is 342.30074.
Hope this help!
What about this?
import re
atom_masses = {'H': 1.00797, 'He': 4.00260, 'B': 10.81, 'C': 12.011, 'N': 14.067, 'O': 15.9994, 'F':
18.998403, 'P': 30.97376, 'S': 32.06, 'K': 39.0983, ' ': 0, None: 0}
total_mass = 0
elements = []
mol = input("Enter a molecule:")
parts = re.findall('([A-Z][a-z]?)(\d)*', mol)
print(parts)
for element, count in parts:
if count == '':
count = 0
atomic_mass = atom_masses.get(element)
total_mass = total_mass + atomic_mass * float(count)
print (total_mass)
I changed the regex to divide the string into separate atoms and their count. It has to be a capital letter followed by an optional small letter and an optional number.
Additionally, i changed the variable name because they should be in small letter.
Use isalpha() to check if the element only contains letters. If not, you can use string slicing to get the value of the first character from the dictionary, and multiply by the second character.
atomMass_Table = {'H': 1.00797, 'He': 4.00260, 'B': 10.81,'C': 12.011, 'N': 14.067, 'O': 15.9994,'F':
18.998403,'P': 30.97376, 'S': 32.06, 'K':39.0983, ' ': 0, None: 0}
TotalMass = 0
mol = input("Enter a molecule: ")
elements = re.findall('[A-Z][^A-Z]*', mol)
for a in elements:
if a.isalpha():
TotalMass += atomMass_Table.get(a)
else:
TotalMass += atomMass_Table.get(a[0]) * int(a[1])
print(TotalMass)
Example:
Enter a molecule: H2O
18.01534
>>>
I extended a bit your Request and added a Class for each molecule.
A Class contains of three attributes:
raw_element
molecule structure
molecule mass
the class could be extended with a drawing of the molecule or other features.
The Class:
class molecule:
def __init__(self, raw_element, atom_mass_table):
self.amt = atom_mass_table
self.raw_element = raw_element
self.molecule_structur = self.get_struc()
self.molecule_mass = self.cal_mass()
def get_struc(self):
return [self._split_nodes(e) for e in self._split_in_nodes()]
def cal_mass(self):
sum = 0
for i in self.molecule_structur:
sum += self.amt[i[0]] * i[1]
return sum
def _split_nodes(self, node):
s = ""
n = ""
for l in node:
if l.isalpha():
s += l
elif l.isdigit():
n += l
if n is None:
n = 1
return (s, int(n))
def _split_in_nodes(self):
new_el = [e.isupper() for e in self.raw_element]
el_str = []
pos = 0
for _ in range(sum(new_el)):
if True in new_el[pos+1:]:
end = pos + new_el[pos+1:].index(True)+1
else:
end = len(new_el)
el_str.append(self.raw_element[pos:end])
pos = end
return el_str
The Class only needs:
raw element description - C12H22O11
your provided atom_mass_table - I didn't include it in the class, for easier expansion later on.
So to test the code:
if __name__ == "__main__":
element = input("Please enter your Molecule: ")
molecule = Molecule(element, atom_mass_table)
print(molecule.molecule_structur)
print(molecule.molecule_mass)
Input:
Please enter you Molecule: C32H128O64
Output:
[('C', 32), ('H', 128), ('O', 64)]
1537.33376
Hope it helps and when you further improve this Application, you can invite me to you GitHub Project.

How to select the nearby key in python dictionary?

Please consider the below Python code:
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
for k in dict2:
usr_id = 3
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
In the "dict2", if values == 1 then it is active or if values == 0 then it is inactive. Here, match the usr_id with key id in dict2.
Case 1: dict2 = {'1': 1, '2': 1, '3': 1, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==1. so allotted id=3.
Case 2: dict2 = {'1': 1, '2': 1, '3': 0, '4': 1, '5': 1}. Now usr_id==3 and dict2 key '3'==0 . Then next active id is allotted.So allotted id=4.
Case 3: dict2 = {'1': 1, '2': 1, '3': 0, '4': 0, '5': 1}. Now usr_id==3 and dict2 key '3' & '4'==0 . So the next nearest active id to the usr_id want allocate (is nothing but key id '2').How to do it?
Guide me for my case 3 scenario. Thanks in advance.
Assuming you want no efficiency changes to the code, you're overwriting the usr_id in the for k in dict2 loop.
def allot():
dict2 = {'1': 1, '2': 1, '3': 0, '4': , '5': 1}
allotted_id = None
usr_id = 3 # Move this out of the loop
for k in dict2:
if (str(usr_id) != k):
continue;
if ((str(usr_id) == k) and (dict2[str(usr_id)] == 1)):
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is available ! ")
allotted_id = k
break;
else:
print("\n user Requested Id : ", usr_id)
print("\n user Requested Id is not available ! ")
usr_id = usr_id + 1
if (dict2[str(usr_id)] == 1):
allotted_id = usr_id
break;
print('So allotted dict2 Id', allotted_id)
allot()
You can write this code to do more checks and utilise the dictionary structure a bit more...
def allot():
# Variables to Enter
dict2 = {1: 1, 2: 1, 3: 0, 4: 0, 5: 1}
usr_id = 3
# Boolean Variables
allotted_id = None
upper_exhausted = False
lower_exhausted = False
# Need to calculate the min and max to know when to stop searching
max_id = max(dict2.keys())
min_id = min(dict2.keys())
# Check the initial ID
if dict2[usr_id] == 0:
print("ID {} inactive. Continuing search.".format(usr_id))
else:
allotted_id = usr_id
# Run two searches - one increasing through the dictionary
# and one decreasing through the dictionary
upper_usr_id = usr_id + 1
lower_usr_id = usr_id - 1
# Run loop whilst the max and min dict key haven't been reached
# AND there's no allotted ID.
while not allotted_id:
if not upper_exhausted:
if dict2[upper_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(upper_usr_id))
if upper_usr_id < max_id:
upper_usr_id += 1
else:
upper_exhausted = True # Maximum has been reached
else:
allotted_id = upper_usr_id
if not lower_exhausted:
if dict2[lower_usr_id] == 0:
print("ID {} inactive. Continuing search.".format(lower_usr_id))
if lower_usr_id > min_id:
lower_usr_id -= 1
else:
lower_exhausted = True # Minimum has been reached
else:
allotted_id = lower_usr_id
# Exhausted all values - No Data value
if upper_exhausted and lower_exhausted:
allotted_id = -999
if allotted_id == -999:
print("Couldn't allot an ID")
else:
print("Allotted ID is: {}".format(allotted_id))
allot()
I would use numpy:
user_ids = np.array(range(5))
valid_user = np.array([1, 1, 0, 0, 1])
anchor_id = 2
dist_from_anchor = np.abs(user_ids - anchor_id)
dist_from_anchor[valid_user == 0] = len(user_ids) +1 #will not be the min
print(np.argmin(dist_from_anchor))
I used the minimum user_id as 0 (just a cs thing...) but you can easily change it to be 1...
I suggest a different approach (Dont know how flexible you are with your approach)-
Store your data like this
dict2 = {"1": {1, 2, 5}, "0": {3, 4}} # 1 for available Ids and 0 for allocated
Now for any incoming user id
if usr_id in dict2["1"]:
allotted_id = usr_id
elif usr_id in dict2["0"]:
# either return the first available Or
# traverse and return the next higher user id available
else:
# exception

Categories

Resources