list object not callable project euler 59 - python
I am trying to do project euler problem 59, i am having an issue in that one of the necessary methods won't work as the program returns:
xorNum = test(f,j)
TypeError: 'list' object is not callable.
Both f and j are integers and when I used the test method with two random integers, it worked perfectly. Does anyone have any ideas why it may not be working?
def main():
cipherText = """79,59,12,2,79,35,8,28,20,2,3,68,8,9,68,45,0,12,9,67,68,4,7,5,23,27,1,21,79,85,78,79,85,71,38,10,71,27,12,2,79,6,2,8,13,9,1,13,9,8,68,19,7,1,71,56,11,21,11,68,6,3,22,2,14,0,30,79,1,31,6,23,19,10,0,73,79,44,2,79,19,6,28,68,16,6,16,15,79,35,8,11,72,71,14,10,3,79,12,2,79,19,6,28,68,32,0,0,73,79,86,71,39,1,71,24,5,20,79,13,9,79,16,15,10,68,5,10,3,14,1,10,14,1,3,71,24,13,19,7,68,32,0,0,73,79,87,71,39,1,71,12,22,2,14,16,2,11,68,2,25,1,21,22,16,15,6,10,0,79,16,15,10,22,2,79,13,20,65,68,41,0,16,15,6,10,0,79,1,31,6,23,19,28,68,19,7,5,19,79,12,2,79,0,14,11,10,64,27,68,10,14,15,2,65,68,83,79,40,14,9,1,71,6,16,20,10,8,1,79,19,6,28,68,14,1,68,15,6,9,75,79,5,9,11,68,19,7,13,20,79,8,14,9,1,71,8,13,17,10,23,71,3,13,0,7,16,71,27,11,71,10,18,2,29,29,8,1,1,73,79,81,71,59,12,2,79,8,14,8,12,19,79,23,15,6,10,2,28,68,19,7,22,8,26,3,15,79,16,15,10,68,3,14,22,12,1,1,20,28,72,71,14,10,3,79,16,15,10,68,3,14,22,12,1,1,20,28,68,4,14,10,71,1,1,17,10,22,71,10,28,19,6,10,0,26,13,20,7,68,14,27,74,71,89,68,32,0,0,71,28,1,9,27,68,45,0,12,9,79,16,15,10,68,37,14,20,19,6,23,19,79,83,71,27,11,71,27,1,11,3,68,2,25,1,21,22,11,9,10,68,6,13,11,18,27,68,19,7,1,71,3,13,0,7,16,71,28,11,71,27,12,6,27,68,2,25,1,21,22,11,9,10,68,10,6,3,15,27,68,5,10,8,14,10,18,2,79,6,2,12,5,18,28,1,71,0,2,71,7,13,20,79,16,2,28,16,14,2,11,9,22,74,71,87,68,45,0,12,9,79,12,14,2,23,2,3,2,71,24,5,20,79,10,8,27,68,19,7,1,71,3,13,0,7,16,92,79,12,2,79,19,6,28,68,8,1,8,30,79,5,71,24,13,19,1,1,20,28,68,19,0,68,19,7,1,71,3,13,0,7,16,73,79,93,71,59,12,2,79,11,9,10,68,16,7,11,71,6,23,71,27,12,2,79,16,21,26,1,71,3,13,0,7,16,75,79,19,15,0,68,0,6,18,2,28,68,11,6,3,15,27,68,19,0,68,2,25,1,21,22,11,9,10,72,71,24,5,20,79,3,8,6,10,0,79,16,8,79,7,8,2,1,71,6,10,19,0,68,19,7,1,71,24,11,21,3,0,73,79,85,87,79,38,18,27,68,6,3,16,15,0,17,0,7,68,19,7,1,71,24,11,21,3,0,71,24,5,20,79,9,6,11,1,71,27,12,21,0,17,0,7,68,15,6,9,75,79,16,15,10,68,16,0,22,11,11,68,3,6,0,9,72,16,71,29,1,4,0,3,9,6,30,2,79,12,14,2,68,16,7,1,9,79,12,2,79,7,6,2,1,73,79,85,86,79,33,17,10,10,71,6,10,71,7,13,20,79,11,16,1,68,11,14,10,3,79,5,9,11,68,6,2,11,9,8,68,15,6,23,71,0,19,9,79,20,2,0,20,11,10,72,71,7,1,71,24,5,20,79,10,8,27,68,6,12,7,2,31,16,2,11,74,71,94,86,71,45,17,19,79,16,8,79,5,11,3,68,16,7,11,71,13,1,11,6,1,17,10,0,71,7,13,10,79,5,9,11,68,6,12,7,2,31,16,2,11,68,15,6,9,75,79,12,2,79,3,6,25,1,71,27,12,2,79,22,14,8,12,19,79,16,8,79,6,2,12,11,10,10,68,4,7,13,11,11,22,2,1,68,8,9,68,32,0,0,73,79,85,84,79,48,15,10,29,71,14,22,2,79,22,2,13,11,21,1,69,71,59,12,14,28,68,14,28,68,9,0,16,71,14,68,23,7,29,20,6,7,6,3,68,5,6,22,19,7,68,21,10,23,18,3,16,14,1,3,71,9,22,8,2,68,15,26,9,6,1,68,23,14,23,20,6,11,9,79,11,21,79,20,11,14,10,75,79,16,15,6,23,71,29,1,5,6,22,19,7,68,4,0,9,2,28,68,1,29,11,10,79,35,8,11,74,86,91,68,52,0,68,19,7,1,71,56,11,21,11,68,5,10,7,6,2,1,71,7,17,10,14,10,71,14,10,3,79,8,14,25,1,3,79,12,2,29,1,71,0,10,71,10,5,21,27,12,71,14,9,8,1,3,71,26,23,73,79,44,2,79,19,6,28,68,1,26,8,11,79,11,1,79,17,9,9,5,14,3,13,9,8,68,11,0,18,2,79,5,9,11,68,1,14,13,19,7,2,18,3,10,2,28,23,73,79,37,9,11,68,16,10,68,15,14,18,2,79,23,2,10,10,71,7,13,20,79,3,11,0,22,30,67,68,19,7,1,71,8,8,8,29,29,71,0,2,71,27,12,2,79,11,9,3,29,71,60,11,9,79,11,1,79,16,15,10,68,33,14,16,15,10,22,73"""
asciiDict = {} #create ascii table dictionary with number as key
asciiDict2 = {} #reverse key value of above dictionary
for char in range(256):
keyVal = "%d: %c" % (char, char)
slicer = keyVal.index(':')
key = keyVal[0:slicer]
val = keyVal[slicer+2:]
asciiDict[int(key)] = val
for key in asciiDict.keys():
newVal = asciiDict[key]
asciiDict2[newVal] = key
newlist = [int(n) for n in cipherText.split(',')]
#convert cipher text into list of numbers
listOfThreeChars = []
for n in range(len(newlist)):
listOfThreeChars.append(newlist[n:n+3])
#create list of groups of three consecutive numbers in cipherText
mostCommonDict = mostCommon(listOfThreeChars)
mostFrequent3 = mostCommonDict[max(mostCommonDict.keys())]
#most common three consecutive numbers, if the key is right these
#numbers will become a common three letter word such as 'the'
print testCipher(asciiDict,asciiDict2, 'jhd', mostFrequent3)
def testCipher(asciiDict,asciiDict2, cipherKey, cipherExtract):
cipherKeyAscii = []
test = []
output = []
for k in cipherKey:
asciiNum = asciiDict2[k]
cipherKeyAscii.append(asciiNum)
print cipherKeyAscii
for i in range(len(cipherKeyAscii)):
f,j = cipherKeyAscii[i],cipherExtract[i]
print type(f), type(j),f,j
xorNum = test(f,j) #HERE IS WHERE THE PROBLEM IS
test.append(xorNum)
for final in test:
letter = asciiDict[final]
output.append(letter)
return output
def mostCommon(lst): #find most common three consecutive number combinations in text
dic = {}
for three in lst:
key = three
count = []
for n in lst:
if n == key:
count.append(1)
dic[len(count)] = key
return dic
#return max(set(sum(lst, [])), key=sum(lst, []).count)
def toBinary(decimalNumber):
quotient = 1
remainder = 0
tmpNum = decimalNumber
finalNumberList = []
n = ""
#e.g. take 14...
while quotient != 0:
remainder = decimalNumber % 2 #14 % 2 = 0
quotient = decimalNumber / 2 #14 / 2 = 7
decimalNumber = quotient # 7 % 2 = 1 and so on...
finalNumberList.insert( 0, remainder )
# Used because all numbers are in a list, i.e. convert to string
for num in finalNumberList:
n += str( num )
return n
def XOR(number1, number2):
number1List = []
number2List = []
XORoutput = []
for i in str(number1): #turn both binary numbers into lists
number1List.append(int(i))
for i in str(number2):
number2List.append(int(i))
if len(number1List)>len(number2List): #make sure they are same lengths
diff = len(number1List) - len(number2List)
for i in range(diff):
number2List.insert(0,0)
for i in range(len(number1List)): #XOR it
if number1List[i] == number2List[i]:
XORoutput.append(0)
if number1List[i] != number2List[i]:
XORoutput.append(1)
num = int(''.join(map(str,XORoutput))) #turn XOR list into int
return num
def test(num1, num2): #convert input to binary and xor and return to integer
print num1,num2
bin1 = toBinary(num1) #turn to binary
bin2 = toBinary(num2)
xor = XOR(bin1,bin2) #XOR
output = int(str(xor),2) #return to number
return output
if __name__ == "__main__":
#print main.__doc__
main()
You set test to a list; you cannot have both a function and a list use the same name:
def main():
# other code
test = []
# more code
for i in range(len(cipherKeyAscii)):
# more irrelevant code
xorNum = test(f,j)
test.append(xorNum)
masking the function test(). You even use test as a list again on the very next line.
Rename the list, or rename the function. Most of all, pick better, clearer names for your variables.
You defined test to be a list. You also defined it to be a function. De-conflict your names and you should be good to go.
Related
How can I create a new list when giving intergers, and have to return hexadecimal
Given the following list: list = [2,10,10,10,4,5] How can I write a function that returns the output: output = 210AA:45 I was working with this code so far, but don't know what else to add so that once a number between 10 and 15 is repeated, return the repeated number in its hexadecimal form as in the output def int_to_string(data): string = "" for i in data: hexadecimal = hex(i) string += hexadecimal[2:] string[0] = 15 return string
Use a list [] instead of a string "" strings are immutable and don't support index lookup and assignment. append the hex val and then edit the first index as you see fit to get your result and retun a joined list with ''.join(#ur_lst)
A dictionary describing the mapping between decimal and hex could add readability. Remark: don't shadow the name of build-functions, in this case list. See doc for a complete list. lst = [2,10,10,10,4,5,13,15,0] # <- new testing list # dictionary for conversion num2hex = {i: str(i) for i in range(10)} num2hex.update(zip(range(10, 16), "ABCDEF")) # conversion list -> str res = '' consecutve_hex, is_last_hex = 0, False for d in lst: if 10 <= d <= 15: consecutive_hex += 1 is_last_hex = False if consecutive_hex > 1: res += num2hex[d] else: res += str(d) else: if not is_last_hex: if res: res += ':' consecutive_hex = 0 is_last_hex = True res += str(d) print(res) #210AA:4513F:0
Printing numbers that contain only odd digits in a given range
I find some difficulties with the task of printing numbers in given range that contain only odd digits. f.e: The first number is 2345 and the second number is 6789. There is one more thing - the printed numbers should be limited only the range according to the digit position 2 to 6 (3,5), 3 to 7(3,5,7), 4 to 8(5,7), 5 to 9(5,7,9) - so it means that the first numbers should be 3355,3357,3359,3375,3377,3379,3555,3557.... The code does not execute it the way output should look: number_one=int(input()) number_two=int(input()) list_one=[] list_two=[] number_one=str(number_one) number_two=str(number_two) for i in number_one: if int(i)==0 or int(i)%2==0: i=int(i)+1 list_one.append(int(i)) for i in number_two: list_two.append(int(i)) a=0 b=0 c=0 d=0 for j in range(list_one[0],list_two[0]+1): if j%2==1: a=j for p in range(list_one[1],list_two[1]+1): if p%2==1: b=p for x in range(list_one[2],list_two[2]+1): if x%2==1: c=x for y in range(list_one[3],list_two[3]+1): if y%2==1: d=y print(f"{a}{b}{c}{d}",end=" ") There are a lot of repetitions in the output that I would like to avoid. Thank you in advance!
May be this is not an optimal solution. But this is working for positive integers with same length. number_one=int(input()) number_two=int(input()) if len(str(number_one)) != len(str(number_two)): raise Exception("numbers should be of same length") def print_num(num_one, num_two): res = [] for i,j in zip(num_one, num_two): next_odd_for_i = int(i) + (not (int(i)%2)) prev_odd_for_j = int(j) - (not (int(j)%2)) temp_str = "" for i_next in range(next_odd_for_i, prev_odd_for_j+1, 2): temp_str += str(i_next) res.append(temp_str) return res def print_perm(li_of_str): if len(li_of_str) == 1: return [li_of_str[-1]] res = [] first = li_of_str[0] for j in first: tmp = [j+k for n in print_perm(li_of_str[1:]) for k in n ] res.append(tmp) return res print(print_num(str(number_one), str(number_two))) print(print_perm(print_num(str(number_one), str(number_two))))
One way to solve this problem is with recursion. This function takes in two strings representing numbers and returns all the odd numbers (as strings) that satisfy the conditions you specified: def odd_digits(num1, num2): # split off first digit of string msd1, rest1 = int(num1[0]), num1[1:] # make the digit odd if required msd1 += msd1 % 2 == 0 # split off first digit of string msd2, rest2 = int(num2[0]), num2[1:] # make the digit odd if required msd2 -= msd2 % 2 == 0 # if no more digits, just return the values between msd1 and msd2 if not rest1: return [str(i) for i in range(msd1, msd2+1, 2)] # otherwise, append the results of a recursive call to each # odd digit between msd1 and msd2 result = [] for i in range(msd1, msd2+1, 2): result += [str(i) + o for o in odd_digits(rest1, rest2)] return result print(odd_digits('2345', '6789')) Output: [ '3355', '3357', '3359', '3375', '3377', '3379', '3555', '3557', '3559', '3575', '3577', '3579', '3755', '3757', '3759', '3775', '3777', '3779', '5355', '5357', '5359', '5375', '5377', '5379', '5555', '5557', '5559', '5575', '5577', '5579', '5755', '5757', '5759', '5775', '5777', '5779' ] If you want to use integer values just use (for example) print(list(map(int, odd_digits(str(2345), str(6789))))) The output will be as above but all values will be integers rather than strings. If you can use libraries, you can generate ranges for each digit and then use itertools.product to find all the combinations: import itertools def odd_digits(num1, num2): ranges = [] for d1, d2 in zip(num1, num2): d1 = int(d1) + (int(d1) % 2 == 0) d2 = int(d2) - (int(d2) % 2 == 0) ranges.append(list(range(d1, d2+1, 2))) return [''.join(map(str, t)) for t in itertools.product(*ranges)] This function takes string inputs and produces string outputs, which will be the same as the first function above.
generate a sequence with respect to subsequences in python
I try to generate the following sequences. text = ACCCEBCE target = 000000D0 a random text of different characters is generated. In the text sequence, if the following subsequences are found, the target is going to be D or E. Otherwise, the target will be 0. ABC --> D BCD --> E I write the following code. It works well if I generate a small number of characters. But it does not give any output if I make timesteps = 1000 etc. import string import random as rn import numpy as np def is_subseq(x, y): it = iter(y) return all(any(c == ch for c in it) for ch in x) def count(a, b, m, n): # If both first and second string # is empty, or if second string # is empty, return 1 if ((m == 0 and n == 0) or n == 0): return 1 # If only first string is empty # and second string is not empty, # return 0 if (m == 0): return 0 # If last characters are same # Recur for remaining strings by # 1. considering last characters # of both strings # 2. ignoring last character # of first string if (a[m - 1] == b[n - 1]): return (count(a, b, m - 1, n - 1) + count(a, b, m - 1, n)) else: # If last characters are different, # ignore last char of first string # and recur for remaining string return count(a, b, m - 1, n) # create a sequence classification instance def get_sequence(n_timesteps): alphabet="ABCDE"#string.ascii_uppercase text = ''.join(rn.choices(alphabet, k=n_timesteps)) print(text) seq_length=3 subseqX = [] subseqY = [] for i in range(0, len(alphabet) - seq_length, 1): seq_in = alphabet[i:i + seq_length] seq_out = alphabet[i + seq_length] subseqX.append([char for char in seq_in]) subseqY.append(seq_out) print(seq_in, "\t-->\t",seq_out) y2 = [] match = 0 countlist=np.zeros(len(subseqX)) for i, val in enumerate(text): found = False counter = 0 for g, val2 in enumerate(subseqX): listToStr = ''.join(map(str, subseqX[g])) howmany = count(text[:i], listToStr, len(text[:i]),len(listToStr)) if is_subseq(listToStr, text[:i]): if countlist[g] < howmany: match = match + howmany countlist[g] = howmany temp = g found = True if found: y2.append(subseqY[temp]) else: y2.append(0) print("counter:\t", counter) print(text) print(y2) # define problem properties n_timesteps = 100 get_sequence(n_timesteps) It might be because of the depth of the recursive function. But I need to generate 1000 or 10000 characters. How can I fix this problem? Any ideas?
I'm not sure I understand all you're trying to do (lots of code there), but I believe this simplified form of the function should work. It maintains a set of subsequences seen so far. It only extends them by adding the next letter when it is encountered. This allows the flagging to know if the prefix to the sequence up to the current character has been seen before. def flagSequence(S,letters="ABCDE",seqLen=3): subSeqs = set() result = "0" for c in S[:-1]: p = letters.index(c) subSeqs.add(c) if p>0: subSeqs.update([s+c for s in subSeqs if s[-1]==letters[p-1]]) if p in range(seqLen-1,len(letters)-1) and letters[p-seqLen+1:p+1] in subSeqs: result += letters[p+1] else: result += "0" return result output: text = "BDBACCBECEECAEAEDCAACBCCDDDBBDEEDABDBDE" print(text) print(flagSequence(text)) BDBACCBECEECAEAEDCAACBCCDDDBBDEEDABDBDE 000000000D00D0000ED00D0DDEEE00E00E00E0E with more letters: alphabet=string.ascii_uppercase text = ''.join(rn.choices(alphabet, k=10000)) flags = flagSequence(text,alphabet) print(text[:60]) print(flags[:60]) CHUJKAMWCAAIBXGIZFHALAWWFDDELXREMOQQVXFPNYJRQESRVEJKIAQILYSJ... 000000000000000000000M000000FM00FN00000G0OZK0RFTS0FKLJ0RJMZT... with longer sequences: alphabet=string.ascii_uppercase text = ''.join(rn.choices(alphabet, k=10000)) flags = flagSequence(text,alphabet,seqLen=10) print(text[200:260]) print(flags[200:260]) ...PMZCDQXAOHVMTRLYCNCJABGGNZYAWIHJJCQKMMAENQFHNQTOQOPPGHVQZXZU... ...00N0000Y000WN000Z0O0K0000O0Z0X00KK00LNN00O000O00P0PQQ00WR0Y0...
Addition of two binaries numbers in Python
Hey guys i have a trouble when i want to add two binaries numbers in Python, i mean i can enter a chain of character in a form of a string but i don't know how to select a specific value in the chain. Here is my code: chaina = input('Enter your first binary number') chainb = input('Enter your second binary number') liste = str() r = 0 for i in range [-1,chaina]: t = 0 t = chaina() + chainb() + r if t == 2 : r = 1 liste = str(t) + liste elif t == 0 or t == 1: r = 0 liste = str(t) + liste
To add two binary numbers chaina and chainb: bin(eval('0b{} + 0b{}'.format(chaina, chainb))) Or, if you want the binary number without the leading '0b': format(eval('0b{} + 0b{}'.format(chaina, chainb)), 'b') Explanation Assume for illustration that chaina = '1010' and chainb = '1111'. Then: >>> '0b{} + 0b{}'.format(chaina, chainb) '0b1010 + 0b1111' By applying eval() on this string, we get the same result as if we typed the expression 0b1010 + 0b1111 directly into Python console. >>> 0b1010 + 0b1111 25 >>> eval('0b1010 + 0b1111') 25 Finally, bin() produces a binary representation of the number passed to it as an argument: >>> bin(25) '0b11001' The same thing is accomplished by calling format() with a 'b' argument: >>> format(25, 'b') '11001' All put together, we are getting the expressions shown above.
Why don't you simply convert them into decimal and add them as you would do with decimals: y = '0b101010' z = '0b101010' print(int(y,2) + int(z,2)) print(bin((int(y,2) + int(z,2))))
Assuming that you want to do a binary sum by hand, you must: process both numbers starting from the end (reversed will help here) consistently add bits processing carry until the lengther of both numbers is exhausted reorder the result bits (here again reversed) Code could be (assuming that you can be sure that chaina and chainb only consist in 0 and 1 characters, no test for it here): def binsum(chaina, chainb): def next0(it): """Retrieve next digit from a binary representation, 0 when exhausted""" try: return int(next(it)) except StopIteration: return 0 a = reversed(chaina) # reverse chains to start with lowest order bit b = reversed(chainb) r = 0 result = [] # future result for i in range(n): t = next0(a) + next0(b) + r # add with carry if t > 1: t -= 2 r = 1 else: r = 0 result.append('1' if t else '0') if r != 0: # do not forget last carry result.append('1') return ''.join(result)
A couple of suggestions normalize the lengths of the bit strings l0, l1 = map(len, (str0, str1)) if l0 < l1: str0 = "0"*(l1-l0) + str0 elif l1 < l0: str1 = "0"*(l0-l1) + str1 do a loop on the reversed strings elements and construct the binary string bottom up remainder = 0 result = "" for bit_0, bit1 in zip(reversed(str0), reversed(str1)): bit_0, bit_1 = map(int, (bit_0, bit_1)) new_bit, remainder = f(bit_0, bit_1, remainder) result = str(new_bit) + result if remainder != 0 ... writing f(bit_0, bit_1, remainder) and treating what to do if remainder is not null at the end of the loop is left as an exercise.
Locating specific keys and corresponding values in dictionary
I wrote the following piece of code: def all_di(fl): dmm = {} for k in range(2): for i in fl: for m in range (len(i)-1): temp = i[m:m+k+1] if temp in dmm: dmm[temp] += 1.0 else: dmm[temp] = 1.0 ## return dmm p = raw_input("Enter a 2 AA long seq:") sum = 0 for x,y in dmm.iteritems(): if x == p: n1 = y for l,m in dmm.iteritems(): if l[0] == p[0]: sum = sum + m print float(n1)/float(sum) all_di(inh) if inh = {'VE':16,'GF':19,'VF':23,'GG' :2} The code works as follows: Enter a 2 AA long seq: VE result will be = 16/(16+23) = 0.41 How it works: the function searches the dictionary dmm for the key similar to the one entered in input (example taken here 'VE'). It stores its value and then searches for all the key-value pairs that have the 1st letter in common and adds all its values and returns a fraction. VE = 16 **V**E + **V**F = 39 = 16/39 = 0.41 What I want: keeping the function intact, I want to have a secondary dictionary that iterates for every key-value pair in the dictionary and stores the fractional values of it in a different dictionary such that: new_dict = {'VE' : 0.41, 'GF':0.90,'VF':0.51, 'GG': 0.09} I don't want to remove the print statement as it is the output for my program. I however need the new_dict for further work.
def all_di(fl,p=0): dmm = {} interactive = p == 0 if interactive: p = raw_input("Enter a 2 AA long seq:") if p in fl: numer = fl[p] denom = 0.0 for t in fl: if t[0] == p[0]: denom = denom + fl[t] if interactive: print numer / denom return numer / denom inh = {'VE':16,'GF':19,'VF':23,'GG' :2} all_di(inh) new_dict = {x:all_di(inh, x) for x in inh} print new_dict