Value Replacement Recursion in Python - python

Hi I have a question with regards to python programming for my assignment
The task is to replace the occurrence of a number in a given value in a recursive manner, and the final output must be in integer
i.e. digit_swap(521, 1, 3) --> 523 where 1 is swapped out for 3
Below is my code and it works well for s = 0 - 9 if the final answer is outputted as string
def digit_swap(n, d, s):
result = ""
if len(str(n)) == 1:
if str(n) == str(d):
return str(s)
else:
return str(n)
elif str(n)[0] == str(d):
result = result + str(s) + str(digit_swap(str(n)[1:], d, s))
return result
else:
result = result + str(n)[0] + str(digit_swap(str(n)[1:], d, s))
return result
However, I have trouble making the final output as Integer
The code breaks down when s = 0
i.e. digit_swap(65132, 1, 0) --> 6532 instead of 65032
Is there any fix to my code?
def digit_swap(n, d, s):
result = ""
if len(str(n)) == 1:
if str(n) == str(d):
return str(s)
else:
return str(n)
elif str(n)[0] == str(d):
result = result + str(s) + str(digit_swap(str(n)[1:], d, s))
return int(result) # Changes
else:
result = result + str(n)[0] + str(digit_swap(str(n)[1:], d, s))
return int(result) # Changes

