Related
I am trying to find the number of ways to construct an array such that consecutive positions contain different values.
Specifically, I need to construct an array with elements such that each element 1 between and k , all inclusive. I also want the first and last elements of the array to be 1 and x.
Complete problem statement:
Here is what I tried:
def countArray(n, k, x):
# Return the number of ways to fill in the array.
if x > k:
return 0
if x == 1:
return 0
def fact(n):
if n == 0:
return 1
fact_range = n+1
T = [1 for i in range(fact_range)]
for i in range(1,fact_range):
T[i] = i * T[i-1]
return T[fact_range-1]
ways = fact(k) / (fact(n-2)*fact(k-(n-2)))
return int(ways)
In short, I did K(C)N-2 to find the ways. How could I solve this?
It passes one of the base case with inputs as countArray(4,3,2) but fails for 16 other cases.
Let X(n) be the number of ways of constructing an array of length n, starting with 1 and ending in x (and not repeating any numbers). Let Y(n) be the number of ways of constructing an array of length n, starting with 1 and NOT ending in x (and not repeating any numbers).
Then there's these recurrence relations (for n>1)
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
In words: If you want an array of length n+1 ending in x, then you need an array of length n not ending in x. And if you want an array of length n+1 not ending in x, then you can either add any of the k-1 symbols to an array of length n ending in x, or you can take an array of length n not ending in x, and add any of the k-2 symbols that aren't x and don't repeat the last value.
For the base case, n=1, if x is 1 then X(1)=1, Y(1)=0 otherwise, X(1)=0, Y(1)=1
This gives you an O(n)-time method of computing the result.
def ways(n, k, x):
M = 10**9 + 7
wx = (x == 1)
wnx = (x != 1)
for _ in range(n-1):
wx, wnx = wnx, wx * (k-1) + wnx*(k-2)
wnx = wnx % M
return wx
print(ways(100, 5, 2))
In principle you can reduce this to O(log n) by expressing the recurrence relations as a matrix and computing the matrix power (mod M), but it's probably not necessary for the question.
[Additional working]
We have the recurrence relations:
X(n+1) = Y(n)
Y(n+1) = X(n)*(k-1) + Y(n)*(k-2)
Using the first, we can replace the Y(_) in the second with X(_+1) to reduce it down to a single variable. Then:
X(n+2) = X(n)*(k-1) + X(n+1)*(k-2)
Using standard techniques, we can solve this linear recurrence relation exactly.
In the case x!=1, we have:
X(n) = ((k-1)^(n-1) - (-1)^n) / k
And in the case x=1, we have:
X(n) = ((k-1)^(n-1) - (1-k)(-1)^n)/k
We can compute these mod M using Fermat's little theorem because M is prime. So 1/k = k^(M-2) mod M.
Thus we have (with a little bit of optimization) this short program that solves the problem and runs in O(log n) time:
def ways2(n, k, x):
S = -1 if n%2 else 1
return ((pow(k-1, n-1, M) + S) * pow(k, M-2, M) - S*(x==1)) % M
could you try this DP version: (it's passed all tests) (it's inspired by #PaulHankin and take DP approach - will run performance later to see what's diff for big matrix)
def countArray(n, k, x):
# Return the number of ways to fill in the array.
big_mod = 10 ** 9 + 7
dp = [[1], [1]]
if x == 1:
dp = [[1], [0]]
else:
dp = [[1], [1]]
for _ in range(n-2):
dp[0].append(dp[0][-1] * (k - 1) % big_mod)
dp[1].append((dp[0][-1] - dp[1][-1]) % big_mod)
return dp[1][-1]
The sequence is:
an = an-1 + (2 * an-2)
a0 = 1, a1= 1. Find a100
The way I did it is making a list.
#List 'a' with a0 = 1 , a1 = 1.
a = [1,1]
#To get the a100, implement 'i' as the index value of the list.
for i in range (2,101):
x = a[i-1] + (2 * a[i-2])
print( str(len(a)) + (": ") + str(x))
#Save new value to list
a.append(x)
Is there another way to do this where you can just directly get the value of a100? Or the value of a10000.. it will take up so much memory.
For this specific case, the sequence appears to be known as the Jacobsthal sequence. Wikipedia gives a closed form expression for a_n that can be expressed as follows:
def J(n):
return (2**(n+1) - (1 if n % 2 else -1))//3
Slightly more generally, you can use fast matrix exponentiation to find a specific value of a_n in O(log n) matrix operations. The approach here is a slight modification of this.
import numpy as np
def a(n):
mat = np.array([[1, 2], [1, 0]], dtype=object) # object for large integers
return np.linalg.matrix_power(mat, n)[0,0]
Here is the value for a_1000:
7143390714575115472989500327066678737076032078036890716291669255802340340832907483287989192104639054183964486117020978834580968571282093623989718383132383202623045183216153990280716403374914094585302788102030983322387960844932511706110362630718041943047464318457694778440286554435082924558137112046251
This recurrence relation has a closed form solution:
a = lambda n: (2**(n+1) + (-1)**n)//3
Then
a(0) == 1
a(1) == 1
a(2) == 3
...
Use Wolfram Alpha solve for the closed form solution.
For a more general solution, sympy's rsolve can generate a formula for linear recurrences. And then use substitution to find particular values.
from sympy import rsolve, Function, symbols
f = Function('f')
n = symbols('n', integer=True)
T = f(n) - f(n - 1) - 2 * f(n - 2)
sol = rsolve(T, f(n), {f(0): 1, f(1): 1})
print(sol.factor())
for k in range(6):
print(f'a[{10**k}] = {sol.subs({n:10**k})}')
This finds the formula: ((-1)**n + 2*2**n)/3 and substituting various values gives:
a[1] = 1
a[10] = 683
a[100] = 845100400152152934331135470251
a[1000] = 7143390714575115472989500327066678737076032078036890716291669255802340340832907483287989192104639054183964486117020978834580968571282093623989718383132383202623045183216153990280716403374914094585302788102030983322387960844932511706110362630718041943047464318457694778440286554435082924558137112046251
a[10000] = 13300420779205055899224947751223900558823312212574616365680059665686292553481297754613307789357463065266220752948806082847704327566275854078395857288064215971903820031195863017843497700844039930347033391278795541028339072307078736457006049910726416592060326596558672835961088838567081045539649268371274925376816731095916294031173247751323635481912358774462877183753093841891253840488152356727760984122637587639312975932940560640357511880709747618222262691017043766353735428453489979600223956211100972865182186443850404115054687605329465453071585497122508186691535256991501267222976387636433705286400943222614410489725426171396919846079518533884638490449629415374679171890883668485549192847140249201910928687618755494267749463781127049374279769561549759200832570764870138287994839741197500087328573494472227205070621546774178994858997503894208562707691159300991409504210074059830342802209213468621093971730976504006937230561044048029975244677676707947087336124281517272447267049737611904634607637370045500833604005013228174598706158078702963192048604263495032226147988471602982108251173897742022519137359868942131422329103081800375446624970338827853981873988860876269047918349845673238184625284288814399599917924440538912558558685095521850114849105048496522741529593155873907738282168861316542080131736118854643798317265443020838956090639908522753418790270855651099392460347365053921743882641323846748271362887055383912692879736402269982104388805781403942200602501882277026496929598476838303527006808207298214407168983217160516849324232198998893837958637097759081249712999519344381402467576288757211476207860932148655897231556293513976121900670048618498909700385756334067235325208259649285799693889564105871362639412657210097186118095746465818754306322522134720983321447905340926047485500603884544957480384983947611769143791817076603055269994974019086721023722205420067991783904156229025970272783748933896591684108429045765889012975813584862160062970831282169566933785351515891836917604484599090827358327607311145704700506065400164526586785514617302254188281302685535172938965970009784445593131997924161090875584262602248970534271757827918474036922817159666073457645479797721100990086996148246631809842046103645478455250800241851505149187576887740797874187195112987924800865762440512367759907023068198581038345298256830912964615391929510632144672034080214910330858779357159414245558929061170945822567007313514409276959727327732103102944890874437957354081499958646666151187821572015407908429716866090505450005466559490856410166587392640154829574782514412057571343645656039081553195235917082324370960357975081345975714019208241045008362225535513352731779100379038105003677818345932796086474225126766610787543447696005152433715459704967280220123536564742545543604882702212692308056024281175802607700426526000495235781464187268985316355546978912530579053491968145752746720495213034211965438416298865678974339803258684849814383125421063166939821410053665460303868944551299858094210708807124261007787849536528397806251
Inputs:
k-> number of lists
m->modulo
Constraints
1<=k<=7
1<=M<=1000
1<=Magnitude of elements in list<=10*9
1<=Elements in each list<=7
`
This snippet of code is responsible for maximizing (x1^2 + x2^2 + ...) % m where x1, x2, ... are chosen from lists X1, X2, ...
k,m=map(int,input().split())
Sum=0
s=[]
for _ in range(k):
s.append(max(map(int,input().split())))
Sum+=int(s[_])**2
print(Sum%m)
So for instance if inputs are :
3 1000
2 5 4
3 7 8 9
5 5 7 8 9 10
The output would be 206, owing to selecting highest element in each list, square that element, take the sum and perform modulus operation using m
So, it would be (5^2+9^2+10^2)%1000=206
If I provide input like,
3 998
6 67828645 425092764 242723908 669696211 501122842 438815206
4 625649397 295060482 262686951 815352670
3 100876777 196900030 523615865
The expected output is 974, but I am getting 624
I would like to know how you would approach this problem or how to correct existing code.
You have to find max((sum of squares) modulo m). That's not the same as max(sum of squares) modulo m.
It may be that you find a sum of squares that's not in absolute terms as large as possible, but is maximum when you take it modulo m.
For example:
m=100
[10, 9],
[10, 5]
Here, the maximum sum of squares is 100 + 100 = 200, which is 0 modulo 100. The maximum (sum of squares modulo 100) is (81 + 100) = 182, which is 82 modulo 100.
Given that m is forced to be small, there's an fast dynamic programming solution that runs in O(m * N) time, where N is the total number of items in all the lists.
def solve(m, xxs):
r = [1] + [0] * (m - 1)
for xs in xxs:
s = [0] * m
for i in xrange(m):
for x in xs:
xx = (x * x) % m
s[i] += r[(i - xx) % m]
r = s
return max(i for i in xrange(m) if r[i])
m = 998
xxs = [
[67828645, 425092764, 242723908, 669696211, 501122842, 438815206],
[625649397, 295060482, 262686951, 815352670],
[100876777, 196900030, 523615865]]
print solve(m, xxs)
This outputs 974 as required.
One important logical problem here is you have to skip the number of items in each list while find the max element in your for loop. That is, instead of
Example,
6 67828645 425092764 242723908 669696211 501122842 438815206
and your data is
67828645 425092764 242723908 669696211 501122842 438815206
That is,
input().split()
You have to use,
input().split()[1:]
As pointed by Paul Hankin, you basically need to find max(sum of powers % m)
You have to find the combination from three lists whose sum%m is max.
So, this is basically,
You scan the input, split with space, leaving the first element which is the number of values in each line,you map them to integers. And then, you find the squares and append them to a list s. Having that you find the product(itertools module) Example - product([1,2],[3,4,5]) will give, [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)]. Now, you can find the sum of each such result % m and find the max value!
That is,
k,m=map(int,input().split())
from itertools import product
s=[]
for _ in range(k):
s.append(map(lambda x:x**2,map(int,input().split()[1:])))
print(max([sum(i)%m for i in product(*s)]))
Try it online!
This will give you the desired output!
Hope it helps!
Your question is not very clear. However, if I understand it correctly, you have lists of possible values for f(X1), ..., f(Xn) (probably obtained by applying f to all possible values for X1, ..., Xn), and you want to maximize f(X1)^2 + ... + f(Xn)^2 ?
If so, your code seems good, I get the same result:
lists = [[6, 67828645, 425092764, 242723908, 669696211, 501122842, 438815206],
[4, 625649397, 295060482, 262686951, 815352670],
[3, 100876777, 196900030, 523615865]]
sum = 0
for l in lists:
sum += max(l)**2
print(sum%998)
This print 624, just like your code. Where are you getting the 974 from ?
Not going to win any codegolf with this but here was my solution:
from functools import reduce
def get_input():
"""
gets input from stdin.
input format:
3 1000
2 5 4
3 7 8 9
5 5 7 8 9 10
"""
k, m = [int(i) for i in input().split()]
lists = []
for _ in range(k):
lists.append([int(i) for i in input().split()[1:]])
return m, k, lists
def maximise(m, k, lists):
"""
m is the number by which the sum of squares is modulo'd
k is the number of lists in the list of lists
lists is the list of lists containing vals to be sum of squared
maximise aims to maximise S for:
S = (f(x1) + f(x2)...+ f(xk)) % m
where:
f(x) = x**2
"""
max_value = reduce(lambda x,y: x+y**2, [max(l) for l in lists], 0)
# check whether the max sum of squares is greater than m
# if it is the answer has to be the max
if max_value < m:
print(max_value)
return
results = []
for product in cartesian_product(lists):
S = reduce(lambda x, y: x + y**2, product, 0) % m
if S == m-1:
print(S)
return
results.append(S)
print(max(results))
def cartesian_product(ll, accum=None):
"""
all combinations of lists made by combining one element from
each list in a list of lists (cartesian product)
"""
if not accum:
accum = []
for i in range(len(ll[0])):
if len(ll) == 1:
yield accum + [ll[0][i]]
else:
yield from cartesian_product(ll[1:], accum + [ll[0][i]])
if __name__ == "__main__":
maximise(*get_input())
Given a number and a ratio, how do I create an exponentially growing list of numbers, whose sum equals the starting number?
>>> r = (1 + 5 ** 0.5) / 2
>>> l = makeSeq(42, r)
>>> l
[2.5725461188664465, 4.162467057952537, 6.735013176818984,
10.897480234771521, 17.63249341159051]
>>> sum(l)
42.0
>>> l[-1]/l[-2]
1.6180339887498953
>>> r
1.618033988749895
A discrete sequence of exponentially growing numbers is called a geometric progression. The sum is called a geometric series. The formula here can easily be solved to produce the sequence you need:
>>> n = 5
>>> r = (1 + 5 ** 0.5) / 2
>>> r
1.618033988749895
>>> total = 2.28
>>> a = total * (1 - r) / (1 - r ** n)
>>> a
0.13965250359560707
>>> sequence = [a * r ** i for i in range(n)]
>>> sequence
[0.13965250359560707, 0.22596249743170915, 0.36561500102731626, 0.5915774984590254, 0.9571924994863418]
>>> sum(sequence)
2.28
>>> sequence[1] / sequence[0]
1.618033988749895
>>> sequence[2] / sequence[1]
1.618033988749895
>>> sequence[2] / sequence[1] == r
True
It's also worth noting that both this problem and the original problem of the Fibonacci could be solved using a binary search / bisection method.
Pick any sequence of Fibonacci numbers you want. Add them up, and divide your target number by the sum to get a scaling factor. Multiply each number in your chosen sequence by the scaling factor, and you'll have a new sequence that sums to your target, and has the same ratio of adjacent terms as the original sequence of Fibonacci numbers.
To generate the example in your question, note that 1 + 2 + 3 + 5 + 8 = 19, and 2.28/19 = 0.12.
The Fibonacci sequence goes as follows: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ... etc. As you may have already seen in the comments on your question, the Fibonacci sequence itself doesn't "scale" (i.e., fib_seq * 0.12 = 0, 0.12, 0.12, 0.24, 0.36, 0.60, 0.96 ... etc. isn't the Fibonacci sequence any longer), so you you can really only make a Fibonacci series in the order the values are presented above. If you would like to make the Fibonacci sequence dynamically scalable depending on some criteria, please specify further what purpose that would serve and what you are having trouble with so that the community can help you more.
Now, let's start with the basics. If you've had trouble with implementing a function to print the Fibonacci Sequence in the first place, refer to the answer #andrea-ambu gives here: https://stackoverflow.com/a/499245/5209610. He provides a very comprehensive explanation of how to not only implement the Fibonacci Sequence in a function in any given language, but even goes further to explore how to do so efficiently!
I presume that you are trying to figure out how to write a function that will take a user-provided integer and print out the Fibonacci series that sums up to that value (i.e., print_fib_series(33) would print 0 + 1 + 1 + 2 + 3 + 5 + 8 + 13). This is fairly easily achievable by just incrementally adding the next value in the Fibonacci series until you arrive to the user-provided value (and keeping track of which values you've summed together so far), assuming that the user-provided value is a sum of Fibonacci series values. Here's an easy implementation of what I just described:
# Recursive implementation of the Fibonacci sequence from the answer I linked
def fib_seq(ind):
if ind == 0:
return 0;
elif ind == 1:
return 1;
else:
return fib_seq(ind - 1) + fib_seq(ind - 2);
def list_fib_series(fib_sum, scaling_factor):
output_list = [];
current_sum = 0;
for current_val in fib_seq():
current_sum += current_val * scaling_factor;
output_list.append(current_val);
if current_sum == fib_sum:
return output_list;
elif current_sum > fib_sum:
return 0; # Or you could raise an exception...
fib_list = list_fib_series(2.4, 0.12):
print ' + '.join(map(str, fib_list));
So, considering the decimal value of 2.4 you could apply a linear scaling factor of 0.12 to the Fibonacci series and get the result you indicated in your question. I hope this helps you out!
Forget about the decimal numbers, like julienc mentioned program would never know where to start from if you bend the 'definition of Fibonacci series' like the way you wish to. You must be definitive about fibonacci series here.
For whole numbers and actual definition of fibonacci series, best you can do is make a program which takes number as input and tells whether the number sums up to some fibonacci series. And if it does then print the series. Assuming this is what you want.
a = 33
f_list = []
def recur_fibo(n):
if n <= 1:
return n
else:
return(recur_fibo(n-1) + recur_fibo(n-2))
i=0
total = 0
while True:
num = recur_fibo(i)
total += num
f_list.append(num)
if total > a:
print "Number can not generate fibonacci series"
break
elif total == a:
print "Series: %s" % f_list
break
i +=1
Output:
Series: [0, 1, 1, 2, 3, 5, 8, 13]
Based off of Alex Hall's answer, this is what I ended up using:
def geoProgress(n, r=(1 + 5 ** 0.5) / 2, size=5):
""" Creates a Geometric Progression with the Geometric sum of <n>
>>> l = geoProgress(42)
>>> l
[2.5725461188664465, 4.162467057952537, 6.735013176818984,
10.897480234771521, 17.63249341159051]
>>> sum(l)
42.0
>>> l[-1]/l[-2]
1.6180339887498953
"""
return [(n * (1 - r) / (1 - r ** size)) * r ** i for i in range(size)]
I get this code from leetcode.
class Solution(object):
def myPow(self, x, n):
if n == 0:
return 1
if n == -1:
return 1 / x
return self.myPow(x * x, n / 2) * ([1, x][n % 2])
This code is used to implement poe(x, n), which means x**n in Python.
I want to know why it can implement pow(x, n).
It looks doesn't make sense...
I understand
if n == 0:
and
if n == -1:
But the core code:
self.myPow(x * x, n / 2) * ([1, x][n % 2])
is really hard to understand.
BTW, this code only works on Python 2.7. If you want to test on Python 3, you should change
myPow(x*x, n / 2) * ([1, x][n % 2])
to
myPow(x*x, n // 2) * ([1, x][n % 2])
The recursive function is to compute power (most probably integer, non negative or -1, power) of a number, as you might have expected (something like x = 2.2 and n = 9).
(And this seems to be written for Python 2.x (due to the n/2 having expected result of integer instead of n//2))
The initial returns are very straight-forward math.
if n == 0:
return 1
if n == -1:
return 1 / x
When the power is 0, then you return 1 and then the power is -1, you return 1/x.
Now the next line consists of two elements:
self.myPow(x * x, n/2)
and
[1, x][n%2]
The first one self.myPow(x * x, n/2) simply means you want to make higher power (not 0 or -1) into half of it by squaring the powered number x
(most probably to speed up the calculation by reducing the number of multiplication needed - imagine if you have case to compute 2^58. By multiplication, you have to multiply the number 58 times. But if you divide it into two every time and solve it recursively, you end up will smaller number of operations).
Example:
x^8 = (x^2)^4 = y^4 #thus you reduce the number of operation you need to perform
Here, you pass x^2 as your next argument in the recursive (that is y) and do it recursively till the power is 0 or -1.
And the next one is you get the modulo of two of the divided power. This is to make up the case for odd case (that is, when the power n is odd).
[1,x][n%2] #is 1 when n is even, is x when n is odd
If n is odd, then by doing n/2, you lose one x in the process. Thus you have to make up by multiplying the self.myPow(x * x, n / 2) with that x. But if your n is not odd (even), you do not lose one x, thus you do not need to multiply the result by x but by 1.
Illustratively:
x^9 = (x^2)^4 * x #take a look the x here
but
x^8 = (x^2)^4 * 1 #take a look the 1 here
Thus, this:
[1, x][n % 2]
is to multiply the previous recursion by either 1 (for even n case) or x (for odd n case) and is equivalent to ternary expression:
1 if n % 2 == 0 else x
This is divide and conquer technique. The implementation above is a fast way of computing exponentiation. At each call, half of the multiplications are eliminated.
Assuming that n is even, x^n can be written as below (If n is odd, it requires one extra multiplication)
x^n = (x^2)^(n/2)
or
x^n = (x^n/2)^2
The function shown above implements the 1st version. It's easy to implement the 2nd one also (I removed recursion base cases below)
r = self.myPow(x,n/2)
return r * r * ([1, x][n % 2])
The right answer might be below
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0:
return 1
if n > 0:
return self.myPow(x * x, int(n / 2)) * ([1, x][n % 2])
else:
return self.myPow(x * x, int(n / 2)) * ([1, 1/x][n % 2])