I came across this question as follows:
There are three integers a, b, c given in input. You have to convert the number a to b by performing the given operations:
Multiply a by c
Decrease a by 2.
Decrease a by 1.
You have to perform the above operations to convert the integer from a to b and find the minimum steps.
Note: You can perform the operations in any order.
I found this solution:
def rec(a,b,c):
if a>=b:
return ((a-b)//2+(a-b)%2)
if b%c==0:
return (1+rec(a,b//c,c))
else:
x=(b//c+1)*c;
return ((x-b)//2+(x-b)%2+rec(a,x,c))
a,b,c=map(int,input().split())
print(rec(a,b,c))
The first condition check is easily understandable that if (a>=b) then we decrement a in steps of 2 until we reach b and if there is a remainder "1" we add it to the steps to compute the final output.
In second and third condition checks it successfully performs the required operation using the concept of recursion, but why recursion is used? Is it possible to do it without recursion? What is the use of x in third condition?
You can add some kind of logging, at each moment there really is only one possible route:
def rec(a, b, c):
if a >= b:
# when a >= b, multiplying doesn't make sense,
# so subtract 2 as many times as needed
# then subtract 1 if the difference was odd
print(f"from {a}, subtract 2 for {(a - b) // 2} steps, subtract 1 for {(a - b) % 2} steps to get {b}" +
f" (this are {((a - b) // 2 + (a - b) % 2)} steps)")
return ((a - b) // 2 + (a - b) % 2)
if b % c == 0:
# we have a < b, we need to multiply at least once to get from b/c to b,
# we still need to go from a to b/c
print(f"first get {b // c}, then multiply by {c} to get {b}" +
f" (this is 1 step)")
return (1 + rec(a, b // c, c))
else:
# we have a < b and b isn't a multiple of c
# we need to get to a multiple of c that is larger then b, let x be this multiple
# we need to multiply at least once to get from x/c to x
# we will need subtractions of 2 and 1 to get from x to b
# we still need to go from a to x
x = (b // c + 1) * c
print(f"first get {x}, then subtract 2 for {(x - b) // 2} steps, subtract 1 for {(x - b) % 2} steps to get {b}" +
f" (this are {((x - b) // 2 + (x - b) % 2)} steps)")
return ((x - b) // 2 + (x - b) % 2 + rec(a, x, c))
a, b, c = map(int, input().split())
print("Total number of steps:", rec(a, b, c))
For example, for 4 29 5:
first get 30, then subtract 2 for 0 steps, subtract 1 for 1 steps to get 29 (this are 1 steps)
first get 6, then multiply by 5 to get 30 (this is 1 step)
first get 10, then subtract 2 for 2 steps, subtract 1 for 0 steps to get 6 (this are 2 steps)
first get 2, then multiply by 5 to get 10 (this is 1 step)
from 4, subtract 2 for 1 steps, subtract 1 for 0 steps to get 2 (this are 1 steps)
Total number of steps: 6
PS: As the function is written with tail recursion, it can easily be transformed to a loop. Instead of giving the variables new values by recursion, the new values can be assigned localy in the loop:
def rec(a, b, c):
result = 0
while a < b:
if b % c == 0:
result += 1
b //= c
else:
x = (b // c + 1) * c
result += (x - b) // 2 + (x - b) % 2
b = x
result += ((a - b) // 2 + (a - b) % 2)
return result
A benefit of the recursive code, is that it is easier to convert to write the output in the correct order:
def rec(a, b, c):
if a >= b:
steps2 = (a - b) // 2
steps1 = (a - b) % 2
if steps1 + steps2 > 0:
print(f"from {a}" +
(f", subtract 2 for {steps2} steps" if steps2 > 0 else "") +
(f", subtract 1" if steps1 > 0 else "") +
f" to get {b}" +
f" ({steps1 + steps2} steps)")
return steps1 + steps2
if b % c == 0:
prev_steps = rec(a, b // c, c)
print(f"from {b // c}, multiply by {c} to get {b}" +
f" (plus 1 step, totaling {1 + prev_steps} steps)")
return 1 + prev_steps
else:
x = (b // c + 1) * c
prev_steps = rec(a, x, c)
steps2 = (x - b) // 2
steps1 = (x - b) % 2
print(f"from {x}" +
(f", subtract 2 for {steps2} steps" if steps2 > 0 else "") +
(f", subtract 1" if steps1 > 0 else "") +
f" to get {b}" +
f" (plus {steps1 + steps2} steps, totaling {steps1 + steps2 + prev_steps} steps)")
return steps1 + steps2 + prev_steps
from 4, subtract 2 for 1 steps to get 2 (1 steps)
from 2, multiply by 5 to get 10 (plus 1 step, totaling 2 steps)
from 10, subtract 2 for 2 steps to get 6 (plus 2 steps, totaling 4 steps)
from 6, multiply by 5 to get 30 (plus 1 step, totaling 5 steps)
from 30, subtract 1 to get 29 (plus 1 steps, totaling 6 steps)
Related
A Pythagorean triplet is a set of three natural numbers, a < b < c,
for which,
a^2 + b^2 = c^2
For example, 3^2 + 4^2 = 9 + 16 = 25 = 5^2.
There exists exactly one Pythagorean triplet for which a + b + c =
1000. Find the product abc.
above is the question. when i run my code it works and runs how i expect it to, but the programme always finishes without finding an answer. any advice on how to improve my code would be appreciated.
for k in range (1,1000):
c = 1000 - k
for i in range (1,c):
b = c - i
c_sqr = c ** 2
b_sqr = b ** 2
a = c - b
a_sqr = a ** 2
if a_sqr + b_sqr == c_sqr:
if a + b + c == 1000:
product = a * b * c
print(f"{product} is the answer")
exit()
else:
print("Pythagorean triplet!")
else:
josephmama = 11
print("not a pythagorean triplet")
In your code c < 1000 and a + b == c are invariants. The sum (a + b + c) == 2 * c requires that the longest side(hypotenuse) of the right triangle to be as long as the sum of the other sides, and there's no such numbers that satisfy it and so the if body never executes.
for a in range(1, 1000):
for b in range(1, 1000):
c = 1000 - (a + b)
if (a ** 2 + b ** 2 == c ** 2):
print(a * b * c)
exit()
a is not always equal to c - b
by deriving b from c and a from c and b you are unnecessarily limiting the options of what b and a could be. Just loop through all combinations of a, b and c, add the constrains you have and you'll eventually get your triplet.
for a in range(1, 1000):
for b in range(1, 1000):
for c in range(1, 1000):
if a+b+c == 1000:
if a**2+b**2 == c**2:
if a < b:
if b < c:
print(f"My Triplet: a: {a}, b: {b}, c:{c}")
Here's a python code that prints the square matrix from interior to outer. How can I reverse to print from outer to interior clockwise
# Function to prints a N x N spiral matrix without using any extra space
# The matrix contains numbers from 1 to N x N
def printSpiralMatrix(N):
for i in range(N):
for j in range(N):
# x stores the layer in which (i, j)'th element lies
# find minimum of four inputs
x = min(min(i, j), min(N - 1 - i, N - 1 - j))
# print upper right half
if i <= j:
print((N - 2 * x) * (N - 2 * x) - (i - x) - (j - x), end='')
# print lower left half
else:
print((N - 2 * x - 2) * (N - 2 * x - 2) + (i - x) + (j - x), end='')
print('\t', end='')
print()
if __name__ == '__main__':
N = 4
printSpiralMatrix(N)
The output should be like that
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
Try with this:
def printSpiralMatrix(N):
for i in range(N):
for j in range(N):
# x stores the layer in which (i, j)'th element lies
# find minimum of four inputs
x = min(min(i, j), min(N - 1 - i, N - 1 - j))
# print upper right half
if i <= j:
print(abs((N - 2 * x) * (N - 2 * x) - (i - x) - (j - x) -(N**2 + 1)), end='')
# print lower left half
else:
print( abs((N - 2 * x - 2) * (N - 2 * x - 2) + (i - x) + (j - x) - (N**2 + 1)), end='')
print('\t', end='')
print()
printSpiralMatrix(4)
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
def generateMatrix(n):
if n<=0:
return []
matrix=[row[:] for row in [[0]*n]*n]
row_st=0
row_ed=n-1
col_st=0
col_ed=n-1
current=1
while (True):
if current>n*n:
break
for c in range (col_st, col_ed+1):
matrix[row_st][c]=current
current+=1
row_st+=1
for r in range (row_st, row_ed+1):
matrix[r][col_ed]=current
current+=1
col_ed-=1
for c in range (col_ed, col_st-1, -1):
matrix[row_ed][c]=current
current+=1
row_ed-=1
for r in range (row_ed, row_st-1, -1):
matrix[r][col_st]=current
current+=1
col_st+=1
return matrix
print(list(generateMatrix(3)))
Output
[[1, 2, 3], [8, 9, 4], [7, 6, 5]]
def sum(a):
if a==1:
s=1
else:
s=1+2*sum(a-1)
return s
function:calculate the sum of the sequence of number. Its common ratio is 2, last term is 2^( a-1) and first term is 1.
Why does it use s=1+2*sum(a-1) to implement the function?
def sum1(a):
if a==1:
s=1
else:
s=1+2*sum1(a-1)
return s
What this function does, let's take a=4.
(1) s = 1 + 2*sum1(4-1) = 1 + 2*sum1(3) = 1 + 2*s2
(2) s2 = 1 + 2*sum1(3-1) = 1 + 2*sum1(2) = 1 + 2*s3
(3) s3 = 1 + 2*sum(2-1) = 1 + 2*sum(1) = 1 + 2*s4 = 1+2 = 3
Going BackWard : (3 * 2 + 1 ) * 2 + 1 = (7) * 2 + 1 = 15
Do it for bigger numbers, you will notice that this is the formula of 2^a - 1.
Print 2^a and 2^a - 1
Difference: (4, 3)
Difference: (8, 7)
Difference: (16, 15)
Difference: (32, 31)
Difference: (64, 63)
Difference: (128, 127)
Difference: (256, 255)
#Zhongyi I'm understanding this question as asking "how does recursion work."
Recursion exists in Python, but I find it a little difficult to explain how it works in Python. Instead I'll show how this works in Racket (a Lisp dialect).
First, I'lll rewrite yoursum provided above into mysum:
def yoursum(a):
if a==1:
s=1
else:
s=1+2*yoursum(a-1)
return s
def mysum(a):
if a == 1:
return 1
return 1 + (2 * mysum(a - 1))
for i in range(1, 11):
print(mysum(i), yoursum(i))
They are functionally the same:
# Output
1 1
3 3
7 7
15 15
31 31
63 63
127 127
255 255
511 511
1023 1023
In Racket, mysum looks like this:
#lang racket
(define (mysum a)
(cond
((eqv? a 1) 1)
(else (+ 1 (* 2 (mysum (sub1 a)))))))
But we can use language features called quasiquoting and unquoting to show what the recursion is doing:
#lang racket
(define (mysum a)
(cond
((eqv? a 1) 1)
(else `(+ 1 (* 2 ,(mysum (sub1 a))))))) ; Notice the ` and ,
Here is what this does for several outputs:
> (mysum 1)
1
> (mysum 2)
'(+ 1 (* 2 1))
> (mysum 3)
'(+ 1 (* 2 (+ 1 (* 2 1))))
> (mysum 4)
'(+ 1 (* 2 (+ 1 (* 2 (+ 1 (* 2 1))))))
> (mysum 5)
'(+ 1 (* 2 (+ 1 (* 2 (+ 1 (* 2 (+ 1 (* 2 1))))))))
You can view the recursive step as substituting the expression (1 + 2 * rest-of-the-computation)
Please comment or ask for clarification if there are parts that still do not make sense.
Formula Explanation
1+2*(sumOf(n-1))
This is not a generic formula for Geometric Progression.
this formula is only valid for the case when ratio is 2 and first term is 1
So how it is working.
The Geometric Progression with first term = 1 and r = 2 will be
1,2,4,6,8,16,32,64
FACT 1
Here you can clearly see nth term is always equals to sumOf(n-1) terms + 1
Let declare an equation from fact 1
n = sumOf(n-1) + 1 =======> Eq1.
Let put our equation to test
put n = 2 in Eq1
2 = sumOf(2-1) + 1
we know that sumOf(1) is 1 then
2 = 2 ==> proved
so if n = sumOf(n-1)+1 then
FACT 2
Sum of n term is n term + sum(n-1) terms
Lets declare an Equation from FACT 2
sumOf(n) = sumOf(n-1) + n ==> eq2
let us put eq1 in eq2 i.e. n = sumOf(n-1) + 1
sumOf(n) = sumOf(n-1) + sumOf(n-1) + 1 ==> eq3
Simplifying
sumOf(n) = 2 * sumOf(n-1) + 1
Rearranging
sumOf(n) = 1 + 2 * sumOf(n-1) ==> final Equation
Now Code this equation
we know sumOf 1st term is alway 1 so, this is our base case.
def sumOf(a):
if a==1:
return 1
so now sum of first n terms will be 1 + 2 * sumOf(n-1) ==> From final Equation
put this equation in else part
def sumOf(a):
if a==1:
return 1
else:
return 1 + 2 * sumOf(a-1)
In the following code snippet I am finding the sum of digits of all odd number between the interval [a,b]
def SumOfDigits(a, b):
s = 0
if a%2 == 0:
a+=1
if b%2 == 0:
b-=1
for k in range(a,b+1,2):
s+= sum(int(i) for i in list(str(k)))
return s
Is there an efficient way to accomplish the same?
Any patterns, which is leading to a clear cut formula.
I did search in https://oeis.org
Avoid all the overhead of conversion to and from strings and work directly with the numbers themselves:
def SumOfDigits(a, b):
result = 0
for i in range(a + (not a % 2), b + 1, 2):
while i:
result += i % 10
i //= 10
return result
Of course there is a pattern. Let's look at the problem of summing up the digitsums of all – odd and even – numbers between a and b inclusively.
For example: 17 to 33
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
The middle section gives you the sum of all digits from 0 to 9 (45) plus ten times 2. The left section is 7 + 8 + 9 plus three times 1 and the right the sum of 0 + 1 + 2 + 3 plus four times 3.
The middle section can comprise several blocks of ten, for example if you calculate the range between 17 and 63, you get 40 times 45 plus ten simes the the digitsums from 2 to 5.
This gives you a recursive algorithm:
def ssum(n):
return n * (n + 1) // 2
def dsum(a, b):
res = 0
if a == b:
while a:
res += a % 10
a //= 10
elif a < b:
aa = a // 10
bb = b // 10
ra = a % 10
rb = b % 10
if aa == bb:
res += ssum(rb) - ssum(ra - 1)
res += (rb - ra + 1) * dsum(aa, bb)
else:
if ra > 0:
res += 45 - ssum(ra - 1)
res += (10 - ra) * dsum(aa, aa)
aa += 1
if rb < 9:
res += ssum(rb)
res += (rb + 1) * dsum(bb, bb)
bb -= 1
if aa <= bb:
res += 45 * (bb - aa + 1)
res += 10 * dsum(aa, bb)
return res
Now let's extend this to include only odd numbers. Adkust a so that it is even and b so that it is odd. Your sum of digit sums now runs over pairs of even and odd numbers, where even + 1 == odd. That means that the digitsum of the odd number id one more than the even number, because all except the last digits are the same and the last odd digit is one more than the even digit.
Therefore:
dsum(a, b) == oddsum + evensum
and:
oddsum - evensum == (b - a + 1) // 2
The function to sum the digitsums of all odd numbers is then:
def oddsum(a, b):
if a % 2: a -= 1
if b % 2 == 0: b -= 1
d = (b - a + 1) // 2
return (dsum(a, b) + d) // 2
When I looked at your comment about OEIS, I've noticed that the algorithm can probably be simplified by writing a function to sum the digits from all numbers from zero to n and then calculate the difference dsum(b) - dsum(a). There are probably more opportunities for optimisation.
I have two expressions:
a = 3 * b + c , with c = 1
b = (a - d) / 5 , with d = 1
I must calculate a in 1 starting with b = 1, then (with a just calculated) I must calculate b in 2.
if the subtraction of b in 1 and b in 2 is > 0,25
the loop continues calculating a in 1 again with the b value in 2 and so on,
otherwise it stops.
It needs two iterations and I think I must use the while loop but I can't write it down.
Especially I don't know how giving the instruction to take the b value calculated in 2 as the first step
of the following iteration.
It sounds like you mean this. Some kind of iterative function closing in on a value?
#!/usr/bin/env python3
c = 1
d = 1
b = 1
while True:
a = 3 * b + c
new_b = (a - d) / 5
if b - new_b <= 0.25:
break
b = new_b
print(a, new_b)
Roughly this:
b, c, d = [1]*3
while True:
a=3*b + c
b= (a - d)/5
if condition:
break
You just need to fill out condition