Python 3 While Loop within a function - python

Write a function named powPosInt. This function will take two integer input parameters, named x and p. This function will compute the value of x to the power of p, where p >= 0, which is defined as x to the power of p = x × · · · × x
| {z }
p times
or 1 if p is 0.
The function will return this computed result. This function should not produce any console output.
For computing x to the power of p
, I am requiring that you implement the calculations using a while loop and an accumulator variable.
Examples of values you should test with: x = 2, p = 3 should return 8. x = 1, p = 4
should return 1. x = 7, p = 0 should return 1. x = −3, p = 2 should return 9.
x = −3, p = 3 should return −27.
This is what I have so far, I am having trouble figuring out how to put a while loop within this function. I am asking on here for help as my TEACHER will not assist, (he wants us to treat his class like the real world where we will have to figure out solutions on our own... why pay his salary right?)
def powPosInt(x,p):
number = p
count = 0
while (number != 0):
answer = (x**p)
count = count + 1
if (p<0):
answer = (x**(1/abs(p)))
return answer

Using accumulation means you need to create a variable that will store the result, and while loop will multiply it by x each step. You shouldn't use the ** operator.
steps = 0
result = 1
while (steps < p):
result *= x
steps += 1

def powPosInt(x,p):
number = p
count = 0
while (number != 0):
answer = (x**p)
count = count + 1
if (p<0):
answer = (x**(1/abs(p)))
return answer
I see a number of problems here:
A loop for calculating powers will be using repeated multiplication, not exponentiation. The intent here is to assume Python doesn't have an exponentiation operator, otherwise this assignment would be futile.
There's no reason to handle negative powers, the specifications clarly call for p >= 0. Hence your final if block is unnecessary.
This is a style issue only: you should get into the habit of using meaningful variable names. The only situation in which I use single-letter variables nowadays is a short-lived, non-nested, loop where the variable name is irrelevant (and I use i for that). For any other situation, I use explanatory names (yes, not even j or k for nested loops). And I'm even starting to move away from using i for these simple cases.
Having said all that, I'd suggest revisiting your solution to take those into account.
Once you've done so, you can refer to the code below for one solution:
def powPosInt(myBase, myPower):
result = 1
for _ in range(myPower):
result *= myBase
return result
And, if you wanted to go for extra credits(a), you could put in place contractual checks to ensure callers are doing the right thing:
def powPosInt(myBase, myPower):
if type(myBase) != int: raise TypeError("Base must be an integer")
if type(myPower) != int: raise TypeError("Power must be an integer")
if myPower < 1: raise ValueError("Power must be >= 1")
result = 1
for _ in range(myPower):
result *= myBase
return result
(a) Or risk losing marks for being a smart-alec. This depends very much on the personality of your teacher :-)

Related

Google foo.bar challenge "Hey I already did that", not passing all the test cases

