Python - print only the highest number of collatz - python

def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
result = 3 * number + 1
print(result)
return result
#4. zolang n ongelijk is aan 0, niet stoppen.
n = input("invoer: ")
while n != 1:
n = collatz(int(n))
I've got this code, but I only want to print the highest number in place of the whole queue of collatz sequence.
How could I do that?

Your code can be refactored to print the maximum number from the Collatz Sequence as follows:
def collatz(number):
if number % 2 == 0:
return number // 2
else:
return (3 * number) + 1
# Refactored this part because Collatz Conjecture is defined for positive
# numbers only
try:
n = int(input('invoer: '))
if n <= 0:
raise ValueError
except ValueError:
print('Enter a valid positive integer')
# Set a variable to store maximum value
max_num = 0
while n != 1:
# If the current number is bigger than existing maximum number, update it
max_num = max(n, max_num)
n = collatz(int(n))
print('Maximum number is {}'.format(max_num))
Note that I have updated some of your original code so that only positive integer is a valid input. This is because Collatz Conjecture states that the sequence starts with a positive integer.
Also, in the if-else construct, you do not need to write the condition for odd numbers explicitly because if the integer is not even then it must be odd.

Just have a max variable which you update with n, if n is larger than that variable's value:
def collatz(number):
if number % 2 == 0:
return number // 2
elif number % 2 == 1:
return 3 * number + 1
n = input('invoer: ')
m = 0
while n != 1:
if n > m: m = n
n = collatz(int(n))
print('the max was:', m)
With the input 5 gives 16, since 16 is the max of [5, 16, 8, 4, 2, 1].

Related

How to put my for-loop and range output into a list and display only certain logic text?

I have a piece of code here where I am creating a logic to be displaying all of the numbers from 2, to my int(input) to be converted to a list and then only display the prime numbers from 2 to my input.
Here is my code:
def display_prime_numbers(maximum):
lst = []
if maximum <= 2:
print('Enter Number Greater Than 2')
maximum = maximum + 1
rng = range(2,maximum)
for index in rng:
print(index, end=' ')
for i in rng:
if (index % i) == 0:
return False
else:
print(f'{index} is a prime number')
This is my output:
Enter Positive Integer Greater Than 2:10
2 3 4 5 6 7 8 9 10
Summary: I'm unable to display my range count loop as a list and am trying to only display my prime number pieces.
i.e. expected:
[2,3,4,5,6,7,8,9,10]
3 is a prime number
5 is a prime number
7 is a prime number
To clarify my comment, your return false statement will end the function. The first time the mod of the index is == 0, then the function will end and the rest of the list will not be evaluated for being prime.
def display_prime_numbers(maximum):
lst = []
if maximum <= 2:
print('Enter Number Greater Than 2')
maximum = maximum + 1
rng = range(2,maximum)
for index in rng:
print(index, end=' ')
for i in rng:
if (index % i) != 0: #Just print here!
print(f'{index} is a prime number')
display_prime_numbers(10)

How can I retain zero in python for calculation?

So I supposed to verify if the input number is a UPC number or not. I have to allowed leading zeros and accounted it in the calculation.
Here is my current code, it works for all number except number has leading zeros:
Condition for UPC code valid:
Calculate the sum of multiplying odd digit index by 3 and even digit index by 1 of the input number.
Calculate the sum we just did modulo 10, get result digit.
If the resulting digit is between 1 and 9 then subtract result digit from 10. If the result digit is 0, add 0 to the to the base number to get the completed number.
def UPC_code(num):
sum_digit = 0
index = 0
num_temp = str(num)[:-1]
len_nt = len(num_temp)
for digit in num_temp:
if (index + 1) % 2 != 0: # If number position is odd
sum_digit += int(digit) * 3 # Sum = digit * 3
if index < len_nt: # Increase index till end
index += 1
elif (index + 1) % 2 == 0: # If number position is even
sum_digit += int(digit) * 1 # Sum = digit * 1
if index < len_nt:
index += 1
# print(sum_digit)
res_digit = sum_digit % 10
if 1 <= res_digit <= 9:
res_digit = 10 - res_digit # Res digit meet condition = 10 - res digit
if res_digit == num % 10:
return True
elif res_digit != num % 10:
return False
else:
print("Something went wrong")
# End UPC_code()
Call UPC_code()
import code_check.py as cc
num = str(input())
num_int = int(num)
if cc.UPC_code(num_int) is True and num_int != 0:
print(num, "valid UPC code.")
else:
print("Not valid")
Expected input:
042100005264
Expected output:
042100005264 valid UPC code
Actual output:
Not valid
it works for all number except number has leading zeros
As you have doubtless discovered, python does not allow you to write 0700. Historically that would have meant 0o700, or 448, which is likely not what you want anyhow...
In this case the solution is simple. If you need to handle numbers like 00007878979345, handle strings.
Thus refactor your code to take a string. As a bonus, int("000008") is 8, so when you need the number as a number you don't even have to do anything.

