using while loop to count how many doublings happen between two numbers - python-3.x

My task is to write a function that uses a while loop to count how many days(how many doublings) it takes for the population to go from a given initial size to a value greater than or equal to a given final size.
In addition, The answer should be zero if the final populations is less than or equal to the initial population.
My approach:
def num_doublings(initial_population, final_population):
days = 0
if final_population <= initial_population:
return 0
else:
while initial_population < final_population:
initial_population * 2
days = days + 1
return days
Testing:
ans = num_doublings(1, 8)
print(ans)
When i press enter, it tells me "executing command. please wait for results."
and i don't think it'll ever return something so i just discontinue the code from running.
So what am i doing wrong?

You are calling initial_population * 2, which does not modify the in-place variable. Instead try:
initial_population *= 2
Which is equivalent to:
initial_population = initial_population*2
Final Code:
def num_doublings(initial_population, final_population):
days = 0
if final_population <= initial_population:
return 0
else:
while initial_population < final_population:
initial_population *= 2 #Right here
days += 1 #Also changed this to be more concise
return days
Why this is an issue:
You are testing for if x < y, and if x is indeed less than y, and you do not modify either x or y, your while loop will run indefinitely.

Related

Can anyone help me out? My code print 0 every time input a different value; my code is supposed to print number of coins

In problem set6 I am required to ask user for an input( a float) and then use the input to calculate number of coin the use owe. In my code I used modulo function in a while to increment number of coin by one. Unfortunately I don't get the outcome I expected. Can anyone assist?
Below is my code
# ask the user for change owed
from cs50 import get_float
while True:
change = get_float("Change owed:")
if change > 0:
break
#compute quarter
coin = 0
while change % 0.25 >= 0.25:
change = change - 0.25
coin += 1
#compute dime
while change % 0.1 >= 0.1:
change = change - 1
coint += 1
#compute nickel
while change % 0.5 >= 0.5:
change = change - 0.5
coin += 1
#compute pennies
while change % 0.1 >= 0.1:
change = change - 0.1
coin += 1
print(coin)
in your code lines like:
change % 0.1 >= 0.1
always will be false, because any remainder after division change on some k is less than k.
Your coin always will be 0. Also try to think about order of while loops in your algo, seems it should be differ.

How can I solve finding consecutive factors problem in an optimal way?

I need to develop a function which finds consecutive factors of the given number and then the function will return the smallest of these consecutive numbers.
I tried to solve a Codility question. (I submitted my solution)
I need to develop the solution function.
def solution(N):
# write your code in Python 3.6
pass
An example:
If N is 6, the function will return 2 (because of 6 = 2 * 3)
If N is 20, the function will return 4 (because of 20 = 4 * 5)
If N is 29, the function will return 0
I developed the solution function (by checking all the numbers from 1 up to N, brute force search) and it works.
However, when the argument of the solution function is too big, the execution of the function takes too much time. Codility Python engine is running the function for a while and then it is throwing TIMEOUT ERROR.
What may be an optimal solution for this problem?
Thank you
I developed the function but it is not optimized.
def solution(N):
for i in range(1,N+1):
if i * (i+1) == N:
return i
return 0
When N is too big like 12,567,543, the function execution takes too much time.
After my comment, I thought a little bit about the question.
If you have an integer, N, and two consecutive factors, m and m+1, then it MUST be true that m < sqrt(N) and m + 1 > sqrt(N)
Therefore, all you have to do is check if the floor of the square root times the ceiling of the square root is equal to your original number..
import math
def solution(N):
n1 = math.floor(math.sqrt(N))
n2 = n1 + 1 # or n2 = math.ceil(math.sqrt(N))
if n1*n2 == N:
return n1
return 0
This has a run time of O(1).
import math
import math
def mysol(n):
s = math.sqrt(n)
if math.floor(s) * math.ceil(s) == n:
return math.floor(s)
else:
return 0

make change in python (maximum recursion depth exceeded in comparison)

