I'm trying to solve this question:
We want to make a row of bricks that is goal inches long. We have a
number of small bricks (1 inch each) and big bricks (5 inches each).
Return True if it is possible to make the goal by choosing from the
given bricks. This is a little harder than it looks and can be done
without any loops.
make_bricks(3, 1, 8) → True
make_bricks(3, 1, 9) → False
make_bricks(3, 2, 10) → True
— codingbat.com
For that, I made this code:
def make_bricks(small, big, goal):
tam = small + big*5
ex_gran = goal - small
if goal <= small:
return True
elif ex_gran > big*5:
return False
elif ex_gran <= big * 5 and (ex_gran % 5 <= small) :
return True
else:
return False
And this is the result os the tests:
Expected Run
make_bricks(3, 1, 8) → True True OK
make_bricks(3, 1, 9) → False False OK
make_bricks(3, 2, 10) → True True OK
make_bricks(3, 2, 8) → True True OK
make_bricks(3, 2, 9) → False True X
make_bricks(6, 1, 11) → True True OK
make_bricks(6, 0, 11) → False False OK
make_bricks(1, 4, 11) → True True OK
make_bricks(0, 3, 10) → True True OK
make_bricks(1, 4, 12) → False True X
make_bricks(3, 1, 7) → True False X
make_bricks(1, 1, 7) → False False OK
make_bricks(2, 1, 7) → True True OK
make_bricks(7, 1, 11) → True True OK
make_bricks(7, 1, 8) → True True OK
make_bricks(7, 1, 13) → False False OK
make_bricks(43, 1, 46) → True True OK
make_bricks(40, 1, 46) → False False OK
make_bricks(40, 2, 47) → True True OK
make_bricks(40, 2, 50) → True True OK
make_bricks(40, 2, 52) → False False OK
make_bricks(22, 2, 33) → False False OK
make_bricks(0, 2, 10) → True True OK
make_bricks(1000000, 1000, 1000100) → True True OK
make_bricks(2, 1000000, 100003) → False True X
make_bricks(20, 0, 19) → True True OK
make_bricks(20, 0, 21) → False False OK
make_bricks(20, 4, 51) → False False OK
make_bricks(20, 4, 39) → True True OK
Only 4 of them was wrong, but I still can't figure it out the error.
What is wrong?
Try first to use as many big bricks as possible, then complete with the small ones. Note that this works because the size of the big ones is a multiple of the size of the small ones, you would need another approach if the sizes were for example 2 and 5.
def make_bricks(small, big, goal):
max_big = goal // 5 # max number of big we can use
nb_big = min(big, max_big) # big ones we really use
return small >= goal - 5 * nb_big # True if we have enough small ones to complete
Error is simple :) it lies on line 16. Although the code could be shorten a lot.
First if all, notice that condition ex_gran <= big * 5 is irrelevant since the conditional before was already false (elif ex_gran > big*5:) and we are assuming small, big and goal are all integers, so you can take that away from the code. (Althogh this is not what is bringing troubles to the code, that's more of a style remark).
Trouble is generated by this conditional: (ex_gran % 5 <= small).
As I understand, in the example make_bricks(1, 4, 12) your code returns True when it should return False. What happens is that the code checks whether (12 - 1) <= 4*5 which is True, and if (12 - 1) % 5 <= 1 which is also True and returns True in line 18 because of this.
Let's "fix" the code. Remember that from math we know there are integers m and r such that goal = 5*m + r (moreover r = goal % 5). After we know (goal-small) <= big*5 (from false evaluation in line 12) we have two cases:
Case 1: (goal - small) = big*5, which implies goal = big*5 + small and so we should return True.
Case 2: (goal - small) < big*5, then we know goal < big*5 + small. Here you should check whether (goal % 5) <= small. If this is false, then we can't arrange the bricks to obtain the goal length (since we don't have enough 1s to fill the residual, as in the example above). Otherwise, you should return True, since we have enough bricks to surpass the goal length and enough 1s to fill the residual.
Your code ends up looking like this (I took the liberty of renaming the variables):
def make_bricks(small_bricks, big_bricks, goal):
if ( (5*big_bricks + small_bricks) < goal ): #we can't reach the length
return False
elif (small_bricks < (goal%5)) : #we can surpass the length but we don't have
#enough 1s to fill goal's residual w.r.t. 5 div
return False
else: #We can reach the length and have enough 1s to fill residual
return True
notice I took away some case goal <= small as it's not needed here.
# This code works with those 3 tests but got some other one # wrong can some help fixed it?
def make_bricks(small, big, goal):
big = big * 5
if small == goal or big == goal:
return true
elif small + big == goal or big - small == goal:
return True
else:
return False
print(make_bricks(3, 1, 8)) # → True
print(make_bricks(3, 1, 9)) # → False
print(make_bricks(3, 2, 10)) # → True
This should work...
def make_bricks(small, big, goal):
total_bricks = (1 * small) + (5 * big)
if total_bricks >= goal:
if goal%5 == 0:
if goal/5 <= goal:
x = True
elif goal%5 <= small:
x = True
else:
x = False
else:
x = False
return x
This is probably not the most efficient way but it will work..
Probably Not the most Readable
def make_bricks(small, big, goal):
if (big is not 0 and (big*5+small*1 > goal) and goal % 5 <= small) or goal < small or big*5+small*1 == goal:
return True
else:
return False
def make_bricks(small, big, goal):
return small >= goal - 5*min(goal//5,big)
Related
Say I have a circular list which would look like this to a human:
How can I determine whether two indices are adjacent please?
So far I have:
def is_next_to(a, b):
if a == b:
return False
return abs(a - b) == 1
assert is_next_to(1, 1) is False
assert is_next_to(1, 2) is True
assert is_next_to(0, 1) is True
assert is_next_to(5, 0) is True
assert is_next_to(4, 3) is True
assert is_next_to(3, 4) is True
Do I need to make special cases for (0, 5) or (5, 0), or is there some way to use modular arithmetic to solve this?
In a circle of 6, the number 5 is a neighbor of 0, but in a circle of 8, the number 5 would not be a neighbor of 0. So you can only reliable determine this when you know the size of the circle: this should be an extra parameter to your function.
Once you have that, you can use this:
def is_next_to(n, a, b):
return abs(a - b) == 1 or a + b == n - 1
n = 6
assert is_next_to(n, 1, 1) is False
assert is_next_to(n, 1, 2) is True
assert is_next_to(n, 0, 1) is True
assert is_next_to(n, 5, 0) is True
assert is_next_to(n, 4, 3) is True
assert is_next_to(n, 3, 4) is True
With modular arithmetic it would look like this:
return (a + 1) % n == b or (b + 1) % n == a
or:
return (a - b) % n in (1, n - 1)
I am trying to return an array (element-wise) of True/False values on a numpy array comparsion to a float64 static variable. Input and desired output array is 1x10 (column x row)
array = np.random.randint(10, size=(10,1))
Attempt 1:
bool = np.any((array >= min)&(array <= max))
Attempt 2:
bool = np.logical_and((array >= min),(array <= max))
Attempt 3:
bool = np.any([(array >= min)&(array <= max)])
Attempt 4:
bool = np.array(np.any([(array >= min)&(array <= max)]))
All four of the above methods produce this output in the interpreter
print(bool) = True
When desired output looks something like:
print(bool) = [True
False
True
True
False
False
True
False
False
True]
Thank you in advance for any insight you can provide me!
you can use .ravel() to get your output in the desired shape.
try this:
import numpy as np
array = np.random.randint(10, size=(10, 1))
min = 2.2
max = 6.6
result = ((array >= min) & (array <= max)).ravel()
print(result)
Output (example, as it is random):
[False True True True True True False False False True]
def dumb_multiply(a, b):
"""Multiply positive integers a and b."""
p = 0
while b!=0:
p,b = p+a, b-1
return p
I am trying to run this by hand but i keep getting confused on this line "p,b = p+a, b-1" is it setting p=p+a and b=b-1?. I can't figure out how the program gets the solutions
It multiplies two positive integers by doing a+a+...+a (b times)
Let a=4, b=3
Start:
p=0
b!=0 True
p = 0+4, b=3-1
b!=0 True
p = 4+4, b=2-1
b!=0 True
p = 8+4, b=1-1
b!=0 False
Return 12
I've written a program which works out the even perfect numbers for all Mersenne Primes from 1-1000, by using ((2^n)-1)(2^(n-1)) where n is a Mersenne Prime number.
This is the program:
def PrimeFinder(PotPrime):
PlaceNum=1
for x in range (int(PotPrime**0.5)):
PlaceNum=PlaceNum+1
if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum):
return False
return True
TrialNum = 1
for x in range (1000):
if PrimeFinder(TrialNum) == True:
if PrimeFinder((2**TrialNum)-1) == True:
print(TrialNum,"is the Mersenne Prime for the perfect number:",(2**(TrialNum-1))*((2**TrialNum)-1))
TrialNum = TrialNum+1
This program works fine, up until somewhere where 32 < TrialNum < 60, as it correctly identifies that 31 is a Mersenne Prime, however it does not for 61 (and all numbers greater than it).
I was wondering if Python simply cannot do calculations that large, or whether there is a flaw in either my understanding Mersenne Primes or programming.
Rounding errors I suppose: if you debug you notice it thinks 2 is a divisor of 2^61 -1 (which makes no sense).
If you replace if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum): with
if PotPrime % PlaceNum == 0: it's fixed. But your algorithm is quite inefficient and 2^61 - 1 is a very large number so expect it to take hours. (probably even longer)
Python's integers do not have limits on their size, so you should arrange your calculations so they're all integer-based. Here are a few changes that could be made in your program to use integers instead of floating-point.
Instead of
for x in range (int(PotPrime**0.5)):
use something like
while x*x < PotPrime:
Instead of
if int(PotPrime/PlaceNum) == (PotPrime/PlaceNum):
use the simpler
if PotPrime % PlaceNum == 0:
Use the Lucas-Lehmer primality test to check what primes produce Mersenne primes (Mp), that way you avoid check the primality of the Mersenne number itself because they are pretty big, and because only prime exponent produce Mp, with this test you only need that that p to be prime and pass this test, then you can build your perfect number as ((2^p)-1)(2^(p-1)).
With this test I can find the first 16 p [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203] that produce a Mp en 12seg in my machine that is kind of old, a Pentium Dual-Core of 3GHz
Here is the code (in python 3.3) you can also use a more powerful primality Test like the Miller-Rabin test or the Baillie-PSW those unlike trial division wound't take forever to check large numbers.
def primality_Test_Trial_Division(n:int) -> bool:
if n >= 0 :
if n<2:
return False
elif n<4:
return True
elif not n&1 or n%3==0:
return False
else:
mid = 1 + int( n**0.5 )
i = 5
while i<mid and n%i:
i += 2
return i>=mid
else:
raise ValueError
isPrime = primality_Test_Trial_Division
def primality_Test_LL(p:int) -> bool:
"""Lucas–Lehmer primality test. Check if Mp = 2^p − 1 is prime.
en.wikipedia.org/wiki/Lucas%E2%80%93Lehmer_primality_test"""
if isPrime(p):
if p==2:
return True
mersenne = (2**p)-1 #Mp
s = 4
for x in range( p-2 ):
s = pow(s,2,mersenne)-2
#Performing the mod Mp at each iteration ensures
#that all intermediate results are at most p bits
#(otherwise the number of bits would double each iteration).
#The same strategy is used in modular exponentiation.
return s==0
else:
return False
import itertools
def perfect_numbers(n:int):
"""print the first n perfect numbers"""
perfect = 0
for p in itertools.count(2):
if primality_Test_LL(p):
print(p,"is the Mersenne Prime for the perfect number:",(2**(p-1))*((2**p)-1))
perfect += 1
if perfect >= n:
break
Perfect Numbers have the following form, they are divisible by the
same number of 2's as the bit_length of the odd factor, which is prime.
semi perfect numbers like 120 and 2016, have this same form, except that
the odd factor is not prime. For example, the factors of 496 are:
[2, 2, 2, 2, 31], and 2k-1 says that 2 * (2 * 2 * 2 * 2)-1 should equal 31. It does,
so 496 just needs a final lucas lehmer test on 31 to test for a final test.
It is very easy to break up an even number to an odd number that you use for
prime testing and an even number that you use for bit_length testing on perfect
numbers, and that is the second example shown below. it's very easy to do.
For example, 496 has the factors and following properties:
import gmpy2
# If you don't have p2ecm, you can use any
# factorization method, but p2ecm is not needed for the final program below
# the example, we use it here just to show the factors.
def isoneminuspowersoftwo(N):
N=N+1
return (N & (N-1) == 0) and N != 0
In [2]: p2ecm(496) # from https://github.com/oppressionslayer/primalitytest
Out[2]: [2, 2, 2, 2, 31]
In [3]: 2*2*2*2
Out[3]: 16
In [5]: isoneminuspowersoftwo(31)
Out[5]: True
In [7]: (2*2*2*2).bit_length() == (31).bit_length()
Out[7]: True
#and
In [8]: 2*(2*2*2*2) -1 # 2k-1
Out[8]: 31
# Perform Lucas Lehmer test on 31 above:
In [106]: s=4
...: for x in range((31).bit_length()-1):
...: s = (s * s - 2) % 31
...: if s in [0,2]: print(True)
...:
True
# All three tests above passed, so the number 496 is a perfect number.
2nd Example
A Simple way to get the factors without factors is using a simple
python program to extract the numbers, which you can than test with:
def ffs(x):
return (x&-x).bit_length()-1
def extractoddfactor(N):
return N//(2**ffs(N))
In [13]: extractoddfactor(496)
Out[13]: 31
In [14]: 496//31
Out[14]: 16
A semiperfect example is below for (2 ** 5)*(2 ** 6-1). It fails on the prime
test so is semiperfect and not a perfect number, althought it passes the
first two tests.
In [11]: (2**5)*(2**6-1)
Out[11]: 2016
In [21]: extractoddfactor(2016)
Out[21]: 63
In [23]: 2016//63
Out[23]: 32
In [24]: (32).bit_length() == (63).bit_length()
Out[24]: True
In [25]: 2*(32) -1 == 63 # 2k-1 test
Out[25]: True
In [107]: s=4
...: for x in range((63).bit_length()-1):
...: s = (s * s - 2) % 63
...: if s in [0,2]: print(True)
...:
# No output, so False
I wrote a program that finds perfect numbers with the above tests
and the above LucasLehmer prime test. If you don't have gmpy2,
just remove the gmpy2.mpz wrappers and change the gmpy2
gmpy2.bit_length(x) statements to pythons equivelant like so:
x.bit_length(). I used gmpy2 as it's ten time faster than without it,
but it's not needed, and can be easily modified to not use it.
This program performs the tests above to test if a number is perfect
or not. It tests for the features of a perfect num, listed above,
and then finishes with a lucas lehmer test.
No external libraries are needed if you remove the gmpy2 mpz wrappers
and change the bit_length() statements to python format
import gmpy2
def ffs(x):
x=gmpy2.mpz(x)
return gmpy2.bit_length(x&-x)-1
def levelx(N, withstats=False):
if N <= 1: return False
N = gmpy2.mpz(N)
zero, one, two = gmpy2.mpz(0), gmpy2.mpz(1), gmpy2.mpz(2)
temp = gmpy2.mpz(N)
newlevel = gmpy2.bit_length(temp)
primetest = gmpy2.mpz(temp//(two**(ffs(temp))))
offset = gmpy2.mpz(temp//primetest)
s = gmpy2.mpz(4)
nextlevel = newlevel // two
check = temp // (two**nextlevel)
prevtemp = two**nextlevel
if withstats == True:
print (newlevel, newlevel, temp)
print (newlevel, nextlevel+one, prevtemp)
if (prevtemp & (prevtemp-one) == zero) and prevtemp != zero:
if gmpy2.bit_length(offset) == gmpy2.bit_length(primetest):
if ((primetest+one) & ((primetest+one)-one) == zero):
for x in range(gmpy2.bit_length(primetest)-1):
s = (s * s - 2) % primetest
if withstats == True:
print(s)
if s in [0,2]: return True
return False
else: return False
else: return False
else: return False
In [69]: levelx((2**4)*(2**5-1))
Out[69]: True
In [101]: for x in range(1, 10000):
...: if levelx((2**x)*(2**(x+1)-1)) == True:
...: print(x+1, (2**x)*(2**(x+1)-1))
...:
2 6
3 28
5 496
7 8128
13 33550336
17 8589869056
19 137438691328
31 2305843008139952128
61 2658455991569831744654692615953842176
89 191561942608236107294793378084303638130997321548169216
107 13164036458569648337239753460458722910223472318386943117783728128
127 14474011154664524427946373126085988481573677491474835889066354349131199152128
...
I wrote a program with Python that is designed to find a formula describing a set of numbers. Anyway, this formula works pretty well with smaller numbers that "play nice" (for instance, it'll handle [1, 5, 7, 4] just fine). However, when you feed it anything too large ([10, 42, 20, 42, 30, 42]) it quickly throws an exception (RuntimeError: maximum recursion depth exceeded in comparison). Now, when I debug this, I find that I'm seeing a bit of lossy conversion to double (for this set of numbers, nval is, on the second iteration, -611.8000000000000001). This, of course, makes things go all wrong and recurse infinitely. Now, I realize that my program is probably crappy BEYOND the lossy conversion, and I'd love any tips you have on that too, but does anyone have any ideas on fixing this?
Code (as per #jonrsharpe's comment, this is as brief as I can make it without sacrificing readability):
import math
def getdeg(numlist, cnt):
if allEqual(numlist):
return (0, numlist[0])
count = cnt
templist = []
for i in range(len(numlist) - 1):
templist.append(numlist[i+1] - numlist[i])
count += 1
if not allEqual(templist):
return getdeg(templist, count)
else:
return (count, templist[0])
def allEqual(numlist):
x = len(numlist)
if x == 1:
return True
for i in range(x-1):
if not (numlist[i] == numlist[i+1]):
return False
return True
def getTerms(numlist, terms, maxpower):
newtable = []
power, fval = getdeg(numlist, 0)
if maxpower == 0:
maxpower = power
terms.append(fval / float(math.factorial(power)))
if not power == 0:
for i in range(len(numlist)):
nval = numlist[i] - (terms[maxpower - power] * ((i + 1) ** power))
newtable.append(nval)
return getTerms(newtable, terms, maxpower)
return terms
def printeq(numlist):
#numlist = [2, 8, 9, 11, 20]
print("Coeff\tPower")
x = getTerms(numlist, [], 0)
topPow = len(x) - 1
for i in range(len(x)):
print(str(x[i]) + "\t" + str(topPow))
topPow -= 1
printeq([10, 42, 20, 42, 30, 42])
Perhaps the fractions module would be useful to you. It can exactly represent any real number, no lossy conversion required. I don't quite understand what your code is doing, but I think you can incorporate fractions by putting import fractions at the top of your script changing a single existing line. Within getTerms,
terms.append(fval / float(math.factorial(power)))
becomes
terms.append(fractions.Fraction(fval,math.factorial(power)))
Then your program runs without crashing:
Coeff Power
13/5 5
-139/3 4
932/3 3
-2900/3 2
20576/15 1
-662 0