Program that finds a numbers divisor

I've been making my own little program that finds the divisors for an inputted number.
The way it determines if a number can be divided with another number is if the result is an integer. If its a float, it should come out negative.
This is what I've got so far:
# Divider
Number = input("> ")
divider = 1
while True:
Number = int(Number)
divider = int(divider)
result = 0
result = int(result)
result = Number/divider
if isinstance(result, int):
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
if divider == Number + 1:
break
The problem is that when I run the program and input a number like "10" which should have more than one divisor (1,2,5,10) it comes out completely negative:
> 10
1 N
2 N
3 N
4 N
5 N
6 N
7 N
8 N
9 N
10 N
>>>
I wonder what I'm doing wrong.
First I'm going to clean up your code:
Number = 15
divider = 1
while True:
if divider == Number + 1:
break
Number = int(Number)
divider = int(divider)
result = Number/divider
if isinstance(result, int):
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
Now, what are they all return as negative? Simply because the / division returns a float (i.e. result is a float). What is the correct solution? Use the % modulo to check if the remainder is 0.
Number = 15
divider = 1
while True:
if divider == Number + 1:
break
Number = int(Number)
divider = int(divider)
result = Number%divider
if result == 0:
print("{} Y".format(divider))
else:
print("{} N".format(divider))
divider = divider + 1
Output:
1 Y
2 N
3 Y
4 N
5 Y
6 N
7 N
8 N
9 N
10 N
11 N
12 N
13 N
14 N
15 Y
The division operator / always results in a floating number in Python 3, so the result will never be an instance of an integer.
You should instead use the modulo operator to test if the remainder is 0:
if number % divider == 0:
print("{} Y".format(divider))
else:
print("{} N".format(divider))
I would solve it using modulus. If the remainder is 0 then its divisible otherwise its not. No need to have any int or float checks.
num = input("> ")
#Assuming the num is an integer
divisors = [] #List of divisors
for i in range(1,num):
if num%i == 0:
divisors.append(i)
Output:
>>[1, 2, 5]
for divisor in range(1, number//2+1):
print("{} {}".format(divisor, "Y" if number % divisor == 0 else "N"))
Some additional advice:
Don't use capitals for variable names. It's good practice to name classes with capitals instead (and all-caps for constants).
It is enough to walk until number // 2 (the integer division) because between number // 2 and number there cannot be any more divisors.
DRY - don't repeat yourself (a very general rule in programming): Use the a if b else c operator to avoid repeating the print.
What about you just use modulo like in the following?
result = Number%divider
if result==0:
print("{} Y".format(divider))
num = int(input('Enter a number : '))
div = 1
count = 0
while True:
if(div == num+1):
break
result = num%div
if result == 0:
print('{} -- yes'.format(div))
count+=1
else:
print('{} -- No'.format(div))
div+=1
print('Total number of divisor : ', count)

Collatz Sequence. (Python 3)

I've started the book "Automate The Boring Stuff" by Al Sweigart.
At the end of Chapter 3, the author suggests creating a Collatz Sequence in Python as a practice exercise. (the practice exercise suggests I use a the print function and return statement)
When I use a print() function in my code, it works great and I get all the evaluated values I want to see on the screen:
print("This is The Collatz Sequence")
user = int(input("Enter a number: "))
def collatz(n):
print(n)
while n != 1:
if n % 2 == 0:
n = n // 2
print(n)
else:
n = n * 3 + 1
print(n)
collatz(user)
Question:
How come when I want to use the return statement, the while loop only runs once?
For example, passing the integer 3 into my function with the return statement only gives me the return value of 3 and 10:
print("This is The Collatz Sequence")
user = int(input("Enter a number: "))
def collatz(n):
print(n)
while n != 1:
if n % 2 == 0:
n = n // 2
return n
else:
n = n * 3 + 1
return n
result = collatz(user)
print(result)
return exits the function and, therefore terminates your while loop.
Perhaps you meant to use yield instead:
print("This is The Collatz Sequence")
user = int(input("Enter a number: "))
def collatz(n):
print(n)
while n != 1:
if n % 2 == 0:
n = n // 2
yield(n)
else:
n = n * 3 + 1
yield(n)
print(list(collatz(user)))
Output:
This is The Collatz Sequence
Enter a number: 3
3
[10, 5, 16, 8, 4, 2, 1]
Yield is logically similar to a return but the function is not terminated until a defined return or the end of the function is reached. When the yield statement is executed, the generator function is suspended and the value of the yield expression is returned to the caller. Once the caller finishes (and assumably uses the value that was sent) execution returns to the generator function right after the yield statement.
In your code you don't re-feed the new value back into your equation. Try separating your while loop from the collatz module. I have an example of this below:
def collatz(number):
if number % 2 == 0:
return number // 2
elif number % 2 == 1:
return 3 * number + 1
chosenInt = int(input('Enter an integer greater than 1: '))
print(chosenInt)
while chosenInt != 1:
chosenInt = collatz(chosenInt)
print(chosenInt)
def collatz(number):
if (number%2 == 0):
return print(number//2);
else:
return (print(number*3+1));
inputNumber = input("Enter a number greater than 1:");
result = collatz(int(inputNumber));
while result != 1:
result = collatz(result);
I am getting a typeError with it! Don't know why?

Python: Code to find a number where first N digits are divisible by N (from 0-9)

I've been trying to write a recursive solution to a program to find a number where first N digits are divisible by N.
As an example: 3816547290, 3 is divisible by 1, 38 is divisible by 2, 381 is divisible by 3 and so on...
My recursive solution works fine while going "into" the recursion, but has issues when the stack unwinds (i.e. I don't specifically know how to backtrack or take steps on the way out
ARR = [0]*10
ARR[0] = 1 #dummy entry
def numSeq(pos, num):
if all(ARR):
print num
return True
if (pos>0) and (num%pos) != 0:
return False
for i in xrange(1,10):
if ARR[i] == 1:
continue
new_num = num*10 + i
if new_num%(pos+1) == 0:
ARR[i] = 1
numSeq(pos+1,new_num)
The problem with this code seems to be that it follows the number generation correctly while going into the recursion...so it correctly generates the number 123654 which is divisible by 6 and follows first N digits being divisible by N, but after it fails to find any further digits from 7-8 or 9 that divide 7, i don't get the next set of steps to "reset" the global ARR and begin from index 2, i.e. try 24xxxx,and eventually get to 3816547290
Thanks in Advance for your help!
EDIT: One condition I'd forgotten to mention is that each digit must be used exactly once (i.e. repetition of digits is disallowed)
2nd EDIT:
I was able to finally apply proper backtracking to solve the problem...this code works as is.
ARR = [0]*10
def numDivisibile(num,pos):
if all(ARR):
print num
return True
for i in xrange(0,10):
if ARR[i] == 1:
continue
new_num = num*10+i
#check for valid case
if new_num%(pos+1) == 0:
ARR[i] = 1
if numDivisibile(new_num, pos+1):
return True
#backtrack
ARR[i] = 0
return False
print numDivisibile(0, 0)
To generate all 10 digits integers where the first n digits are divisible by n for each n from 1 to 10 inclusive:
#!/usr/bin/env python3
def generate_ints_nth_digit_divisible_by_n(n=1, number=0):
number *= 10
if n == 10:
yield number # divisible by 10
else:
for digit in range(not number, 10):
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_ints_nth_digit_divisible_by_n(n + 1, candidate)
print("\n".join(map(str, generate_ints_nth_digit_divisible_by_n())))
Output
1020005640
1020061620
1020068010
...
9876062430
9876069630
9876545640
To get numbers where each digit occurs only once i.e., to find the permutations of the digits that satisfy the divisibility condition:
def divisibility_predicate(number):
digits = str(number)
for n in range(1, len(digits) + 1):
if int(digits[:n]) % n != 0:
return n - 1
return n
def generate_digits_permutation(n=1, number=0, digits=frozenset(range(1, 10))):
# precondition: number has n-1 digits
assert len(set(str(number))) == (n - 1) or (number == 0 and n == 1)
# and the divisibility condition holds for n-1
assert divisibility_predicate(number) == (n - 1) or (number == 0 and n == 1)
number *= 10
if n == 10:
assert not digits and divisibility_predicate(number) == 10
yield number # divisible by 10
else:
for digit in digits:
candidate = number + digit
if candidate % n == 0: # divisible by n
yield from generate_digits_permutation(n + 1, candidate, digits - {digit})
from string import digits
print([n for n in generate_ints_nth_digit_divisible_by_n()
if set(str(n)) == set(digits)])
print(list(generate_digits_permutation()))
Output
[3816547290]
[3816547290]
In your function, you never do return numSeq(...), this seems like causing the issue.
If you want to have a iterative solution, you can check the following:
def getN(number):
strNum = str(number)
for i in range(1, len(strNum)+1):
if int(strNum[:i]) % i != 0:
return i-1
return i
print getN(3816)
print getN(3817)
print getN(38165)
Output:
4
3
5
We can modify your recursive function a little to try different possibilities. Rather than have a global record (ARR) of used positions, each thread of the recursion will have its own hash of used digits:
def numSeq(pos, num, hash):
if pos != 1 and num % (pos - 1) != 0: # number does not pass the test
return
elif pos == 11: # number passed all the tests
print num
elif pos == 5:
numSeq(pos + 1,10 * num + 5,hash) # digit is 5 at position 5
elif pos == 10:
numSeq(pos + 1,10 * num,hash) # digit is 0 at position 10
else:
k = 2 if pos % 2 == 0 else 1 # digit is even at even positions
for i in xrange(k,10,2):
if hash & (1 << i): # digit has already been used, skip it
continue
numSeq(pos + 1,10 * num + i,hash | (1 << i))
numSeq(1,0,0) # 3816547290

Categories