Integers, like molecules, are built from atoms. However there's only one element in the periodic table of maths, namely the number 1, and all other integers can be built from it. For example, there are several ways to build the number 6:
6 = 1 + 1 + 1 + 1 + 1 + 1 = ( 1 + 1 ) ∗ ( 1 + 1 ) + 1 + 1 = ( 1 + 1 ) ∗ ( 1 + 1 + 1 )
We say the number 6 has complexity 5, because that's the cheapest (using the fewest ones) way it can be built. The allowed operations are addition, multiplication and brackets. It's not allowed to write two ones next to each other to make 11.
What's the smallest number with complexity 13?
This is the final problem in a series of 3. You are encouraged to solve the previous problems first.
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
Tiny typo,The n 's on the right side of the recursive function are all supposed to be x 's
Nice solution, but it doesn't follow PEP 8 with all those one-line if statements.
Log in to reply
Thanks..I know its not pythonic..was lazy I guess
great easy to understand
The answer should be a prime number because at every prime number the complexity of the numbers above it are either less or equal. So in such a way we can get 47 :)
the problem is solvable using dynamic programing (c++ code):
int main(){
int A[1000];
for (int i=0;i<1000;i++){
A[i]=i;
}
for (int i=5;i<300;i++){
for (int j=2;j<sqrt(i)+2;j++){
if (i%j==0&&A[i/j]+A[j]<A[i]){A[i]=A[i/j]+A[j];}
}
for (int j=1;j<i;j++){
if (A[i-j]+j<A[i]){A[i]=A[i-j]+j;}
}
}
for (int i=1;i<200;i++){
cout<<i<<" "<<A[i]<<endl;
}
Pretty self-explanatory; any way to make a number ends with adding 1 or multiplying two other expressions.
import qualified Data.MemoCombinators as Memo
complexity = Memo.integral c
where
c 1 = 1
c n = minimum $ (1 + complexity (n-1)) : [complexity f + complexity (n `div` f) | f <- [2..n-1], n `mod` f == 0]
main = print $ head $ dropWhile ((/= 13) . complexity) [1..]
I wrote a little script that would spit out the complexity of every number in a sequence of numbers (for example 1 to 1 0 0 ) and i got comlexity 1 3 for 4 6 , and indeed it could be writen out like the following:
4 6 = 2 3 × 2 = ( 1 1 × 2 + 1 ) × 2 = ( ( 5 × 2 + 1 ) × 2 + 1 ) × 2 ) = ( ( 1 + 1 + 1 + 1 + 1 ) × ( 1 + 1 ) + 1 ) × ( 1 + 1 ) + 1 ) × ( 1 + 1 ) )
So 1 3 one's goes into 4 6 , yet the 'correct' answer to this question is 4 7 , any clarification please?
P.S. after i got it wrong for entering 4 6 I tried 4 7 by pure luck.
46 = (9 X 5)+1 = (3 X 3 X 5)+1 = ((1+1+1) X (1+1+1) X (1+1+1+1+1))+1 so the complexity is 12 not 13. In the question complexity is defined as the cheapest number of 1's with which the number can be formed.
Log in to reply
Ah yes ty! in fact my code gives me a complexity 11 for 45 and 13 for 46 which isn't possible because you could just add 1 to 45 so the complexity of 46 couldn't be >12. I forgot to implement this condition before, but now that i have i think i'm on the right track :)
Sorry I am asking this here, how do I post my solution? All I can see is the comment sections to yours and Hema's post. How do I post mine, without having it show up as a comment to your post?
Here's my brute-force solution which also prints the equation:
def possibleCouples(z):
t=[]
for i in range(1,z/2+1):
t+=[[i,z-i,"+"]]
for i in range(2,int(z*.5)+1):
if z%i<1:
t+=[[i,z/i,"*"]]
return t
def cpst(i):
if i<2:
return (1,"1")
global b
if not b[i][0]:
a=possibleCouples(i)
m=999
for g,h,f in a:
j,k = cpst(g),cpst(h)
if j[0]+k[0] < m:
m = j[0]+k[0]
if f == "*":
c="("+j[1]+")"+f+"("+k[1]+")"
else:
c=j[1]+f+k[1]
b[i]=(m,c)
return b[i]
b=[[0,""]]*999
i=1
while cpst(i)[0]!=13: i+=1
print i,cpst(i)
And the output:
>>> print i,cpst(i)
47 (13, '1+1+(1+1+1)*((1+1+1)*(1+1+1+1+1))')
>>>
By the way,
>>> cpst(46)
(12, '1+(1+1+1)*((1+1+1)*(1+1+1+1+1))')
>>>
You can calculate the complexity of a number based on the complexity of the previous numbers, thereby defining it recursively.
Python solution:
def factor(n):
"""Returns the smallest factor of a number n, except 1 and n"""
for i in xrange(2,int(n ** (0.5))+1):
if n % i == 0:
return i
return None
data = {0:0, 1:1}
num = 2
while True:
f = float('inf')
x = factor(num)
if x:
f = data[x] + data[num/x]
r = min(map(lambda x: data[num-x] + x, xrange(1,num)))
data[num] = min([f,r])
if data[num] == 13:
print num, data[num]
break
num += 1
End result: 4 7
Problem Loading...
Note Loading...
Set Loading...
The c o m p l e x i t y ( x ) of a number x can be defined recursively as follows
{ x min ( c o m p l e x i t y ( x − i ) + c o m p l e x i t y ( i ) , c o m p l e x i t y ( x / j ) + c o m p l e x i t y ( j ) ) x ≤ 5 x ≥ 5 ; i ≤ n ; n ≡ 0 ( m o d j ) Scroll to the right to view full expression
Basically,the complexity of a number x equals the smaller of the two below values:
c o m p l e x i t y ( x − i ) + c o m p l e x i t y ( i ) for some i < x or
c o m p l e x i t y ( x / j ) + c o m p l e x i t y ( j ) for some divisor j of x
Memoizing the function saves a lot of time since values are saved and aren't recomputed whenever the recursive function is called more than once. In Python: