getting only the odd digits in a number with recursion [duplicate] - python

This question already has answers here:
getting only the odd digits in a number with recursion
(3 answers)
Closed 2 years ago.
So my problem is this i have an number like 123 and as the tilte sugests i want the result to be 13.
The problem is that firstly with the method im using im going to get the invert result (31 for example), secondly im getting a zero at the end that shouldn't be there and instead of joining the digits its summing them and i dont understand why.
So to clarify:
My output:
>>> apenas_digitos_impares(123)
40
Correct output:
>>> apenas_digitos_impares(123)
13
program:
def apenas_digitos_impares(n):
if n == 0:
return 0
elif (n%10)%2 == 0:
return apenas_digitos_impares(n//10)
elif (n%10)%2 == 1:
return 10*(n%10) + apenas_digitos_impares(n//10)

You could do it as -
def apenas_digitos_impares(n):
if n == 0:
return 0
elif (n%10)%2 == 0:
return apenas_digitos_impares(n//10)
elif (n%10)%2 == 1:
return (n%10) + 10*apenas_digitos_impares(n//10)
print(apenas_digitos_impares(123))
OUTPUT :
13

Solution#1: You can do the operation with a single method
import math
def convert_int_to_list(n):
result = []
while n > 0:
if (n % 10) % 2 == 1:
result.append(n % 10)
n = math.floor(n / 10)
return result
print(convert_int_to_list(1345986))
Output:
[9, 5, 3, 1]
Solution#2 You don't have to change your method, just declare an array before the method
result = []
You want odd numbers, then place the array into the correct place.
elif (n%10)%2 == 1:
res.append(n%10)
return 10*(n%10) + apenas_digitos_impares(n//10)
print res
[3, 1]
For various examples:
apenas_digitos_impares(1235)
apenas_digitos_impares(12356789)
[5, 3, 1]
[9, 7, 5, 3, 1]

Related

How to return recursion result and recursion steps as a tuple in Python? [duplicate]

This question already has answers here:
I'm getting a TypeError. How do I fix it?
(2 answers)
Closed 5 months ago.
I am trying to return a tuple (recursion result, recursion steps) in this manner. My code adds all even numbers and returns the sum of all even numbers and number of recursive steps. If odd, then it returns 0 and number of recursive steps.
I am getting a Type Error in my value, step variables...why is that so?
def get_sum_evens(numbers):
if not numbers:
return 0, 0
elif numbers[0] % 2 == 0:
value, step = get_sum_evens(numbers[1:])
return numbers[0] + value, step + 1
elif numbers[0] % 2 != 0:
steps = get_sum_evens(numbers[1:])
return 0, steps + 1
print(get_sum_evens([2, 3, 5, 6]))
print(get_sum_evens([]))
print(get_sum_evens([1, 3, 5, 7]))
print(get_sum_evens([9, 5, 15, 11, 23]))
You probably mean you got a TypeError, not "TextError".
steps = get_sum_evens(numbers[1:])
steps is now a tuple, and you're adding + 1 to it.
You'll always want to do:
value, steps = get_sum_evens(...)

Can I return the base case as answer?

def encryption(n):
if len(n) == 2:
return n
result = []
for i in range(len(n) - 1):
total = n[i] + n[i + 1]
right_most_digit = total % 10
result.append(right_most_digit)
if len(result) > 2:
result = encryption(result)
return "".join([str(x) for x in result])
if __name__ == '__main__':
numbers = [1, 5, 7, 9]
print(encryption(numbers))
I need help with this code.
The problem is to add the two adjacent numbers and keep the right_most_digit, repeat the process to a point where only two numbers left, and return a string.
For example, 1+5, 5+7, 7+9 will be 6,2,6, then 6+2, 2+6 will be 8,8, then return 88 as a string.
With the least changes,
def encryption(n):
if len(n) == 2:
return n
result = []
for i in range(len(n) - 1):
total = n[i] + n[i + 1]
right_most_digit = total % 10
result.append(right_most_digit)
if len(result) > 2:
result = encryption(result)
return result
if __name__ == '__main__':
numbers = [1, 5, 7, 9]
print("".join([str(x) for x in encryption(numbers)]))
print("".join([str(x) for x in encryption(numbers)]).lstrip("0")) if you also want to strip any leading 0
Since you asked about a different approach, you might consider not doing this recursively. You can simply keep processing the list in a while loop until the list is of length 2 or less. Then convert to a string:
def encryption(n):
while len(n) > 2:
n = [(a + b) % 10 for a, b in zip(n, n[1:])]
return "".join([str(x) for x in n])
numbers = [1, 5, 7, 9]
print(encryption(numbers))
# 88
This is a little easier to reason about and it also makes it easy to debug by sticking a print(n) in the loops to see the progression.

Largest number formed from some or all elements in an array divisible by 3

I am trying solve the following question:
Given an array with a length of 1-9 elements consisting of digits 0-9, what is the largest number divisble by 3 that can be formed using some / all the elements in the array?
The question only accepts Java and Python, and I chose Python despite being completely inexperienced with it.
I looked around and it seems like the general idea was to kick off the smallest element to get the digits total divisible by 3, and wrote the following "subtractive" approach:
def maxdiv3(l):
l.sort()
tot = 0
for i in l:
tot += i
if tot % 3 == 0:
l.sort(reverse=True)
return int(''.join(str(e) for e in l))
elif tot % 3 == 1:
cl = [] # A copy of the list but only for elements % 3 != 0
acl = [] # Anti copy of the list, only for elements % 3 = 0
for i in l:
if i % 3 == 0:
acl.append(i)
else:
cl.append(i)
removed = False
nl = [] # A new list for the final results
for i in cl:
if not removed:
if i % 3 == 1:
removed = True
else:
nl.append(i)
else:
nl.append(i)
if removed:
nl.extend(acl)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
else:
return 0
else:
if len(acl) > 0:
acl.sort(reverse=True)
return int(''.join(str(e) for e in acl))
return 0
elif tot % 3 == 2:
cl = []
acl = []
for i in l:
if i % 3 == 0:
acl.append(i)
else:
cl.append(i)
removed2 = False
nl = []
for i in cl:
if not removed2:
if i % 3 == 2:
removed2 = True
else:
nl.append(i)
else:
nl.append(i)
if removed2:
nl.extend(acl)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
removed1 = 0
nl = []
for i in cl:
if removed1 < 2:
if i % 3 == 1:
removed1 += 1
else:
nl.append(i)
else:
nl.append(i)
if removed1 == 2:
nl.extend(acl)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
if len(acl) > 0:
acl.sort(reverse=True)
return int(''.join(str(e) for e in acl))
else:
return 0
This approach kept gets stuck on a hidden test case, which means I can't work out what or why.
Based on this, I wrote up a new one:
def maxdiv3(l):
l.sort()
l0 = []
l1 = []
l2 = []
for i in l:
if i % 3 == 0:
l0.append(i)
elif i % 3 == 1:
l1.append(i)
elif i % 3 == 2:
l2.append(i)
tot = sum(l)
nl = []
if tot % 3 == 0:
nl = l
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
return 0
elif tot % 3 == 1:
if len(l1) > 0:
l1.remove(l1[0])
nl.extend(l0)
nl.extend(l1)
nl.extend(l2)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
return 0
elif len(l2) > 1:
l2.remove(l2[0])
l2.remove(l2[0])
nl.extend(l0)
nl.extend(l1)
nl.extend(l2)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
return 0
else:
return 0
elif tot % 3 == 2:
if len(l2) > 0:
l2.remove(l2[0])
nl.extend(l0)
nl.extend(l1)
nl.extend(l2)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
return 0
elif len(l1) > 1:
l1.remove(l1[0])
l1.remove(l1[0])
nl.extend(l0)
nl.extend(l1)
nl.extend(l2)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
return 0
else:
return 0
And this one does pass all the test cases, including the hidden ones.
Here are some of the test cases that I ran my attempt through:
[3, 9, 5, 2] -> 93
[1, 5, 0, 6, 3, 5, 6] -> 665310
[5, 2] -> 0
[1] -> 0
[2] -> 0
[1, 1] -> 0
[9, 5, 5] -> 9
It seems to me that my attempt and the SO solution had the same idea in mind, so what did I neglect to consider? How is the SO solution different from mine and how does that catch whatever it is that my attempt didn't?
Thank you for your time.
A slightly off topic additional question: How do I find edge cases when dealing with blind test cases? I built a random input generator for this question but that didn't help anywhere near I wished it would and is likely not a good general solution.
How do I find edge cases when dealing with blind test cases?
Here is what I did as tester:
digits = list(range(10))
for k in range(1, 10): # Try different sizes
for _ in range(100): # Repeat many times
lst = random.choices(digits, k=k) # Produce random digits
a = maxdiv3(lst) # Run working solution
b = maxdiv3b(lst) # Run solution with a problem
if a != b: # Found a deviation!
print(lst)
break
This was one of the lists I got:
[2, 2, 5, 5, 8]
Then I retraced your code with that input and came into this block:
else:
if len(acl) > 0:
acl.sort(reverse=True)
return int(''.join(str(e) for e in acl))
We are here in the case where the total has a remainder of 1 when divided by 3. We get in this else block when there is no individual digit with such a remainder. It then just outputs all the digits that are multiples of 3. But this is not always right. When there are at least two digits with a remainder of 2 (i.e. 2, 5, 8), such a pair represents a total that has a remainder of 1, i.e. you only have to remove two digits, not more.
The correction is to remove two of those digits (the smallest) and then join the two lists as you did elsewhere in the code:
else:
del nl[0:2]
nl.extend(acl)
nl.sort(reverse=True)
if len(nl) > 0:
return int(''.join(str(e) for e in nl))
else:
return 0
NB: It didn't help that the chosen names are not very descriptive. I have no clue what acl, nl, or cl are abbreviations of.
You can use recursivity to "improve" the digit selection, stopping as soon as the sum of digits is a multiple of 3 (all numbers divisible by 3 have a sum of digits that is a multiple of 3). Only removing digits that are not multiples of 3 can improve the result
The largest number is the one that has digits in decreasing order.
def div3(D):
if sum(D)%3 == 0:
return sum(d*10**i for i,d in enumerate(sorted(D)))
return max(div3(D[:i]+D[i+1:]) for i,d in enumerate(D) if d%3)
d = [1,2,3,4,5]
print(div3(d))
# 54321
d = [2, 2, 5, 5, 8]
print(div3(d))
# 855
print(div3([4,1]))
# 0

How to take list of numbers from a recursive function and return it as a list?

I made a recursive function that gives me a certain number if it's odd or even. So, if I call the function with a 5, it'll output 5, 16, 8, 4, 2, 1. How do I have the output return this sequence of numbers as a list? So, [5, 16, 8, 4, 2, 1].
This is my code:
def recursion_list(number):
ls = []
print(number)
if number == 1:
return 1
if number % 2 == 0:
first = recursion_list(number // 2)
return first
elif number % 2 == 1:
second = recursion_list(3 * number + 1)
return second
There are two ways to do this.
First, return a variable of list type and receive the return value and appending it.
But this method has a large overhead
Second, make variable ls to global variable of list type and instead of returning a value, attach it to the ls variable.
Try to return a list of the printed variables and recursively append them.
def recursion_list(number):
ls = [number]
print(number)
if number == 1:
return ls
if number % 2 == 0:
ls += recursion_list(number // 2)
return ls
elif number % 2 == 1:
ls += recursion_list(3 * number + 1)
return ls
print(recursion_list(5))
output
5
16
8
4
2
1
[5, 16, 8, 4, 2, 1]
The task can be done by defining a list globally.
ls = []
def recursion_list(number):
ls.append(number)
if number == 1:
return ls
if number % 2 == 0:
first = recursion_list(number // 2)
return first
elif number % 2 == 1:
second = recursion_list(3 * number + 1)
return second
print(recursion_list(5))
def recursion_list(number):
ls = [number]
if number == 1:
return ls
elif number % 2 == 0:
return ls + recursion_list(number // 2)
elif number % 2 == 1:
return ls + recursion_list(3 * number + 1)
You could convert you recursive function into a generator and make a list of the output only when needed.
def recursion_gen(number):
yield number
if number == 1: return
if number % 2 == 0:
for n in recursion_gen(number // 2):
yield n
else:
for n in recursion_gen(3 * number + 1):
yield n
print(*recursion_gen(5)) # 5 16 8 4 2 1
ls = list(recursion_gen(5))
print(ls) # [5, 16, 8, 4, 2, 1]
To return a list directly, you don't need an intermediate variable:
def recursion_list(number):
if number == 1:
return [number]
if number % 2 == 0:
return [number] + recursion_list(number // 2)
else:
return [number] + recursion_list(3 * number + 1)

Program that checks if number can be divided to three numbers

I need to make a program that checks if a number can be divided to three(or more) numbers. for example 8=2*2*2 and 153=3*3*17 and so on. And it has to work for all positive real numbers. I just can't wrap my head around it :(
def loytyyko_kolme_tekijaa(luku):
tekija = 2
kaikki = 0
while luku > tekija:
if luku % tekija == 0:
kaikki = kaikki + 1
tekija = tekija + 1
if kaikki >= 3:
return True
else:
return False
Ok now that I see that you tried. Is this what you want?
Copied answer from here:
Python - Integer Factorization into Primes
def factorize(num):
for possible_factor in range(2, num):
if num % possible_factor == 0:
return [possible_factor] + factorize(num // possible_factor)
return [num]
nums = [8,153]
for num in nums:
print("{}: {}".format(num, factorize(num)))
Returns:
8: [2, 2, 2]
153: [3, 3, 17]

Categories

Resources