I am trying to write a tree growing algorithm where Trees go through 2 cycles of growth every year. The first growth cycle occurs during the spring, when it doubles in height. The second growth cycle occurs during the summer, when its height increases by 1 meter.
The problem I have is that Now, a new Tree is planted at the onset of spring. Its height is 1 meter. I want to find the height of the tree after N growth cycles?
I was doing some research on recursive functions where the function is calling it self. I here it makes the code you write more elegant and simple then while loops. I am having problems execute this function though
n = input('How long would you like the tree to for?: ')
def cycle(n):
if n == 0:
n = + 1
return n
print '/n' # The reason for all the '/n' is just for neatness.
print('The tree will be ' + n + 'Ft tall')
elif n % 2 == 0:
n = 1 + cycle(n - 1)
return n
print '/n'
print('The tree will be ' + n + 'Ft tall')
elif n % 2 != 0:
n = 2 * cycle(n - 1)
return n
print '/n'
print('The tree will be ' + n + ' Ft tall')
cycle(n)
Your variable n also conflates height of the tree with the cycles of growth. You should instantiate distinct variables for distinct measurements! Also, n is being modified at all levels of the stack, likely causing the erroneous output.
Recursive calls can make algorithms more elegant, but they are also almost always less intuitive than the non-recursive solution. My recommendation to a beginning student is to solve the problem iteratively and then translate the iterative algorithm to its recursive form.
I do not believe a recursive function is the best way to go for this program. Also, for your first line, you should use int(input()), not just input(). Although, if you do wish to use recursive functions, here is my code for the program:
n = int(input("How many years does the tree grow? "))
def cycle(s, height):
height *= 2
height += 1
s -= 1
if s != 0:
cycle(s, height)
else:
print("Your tree was", height, "meters.")
cycle(n, 1)
Related
The program asks the user for a number N.
The program is supposed to displays all numbers in range 0-N that are "super numbers".
Super number: is a number such that the sum of the factorials of its
digits equals the number.
Examples:
12 != 1! + 2! = 1 + 2 = 3 (it's not super)
145 = 1! + 4! + 5! = 1 + 24 + 120 (is super)
The part I seem to be stuck at is when the program displays all numbers in range 0-N that are "super numbers". I have concluded I need a loop in order to solve this, but I do not know how to go about it. So, for example, the program is supposed to read all the numbers from 0-50 and whenever the number is super it displays it. So it only displays 1 and 2 since they are considered super
enter integer: 50
2 is super
1 is super
I have written two functions; the first is a regular factorial program, and the second is a program that sums the factorials of the digits:
number = int(input ("enter integer: "))
def factorial (n):
result = 1
i = n * (n-1)
while n >= 1:
result = result * n
n = n-1
return result
#print(factorial(number))
def breakdown (n):
breakdown_num = 0
remainder = 0
if n < 10:
breakdown_num += factorial(n)
return breakdown_num
else:
while n > 10:
digit = n % 10
remainder = n // 10
breakdown_num += factorial(digit)
#print (str(digit))
#print(str(breakdown_num))
n = remainder
if n < 10 :
#print (str(remainder))
breakdown_num += factorial(remainder)
#print (str(breakdown_num))
return breakdown_num
#print(breakdown(number))
if (breakdown(number)) == number:
print(str(number)+ " is super")
Existing answers already show how to do the final loop to tie your functions together. Alternatively, you can also make use of more builtin functions and libraries, like sum, or math.factorial, and for getting the digits, you can just iterate the characters in the number's string representation.
This way, the problem can be solved in a single line of code (though it might be better to move the is-super check to a separate function).
def issuper(n):
return sum(math.factorial(int(d)) for d in str(n)) == n
N = 1000
res = [n for n in range(1, N+1) if issuper(n)]
# [1, 2, 145]
First I would slightly change how main code is executed, by moving main parts to if __name__ == '__main__', which will execute after running this .py as main file:
if __name__ == '__main__':
number = int(input ("enter integer: "))
if (breakdown(number)) == number:
print(str(number)+ " is super")
After that it seems much clearer what you should do to loop over numbers, so instead of above it would be:
if __name__ == '__main__':
number = int(input ("enter integer: "))
for i in range(number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
Example input and output:
enter integer: 500
1 is super
2 is super
145 is super
Small advice - you don't need to call str() in print() - int will be shown the same way anyway.
I haven't done much Python in a long time but I tried my own attempt at solving this problem which I think is more readable. For what it's worth, I'm assuming when you say "displays all numbers in range 0-N" it's an exclusive upper-bound, but it's easy to make it an inclusive upper-bound if I'm wrong.
import math
def digits(n):
return (int(d) for d in str(n))
def is_super(n):
return sum(math.factorial(d) for d in digits(n)) == n
def supers_in_range(n):
return (x for x in range(n) if is_super(x))
print(list(supers_in_range(150))) # [1, 2, 145]
I would create a lookup function that tells you the factorial of a single digit number. Reason being - for 888888 you would recompute the factorial of 8 6 times - looking them up in a dict is much faster.
Add a second function that checks if a number isSuper() and then print all that are super:
# Lookup table for single digit "strings" as well as digit - no need to use a recursing
# computation for every single digit all the time - just precompute them:
faks = {0:1}
for i in range(10):
faks.setdefault(i,faks.get(i-1,1)*i) # add the "integer" digit as key
faks.setdefault(str(i), faks [i]) # add the "string" key as well
def fakN(n):
"""Returns the faktorial of a single digit number"""
if n in faks:
return faks[n]
raise ValueError("Not a single digit number")
def isSuper(number):
"Checks if the sum of each digits faktorial is the same as the whole number"
return sum(fakN(n) for n in str(number)) == number
for k in range(1000):
if isSuper(k):
print(k)
Output:
1
2
145
Use range.
for i in range(number): # This iterates over [0, N)
if (breakdown(number)) == number:
print(str(number)+ " is super")
If you want to include number N as well, write as range(number + 1).
Not quite sure about what you are asking for. From the two functions you write, it seems you have solid knowledge about Python programming. But from your question, you don't even know how to write a simple loop.
By only answering your question, what you need in your main function is:
for i in range(0,number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
import math
def get(n):
for i in range(n):
l1 = list(str(i))
v = 0
for j in l1:
v += math.factorial(int(j))
if v == i:
print(i)
This will print all the super numbers under n.
>>> get(400000)
1
2
145
40585
I dont know how efficient the code is but it does produce the desired result :
def facto():
minr=int(input('enter the minimum range :')) #asking minimum range
maxr=int(input('enter the range maximum range :')) #asking maximum range
i=minr
while i <= maxr :
l2=[]
k=str(i)
k=list(k) #if i=[1,4,5]
for n in k: #taking each element
fact=1
while int(n) > 0: #finding factorial of each element
n=int(n)
fact=fact*n
n=n-1
l2.append(fact) #keeping factorial of each element eg : [1,24,120]
total=sum(l2) # taking the sum of l2 list eg 1+24+120 = 145
if total==i: #checking if sum is equal to the present value of i.145=145
print(total) # if sum = present value of i than print the number
i=int(i)
i=i+1
facto()
input : minr =0 , maxr=99999
output :
1
2
145
40585
I have made some code that calculates prime numbers (Nothing special I know) and as expected it slows down the bigger the number, I know it is impossible to make it the same speed no matter the number but I am sure I could improve it's speed, I just don't know how...
import time
number = 1000000001
count = 0
start = time.time()
while number > 1000000000 and number < 10000000000000:
for i in range(1, round(number/2 + 1)):
if (number / i).is_integer():
count += 1
if count > 1:
break
if count < 2:
print(str(number) + ' prime')
number = number + 1
count = 0
end = time.time()
print(end - start)
Several things:
you do not have to check from 1, but 3, 5 and all odd numbers;
you do not have to check until n/2, but you can stop at sqrt(n);
do not use division, since then you work with floating points, but use % to check modulo;
you only have to check odd numbers (or two); and
you can omit the greater than check in the while loop, since the number only increments.
So an improved version would be:
import time
from math import sqrt # import square root
start = time.time()
for number in range(1000000001,10000000000000,2): # use for, hops of 2
for i in range(3, int(sqrt(number))+1,2): # check 3, 5,... up to sqrt(n)
if number % i == 0: # use modulo checks instead of floating point
break
else: # use a for-else structure for faster ending
print(str(number) + ' prime')
count = 0
end = time.time()
print(end - start)
Nevertheless, Python is not designed to get the most out of a CPU. If you really want to code a superoptimized algorithm, you will have to pick a faster (and less convenient) programming language.
number1 = int(input('Number #1: '))
number2 = int(input('Number #2: '))
l = len(str(number1))
l1 = len(str(number2))
print()
def addition():
print(' ',max(number1,number2))
print('+')
print(' ',min(number1,number2))
print('-'*(max(l,l1)+2))
print(' ')
print(' ',number1+number2)
def carries():
while (int(str(number1)[::-1])+int(str(number2)[::-1]))>=10:
carries = 0
carries = carries + 1
return carries
addition()
print()
print('Carries : ',carries())
I am trying to make a program that does the addition of two user input numbers and calculates the answer while also stating how many carries there are. Carries being if 9+8=17, then there would be 1 carry and so forth. I am having issues with having my program go beyond 1 carry. So this program so far is only applicable for user input numbers that when added are below 99. If you could explain to me how I would go about altering this program to make it applicable to any numbers, that would be great. I was thinking about using the len(number1) and len(number2) and then inputting the string of the user input backwards so it would look like str(number1[::-1])) but I do not think it works like that.
Fun one-liner solution
def numberOfCarryOperations(a, b):
f=lambda n:sum(map(int,str(n)));return(f(a)+f(b)-f(a+b))/9
# f is the digitSum function :)
Explanation
Asserting a,b >=0, you can proof mathematically: every time you have a carry, the digitSum decreases by 9.
9, because we are in number system 10, so we "lose 10" on one digit if we have carry, and we gain +1 as the carry.
Readable solution
def digitSum(n):
return sum(map(int,str(n)))
def numberOfCarryOperations(a, b)
# assert(a >= 0); assert(b >= 0);
return (digitSum(a) + digitSum(b) - digitSum(a+b)) / 9
I rewrote your carry function so it works, but the implementation is totally different. You first make the numbers strings so you can iterate through them. Then you make them equal length by appending 0's, and loop through each digit to check whether their sum (plus the carry) is over 9. If it is, increment the counter. Hope this helps:
number1 = int(input('Number #1: '))
number2 = int(input('Number #2: '))
l = len(str(number1))
l1 = len(str(number2))
print()
def addition():
print(' ',max(number1,number2))
print('+')
print(' ',min(number1,number2))
print('-'*(max(l,l1)+2))
print(' ')
print(' ',number1+number2)
def carries():
num1 = str(number1)
num2 = str(number2)
carry = 0
carries = 0
c1 = l
c2 = l
if (l < l1):
while (c1 < l1):
num1 = '0' + num1
c1+=1
if (l1 < l):
while (c2 < l):
num2 = '0' + num2
c2+=1
i = c1
while (i > 0):
if (int(num1[i-1])+int(num2[i-1])+carry > 9):
carry = 1;
carries+=1
else:
carry = 0
i-=1
return carries
addition()
print()
print('Carries : ',carries())
Edited with quick fix
Your while loop is fatally flawed.
You set carries to 0 every time, and then add 1, so there's no way to return anything but 0.
The return is inside the loop, so you will always return after the first iteration.
If the ones digits don't provide a carry, then you never get into the loop, and return None.
You don't provide for multiple carries, such as the three carries in 999 + 1.
If you remove the return from the while loop, you have an infinite loop: the terms of the condition never change. You don't iterate through anything.
You gave a function and a variable the same name. This is not good practice.
Here's a start for you, based loosely on your original routine.
Set the count of carries to 0.
Convert the two numbers to strings and find the common (shorter) length.
So long as you have digits in both numbers, grab the digits (moving from the right end) and see whether their numeric sum requires a carry. If so, increment the count.
def carries():
carry_count = 0
str1 = str(number1)
str2 = str(number2)
for digit_pos in range(1, min(len(str1), len(str2)) + 1):
if int(str1[-digit_pos]) + int(str2[-digit_pos]) >= 10:
carry_count += 1
return carry_count
Sample output:
Number #1: 77077
Number #2: 4444
77077
+
4444
-------
81521
Carries : 3
This still has deficiencies for you to fix. Most notably, it doesn't handle multiple carries. However, it should get you moving toward a solution.
Im new to programming and python. I need help with coding a geometric progression thats supposed to calculate the progression 1,2,4,8,16... Heres what I have so far:
def work_calc (days_worked, n):
temp=int(1)
if days_worked<2:
print (1)
else:
while temp <= days_worked:
pay1 = (temp**2)
pay = int(0)
pay += pay1
temp +=1
print ('your pay for ',temp-1,'is', pay1)
main()
Right now it gives me this output: 1, 4, 9, 16, 25
i need : 1,2,4,8,16,32...
im writing code that basically should do this:
Example:
Enter a number: 5
your value 1 is: 1
your value 2 is : 2
your value 3 is : 4
your value 4 is : 8
your value 5 is : 16
your total is: 31
Thanks in advance for your help and guidance!
P.S: Im like a dumb blonde sometimes(mostly) when it comes to programming, so thanks for your patience..
As I said, looks like you need powers of 2:
def work_calc (days_worked, n):
for temp in range(days_worked):
print ('your pay for ', temp + 1, 'is', 2 ** temp)
if you want to print strings (not tuples as you're doing now):
def work_calc (days_worked):
for temp in range(days_worked):
print 'your pay for {} is {}'.format(temp + 1, 2 ** temp)
>>> work_calc(5)
your pay for 1 is 1
your pay for 2 is 2
your pay for 3 is 4
your pay for 4 is 8
your pay for 5 is 16
Just to note - your code is calculating squares of temp, not powers of 2 that's why is not working
I understand this is probably overkill for what you are looking to do and you've been given great advice in the other answers in how to solve your problem but to introduce some other features of python here are some other approaches:
List comprehension:
def work_calc(days):
powers_of_two = [2**x for x in range(days)]
for i, n in enumerate(powers_of_two):
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(sum(powers_of_two)))
This is compact and neat but would hold the whole list of 2^n in memory, for small n this is not a problem but for large could be expensive. Generator expressions are very similar to list comprehensions but defer calculation until iterated over.
def work_calc(days):
powers_of_two = (2**x for x in range(days))
total = 0
for i, n in enumerate(powers_of_two):
total += n
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(total))
Had to move the total to a rolling calculation and it still calculates 2**n each time, a generator function would avoid power calculation:
import itertools
def powers_of_two():
n = 1
while True:
yield n
n *= 2
def work_calc(days):
total = 0
for i, n in enumerate(itertools.islice(powers_of_two(), days)):
total += n
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(total))
As I said overkill, but hopefully introduces some of the other features of python.
Is this a homework question? (insufficient rep to comment)
In the sequence 1,2,4,8,16,32 each term is double the previous term.
So, you can keep a record of the previous term and double it to get the next one.
As others have mentioned, this is the same as as calculating 2^n (not, as I previously stated, n^2) , where n is the number of terms.
print ('your pay for 1 is' 1)
prevpay = 1
while temp <= days_worked:
pay1 = prevpay*2
pay = int(0)
pay += pay1
temp +=1
prevpay = pay1
print ('your pay for ',temp-1,'is', pay1)
That is all too complicated. Try always to keep things as simple as possible and especially, keep your code readable:
def main():
i = int(input("how many times should I double the value? "))
j = int(input("which value do you want to be doubled? "))
double_value(i,j)
def double_value(times,value):
for i in range(times):
i += 1
value = value + value
print(f"{i} --- {value:,}")
main()
Hope I could help.
I am now doing the MIT opencourse thing, and already the second assignment, I feel it has left me out in the cold. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/assignments/pset1a.pdf
The specifics of it, are to write something that can calculate the 1000th prime number. We only know about the print, ==, =, 1=,if, else, elif, while, %, -,+,*,/, commands I think. We also don't yet know about importing libraries.
My Idea of how it would work is to take an odd number and try to divide it by, 3,4,5,6,7,8,9 and if %n !=0, then add a number to NumberofPrimes variable starting with 11 as the base of the tests, and assigning it a base value of 4 at the base of NumberofPrimes, though I don't know if that is even right, because I wouldn't know how to display the 1000th prime number.
Am I close?
The latest incarnation of it is as follows:
##calculate the 1000th prime number
potprime = 3
numberofprime = 1
cycle = if potprime%3 = 0:
break
if potpimre%4 = 0:
break
if potprime%5 = 0:
break
if potprime%6 = 0:
break
if potprime%7 = 0:
break
if potprime%8 = 0:
break
if potprime%9 = 0:
break
numberofprime + 1
potprime + 1
if potprime%2 == 0:
potprime = potprime + 1
if potprime != 0:
cycle
Where exactly am I going wrong? Walk me through it step by step. I really want to learn it, though I feel like I am just being left out in the cold here.
At this point, it would be more beneficial for me to see how a proper one could be done rather than doing this. I have been working for 3 hours and have gotten nowhere with it. If anybody has a solution, I would be more than happy to look at it and try to learn from that.
Looks like I am late
It is quite straight forward that if a number is not divisible by any prime number, then that number is itself a prime number. You can use this fact to minimize number of divisions.
For that you need to maintain a list of prime numbers. And for each number only try to divide with prime numbers already in the list. To optimize further it you can discard all prime numbers more than square root of the number to be tested. You will need to import sqrt() function for that.
For example, if you test on 1001, try to test with 3, 5, 7, 11, 13, 17, 19, 23, 29 and 31. That should be enough. Also never try to find out if an even number is prime. So basically if you test an odd number n, then after that test next number: (n + 2)
Have tested the below code. The 1000th prime number is 7919. Not a big number!!
Code may be like:
from math import sqrt
primeList = [2]
num = 3
isPrime = 1
while len(primeList) < 1000:
sqrtNum = sqrt(num)
# test by dividing with only prime numbers
for primeNumber in primeList:
# skip testing with prime numbers greater than square root of number
if num % primeNumber == 0:
isPrime = 0
break
if primeNumber > sqrtNum:
break
if isPrime == 1:
primeList.append(num)
else:
isPrime = 1
#skip even numbers
num += 2
# print 1000th prime number
print primeList[999]
The following code is gross, but since 1000 is indeed a small index, it solves your problem in a fraction of a second (and it uses only the primitives you are supposed to know so far):
primesFound = 0
number = 1
while primesFound < 1000:
number = number + 1 # start from 2
# test for primality
divisor = 2
numberIsPrime = True
while divisor*divisor <= number: # while divisor <= sqrt(number)
if number % divisor == 0:
numberIsPrime = False
break
divisor = divisor + 1
# found one?
if numberIsPrime:
primesFound = primesFound + 1
print number
You can test the solution here.
Now you should find a more efficient solution, optimize and maybe go for the 1000000-th prime...
For one thing, I'm pretty sure that in Python, if you want to have an if statement that tests whether or not A = B, you need to use the == operator, rather then the =.
For another thing, your algorithm would consider the number 143 to be prime, even though 143 = 11 * 13
You need keep track of all the prime numbers that you have already computed - add them to an array. Use that array to determine whether or not a new number that you are testing is prime.
It seems to me that you are jumping into the deep-end after deciding the kiddy-pool is too deep. The prime number project will be assignment 2 or 3 in most beginning programming classes, just after basic syntax is covered. Rather than help you with the algorithm (there are many good ones out there) I'm going to suggest that you attempt to learn syntax with the python shell before you write long programs, since debugging a line is easier than debugging an entire program. Here is what you wrote in a way that will actually run:
count = 4
n = 10 #I'm starting you at 10 because your method
#says that 2, 3, 5, and 7 are not prime
d = [2, 3, 4, 5, 6, 7, 8, 9] #a list containing the ints you were dividing by
def cycle(n): #This is how you define a function
for i in d: #i will be each value in the list d
if not n%i: #this is equal to if n%i == 0
return 0 #not prime (well, according to this anyway)
return 1 #prime
while count < 1000:
count += cycle(n) #adds the return from cycle to count
n += 1
print n - 1
The answer is still incorrect because that is not how to test for a prime. But knowing a little syntax would at least get you that wrong answer, which is better than a lot of tracebacks.
(Also, I realize lists, for loops, and functions were not in the list of things you say you know.)
Your code for this answer can be condensed merely to this:
prime_count = 1
start_number = 2
number_to_check = 2
while prime_count <= 1000:
result = number_to_check % start_number
if result > 0:
start_number +=1
elif result == 0:
if start_number == number_to_check:
print (number_to_check)
number_to_check +=1
prime_count +=1
start_number =2
else:
number_to_check +=1
start_number = 2
To answer your subsequent question, 'How do I keep track of all the prime numbers?
One way of doing this is to make a list.
primeList = [] # initializes a list
Then, each time you test a number for whether it is prime or not, add that number to primeList
You can do this by using the 'append' function.
primeList.append( potprime ) # adds each prime number to that list
Then you will see the list filling up with numbers so after the first three primes it looks like this:
>>> primeList
[11, 13, 17]
Your math is failing you. A prime number is a number that has 2 divisors: 1 and itself. You are not testing the numbers for primality.
I am very late on this but maybe my answer will be of use to someone. I am doing the same open course at MIT and this is the solution I came up with. It returns the correct 1000th prime and the correct 100,000th prime and various others in between that I have tested. I think this is a correct solution (not the most efficient I am sure but a working solution I think).
#Initialise some variables
candidate = 1
prime_counter = 1
while prime_counter < 1000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
print "The 1000th prime is: " + str(candidate)
While I was at it I went on and did the second part of the assignment. The question is posed as follows:
"There is a cute result from number theory that states that for sufficiently large n the product of the primes less than n is less than or equal to e^n and that as n grows, this becomes a tight bound (that is, the ratio of the product of the primes to e^n gets close to 1 as n grows).
Computing a product of a large number of prime numbers can result in a very large number,
which can potentially cause problems with our computation. (We will be talking about how
computers deal with numbers a bit later in the term.) So we can convert the product of a set of primes into a sum of the logarithms of the primes by applying logarithms to both parts of this conjecture. In this case, the conjecture above reduces to the claim that the sum of the
logarithms of all the primes less than n is less than n, and that as n grows, the ratio of this sum to n gets close to 1."
Here is my solution. I print the result for every 1,000th prime up to the 10,000th prime.
from math import *
#Initialise some variables
candidate = 1
prime_counter = 1
sum_logs = log(2)
while prime_counter < 10000:
test = 2
candidate = candidate + 2
# While there is a remainder the number is potentially prime.
while candidate%test > 0:
test = test + 1
# No remainder and test = candidate means candidate is prime.
if candidate == test:
prime_counter = prime_counter + 1
# If the number is prime add its log to the sum of logs.
sum_logs = sum_logs + log(candidate)
if prime_counter%1000 == 0:
# For every 1000th prime print the result.
print sum_logs," ",candidate," ",sum_logs/candidate
print "The 10000th prime is: " + str(candidate)
Cheers,
Adrian
I came up with this solution in my interview, but I didn't get the job :( It has about 1/100 less iterations than the solution above:
from math import *
MAX_IDX=1000
MAX_IDX-=1
num_iter=0
l_pirme_list=[3]
candidate=l_pirme_list[0]
prime_counter=1
while prime_counter < MAX_IDX:
candidate+=2
#Cut the binary number in half. This is quite faster than sqrt()
bin_candidate=format(candidate, "2b")
max_prime_search=int(bin_candidate[:len(bin_candidate)/2+1],2)+1
# max_prime_search=sqrt(candidate)+1
candidate_is_prime=1
for prime_item in l_pirme_list:
num_iter+=1
if candidate % prime_item==0:
candidate_is_prime=0
break
elif prime_item > max_prime_search:
candidate_is_prime=1
break
if candidate_is_prime:
prime_counter+=1
l_pirme_list.append(candidate)
l_pirme_list.insert(0,2)
print "number iterations=", num_iter
print l_pirme_list[MAX_IDX]