List output being duplicated - python

I created a simple recursive function that determines whether a number is even or odd, performs math on them, and appends them to a list:
iter_list = []
def function(n):
iter_list.append(n)
if n < 2:
print iter_list
print iterations
pass
elif n % 2 == 0:
even = n / 2
iter_list.append(even)
collatz(even)
elif n % 2 == 1:
odd = (3 * n) + 1
iter_list.append(odd)
collatz(odd)
else:
print "Code not working."
pass
stdin = input("Number")
print collatz(stdin)
iterations = len(iter_list) - 1
When I run the function with 276, the output is:
Number[276, 138, 138, 69, 69, 208, 208, 104, 104, 52, 52, 26, 26, 13, 13, 40, 40, 20, 20, 10, 10, 5, 5, 16, 16, 8, 8, 4, 4, 2, 2, 1, 1]
Which is what I would expect, except that there are two instances of each number, instead of one.
How would I fix this?

Let's look at what happens when n == 4:
def function(n):
iter_list.append(n)
if n < 2:
print iter_list
print iterations
pass
elif n % 2 == 0:
even = n / 2
iter_list.append(even)
collatz(even)
...
On line 2, we append 4.
On line 9, we append 2.
We call collatz(2)
On line 2, we append 2.
On line 9, we append 1.
We call collatz(1)
Note that we added 2 twice! Perhaps you should only append to the list at the beginning of your function instead of additionally inside the conditionals.

Related

Create a python function that accepts two integer parameters, finds all prime numbers between them and return these primes in a list

I want to create a python function that accepts two integer parameters finds all prime numbers between them and returns these primes in a list.
I did a part of the code but I'm stuck in printing prime numbers and turning them into a list.
a,n = map(int,input("Enter a and n: ").split())
def isPrime(a,n):
if n <= 1:
return False
for i in range(a, n+1):
if n % i == 0:
return False;
return True
You can make your is_prime function shorter like that:
a,n = map(int,input("Enter a and n: ").split(" "))
def is_prime(a):
return all(a % i for i in range(2, a))
out = []
for i in range(a, n):
if is_prime(i):
out.append(i)
print(out)
The output for a = 0 and n = 90 would be:
[0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89]
I edited your solution so that you only check for numbers with a value of 2 or higher. Your solution allows negatives, which is not correct.
Also, your clause for checking for the primes is wrong, as you check if n has divisors. Instead, you want to check if every number in [a, n) interval has a divisor. The interval is [a, n) because a prime number has only 1 and itself as divisors.
My code does just that, so if the algorithm finds that a number in the [a, n) interval has no divisors, then it will append it in an empty list that I created before going through the loop, and return the list, then print it.
a, n = map(int, input("Enter a and n: ").split())
def isPrime(a, n):
lst = []
for i in range(a, n + 1):
if (i > 1):
for j in range(2, i):
if (i % j == 0):
break
else:
lst.append(i)
return lst
print(isPrime(a, n))
My output for a = 0 and n = 100 is:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
My code is a modified version of this.

How to check all the numbers in a range against a calculation?