This is the description of the problem I am trying to solve.
Hey, I Already Did That!
Commander Lambda uses an automated algorithm to assign minions randomly to tasks, in order to keep minions on their toes. But you've noticed a flaw in the algorithm -- it eventually loops back on itself, so that instead of assigning new minions as it iterates, it gets stuck in a cycle of values so that the same minions end up doing the same tasks over and over again. You think proving this to Commander Lambda will help you make a case for your next promotion.
You have worked out that the algorithm has the following process:
Start with a random minion ID n, which is a nonnegative integer of length k in base b
Define x and y as integers of length k. x has the digits of n in descending order, and y has the digits of n in ascending order
Define z = x - y. Add leading zeros to z to maintain length k if necessary
Assign n = z to get the next minion ID, and go back to step 2
For example, given minion ID n = 1211, k = 4, b = 10, then x = 2111, y = 1112 and z = 2111 - 1112 = 0999. Then the next minion ID will be n = 0999 and the algorithm iterates again: x = 9990, y = 0999 and z = 9990 - 0999 = 8991, and so on.
Depending on the values of n, k (derived from n), and b, at some point the algorithm reaches a cycle, such as by reaching a constant value. For example, starting with n = 210022, k = 6, b = 3, the algorithm will reach the cycle of values [210111, 122221, 102212] and it will stay in this cycle no matter how many times it continues iterating. Starting with n = 1211, the routine will reach the integer 6174, and since 7641 - 1467 is 6174, it will stay as that value no matter how many times it iterates.
Given a minion ID as a string n representing a nonnegative integer of length k in base b, where 2 <= k <= 9 and 2 <= b <= 10, write a function solution(n, b) which returns the length of the ending cycle of the algorithm above starting with n. For instance, in the example above, solution(210022, 3) would return 3, since iterating on 102212 would return to 210111 when done in base 3. If the algorithm reaches a constant, such as 0, then the length is 1.
My solution isn't passing 5 of the 10 test cases for the challenge. I don't understand if there's a problem with my code, as it's performing exactly as the problem asked to solve it, or if it's inefficient.
Here's my code for the problem. I have commented it for easier understanding.
def convert_to_any_base(num, b): # returns id after converting back to the original base as string
digits = []
while(num/b != 0):
digits.append(str(num % b))
num //= b
result = ''.join(digits[::-1])
return result
def solution(n, b):
minion_id_list = [] #list storing all occurrences of the minion id's
k = len(n)
while n not in minion_id_list: # until the minion id repeats
minion_id_list.append(n) # adds the id to the list
x = ''.join(sorted(n, reverse = True)) # gives x in descending order
y = x[::-1] # gives y in ascending order
if b == 10: # if number is already a decimal
n = str(int(x) - int(y)) # just calculate the difference
else:
n = int(x, b) - int(y, b) # else convert to decimal and, calculate difference
n = convert_to_any_base(n, b) # then convert it back to the given base
n = (k-len(n)) * '0' + n # adds the zeroes in front to maintain the id length
if int(n) == 0: # for the case that it reaches a constant, return 1
return 1
return len(minion_id_list[minion_id_list.index(n):]) # return length of the repeated id from
# first occurrence to the end of the list
I have been trying this problem for quite a while and still don't understand what's wrong with it. Any help will be appreciated.

Breaking an iterative function in Python before a condition turns False

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 :)

Code simplifcation using iteration and recursion

