How do I access only a particular key in a dictionary? - python-3.x

I am solving a problem on Hackerrank and I'm using a dictionary as:
dic = {'1':type1, '2':type2, '3':type3, '4',type4, '5',type5}
In my problem, I need to return the key which has the maximum value (type variables are counts of each type).
Like if the value of type4 is 3 (type4 count is 3) then I need to return the key '4'.
How do I do that?
I tried using keys() and items() functions but they return lists and not particular elements.
type1 = 0
type2 = 0
type3 = 0
type4 = 0
type5 = 0
maxim = 0
for i in arr:
if i == 1:
type1+=1
elif i == 2:
type2+=1
elif i == 3:
type3+=1
elif i == 4:
type4+=1
else:
type5+=1
dic = {'1':type1, '2':type2, '3':type3, '4':type4, '5':type5}
for j in range(1,len(dic)):
if dic[str(j)]>maxim:
maxim = dic[str(j)]
return maxim
My output comes out to be 3 which is the maximum count that one of the type variables hold but what I need is for it to return the key to the corresponding value (here value is 3 and key is 4).

Your code cleaned up would lead to:
arr = [1,2,3,2,3,4,5,3,4,21,1,2,3,2,3,4,5,6,5,4,3,2,3,4,1,1,1,2]
dic = {}
for i in arr:
dic.setdefault(i,0) # set count of 0 if not existent
dic[i] +=1 # increase count
# use the builtin max function to get the item with the highest count
m = max(dic.items(), key = lambda x:x[1])
print(m) # (3,7)
See dict.setdefault
Using a collections.Counter will speed this up, it is a specialized dict to count things:
from collections import Counter
arr = [1,2,3,2,3,4,5,3,4,21,1,2,3,2,3,4,5,6,5,4,3,2,3,4,1,1,1,2]
# feed the array into Counter (which is a specialized counting dictionary)
c = Counter( arr )
print(c.most_common())
key, occ = c.most_common()[0]
print( key,"occured",occ,"times")
Output:
# counter.most_common() - i.e. 3 occured 7 time, 2 occured 6 times etc. it is sorted
[(3, 7), (2, 6), (1, 5), (4, 5), (5, 3), (6, 1), (21, 1)]
3 occured 7 times

Related

Text Justification / Word Wrap dp problem.Unable to find the overlapping condition in my recursion?

Que: https://en.wikipedia.org/wiki/Line_wrap_and_word_wrap
What I tried & issue faced: I tried a recursive approach to solve this problem. Currently, unable to find the overlapping subproblems. Can anyone help me how can I optimize, memoize and modify/update my recursion approach?. (I am thinking my approach is Wrong)
approach: Either the word is in the current line(if and only if space is left) or will be in the new line.
Code Flow:
Input text = "Cat is on Floor" .
I stored len in an array = [3,2,2,5]
ans(a,b,c) : a: index, b: line (currently no use), c: current line sum
base condn if all elements are over a>=size: return pow(spaceleft,2)
will return min( subproblem(word in current line),subproblem(word in new line)+pow(spaceleft,2))
Initially : ans(1,1,3)
ans(2,1,6) ans(2,2,2)
ans(3,2,2) ans(3,2,5) ans(3,3,2)
ans(4,3,5) ans(4,3,5) ans(4,4,5)
The below code is in python3.x :
n=6
arr=[3,2,2,5]
size = 4
def ans(a,b,c):
if(a>=size):
return pow((n-c),2);
if(c+arr[a]+1 > n):
return (pow((n-c),2)+ans(a+1,b+1,arr[a]))
return (min(ans(a+1,b,c+arr[a]+1),pow((n-c),2)+ans(a+1,b+1,arr[a])))
print(ans(1,1,3))
Thanks in advance for giving your valuable time and helping me....
I think your formulation might be missing some cases. It surely is hard to understand. Here's one that seems to get the right answer.
class LineWrapper:
def __init__(self, lens, width):
self.lens = lens
self.width = width;
def cost(self, ptr=0, used=0):
remaining = self.width - used
# Case 1: No words: Cost is due to partially used line.
if ptr == len(self.lens):
return remaining ** 2 if used else 0
# Case 2: First word of line. Must skip.
if used == 0:
return self.cost(ptr + 1, self.lens[ptr])
# Case 3: Out of space. Must wrap.
needed = 1 + self.lens[ptr]
if remaining < needed:
return remaining ** 2 + self.cost(ptr)
# Case 4: Min cost of skip and wrap.
return min(self.cost(ptr + 1, used + needed), remaining ** 2 + self.cost(ptr))
There's lots of overlap among subproblems in this formulation, and yours, too. A simple example is [1, 1, 1, 1] with a width of 7. The solution will try putting this on all combinations of 1, 2, 3, and 4 lines. May sub-combinations will repeat.
To see this more obviously, we can memoize and check for hits:
def memo_cost(self, ptr=0, used=0):
args = (ptr, used)
print(args)
if args in self.memos:
print(f'Memo hit: {args}')
return self.memos[args]
remaining = self.width - used
# Case 1: No words has cost of partially used line
if ptr == len(self.lens):
r = remaining ** 2 if used else 0
self.memos[args] = r
print(f'Done: {r}')
return r
# Case 2: First word of line. Must skip.
if used == 0:
r = self.memo_cost(ptr + 1, self.lens[ptr])
self.memos[args] = r
print(f'Must skip: {r}')
return r
# Case 3: Out of space. Must wrap.
needed = 1 + self.lens[ptr]
if remaining < needed:
r = remaining ** 2 + self.memo_cost(ptr)
self.memos[args] = r
print(f'Must wrap: {r}')
return r
# Case 4: Min cost of skip wrap and wrap.
r = min(remaining ** 2 + self.memo_cost(ptr), self.memo_cost(ptr + 1, used + needed))
self.memos[args] = r
print(f'Min: {r}')
return r
print(LineWrapper([1, 1, 1, 1], 7).memo_cost())
When run, this produces:
$ python3 lb.py
(0, 0)
(1, 1)
(1, 0)
(2, 1)
(2, 0)
(3, 1)
(3, 0)
(4, 1)
Done: 36
Must skip: 36
(4, 3)
Done: 16
Min: 16
Must skip: 16
(3, 3)
(3, 0)
Memo hit: (3, 0)
(4, 5)
Done: 4
Min: 4
Min: 4
Must skip: 4
(2, 3)
(2, 0)
Memo hit: (2, 0)
(3, 5)
(3, 0)
Memo hit: (3, 0)
(4, 7)
Done: 0
Min: 0
Min: 0
Min: 0
Must skip: 0
0
My answer with memo thanks to #Gene
n=7
arr=[3,2,2,5]
INF = 9223372036854775807
size = 4
dp = [[INF for i in range(n+1)] for j in range(size+1)]
def ans(a,b,c):
if(dp[a][c]!=INF):
return dp[a][c]
if(a>=size):
dp[a][c] = pow((n-c),2)
return pow((n-c),2)
if(c+arr[a]+1 > n):
dp[a][c] = (pow((n-c),2)+ans(a+1,b+1,arr[a]))
return dp[a][c]
dp[a][c] = (min(ans(a+1,b,c+arr[a]+1),pow((n-c),2)+ans(a+1,b+1,arr[a])))
return dp[a][c]
print(ans(1,1,3))

