getting specific data in range of 1-10 from dict - python-3.x

Im fairly new to programming and came upon a work-related problem(nothing to do with computers or any)
and thought i could automaticly calculate this for my employees.
update:
It needs to scan through the dict keys and find the number related to the input:
For example input 289:
Search through Dict keys
271: 1393.289, # 7.5505
281: 1468.817, # 7.5735
291: 1544.574, # 7.5962
301: 1620.559, # 7.6188
289 is between 281 and 291
Take value of 281 which is 1468.817(use this as base value)
289-281 = 8, so remainder of 8 is then multiplied by 7.5735(the [1] index of the dict) then return value of base + remainder * 7.5735 = 1.529,405
the value that we need to multiple remainder with changes on every new dict key

I am not sure I fully comprehend what you are trying to do, but if I understand correctly you are processing a user input with a special function that will yield a result 'base' in the range of 0 to 320. Using this computed base you then want to select a key from a dictionary basisIJK such that key-1 <= key < key+1. Having identified the appropriate basisIJK dictionary key you want to return key + (base-key)* basisIJK[key][1].
If my understanding is correct you can do the following:
basisIJK = {271 : [1393.289, 7.5505], 281 : [1468.817, 7.5735], 291 : [1544.574, 7.5962], 301 : [1620.559, 7.6188]}
def find_value(n, d):
kys = sorted(list(d.keys()))
for i in range(1, len(kys)):
if kys[i-1] <= n and n < kys[i]:
r = d[kys[i-1]][0] + (n - kys[i-1]) * d[kys[i-1]][1]
return r
return None
executing
find_value(289, basisIJK)
Yields
1529.405

Related

Key error while adding a new key to the dictionary

This is my code:
nums = sorted(nums)
n = len(nums)
maps = { 0 : [nums[0]]}
maps[2] = ["shot"]
dp = [1 for _ in nums]
for i in range(1 , n):
for j in range(i , -1 , -1):
if nums[i] % nums[j] == 0:
dp[i] = dp[j]+1
print(maps)
if i not in maps.keys():
maps[i] = maps[j].append(nums[i])
The error message:
KeyError: 1
maps[i] = maps[j].append(nums[i])
Line 15 in largestDivisibleSubset (Solution.py)
ret = Solution().largestDivisibleSubset(param_1)
Line 41 in _driver (Solution.py)
_driver()
Line 52 in <module> (Solution.py)
The input: nums = [1,2,3,5,7]
You can only use the append method to insert a value to a key, that is already existing.
So either you do something like this:
maps[i] = nums[i]
Or:
maps[i] = nums[j]
This is your problem stanza:
if i not in maps.keys():
maps[i] = maps[j].append(nums[i])
Here you are asking 'if i is not in the maps dictionary, then get the value at index i from the nums array and append it to the value referenced by the key j in the maps dictionary, then assign the result of that function back to the value of the key i in the dictionary'.
append() returns None, which means you'll just be putting None at the key i. But your error is actually saying that the key 1 doesn't exist in the object you're looking into. Presumably that is maps, because you are attempting to dereference maps[j] - and j is not one of the keys in maps. Since that can't be fetched, and would be None if you did, you can't append anything to it.
A definitive solution can't be given here, since it's unclear what you want to end up with. Given an input array of [1,2,3,5,7] what do you expect maps to look like at the end of this function?
One thing that might help is something like:
if i not in maps.keys():
ls = maps.get(j, [])
ls.append(nums[i])
maps[i] = ls
Here, we get the list at index j and return a default empty list [] if j is not inside the map already. Then we assign the modified list to the key i. I'm not sure if this is actually what you're looking for, though.

List Index Error - Combining list elements via index

