Finding common outputs of 3 functions - python

I have 3 functions.These are
A(n) = n(n+1)/2
B(n) = n(3n-1)/2
C(n) = n(2n-1)
Their first common output and indexes are:
A(285)=B(165)=C(143)=40755
I need second one,so I tried this:
def equation1(x):
return x*(x+1)/2
def equation2(x):
return x*((3*x)-1)/2
def equation3(x):
return x*((2*x)-1)
for i in range(144,30000):
x = equation3(i)
for a in range(i,2*i):
y = equation2(a)
if(x==y):
for b in range(a,2*a):
z = equation1(b)
if(x==y==z):
print("Term =" + str(x))
print("A" + str(b))
print("B" + str(a))
print("C" + str(i))
But it takes too much time to find it.How can I handle this in an easier way?

Since all three functions are increasing for positive values, you can write a loop that increases the number with the smallest value at each iteration:
a = b = c = 1
eq_a = equation1(a)
eq_b = equation2(b)
eq_c = equation3(c)
while True:
if eq_a == eq_b and eq_b == eq_c:
print("Found {}, {}, {}, result={}".format(a,b,c,eq_a))
if eq_a <= eq_b and eq_a <= eq_c:
a += 1
eq_a = equation1(a)
elif eq_b <= eq_a and eq_b <= eq_c:
b += 1
eq_b = equation2(b)
elif eq_c <= eq_a and eq_c <= eq_b:
c += 1
eq_c = equation3(c)
else:
print("Should never be here")
assert(False);
Test run:
Found 1, 1, 1, result=1
Found 285, 165, 143, result=40755
Found 55385, 31977, 27693, result=1533776805
Found 10744501, 6203341, 5372251, result=57722156241751

Related

dummy numbers generator in Python

With an = (an-2 + 1)×an-1 with a0 = 0 and a1 = 1 formula find dummy_numbers(max)
My code:
def dummy_numbers(nums):
binsize = (((nums - 2) +1) * (nums -1))
return map(lambda x: int(nums + binsize * x), range(nums))
for num in dummy_numbers(10):
print(num)
my code prints different result than I expected
Use an actual generator with yield to make this easier. The tricky part here is keeping track of an-1 and an-2 as you iterate. This can be achieve like so:
second_last, last = None, None
for current in range(10):
second_last, last = last, current
assert (second_last, last) == (8, 9)
You also need to hardcode in the constant value that get returned for 0 and 1:
def dummy_numbers(an):
if an == 0:
yield 0
elif an == 1:
yield 0
yield 1
else:
an_2, an_1 = None, None
for an_0 in dummy_numbers(an - 1):
an_2, an_1 = an_1, an_0
yield an_0
yield (an_2 + 1) * an_1
for num in dummy_numbers(10):
print(num)
Outputs:
0
1
1
2
4
12
60
780
47580
37159980
1768109008380
You could also make this non-recursive like so:
def dummy_numbers(an):
an_2, an_1 = None, None
for i in range(an):
if i == 0:
an_0 = 0
elif i == 1:
an_0 = 1
else:
an_0 = (an_2 + 1) * an_1
yield an_0
an_2, an_1 = an_1, an_0

How can i add a While loop to detect errors in the input in python

So, i am trying to write a code to not only do arithmetic equations, but also, give feedback if there is an error as well as give me 3 tries max. any advice?
arithmetic=input("Enter an arithmetic operation:")
arithmetic= arithmetic.replace(" ", "")
w=arithmetic.split('/')
x= arithmetic.split('-')
y=arithmetic.split('+')
z=arithmetic.split('*')
if ("+" in arithmetic):
a= int(y[0])
b= int(y[1])
sum = a + b
print("The result is = " + str(sum))
elif ("*" in arithmetic):
a= int(z[0])
b= int(z[1])
result = a * b
print("The result is = " + str(result))
elif ("/" in arithmetic):
a= int(w[0])
b= int(w[1])
result = a / b
result = round(result,3)
print("The result is = " + str(result))
elif ("-" in arithmetic) and (len(x)==3):
a= int(x[1])
b= int(x[2])
result = a + b
result = result * (-1)
print("The result is = " + str(result))
elif ("-" in arithmetic) and (len(x)==2):
a= int(x[0])
b= int(x[1])
result = a - b
print("The result is = " + str(result))
#tries = 0
#while(tries < 3):
# arithmetic=input("Enter an arithmetic operation:")
# match = arithmetic.find('+')
# print(match)
# if(match == -1):
# print ("Invalid")
# tries += 1
# else:
# tries= 3
I tried to add the while in the beginning. However, when i put an input such as 11 and 12 without the + sign, it just printed the input without giving me an error. why is that?
tries = 0
while tries < 3:
arithmetic = input("Enter an arithmetic operation:")
arithmetic = arithmetic.replace(" ", "")
w = arithmetic.split('/')
x = arithmetic.split('-')
y = arithmetic.split('+')
z = arithmetic.split('*')
try:
if ("+" in arithmetic):
a = int(y[0])
b = int(y[1])
sum = a + b
print("The result is = " + str(sum))
elif ("*" in arithmetic):
a = int(z[0])
b = int(z[1])
result = a * b
print("The result is = " + str(result))
elif ("/" in arithmetic):
a = int(w[0])
b = int(w[1])
result = a / b
result = round(result, 3)
print("The result is = " + str(result))
elif ("-" in arithmetic) and (len(x) == 3):
a = int(x[1])
b = int(x[2])
result = a + b
result = result * (-1)
print("The result is = " + str(result))
elif ("-" in arithmetic) and (len(x) == 2):
a = int(x[0])
b = int(x[1])
result = a - b
print("The result is = " + str(result))
else:
print("Invalid")
tries += 1
continue
break
except ValueError: # for case split not working good due cases like first input is a negative number
print("Invalid")
tries += 1
At the end of your if / else if chain, just add:
else:
print("invalid")
tries += 1
Replace everything you have inside your while loop currently with the uncommented code above it and that should work.

Fibonacci that takes a list of numbers and returns their fibonacci number

I am trying to implement a function that will print a number of fibonacci numbers. For example if my input was fibonacci([0,1,2,3], the output would be 0,1,1,2.
I am not sure how to proceed.
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n-2)
while True:
n.append(n)
print(fibonacci[5,10,11])
You can refactor your code a bit and get:
def fibonacci(lst):
def getTerm(n):
if n == 0:
return 0
elif n == 1:
return 1
return getTerm(n - 1) + getTerm(n-2)
return [getTerm(x) for x in lst]
Gives output:
>>> fibonacci([0,1,2,3])
[0, 1, 1, 2]
>>> fibonacci([5,10,11])
[5, 55, 89]
Avoiding redundant computations:
def fibonacci(indices):
fibs = {}
set_of_indices = set(indices)
f0 = fibs[0] = 0
f1 = fibs[1] = 1
for i in range(2,max(indices)+1):
f2 = f0+f1
if i in set_of_indices:
fibs[i] = f2
f0,f1=f1,f2
return [fibs[i] for i in indices]

how to fix this combination program using binomial factorial equation?

my answer for finding the number of combinations given drawing 3 cards out of 52 is off by a spot. Like 0 cards from 52 should = 1, 1 should = 52, 2 = 1326 and so on. but I have 0 = 1, 1 = 1, 2 = 52 and so on. What would I modify to reach the desired result? I think the error is in def factorial() but I can not seem to fix/ find the issue, no matter what I try.
def factorial(num):
i = 2
if num == 0:
num = 1
print(num)
elif num > 1:
for i in range(i, num):
num = num * i
return num
def combinations(n,r):
l = n-r
nn = factorial(n)
rn = factorial(r)
ln = factorial(l)
result = nn / (rn * ln)
print(result)
return result
def main():
h = 52
a = 0
while a<4:
combinations(h,a)
a = a + 1
You're printing extra stuff in factorial which may lead to the confusion. I suggest you print out your final result with comparison to your a variable at the end of the combinations function like so:
print("For a=" + str(r) + ", result=" + str(result))
Here is the overall edited code:
def factorial(num):
if num == 0:
num = 1
elif num > 1:
for i in range(2, num): # Setting i=2 at the start is redundant
num = num * i
return num
def combinations(n,r):
l = n-r
nn = factorial(n)
rn = factorial(r)
ln = factorial(l)
result = nn / (rn*ln)
print("For a=" + str(r) + ", result=" + str(result))
return
h = 52
a = 0
while a<4:
combinations(h,a)
a = a + 1