So I have a recursive solution to the make change problem that works sometimes. It is:
def change(n, c):
if (n == 0):
return 1
if (n < 0):
return 0;
if (c + 1 <= 0 and n >= 1):
return 0
return change(n, c - 1) + change(n - coins[c - 1], c);
where coins is my array of coins. For example [1,5,10,25]. n is the amount of coins, for example 1000, and c is the length of the coins array - 1. This solution works in some situations. But when I need it to run in under two seconds and I use:
coins: [1,5,10,25]
n: 1000
I get a:
RecursionError: maximum recursion depth exceeded in comparison
So my question is, what would be the best way to optimize this. Using some sort of flow control? I don't want to do something like.
# Set recursion limit
sys.setrecursionlimit(10000000000)
UPDATE:
I now have something like
def coinss(n, c):
if n == 0:
return 1
if n < 0:
return 0
nCombos = 0
for c in range(c, -1, -1):
nCombos += coinss(n - coins[c - 1], c)
return nCombos
but it takes forever. it'd be ideal to have this run under a second.
As suggested in the answers above you could use DP for a more optimal solution.
Also your conditional check -
if (c + 1 <= 0 and n >= 1)
should be
if (c <= 1 ):
as n will always be >=1 and c <= 1 will prevent any calculations if the number of coins is lesser than or equal to 1.
While using recursion you will always run into this. If you set the recursion limit higher, you may be able to use your algorithm on a bigger number, but you will always be limited. The recursion limit is there to keep you from getting a stack overflow.
The best way to solved for bigger change amounts would be to swap to an iterative approach. There are algorithms out there, wikipedia:
https://en.wikipedia.org/wiki/Change-making_problem
Note that you have a bug here:
if (c + 1 <= 0 and n >= 1):
is like
if (c <= -1 and n >= 1):
So c can be 0 and pass to the next step where you pass c-1 to the index, which works because python doesn't mind negative indexes but still false (coins[-1] yields 25), so your solution sometimes prints 1 combination too much.
I've rewritten your algorithm with recursive and stack approaches:
Recursive (fixed, no need for c at init thanks to an internal recursive method, but still overflows the stack):
coins = [1,5,10,25]
def change(n):
def change_recurse(n, c):
if n == 0:
return 1
if n < 0:
return 0;
if c <= 0:
return 0
return change_recurse(n, c - 1) + change_recurse(n - coins[c - 1], c)
return change_recurse(n,len(coins))
iterative/stack approach (not dynamic programming), doesn't recurse, just uses a "stack" to store the computations to perform:
def change2(n):
def change_iter(stack):
result = 0
# continue while the stack isn't empty
while stack:
# process one computation
n,c = stack.pop()
if n == 0:
# one solution found, increase counter
result += 1
if n > 0 and c > 0:
# not found, request 2 more computations
stack.append((n, c - 1))
stack.append((n - coins[c - 1], c))
return result
return change_iter([(n,len(coins))])
Both methods return the same values for low values of n.
for i in range(1,200):
a,b = change(i),change2(i)
if a != b:
print("error",i,a,b)
the code above runs without any error prints.
Now print(change2(1000)) takes a few seconds but prints 142511 without blowing the stack.

Two trigonometry-based turtle codes not giving similar output