'Original String = 1234 A 56 78 90 B'
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
return ends
The above returns:
['B', 'A']
My next function is supposed to then combine them into 1 string and get value from dictionary. I've tried this with/without the str in mult_ends with the same result.
def func_2(two_dict):
global mult_ends
mult_ends = str(ends[0] + ends[1])
for key in mult_ends:
if key in two_dict:
return two_dict[key]
The results confuse me since I use pretty identical processes in other functions with no issue.
IndexError: list index out of range
Why would the list index be out of range when there is clearly a 0 and 1? I've also added global ends to func_2 and I still received the same error.
*** RESTRUCTURED FUNCTIONS INTO 1 ***
def func_1(one_dict):
global ends
ends = []
for x in original_string:
if x in one_dict:
ends.append(one_dict[x])
mult_ends = ends[0] + ends[1]
for key in two_dict:
if key in mult_ends:
return ends_final_dict[key]
return None
Now, it actually does what I want it to do and returns the correct dictionary key in the event log:
A B
However, it does not return when I try to insert it back into my GUI for the user and it still throws the IndexError: list index out of range.

What's the best way to search a text file for consecutive repetitions and return the text with highest number of them?

I'm extremely new to programming in general and have only been learning Python for 1 week.
For a class, I have to analyze a text DNA sequence, something like this:
CTAGATAGATAGATAGATAGATGACTA
for these specific keys: AGAT,AATG,TATC
I have to keep track of the largest number of consecutive repetitions for each, disregarding all but the highest number of repetitions.
I've been pouring over previous stackoverflow answers and I saw groupby() suggested as a way to do this. I'm not exactly sure how to use groupby for my specific implementation needs though.
It seems like I will have to read the text sequence from a file into a list. Can I import what is essentially a text string into a list? Do I have to separate all of the characters by commas? Will groupby work on a string?
It also looks like groupby would give me the highest incident of consecutive repetitions, but in the form of a list. How would I get the highest result from that list out of that list to them be stored somewhere else, without me the programmer having to look at the result? Will groupby return the highest number of consecutive repeats first in the list? Or will it be placed in order of when it occured in the list?
Is there a function I can use to isolate and return the sequence with the highest repetition incidence, so that I can compare that with the dictionary file I've been provided with?
Frankly, I really could use some help breaking down the groupby function in general.
My assignment recommended possibly using a slice to accomplish this, and that seemed somehow more daunting to try, but if that's the way to go, please let me know, and I wouldn't turn down a mudge in the direction on how in the heck to do that.
Thank you in advance for any and all wisdom on this.
Here's a similar solution to the previous post, but may have better readability.
# The DNA Sequence
DNA = "CTAGATAGATAGATAGATAGATGACTAGCTAGATAGATAGATAGATAGATGACTAGAGATAGATAGATCTAG"
# All Sequences of Interest
elements = {"AGAT", "AATG", "TATC"}
# Add Elements to A Dictionary
maxSeq = {}
for element in elements:
maxSeq[element] = 0
# Find Max Sequence for Each Element
for element in elements:
i = 0
curCount = 0
# Ensure DNA Length Not Reached
while i+4 <= len(DNA):
# Sequence Not Being Tracked
if curCount == 0:
# Sequence Found
if DNA[i: i + 4] == element:
curCount = 1
i += 4
# Sequence Not Found
else: i += 1
# Sequence Is Being Tracked
else:
# Sequence Found
if DNA[i: i + 4] == element:
curCount += 1
i += 4
# Sequence Not Found
else:
# Check If Previous Max Was Beat
if curCount > maxSeq[element]:
maxSeq[element] = curCount
# Reset Count
curCount = 0
i += 1
#Check If Sequence Was Being Tracked At End
if curCount > maxSeq[element]: maxSeq[element] = curCount
#Display
print(maxSeq)
Output:
{'AGAT': 5, 'TATC': 0, 'AATG': 0}
This doesn't seem like a groupby problem since you want multiple groups of the same key. It would easier to just scan the list for key counts.
# all keys (keys are four chars each)
seq = "CTAGATAGATAGATAGATAGATGACTAGCTAGATAGATAGATAGATAGATGACTAGAGATAGATAGATCTAG"
# split key string into list of keys: ["CTAG","ATAG","ATAG","ATAG", ....]
lst = [seq[i:i+4] for i in (range(0,len(seq),4))]
lst.append('X') # the while loop only tallies when next key found, so add fake end key
# these are the keys we care about and want to store the max consecutive counts
dicMax = { 'AGAT':0, 'AATG':0, 'TATC':0, 'ATAG':0 } #dictionary of keys and max consecutive key count
# the while loop starts at the 2nd entry, so set variables based on first entry
cnt = 1
key = lst[0] #first key in list
if (key in dicMax): dicMax[key] = 1 #store first key in case it's the max for this key
ctr = 1 # start at second entry in key list (we always compare to previous entry so can't start at 0)
while ctr < len(lst): #all keys in list
if (lst[ctr] != lst[ctr-1]): #if this key is different from previous key in list
if (key in dicMax and cnt > dicMax[key]): #if we care about this key and current count is larger than stored count
dicMax[key] = cnt #store current count as max count for this key
#set variables for next key in list
cnt = 0
key = lst[ctr]
ctr += 1 #list counter
cnt += 1 #counter for current key
print(dicMax) # max consecutive count for each key
Raiyan Chowdhury suggested that the sequences may overlap, so dividing the base sequence into four character strings may not work. In this case, we need to search for each string individually.
Note that this algorithm is not efficient, but readable to a new programmer.
seq = "CTAGATAGATAGATAGATAGATGACTAGCTAGATAGATAGATAGATAGATGACTAGAGATAGATAGATCTAG"
dicMax = { 'AGAT':0, 'AATG':0, 'TATC':0, 'ATAG':0 } #dictionary of keys and max consecutive key count
for key in dicMax: #each key, could divide and conquer here so all keys run at same time
for ctr in range(1,9999): #keep adding key to itself ABC > ABCABC > ABCABCABC
s = key * ctr #create string by repeating key "ABC" * 2 = "ABCABC"
if (s in seq): # if repeated key found in full sequence
dicMax[key]=ctr # set max (repeat) count for this key
else:
break; # exit inner for #done with this key
print(dicMax) #max consecutive key counts

