how to fix this combination program using binomial factorial equation? - python

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

Related

Syntax error in python code to find Prime-factors. Id appreciate if someone could help me

I have been getting a syntax error with code which does prime-factorization
The is this Code
from sys import argv
from os import system, get_terminal_size
from math import sqrt
number = int(argv[1])
width = get_terminal_size().columns
prime_numbers = []
prime_factors = []
_ = system('clear')
print()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
if is_prime(number):
print(f"It is a prime number \nIts only factors are 1 and itself \n1, {number}")
exit()
x = len(str(number))
for i in range(2, int(sqrt(number))):
if is_prime(i):
prime_numbers.append(i)
#print(f"found ")
#print(prime_numbers)
i = 0
while True:
if (number % prime_numbers[i] != 0):
i += 1
continue
prime_factors.append(prime_numbers[i])
print("%2d | %3d".center(width) % (prime_numbers[i], number))
print("_________".center(width))
number /= prime_numbers[i]
if number == 1:
break
print("1".center(width))
print("Answer ")
i = len(prime_factors)
j = 1
for k in prime_factors:
if j == i:
print(k)
break
print(f"{k}", end=" X ")
j += 1
This works for small numbers , less than 4 or 5 digits but gives an index error for bigger ones.
If I remove the sqrt function on line 24 it starts taking too long.
The errors look like this
Traceback (most recent call last):
File "prime-factor.py", line 33, in <module>
if (number % prime_numbers[i] != 0):
IndexError: list index out of range
real 0m0.049s
user 0m0.030s
sys 0m0.014s
(base) Souravs-MacBook-Pro-5:Fun-Math-Algorithms aahaans$ time python3 prime-factor.py 145647
I am unable to resolve this issue, Id appreciate it if you could help me.
No need to rebuild what's already available primePy
from primePy import primes
primes.factors(101463649)
output
[7, 23, 73, 89, 97]
There are two basic issues with the code. One with the for loop for prime numbers, you have to check until int(sqrt(number))+1. And, in the while loop after that, you have to break when the number is below sqrt of the original number, for which another variable should be used. The corrected code is:
from sys import argv
from os import system, get_terminal_size
from math import sqrt
number = int(argv[1])
width = get_terminal_size().columns
prime_numbers = []
prime_factors = []
_ = system('clear')
print()
def is_prime(n):
for i in range(2, n):
if n % i == 0:
return False
return True
if is_prime(number):
print(f"It is a prime number \nIts only factors are 1 and itself \n1, {number}")
exit()
x = len(str(number))
limit = int(sqrt(number))
for i in range(2, limit+1):
if is_prime(i):
prime_numbers.append(i)
i = 0
while True:
if i == len(prime_numbers)-1:
# prime_factors.append(int(number))
break
if (number % prime_numbers[i] != 0):
i += 1
continue
prime_factors.append(prime_numbers[i])
print("%2d | %3d".center(width) % (prime_numbers[i], number))
print("_________".center(width))
number /= prime_numbers[i]
prime_factors.append(int(number))
print("%2d | %3d".center(width) % (number, number))
print("_________".center(width))
print("1".center(width))
print("Answer ")
i = len(prime_factors)
j = 1
for k in prime_factors:
if j == i:
print(k)
break
print(f"{k}", end=" X ")
j += 1
If my explanation wasn't clear, look at the changes in the code.
I wrote a small number factorization engine that can factor numbers.
import math
def LLL(N):
p = 1<<N.bit_length()-1
if N == 2:
return 2
if N == 3:
return 3
s = 4
M = pow(p, 2) - 1
for x in range (1, 100000):
s = (((s * N ) - 2 )) % M
xx = [math.gcd(s, N)] + [math.gcd(s*p+x,N) for x in range(7)] + [math.gcd(s*p-x,N) for x in range(1,7)]
try:
prime = min(list(filter(lambda x: x not in set([1]),xx)))
except:
prime = 1
if prime == 1:
continue
else:
break
#print (s, x, prime, xx)
return prime
Factor:
In [219]: LLL(10142789312725007)
Out[219]: 100711423
from https://stackoverflow.com/questions/4078902/cracking-short-rsa-keys
I also made Alpertons ECM SIQs engine work in python if you want factorization at that (over 60 digits level): https://github.com/oppressionslayer/primalitytest

