using the collatz sequence in dictionaries - python

I'm pretty new to python and currently, I'm trying to learn dictionaries. I'm trying to write a program that asks the user for a number, and then outputs the number less than or equal to the one the user entered with the longest Collatz sequence.
This is what I currently have right now, but I don't know why it won't work.
def collatz(number):
segLength = {}
for i in range(1, number + 1):
current = 1
count = 0
while current != 1:
if current % 2 == 0:
current = number / 2
elif current % 2 != 0:
current = (3 * number + 1)
count += 1
segLength[i] = count
value = list(segLength.values())
key = list(segLength.keys())
x = max(value)
index = value.index(x)
output = key[index]
return output
result = collatz(number)
print = result

Each iteration of your for loop, you set current = 1, so current != 1 will always be False and you'll skip the while.
It looks like you want to calculate the collatz sequence for each number so I'm guessing you want to instead set current = i.
Then, for each iteration of your for loop, current will have the number you want to reduce to 1 and count the number of steps it takes. To make this work, you'll want to change:
current = number / 2
(and the corresponding 3n+1 line in the elif) to
current = current / 2
because number is always going to be the number you passed into the function at the start, not the number you're trying to run a collatz sequence on this iteration
It looks like it should work otherwise!
EDIT: you should also call print rather than assign to it as Barmar said.

Related

alternative to if else python

