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)
CodePudding user response:
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 num
s 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 num
s and prints the results for each one.
Note that I kept everything as int
s 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.