Implementing Knuth-Morris-Pratt (KMP) algorithm for string matching with Python

I am following Cormen Leiserson Rivest Stein (clrs) book and came across "kmp algorithm" for string matching. I implemented it using Python (as-is).
However, it doesn't seem to work for some reason. where is my fault?
The code is given below:
def kmp_matcher(t,p):
n=len(t)
m=len(p)
# pi=[0]*n;
pi = compute_prefix_function(p)
q=-1
for i in range(n):
while(q>0 and p[q]!=t[i]):
q=pi[q]
if(p[q]==t[i]):
q=q+1
if(q==m):
print "pattern occurs with shift "+str(i-m)
q=pi[q]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
pi[1]=0
k=0
for q in range(2,m):
while(k>0 and p[k]!=p[q]):
k=pi[k]
if(p[k]==p[q]):
k=k+1
pi[q]=k
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t,p)
This is a class I wrote based on CLRs KMP algorithm, which contains what you are after. Note that only DNA "characters" are accepted here.
class KmpMatcher(object):
def __init__(self, pattern, string, stringName):
self.motif = pattern.upper()
self.seq = string.upper()
self.header = stringName
self.prefix = []
self.validBases = ['A', 'T', 'G', 'C', 'N']
#Matches the motif pattern against itself.
def computePrefix(self):
#Initialize prefix array
self.fillPrefixList()
k = 0
for pos in range(1, len(self.motif)):
#Check valid nt
if(self.motif[pos] not in self.validBases):
self.invalidMotif()
#Unique base in motif
while(k > 0 and self.motif[k] != self.motif[pos]):
k = self.prefix[k]
#repeat in motif
if(self.motif[k] == self.motif[pos]):
k += 1
self.prefix[pos] = k
#Initialize the prefix list and set first element to 0
def fillPrefixList(self):
self.prefix = [None] * len(self.motif)
self.prefix[0] = 0
#An implementation of the Knuth-Morris-Pratt algorithm for linear time string matching
def kmpSearch(self):
#Compute prefix array
self.computePrefix()
#Number of characters matched
match = 0
found = False
for pos in range(0, len(self.seq)):
#Check valid nt
if(self.seq[pos] not in self.validBases):
self.invalidSequence()
#Next character is not a match
while(match > 0 and self.motif[match] != self.seq[pos]):
match = self.prefix[match-1]
#A character match has been found
if(self.motif[match] == self.seq[pos]):
match += 1
#Motif found
if(match == len(self.motif)):
print(self.header)
print("Match found at position: " + str(pos-match+2) + ':' + str(pos+1))
found = True
match = self.prefix[match-1]
if(found == False):
print("Sorry '" + self.motif + "'" + " was not found in " + str(self.header))
#An invalid character in the motif message to the user
def invalidMotif(self):
print("Error: motif contains invalid DNA nucleotides")
exit()
#An invalid character in the sequence message to the user
def invalidSequence(self):
print("Error: " + str(self.header) + "sequence contains invalid DNA nucleotides")
exit()
You might want to try out my code:
def recursive_find_match(i, j, pattern, pattern_track):
if pattern[i] == pattern[j]:
pattern_track.append(i+1)
return {"append":pattern_track, "i": i+1, "j": j+1}
elif pattern[i] != pattern[j] and i == 0:
pattern_track.append(i)
return {"append":pattern_track, "i": i, "j": j+1}
else:
i = pattern_track[i-1]
return recursive_find_match(i, j, pattern, pattern_track)
def kmp(str_, pattern):
len_str = len(str_)
len_pattern = len(pattern)
pattern_track = []
if len_pattern == 0:
return
elif len_pattern == 1:
pattern_track = [0]
else:
pattern_track = [0]
i = 0
j = 1
while j < len_pattern:
data = recursive_find_match(i, j, pattern, pattern_track)
i = data["i"]
j = data["j"]
pattern_track = data["append"]
index_str = 0
index_pattern = 0
match_from = -1
while index_str < len_str:
if index_pattern == len_pattern:
break
if str_[index_str] == pattern[index_pattern]:
if index_pattern == 0:
match_from = index_str
index_pattern += 1
index_str += 1
else:
if index_pattern == 0:
index_str += 1
else:
index_pattern = pattern_track[index_pattern-1]
match_from = index_str - index_pattern
Try this:
def kmp_matcher(t, d):
n=len(t)
m=len(d)
pi = compute_prefix_function(d)
q = 0
i = 0
while i < n:
if d[q]==t[i]:
q=q+1
i = i + 1
else:
if q != 0:
q = pi[q-1]
else:
i = i + 1
if q == m:
print "pattern occurs with shift "+str(i-q)
q = pi[q-1]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
k=1
l = 0
while k < m:
if p[k] <= p[l]:
l = l + 1
pi[k] = l
k = k + 1
else:
if l != 0:
l = pi[l-1]
else:
pi[k] = 0
k = k + 1
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t, p)
KMP stands for Knuth-Morris-Pratt it is a linear time string-matching algorithm.
Note that in python, the string is ZERO BASED, (while in the book the string starts with index 1).
So we can workaround this by inserting an empty space at the beginning of both strings.
This causes four facts:
The len of both text and pattern is augmented by 1, so in the loop range, we do NOT have to insert the +1 to the right interval. (note that in python the last step is excluded);
To avoid accesses out of range, you have to check the values of k+1 and q+1 BEFORE to give them as index to arrays;
Since the length of m is augmented by 1, in kmp_matcher, before to print the response, you have to check this instead: q==m-1;
For the same reason, to calculate the correct shift you have to compute this instead: i-(m-1)
so the correct code, based on your original question, and considering the starting code from Cormen, as you have requested, would be the following:
(note : I have inserted a matching pattern inside, and some debug text that helped me to find logical errors):
def compute_prefix_function(P):
m = len(P)
pi = [None] * m
pi[1] = 0
k = 0
for q in range(2, m):
print ("q=", q, "\n")
print ("k=", k, "\n")
if ((k+1) < m):
while (k > 0 and P[k+1] != P[q]):
print ("entered while: \n")
print ("k: ", k, "\tP[k+1]: ", P[k+1], "\tq: ", q, "\tP[q]: ", P[q])
k = pi[k]
if P[k+1] == P[q]:
k = k+1
print ("Entered if: \n")
print ("k: ", k, "\tP[k]: ", P[k], "\tq: ", q, "\tP[q]: ", P[q])
pi[q] = k
print ("Outside while or if: \n")
print ("pi[", q, "] = ", k, "\n")
print ("---next---")
print ("---end for---")
return pi
def kmp_matcher(T, P):
n = len(T)
m = len(P)
pi = compute_prefix_function(P)
q = 0
for i in range(1, n):
print ("i=", i, "\n")
print ("q=", q, "\n")
print ("m=", m, "\n")
if ((q+1) < m):
while (q > 0 and P[q+1] != T[i]):
q = pi[q]
if P[q+1] == T[i]:
q = q+1
if q == m-1:
print ("Pattern occurs with shift", i-(m-1))
q = pi[q]
print("---next---")
print("---end for---")
txt = " bacbababaabcbab"
ptn = " ababaab"
kmp_matcher(txt, ptn)
(so this would be the correct accepted answer...)
hope that it helps.

Categories

Resources