Hash table problem for education perposes

The problem is this:
It is required to create and use the hash table structure in a problem
large number of keys.
Here are the steps:
Creating one million (1,000,000) visits to a department store
and Credit Card Payment.
From the very large number of different cards, a relatively small subset is created
as follows. Credit cards for visits will have
sixteen (16) specific fixed digits eg 1234567890123456,
but in four (4) of the sixteen (16) random positions they will also have
four characters: X, Y, Z, W in random order.
eg 12Y45W789012Z4X6
In the other places the prices are the initial ones.
I have written the codes. Is is supposed to run super fast but it runs super slowly and I don't know why... Currently, I am running my code for 10,000 cards. Could you help me? Please excuse my poor english...
The code is bellow:
import string
import random
import time
random.seed(1059442)
global max_load_factor
max_load_factor = 0.6
def printGreaterThan2(num):
while True:
if num % 2 == 1:
isPrime = True
for x in range(3,int(num**0.5),2):
if num % x == 0:
isPrime = False
break
if isPrime:
return num
num += 1
N = printGreaterThan2(1000)
arr = [ [] for _ in range(N)]
arr = [ None for _ in range(N)]
def CreatNewItem():
letters = "WXZY"
days = ["Mon", "Tue", "Wed" , "Thu" , "Fri", "Sat"]
s = ''
count = 0
num = ['1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6']
list_a = []
while(count!=4):
a = random.randint(0,15)
b = random.choice(letters)
if b not in num and a not in list_a:
num[a] = b
count = count + 1
list_a.append(a)
s = ''.join(num)
d = random.randint(0,5)
day = days[d]
money = random.randint(10,100)
a = [s,day,money]
return a
def hash(key, tablesize):
sum = 0
for pos in range(len(key)):
sum = sum + ord(key[pos])
hash = sum % tablesize
return hash
#--------------------------------------
def rehash(oldhash , tablesize):
rehash = ( oldhash + 1 ) % tablesize
return rehash
#--------------------------------------
def put2 (arr,a,N,lenght,collitions):
if float(lenght)/float(N) >= max_load_factor:
(arr,N,collitions) = Resize(arr,N,lenght,collitions)
key = a[0]
i = hash(key,N)
j =0
while (True):
if arr[i] is None:
arr[i] = a
lenght = lenght + 1
break
elif arr[i][0] == key:
arr[i][2] = arr[i][2] + a[2]
arr[i][1] = arr[i][1] + a[1]
break
else:
if j == 0 :
collitions = collitions +1
j = 1
i = rehash(i,N)
return (lenght,N,arr,collitions )
#----------------------------------------
def Resize(arr,N,lenght,collitions):
print("resize")
N = printGreaterThan2(2*N)
collitions = 0
arr2 = [ [] for _ in range(N)]
arr2 = [ None for _ in range(N)]
for p in arr:
if p is not None:
(lenght,N,arr2,collitions)=put2(arr2,p,N,lenght,collitions)
return (arr2,N,collitions)
#-----------------------------------------
l = 0
cards = []
collitions = 0
t0 = time.time()
i=0
while i!=10000:
b = CreatNewItem()
(l,N,arr,collitions) = put2(arr,b,N,l,collitions)
i=i+1
t1 = time.time() - t0
print('\ntime is {:0.20f}'.format(t1))

Convert between str and int without using built-in typecasting