I would like to 1)simplify the code below using iteration 2)implement it using recursion
This code features an equation similar to the Fibonacci series the difference being the previous answer is multiplied by a function in this case just 2 by index.
The algorithm will input different images and calculate the total incremented points, the flattened optimal matrix will give the highest value.
Note that list_c should give the highest value.
sum_list=[]
list_a= [1,0,1,0,1]
list_b= [1,0,0,1,1]
list_c= [1,1,1,0,0]
def increment(input_list):
global i #i added it because i received an error
""" returns
Incrementing_answer = previous_answer + (list[i+1])
for which previous_answer begins with list[0]
if list[0] =0 then list[0]=-1
for example, list_a should be evaluated as follows
- ans = 1+2*(1)
= 3
- ans = 3+ 2*(0) --since since its 0 ,-1 is replaced
= 3+ 2*(-1)
= 1
- ans = 1+2(1)
=3
and so on
Incrementing_answers = sum_list=[3,1,3,1,3] =11
"""
for i in range(0,len(input_list)):
if input_list[i] == 0 :
input_list[i] == -1
ans = input_list[i]+2*input_list[i]
sum_list.append(ans)
else:
ans = ans+input_list[i]
sum_list.append(ans)
return sum(sum_list)
Previous answers have been helpful, the code above does not work
1)I would like corrections
2)Is it possible to solve the same problem using recursion
3) I also just realised the code does not work well for large arrays(preprocesed_images)
4) for lists or arrays that include floating points I get the error ('
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()')
3)Feedback on using good programming practices
4) Any additional advice on how to tackle the problem is Welcome, the inputted images will be captured using cv2 and the algorithm has to pick optimal images in real-time, to solve the puzzle.
Thanks very much in advance
Global variables are discouraged over passing arguments as parameters to function
Use of PEP 8 naming conventions is encouraged (i.e. name function increment rather than Increment)
Single letter variable names are discouraged (i.e. no idea of what a, l, p represents) (adopting Dan's comment below).
Code
def increment(a, l, p):
"""
Returns in an incrementing value ,using the formula a(n)=a(n)+l(i+1)
were a(n) starts with the starts with l[0] and then l(i+1)
"""
for i in range(len(l)):
if l[i] == 0: # equation
a += -2 # no change to l
else:
a += 2*l[i]
p.append(a)
return sum(p)
Usage
l = [1,0,1,0,1]
p=[]
a = 0
print(f'Increment: {increment(a, l, p)}')
print(f'l unchanged: {l}')
print(f'Updated p: {p}')
a = p[-1] # a is last p
print(f'Updated a: {a}')
Output
Increment: 6
l unchanged: [1, 0, 1, 0, 1]
Updated p: [2, 0, 2, 0, 2]
Updated a: 2
a doesn't need to be a global and p & l should be passed as argumets -in your version you tied your implementation of your function to the implementation of the calling code - a better implementation would be :
I don't fully understand why you need a at all, but I think this code does what you need :
def Increment( initial, results ):
"""
Returns in an incrementing value ,using the formula a(n)=a(n)+l(i+1)
were a(n) starts with the starts with l[0] and then l(i+1)
,if l[i]= 0,-1 is calculated instead.
"""
last = results[-1] if results else 0
for index, value in enumerate(initial):
term = -1 if value == 0 else value
last += 2* term
results.append(last)
return sum(results)
l = [1,0,1,0,1]
p=[]
r = Increment(initial=l, results=p)
print(r)
If you do need the a value outside the function it will just be p[-1]
I think the above code replicates the functionality, without changing your l list (which you indicated you didn't need.

Python While Loop Square

I am a beginner at Python and I'm trying to use a while loop to sum up all of the squared n values in a given n value range.
Code:
def problem2(n):
x = 0
y = 0
while x < n:
y = (n**2)+y
x+=1
return y
For some reason, this equation returns the input number cubed.
Can someone explain why this happens and how to fix it?
You need to perform the ** on x, the value that is being incremented:
def problem2(n):
x = 0
count = 0
while x < n:
count += pow(x, 2)
x += 1
return count
You keep squaring the same number n, instead of the one being incremented x.
def sum_of_squares(n):
sum = 0
for x in range(0, n):
sum += x*x
return sum
You also don't really need the while loop, avoiding having to manually keep track of which variable is the counting variable and which one is the result variable (which is what you are confusing, as explained e.g. by #Ajax1234 in their answer).
It is a lot more Pythonic to use the built-in function sum, a generator expression and range:
def problem2(n):
return sum(x**2 for x in range(n))
This would be a lot more readable and better (unless of course you are being forced to use while).
Looks good. You're almost there.
It makes it the cube root because you add y to (n**2) everytime. Because you code runs until x !< n it runs n times. That means that you add n**2 to n**2*n.
That means that it gives 1(n**2)*(n-1)(n**2) which equals n(n**2) = n**3
Hope this was clear enough.

How to better implement recurrence relations in code?

I've been struggling with this problem for a couple days now, I'm still new to Python and more math intensive coding so any help would be appreciated, just point me in the right direction :)
So the question was something like:
You have a movie pass which is valid for N days. You can use it in any way you want except for 3 consecutive days or more.
So basically, you can either use your pass on a given day or choose to not, meaning 2 raised to N total possibilities. The valid ways for claiming the pass are then 2 raised to N - invalidCases
You have to find the number of valid cases % (10^9+7)
I found a recurrence relation for the invalid cases which looked like
invalidCases(at_N) = 2^(n-4) + 2*invalidCases(at_N-1) - invalidCases(at_n-4)
So my first impulse was to simply use recursion:
def invalidCases(n):
if(n<3):
return 0;
elif(n==3):
return 1;
else:
return 2**(n-4)+ 2*invalidCases(n-1)- invalidCases(n-4)
Very inefficient, but my equation seemed correct.
My next attempt, I tried memoization, but I kept running into an error at N=1006.
So I changed the recursion limit.
My present attempt(with memoization and increased recursion limit)
import sys
sys.setrecursionlimit(10**6)
T=int(input());
#2**(n-4) + 2*ans(n-1)-ans(n-4)
memo={0:0,1:0,2:0,3:1,4:3,5:8,6:20,7:47} #
def ans(n):
#complete this function
if n not in memo:
memo[n]=(2**(n-4) + 2*ans(n-1)-ans(n-4));
return memo[n];
modulo = 10**9 + 7;
print((2**n-ans(n))%modulo);
Finally, my problem.
I need this code to work for n = 999999.
How do I bring its worst case down to minimum?
Any pointers or tips would be great.
Here's a complete solution which is based on the observation that a valid solution for three or more days must begin with one of the following:
0
10
110
where 1 indicates the pass is used on that day, and 0 indicates it is not.
There are valid(n-1) possibilities for the first form, valid(n-2) possibilities for the second form, and valid(n-3) possibilities for the third form.
The recurrence is then:
valid(n) = valid(n-1) + valid(n-2) + valid(n-3)
The basis cases are valid(0) = 1, valid(1) = 2, and valid(2) = 4. It is important to note that valid(0) is 1, not zero. That's because there is exactly one solution when n=0, namely, the empty sequence. This is not only mathematically correct, but is also needed for the recurrence to work correctly.
The code does three things to make it run fast:
It uses a cache to cache results (memoization), as you had done.
It doesn't store the full results, but instead first applies the modulus, greatly reducing the value ranges.
It preloads the cache, starting with 0 and going up to the desired value. This reduces the maximum recursion depth to one.
Here's the code:
cache = {}
modulus = 10**9 + 7
def valid(n):
if n in cache:
return cache[n]
if n == 0:
v = 1
elif n == 1:
v = 2
elif n == 2:
v = 4
else:
v = valid(n-1) + valid(n-2) + valid(n-3)
v %= modulus
cache[n] = v
return v
def main():
# Preload the cache
for n in range(1000000):
valid(n)
print(valid(999999))
main()
Here's the output:
746580045
It runs in under 2 seconds on my system.
Update: Here's a minimal iterative solution, inspired by the approach used by MFisherKDX. The seed values were constructed in a way that eliminates the need for special-casing (the intial v2 is valid(0)):
modulus = 10**9 + 7
def valid(n):
v0, v1, v2 = 0, 1, 1
for i in range(n):
v0, v1, v2 = v1, v2, (v0 + v1 + v2) % modulus
return v2
print(valid(999999))
This solution is probably as fast as you can get. It discards the intermediate results after using them, which is fine if you're only calling the function once.
Here's my answer. Bottom up solution. Compare with Tom's answer which is top down and equally valid. At each day j it keeps track of the number of possibilities that use the pass on day j as well as the number of possibilities that use the pass on both j and j-1.
def ans(n):
total = 1
tcd = 0 #total used at current day
tcpd = 0 #total used at current and previous day
m = 1000000007
for j in range(0, n):
next_tot = 2*total - tcpd
next_tcd = total - tcpd
next_tcpd = tcd - tcpd
total = next_tot % m
tcd = next_tcd % m
tcpd = next_tcpd % m
return total
print(ans(999999))
Result is 746580045 and takes 400ms on my system.

Categories

Resources