Create a dictionary of subcubes from larger cube in Python

I am examining every contiguous 8 x 8 x 8 cube within a 50 x 50 x 50 cube. I am trying to create a collection (in this case a dictionary) of the subcubes that contain the same sum and a count of how many subcubes share that same sum. So in essence, the result would look something like this:
{key = sum, value = number of cubes that have the same sum}
{256 : 3, 119 : 2, ...}
So in this example, there are 3 cubes that sum to 256 and 2 cubes that sum to 119, etc. Here is the code I have thus far, but it only sums (at least I think it does):
an_array = np.array([i for i in range(500)])
cube = np.reshape(an_array, (8, 8, 8))
c_size = 8 # cube size
sum = 0
idx = None
for i in range(cube.shape[0] - cs + 2):
for j in range(cube.shape[1] - cs + 2):
for k in range(cube.shape[2] - cs + 2):
cube_sum = np.sum(cube[i:i + cs, j:j + cs, k:k + cs])
new_list = {cube_sum : ?}
What I am trying to make this do is iterate the cube within cubes, sum all cubes then count the cubes that share the same sum. Any ideas would be appreciated.
from collections import defaultdict
an_array = np.array([i for i in range(500)])
cube = np.reshape(an_array, (8, 8, 8))
c_size = 8 # cube size
sum = 0
idx = None
result = defaultdict(int)
for i in range(cube.shape[0] - cs + 2):
for j in range(cube.shape[1] - cs + 2):
for k in range(cube.shape[2] - cs + 2):
cube_sum = np.sum(cube[i:i + cs, j:j + cs, k:k + cs])
result[cube_sum] += 1
Explanation
The defaultdict(int), can be read as a result.get(key, 0). Which means that if a key doesn't exists it will be initialized with 0. So the line result[cube_sum] += 1, will either contain 1, or add 1 to the current number of cube_sum.

If element in list is in in range of another element from another list