Conversion to string is unnecessary, this can be implemented much easier
def digit_swap(n, d, s):
if n == 0:
return 0
lower_n = (s if (n % 10) == d else (n % 10))
higher_n = digit_swap(n // 10, d, s) * 10
return higher_n + lower_n
assert digit_swap(521, 1, 3) == 523
assert digit_swap(65132, 1, 0) == 65032

do not return int from method, instead convert it to int from where you are calling method. Problem lies where your code trying to convert string to int return int(result).
So if result is 03 then function will return int('03') i.e 3.
call your method like this
print int(digit_swap(65132, 1, 0)) so you will get integer at the end.

For example int(00) is casted to 0. Therefore a zero is discarded. I suggest not to cast, instead leave it as a string. If you have to give back an int, you should not cast until you return the number. However, you still discard 0s at the beginning. So all in all, I would suggest just return strings instead of ints:
return str(result) # instead of return int(result)
And call it:
int(digit_swap(n,d,s))

Related

Python: TypeError while adding

I'm getting an error when trying to do these functions. I know you cannot add a string and integer, but I'm having trouble finding a way around this error for the following two functions.
TypeError: can only concatenate str (not "int") to str
def basetobase(B1,B2,s_in_B1):
#docstring here
pass
decimal = int(s_in_B1, B1)
if decimal == 0:
return '0'
result = ''
while decimal > 0:
remainder = decimal % B2
decimal = decimal // B2
result = str(remainder) + decimal
return result
def numtobase( N, B ):
#docstring here
pass
final = ""
if N == 0:
return result
while N > 0:
remainder = N % B
result = str(remainder) + (N // B)
return result
while len(result) % 8 != 0:
result = '0' + result
return result
I've tried switching both to strings, but it does not work and gives me another error.

function that prints counding down numbers and up but in a pattern

I already know how to count down and up using reccurssive function but I cant figure out how to define another function to have spaces in a pattern like this:
Desired output
My code for counting down and up:
def f(n):
if n==0:
print (n)
return
print (n)
f(n-1)
print (n)
a = 5 #you can take any value, it will be actually taken from the user
def f(n):
global a
if n == 0:
print(' '*a + str(n))
return
print(' '*(a-n), + str(n))
f(n-1)
print(' '*(a-n), + str(n))
a = int(input())
f(a)
I am posting this to contrast the other answers provided here -
def f(n, s = ""):
if n <= 0:
print(s, n)
else:
print(s, n)
f(n - 1, s + " ")
print(s, n)
f(5)
5
4
3
2
1
0
1
2
3
4
5
The program could be further simplified, if desired -
def f(n, s = ""):
print(s, n)
if n > 0:
f(n - 1, s + " ")
print(s, n)
f(5)
Default parameter s could be an integer instead of a string, if desired -
def f(n, s = 0):
print(" "*s, n)
if n > 0:
f(n - 1, s + 1)
print(" "*s, n)
f(5)
Output is the same.
print adds a space between the printed arguments. To remove this, we can print a single formatted value -
def f(n, s = ""):
print(s + str(n)) # <- single value
if n > 0:
f(n - 1, s + " ")
print(s + str(n)) # <- single value
Or you can use a formatted string literal -
def f(n, s = ""):
print(f"{s}{n}") # <- formatted string
if n > 0:
f(n - 1, s + " ")
print(f"{s}{n}") # <- formatted string
This is probably not exactly what you need. But it gives you an idea :)
As you can see it is based on #Samudra Ganguly's answer
def f(n,x):
if n < 0:
return
p(n,x-n)
f(n-1,x)
if n !=0:
p(n,x-n)
def p(m,x):
print(" ", end = "")
if x>0:
p(m,x-1)
else:
print(m, end = "\n")
f(8,8)
Also you can change the function like this:
k=4;
def f(n):
if n < 0:
return
p(n,k-n)
f(n-1)
if n !=0:
p(n,k-n)
def p(m,x):
print(" ", end = "")
if x>0:
p(m,x-1)
else:
print(m, end = "\n")
f(k)

Generating pattern based on odd and even integers

I need help with converting my iterative code to recursive.
def pattern(int):
if int == 0:
return ''
else:
result = '*-'
for i in range(int-1):
if i%2 != 0:
result += '*-'
elif i % 2 == 0:
result += '*--'
return result
Above is the code I wrote to convert an integer into repetitive patterns. For int%2 != 0, it prints '*-' , and for int%2 == 0, it prints '*--'.
I have been stucked with converting the above to recursive. I understand the base case is '*-' with the terminating condition of int == 1. I should then concatenate the base case with pattern(int-1) recursively. Can anyone advise me?
IIUC, Use:
def pattern(n):
if n == 1: # Base case
return "*-"
if n % 2 == 0:
return pattern(n - 1) + "*--"
else:
return pattern(n - 1) + "*-"
Calling the function:
print(pattern(10)) # builds the pattern corrensponding to integers from 1,2...10.
This prints:
*-*--*-*--*-*--*-*--*-*--

How to write a program to get all methods to get 2016 using numbers from 9 to 1?

You can add any operator(including parentheses and + - * / ** ) between 9 8 7 6 5 4 3 2 1.
For example,
98*76-5432*1=2016
9*8*7*(6+5-4-3)*(2-1)=2016
I wrote a programme like this
from __future__ import division
s = ['+','-','*','/','','(',')']
def calc(s):
a=s.split()
return eval(''.join(a))
a=['','9','','8','','7','','6','','5','','4','','3','','2','','1.','']
def test(tmp):
if tmp == 20:
try:
z = eval(''.join(a))
if z == 2016:
print ''.join(a)
except:
pass
return
for i in s:
#print a
a[tmp] = i
test(tmp+2)
for j in s:
a[0] = j
test(2)
But it is not right, because there can be multiple operators exist between numbers.
There's a well known trick to questions that involve constructing arithmetic expressions with brackets: often it's easier to use reverse polish notation instead.
Here's code that does this.
# Compute "a op b", returning None if the result
# is no good (eg: 9/0 or too big).
def do_op(a, op, b):
if op == '+':
return a + b
if op == '-':
return a - b
if op == '*':
return a * b
if op == '/':
if b == 0 or a % b != 0:
return None
return a // b
if op == '**':
# Disallow arguments that would result
# in fractions or huge numbers, being careful
# to allow valid results.
if a == 1:
return a
if a == -1:
return -1 if b % 2 else 1
if a == 0 and b == 0:
return None
if b < 0 or b > 20 or a > 10000 or a < -10000:
return None
return a ** b
assert False
# Generates expressions that result in the given target.
# ops is the a record of the operations applied so far,
# stack is the evaluation stack, and num is the first
# digit that we've not pushed yet.
def sums(ops, stack, num, target):
if not num and len(stack) == 1:
if stack[0] == target:
yield ops
return
# If num is 7, say, try pushing 7, 76, 765, 7654, ..., 7654321.
k = num
for i in xrange(num, 0, -1):
for s in sums(ops + [k], stack + [k], i-1, target):
yield s
k = 10 * k + (i - 1)
# If we've less that 2 things on the stack, we can't apply
# any operations.
if len(stack) < 2:
return
# Try each of the possible ops in turn.
for op in ['+', '-', '*', '/', '**']:
result = do_op(stack[-2], op, stack[-1])
if result is None:
continue
for s in sums(ops + [op], stack[:-2] + [result], num, target):
yield s
# Convert a list of operations that represent an expression in RPN
# into infix notation. Every operation is bracketed, even when
# that's redundant.
def to_infix(ops):
stack = []
for p in ops:
if isinstance(p, int):
stack = stack + [p]
else:
stack = stack[:-2] + ['(%s%s%s)' % (stack[-2], p, stack[-1])]
assert len(stack) == 1
return stack[0]
# Starting with an empty stack (and no operations), with 9 as the first
# unused digit, generate all expressions that evaluate to 2016.
for s in sums([], [], 9, 2016):
print to_infix(s)
It takes a few minutes to run, but there's a lot (more than 25000) of valid expressions that evaluate to 2016.
My favorite is (((98*76)-5432)*1).

Calculator Subtraction leads to infinite loop

I'm working on a calculator which will accept input from the user.
It has to solve expressions such as:
1+38*(!2)-5%37
I have been working on the addition and the subtraction but I got into a problem.
I have a loop that is looking for "+" or "-" symbols.
For the "+" it works, but for the "-", whenever I'm solving an expression like
1-38
It gets me into an infinite loop since the result of that expression is
-37
and the loop keeps recognizing the "-" symbol as a subtraction, but as negative 37.
How do I solve this issue?
def symbols_exist(exp, symbols_list):
""" Gets an expression string and a symbols list and returns true if any symbol
exists in the expression, else returns false. """
for s in symbols_list:
if s in exp:
return True
return False
def BinaryOperation(exp, idx):
""" Gets an expression and an index of an operator and returns a tuple with (first_value, operator, second_value). """
first_value = 0
second_value = 0
#Get first value
idx2 = idx -1
while (idx2 > 0) and (exp[idx2] in string.digits):
idx2 -=1
first_value = exp[idx2:idx]
#Get second value
idx2 = idx +1
while (idx2 < len(exp)) and (exp[idx2] in string.digits):
idx2 += 1
second_value = exp[idx+1:idx2]
return (first_value, exp[idx], second_value)
def solve(exp):
if not symbols_exist(exp, all_symbols):
return exp
idx = 0
while idx < len(exp):
if exp[idx] in string.digits:
#Digit
idx +=1
elif exp[idx] in ("+", "-"):
#Addition and Subtraction
sub_exp = BinaryOperation(exp, idx)
if sub_exp[1] == "+":
value = int(sub_exp[0]) + int(sub_exp[2])
else:
value = int(sub_exp[0]) - int(sub_exp[2])
value = str(value)
exp = exp.replace(''.join(sub_exp), value)
print exp
return solve(exp)
A possible solution that combines the three functions in the original example. (EDIT: just realised the original answer I posted could be simplified quite a bit)
all_symbols = '+-'
def solve(expres):
lhs, symbol, rhs = expres[0], None, ''
for ch in expres[1:]:
if symbol:
rhs += ch
elif ch in all_symbols:
symbol = ch
else:
lhs += ch
if symbol is '+':
return int(lhs) + solve(rhs)
if symbol is '-':
return int(lhs) - solve(rhs)
return int(expres)
print solve('1+5')
And another type of solution that may be useful to consider
operations = [
('+', lambda a, b: a + b),
('-', lambda a, b: a - b)
]
def solve(exp):
for symbol, operation in operations:
p = exp.rfind(symbol)
if p > 0:
return operation(solve(exp[:p]), solve(exp[p + 1:]))
return int(exp)

Categories

Resources