Integer chemistry III

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


The answer is 47.

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.

7 solutions

Thaddeus Abiy
Feb 16, 2014

The c o m p l e x i t y ( x ) complexity(x) of a number x x can be defined recursively as follows

{ x x 5 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 ; i n ; n 0 ( m o d j ) \begin{cases} x & x\leq 5 \\ \min(complexity(x-i)+complexity(i),complexity(x/j)+complexity(j)) & x\geq 5; \: i\leq n ;\: n\equiv 0 (mod j)\\ \end{cases} Scroll to the right to view full expression

Basically,the complexity of a number x x equals the smaller of the two below values:

  1. c o m p l e x i t y ( x i ) + c o m p l e x i t y ( i ) complexity(x-i)+complexity(i) for some i < x i<x or

  2. c o m p l e x i t y ( x / j ) + c o m p l e x i t y ( j ) complexity(x/j)+complexity(j) for some divisor j j of x 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
Save = {i:i for i in range(6)}
def Complexity(n):
    if n <= 5:return n
    if n in Save:return Save[n]
    Min=n
    for i in range(2,n):
        Sum = Complexity(n-i)+Complexity(i)
        if Sum < Min:Min = Sum
        if  n%i==0:
            Product = Complexity( n / i ) + Complexity( i )
            if Product < Min:Min = Product
    Save[n]=Min
    return Min       
n = 5
while complexity(n)!=13:
    n += 1
print n 

Tiny typo,The n n 's on the right side of the recursive function are all supposed to be x x 's

Thaddeus Abiy - 7 years, 3 months ago

Nice solution, but it doesn't follow PEP 8 with all those one-line if statements.

Eric Zhang - 7 years, 3 months ago

Log in to reply

Thanks..I know its not pythonic..was lazy I guess

Thaddeus Abiy - 7 years, 3 months ago

great easy to understand

Rush Apolonio - 6 years, 10 months ago
Hema Pola
Feb 13, 2014

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

Issa Saba
Feb 20, 2014

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;
}
Brian Chen
Feb 16, 2014

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..]
Christian Nader
Feb 13, 2014

I wrote a little script that would spit out the complexity of every number in a sequence of numbers (for example 1 1 to 100 100 ) and i got comlexity 13 13 for 46 46 , and indeed it could be writen out like the following:

46 = 23 × 2 = ( 11 × 2 + 1 ) × 2 = ( ( 5 × 2 + 1 ) × 2 + 1 ) × 2 ) = ( ( 1 + 1 + 1 + 1 + 1 ) × ( 1 + 1 ) + 1 ) × ( 1 + 1 ) + 1 ) × ( 1 + 1 ) ) 46 = 23\times 2 = (11\times 2+1)\times 2 = ((5\times 2+1)\times 2+1)\times 2) = ((1+1+1+1+1)\times (1+1)+1)\times (1+1)+1)\times (1+1))

So 13 13 one's goes into 46 46 , yet the 'correct' answer to this question is 47 47 , any clarification please?

P.S. after i got it wrong for entering 46 46 I tried 47 47 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.

kishore battula - 7 years, 3 months ago

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

christian nader - 7 years, 3 months ago

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?

Pragy Agarwal - 7 years, 3 months ago
Kim Phú Ngô
Mar 29, 2014

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))')
>>>
Eric Zhang
Feb 21, 2014

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: 47 \boxed{47}

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...