This is my first time posting a question.
I'm having trouble creating a code involving cosine, and I am not recieving the desired outcome. What is even more confusing is the fact that the two codes should be creating similar images (Explained later). Any ideas?
In the code below, these variables represent:
Y is a counter, making sure that the code only runs until the specified amount of radi is produced.
W is the colour randomly generated.
Z is the angle turn from 0 degrees. (The turtle's angle resets due to turtle.home).
Adjacent is the smallest length from centre to a line.
Radi is the amount of lines protruding from the centre.
def Triangle(Radi, Adjacent):
y = 0
if (Radi) % 1 == 0:
while (Radi) > y:
y = y + 1
w = randhex()
z = 360/(Radi)*y
turtle.left(z+30)
turtle.color(w)
if z > 300:
turtle.forward(Adjacent/math.cos(math.pi*(60 - (z - 300))/180))
elif z > 240:
turtle.forward(Adjacent/math.cos(math.pi*(z - 240)/180))
elif z > 180:
turtle.forward(Adjacent/math.cos(math.pi*(60 - (z - 180))/180))
elif z > 120:
turtle.forward(Adjacent/math.cos(math.pi*(z - 120)/180))
elif z > 60:
turtle.forward(Adjacent/math.cos(math.pi*(60 - (z - 60))/180))
else:
turtle.forward(Adjacent/math.cos(math.pi*z/180))
turtle.home()
Above is my first code which appears to work, giving these results when Triangle(100,180) is entered (Please note that randhex() is a custom function that generates random colours).
Triangle(100,180) results.
My apologies if my variable naming creativity is annoying.
In this code, counter represents 'y' and angle represents 'z' from the previous code
Here is my second code:
def Polygon(Radi, Adjacent, Sides):
counter = 0
if Sides % 1 != 0 or Sides == 2 or Sides <= 0:
print ("INVALID")
elif Sides == 1:
while Radi > counter:
counter = counter + 1
colour = randhex()
turn = 360/Radi*counter
turtle.left(turn)
turtle.color(colour)
turtle.forward(Adjacent)
turtle.home()
else:
while Radi > counter:
counter = counter + 1
colour = randhex()
turn = 360/Radi*counter
turtle.left(turn)
turtle.color(colour)
segment = str(counter/Radi*Sides*2)
position = segment.index('.')
test = int(segment[:position])
if test % 2 == 1:
length = Adjacent/math.cos(math.pi*(turn - (360 - 360/Sides*((test+1)/2)))/180)
turtle.forward(length)
else:
length = Adjacent/math.cos(math.pi*(180/Sides - (turn - (360 - 180/Sides*(test+1))))/180)
turtle.forward(length)
turtle.home()
Above is my second code, being the one I'm struggling with. Once again, apologies for my variable names being annoying and some of the maths not simplified. I find it easier to see how my ideas make sense when I leave them as they are. Below are my results for my second code after entering Polygon(180,100,3).
Polygon(180,100,3) results.
As you can see, it didn't go quite how I was planning.
I should also note that I tried substituting the numbers into the codes where one of the codes were giving a different line length. Sometimes they even went in an opposite direction (because the number came out negative). I did this on the Google calculator, but it seemed that both codes would give the same answer, but they corresponded to what the second code was outputing, not the first.
If you want me to explain anything leave a comment.
But if it turns out that my code is wrong (Which I believe), could you please point me to what I need to do instead.
I'd appreciate the help.
Your code is too complicated to debug. The unhelpful variable names, the lack of comments and excessively long equations make it hard to read.
If we consider the equation suggested in this answer to Is there an equation to describe regular polygons? then your original triangle code simplifies to:
import math
import turtle
def randhex():
""" substitute random color generator here """
return 'red'
def triangle(radii, adjacent):
if radii % 1 != 0: # only whole numbers (int or float) allowed
return
counter = 1
while counter <= radii:
angle = counter * (2 * math.pi / radii)
turtle.setheading(angle)
colour = randhex()
turtle.color(colour)
radius = adjacent / math.cos(angle % (math.pi / 1.5) - math.pi / 3)
turtle.forward(radius)
turtle.backward(radius)
counter += 1
turtle.radians() # avoid individual conversions, switch to radians
triangle(100, 180)
turtle.exitonclick()
And the general polygon solution can be achieved with just a few changes:
import math
import turtle
def randhex():
""" substitute random color generator here """
return 'red'
def polygon(radii, adjacent, sides):
if radii % 1 != 0: # only whole numbers (int or float) allowed
return
if sides % 1 != 0 or sides == 2 or sides <= 0:
return
counter = 1
while counter <= radii:
angle = counter * (2 * math.pi / radii)
turtle.setheading(angle)
colour = randhex()
turtle.color(colour)
if sides == 1: # special case, a circle
radius = adjacent
else:
radius = adjacent / math.cos(angle % (math.pi / (sides / 2)) - math.pi / sides)
turtle.forward(radius)
turtle.backward(radius)
counter += 1
turtle.radians() # avoid individual conversions, switch to radians
polygon(100, 180, 3)
turtle.exitonclick()
With polygon(100, 90, 5) looking like:

split a value into values in max, min range

I want to find an efficient algorithm to divide an integer number to some value in a max, min range. There should be as less values as possible.
For example:
max = 7, min = 3
then
8 = 4 + 4
9 = 4 + 5
16 = 5 + 5 + 6 (not 4 + 4 + 4 + 4)
EDIT
To make it more clear, let take an example. Assume that you have a bunch of apples and you want to pack them into baskets. Each basket can contain 3 to 7 apples, and you want the number of baskets to be used is as small as possible.
** I mentioned that the value should be evenly divided, but that's not so important. I am more concerned about less number of baskets.
This struck me as a fun problem so I had a go at hacking out a quick solution. I think this might be an interesting starting point, it'll either give you a valid solution with as few numbers as possible, or with numbers as similar to each other as possible, all within the bounds of the range defined by the min_bound and max_bound
number = int(input("Number: "))
min_bound = 3
max_bound = 7
def improve(solution):
solution = list(reversed(solution))
for i, num in enumerate(solution):
if i >= 2:
average = sum(solution[:i]) / i
if average.is_integer():
for x in range(i):
solution[x] = int(average)
break
return solution
def find_numbers(number, division, common_number):
extra_number = number - common_number * division
numbers_in_solution = [common_number] * division
if extra_number < min_bound and \
extra_number + common_number <= max_bound:
numbers_in_solution[-1] += extra_number
elif extra_number < min_bound or extra_number > max_bound:
return None
else:
numbers_in_solution.append(extra_number)
solution = improve(numbers_in_solution)
return solution
def tst(number):
try:
solution = None
for division in range(number//max_bound, number//min_bound + 1): # Reverse the order of this for numbers as close in value to each other as possible.
if round (number / division) in range(min_bound, max_bound + 1):
solution = find_numbers(number, division, round(number / division))
elif (number // division) in range(min_bound, max_bound + 1): # Rarely required but catches edge cases
solution = find_numbers(number, division, number // division)
if solution:
print(sum(solution), solution)
break
except ZeroDivisionError:
print("Solution is 1, your input is less than the max_bound")
tst(number)
for x in range(1,100):
tst(x)
This code is just to demonstrate an idea, I'm sure it could be tweaked for better performance.

Resources