Below is a question that is an extension of a question I asked a month ago.
Find if item in list a in range of items in sublist of list b
Let's suppose I have two lists:
x = ['2_12_20','2_40_60','4_45_70']
y = ['2_16','2_18','4_60','3_400']
In a biological context, these numbers refer to chromosome positions. For example, in list x, '2_12_20' refers to chromosome 2 between positions 12 and 20.
Similarly, in list y, '2_16' refers to chromosome 2 at position 16.
What I would like to do is determine which chromosome position pairs in y fall within the range in each element in list x.
This is the code I have written so far:
x_new = list(map(lambda z: tuple(map(int,z.split('_'))),x))
y_new = list(map(lambda z: tuple(map(int,z.split('_'))),y))
def check_in_range(number):
for i in y_new:
if number[0] == i[0]: #if chromosomes match
if number[1] <= i[1] and i[1] <= number[2]: #if position falls in range
return i
else:
continue #if chromosomes do not match, move on to next
answer = dict(zip(x_new, map(check_in_range, x_new)))
I would like my output to return a dictionary, where the elements in x are the keys and the values are any element in y.
My answer should be
{(2, 12, 20): [(2, 16),(2,18)], (2, 40, 60): None, (4, 45, 70): (4, 60)}
But I am getting
{(2, 12, 20): (2, 16), (2, 40, 60): None, (4, 45, 70): (4, 60)}
How do I alter my code so that it updates the dictionary if a key-value pair is already present?
I believe I figured it out.
x_new = list(map(lambda z: tuple(map(int,z.split('_'))),x))
y_new = list(map(lambda z: tuple(map(int,z.split('_'))),y))
def check_in_range(number):
list_a = []
for i in y_new:
if number[0] == i[0]: #if chromosomes match
if number[1] <= i[1] and i[1] <= number[2]: #if position falls in range
list_a.append(i)
else:
continue #if chromosomes do not match, move on to next
return(list_a)
answer = dict(zip(x_new, map(check_in_range, x_new)))

Python find indexes of list of lists

I'm trying to find the indexes of all the elements in a python list of lists. The list would look something like this:
list = [[x,y,x],
[x,y,y],
[y,y,y]]
To do this I have tried to use a nested loop like this:
for lst in list:
print(list.index(lst))
for x in lst:
print(lst.index(x))
This however prints out a long list with almost seemingly random numbers.
screenshot of output for a slightly different list
What I'm tring to achieve is an output looking something like this:
0
1
0
2
0
3
1
0
1
0
Is there anyone who can help out a python beginner?
You can enumerate to print indexes
x = 22
y = 34
l = [[x,y,x],
[x,y,y],
[y,y,y]]
indexes = [(i, j) for i, nl in enumerate(l) for j, nle in enumerate(nl)]
print(*indexes, sep="\n")
# output
(0, 0)
(0, 1)
(0, 2)
(1, 0)
(1, 1)
(1, 2)
(2, 0)
(2, 1)
(2, 2)
https://docs.python.org/3/library/functions.html#enumerate
You can easily access index and value with the use of by looping thorugh the list using enumerate. I added some printing with text to show what number is what.
myList = [[1,2,3],
[4,5,6],
[7,8,9]]
for lstIdx, lst in enumerate(myList):
print("list idx: " + str(lstIdx))
for idx, item in enumerate(lst):
print("item idx in list: " + str(idx))
output:
list idx: 0
item idx in list: 0
item idx in list: 1
item idx in list: 2
list idx: 1
item idx in list: 0
item idx in list: 1
item idx in list: 2
list idx: 2
item idx in list: 0
item idx in list: 1
item idx in list: 2

Getting the wrong output (Ramanujan)

Essentially what I want the function to do is this:
Take an integer input and save it as n
Print a list of vectors with two entries (a,b), where
For example, when I input n = 443889, I should get an output of [(76,17),(38,73)], because the only two solutions to this problem are: , and
But with my code, when I give the input n=443889, I get the output [(76, 17), (75, 28), (74, 34), (73, 38), (72, 41)], even though some of these vectors doesn't give a solution to my equation.
def ramanujans(n):
lista = []
counter = 0
for a in range(1,n):
b = (n- (a**3))**(1/3)
result = a**3 + b**3
if isinstance(b,complex):
break
elif result == n:
b = int(round(b))
lista.insert(0,(a, b))
return (lista)
with a little different checking for complex results and a different check if result == n (integer comparison only) i seem to be getting the correct results:
def ramanujans(n):
res = []
for a in range(1, n):
s = n - a**3
if s < 0:
break
b = round(s**(1/3))
result = a**3 + b**3
if result == n:
res.append((a, b))
return res
with:
[(17, 76), (38, 73), (73, 38), (76, 17)]
as results for n=443889
you could stop the loop earlier; if a is around (n/2)**(1/3) you just get the results you already have with the a and b interchanged; this could then look like (did not carefully check the edge cases...):
from math import ceil
def ramanujans(n):
res = []
limit = ceil(((n/2)**(1/3)))
for a in range(1, limit+1):
s = n - a**3
b = round(s**(1/3))
result = a**3 + b**3
if result == n:
if a <= b: # this is to cover the edge cases...
res.append((a, b))
return res
print(ramanujans(n=443889)) # [(17, 76), (38, 73)]
print(ramanujans(n=2000)) # [(10, 10)]
print(ramanujans(n=1729)) # [(1, 12), (9, 10)]
and would only return 'half' the results.

Resources