NB: You may not use built-in typecasting: code this yourself.
def str2int(s):
result = 0
if s[0] == '-':
sign = -1
i = 1
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
result = sign * result
return result
else:
i = 0
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
return result
NB: You may not use built-in str() or string template. Code this yourself.
def int2str(i):
strng = ""
if i > 0:
while i != 0:
num = i % 10
strng += chr(48+num)
i = i / 10
return strng[::-1]
else:
while i != 0:
num = abs(i) % 10
strng += chr(48+num)
i = abs(i) / 10
return '-' + strng[::-1]
I am a newbie and I have to write code based on basic. I write these function by myself but these look weird. Can you help me to improve code? Thank you
This maybe a better question for https://codereview.stackexchange.com/.
Not withstanding there is no error checking, one obvious comment is you have common code that can be factored out. Only capture in the if, else what is unique rather than repeat the while loop:
def str2int(s):
if s[0] == '-':
sign = -1
i = 1
else:
sign = 1
i = 0
result = 0
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
return sign * result
It is generally considered better form in python to iterate over list rather than indices:
def str2int(s):
sign = 1
if s[0] == '-':
sign = -1
s = s[1:]
result = 0
for c in s:
num = ord(c) - ord('0')
result = result * 10 + num
return sign * result
These last lines are equivalent to a standard map and reduce (reduce is in functools for py3). Though some would argue against it:
from functools import reduce # Py3
def str2int(s):
sign = 1
if s[0] == '-':
sign = -1
s = s[1:]
return sign * reduce(lambda x,y: x*10+y, map(lambda c: ord(c) - ord('0'), s))
There are similar opportunities to do the same for int2str().

Python does not start for loop

old = [[0 for x in range(3)] for y in range(10)]
count =0
# check if the number has non-repeating digits
def different(number):
digit_list = [0] * 4
i = 0
while i:
digit_list[i] = number%10
number /= 10
i += 1
for x in range(0,3):
for y in range(x+1,3):
if digit_list[x] == digit_list[y]:
return False
return True
# save the tried numbers, plus and minus values
# for prediction of the next number
def save(number,plus,minus):
global count
old[count][0] = number
old[count][1] = plus
old[count][2] = minus
count += 1
return
# compare for plus values
def get_plus(number1,number2):
ret_value = 0
for x in range(0, 3):
if number1 % 10 == number2 % 10:
ret_value += 1
number1 /= 10
number2 /= 10
return ret_value
# compare for minus values
def get_minus(number1,number2):
temp = [[0]*4 for i in range(2)]
ret_value = 0
for x in range(0,3):
temp[0][x] = number1 % 10
temp[0][x] = number2 % 10
number1 /= 10
number2 /= 10
for x in range(0,3):
for y in range(0,3):
if x != y:
if temp[0][x] == temp[1][y]:
ret_value += 1
return ret_value
# compare the number to be asked with the numbers in the array
def control(number):
for x in range(0,count-1):
if get_plus(old[x][0],number) != old[x][1]:
return False
if get_minus(old[x][0],number) != old[x][2]:
return False
return True
def main():
flag = False
print('1023 ??')
plus = input('plus ?')
minus = input('minus ?')
save(1023, plus, minus)
print('4567 ??')
plus = input('plus ?')
minus = input('minus ?')
save(4567, plus, minus)
for i in range(1024, 9876):
if different(i):
if control(i):
print(i + ' ??')
plus = input('plus ?')
minus = input('minus ?')
save(i, plus, minus)
if plus == 4 and minus == 0:
print('I WON !!!')
flag = True
break
if not flag:
print('False')
return
main()
I am trying to make an AI for mindgame in python. But in this function it doesn't even start the for loop. Can anyone know why ?
The while loop in your different() function does nothing as while(0) will prevent the loop from running. Even if that would run, your different() function will always return false. At least in the last loop it will compare digit_list[3] == digit_list[3] as both loop range until 3. This is always true and the function will return false. Thus the code within your main loop will never be entered.
def different(number):
digit_list = [0] * 4
i = 0
while i:
digit_list[i] = number%10
number /= 10
i += 1
for x in range(0,3):
for y in range(x+1,3):
if digit_list[x] == digit_list[y]:
return False
return True
Try this one:
import random
def different(num):
digits = []
while num >= 1:
cur = num%10
if cur in digits:
return False
digits.append(cur)
num = (num - cur) / 10
return True
for i in range(0, 10000):
rand = random.randrange(1000, 10000)
if not different(rand):
print(rand)

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