Splitting number into 2 lists of numbers of certain range

I want to create 2 lists of numbers, generated randomly with certain range.
So, if user want to generate lists as above from value 1000 (example) it should split 1000 into 2 lists:
1st list - 4 numbers in range from 40 to 80
2nd list - 5 numbers in range from 80 to 160
Sum of all produced list numbers must equal input (or hardcoded number, doesn't matter). Main range of input 560 - 1120.
Python 3.7 actually, and some problems in declaring that
See code below, I've managed to generate random 2 lists of certain range but I don't have idea how to work that out that it can have declared sum and split it into lists rather than generating random lists all together.
import random
def function():
num = 4
start = 40
end = 80
def rand(start, end, num):
res = []
for j in range(num):
res.append(random.randint(start,end))
return res
return rand(start, end, num)
def function2():
num2 = 5
start2 = 80
end2 = 160
def rand2(start2, end2, num2):
res2 = []
for k in range(num2):
res2.append(random.randint(start2,end2))
return res2
return rand2(start2, end2, num2)
a = function()
b = function2()
print (a)
print (sum(a))
print(b)
print(sum(b))
suma = sum(a+b)
print (suma)
If anyone could help me solving that I'd be really glad, I'm making a little project and this is required :)

find the first occurrence of a number greater than k in a sorted array

