I'm not sure how to complete my code for the "persistence bugger" problem. The goal is to create a function called "persistence" to return the number of iterations until the digits of a number multiplied together equal a single-digit number.
For example: persistence(39) = 3, because 3*9 = 27, 2*7 = 14, and 1*4 = 4; hence, three iterations.
Below is my code so far, and I'm not sure where to go from here or if what I have is correct. Any help would be appreciated.
def persistence(num):
num_str = str(num)
total = 1
for i in num_str:
total = total * int(i)
while len(str(total)) <> 1:
total = total * total(i)
#not sure what to do from here...
You'll notice that if you want to do what you did to 39 to 27, you'll be repeating code. This is a case where recursion can help (calling the function in itself):
def persistence(num):
if num < 10:
return 0 # Only one digit. Can't iterate over it
num_str = str(num)
total = 1
for i in num_str:
total = total * int(i)
return 1 + persistence(total) # We do 1 + because we just did an iteration
Let's imagine the input was 39:
39 is not less than 10 so we go to the next stage.
We do the same code you provided to get the total of multiplying the digits
We now have a new number (27) allocated at total. We repeat the code above by calling the function again, but instead of passing 39, we pass through 27.
27 is not less than 10 so we go to the next stage
We get the multiplication of digits
We repeat until we get a total of 4 (1*4).
We call persistence(4), but it returns 0 because 4 < 10. No iteration has been done for the number 4 (hence we return 0)
At this point, recursion has stopped. Python now backtracks through all previous calls. It adds 0 + 1 + 1 + 1 to give 3.
Recursion is a little tricky to wrap your head around at first, but basically it's a function which calls itself, but it has "base cases" to stop the function running indefinitely. In this case, our base case is if the number is less than 10 (it has one digit). No iterations take place on this number.
TerryA's answer is really good, and when you want to keep applying the result of a function to the same function again (as in this example) recurssion is normally a very good idea. Just for the sake of completeness though, the solution can be implemented with a simple while loop, not too dissimilar to what you have attempted:
def persistance(num):
counter=0
while num>9:
counter+=1
num_str=str(num)
total=1
for i in num_str:
total=total* int(i)
num=total
print (counter)
The counter keeps track of how many times the loop runs, which gives you your final answer.
Related
I want to have a number that halves until it reaches 1, then it should return a count of how many times it halved.
example:
halve(4)
2
halve(11)
3
since 4/2 = 2 and 2/2= 1, hence it halved twice before reaching 1, and this is what I want it to return but my code isn't working, why? Can a modification be made ?
Here's my code
Python
def halve(n):
i = 0
for i in range(n,1):
if float(i/2) >=1:
i+=1
return i
Thanks,
It seems to me you can employ some math and just write:
import math
def halve(n):
return math.floor(math.log(n, 2))
You attempt is wrong for three reasons.
You are returning from within the loop. Thus it will never execute more than once.
Your loop will never execute unless n is 0 because range needs a third parameter as a negative number to increment "backwards."
The i assigned by your loop is shadowing the i you have previously assigned. Let's just use a while loop.
def halve(n):
i = 0
while n/2 >= 1:
i += 1
n /= 2
return i
Since you wanted to know what is wrong with your code:
First, immediate problem is that you return on first loop iteration. You need to return only when the number is smaller than 1 (so if condition is not met):
else:
return i
Now, there is another problem - you are iterating over range(n,1) which... doesn't really make sense. You need way less than n divisions to reach number smaller than 1. Use a while loop instead - this way you loop as long as you need. You're also using i as an iterator, but also seem to be dividing it to see if it's more than one - shouldn't you use n there? You're also not reducing n, so you'd actually never reach n < 1.
Taking all of those your code might look like this:
while True:
if float(n/2) >=1:
i+=1
n /= 2
else:
return i
We can improve it even further - as you want your code to end if the condition is not met, we can simply move that to while condition:
def halve(n):
i = 0
while float(n/2) >=1:
i+=1
n /= 2
return i
As #Sembei Norimaki commented, a while loop is a more natural fit for this use case.
def halve(n):
halves = 0
while n > 1:
n /= 2
halves += 1
return halves
This loop can be summarized "As long as n is greater than one, cut it in half and add one to the number of halves we have performed."
Instructions are to write a function that returns all prime numbers below a certain max number. The function is_factor was already given, I wrote everything else.
When I run the code I don't get an error message or anything, it's just blank. I'm assuming there's something I'm missing but I don't know what that is.
def is_factor(d, n):
""" True if `d` is a divisor of `n` """
return n % d == 0
def return_primes(max):
result = []
i = 0
while i < max:
if is_factor == True:
return result
i += 1
You should test each i against all divisors smaller than math.sqrt(i). Use the inner loop for that. any collects the results. Don't return result right away, for you should fill it first.
def return_primes(max):
result = []
for i in range(2, max):
if not any(is_factor(j, i) for j in range(2, int(math.sqrt(i)) + 1)):
result.append(i)
return result
print(return_primes(10))
As a side note, use for and range rather than while to make less mistakes and make your code more clear.
The reason that your code is returning blank when you run it, is because you are comparing a function type to the value of True, rather than calling it.
print(is_factor)
<function is_factor at 0x7f8c80275dc0>
In other words, you are doing a comparison between the object itself rather than invoking the function.
Instead, if you wanted to call the function and check the return value from it, you would have to use parenthesis like so:
if(is_factor(a, b) == True):
or even better
if(is_factor(a, b)):
which will inherently check whether or not the function returns True without you needing to specify it.
Additionally, you are not returning anything in your code if the condition does not trigger. I recommend that you include a default return statement at the end of your code, not only within the condition itself.
Now, in terms of the solution to your overall problem and question;
"How can I write a program to calculate the prime numbers below a certain max value?"
To start, a prime number is defined by "any number greater than 1 that has only two factors, 1 and itself."
https://www.splashlearn.com/math-vocabulary/algebra/prime-number
This means that you should not include 1 in the loop, otherwise every single number is divisible by 1 and this can mess up the list you are trying to create.
My recommendation is to start counting from 2 instead, then you can add 1 as a prime number at the end of the function.
Before going over the general answer and algorithm, there are some issues in your code I'd like to address:
It is recommended to use a different name for your variable other than max, because max() is a function in python that is commonly used.
Dividing by 0 is invalid and can break the math within your program. It is a good idea to check the number you are dividing by to ensure it is not zero to make sure you do not run into math issues. Alternatively, if you start your count from 2 upwards, you won't have this issue.
Currently you are not appending anything into your results array, which means no results will be returned.
My recommendation is to add the prime number into the results array once it is found.
Right now, you return the results array as soon as you have calculated the first result. This is a problem because you are trying to capture all of the prime numbers below a specific number, and hence you need more than one result.
You can fix this by returning the results array at the end of the function, not in between, and making sure to append each of the prime numbers as you discover them.
You need to check every single number between 2 and the max number to see if it is prime. Your current code only checks the max number itself and not the numbers in between.
Now I will explain my recommended answer and the algorithm behind it;
def is_factor(d, n):
print("Checking if " + str(n) + " is divisible by " + str(d))
print(n % d == 0)
return n % d == 0
def return_primes(max_num):
result = []
for q in range(2, max_num+1):
count_number_of_trues = 0
for i in range(2, q):
if(i != q):
if(is_factor(i, q)):
print("I " + str(i) + " is a factor of Q " + str(q))
count_number_of_trues += 1
if(q not in result and count_number_of_trues == 0):
result.append(q)
result.append(1)
return sorted(result)
print(return_primes(10))
The central algorithm is that you want to start counting from 2 all the way up to your max number. This is represented by the first loop.
Then, for each of these numbers, you should check every single number from 2 up to that number to see if a divisor exists.
Then, you should count the number of times that the second number is a factor of the first number, and if you get 0 times at the end, then you know it must be a prime number.
Example:
Q=10
"Is I a factor of Q?"
I:
9 - False
8 - False
7 - False
6 - False
5 - True
4 - False
3 - False
2 - True
So for the number 10, we can see that there are 2 factors, 5 and 2 (technically 3 if you include 1, but that is saved for later).
Thus, because 10 has 2 factors [excluding 1] it cannot be prime.
Now let's use 7 as the next example.
Example:
Q=7
"Is I a factor of Q?"
I:
6 - False
5 - False
4 - False
3 - False
2 - False
Notice how every number before 7 all the way down to 2 is NOT a factor, hence 7 is prime.
So all you need to do is loop through every number from 2 to your max number, then within another loop, loop through every number from 2 up to that current number.
Then count the total number of factors, and if the count is equal to 0, then you know the number must be prime.
Some additional recommendations:
although while loops will do the same thing as for loops, for loops are often more convenient to use in python because they initialize the counts for you and can save you some lines of code. Also, for loops will take care of the incrementing process for you so there is no risk of forgetting.
I recommend sorting the list when you return it, it looks nicer that way.
Before adding the prime factor into your results list, check to see if it is already in the list so you don't run into a scenario where multiples of the same number is added (like [2,2,2] for example)
Please note that there are many different ways to implement this, and my example is but one of many possible answers.
I would like to create a computer program that starts at a given value and adds the same sum over and over again in a loop until the total sum reaches or exceeds a given limit.
For example: I start at the number 7. I add 3 over and over again until the total sum reaches or exceeds x (the limit). If my limit is 23, the program would stop at 25 and display that it went beyond the limit by 2.
We have two kinds of loops in Python: for-loop and while-loop
Usually we use while when we don't know how many times we are going to do something...Here since you have a condition, and you don't know in advance how many times you have to add the value 3 to your 7 to reach the limit, it's time to use while-loop.
initial = 7
add_value = 3
limit = 23
while initial < limit:
initial += add_value
print(initial)
In every iteration, the condition (the expression you write in front of while keyword) is evaluated. If it evaluates to True, the body of the while block is gonna be executed, otherwise Python jumps out of the while-loop block and execute the next line after it.
I know you are particularly asking for loops but I just wanted to say that this question can be solved using simple math operations:
initial = 7
add_value = 3
limit = 23
d, r = divmod(limit - initial, add_value)
if r == 0:
print(initial + add_value * d)
else:
print(initial + add_value * (d + 1))
You can achieve this using while-loop as follows:
start = 7
end = 23
add = 3
while start <= end:
start += add
if start == end:
print(“Ended at end value”)
else:
print(“Went beyond the limit by: ”, start-end)
Here, in while-loop, we check if the start value reaches or exceeds the limit using <= . When that’s not the case, the add value is added to the start value. When it reaches or exceeds it, the loop ends. If the program reaches exactly to the limit, it prints that “Ended at value”. Otherwise, it prints “Went beyond the limit by: X”.
I'm trying to solve a question from onlinejudge.org - The 3n + 1 Problem using Python.
in case the link doesn't load (that happens quite frequently), below is my summarized version of the question:
Consider the following algorithm:
input n
print n
if n = 1 then STOP
if n is odd then n <- 3n + 1
else n <- n/2
GOTO 2
Given the input 22, the following sequence of numbers will be printed
22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
In the example above, the cycle length of 22 is 16.
For any two numbers i and j you are to determine the maximum cycle length over all numbers between and including both i and j.
Sample Input
1 10
100 200
201 210
900 1000
Sample Output
1 10 20
100 200 125
201 210 89
900 1000 174
And here's my code.
inputText = input().split()
inputList=[]
for index in range(0, len(inputText), 2):
inputList.append([int(inputText[index]), int(inputText[index + 1])])
def CycleLen(num):
chainList = [num]
while num > 1:
chainList.append(num//2 if num % 2 == 0 else 3*num + 1)
num = chainList[-1]
return len(chainList)
for listSet in inputList:
countList = []
minRange = min(listSet[0], listSet[1])
maxRange = max(listSet[0], listSet[1])
for num in range(minRange, maxRange + 1):
countList.append(CycleLen(num))
countList.sort()
print(listSet[0], listSet[1], countList[-1])
I'm aware of the memorization solution to make it more time efficient, but I planned to implement that only if the question rejected my answer for exceeding time limit. However, I'm straight up getting the wrong answer, and I have no idea why.
I used uDebug to see if there are any mistakes, and searched for other's solution. The most confusing part is how the online judge submits its input - single line by line, or all the lines at once. Different sources claim different things.
Please help. Thank you!
Given your code actually does generate the correct results for the given samples, it's a safe bet you're not handling the input data correctly. And, in fact, the problem statement states (my emphasis):
The input will consist of a series of pairs of integers i and j, one pair of integers per line. All integers will be less than 10,000 and greater than 0.
You should process all pairs of integers and for each pair determine the maximum cycle length over all integers between and including i and j.
Hence, your code that gets only one pair will not be sufficient. The reason it only processes one pair has to do with a misunderstanding that the code:
inputText = input().split()
will give you all the input lines, as evidenced by the loop that tries to create a list of 2-tuples from each pair:
inputList=[]
for index in range(0, len(inputText), 2):
inputList.append([int(inputText[index]), int(inputText[index + 1])])
However, input() only reads one line of input (see here for details), meaning that you will only process the first line of the multi-line input. To do it properly, you need to continuously read and process lines until the file ends.
Having said that, you may also want to reconsider the use of a lists as your first step if it exceeds the time limit. It would be far easier to just maintain the current item and a count for calculating the cycle length (for the individual cycles) and just processing input lines sequentially (for the different ranges). Neither of those aspects requires an actual list.
Addressing both those list issues (and the one-line-of-input issue mentioned above), you would end up with something like:
def CycleLen(num):
# Start with one number, the one given.
curr = num
count = 1
# Until you get to 1, increase count and calculate next.
while curr > 1:
count += 1
curr = curr // 2 if curr% 2 == 0 else curr * 3 + 1
return count
while True:
# Reads a single line and splits into integers. Any problem, exit loop.
try:
inputInt = [int(item) for item in input().split()]
if len(inputInt) != 2: break
except:
break
# Find value in the range with the longest cycle then print it.
maxCycle = 0
for number in range(min(inputInt), max(inputInt) + 1):
maxCycle = max(maxCycle, CycleLen(number))
print(inputInt[0], inputInt[1], maxCycle)
This is for a school assignment.
I have been tasked to define a function determining the largest square pyramidal number up to a given integer(argument). For some background, these are square pyramidal numbers:
1 = 1^2
5 = 1^2+2^2
14 = 1^2+2^2+3^2
So for a function and parameter largest_square_pyramidal_num(15), the function should return 14, because that's the largest number within the domain of the argument.
I get the idea. And here's my code:
def largest_square_pyramidal_num(n):
sum = 0
i = 0
while sum < n:
sum += i**2
i += 1
return sum
Logically to me, it seemed nice and rosy until I realised it doesn't stop when it's supposed to. When n = 15, sum = 14, sum < n, so the code adds one more round of i**2, and n is exceeded. I've been cracking my head over how to stop the iteration before the condition sum < n turns false, including an attempt at break and continue:
def largest_square_pyramidal_num(n):
sum = 0
for i in range(n+1):
sum += i**2
if sum >= n:
break
else:
continue
return sum
Only to realise it doesn't make any difference.
Can someone give me any advice? Where is my logical lapse? Greatly appreciated!
You can do the following:
def largest_pyr(x):
pyr=[sum([i**2 for i in range(1,k+1)]) for k in range(int(x**0.5)+1)]
pyr=[i for i in pyr if i<=x]
return pyr[-1]
>>>largest_pyr(15)
14
>>> largest_pyr(150)
140
>>> largest_pyr(1500)
1496
>>> largest_pyr(15000)
14910
>>> largest_pyr(150000)
149226
Let me start by saying that continue in the second code piece is redundant. This instruction is used for scenario when you don't want the code in for loop to continue but rather to start a new iteration (in your case there are not more instructions in the loop body).
For example, let's print every number from 1 to 100, but skip those ending with 0:
for i in range(1, 100 + 1):
if i % 10 != 0:
print(i)
for i in range(1, 100 + 1):
if i % 10 == 0:
# i don't want to continue executing the body of for loop,
# get me to the next iteration
continue
print(i)
The first example is to accept all "good" numbers while the second is rather to exclude the "bad" numbers. IMHO, continue is a good way to get rid of some "unnecessary" elements in the container rather than writing an if (your code inside if becomes extra-indented, which worsens readability for bigger functions).
As for your first piece, let's think about it for a while. You while loop terminates when the piramid number is greater or equal than n. And that is not what you really want (yes, you may end up with a piramid number which is equal to n, but it is not always the case).
What I like to suggest is to generate a pyramid number until in exceedes n and then take a step back by removing an extra term:
def largest_square_pyramidal_num(n):
result = 0
i = 0
while result <= n:
i += 1
result += i**2
result -= i ** 2
return result
2 things to note:
don't use sum as a name for the variable (it might confuse people with built-in sum() function)
I swapped increment and result updating in the loop body (such that i is up-to-date when the while loop terminates)
So the function reads like this: keep adding terms until we take too much and go 1 step back.
Hope that makes some sense.
Cheers :)