Ok i wrote this in python then rewrote because i don't like if else statements.
the first version worked perfectly. my second one failed and ended up taking more lines than my first version. my question is, am i just stupid? is there a better way to do this or should i just accept the need for if else statement?
sorry for the code dump, i am going mad
first attempt
#number we are starting with
num = 1
#what we are going to apply equation loop to
result = num
#how many times goes through equation loop before reaching 1
count = 0
# list of numbers used in equation loop
num_in_loop = [result]
#end equation loop function.
running = True
# equation loop
def eqation_loop(running, num_in_loop, count, num, result):
while running == True:
if (result % 2) == 0:
result = result /2
count +=1
num_in_loop.append(result)
elif result == 1.0:
print(num, "took", count ," loops to get to 1: numbers in loop = ", num_in_loop, file=open('3x+1/result.txt','a'))
num +=1
print(num)
result = num
num_in_loop = [result]
count = 0
elif num == 100:
running = False
elif (result % 2) != 0:
result = result * 3 + 1
count +=1
num_in_loop.append(result)
eqation_loop(running, num_in_loop, count, num, result)
second attempt:
#number we are starting with
num = 1
#what we are going to apply equation loop to
result = num
#how many times goes through equation loop before reaching 1
count = 0
# list of numbers used in equation loop
num_in_loop = [result]
limit = int(input("range you want to try: " ))
def update_var(num_in_loop,result,count):
count +=1
num_in_loop.append(result)
return equation_loop(limit,num, result)
def reset_var(num_in_loop, count, limit,num, result):
print(num, "took", count ," loops to get to 1: numbers in loop = ", num_in_loop, file=open('3x+1/test.txt','a'))
num +=1
result = num
num_in_loop = [result]
count = 0
return equation_loop(limit,num, result)
def equation_loop(limit,num, result):
if num == limit:
return
elif result == 1:
return reset_var(num_in_loop, count, limit,num, result)
elif (result % 2) == 0:
result = result /2
return update_var(num_in_loop,result,count)
elif (result % 2) != 0:
result = result *3 +1
return update_var(num_in_loop,result,count)
equation_loop(limit,num, result)
You can't write this without any if/else statements (okay maybe if you really know what you're doing you technically can by severely abusing while, but you shouldn't), but here's a simplified-down version that hopefully contains some useful examples of how to make your code easier to write (and read!):
def equation_loop(num: int) -> list[int]:
"""
Repeatedly applies the magic equation trying to
reach 1.0, starting with num. Returns all the results.
"""
nums = [num]
while True:
if num == 1:
return nums
if num % 2:
num = num * 3 + 1
else:
num = num // 2
nums.append(num)
for num in range(1, 100):
results = equation_loop(num)
print(f"{num} took {len(results)} loops to get to 1: {results}")
A key thing here is that you don't need so many variables! A single loop only needs its starting point (num) and only needs to return the list of results (from which you can get the count, since it'll be the length of the list). Reducing the number of redundant variables eliminates a lot of unnecessary lines of code that are just copying state back and forth. Passing a value like running = True is unnecessary when it will always be True until it's time to end the loop -- instead just use while True: and return or break when you're done.
The big takeaway is that if you have two variables that always have the same value (or even two values that are always related in exactly the same way, like a list and its length), you probably just need one of them.
You can also simplify the code by separating the two nested loops -- for a given num you want to loop until the number reaches 1, so that's one loop. You also want to loop over all the nums up to 99 (it took me a while to even figure out that that's what the code was doing; I had to run it and look at the output to see that some of those extra pieces of state were serving to implement nested loops inside a single loop). Doing those in two different loops makes it easy, and you can put one of them in a nice neat function (I used your equation_loop name for that, although it does less work than your original version does) that takes the starting num and returns the list of results for that starting point. That simple function can then be called in an even simpler for loop that iterates through the nums and prints the results for each one.
Note that I kept everything as ints by using int division (//) -- testing floats for exact equality is often dangerous because floating point numbers aren't exactly precise! Your equation is always operating with integer values (because you only divide by two if it's an even number) so it makes more sense to use int division and not even worry about floating point values.

Fibonacci sequence with numbers in 1 line and without using list or array [duplicate]

This question already has answers here:
How do I print a fibonacci sequence to the nth number in Python?
(8 answers)
Closed 2 years ago.
I'm very new to python and programming in general. This is the first year we have programming classes, so I'd say I started about a month ago.
We got our first assignment last week and I've managed to make most of the tasks, apart from the following one:
Generate n numbers from the Fibonacci sequence, where n is entered by the user.
Write these numbers to the screen.
Print the numbers on 1 single line.
Tip: print (value, end = '')
Do not use list or array.
This is the last question and this one is significantly more difficult than the others. I tried some things but non came close to doing what is asked. I genuinely have no clue how I'd even have to start.
In pseudocode:
First you need to check, print and save the results of fibonacci(0) and fibonacci(1)
Then make a loop to calculate the next fibonacci value using the last two calculated and print it.
Update the variables for the last two calculated.
Iterate steps 2 and 3 for each N>2
Thinking in python3:
# Print Fibonacci(0)
if n>=0:
print (1, end =', ')
f2 = 1
# Print Fibonacci(1)
if n>0:
print (1, end =', ')
f1=1
# Print Fibonacci(n) ; n>1
if n>1:
for i in range (2, n+1):
result = f1+f2
print(result, end=', ')
# updating last two variables
f2 = f1
f1 = result
Although not mentioned, you may want to 'memorize' previous Fibonacci numbers so you can generate the sequence faster.
def fibonacci(n, _cache={}):
if n in _cache: # Check to see if the number has been done
return _cache[n] # Return the pre-done number
elif n > 1:
return _cache.setdefault(n, fibonacci(n-1) + fibonacci(n-2)) # Call this function recursively to generate the previous Fibonacci numbers
return n
n = int(input("n = "))
for i in range(n):
print(fibonacci(i), end=', ')
You need to think about loops, how to iterate a set number of times, and use the print statement given to you in the "tip".
In pseudo code:
next_in_sequence = 1
loop_count = 1
while loop_counter <= number_entered:
next_in_sequence = caclulate_next_fibonacci(next_in_sequence)
print (next_in_sequence, end = '')
loop_counter = loop_counter + 1
Have a go at writing this in python, you'll have to write the caclulate_next_fibonacci function to work out the next number in the sequence. If you have any problems edit your question to show your code and ask for more help
To calculate the next Fibonacci number simply add together the two previous values. You can do this in a for loop using variables declared outside the loop to hold the previous two values.
Use this statement within your loop
print (value, end = '')
This will print the sequence all on one line with each value separated by a space.
n = int(input())
fib0 = 0
fib1 = 1
for x in range(0, n):
nextFib = fib0 + fib1
fib0 = fib1
fib1 = nextFib
print(fib0 , end = ' ')

Looking for Clarification on how this "For-Loop" works

I'm a complete beginner to programming so forgive me for my naivete.
I wanted to make a program in Python that lets me print a given N number of prime numbers, where N is inputted by the user. I searched a little on "for/while" loops and did some tinkering. I ran a program I saw online and modified it to suit the problem. Here is the code:
i = 1
print("Hi! Let's print the first N prime numbers.")
nPrimes = int(input("Enter your N: "))
counter = 0
while True:
c = 0 #another initialization
for x in range (1, (i + 1)):
a = i % x # "a" is a new variable that got introduced.
if a == 0:
c = c + 1
if c == 2:
print(i, end = " ")
counter = counter + 1
if counter > = nPrimes: #if it reaches the number input, the loop will end.
break
i = i+1
print(": Are your", nPrimes, "prime number/s!")
print()
print("Thanks for trying!")
This should be able to print the amount of prime numbers the user so likes. It is a working code, though I am having difficulty trying to understand it. It seems that the variable c is important in deciding whether or not to print the variable i (which in our case is the supposed prime number during that interval).
We do c + 1 to c every time our variable a has a remainder of 0 in a = i % x. Then, if c reaches 2, the current variable i is printed, and variable c re-initializes itself to 0 once a prime number has been found and printed.
This I can comprehend, but I get confused once the numbers of i get to values 4 and onwards. *How is 4 skipped by the program and not printed when it has 2+ factors in the range that makes its remainder equal to zero? Wouldn't c == 2 for 4 and thus print 4? *And how would the program continue to the next number, 5? (Given that variable N is a large enough input).
Any clarifications would be greatly appreciated. Thank you so much!
From Wikipedia we know:
A prime number (or a prime) is a natural number greater than 1 that cannot be formed by multiplying two smaller natural numbers.
So to find a prime, is to find a natural number, aka an integer, which can only be exactly divided by 1 or itself. This is called Approach of Definition to find primes.
Hence, the following loop traverses through all integers from 1 to i,
and it counts how many times the integer i can be exactly divided by them.
for x in range (1, (i + 1)):
a = i % x # "a" is a new variable that got introduced.
if a == 0:
c = c + 1
And later you judge if the integer i can only be exactly divided by 1 and itself.
If true, you got a prime;
otherwise you just keep on.
if c == 2:
print(i, end = " ")
counter = counter + 1
if counter > = nPrimes: #if it reaches the number input, the loop will end.
break
Meanwhile, you can improve this prime searching algorithm a little bit by changing i = 1 to i = 2 in the beginning and adding an if statement:
# Start from 2 instead of 1
# and end at `i - 1` instead of `i`
for x in range (2, i):
a = i % x # "a" is a new variable that got introduced.
if a == 0:
c = c + 1
# Abandon the loop
# because an integer with factors other than 1 and itself
# is unevitably a composite number, not a prime
if c > 0:
break
if c == 0:
print(i, end = " ")
counter = counter + 1
if counter >= nPrimes: #if it reaches the number input, the loop will end.
break
This twist improves the efficiency of your program because you avoid unnecessary and meaningless amount of work.
To prevent potential infinite loop resulting from while expression,
you should replace while True: with while counter < nPrimes:. And the code turns out to be like this:
#if it reaches the number input, the loop will end.
while counter < nPrimes:
c = 0 #another initialization
# Start from 2 instead of 1
# and end at `i - 1` instead of `i`
for x in range (2, i):
a = i % x # "a" is a new variable that got introduced.
if a == 0:
c = c + 1
# Abandon the loop
# because an integer with factors other than 1 and itself
# is unevitably a composite number, not a prime
if c > 0:
break
if c == 0:
print(i, end = " ")
counter = counter + 1
i = i + 1
If you want to read more about how to improve your program's efficiency in finding primes, read this code in C language. :P
c in this case is used to count the number of numbers that divide evenly into i.
for example, if i = 8: 8 is divisible by 1, 2, 4, and 8. so c = 4 since there are 4 things that divide evenly into it
if i = 5: 5 is divisible by 1 and 5. so c = 2 since there are 2 numbers that divide evenly into it
if i = 4 (where you seem to be confused): 4 is divisible by 1, 2, and 4. so c = 3, not 2.

Python == Function to Count All Integers Below Defined Variable, Inclusive [duplicate]

This question already has answers here:
Python Memory Error while iterating to a big range
(3 answers)
Closed 6 years ago.
Sorry I have to ask such a simple question, but I've been trying to do this for a while with no luck, despite searching around.
I'm trying to define a function that will get user input for X, and then add every integer from 0 to X, and display the output.
For example, if the user inputs 5, the result should be the sum of 1 + 2 + 3 + 4 + 5.
I can't figure out how to prompt the user for the variable, and then pass this variable into the argument of the function. Thanks for your help.
def InclusiveRange(end):
end = int(input("Enter Variable: ")
while start <= end:
start += 1
print("The total of the numbers, from 0 to %d, is: %d" % (end, start))
Just delete argument "end" from function header and use your function.
InclusiveRange()
or define code in other way:
def InclusiveRange(end):
while start <= end:
start += 1
print("The total of the numbers, from 0 to %d, is: %d" % (end, start))
end = int(input("Enter Variable: ")
InclusiveRange(end)
Here's an itertools version:
>>> from itertools import count, islice
>>> def sum_to_n(n):
... return sum(islice(count(), 0, n + 1))
>>>
>>> sum_to_n(int(input('input integer: ')))
input integer: 5
15
You should take the user input out of the function, and instead call the function once you have received the user input.
You also need to store the sum in a separate variable to start, otherwise you're only adding 1 each iteration. (I renamed it to index in this example as it reflects it's purpose more).
def InclusiveRange(end):
index = 0
sum = 0
while index <= end:
sum += start
index += 1
print("The total of the numbers, from 0 to %d, is: %d" % (end, sum))
end = int(input("Enter Variable: "))
InclusiveRange(end)
Demo
Instead of using a loop, use a range object, which you can easily send to sum(). Also, you're never actually using the passed end variable, immediately throwing it away and binding end to a new value. Pass it in from outside the function.
def inclusive_range(end):
num = sum(range(end+1))
print("The total of the numbers, from 0 to {}, is: {}".format(end, num))
inclusive_range(int(input("Enter Variable: ")))
You can also use a math formula to calculate the sum of all natural numbers from 1 to N.
def InclusiveRange(end):
''' Returns the sum of all natural numbers from 1 to end. '''
assert end >= 1
return end * (end + 1) / 2
end = int(input("Enter N: "))
print(InclusiveRange(end))

Python Code to Find x Prime Numbers w/ For Loop?

I am trying to put together a simple program which could work out n prime numbers. I would like to do this by using a nested for loop, where one would go through the numbers, and another would divide that number by all of the numbers up to it to see if it would be divisible by anything.
The problem I am having is that in the main for loop, I need to start it at 2, seeing as 1 would mess up the system and I don't want it to be considered a prime. For the loop to have a starting number however, it also needs an ending number which is difficult in this instance as it is hard to generate the largest prime that will be needed prior to the loop working.
Here's the program that I am using right now. Where I have marked X is where I need to somehow put an ending number for the For Loop. I guess it would be much simpler if I let the For Loop be completely open, and simply take out anything that '1' would produce in the loop itself, but this feels like cheating and I want to do it right.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in range(2,X):
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
Thanks for your help!
You can step through an unlimited amount of numbers using a generator object.
Insert the following somewhere near the top of your code:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
What this does is it creates a function for constructing generator objects that "pause" whenever they reach the yield statement to "yield" whatever value is specified by the yield command, and then continue to execute from the next line beneath the yield statement.
Python's own range function is itself an example of a generator, and is roughly equivalent to (ignoring the step argument and other peculiarities)
def range(start, end):
i = start
while i < end:
yield i
i += 1
So your program would then look like this:
def infinite_number_generator(initial_value=2):
""" Generates an infinite amount of numbers """
i = initial_value
while True:
yield i
i += 1
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
for i in infinite_number_generator():
check = 0
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
print (i)
if i == limit:
break
I should also point out that the code you provided is buggy - it will never stop printing because there's no checking whether you've found your limit number of primes yet or not.
This should do what you want.
check = 0
limit = int(input("Enter the amount of Prime Numbers"))
counter = 0
i = 2
while counter < limit:
check = 0
if i > 1:
for j in range(2,i):
if (i % j) == 0:
check = 1
if check == 0:
counter += 1
print (i)
i += 1
In your code you start i with 2 and always increment by 1, so the i will always remain greater than 1, therefore the test if i > 1 is useless.
For efficiency you can stop the check at the square of i or i/2 (no divisors in [i/2 + 1, i[ ).
you can update your code as follow:
n = int(input("Enter the amount of Prime Numbers: "))
FoundPrimes = 0
i = 2
while FoundPrimes < n:
isPrime = True
for j in range(2,1 + i//2):
if (i % j) == 0:
isPrime = False
if isPrime:
FoundPrimes += 1
print(i, end = '\t')
i += 1

Categories