So I'm trying to print all the prime numbers up to 100. Here's my code so far:
primes = []
for num in range(100):
if num > 1:
for i in range(2, num):
if num % i != 0:
primes += [num]
break
else:
break
print(primes)
However when i run the code, it only does the calculation (if num % i != 0) for the first iteration in the range (for i in range(2, num)). This is a problem in the case of numbers like 15, where the first iteration in for i in range is 2. 15 divided by 2 does not give a whole number, and so it runs primes += [num]. It has taken the first iteration and has not run the rest of them. Is there a way to run all the iterations in the range?
Try this:
primes = []
for num in range(100):
if num > 1:
for i in range(2, num):
if num % i == 0:
break
else:
primes.append(num)
print(primes)
The code will execute the else block only if the inner for loop is exhausted, i.e completes it's all iteration without breaking.
You got the logic somewhat wrong. Here's how you've to do it
primes = []
for num in range(2, 100): # 0 and 1 aren't primes
for i in range(2, num):
if num % i == 0:
break
else: # the else condition is for the for loop i.e. if it executes without break
primes.append(num)
print(primes)
The all function may be what you're looking for!
Here is my take on it.
>>> def primes(limit=100):
... for number in range(limit):
... is_prime = all([number % divisor != 0 for divisor in range(2, number)])
... if is_prime:
... yield number
...
>>> list(primes(10))
[0, 1, 2, 3, 5, 7]
>>> list(primes(100))
[0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
>>>
Is not complete, 0 and 1 are not primes. But I think you get the idea.
tried to adapt to your approach although, I think there should be better ways to solve this problem
>>> primes = []
>>> for num in range(2,100):
... p = True
... for i in range(2, num):
... if num % i == 0:
... p = False
... if p:
... primes += [num]
...
>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

sum to turn divisible by one element of the list each time

Given the list:
n = [3, 6, 12, 24, 36, 48, 60]
I need to turn a random number divisible by 3, after by 6, after by 12, after by 24, after by 36, after by 48 and after by 60. One at each time, not the divisible for the seven numbers simultaneously.
But, to make the number divisible, I need to sum another number to reach the number divisible by 3, 6, 12, 24, 36, 48 or 60.
I don't know the random number neither the number to add to this random number in order to turn it divisible by 3, 6, 12, 24, 36, 48 or 60.
Can someone help me, please?
Using the map function list comprehension:
import random
n = [3, 6, 12, 24, 36, 48, 60]
a = random.randint(start, stop)
result = [a + x - a % x if a % x else a for x in n]
addition = [x - a for x in result]
print(a)
print(result)
print(addition)
start and stop are the limits for your random number.
Output for a = 311:
311
[312, 312, 312, 312, 324, 336, 360]
[1, 1, 1, 1, 13, 25, 49]
Begin of the old answer to the rather unclear question before the first edit by the author.
The following post answers the question: Which is the next number after a, which is a multiple of all numbers of the list n, if it is not a?
First the least common multiple lcm of the numbers from the list must be determined. For this purpose, the method least_common_multiple is executed for the complete list. The modulo operation then checks whether a is not already a multiple of the numbers. If this is the case, a is output. Otherwise, the next multiple of lcm is output.
from math import gcd
from functools import reduce
n = [3, 6, 12, 24, 36, 48, 60]
a = 311
def least_common_multiple(x, y):
return abs(x * y) // gcd(x, y)
lcm = reduce(least_common_multiple, n)
result = a if a > 0 else 1 # can be change if necessary, see edit
mod = result % lcm
if mod:
result += (lcm - mod)
print('Current number: ' + str(a))
print('The next number divisible by any number from the given list: ' + str(result))
print('Necessary addition: ' + str(result - a))
Output:
Current number: 311
The next number divisible by any number from the given list: 720
Necessary addition: 409
Edit: Changed the code so that 0 is no longer a valid result for a non-positive a.
However, if it is valid, you can change the code at the commented part with: result = a.
New answer for the clarified question:
import math
def f(x, a):
return math.ceil(a / x) * x - a
n = [3, 6, 12, 24, 36, 48, 60]
a = 311
result = [f(x, a) for x in n]
print(result)
Old answer:
I think you're looking for the LCM (lowest common multiple) of all numbers in n. We can get the LCM for two numbers using the GCD (greatest common divisor). We can then use reduce to get the LCM for the whole list. Assuming x can be negative, simply subtract a from the LCM to get your answer. The code could look like this:
import math
from functools import reduce
def lcm(a, b): # lowest common multiple
return a * b // math.gcd(a, b)
n = [3, 6, 12, 24, 36, 48, 60]
smallest_divisible_by_all = reduce(lcm, n)
a = 311
x = smallest_divisible_by_all - a
print(x)
which outputs
409
If speed is not important, you could also do a brute force solution like this:
ns = [3, 6, 12, 24, 36, 48, 60]
a = 311
x = 0
while not all([(a + x) % n == 0 for n in ns]):
x += 1
(assuming that x >= 0)
So I can think of 2 solutions:
First if you want a list which show how much you have to add for the random number to get to a divisible number:
def divisible(numbers,random):
l = []
for number in numbers:
if random % number != 0:
l += [number - (random % number)]
else:
l += [0]
return l
a = 311
n = [3, 6, 12, 24, 36, 48, 60]
print(divisible(n,a))
Output:
[1, 1, 1, 1, 13, 25, 49]
Or if you want to know how far is the smallest number from the random number that everyone shares as divisible. For this take a look how you calculate lcm.
from math import gcd
def divisible_all(numbers, random):
lcm = numbers[0]
for i in numbers[1:]:
lcm = lcm*i//gcd(lcm, i)
tempLcm = lcm
while lcm < random: # in case the lcm is smaller than the random number add lcm until it is bigger (I assume you only allow positive numbers)
lcm += tempLcm
return lcm-random
print(divisible_all(n,a))
Output:
409
You can do:
import math
n = [3, 6, 12, 24, 36, 48, 60]
div_n={el: False for el in n}
a=311
a0=math.ceil(a/max(n)) * max(n)
while not all(div_n.values()):
div_n={el: False for el in n}
# print(a0)
for el in n:
if(a0 % el > 0):
a0=math.ceil(a0/el) * el
break
else:
div_n[el]=True
print(a0-a)
Output:
409

python solution in codewars could not pass time limit, needs optimization

There is a question on codewars, life without primes. I solved it yet the time issue comes up. I really cannot find a better way. The instructions go like;
Consider an array that has no prime numbers, and none of its elements has any prime digit. It would start with: [1,4,6,8,9,10,14,16,18,..]. The element at index 1 is 4.
There will be given an integer n and the task will be return the number at that index in the array. For example, solve(1) = 4, as explained above.
Here is my solution
def solve(n):
no_primes=[]
a=1
if n == 1:
return 4
else:
while True:
try:
no_primes[n]
break
except IndexError:
if is_prime(a) == True:
if is_num_prime(a) == False:
no_primes.append(a)
a=a+1
return no_primes[n]
def is_prime(num):
numbers = list(map(int, list(str(num))))
#primes=[0,2,3,5,7,9]
non_primes=[0,1,4,6,8,9]
return all(list(map(lambda x:x in non_primes,numbers)))
def is_num_prime(num):
if num == 2:
return True
elif num >2:
for i in range(2,num):
if num%i == 0:
return False
else:
return True
else:
return False
Getting rid of the while loop could help but I need to keep on appending until I can reach the value from the list. A recursive for loop with using range(1,n) where n increases recursively may be an option but I could not write it anyways.
You can easily break down this problem in simple steps:
Generate the all the combinations
You can make an endless generator making ever-longer combinations of these digits
def generate_numbers():
digits= '014689'
for i in itertools.count(1): # ever longer number
for x in itertools.product(digits, repeat=i): # combine the digits
number = ''.join(x)
if number[0] != '0':
yield int(number)
print(list(itertools.islice(generate_numbers(), 40)))
[1, 4, 6, 8, 9, 10, 11, 14, 16, 18, 19, 40, 41, 44, 46, 48, 49, 60, 61, 64, 66, 68, 69, 80, 81, 84, 86, 88, 89, 90, 91, 94, 96, 98, 99, 100, 101, 104, 106, 108]
Check whether a number is prime
def is_prime(num):
if num in {0, 1,}:
return False
if num == 2:
return True
if not (num % 2):
return False
for i in range(3, round(num **.5 + 1), 2):
if not (num % i):
return False
return True
return the nth non-prime number
def solve(n):
non_prime_solutions = (i for i in generate_numbers() if not is_prime(i))
return next(itertools.islice(non_prime_solutions, n, None))
[solve(i) for i in (1, 2, 10, 100)]
[4, 6, 44, 644]
Since all of this is lazily evaluated, this should go pretty fast. The one thing that can be optimised is the is_prime
import math
import itertools
def is_prime(n):
return all(n % i for i in range(2, int(math.sqrt(n) + 1)))
prime_digits = {"2", "3", "5", "7"}
def no_prime_digit(n):
return not any(x in prime_digits for x in str(n))
def non_primes():
return (i for i in itertools.count() if no_prime_digit(i) and not is_prime(i))
def get_non_prime(n):
return next(x for i, x in enumerate(non_primes()) if i == n - 1)
print([(x, get_non_prime(x)) for x in [1, 10, 100]])

Making recursive function in python

This is a homework problem. I try to get a recursive function:
def problem_a(n):
answer.append(n)
if n == 1:
return answer
elif n % 2 == 0:
answer.append(n/2)
else :
answer.append(n*3 + 1)
problem_a(n*3 + 1)
This code obviously doesn't work as answer isn't defined as a list. With loops it would work, but I want to make a recursive function. I could just use as input a list, but I wonder if there exist something more elegant.
problem_a(7) should give as output:
[7, 22, 11, 34, 17, 52, 26, 13, 40 , 20, 10 ,5 ,16, 8, 4, 2, 1]
One alternative solution to the ones that have been suggested so far (which use an extra argument to pass the list up the recursive chain) is to build the final list as you return from the recursion. This is not terribly efficient, since concatenating lists requires copying both of them, but it will work:
def problem_a(n):
if n == 1:
return [n]
elif n % 2 == 0:
return [n] + problem_a(n // 2)
else:
return [n] + problem_a(3*n + 1)
You could try a generator:
def problem_a(n):
yield n
if n == 1:
return
elif n % 2 == 0:
x = n / 2
else:
x = n * 3 + 1
for y in problem_a(x):
yield y
print list(problem_a(7))
You can define a local variable answer and pass it around in recursive calls.
def problem_a(n, answer = None):
answer = [n] if answer is None else answer
if n == 1:
return answer
elif n % 2 == 0:
n = n/2
answer.append(n)
else:
n = n*3 + 1
answer.append(n)
return problem_a(n, answer)
print problem_a(7)
output:
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
There is a problem with your skeleton solution. You need to recurse when n % 2 == 0 as well as in the final else. The answer variable is given a default value so that it is initialized to [] when the function is first called without an argument.
def problem_a(n, answer=None):
if answer == None:
answer = []
answer.append(n)
if n == 1:
return answer
elif n % 2 == 0:
return problem_a(n/2, answer)
else :
return problem_a(n*3 + 1, answer)
>>> problem_a(7)
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
Edit
As per the comments, using a mutable default argument is a bad idea. Just set it to None like in the other posts and check if its None to create a new list. I changed the answer to reflect this.
The original bad code was as follows:
def problem_a(n, answer=[]):
answer.append(n)
...
You can also use a closure:
>>> def s():
ret = []
def f(n):
ret.append(n)
if n % 2 == 0:
f(int(n/2))
elif n != 1:
f(int(n*3 + 1))
return ret
return f
>>> s()
<function f at 0x00000000033A5848>
>>> s()(7)
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]

Categories

Resources