Related
I'm a novice when it comes to recursion (and python, be kind haha), so I wanted to give it a go with a codewars problem (https://www.codewars.com/kata/541c8630095125aba6000c00/train/python)
I'm just super confused as to why the break gets ignored, and the recursion continues.
def digital_root(n):
x = list(str(n))
z = 0
while True:
for i in range(0, len(x)):
x[i] = int(x[i])
for i in x:
z = i + z
if z < 10:
break
elif z >= 10:
digital_root(z)
return z
print(digital_root(942))
After calling itself recursively, it's discarding the return value, so z and x remain unchanged. Change the recursive call to:
return digital_root(z)
That way the recursion will end. In fact, the while loop should never execute more than once, so you could just do:
def digital_root(n):
x = list(str(n))
z = 0
for i in range(0, len(x)):
x[i] = int(x[i])
for i in x:
z = i + z
if z < 10:
return z
return digital_root(z)
Or, if you'd rather eliminate the recursion entirely, all you really need is the following (which includes some additional simplifications):
def digital_root(n):
while n >= 10:
n = sum(int(d) for d in str(n))
return n
I have implemented solution of Longest Common Subsequence using Dynamic programming in python. For those who don't know LCS here's the link.
https://www.tutorialspoint.com/design_and_analysis_of_algorithms/design_and_analysis_of_algorithms_longest_common_subsequence.htm
My code is not returning the the most optimal answer. What is wrong in my logic ?
import enum
class LCS:
class Dir(enum.Enum):
up = 1
diagonal = 2
left = 3
none = 0
def LCS(self, x, y):
self.DP = {}
m = len(x) - 1
n = len(y) - 1
self.recursion(x, y, m, n)
print(self.DP)
self.printLCS(x, m, n)
def recursion(self, x, y, i, j):
if i == 0 or j == 0:
return [0, self.Dir.none]
else:
if (i, j) not in self.DP:
if x[i] == y[j]:
cost = self.recursion(x, y, i - 1, j - 1)[0] + 1
dir = self.Dir.diagonal
else:
first = self.recursion(x, y, i - 1, j)
second = self.recursion(x, y, i, j - 1)
if first[0] >= second[0]:
cost = first[0]
dir = self.Dir.up
else:
cost = second[0]
dir = self.Dir.left
self.DP[(i, j)] = [cost, dir]
return self.DP[(i, j)]
def printLCS(self, string, i, j):
if i == 0 or j == 0:
return
elif self.DP[(i, j)][1] == self.Dir.diagonal:
self.printLCS(string, i - 1, j - 1)
print(string[i], end="")
elif self.DP[(i, j)][1] == self.Dir.up:
self.printLCS(string, i - 1, j)
else:
self.printLCS(string, i, j - 1)
x = "BDCABA"
y = "ABCBDAB"
sol = LCS()
sol.LCS(x, y)
Expected = "BCBA", Actual = "DAB"
the problem is your base states.
the string in python is 0-base, cause of this the first character of string s is not s[1] its s[0] and you must end your recursion when you reach before first element not at first element.
just replace if i == 0 or j == 0: with if i == -1 or j == -1: in function printLCS and recursion then you will get output BDAB which is the one of correct answers.
I need forLoop1 to use y if z equals 1 else use x and same for forLoop2 but reversed
my code:
for z in range(3):
count=[0]*plys
for y in range(len(game)): #forLoop1
for x in range(len(game[y])): #forLoop2
for i in range(plys):
if game[y][x] == i+1:
count[i] += 1
for i in range(plys):
if count[i] >= 3:
print("Player " + str(i+1) + " is the winner")
count=[0]*plys
I tried something like this:
for y if z == 0 else x in range(len(game)):
and:
for (y if z == 0 else x) in range(len(game)):
But that didn't work
Any help would be greatly appreciated
and sorry if I'm bad at explaining it
The ... if ... else ... conditional expression produces an expression, you can't use it to man-handle the for loop index variable names like that.
But you can do this:
for z in range(3):
count=[0]*plys
for k1 in range(len(game)): #forLoop1
for k2 in range(len(game)): #forLoop2
y, x = (k1, k2) if z == 1 else (k2, k1)
for i in range(plys):
if game[y][x] == i+1:
count[i] += 1
for i in range(plys):
if count[i] >= 3:
print("Player " + str(i+1) + " is the winner")
count=[0]*plys
However, it might be clearer if you just use a full if... else block:
if z == 1:
y, x = k1, k2
else:
y, x = k2, k1
I recently asked this question and got the first answer. I'm trying to put this into python code. This is what I have, but I keep getting 0 as the answer.
def f(n, k, s):
ans = 0
for j in range(1, min({k,s}) + 1):
print j
if (n == 1):
if (k >= s):
ans = ans + 1
elif (k < s):
ans = ans + 0
elif (s > n):
ans = ans + 0
elif (n*k < s):
ans = ans + 0
else:
ans = ans + f(n-1,j,s-j)
return ans
print f(10, 12, 70)
What is wrong with my code? What do I need to change? I don't know what's wrong. Please help. Thanks!
Your code is way too complex. You can write an almost one-to-one transcription of the answer you got on math exchange:
def f(n, k, s):
if n == 1:
return int(k >= s)
# or: 1 if k >=s else 0
return sum(f(n-1, j, s-j) for j in range(1, min(k, s)+1))
# to make it faster:
#return sum(f(n-1, j, s-j) for j in range(1, min(k, s)+1) if n*k >= s)
The problem in your code is that you put the base-case checking inside the loop, when it should be outside:
def f(n, k, s):
ans = 0
if n == 1:
return int(k >= s)
for j in range(1, min({k,s}) + 1):
print j
if n*k >= s:
ans += f(n-1,j,s-j)
return ans
With both implementations I get 12660 as result for f(10, 12, 70).
I don't know why yours doesn't work, but here's an implementation that does, which IMO is MUCH more readable:
from itertools import permutations
def f(n, k, s):
if k > s:
k = s-1
count = 0
sum_perms = []
number_list = []
for i in range(1,k):
for j in range(1,k,i):
number_list.append(i)
for perm in permutations(number_list, n):
if sum(perm) == s and perm not in sum_perms:
sum_perms.append(perm[:])
count += 1
return sum_perms, count
It's a lot slower than the recursion technique though :-(
itertools is amazing.
In problem 4 from http://projecteuler.net/ it says:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 * 99.
Find the largest palindrome made from the product of two 3-digit numbers.
I have this code here
def isPalindrome(num):
return str(num) == str(num)[::-1]
def largest(bot, top):
for x in range(top, bot, -1):
for y in range(top,bot, -1):
if isPalindrome(x*y):
return x*y
print largest(100,999)
It should find the largest palindrome, it spits out 580085 which I believe to be correct, but project euler doesn't think so, do I have something wrong here?
When I revered the for loop I didn't think it through, I removed the thing that checks for the biggest, silly me. Heres the working code
def isPalindrome(num):
return str(num) == str(num)[::-1]
def largest(bot, top):
z = 0
for x in range(top, bot, -1):
for y in range(top,bot, -1):
if isPalindrome(x*y):
if x*y > z:
z = x*y
return z
print largest(100,999)
it spits out 906609
Iterating in reverse doesn't find the largest x*y, it finds the palindrome with the largest x. There's a larger answer than 580085; it has a smaller x but a larger y.
This would more efficiently be written as:
from itertools import product
def is_palindrome(num):
return str(num) == str(num)[::-1]
multiples = ( (a, b) for a, b in product(xrange(100,999), repeat=2) if is_palindrome(a*b) )
print max(multiples, key=lambda (a,b): a*b)
# (913, 993)
You'll find itertools and generators very useful if you're doing Euler in Python.
Not the most efficient answer but I do like that it's compact enough to fit on one line.
print max(i*j for i in xrange(1,1000) for j in xrange(1,1000) if str(i*j) == str(i*j)[::-1])
Tried making it more efficient, while keeping it legible:
def is_palindrome(num):
return str(num) == str(num)[::-1]
def fn(n):
max_palindrome = 1
for x in range(n,1,-1):
for y in range(n,x-1,-1):
if is_palindrome(x*y) and x*y > max_palindrome:
max_palindrome = x*y
elif x * y < max_palindrome:
break
return max_palindrome
print fn(999)
Here I added two 'break' to improve the speed of this program.
def is_palindrome(num):
return str(num) == str(num)[::-1]
def max_palindrome(n):
max_palindrome = 1
for i in range(10**n-1,10**(n-1)-1,-1):
for j in range(10**n-1,i-1,-1):
if is_palindrome(i*j) and i*j > max_palindrome:
max_palindrome = i * j
break
elif i*j < max_palindrome:
break
return max_palindrome
n=int(raw_input())
print max_palindrome(n)
Simple:
def is_pallindrome(n):
s = str(n)
for n in xrange(1, len(s)/2 + 1):
if s[n-1] != s[-n]:
return False
return True
largest = 0
for j in xrange(100, 1000):
for k in xrange(j, 1000):
if is_pallindrome(j*k):
if (j*k) > largest: largest = j*k
print largest
Each time it doesnot have to start from 999 as it is already found earlier.Below is a simple method using string function to find largest palindrome using three digit number
def palindrome(y):
z=str(y)
w=z[::-1]
if (w==z):
return 0
elif (w!=z):
return 1
h=[]
a=999
for i in range (999,0,-1):
for j in range (a,0,-1):
l=palindrome(i*j)
if (l==0):
h=h+[i*j]
a-=1
print h
max=h[0]
for i in range(0,len(h)):
if (h[i] > max):
max= h[i]
print "largest palindrome using multiple of three digit number=%d"%max
Here is my code to solve this problem.
lst = []
for i in range(100,1000):
for n in range(2,i) :
lst.append (i* n)
lst.append(i*i)
lst2=[]
for i in lst:
if str(i) == str(i)[::-1]:
lst2.append(i)
print max(lst2)
Here is my Python code:
max_pal = 0
for i in range(100,999):
for j in range(100,999):
mult = i * j
if str(mult) == str(mult)[::-1]: #Check if the number is palindrome
if mult > max_pal:
max_pal = mult
print (max_pal)
def div(n):
for i in range(999,99,-1):
if n%i == 0:
x = n/i
if x % 1 == 0:
x = n//i
if len(str(x)) == 3:
print(i)
return True
return False
def palindrome():
ans = []
for x in range(100*100,999*999+1):
s = str(x)
s = int (s[::-1])
if x - s == 0:
ans.append(x)
for x in range(len(ans)):
y = ans.pop()
if div(y):
return y
print(palindrome())
580085 = 995 X 583, where 906609 = 993 X 913.
Found it only by applying brute-forcing from top to bottom!
Here is the function I made in python to check if the product of 3 digit number is a palindrome
Function:
def is_palindrome(x):
i = 0
result = True
while i < int(len(str(x))/2):
j = i+1
if str(x)[i] == str(x)[-(j)]:
result = True
else:
result = False
break
i = i + 1
return result
Main:
max_pal = 0
for i in range (100,999):
for j in range (100,999):
x = i * j
if (is_palindrome(x)):
if x > max_pal:
max_pal = x
print(max_pal)
Here is my solution for that:
lst1 = [x for x in range(1000)]
palindrome = []
def reverse(x):
a = str(x)[::-1]
return int(a)
x = 0
while x < len(lst1):
for y in range(1000):
z = lst1[x] * y
if z == reverse(z):
palindrome.append(z)
x += 1
duppal = set(palindrome)
sortpal = sorted(duppal)
total = sortpal[-1]
print(sortpal)
print('Largest palindrome: ' + str(total))
ReThink: efficiency and performance
def palindrome(n):
maxNumberWithNDigits = int('9' * n) #find the max number with n digits
product = maxNumberWithNDigits * maxNumberWithNDigits
#Since we are looking the max, stop on the first match
while True:
if str(product) == str(product)[::-1]: break;
product-=1
return product
start=time.time()
palindrome(3)
end=time.time()-start
palindrome...: 997799, 0.000138998031616 secs