Beginner programmer here!
So I'm trying to create functions for tetration using a recursive formula. I use that same function tetrate_F in finding the nth super root of some big number.
In sprRt(a, b), when b gets a tiny bit too high the function seems to slow down by a ton. I find that 2,3 and 5 works for pretty much any value of a. But when b is set to 4 or any other value it just takes so damn long for some reason.
def tetrate_F(a, b):
if b == 0:
return b+1
else:
res = a ** tetrate_F(a, b-1)
return(res)
def sprRt(a, b):
l_head = []
lt0 = []
if b == 1:
print("Undefined")
elif b > 1:
for j in range(0, a+1):
if tetrate_F(j, b) < a:
lt0.append(j)
elif tetrate_F(j, b) > a:
break
val0 = lt0[-1]
lt0.clear()
l_head.append(val0)
print(val0)
sprRt(1234567890, 4)
Like in sprRt(1234567890, 2), I can use 2,3 or even 5 for b and get a result almost immediately but not any other number.
Help will be much appreciated thx!
Related
I have been kinda practicing some recursive / dynamic programming exercises, but I have been struggling trying to convert this recursive problem into a top-down one, as for example, for f(4,4), the recursive one yields 5, whereas my top-down yields 2.
I can see the base cases being the same, so I might be messing up with the logic somehow, but I haven't found where.
the code is as written:
def funct(n, m):
if n == 0:
return 1
if m == 0 or n < 0:
return 0
return funct(n-m, m) + funct(n, m-1)
and the top-down approach is:
def funct_top_down(n, m):
if n == 0:
return 1
if m == 0 or n < 0:
return 0
memo = [[-1 for x in range(m+1)] for y in range(n+1)]
return funct_top_down_imp(n, m, memo)
def funct_top_down_imp(n, m, memo):
if memo[n][m] == -1:
if n == 0:
memo[n][m] = 1
elif m == 0 or n < 0:
memo[n][m] = 0
else:
memo[n][m] = funct_top_down_imp(n-m, m, memo) + funct_top_down_imp(n, m-1, memo)
return memo[n][m]
Thanks!
The basic idea is to compute all possible values of func instead of just one. Sounds like a lot, but since func needs all previous values anyways, this would be actually the same amount of work.
We place computed values in a matrix N+1 x M+1 for given N, M so that it holds that
matrix[n][m] === func(n, m)
Observe that the first row of the matrix will be all 1, since f(0,m) returns 1 for every m. Then, starting from the second row, compute the values left to right using your recursive dependency:
matrix[n][m] = matrix[n-m][m] + matrix[n][m-1]
(don't forget to check the bounds!)
Upon completion, your answer will be in the bottom right corner of the matrix. Good luck!
I am trying to write code which gives you numbers which are less than given or entered number , and their GCD equal to 1 . I wrote this code but I don't know if works or why not . For example I chose number 6. array will be like [1,2,3,4,5]. And my point is to filter numbers that GCD equals to 1. So it will be [1,5]. And their amount is two.
a is input number and b is list numbers that are less than entered one and not equal to zero . And then print it .
a = int(input("enter number \n"))
b = list(range(1,a))
print (b)
Then I convert list to array
for i in range(1, len(b)):
b[i] = int(b[i])
and then this
r = a % b[i]
q = int ( a / b[i])
while(r!=0):
a = b[i]
b[i] = r
q = int ( a / b[i])
r = a - (b[i] * q)
print ( a , b[i], r )
break
I am beginner .
A few comments about your code:
You should always encapsulate code like this in a function; write a function find_coprimes which takes an argument n and returns the list you want;
In order to test the correctness of your function, write a reference function find_coprimes_ref which does the same thing, but uses library functions to make sure there is no error; this will teach you to look for relevant library functions, and you can compare the results of the two functions;
The initial loop for i in range(1, len(b)): b[i] = int(b[i]) is wrong for two reasons; 1) It has no effect, as b is already a list of integers. 2) Lists are 0-indexed, so a correct iterations on every element of b would be for i in range(0, len(b)): or simply for i in range(len(b)):;
Your code has two nested loops: a while-loop executing repeatedly inside a for-loop; whenever there are nested loops like this, you must make sure that variables are reinitialised the way you intend them to at the beginning of the outer loop; in your case, variable a is modified inside the while-loop, and as a result, its value is wrong at the beginning of the next iteration of the for-loop.
The break statement at the end of the while-loop makes no sense; in general, break statements only make sense if they are encapsulated in an if conditional, and they act as a substitute for the loop condition; but it's always possible to write loops without using break at all and I recommend you forget about break entirely.
After performing the gcd calculation using q and r, your code is missing something to tell it whether or not to keep b[i] or not in the final result;
For integer division in python, it is better to use // rather than int(... / ...).
Code
import math
def find_coprimes_ref(n):
return [x for x in range(1,n) if math.gcd(x,n) == 1]
def find_coprimes(n):
result = []
for x in range(1, n):
a = n
b = x
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
if (r == 1):
result.append(x)
return result
# TESTING
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
Note how my code never modifies n or x in the loop; instead, I make copies called a and b and modify the copies.
Encapsulating even further
Note how function find_coprimes_ref is so much easier to read than function find_coprimes? This is not just because we used library function math.gcd. It's because library function math.gcd is a cleanly-encapsulated function with a name that explains clearly what it does. Your code contains a while loop inside a for loop and it's a bit hard to keep track of every variable and everything that is going on and not lost track of our sub-objective and overall objective.
To make your function both easier to read, easier to code and easier to debug, You should encapsulate the gcd calculation inside a function called gcd:
def gcd(a, b):
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
return r
def find_coprimes(n):
result = []
for x in range(1, n):
if gcd(a, b) == 1:
result.append(x)
return result
# TESTING GCD
for b in range(1, 31):
for a in range(b, 31):
r1 = math.gcd(a, b)
r2 = gcd(a, b)
if r1 != r2:
print(a, b, r1, r2)
# TESTING FIND_COPRIMES
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
There are two reasons why the code is easier to debug now:
The logic for gcd and for find_coprimes is cleanly separated, which means you can reason about gcd clearly without any risk of messing up the list and the other variables used in find_coprimes;
You can test separately your function gcd and your function find_coprimes; and if something doesn't work correctly, you'll know more precisely where to look for the issue rather than just thinking "well, something is wrong somewhere in the code but I have no idea where".
There are a few errors in your code like, break inside while loop. I have refactored your code and also added inbuilt math.gcd function to compare results.
import math
def math_inbuilt_gcd(a, b):
gcd_one = []
for x in b:
if math.gcd(x, a) == 1:
gcd_one.append(x)
print("gcd_one_math_fun:", gcd_one)
def gcd_my_fun(a, b):
gcd_arr = []
for i in range(len(b)):
x, y = a, b[i] # taking x, y just to make things clear
r = x % y # remainder
q = int(x / y) # quotient
while(r != 0):
x = y
y = r
q = int(x/y)
r = x % y
if y == 1:
gcd_arr.append(b[i])
print("gcd_one_my_fun:", gcd_arr)
a = int(input("Enter number: "))
b = list(range(1, a))
print("b:", b)
math_inbuilt_gcd(a, b)
gcd_my_fun(a, b)
Output:
Enter number: 10
b: [1, 2, 3, 4, 5, 6, 7, 8, 9]
gcd_one_math_fun: [1, 3, 7, 9]
gcd_one_my_fun: [1, 3, 7, 9]
Here's my issue:
I have a large integer (anywhere between 0 and 2^32-1). Let's call this number X.
I also have a list of integers, unsorted currently. They are all unique numbers, greater than 0 and less than X. Assume that there is a large amount of items in this list, let's say over 100,000 items.
I need to find up to 3 numbers in this list (let's call them A, B and C) that add up to X.
A, B and C all need to be inside of the list, and they can be repeated (for example, if X is 4, I can have A=1, B=1 and C=2 even though 1 would only appear once in the list).
There can be multiple solutions for A, B and C but I just need to find one possible solution for each the quickest way possible.
I've tried creating a for loop structure like this:
For A in itemlist:
For B in itemlist:
For C in itemlist:
if A + B + C == X:
exit("Done")
But since my list of integers contains over 100,000 items, this uses too much memory and would take far too long.
Is there any way to find a solution for A, B and C without using an insane amount of memory or taking an insane amount of time? Thanks in advance.
you can reduce the running time from n^3 to n^2 by using set something like that
s = set(itemlist)
for A in itemlist:
for B in itemlist:
if X-(A+B) in s:
print A,B,X-(A+B)
break
you can also sort the list and use binary search if you want to save memory
import itertools
nums = collections.Counter(itemlist)
target = t # the target sum
for i in range(len(itemlist)):
if itemlist[i] > target: continue
for j in range(i+1, len(itemlist)):
if itemlist[i]+itemlist[j] > target: continue
if target - (itemlist[i]+itemlist[j]) in nums - collections.Counter([itemlist[i], itemlist[j]]):
print("Found", itemlist[i], itemlist[j], target - (itemlist[i]+itemlist[j]))
Borrowing from #inspectorG4dget's code, this has two modifications:
If C < B then we can short-circuit the loop.
Use bisect_left() instead of collections.Counter().
This seems to run more quickly.
from random import randint
from bisect import bisect_left
X = randint(0, 2**32 - 1)
itemset = set(randint(0,X) for _ in range(100000))
itemlist = sorted(list(itemset)) # sort the list for binary search
l = len(itemlist)
for i,A in enumerate(itemlist):
for j in range(i+1, l): # use numbers above A
B = itemlist[j]
C = X - A - B # calculate C
if C <= B: continue
# see https://docs.python.org/2/library/bisect.html#searching-sorted-lists
i = bisect_left(itemlist, C)
if i != l and itemlist[i] == C:
print("Found", A, B, C)
To reduce the number of comparisons, we enforce A < B < C.
def mystery_code(n):
return mystery_recursive(n, n-1)
def mystery_recursive(a, b):
if b<=0:
return 0
else:
c=mystery_recursive(a,b-1)
if a%b==0:
c+=b
return c
Could someone please help me understand what this code does?
It computes the sum of proper divisors of n.
If you step through the code you'll see it calls, e.g., mystery_recursive(5, 4) and then recursively mystery_recursive(5, 3), mystery_recursive(5, 2), mystery_recursive(5, 1), mystery_recursive(5, 0). It'll then return 0 because b <= 0.
In each of these calls, it assigns the result of a call to c and if a % b == 0 (i.e., a can be divided by b) then it adds b to c. So you'll end up with a sum of the proper divisors of n.
As already told by Simeon Visser the above code computes the sum of proper divisors of n.
if your function call is:
mystery_code(12)
then it will call the mystery recursive function (mystery_recursive(a, b)) in your code as:
mystery_recursive(12, 11)
Once the recursive function started to execute it will keep on calling itself until the condition b<=0 satisfies. In this case mystery_recursive(12, 0) will return a value of '0' to the variable 'c' to its called function mystery_recursive(12, 1). Then, beginning with the above mystery function (mystery_recursive(12, 1)) the 'c' value will be computed and returned to their respective calling functions of the same until the called function mystery_recursive(12, 11).
Output in this case: 16
Perhaps it helps to convert this recursive function to an interative version
def mystery_recursive(a, b):
c = 0
while True:
if b <= 0:
return c
if a % b == 0:
c += b
b -= 1
It's still a bit clumsy, so try to convert it to a sum generator expression
def mystery_recursive(a, b):
return sum(b for b in range(b, 0, -1) if a % b == 0)
You can even roll that back into mystery_code
def mystery_code(n):
return sum(b for b in range(n - 1, 0, -1) if n % b == 0)
As a homework assignment I have to write a script which finds the median of 3 given numbers without using a standard sort function of Python.
This is my first week in class and my first programming experience so I find it very difficult to get any further than I am right now.
Here's what I have so far:
def med3(a,b,c):
list = [a, b, c]
newlist = []
if list:
minimum = list[0]
for x in list:
if x < minimum:
minimum = x
newlist.append(minimum)
list.remove(minimum)
elif x >= minimum:
newlist.append(x)
list.remove(x)
return newlist[1]
This seems to do the trick, but only for the first two entries of the list. The loop doesn't include the third entry.
How can I make the script include all three entries?
Thanks in advance!
Sander
sum([a, b, c]) - min(a, b, c) - max(a, b, c) - no sorting!
You are modifying the list in-place while looping over it, which has consequences for what elements you see:
>>> numbers = [1,2,3]
>>> for i in numbers:
... if i == 2: numbers.remove(i)
... print i
...
1
2
Note how 3 is never printed; by removing the second entry in the list, we've shortened it by one element and the loop finds the list exhausted early.
Note that you don't need to loop over the items, a few simple comparisons will tell you what item is the median if you think about it for a second. :-)
There are a number of simpler ways to go about this, but as for your approach:
You're modifying list inside of your loop. Don't do that. :)
In your case, you should be removing elements from newlist:
def med3(a,b,c):
list = [a, b, c]
newlist = []
if list:
minimum = list[0]
for x in list:
if x < minimum:
minimum = x
newlist.pop()
newlist.append(minimum)
elif x >= minimum:
newlist.append(x)
return newlist[1]
But as an exercise, you might want to think about a few things:
Why are you putting the elements in a list and looping over them? What advantage does this have over comparing a,b,c with simply if statements?
Why the if list:?
The fastest way to do it:
def medianFast(a, b, c):
if a > b:
if b > c:
return b
elif a > c:
return c
else:
return a
else:
if b < c:
return b
elif a > c:
return a
else:
return c
Guarantees you 3 comparisons at the worst case and 2 comparisons in the best case. 2,5 comparisons in average.
Using ternary conditional we can write it shorter as:
def medianTernary(a, b, c):
return (b if b > c else (c if a > c else a)) if a > b else (b if b < c else (a if a > c else c))
If you could use sorting you would have the shortest version:
def medianSorted(a, b, c):
return sorted([a, b, c])[1]