For the given sorted list,the program should return the index of the number in the list which is greater than the number which is given as input.
Now when i run code and check if it is working i am getting 2 outputs. One is the value and other output is None.
If say i gave a input of 3 for the below code.The expected output is index of 20 i.e., 1 instead i am getting 1 followed by None.
If i give any value that is greater than the one present in the list i am getting correct output i.e., "The entered number is greater than the numbers in the list"
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a,num_to_find):
j = i = 0
while j==0:
if a[len(a)-1] > num_to_find:
if num_to_find < a[i]:
j=1
print(i)
break
else:
i = i + 1
else:
ret_state = "The entered number is greater than the numbers in the list"
return ret_state
print(occur1(a,num_to_find))
This code is difficult to reason about due to extra variables, poor variable names (j is typically used as an index, not a bool flag), usage of break, nested conditionals and side effect. It's also inefficient because it needs to visit each element in the list in the worst case scenario and fails to take advantage of the sorted nature of the list to the fullest. However, it appears working.
Your first misunderstanding is likely that print(i) is printing the index of the next largest element rather than the element itself. In your example call of occur1([2, 20, 30], 3)), 1 is where 20 lives in the array.
Secondly, once the found element is printed, the function returns None after it breaks from the loop, and print dutifully prints None. Hopefully this explains your output--you can use return a[i] in place of break to fix your immediate problem and meet your expectations.
Having said that, Python has a builtin module for this: bisect. Here's an example:
from bisect import bisect_right
a = [1, 2, 5, 6, 8, 9, 15]
index_of_next_largest = bisect_right(a, 6)
print(a[index_of_next_largest]) # => 8
If the next number greater than k is out of bounds, you can try/except that or use a conditional to report the failure as you see fit. This function takes advantage of the fact that the list is sorted using a binary search algorithm, which cuts the search space in half on every step. The time complexity is O(log(n)), which is very fast.
If you do wish to stick with a linear algorithm similar to your solution, you can simplify your logic to:
def occur1(a, num_to_find):
for n in a:
if n > num_to_find:
return n
# test it...
a = [2, 5, 10]
for i in range(11):
print(i, " -> ", occur1(a, i))
Output:
0 -> 2
1 -> 2
2 -> 5
3 -> 5
4 -> 5
5 -> 10
6 -> 10
7 -> 10
8 -> 10
9 -> 10
10 -> None
Or, if you want the index of the next largest number:
def occur1(a, num_to_find):
for i, n in enumerate(a):
if n > num_to_find:
return i
But I want to stress that the binary search is, by every measure, far superior to the linear search. For a list of a billion elements, the binary search will make about 20 comparisons in the worst case where the linear version will make a billion comparisons. The only reason not to use it is if the list can't be guaranteed to be pre-sorted, which isn't the case here.
To make this more concrete, you can play with this program (but use the builtin module in practice):
import random
def bisect_right(a, target, lo=0, hi=None, cmps=0):
if hi is None:
hi = len(a)
mid = (hi - lo) // 2 + lo
cmps += 1
if lo <= hi and mid < len(a):
if a[mid] < target:
return bisect_right(a, target, mid + 1, hi, cmps)
elif a[mid] > target:
return bisect_right(a, target, lo, mid - 1, cmps)
else:
return cmps, mid + 1
return cmps, mid + 1
def linear_search(a, target, cmps=0):
for i, n in enumerate(a):
cmps += 1
if n > target:
return cmps, i
return cmps, i
if __name__ == "__main__":
random.seed(42)
trials = 10**3
list_size = 10**4
binary_search_cmps = 0
linear_search_cmps = 0
for n in range(trials):
test_list = sorted([random.randint(0, list_size) for _ in range(list_size)])
test_target = random.randint(0, list_size)
res = bisect_right(test_list, test_target)[0]
binary_search_cmps += res
linear_search_cmps += linear_search(test_list, test_target)[0]
binary_search_avg = binary_search_cmps / trials
linear_search_avg = linear_search_cmps / trials
s = "%s search made %d comparisons across \n%d searches on random lists of %d elements\n(found the element in an average of %d comparisons\nper search)\n"
print(s % ("binary", binary_search_cmps, trials, list_size, binary_search_avg))
print(s % ("linear", linear_search_cmps, trials, list_size, linear_search_avg))
Output:
binary search made 12820 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 12 comparisons
per search)
linear search made 5013525 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 5013 comparisons
per search)
The more elements you add, the worse the situation looks for the linear search.
I would do something along the lines of:
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a, num_to_find):
for i in a:
if not i <= num_to_find:
return a.index(i)
return "The entered number is greater than the numbers in the list"
print(occur1(a, num_to_find))
Which gives the output of 1 (when inputting 3).
The reason yours gives you 2 outputs, is because you have 2 print statements inside your code.

Resources