Peter Norvig
5 January 2016

Countdown to 2016

Alex Bellos posed this New Year's puzzle:

Fill in the blanks so that this equation makes arithmetical sense:

10 □ 9 □ 8 □ 7 □ 6 □ 5 □ 4 □ 3 □ 2 □ 1 = 2016

You are allowed to use only the four basic arithmetical operations: +, -, ×, ÷. But brackets (parentheses) can be used wherever needed. So, for example, the solution could begin

(10 - 9) × (8 ...

or

10 + (9 × 8) ...

Let's see if we can solve this puzzle, and some of the related ones from Alex's first and second post. We'll start with a simpler version of the puzzle.

Four Operators, No Brackets

Suppose for the moment we are not allowed to use brackets. Then there are nine blanks, each of which can be filled by one of four operators, so the total number of possible expressions is:

In [1]:
4 ** 9
Out[1]:
262144

That's small enough that we can just enumerate all the expressions and see if any evaluates to 2016. We will generate each expression as a string and then evaluate it with eval. But we need to catch errors such as dividing by zero, so we'll define a wrapper function, evaluate:

In [2]:
from __future__ import division

def evaluate(exp):
    "eval exp, or return None if there is an arithmetic error."
    try:
        return eval(exp)
    except ArithmeticError:
        return None

We'll try each of the four operators in each of the nine blanks, evaluate each resulting expression, and collect the ones that evaluate to 2016:

In [3]:
def solve_no_brackets(ops=('+', '-', '*', '/')):
    "All solutions to the countdown puzzle (with no brackets)."
    exps = ('10'+a+'9'+b+'8'+c+'7'+d+'6'+e+'5'+f+'4'+g+'3'+h+'2'+i+'1'
            for a in ops    for b in ops    for c in ops 
            for d in ops    for e in ops    for f in ops 
            for g in ops    for h in ops    for i in ops)
    return [exp for exp in exps if evaluate(exp) == 2016]
In [4]:
solve_no_brackets()
Out[4]:
[]

Too bad; we did all that work and didn't find a solution. What years can we find solutions for? Let's modify solve_no_brackets to take a collection of target years, and return a dict of the form {year: "expression"} for each expression that evaluates to one of the target years:

In [5]:
def solve_no_brackets(targets, ops=('+', '-', '*', '/')):
    "Solutions to the no-bracket countdown puzzle matching one of targets."
    exps = ('10'+a+'9'+b+'8'+c+'7'+d+'6'+e+'5'+f+'4'+g+'3'+h+'2'+i+'1'
            for a in ops    for b in ops    for c in ops 
            for d in ops    for e in ops    for f in ops 
            for g in ops    for h in ops    for i in ops)
    return {int(evaluate(exp)): exp
            for exp in exps if evaluate(exp) in targets}

Let's try it:

In [6]:
%time solve_no_brackets(range(1900, 2100))
CPU times: user 14 s, sys: 9.32 s, total: 23.3 s
Wall time: 23.7 s
Out[6]:
{1979: '10*9*8+7*6*5*4*3/2-1',
 1980: '10*9*8+7*6*5*4*3/2/1',
 1981: '10*9*8+7*6*5*4*3/2+1',
 2013: '10*9*8*7/6/5*4*3-2-1',
 2014: '10*9*8*7/6/5*4*3-2/1',
 2015: '10*9*8*7/6/5*4*3-2+1',
 2017: '10*9*8*7/6/5*4*3+2-1',
 2018: '10*9*8*7/6/5*4*3+2/1',
 2019: '10*9*8*7/6/5*4*3+2+1'}

Interesting: in the 20th and 21st centuries, there are only two "golden eras" where the countdown equation works: the three year period centered on 1980, and the seven year period that is centered on 2016, but omits 2016. Note it takes about half a minute to do the computation.

Four Operators, With Brackets

Now let's return to the original puzzle, with the brackets. How many ways are there of bracketing an expression with 9 binary operators? I happen to remember that this is given by the Catalan numbers, and we can look it up to find that there are 4862 diffferent bracketing. If we enumerated and evaluated all of them, 4862 times half a minute is 40 hours. I'm impatient, so I'd like a faster approach. One possibility would be to switch to a faster compiled language like C++ or Go. But I'll concentrate on a better algorithm and stick with Python.

I'll use the idea of dynamic programming: break the problem down into simpler subparts, and compute an answer for each subpart, and store intermediate results in a table so we don't need to re-compute them when we need them again.

How do we break the problem into parts? In general, any expression must consist of an operator with two operands (which might in turn be complex subexpressions). For example, a complete countdown expression might be of the form

(10 ... 8) + (7 ... 1)

where (10 ... 8) means some expression that starts with 10 and ends with 8. Of course we need not use '+' as the operator, and we need not split after the 8; we could use any of the four operators and split anywhere. Let's start by defining c10 as the tuple of integers forming the countdown from 10 to 1, and the function splits to split a tuple in all ways:

In [7]:
c10 = (10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

def splits(items):
    "Split sequence of items into two non-empty parts, in all ways."
    return [(items[:i], items[i:]) 
            for i in range(1, len(items))]
In [8]:
splits(c10)
Out[8]:
[((10,), (9, 8, 7, 6, 5, 4, 3, 2, 1)),
 ((10, 9), (8, 7, 6, 5, 4, 3, 2, 1)),
 ((10, 9, 8), (7, 6, 5, 4, 3, 2, 1)),
 ((10, 9, 8, 7), (6, 5, 4, 3, 2, 1)),
 ((10, 9, 8, 7, 6), (5, 4, 3, 2, 1)),
 ((10, 9, 8, 7, 6, 5), (4, 3, 2, 1)),
 ((10, 9, 8, 7, 6, 5, 4), (3, 2, 1)),
 ((10, 9, 8, 7, 6, 5, 4, 3), (2, 1)),
 ((10, 9, 8, 7, 6, 5, 4, 3, 2), (1,))]

Now what I would like to do is build up a table that says, for every subsequence of the numbers, what are the expressions we can make with those numbers, and what do they evaluate to? We'll call the table EXPS. For example, with the subsequence (10, 9, 8), we would have:

EXPS[(10, 9, 8)] = {
  27: '((10+9)+8)',
  8:  '((10-9)*8)', 
  -7: '(10-(9+8))', 
  ...}

We'll do the same for every other subsequence, for example:

EXPS[(7, 6, 5, 4, 3, 2, 1)] = {
  1:   '((((7/((6/5)-4))+3)*2)*1)',
  2:   '((((7/((6/5)-4))+3)*2)+1)',
  3.5: '((((7/((6/5)-4))+3)+2)+1)',
  4:   '((7-((6/5)*((4/3)+2)))+1)',
  ...}

Once we have the tables for these two subsequences, we can put them together to get the table for the complete countdown(10) by considering all ways of taking a value from the first table, then one of the four operators, then a value from the second table. For example, taking the first entry from each table, and the operator '+', we would have:

EXPS[(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)] = { 
  28: '(((10+9)+8)+((((7/((6/5)-4))+3)*2)*1))',
  ...}


I can implement EXPS as a defaultdict of dicts, and define expressions(numbers) to fill in EXPS entries for numbers and all sub-sequences of numbers. Within fill_tables, note that Lnums and Rnums are sequences of numbers, such as (10, 9, 8) and (7, 6). L and R are values, such as 27 and 1. And Lexp and Rexp are strings, such as "((10+9)+8)" and "(7-6)". Rather than catching division-by-zero errors, we just avoid the division when the denominator is 0.

In [9]:
from collections import defaultdict, Counter
import itertools

EXPS = defaultdict(dict) # e.g., EXPS[(10, 9, 8)][27] == '((10+9)+8)'

def expressions(numbers):
    "Fill EXPS table for numbers, and all sub-sequences of numbers. Return EXPS[numbers]"
    if numbers in EXPS: # Already did the work
        pass
    elif len(numbers) == 1: # Only one way to make an expression out of a single number
        expr(numbers, numbers[0], str(numbers[0]))
    else: # Split in all ways; fill tables for left and right; combine tables in all ways
        for (Lnums, Rnums) in splits(numbers):
            for (L, R) in itertools.product(expressions(Lnums), expressions(Rnums)):
                Lexp, Rexp = '(' + EXPS[Lnums][L], EXPS[Rnums][R] + ')'
                if R != 0: 
                    expr(numbers, L / R, Lexp + '/' + Rexp)
                expr(numbers, L * R, Lexp + '*' + Rexp)
                expr(numbers, L - R, Lexp + '-' + Rexp)
                expr(numbers, L + R, Lexp + '+' + Rexp)
    return EXPS[numbers]

def expr(numbers, value, exp): 
    "Record exp as an expression with the given value, covering the sequence of numbers."
    EXPS[numbers][value] = exp

Let's give it a try:

In [10]:
expressions((10, 9, 8))
Out[10]:
{-62: '(10-(9*8))',
 -7: '((10-9)-8)',
 -6.888888888888889: '((10/9)-8)',
 0.125: '((10-9)/8)',
 0.1388888888888889: '((10/9)/8)',
 0.5882352941176471: '(10/(9+8))',
 2.375: '((10+9)/8)',
 8: '((10-9)*8)',
 8.875: '(10-(9/8))',
 8.88888888888889: '((10/9)*8)',
 9: '((10-9)+8)',
 9.11111111111111: '((10/9)+8)',
 10.0: '(10*(9-8))',
 11: '((10+9)-8)',
 11.125: '(10+(9/8))',
 11.25: '((10*9)/8)',
 27: '((10+9)+8)',
 82: '((10*9)-8)',
 98: '((10*9)+8)',
 152: '((10+9)*8)',
 170: '(10*(9+8))',
 720: '((10*9)*8)'}
In [11]:
EXPS[(10, 9, 8)][27]
Out[11]:
'((10+9)+8)'

That looks reasonable. Let's solve the whole puzzle.

Countdown to 2016: A Solution

In [12]:
%time expressions(c10)[2016]
CPU times: user 40.9 s, sys: 14.6 s, total: 55.5 s
Wall time: 55.6 s
Out[12]:
'(((((((10+((9*8)*7))-6)-5)*4)+3)+2)-1)'

We have an answer! And in a lot less than 40 hours, thanks to dynamic programming!

Removing unnecessry brackets, this equation is equivalent to:

In [13]:
(10 + 9 * 8 * 7 - 6 - 5) * 4 + 3 + 2 - 1
Out[13]:
2016

Counting Solutions

Alex Bellos had another challenge:

I was half hoping a computer scientist would let me know exactly how many solutions there are with only the four basic operations. Maybe someone will.

As it stands, my program can't answer that question, because I only keep one expression for each value.

Also, I'm not sure what it means to be a distinct solution. For example, are ((10+9)+8) and (10+(9+8)) different, or are they same, because they both are equivalent to (10+9+8)? Similarly, are ((3-2)-1) and (3-(2+1) different, or the same because they both are equivalent to (3 + -2 + -1)? I think the notion of "distinct solution" is just inherently ambiguous, and each of these questions could reasonably be answered either way. My choice is to count each of these as distinct: every expression has exactly ten numbers, nine operators, and nine pairs of brackets, and if an expression differs in any character, it is different. But I won't argue with anyone who has a different definition of "distinct solution."

So how can I count expressions? One approach would be to go back to enumerating every equation (all 4862 × 49 = 1.2 bilion of them) and checking which ones equal 2016. That would take about 40 hours with my Python program, but I could get it under 40 minutes in a more efficient language.

Another approach is to count subexpressions as the table is filled in. We won't enumerate all the expressions, just count them. I'll introduce a second table, COUNTS, such that

COUNTS[(10, 9, 8)][27] == 2

because there are 2 ways to make 27 with the numbers (10, 9, 8), namely, ((10+9)+8) and (10+(9+8)). How do we compute the counts? By looking at every split and operator choice that can make the value, and summing up (over all of these) the product of the counts for the two sides. For example, there are 2 ways to make 27 with (10 ... 8), and it turns out there are 3526 ways to make 1 with (7 ... 1). So there are 2 × 3526 = 7052 ways to make 28 with this split by adding 27 and 1.

I'll make expr handle COUNTS as well as EXPS. And I'll define clear to clear out the cache of COUNTS and EXPS, so that we can fill the tables with our new, improved entries.

In [14]:
COUNTS = defaultdict(Counter) # e.g., COUNTS[(10, 9, 8)][27] == 2

def expressions(numbers):
    "Fill EXPS table for numbers, and all sub-sequences of numbers. Return EXPS[numbers]"
    if numbers in EXPS: # Already did the work
        pass
    elif len(numbers) == 1: # Only one way to make an expression out of a single number
        expr(numbers, numbers[0], str(numbers[0]), 1)
    else: # Split in all ways; fill tables for left and right; combine tables in all ways
        for (Lnums, Rnums) in splits(numbers):
            for (L, R) in itertools.product(expressions(Lnums), expressions(Rnums)):
                Lexp, Rexp = '(' + EXPS[Lnums][L], EXPS[Rnums][R] + ')'
                count = COUNTS[Lnums][L] * COUNTS[Rnums][R]
                if R != 0: 
                    expr(numbers, L / R, Lexp + '/' + Rexp, count)
                expr(numbers, L * R, Lexp + '*' + Rexp, count)
                expr(numbers, L - R, Lexp + '-' + Rexp, count)
                expr(numbers, L + R, Lexp + '+' + Rexp, count)
    return EXPS[numbers]

def expr(numbers, val, exp, count):
    "Fill EXPS[numbers][val] with exp, and increment COUNTS."
    EXPS[numbers][val] = exp
    COUNTS[numbers][val] += count
    
def clear(): EXPS.clear(); COUNTS.clear()
In [15]:
clear()
expressions((10, 9, 8))
Out[15]:
{-62: '(10-(9*8))',
 -7: '((10-9)-8)',
 -6.888888888888889: '((10/9)-8)',
 0.125: '((10-9)/8)',
 0.1388888888888889: '((10/9)/8)',
 0.5882352941176471: '(10/(9+8))',
 2.375: '((10+9)/8)',
 8: '((10-9)*8)',
 8.875: '(10-(9/8))',
 8.88888888888889: '((10/9)*8)',
 9: '((10-9)+8)',
 9.11111111111111: '((10/9)+8)',
 10.0: '(10*(9-8))',
 11: '((10+9)-8)',
 11.125: '(10+(9/8))',
 11.25: '((10*9)/8)',
 27: '((10+9)+8)',
 82: '((10*9)-8)',
 98: '((10*9)+8)',
 152: '((10+9)*8)',
 170: '(10*(9+8))',
 720: '((10*9)*8)'}
In [16]:
COUNTS[(10, 9, 8)]
Out[16]:
Counter({-62: 1,
         -7: 2,
         -6.888888888888889: 1,
         0.125: 1,
         0.1388888888888889: 2,
         0.5882352941176471: 1,
         2.375: 1,
         8: 1,
         8.875: 1,
         8.88888888888889: 2,
         9: 2,
         9.11111111111111: 1,
         10.0: 2,
         11: 2,
         11.125: 1,
         11.25: 2,
         27: 2,
         82: 2,
         98: 1,
         152: 1,
         170: 1,
         720: 2})
In [17]:
COUNTS[(10, 9, 8)][27]
Out[17]:
2

Looks good to me. Now let's repeat the computation, this time keeping track of COUNTS:

In [18]:
clear()

%time expressions(c10)[2016]
CPU times: user 1min 21s, sys: 26.4 s, total: 1min 48s
Wall time: 1min 48s
Out[18]:
'(((((((10+((9*8)*7))-6)-5)*4)+3)+2)-1)'

The Answer (?)

Now we can read off the answer:

In [19]:
COUNTS[c10][2016]
Out[19]:
30066

This says there are 30,066 distinct expressions for 2016.

But I don't believe it.

We'll see why in a bit, but first some trivia questions to answer:

  • How many distinct values can be made?
In [20]:
len(expressions(c10))
Out[20]:
5789961
  • What's the smallest positive integer than cannot be made?
In [21]:
import itertools 

def unmakeable(numbers):
    "Smallest positive integer than can't be made by numbers."
    return next(i for i in itertools.count(0) if i not in expressions(numbers))

unmakeable(c10)
Out[21]:
10843
  • What is the expected theoretical number of expressions? It is Catalan(9) × 49:
In [22]:
4862 * 4 ** 9
Out[22]:
1274544128
  • How many expressions were actually entered in the COUNTS table?
In [23]:
sum(COUNTS[c10].values())
Out[23]:
1264876734

So, about 1% of the 1.27 billion theoretically possible expressions do not appear in COUNTS; these are the ZeroDivisionErrors.

Dealing with Round-off Errors

Why don't I believe the answer of 30,066 expressions? Because floating point division can have round-off errors. For example:

In [24]:
2015 + 1/3 + 1/3 + 1/3
Out[24]:
2015.9999999999998
In [25]:
2015 + 1/3 + 1/3 + 1/3 == 2016
Out[25]:
False

So there might be perfectly good solutions that are hiding in the EXPS table under 2015.9999999999998 (or some similar number) when they should be exactly 2016. Let's find all the values that are very near to 2016:

In [26]:
{val for val in expressions(c10)
 if abs(val - 2016) < 0.0001}
Out[26]:
{2015.999999999997,
 2015.999999999999,
 2015.9999999999993,
 2015.9999999999995,
 2015.9999999999998,
 2016.0,
 2016.0000000000002,
 2016.0000000000005,
 2016.0000000000018,
 2016.000000000002,
 2016.0000000000023}

I suspect that all of these actually should be exactly 2016.

To find out for sure, let's re-do all the calculations using exact rational arithmetic, as provided by the fractions.Fraction data type. From experience I know that this will be an order of magnitude slower, so we're looking at maybe a 20 minute computation.

I'll replace the computation L / R with divide(L, R), which calls Fraction. To mitigate the expense of this computation, I make two optimizations. First, divide replaces a whole fraction, such as Fraction(6, 2), with an int, such as 3. Second, I modify expr to not fill in the EXPS[c10] table, except for EXPS[c10][2016]. The rationale is that we don't need the other entries, and by not storing them, we save a lot of memory, and thus save garbage collection time.

In [27]:
from fractions import Fraction

def expressions(numbers):
    "Fill EXPS table for numbers, and all sub-sequences of numbers. Return EXPS[numbers]"
    if numbers in EXPS: # Already did the work
        pass
    elif len(numbers) == 1: # Only one way to make an expression out of a single number
        expr(numbers, numbers[0], str(numbers[0]), 1)
    else: # Split in all ways; fill tables for left and right; combine tables in all ways
        for (Lnums, Rnums) in splits(numbers):
            for (L, R) in itertools.product(expressions(Lnums), expressions(Rnums)):
                Lexp, Rexp = '(' + EXPS[Lnums][L], EXPS[Rnums][R] + ')'
                count = COUNTS[Lnums][L] * COUNTS[Rnums][R]
                if R != 0: 
                    expr(numbers, divide(L, R), Lexp + '/' + Rexp, count)
                expr(numbers, L * R, Lexp + '*' + Rexp, count)
                expr(numbers, L - R, Lexp + '-' + Rexp, count)
                expr(numbers, L + R, Lexp + '+' + Rexp, count)
    return EXPS[numbers]

def divide(L, R):
    "Exact rational division of L/R."
    f = Fraction(L, R)
    return f.numerator if f.denominator == 1 else f

def expr(numbers, value, exp, count):
    "Fill EXPS[numbers][val] with exp, and increment COUNTS."
    if numbers == c10 and value != 2016: 
        return
    EXPS[numbers][value] = exp
    COUNTS[numbers][value] += count

The Answer (!)

In [28]:
clear()

%time expressions(c10)[2016]
CPU times: user 11min 57s, sys: 704 ms, total: 11min 58s
Wall time: 11min 59s
Out[28]:
'(((((((10+((9*8)*7))-6)-5)*4)+3)+2)-1)'
In [29]:
COUNTS[c10][2016]
Out[29]:
44499

That did indeed take about ten times longer, but we now have an answer that I have more confidence in (but I wouldn't accept it as definitive until it was independently verified or I had an extensive tst suite). And of course, if you have a different definition of "distinct solution," you will get a different answer.

Dealing with the Exponentiation Operator

Now let's turn to another of Alex's puzzles: making 2016 and other target values from a string of four or five 4s, with exponentiation allowed. Exponentiation is tricky for five reasons:

  • Division by zero: (0 ** -1) is the same as (1 / 0), and gives a ZeroDivisionError.
  • Irrationals: (2 ** (1 / 2)) is an irrational number; so we can't do exact rational arithmetic.
  • Imaginaries: (-1 ** (1 / 2)) is an imaginary number, but Python gives a ValueError.
  • Overflow: (10. ** (9. ** 8.)), as a float, gives a OverflowError.
  • Finite memory: (10 ** (9 ** (8 * 7))), as an int, gives an OutOfMemoryError (even if your memory was expanded to use every atom in the universe).

How do we deal with this? We can't do exact rational arithmetic. We could try to do exact algebra, perhaps using SymPy, but that seems difficult and computationally expensive, so instead I will abandon the goal of exact computation, and do everything in the domain of floats (reluctantly accepting that there will be some round-off errors). We'll coerce numbers to floats when we first put them in the table, and all subsequent operations will be with floats. I define a new function, expr2, to call expr, catching arithmetic errors. Since we are making some rather arbitrary decisions about what expressions are allowed (e.g. imaginary numbers are not), I'll give up on trying to maintain COUNTS.

In [30]:
from operator import add, sub, mul, truediv

def expressions(numbers):
    "Fill EXPS table for numbers, and all sub-sequences of numbers. Return EXPS[numbers]"
    if numbers in EXPS: # Already did the work
        pass
    elif len(numbers) == 1: # Only one way to make an expression out of a single number
        expr(numbers, float(numbers[0]), str(numbers[0]))
    else: # Split in all ways; fill tables for left and right; combine tables in all ways
        for (Lnums, Rnums) in splits(numbers):
            for (L, R) in itertools.product(expressions(Lnums), expressions(Rnums)):
                Lexp, Rexp = '(' + EXPS[Lnums][L], EXPS[Rnums][R] + ')'
                expr2(numbers, L, pow,     R, Lexp + '**' + Rexp)
                expr2(numbers, L, truediv, R, Lexp + '/'  + Rexp)
                expr2(numbers, L, mul,     R, Lexp + '*'  + Rexp)
                expr2(numbers, L, add,     R, Lexp + '+'  + Rexp)
                expr2(numbers, L, sub,     R, Lexp + '-'  + Rexp)
    return EXPS[numbers]

def expr2(numbers, L, op, R, exp): 
    "Fill table entries for op(L, R), catching errors."
    try:
        expr(numbers, op(L, R), exp)
    except (ArithmeticError, ValueError):
        pass
    
def expr(numbers, value, exp): EXPS[numbers][value] = exp

Now we can solve the "2016 with five fours" puzzle:

In [31]:
clear()

expressions((4, 4, 4, 4, 4))[2016]
Out[31]:
'(((4**4)-4)*(4+4))'

I'll define a function to create a table of makeable integers:

In [32]:
def makeable(numbers):
    "A table of {i: expression} for all integers i from 0 up to first unmakeable."
    targets = range(unmakeable(numbers))
    return {i: expressions(numbers)[i]
            for i in targets}

We'll use this to see if we can solve the "0 to 9 with four fours" puzzle:

In [33]:
makeable((4, 4, 4, 4))
Out[33]:
{0: '(((4+4)-4)-4)',
 1: '(((4+4)-4)/4)',
 2: '((4/(4+4))*4)',
 3: '(((4+4)+4)/4)',
 4: '(((4-4)*4)+4)',
 5: '(((4*4)+4)/4)',
 6: '(((4+4)/4)+4)',
 7: '((4-(4/4))+4)',
 8: '(((4+4)-4)+4)',
 9: '(((4/4)+4)+4)'}

Yes: we can get 0 to 9 (but not 10).

Now I'll see what integers we can make with five fives. Legend has it that you can get all the way up to 55:

In [34]:
ff = (5, 5, 5, 5, 5)

makeable(ff)
Out[34]:
{0: '((((5-5)*5)-5)+5)',
 1: '(((5-(5*5))/5)+5)',
 2: '((((5+5)/5)-5)+5)',
 3: '((((5*5)-5)-5)/5)',
 4: '((((5-5)-5)/5)+5)',
 5: '((5/((5**5)**5))+5)',
 6: '((((5/5)+5)*5)/5)',
 7: '(((5/5)+(5/5))+5)',
 8: '((((5+5)+5)/5)+5)',
 9: '((((5+5)*5)-5)/5)',
 10: '((((5*5)-5)-5)-5)',
 11: '((((5+5)*5)+5)/5)',
 12: '((((5+5)/5)+5)+5)'}

We didn't get there.

More Operations

With some research, I see that others who got up to 55 with five 5s used these three concepts:

  • digit concatenation: 55
  • decimal point: .5
  • unary operations:
    • factorial: 5! = 120
    • square root: √ 5

We'll refactor expressions to call these three new subfunctions:

  • digit_expressions: For every subsequence of numbers, we'll smush the digits together, and then make a table entry for those resulting digits as an integer, and with a decimal point in each possible position.
  • binary_expressions: The code that previously was the main body of expressions.
  • unary_expressions: Apply the unary operators to every entry in the table. (Because it applies to entries already in the table, make sure to call unary_expressions last.)

We'll still do all computation in the domain of floats.

In [35]:
from math import sqrt, factorial

def expressions(numbers):
    "Fill EXPS table for numbers, and all sub-sequences of numbers. Return EXPS[numbers]"
    if numbers not in EXPS: 
        digit_expressions(numbers)
        binary_expressions(numbers)
        unary_expressions(numbers)
    return EXPS[numbers]

def digit_expressions(numbers):
    "Fill tables with expressions made from the digits of numbers, and a decimal point."
    exp = ''.join(str(n) for n in numbers)
    expr(numbers, float(exp), exp)
    for d in range(len(exp)):
        decimal = exp[:d] + '.' + exp[d:]
        expr(numbers, float(decimal), decimal)
            
def binary_expressions(numbers):
    "Fill tables with all expressions formed by splitting numbers and combining with an op."
    for (Lnums, Rnums) in splits(numbers):
        for (L, R) in itertools.product(expressions(Lnums), expressions(Rnums)):
            Lexp, Rexp = '(' + EXPS[Lnums][L], EXPS[Rnums][R] + ')'
            if 1 <= R <= 10 and (L > 0 or int(R) == R):
                expr2(numbers, L, pow, R, Lexp + '**' + Rexp)
            expr2(numbers, L, truediv, R, Lexp + '/'  + Rexp)
            expr2(numbers, L, mul,     R, Lexp + '*'  + Rexp)
            expr2(numbers, L, add,     R, Lexp + '+'  + Rexp)
            expr2(numbers, L, sub,     R, Lexp + '-'  + Rexp)
            
def unary_expressions(numbers):
    for v in list(EXPS[numbers]):
        exp = EXPS[numbers][v]
        if v > 0: 
            expr(numbers, sqrt(v), '√' + exp)
        if 2 <= v <= 6 and v == int(v):
            expr(numbers, factorial(v), exp + '!')

Now that we have more variety in the types of expressions formed, I want to choose a "good" expression to represent each value. I'll modify expr so that when there are multiple expressions for a value, it chooses the one with the least "weight," where I define weight as the length of the string, plus a penalty of 1 for every square root sign (just because square root feels "heavier" than the other operations):

In [36]:
def expr(numbers, value, exp): 
    if value not in EXPS[numbers] or weight(exp) < weight(EXPS[numbers][value]):
        EXPS[numbers][value] = exp
        
def weight(exp): return len(exp) + exp.count('√')

We'll try again:

In [37]:
clear()

%time makeable(ff)
CPU times: user 57.4 s, sys: 19.2 s, total: 1min 16s
Wall time: 1min 17s
Out[37]:
{0: '(5*(55-55))',
 1: '((55/55)**5)',
 2: '(55/(.5*55))',
 3: '√(5!-(555/5))',
 4: '(5-(55/55))',
 5: '(5.55-.55)',
 6: '(5+(55/55))',
 7: '(((5+55)/5)-5)',
 8: '(.5*(5+(55/5)))',
 9: '(5!-(555/5))',
 10: '(5!-(55+55))',
 11: '(5.5/(5.5-5))',
 12: '(5!/(55/5.5))',
 13: '((5+(5+55))/5)',
 14: '((5*5)-(55/5))',
 15: '(5+(55/5.5))',
 16: '(5+(5.5+5.5))',
 17: '(5+((5+55)/5))',
 18: '(5+((5!-55)/5))',
 19: '((5*5)-(.5+5.5))',
 20: '(55/(5*.55))',
 21: '(5+(5+(55/5)))',
 22: '((55+55)/5)',
 23: '((5+(55/.5))/5)',
 24: '(5-(55/55))!',
 25: '(55-(5+(5*5)))',
 26: '(55-(5+(5!/5)))',
 27: '(.5*(55-(5/5)))',
 28: '(.5*(.5+55.5))',
 29: '(5+(5!/(5.5-.5)))',
 30: '(5*((55/5)-5))',
 31: '(55-(5-(5/5))!)',
 32: '(55-((5!-5)/5))',
 33: '(.55*(5+55))',
 34: '((5!+(55-5))/5)',
 35: '(5+(55-(5*5)))',
 36: '((5*5)+(55/5))',
 37: '((5!+(5!-55))/5)',
 38: '(5+(.5*(5!*.55)))',
 39: '(((5*5)-5.5)/.5)',
 40: '(55-(5+(5+5)))',
 41: '(5!-((5!/5)+55))',
 42: '((5+5.5)/(.5*.5))',
 43: '(55-(5!/(5+5)))',
 44: '(55-(55/5))',
 45: '((5*5!)-555)',
 46: '(55-((5-.5)/.5))',
 47: '((5!/5)+((5!-5)/5))',
 48: '(5!/(5*(5.5-5)))',
 49: '(55-(.5+5.5))',
 50: '(55.5-5.5)',
 51: '(.5+(55.5-5))',
 52: '(55-(.5+(.5*5)))',
 53: '(55.5-(.5*5))',
 54: '(((5*55)-5)/5)',
 55: '(.5*(55+55))',
 56: '((5+(5*55))/5)',
 57: '(55+((5+5)/5))',
 58: '((.5*5)+55.5)',
 59: '(5+(55-(5/5)))',
 60: '(5+(55.5-.5))',
 61: '(5.5+55.5)',
 62: '((55-(5!/5))/.5)',
 63: '(5.5+(.5*(5!-5)))',
 64: '(5!-(.5+55.5))',
 65: '(.5+(5!-55.5))',
 66: '(55+(55/5))',
 67: '(55+(5!/(5+5)))',
 68: '(5.5+(.5*(5+5!)))',
 69: '(5!-((.5+(5*5))/.5))',
 70: '(5+(5+(5+55)))',
 71: '((.5*5!)+(55/5))',
 72: '((.5+5.5)!/(5+5))',
 73: '((5*5)+(5!/(.5*5)))',
 74: '((5!/5)+(55-5))',
 75: '((5*5)+(55-5))',
 76: '(5+(5+(5!*.55)))',
 77: '(5+(.5*(5!+(5!/5))))',
 78: '(55+((5!-5)/5))',
 79: '(55+(5-(5/5))!)',
 80: '(5*(5+(55/5)))',
 81: '((√.5+(5!/√(5-.5)))/√.5)',
 82: '(5!-(((5!/5)-5)/.5))',
 83: '((.5*5!)+((5!-5)/5))',
 84: '(5+((5!/5)+55))',
 85: '(5+((5*5)+55))',
 86: '((55/.5)-(5!/5))',
 87: '((555-5!)/5)',
 88: '(.5+(.5*(5!+55)))',
 89: '(5!-(55-(5!/5)))',
 90: '(5!-(55-(5*5)))',
 91: '((5*5)+(5!*.55))',
 92: '(5!-(.5+(.5*55)))',
 93: '(.5+(5!-(.5*55)))',
 94: '(5!-((5/5)+(5*5)))',
 95: '(((55-5)/.5)-5)',
 96: '(5!-(5!/(5.5-.5)))',
 97: '(5!-((5!/5)-(5/5)))',
 98: '(5!-(55/(.5*5)))',
 99: '((55-5.5)/.5)',
 100: '((55/.5)-(5+5))',
 101: '((55.5-5)/.5)',
 102: '(5+(5!-((5!-5)/5)))',
 103: '(55+(5!/(.5*5)))',
 104: '(5!-(5+(55/5)))',
 105: '(55+(55-5))',
 106: '((555/5)-5)',
 107: '(5!-((5!-55)/5))',
 108: '(5!-((5+55)/5))',
 109: '(5!-(5.5+5.5))',
 110: '((555-5)/5)',
 111: '(555/√(5*5))',
 112: '((5+555)/5)',
 113: '(5!-(5+((5+5)/5)))',
 114: '(5+(5!-(55/5)))',
 115: '(5+(55+55))',
 116: '(5+(555/5))',
 117: '(5!-(5.5-(.5*5)))',
 118: '(5!-(5!/(5+55)))',
 119: '(5!-(55/55))',
 120: '(5.55-.55)!',
 121: '(5!+(55/55))',
 122: '(5!+(5!/(5+55)))',
 123: '(5!+(5.5-(.5*5)))',
 124: '(5!+√(5+(55/5)))',
 125: '(.5*(5*(55-5)))',
 126: '(5!+((55/5)-5))',
 127: '((5!/(5/5.5))-5)',
 128: '(5!+(5.5+(.5*5)))',
 129: '((5!-55.5)/.5)',
 130: '(5!+(55/5.5))',
 131: '(5!+(5.5+5.5))',
 132: '(5!*(.55+.55))',
 133: '(5!+((5!-55)/5))',
 134: '((5!/5)+(55/.5))',
 135: '((5!+555)/5)',
 136: '(5+(5!+(55/5)))',
 137: '(5+(5!/(5/5.5)))',
 138: '(.5+(.5*(5*55)))',
 139: '(((.5+5.5)!/5)-5)',
 140: '(.5*(5+(5*55)))',
 141: '(5!+((5+5.5)/.5))',
 142: '(5!+(55/(.5*5)))',
 143: '(((.5+5.5)!-5)/5)',
 144: '(((55/5)-5)!/5)',
 145: '(5!+(.5*(55-5)))',
 146: '(5!+((5/5)+(5*5)))',
 147: '(5!+((.5*55)-.5))',
 148: '(.5+(5!+(.5*55)))',
 149: '(5+((.5+5.5)!/5))',
 150: '(5*(55-(5*5)))',
 151: '(5!+(55-(5!/5)))',
 152: '(5!+(((5+5)/5)**5))',
 153: '(5!+(.5*(5!*.55)))',
 154: '(5+(5+(5!+(5!/5))))',
 155: '(5*(55-(5!/5)))',
 156: '((5!+(5!*5.5))/5)'}

Wow! We almost tripled the 55 goal! I have to say, I would never have come up with the solution for 81 on my own. It works because (√(5 - .5) * √0.5) = √(4.5 * 0.5) = (√2.25) = 1.5.

Even More Operations

At the risk of making the computation take even longer, I'm going to add two more operations:

  • Floor: ⌊x⌋ is the largest integer less than or equal to x (in other words, rounding down).
  • Ceiling: ⌈x⌉ is the smallest integer greater than or equal to x (in other words, rounding up).

These operations are useful because they produce integers, and our targets are the integers (from 0 up to whatever).

In addition, I'll allow two consecutive applications of unary operators, thus allowing expressions such as

  • ⌊√5⌋ = 2
  • ⌈5.5⌉! = 720

But still not allowing three consecutive applications, such as

  • ⌈√5⌉! = 6

To compensate for these new expressions, I'll be pickier about when I allow the square root function to apply.

In [38]:
from math import floor, ceil

def unary_expressions(numbers):
    for i in range(2):
        for v in list(EXPS[numbers]):
            exp = EXPS[numbers][v]
            if 0 < v <= 100 and 4*v == round(4*v):
                expr(numbers, sqrt(v), '√' + exp)
            if 2 <= v <= 6 and v == round(v):
                expr(numbers, factorial(v), exp + '!')
            if v != round(v):
                uexp = unbracket(exp)
                expr(numbers, floor(v), '⌊' + uexp + '⌋')
                expr(numbers, ceil(v),  '⌈' + uexp + '⌉')
            
def unbracket(exp):
    "Remove outer brackets from exp if they are there."
    if exp.startswith('(') and exp.endswith(')'):
        return exp[1:-1]
    else:
        return exp

Let's try:

In [39]:
clear()

%time makeable(ff)
CPU times: user 3min 16s, sys: 1min 6s, total: 4min 23s
Wall time: 4min 23s
Out[39]:
{0: '⌊.55555⌋',
 1: '⌈.55555⌉',
 2: '⌊5*.5555⌋',
 3: '⌈5*.5555⌉',
 4: '⌊5-.5555⌋',
 5: '⌊5.5555⌋',
 6: '⌈5.5555⌉',
 7: '⌈.5+5.555⌉',
 8: '⌈√55+.555⌉',
 9: '⌊55/5.55⌋',
 10: '⌊555/55⌋',
 11: '⌈555/55⌉',
 12: '⌈55.55/5⌉',
 13: '⌈√5*5.555⌉',
 14: '⌈√55/.555⌉',
 15: '(5+(55/5.5))',
 16: '(5+⌊55.5/5⌋)',
 17: '(5+⌈55.5/5⌉)',
 18: '⌊55/⌈5*.55⌉⌋',
 19: '⌈55/⌈5*.55⌉⌉',
 20: '(5*⌊5-.555⌋)',
 21: '⌊5!/5.555⌋',
 22: '⌈5!/5.555⌉',
 23: '⌈555/(5*5)⌉',
 24: '⌊5-.5555⌋!',
 25: '(5*⌊5.555⌋)',
 26: '(⌈.55*55⌉-5)',
 27: '⌊5*5.555⌋',
 28: '⌈5*5.555⌉',
 29: '(5+⌊5-.555⌋!)',
 30: '⌊55*.555⌋',
 31: '⌈55*.555⌉',
 32: '(5+⌊5*5.55⌋)',
 33: '(5+⌈5*5.55⌉)',
 34: '⌈⌈5.5⌉*5.55⌉',
 35: '(5+⌊.55*55⌋)',
 36: '(5+⌈.55*55⌉)',
 37: '⌊5*(55/√55)⌋',
 38: '⌊⌊√55⌋*5.55⌋',
 39: '⌊√.5*55.55⌋',
 40: '⌊5.5*√55.5⌋',
 41: '⌊√55*5.55⌋',
 42: '⌈√55*5.55⌉',
 43: '(55-⌊5+√55⌋)',
 44: '(55-(55/5))',
 45: '(5*⌊5/.555⌋)',
 46: '⌊5555/5!⌋',
 47: '⌈5555/5!⌉',
 48: '⌈55-√55.5⌉',
 49: '⌊55-5.55⌋',
 50: '⌊55.55-5⌋',
 51: '⌈55.55-5⌉',
 52: '(55-⌈5*.55⌉)',
 53: '⌊55.55-√5⌋',
 54: '⌊55-.555⌋',
 55: '⌊55.555⌋',
 56: '⌈55.555⌉',
 57: '⌈.5+55.55⌉',
 58: '⌈√5+55.55⌉',
 59: '(5+⌊55-.55⌋)',
 60: '⌊5+55.55⌋',
 61: '⌈5+55.55⌉',
 62: '⌊√55+55.5⌋',
 63: '⌈√55+55.5⌉',
 64: '⌊5!-55.55⌋',
 65: '⌈5!-55.55⌉',
 66: '⌊5!*.5555⌋',
 67: '⌈5!*.5555⌉',
 68: '(5+⌈55+√55⌉)',
 69: '⌊555/⌈√55⌉⌋',
 70: '⌈555/⌈√55⌉⌉',
 71: '(5+⌊5!*.555⌋)',
 72: '(5+⌈5!*.555⌉)',
 73: '(5!-⌊55-√55⌋)',
 74: '⌊555/√55⌋',
 75: '⌈555/√55⌉',
 76: '(55+⌊5!/5.5⌋)',
 77: '(55+⌈5!/5.5⌉)',
 78: '⌊55.55/√.5⌋',
 79: '⌊555/⌊√55⌋⌋',
 80: '⌊(5*5)+55.5⌋',
 81: '⌈(5*5)+55.5⌉',
 82: '(55+⌊.5*55⌋)',
 83: '(55+⌈.5*55⌉)',
 84: '(5+((5!/5)+55))',
 85: '(5+(55+(5*5)))',
 86: '⌊⌈5+55.5⌉/√.5⌋',
 87: '((555-5!)/5)',
 88: '⌈√5**5.555⌉',
 89: '(5!-⌈.55*55⌉)',
 90: '⌊(55-5)/.55⌋',
 91: '⌈(55-5)/.55⌉',
 92: '⌊555/⌈5.5⌉⌋',
 93: '⌈555/⌈5.5⌉⌉',
 94: '(⌊55/.55⌋-5)',
 95: '(⌈55/.55⌉-5)',
 96: '⌊.55*(5!+55)⌋',
 97: '⌈.55*(5!+55)⌉',
 98: '(⌊55-5.5⌋/.5)',
 99: '⌊55/.555⌋',
 100: '⌊555/5.5⌋',
 101: '⌈555/5.5⌉',
 102: '⌈⌈55.5⌉/.55⌉',
 103: '⌊⌊√5+55⌋/.55⌋',
 104: '(5+⌊55/.55⌋)',
 105: '(55+(55-5))',
 106: '((555/5)-5)',
 107: '(55+⌊55-√5⌋)',
 108: '(5!-⌈55.5/5⌉)',
 109: '(55+⌊55-.5⌋)',
 110: '⌊55+55.5⌋',
 111: '⌈55+55.5⌉',
 112: '⌈555.5/5⌉',
 113: '(55+⌈√5+55⌉)',
 114: '⌊5!-5.555⌋',
 115: '⌈5!-5.555⌉',
 116: '(5+(555/5))',
 117: '(5!-⌈5*.555⌉)',
 118: '(5!-⌈5.55/5⌉)',
 119: '⌊5!-.5555⌋',
 120: '⌊5.5555⌋!',
 121: '⌈5!+.5555⌉',
 122: '(5!+⌈5.55/5⌉)',
 123: '⌊555/(5-.5)⌋',
 124: '⌊√5*55.55⌋',
 125: '⌊5!+5.555⌋',
 126: '⌈5!+5.555⌉',
 127: '⌊⌊5**5.5⌋/55⌋',
 128: '⌈⌊5**5.5⌋/55⌉',
 129: '(5!+⌊5/.555⌋)',
 130: '⌊√5.5*55.5⌋',
 131: '⌈√5.5*55.5⌉',
 132: '(5!+⌈55.5/5⌉)',
 133: '⌈55*(√55-5)⌉',
 134: '⌊55*√⌈5.55⌉⌋',
 135: '(5*⌊5*5.55⌋)',
 136: '⌈√⌈5.5⌉*55.5⌉',
 137: '⌊5.5*⌈55/√5⌉⌋',
 138: '⌊5*(5*5.55)⌋',
 139: '⌈5*(5*5.55)⌉',
 140: '(5*⌈5*5.55⌉)',
 141: '(5!+⌊5!/5.55⌋)',
 142: '(5!+⌈5!/5.55⌉)',
 143: '(5+⌈.5*(5*55)⌉)',
 144: '(⌈5.555⌉!/5)',
 145: '(5+(5*⌈.5*55⌉))',
 146: '⌊55*(5-√5.5)⌋',
 147: '(5!+⌊5*5.55⌋)',
 148: '(5!+⌈5*5.55⌉)',
 149: '⌈5.5*⌊.5*55⌋⌉',
 150: '(5*⌊.55*55⌋)',
 151: '⌊.55*(5*55)⌋',
 152: '⌈.55*(5*55)⌉',
 153: '⌊55*(√5+.55)⌋',
 154: '(5.5*⌈.5*55⌉)',
 155: '(5*⌈.55*55⌉)',
 156: '⌈(55+55)/√.5⌉',
 157: '(⌊.5*555⌋-5!)',
 158: '(⌈.5*555⌉-5!)',
 159: '(5!+⌊√.5*55.5⌋)',
 160: '(5*(5+⌊.5*55⌋))',
 161: '⌊(.5*5)**5.55⌋',
 162: '⌈(.5*5)**5.55⌉',
 163: '(⌊5!/.55⌋-55)',
 164: '(⌈5!/.55⌉-55)',
 165: '(55*⌈5*.55⌉)',
 166: '⌊⌈.5*5⌉*55.5⌋',
 167: '⌈⌈.5*5⌉*55.5⌉',
 168: '(5!+⌈55-√55⌉)',
 169: '(5!+⌊55-5.5⌋)',
 170: '(5!+⌊55.5-5⌋)',
 171: '(5!+⌈55.5-5⌉)',
 172: '⌈5.555**⌈√5⌉⌉',
 173: '⌊55*√⌊5+5.5⌋⌋',
 174: '(5!+⌊55-.55⌋)',
 175: '⌊5!+55.55⌋',
 176: '⌈5!+55.55⌉',
 177: '(55+⌊√5*55⌋)',
 178: '(55+⌈√5*55⌉)',
 179: '⌊55*(5.5-√5)⌋',
 180: '(5+⌊5!+55.5⌋)',
 181: '(5+⌈5!+55.5⌉)',
 182: '(⌊5.5*55⌋-5!)',
 183: '(⌈5.5*55⌉-5!)',
 184: '(5!+⌊5!-55.5⌋)',
 185: '(555/⌈.5*5⌉)',
 186: '⌈555.5/⌈√5⌉⌉',
 187: '(5!+⌈5!*.555⌉)',
 188: '((⌈.5*5⌉**5)-55)',
 189: '(⌊√55⌋*⌊.5*55⌋)',
 190: '(5*⌈5*√55.5⌉)',
 191: '⌈55*√⌊5+√55⌋⌉',
 192: '(⌈5.55⌉/(.5**5))',
 193: '⌊5!**(.55+.55)⌋',
 194: '⌊(555-5!)/√5⌋',
 195: '⌈(555-5!)/√5⌉',
 196: '(.5*⌊√.5*555⌋)',
 197: '⌈.5*⌈√.5*555⌉⌉',
 198: '(⌊55/.55⌋/.5)',
 199: '⌊55/(.5*.55)⌋',
 200: '(⌈55/.55⌉/.5)',
 201: '⌈555/(5-√5)⌉',
 202: '⌊555/(.5+√5)⌋',
 203: '⌊.5*⌊55*√55⌋⌋',
 204: '(.5*⌈55*√55⌉)',
 205: '(5*⌈5.5*√55⌉)',
 206: '⌈⌈5!-√55⌉/.55⌉',
 207: '⌊(5!-5)/.555⌋',
 208: '⌈(5!-5)/.555⌉',
 209: '(5.5*⌈5*√55⌉)',
 210: '⌈⌈5!-5.5⌉/.55⌉',
 211: '(⌊5!/.555⌋-5)',
 212: '(⌈5!/.555⌉-5)',
 213: '⌈⌊5!/.55⌋-5.5⌉',
 214: '⌈⌈5!/.55⌉-5.5⌉',
 215: '⌊⌊5!/.555⌋-.5⌋',
 216: '⌊5!/.5555⌋',
 217: '⌈5!/.5555⌉',
 218: '⌈.5*(555-5!)⌉',
 219: '(5!+⌊55/.55⌋)',
 220: '((5*55)-55)',
 221: '(5+⌊5!/.555⌋)',
 222: '(555/(.5*5))',
 223: '⌊5.5+⌊5!/.55⌋⌋',
 224: '⌊5.5+⌈5!/.55⌉⌋',
 225: '⌊(5+5!)/.555⌋',
 226: '⌈(5+5!)/.555⌉',
 227: '⌈555/√⌈5.5⌉⌉',
 228: '(⌊5!-5.55⌋/.5)',
 229: '⌈(5!-5.55)/.5⌉',
 230: '(5!+(55+55))',
 231: '(5!+(555/5))',
 232: '⌈(5!+√55)/.55⌉',
 233: '⌈⌈5!+√55⌉/.55⌉',
 234: '(5!+⌊5!-5.55⌋)',
 235: '(5*⌊55-√55⌋)',
 236: '⌊555/√5.5⌋',
 237: '⌈555/√5.5⌉',
 238: '⌈5*(55-√55)⌉',
 239: '(5!+⌊5!-.555⌋)',
 240: '(5*⌈55-√55⌉)',
 241: '(5!+⌈5!+.555⌉)',
 242: '(⌈5!+.555⌉/.5)',
 243: '(⌈5*.555⌉**5)',
 244: '⌊55*(5-.55)⌋',
 245: '(5*⌊55-5.5⌋)',
 246: '⌈(555-5)/√5⌉',
 247: '⌊5*(55-5.5)⌋',
 248: '⌊555.5/√5⌋',
 249: '⌈555.5/√5⌉',
 250: '(5*⌊55.5-5⌋)',
 251: '⌈(5+555)/√5⌉',
 252: '⌊5*(55.5-5)⌋',
 253: '⌈5*(55.5-5)⌉',
 254: '(5+⌈555/√5⌉)',
 255: '(5*⌈55.5-5⌉)',
 256: '(⌊55*√5.5⌋/.5)',
 257: '⌊55/(.5/√5.5)⌋',
 258: '(⌈55*√5.5⌉/.5)',
 259: '⌊5!/(55.5/5!)⌋',
 260: '(5*⌊55-√5.5⌋)',
 261: '⌈(5*.55)**5.5⌉',
 262: '⌈555/√(5-.5)⌉',
 263: '⌊5*(55-√5.5)⌋',
 264: '⌈5*(55-√5.5)⌉',
 265: '(5*⌈55-√5.5⌉)',
 266: '⌊5*(55.5-√5)⌋',
 267: '⌊(5*55)-√55⌋',
 268: '⌈(5*55)-√55⌉',
 269: '⌊(5*55)-5.5⌋',
 270: '(5*⌊55-.55⌋)',
 271: '(⌈.5-5⌉+(5*55))',
 272: '(⌊.5*555⌋-5)',
 273: '(⌈.5*555⌉-5)',
 274: '⌊(5*55)-.55⌋',
 275: '(5*⌊55.55⌋)',
 276: '⌈.55+(5*55)⌉',
 277: '⌊5*55.55⌋',
 278: '⌈5*55.55⌉',
 279: '⌈.5+⌈.5*555⌉⌉',
 280: '(5*⌈55.55⌉)',
 281: '⌈5.5+(5*55)⌉',
 282: '(5+⌊.5*555⌋)',
 283: '(5+⌈.5*555⌉)',
 284: '⌊5*((5**5)/55)⌋',
 285: '(5*⌊√5+55.5⌋)',
 286: '(5.5*⌊55-√5⌋)',
 287: '(555-⌊√5*5!⌋)',
 288: '(⌈55*√55⌉-5!)',
 289: '⌈55*√(.5*55)⌉',
 290: '(5*⌈√5+55.5⌉)',
 291: '⌊5.5*⌈55-√5⌉⌋',
 292: '⌈5.5*⌈55-√5⌉⌉',
 293: '⌊5!*√⌈5.555⌉⌋',
 294: '⌈5!*√⌈5.555⌉⌉',
 295: '(5!+⌊5!+55.5⌋)',
 296: '(5!+⌈5!+55.5⌉)',
 297: '(⌊5.5*55⌋-5)',
 298: '(⌈5.5*55⌉-5)',
 299: '⌊5.5*(55-.5)⌋',
 300: '(5*⌊5+55.5⌋)',
 301: '⌊⌊5.5*55⌋-.5⌋',
 302: '⌊5*(5+55.5)⌋',
 303: '⌈5*(5+55.5)⌉',
 304: '⌈.5+⌈5.5*55⌉⌉',
 305: '⌊.55*555⌋',
 306: '⌈.55*555⌉',
 307: '(5+⌊5.5*55⌋)',
 308: '(5+⌈5.5*55⌉)',
 309: '(⌈(√.5+5)*55⌉-5)',
 310: '(5*⌊55+√55⌋)',
 311: '⌈(√5**5)*5.55⌉',
 312: '⌊5*(55+√55)⌋',
 313: '⌈5*(55+√55)⌉',
 314: '⌈5.5*⌊√5+55⌋⌉',
 315: '(5*⌈55+√55⌉)',
 316: '⌊√(55/5.5)**5⌋',
 317: '⌈√(55/5.5)**5⌉',
 318: '⌊(5!+55)/.55⌋',
 319: '⌈(5!+55)/.55⌉',
 320: '(5*⌊5!-55.5⌋)',
 321: '⌊⌈5.555⌉!/√5⌋',
 322: '⌊5*(5!-55.5)⌋',
 323: '⌈5*(5!-55.5)⌉',
 324: '(⌈5.5⌉*⌊55-.5⌋)',
 325: '(5*⌈5!-55.5⌉)',
 326: '⌈(5!/55)**√55⌉',
 327: '(⌈5.5⌉*(55-.5))',
 328: '⌈.5*(55+(5*5!))⌉',
 329: '⌊(55*⌈5.5⌉)-.5⌋',
 330: '(55*⌈5.55⌉)',
 331: '⌈.5+(55*⌈5.5⌉)⌉',
 332: '⌊.55*(5+(5*5!))⌋',
 333: '(⌈5.5⌉*55.5)',
 334: '⌈5*(5!*.555)⌉',
 335: '(5*⌈5!*.555⌉)',
 336: '(5!+⌊5!/.555⌋)',
 337: '⌊.5*(5!+555)⌋',
 338: '⌈.5*(5!+555)⌉',
 339: '⌊55*√⌈5*√55⌉⌋',
 340: '⌈55*√⌈5*√55⌉⌉',
 341: '⌊55*(√.5+5.5)⌋',
 342: '⌈55*(√.5+5.5)⌉',
 343: '⌊5*(.55*(5+5!))⌋',
 344: '⌈5*(.55*(5+5!))⌉',
 345: '(5*⌈.55*(5+5!)⌉)',
 346: '(⌊55*√(5+5)⌋/.5)',
 347: '⌊5!*(.55+√5.5)⌋',
 348: '(⌈5.5⌉*⌈√5+55⌉)',
 349: '(⌊(5-.55)**5⌋/5)',
 350: '(⌊5!+55.5⌋/.5)',
 351: '((5!+55.5)/.5)',
 352: '(⌈5!+55.5⌉/.5)',
 353: '⌈⌈555/√5⌉/√.5⌉',
 354: '⌊(.5*⌈5.5⌉!)-5.5⌋',
 355: '(5*(5+(5!*.55)))',
 356: '⌈(55/5)**√⌈5.5⌉⌉',
 357: '⌊5.5*(5!-55)⌋',
 358: '⌈5.5*(5!-55)⌉',
 359: '⌊.5*⌊⌈5.55⌉!-.5⌋⌋',
 360: '(.5*⌈5.555⌉!)',
 361: '⌊(√5+5)*(55-5)⌋',
 362: '⌊.5*(5+⌈5.55⌉!)⌋',
 363: '(5.5*(5!*.55))',
 364: '⌈5!*(.55*5.5)⌉',
 365: '(5+(.5*⌈5.55⌉!))',
 366: '(5!*(.55+(.5*5)))',
 367: '(5!+⌊55*(5-.5)⌋)',
 368: '(5!+⌊555/√5⌋)',
 369: '(5!+⌈555/√5⌉)',
 370: '⌊√55*(55-5)⌋',
 371: '⌈√55*(55-5)⌉',
 372: '(55+⌈√(5+5)**5⌉)',
 373: '⌊55*√⌈5.5**√5⌉⌋',
 374: '⌈55*√⌈5.5**√5⌉⌉',
 375: '(5*⌈(5+5)*√55⌉)',
 376: '(55+⌊⌈5.5⌉!/√5⌋)',
 377: '(55+⌈⌈5.5⌉!/√5⌉)',
 378: '(⌊√55⌋*⌊55-.5⌋)',
 379: '⌊5!*√(55/5.5)⌋',
 380: '⌊55*(√55-.5)⌋',
 381: '⌈55*(√55-.5)⌉',
 382: '⌈55**(√55/5)⌉',
 383: '(5!+⌊5*(55-√5)⌋)',
 384: '⌊(55*⌊√55⌋)-.5⌋',
 385: '(55*⌊√55.5⌋)',
 386: '(555-⌊5!/√.5⌋)',
 387: '(⌊√.5*555⌋-5)',
 388: '⌊⌊√55⌋*55.5⌋',
 389: '⌈⌊√55⌋*55.5⌉',
 390: '(5*⌊55.5/√.5⌋)',
 391: '⌊⌊√.5*555⌋-.5⌋',
 392: '⌊√.5*555.5⌋',
 393: '⌈√.5*555.5⌉',
 394: '⌈√.5*⌈555.5⌉⌉',
 395: '⌊√.5*(5+555)⌋',
 396: '⌊.55*⌈5.55⌉!⌋',
 397: '(5!+⌊.5*555⌋)',
 398: '(5!+⌈.5*555⌉)',
 399: '⌊⌈5.5⌉!*.555⌋',
 400: '⌈⌈5.5⌉!*.555⌉',
 401: '⌊(√5+5)*55.5⌋',
 402: '(⌊55*√55⌋-5)',
 403: '(⌈55*√55⌉-5)',
 404: '⌊√55*(55-.5)⌋',
 405: '⌈√55*(55-.5)⌉',
 406: '⌊⌊55*√55⌋-.5⌋',
 407: '⌊55*√⌊55.5⌋⌋',
 408: '⌈55*√⌊55.5⌋⌉',
 409: '⌊55*√55.5⌋',
 410: '⌈55*√55.5⌉',
 411: '⌊√55*55.5⌋',
 412: '⌈√55*55.5⌉',
 413: '(5+⌈55*√55⌉)',
 414: '⌈√55.5**⌈.5*5⌉⌉',
 415: '⌊√55*⌈55.5⌉⌋',
 416: '⌈√55*⌈55.5⌉⌉',
 417: '⌊5*(5**(5*.55))⌋',
 418: '⌊55*√⌈√5+55⌉⌋',
 419: '⌊(5**5)/√55.5⌋',
 420: '⌊⌈5*.55⌉**5.5⌋',
 421: '⌈⌈5*.55⌉**5.5⌉',
 422: '(5!+⌊5.5*55⌋)',
 423: '(5!+⌈5.5*55⌉)',
 424: '⌈5.5*⌊55/√.5⌋⌉',
 425: '⌊55*(√5+5.5)⌋',
 426: '⌊55*√(5+55)⌋',
 427: '⌈55*√(5+55)⌉',
 428: '⌊⌈5.5*55⌉/√.5⌋',
 429: '(5.5*⌈55/√.5⌉)',
 430: '(555-(5+5!))',
 431: '⌈√55*⌈√5+55⌉⌉',
 432: '(555-⌈√5+5!⌉)',
 433: '(555-⌊√5+5!⌋)',
 434: '(555-⌈.5+5!⌉)',
 435: '⌊555.5-5!⌋',
 436: '⌈555.5-5!⌉',
 437: '(⌊√5-5!⌋+555)',
 438: '(⌈√5-5!⌉+555)',
 439: '⌊(⌈√55⌉*55)-.5⌋',
 440: '(5+(555-5!))',
 441: '⌈.5+(⌈√55⌉*55)⌉',
 442: '(5+⌈5!/(.5*.55)⌉)',
 443: '⌊55*√(5!-55)⌋',
 444: '(⌈√55⌉*55.5)',
 445: '⌈√55*(5+55)⌉',
 446: '⌊55*√(5!*.55)⌋',
 447: '⌊⌈√5⌉**5.555⌋',
 448: '⌈⌈√5⌉**5.555⌉',
 449: '⌈55*(5+√(5+5))⌉',
 450: '(5!+(55*⌈5.5⌉))',
 451: '⌊5!*(⌈5.55⌉-√5)⌋',
 452: '⌊55*(√5+⌈5.5⌉)⌋',
 453: '⌈55*(√5+⌈5.5⌉)⌉',
 454: '(⌊(5+5!)/.55⌋/.5)',
 455: '(⌊√55⌋*(5!-55))',
 456: '⌊5.5*⌊√5**5.5⌋⌋',
 457: '⌈5.5*⌊√5**5.5⌋⌉',
 458: '(⌊5-.5⌋*(5!-5.5))',
 459: '⌊555/(.5+√.5)⌋',
 460: '⌈555/(.5+√.5)⌉',
 461: '⌈55*√⌊√5.5**5⌋⌉',
 462: '(5.5*⌈√5**5.5⌉)',
 463: '⌈5*(5!-(.5*55))⌉',
 464: '(⌈√55⌉*⌈√5+55⌉)',
 465: '(5*(5!-⌊.5*55⌋))',
 466: '⌊⌊√.5*5!⌋*5.55⌋',
 467: '⌊55*(.5+⌈√55⌉)⌋',
 468: '(5!*(5-(5.5/5)))',
 469: '⌊55*(5+(√.5*5))⌋',
 470: '(555-⌈√.5*5!⌉)',
 471: '(555-⌊√.5*5!⌋)',
 472: '⌈⌈√.5*5!⌉*5.55⌉',
 473: '(5.5*⌈5**(5-√5)⌉)',
 474: '(5!*(5-(.5+.55)))',
 475: '((5!*⌊5-.55⌋)-5)',
 476: '(55+⌈⌈√5⌉**5.5⌉)',
 477: '⌊√.5*(5!+555)⌋',
 478: '⌈√.5*(5!+555)⌉',
 479: '((5*5!)-⌈5!+.55⌉)',
 480: '(5!*⌊5-.555⌋)',
 481: '((5*5!)-⌊5!-.55⌋)',
 482: '⌊√55*(5!-55)⌋',
 483: '⌈√55*(5!-55)⌉',
 484: '⌈(√5*5!)/.555⌉',
 485: '⌊√5*⌈5!/.555⌉⌋',
 486: '⌈√5*⌈5!/.555⌉⌉',
 487: '⌊5!/(.55**√5.5)⌋',
 488: '⌊.55*⌊5!*√55⌋⌋',
 489: '⌊.55*⌈5!*√55⌉⌋',
 490: '⌈.55*⌈5!*√55⌉⌉',
 491: '⌈5!*((5/.55)-5)⌉',
 492: '(⌊5-.5⌋*⌈√5*55⌉)',
 493: '⌈(⌊5/.55⌋**5)/5!⌉',
 494: '(⌊55*(5-.5)⌋/.5)',
 495: '(5*⌊55/.55⌋)',
 496: '(⌊555/√5⌋/.5)',
 497: '⌈555/(.5*√5)⌉',
 498: '(⌈555/√5⌉/.5)',
 499: '⌊5*(55/.55)⌋',
 500: '(555-55)',
 501: '(555-⌈5!/√5⌉)',
 502: '(555-⌊5!/√5⌋)',
 503: '⌊⌊5.5**5⌋/(5+5)⌋',
 504: '⌈⌊5.5**5⌋/(5+5)⌉',
 505: '(5!+(55*⌊√55⌋))',
 506: '⌊(5-.5)*(5!-√55)⌋',
 507: '(⌊5*(5!+5.5)⌋-5!)',
 508: '(⌈5*(5!+5.5)⌉-5!)',
 509: '⌊√.5*⌈5.555⌉!⌋',
 510: '⌈√.5*⌈5.555⌉!⌉',
 511: '⌈⌊5!*√5.5⌋/.55⌉',
 512: '(5!+⌊√.5*555⌋)',
 513: '(5!+⌈√.5*555⌉)',
 514: '⌈√5.5*⌈5!/.55⌉⌉',
 515: '(5!+(5!+(5*55)))',
 516: '(5!+⌊.55*⌈5.5⌉!⌋)',
 517: '(5!+⌈.55*⌈5.5⌉!⌉)',
 518: '(555-⌈5**√5⌉)',
 519: '(555-⌊5**√5⌋)',
 520: '((5*(5!-5))-55)',
 521: '⌈(5**5)/⌈5.55⌉⌉',
 522: '⌊55*(5+(5-.5))⌋',
 523: '⌈55*(5+(5-.5))⌉',
 524: '(⌈5!*(5!/55)⌉/.5)',
 525: '(5*((55/.5)-5))',
 526: '(⌊5*(55-√5)⌋/.5)',
 527: '(5!+⌊55*√55⌋)',
 528: '(5!+⌈55*√55⌉)',
 529: '((5!*(5-.55))-5)',
 530: '(555-(5*5))',
 531: '(555-(5!/5))',
 532: '⌊5**(5-(5.5/5))⌋',
 533: '⌊5!*(5-.555)⌋',
 534: '⌈5!*(5-.555)⌉',
 535: '(55+(5!*⌊5-.5⌋))',
 536: '⌈(5-.5)*⌊5!-.55⌋⌉',
 537: '⌊5.5*((.5*5)**5)⌋',
 538: '⌈5.5*((.5*5)**5)⌉',
 539: '(5+(5!*(5-.55)))',
 540: '((5+5)*⌊55-.5⌋)',
 541: '⌈.55+(5!*(5-.5))⌉',
 542: '(⌊5*(5!-.5)⌋-55)',
 543: '(555-⌈√5*5⌉)',
 544: '(555-⌊√5*5⌋)',
 545: '(555-(5+5))',
 546: '((5!*5.55)-5!)',
 547: '⌊555-√55⌋',
 548: '⌈555-√55⌉',
 549: '⌊555-5.5⌋',
 550: '⌈555-5.5⌉',
 551: '⌈555.5-5⌉',
 552: '⌊555-√5.5⌋',
 553: '⌊555.5-√5⌋',
 554: '⌊555-.55⌋',
 555: '⌊555.55⌋',
 556: '⌈555.55⌉',
 557: '⌊√5+555.5⌋',
 558: '⌈√5+555.5⌉',
 559: '(5+⌊555-.5⌋)',
 560: '⌊5+555.5⌋',
 561: '⌈5+555.5⌉',
 562: '⌊√55+555⌋',
 563: '⌈√55+555⌉',
 564: '⌈(5**5)/5.55⌉',
 565: '(5+(5+555))',
 566: '(⌊√5*5⌋+555)',
 567: '(⌈√5*5⌉+555)',
 568: '(⌈5*(5!-5.5)⌉-5)',
 569: '⌊(5*(5!-5))-5.5⌋',
 570: '(5*⌊5!-5.55⌋)',
 571: '⌊√55*⌊55/√.5⌋⌋',
 572: '⌊5*(5!-5.55)⌋',
 573: '⌈5*(5!-5.55)⌉',
 574: '(5+⌈(5**5)/5.5⌉)',
 575: '(5*⌈5!-5.55⌉)',
 576: '⌈.55+(5*(5!-5))⌉',
 577: '⌊55*(5+5.5)⌋',
 578: '⌈55*(5+5.5)⌉',
 579: '((5!/5)+555)',
 580: '((5*5)+555)',
 581: '⌈5.5+(5*(5!-5))⌉',
 582: '⌈5!*(5.55-√.5)⌉',
 583: '(55/(5/⌊5!/√5⌋))',
 584: '⌈5*(5!-√(55/5))⌉',
 585: '(5*(5!-⌈5*.55⌉))',
 586: '⌊5*(5!-(5*.55))⌋',
 587: '((⌊√5⌋**5)+555)',
 588: '⌈5!*√⌊5-.555⌋!⌉',
 589: '((5*5!)-(55/5))',
 590: '⌈5!*(5-(5/55))⌉',
 591: '(⌊5**√5⌋+555)',
 592: '(⌈5**√5⌉+555)',
 593: '⌈(5*5!)-√55.5⌉',
 594: '⌊(5*5!)-5.55⌋',
 595: '(5*⌊5!-.555⌋)',
 596: '⌈√(5+5)**5.55⌉',
 597: '⌊5*(5!-.555)⌋',
 598: '⌈5*(5!-.555)⌉',
 599: '⌊(5*5!)-.555⌋',
 600: '(5*⌊5.555⌋!)',
 601: '⌈(5*5!)+.555⌉',
 602: '⌊5*(5!+.555)⌋',
 603: '⌈5*(5!+.555)⌉',
 604: '(⌊5.5*55⌋/.5)',
 605: '(55*(55/5))',
 606: '(⌈5.5*55⌉/.5)',
 607: '⌊(5*5!)+√55.5⌋',
 608: '(⌊5!/√5⌋+555)',
 609: '(⌈5!/√5⌉+555)',
 610: '(55+555)',
 611: '(⌈√5**5⌉+555)',
 612: '(5+⌊(5*5!)+√55⌋)',
 613: '⌊5*(5!+(5*.55))⌋',
 614: '(((5**5)-55)/5)',
 615: '((.5*5!)+555)',
 616: '(5.5*⌊5!-√55⌋)',
 617: '⌊5*(.5+⌈√5*55⌉)⌋',
 618: '⌈5*(.5+⌈√5*55⌉)⌉',
 619: '⌊√5*⌊.5*555⌋⌋',
 620: '(5*⌊√5*55.5⌋)',
 621: '(.5*⌈√5*555⌉)',
 622: '⌈√5*⌈.5*555⌉⌉',
 623: '⌊5!*√⌊5*5.55⌋⌋',
 624: '⌈5!*√⌊5*5.55⌋⌉',
 625: '(5**⌊5-.555⌋)',
 626: '(⌊5.5+(5**5)⌋/5)',
 627: '⌊5*(5!+5.55)⌋',
 628: '⌈5*(5!+5.55)⌉',
 629: '⌊5.5*(5!-5.5)⌋',
 630: '(5*⌈5!+5.55⌉)',
 631: '⌈5.5+(5*(5+5!))⌉',
 632: '⌊5.5*⌈5!-5.5⌉⌋',
 633: '⌈5.5*⌈5!-5.5⌉⌉',
 634: '⌊5!*√⌈5*5.55⌉⌋',
 635: '(5*⌊5!+√55.5⌋)',
 636: '(((5**5)+55)/5)',
 637: '⌊5*(5!+√55.5)⌋',
 638: '⌊(5!-5)*5.55⌋',
 639: '⌈(5!-5)*5.55⌉',
 640: '(5*⌊55*√5.5⌋)',
 641: '⌈.5+(5*⌈5!+√55⌉)⌉',
 642: '(5+⌊5*(5!+√55)⌋)',
 643: '⌊5.5*⌊5!-√5.5⌋⌋',
 644: '⌊5*(55*√5.5)⌋',
 645: '(5*⌈55*√5.5⌉)',
 646: '⌈5*(5!+(5/.55))⌉',
 647: '⌊5.5*(5!-√5.5)⌋',
 648: '(5!*(⌊.5*55⌋/5))',
 649: '⌊⌊5!-√5⌋*5.55⌋',
 650: '((5+5)*(5!-55))',
 651: '(⌈√5⌉*⌈5!/.555⌉)',
 652: '⌊(5!*5.5)-√55⌋',
 653: '⌊(5!-√5)*5.55⌋',
 654: '⌊5.5*⌊5!-.55⌋⌋',
 655: '⌊(5*5!)+55.5⌋',
 656: '⌈(5*5!)+55.5⌉',
 657: '⌈5.5*(5!-.55)⌉',
 658: '⌈5!*√⌊.55*55⌋⌉',
 659: '⌊(5!*5.5)-.55⌋',
 660: '(5.5*⌊5.55⌋!)',
 661: '((5!*5.55)-5)',
 662: '⌊(5!-√.5)*5.55⌋',
 663: '⌊5.5*(5!+.55)⌋',
 664: '⌊⌈5.5⌉!-55.5⌋',
 665: '(⌈5.55⌉!-55)',
 666: '⌊5!*5.555⌋',
 667: '⌈5!*5.555⌉',
 668: '⌊(.5+5!)*5.55⌋',
 669: '⌈(.5+5!)*5.55⌉',
 670: '(5!+(555-5))',
 671: '(5+(5!*5.55))',
 672: '(5!+⌊555-√5⌋)',
 673: '(5!+⌈555-√5⌉)',
 674: '(5!+⌊555-.5⌋)',
 675: '⌊5!+555.5⌋',
 676: '⌈5!+555.5⌉',
 677: '(5!+⌊√5+555⌋)',
 678: '(5!+⌈√5+555⌉)',
 679: '⌈(5.5**5)/√55⌉',
 680: '(5+(5!+555))',
 681: '⌈5!*(5+(5/√55))⌉',
 682: '⌊55*(5+√55)⌋',
 683: '⌈55*(5+√55)⌉',
 684: '(⌈5.5⌉*⌊5!-5.5⌋)',
 685: '(5*⌊.5*(5*55)⌋)',
 686: '⌊(√5-⌈.5⌉)*555⌋',
 687: '⌊5.5*⌊5!+5.5⌋⌋',
 688: '⌈5.5*⌊5!+5.5⌋⌉',
 689: '(5!+⌈(5**5)/5.5⌉)',
 690: '⌊5.5*(5!+5.5)⌋',
 691: '⌈5.5*(5!+5.5)⌉',
 692: '(5+⌊5.5*(5+5!)⌋)',
 693: '⌊(5+5!)*5.55⌋',
 694: '⌈(5+5!)*5.55⌉',
 695: '(⌈5.55⌉!-(5*5))',
 696: '(⌈5.55⌉!-(5!/5))',
 697: '(⌈(.5*√55)**5⌉-5)',
 698: '⌊5.5*⌊5!+√55⌋⌋',
 699: '⌈5.5*⌊5!+√55⌋⌉',
 700: '(5*(5*⌈.5*55⌉))',
 701: '⌈5.5*(5!+√55)⌉',
 702: '⌊(5**5)/(5-.55)⌋',
 703: '⌈(5**5)/(5-.55)⌉',
 704: '(5.5*⌈5!+√55⌉)',
 705: '(5*(5!+⌊5!/5.5⌋))',
 706: '⌊(5!-√5)*⌈5.55⌉⌋',
 707: '(⌈5.5⌉!-⌈5+√55⌉)',
 708: '(⌈5!-√5⌉*⌈5.55⌉)',
 709: '(⌈5.5⌉!-(55/5))',
 710: '(⌈5.55⌉!-(5+5))',
 711: '(⌈5.5⌉!-⌊5/.55⌋)',
 712: '⌊⌈5.55⌉!-√55⌋',
 713: '⌈⌈5.55⌉!-√55⌉',
 714: '⌊⌈5.55⌉!-5.5⌋',
 715: '(⌈5.555⌉!-5)',
 716: '(⌈5.5⌉!-⌊5-.55⌋)',
 717: '⌊⌈5.555⌉!-√5⌋',
 718: '⌈⌈5.555⌉!-√5⌉',
 719: '⌊⌈5.555⌉!-.5⌋',
 720: '⌈5.5555⌉!',
 721: '⌈.5+⌈5.555⌉!⌉',
 722: '⌊√5+⌈5.555⌉!⌋',
 723: '⌈√5+⌈5.555⌉!⌉',
 724: '(⌊5!/√.5⌋+555)',
 725: '(5+⌈5.555⌉!)',
 726: '⌈5.5+⌈5.55⌉!⌉',
 727: '⌊√55+⌈5.55⌉!⌋',
 728: '⌈√55+⌈5.55⌉!⌉',
 729: '(⌈√5⌉**⌈5.555⌉)',
 730: '(5+(5+⌈5.55⌉!))',
 731: '(⌈5.5⌉!+(55/5))',
 732: '(5!*(5+(5.5/5)))',
 733: '(5+⌈⌈5.5⌉!+√55⌉)',
 734: '(5!+⌊√5*(5*55)⌋)',
 735: '(5*(5!+⌊.5*55⌋))',
 736: '⌊√5.5**√(5+55)⌋',
 737: '⌊5*(5!+(.5*55))⌋',
 738: '(⌈5.5⌉*⌈√5*55⌉)',
 739: '⌊5!*√⌈5*√55.5⌉⌋',
 740: '(5*(5!+⌈.5*55⌉))',
 741: '(⌈5.5⌉!+⌊5!/5.5⌋)',
 742: '(⌈5.5⌉!+⌈5!/5.5⌉)',
 743: '⌊⌊5!**√5⌋/(5+55)⌋',
 744: '((5!/5)+⌈5.55⌉!)',
 745: '((5*5)+⌈5.55⌉!)',
 746: '(5!+((5+(5**5))/5))',
 747: '(⌈5.5⌉!+⌊.5*55⌋)',
 748: '(⌈5.5⌉!+⌈.5*55⌉)',
 749: '⌈5!*(√5+⌊5-.55⌋)⌉',
 750: '((5+5!)*⌈5.55⌉)',
 751: '⌈5!*(√.5+5.55)⌉',
 752: '(5!+⌊5.5*(5!-5)⌋)',
 753: '(⌈5.5⌉*(5!+5.5))',
 754: '(5!+⌊5!*√⌈.5*55⌉⌋)',
 755: '((5*(5!+55))-5!)',
 756: '(⌈5.5⌉*⌈5!+5.5⌉)',
 757: '(⌈5.5⌉!+⌊5*√55⌋)',
 758: '(⌈5.5⌉!+⌈5*√55⌉)',
 759: '⌈5!*√⌊5.5*√55⌋⌉',
 760: '(5*⌊55*(5-√5)⌋)',
 761: '⌈5*(55*(5-√5))⌉',
 762: '(⌈5.5⌉*⌊5!+√55⌋)',
 763: '⌈5*(5!**(.5+.55))⌉',
 764: '⌊⌈5.5⌉*(5!+√55)⌋',
 765: '(5*⌈55*(5-√5)⌉)',
 766: '⌈(⌈√5⌉**5.5)/.55⌉',
 767: '⌈((5*5)-5.5)**√5⌉',
 768: '⌊√⌈5.55⌉**√55⌋',
 769: '⌊55**√(5*.55)⌋',
 770: '(55*⌊√55/.5⌋)',
 771: '⌈(5*5.55)**⌊√5⌋⌉',
 772: '(55+⌊⌈5.5⌉!-√5⌋)',
 773: '(⌊5!*√55.5⌋-5!)',
 774: '(55+⌊⌈5.5⌉!-.5⌋)',
 775: '(55+⌈5.55⌉!)',
 776: '⌈⌈5.5⌉!+55.5⌉',
 777: '⌊(555-5)/√.5⌋',
 778: '⌈(555-5)/√.5⌉',
 779: '(⌊555/√.5⌋-5)',
 780: '(⌈555/√.5⌉-5)',
 781: '⌊(5**5)/⌊5-.55⌋⌋',
 782: '⌈(5**5)/⌊5-.55⌋⌉',
 783: '⌊⌊555/√.5⌋-.5⌋',
 784: '⌊√⌊.5*5⌋*555⌋',
 785: '⌊555.5/√.5⌋',
 786: '⌈555.5/√.5⌉',
 787: '⌈⌈555.5⌉/√.5⌉',
 788: '⌈(5-.5)*(5!+55)⌉',
 789: '(5+⌊555/√.5⌋)',
 790: '(5+⌈555/√.5⌉)',
 791: '⌊(5+555)/√.5⌋',
 792: '⌈(5+555)/√.5⌉',
 793: '⌈⌈5.5⌉!*(5.5/5)⌉',
 794: '(⌈.55*⌈5.5⌉!⌉/.5)',
 795: '(5!+(5!+555))',
 796: '⌈55**(5/⌈.5*5⌉)⌉',
 797: '⌊5.5*(5!+(5*5))⌋',
 798: '((⌈√5⌉**5)+555)',
 799: '⌈5!*(5+√(5*.55))⌉',
 800: '(5*((⌈√5⌉*55)-5))',
 801: '⌊⌊√55⌋*(5!-5.5)⌋',
 802: '⌈⌊√55⌋*(5!-5.5)⌉',
 803: '⌊⌊5!**√5⌋/55.5⌋',
 804: '⌈⌊5!**√5⌋/55.5⌉',
 805: '((5!-5)*⌊√55.5⌋)',
 806: '⌊(5-.5)**(5-.55)⌋',
 807: '(5!+⌊5.5*(5+5!)⌋)',
 808: '(5!+⌈5.5*(5+5!)⌉)',
 809: '(⌊5!*√(5+55)⌋-5!)',
 810: '(⌈√5⌉*((5*55)-5))',
 811: '⌈(5+(5!**√5))/55⌉',
 812: '⌈(5*⌊5-.55⌋)**√5⌉',
 813: '(⌊5!*(√5+5)⌋-55)',
 814: '(⌊55*√55⌋/.5)',
 815: '⌊55/(.5/√55)⌋',
 816: '(⌈55*√55⌉/.5)',
 817: '⌊5**(5/(⌈5.5⌉/5))⌋',
 818: '((5*5!)+⌊5!/.55⌋)',
 819: '((5*5!)+⌈5!/.55⌉)',
 820: '((⌈√5⌉*(5*55))-5)',
 821: '⌊5!/(√.5**5.55)⌋',
 822: '⌊5!*√⌊55-√55⌋⌋',
 823: '(⌊√5*5!⌋+555)',
 824: '(⌈√5*5!⌉+555)',
 825: '(55*(5+(5+5)))',
 826: '⌊(5*5!)**(.5+.55)⌋',
 827: '⌊(5-.55)**(5-.5)⌋',
 828: '⌈(5-.55)**(5-.5)⌉',
 829: '⌈(√5+5)*(5!-5.5)⌉',
 830: '(5*⌊⌈√5⌉*55.5⌋)',
 831: '(⌈√5⌉*⌊.5*555⌋)',
 832: '⌊(.5+⌈.5⌉)*555⌋',
 833: '⌈(.5+⌈.5⌉)*555⌉',
 834: '(⌊5!*√55⌋-55)',
 835: '(⌈5!*√55⌉-55)',
 836: '⌊⌊√55⌋*(5!-.55)⌋',
 837: '⌈⌊√55⌋*(5!-.55)⌉',
 838: '⌊(5.5**5)/⌈5.5⌉⌋',
 839: '⌈(5.5**5)/⌈5.5⌉⌉',
 840: '(5!+⌈5.555⌉!)',
 841: '(5!+⌈.5+⌈5.55⌉!⌉)',
 842: '(⌈5.5⌉!+⌊√5*55⌋)',
 843: '(⌈5.5⌉!+⌈√5*55⌉)',
 844: '⌊5!*√(55-5.5)⌋',
 845: '⌊√55*⌊5!-5.5⌋⌋',
 846: '⌈√55*⌊5!-5.5⌋⌉',
 847: '(⌊√55⌋*⌈5!+.55⌉)',
 848: '⌊5!*√⌊55.5-5⌋⌋',
 849: '⌊√55*(5!-5.5)⌋',
 850: '(5*(5!+(55-5)))',
 851: '⌊⌊(5!-5)*√55⌋-.5⌋',
 852: '⌊5!*√(55.5-5)⌋',
 853: '⌈5!*√(55.5-5)⌉',
 854: '(5+⌈5!*√(55-5)⌉)',
 855: '(5*⌈5.55**⌈√5⌉⌉)',
 856: '⌊(5!-5)*√55.5⌋',
 857: '⌈(5!-5)*√55.5⌉',
 858: '(5+⌈(5!-5)*√55⌉)',
 859: '⌊55**(√5-.55)⌋',
 860: '⌈55**(√5-.55)⌉',
 861: '⌊5!*(5+(5!/55))⌋',
 862: '⌈5!*(5+(5!/55))⌉',
 863: '⌈5**(⌊5!/5.5⌋/5)⌉',
 864: '(⌊.5*55⌋/(.5**5))',
 865: '(5*⌊55*√(5+5)⌋)',
 866: '⌈5!*√⌊55-√5.5⌋⌉',
 867: '⌊√55*⌊5!-√5.5⌋⌋',
 868: '⌈√55*⌊5!-√5.5⌋⌉',
 869: '⌊5*(55*√(5+5))⌋',
 870: '((555-5!)/.5)',
 871: '⌊5!**√⌈5.55/5⌉⌋',
 872: '⌊5*(5!+(55-.5))⌋',
 873: '⌈5*(5!+(55-.5))⌉',
 874: '⌊(5*(5!+55))-.5⌋',
 875: '(5*⌊5!+55.5⌋)',
 876: '⌈.5+(5*(5!+55))⌉',
 877: '⌊5*(5!+55.5)⌋',
 878: '⌈5*(5!+55.5)⌉',
 879: '⌈√5*⌈√.5*555⌉⌉',
 880: '(5*⌈5!+55.5⌉)',
 881: '⌊5!*√⌊55-.55⌋⌋',
 882: '⌊√55*⌊5!-.55⌋⌋',
 883: '⌊⌊5!*√55⌋-5.5⌋',
 884: '⌊⌈5!*√55⌉-5.5⌋',
 885: '⌈⌈5!*√55⌉-5.5⌉',
 886: '⌈√55*(5!-.55)⌉',
 887: '⌈⌊5!-.5⌋*√55.5⌉',
 888: '(⌊5!*√55.5⌋-5)',
 889: '⌊5!*(55/√55)⌋',
 890: '⌈5!*(55/√55)⌉',
 891: '⌈.55+(5!*√55)⌉',
 892: '⌊⌊5!*√55.5⌋-.5⌋',
 893: '⌊⌊5.5⌋!*√55.5⌋',
 894: '⌊5.5+⌊5!*√55⌋⌋',
 895: '⌈5.5+⌊5!*√55⌋⌉',
 896: '⌈5.5+⌈5!*√55⌉⌉',
 897: '⌊5!*√⌈55.55⌉⌋',
 898: '⌈5!*√⌈55.55⌉⌉',
 899: '(5+⌈5!*√55.5⌉)',
 900: '(5*(5+(5!+55)))',
 901: '⌊⌈.5+5!⌉*√55.5⌋',
 902: '⌊(5-(5.5/5))**5⌋',
 903: '⌈(5-(5.5/5))**5⌉',
 904: '(5!+⌊555/√.5⌋)',
 905: '(5!+⌈555/√.5⌉)',
 906: '(⌈√5⌉*⌊5.5*55⌋)',
 907: '⌊⌈√5⌉*(5.5*55)⌋',
 908: '⌈⌈√5⌉*(5.5*55)⌉',
 909: '(⌈√5⌉*⌈5.5*55⌉)',
 910: '⌊√5*⌊55*√55⌋⌋',
 911: '⌈√5*⌊55*√55⌋⌉',
 912: '⌊√5*⌈55*√55⌉⌋',
 913: '⌈√5*⌈55*√55⌉⌉',
 914: '⌊⌊5.5**5⌋/5.5⌋',
 915: '⌊5.5**⌊5-.55⌋⌋',
 916: '⌈5.5**⌊5-.55⌋⌉',
 917: '⌈⌈√5+5!⌉*√55.5⌉',
 918: '⌊5.5*⌈5.5**⌈√5⌉⌉⌋',
 919: '⌈5.5*⌈5.5**⌈√5⌉⌉⌉',
 920: '(5+⌊5.5**⌊5-.5⌋⌋)',
 921: '⌊(.5*5)**√55.5⌋',
 922: '⌈(.5*5)**√55.5⌉',
 923: '(55+⌊5!*(√5+5)⌋)',
 924: '(55+⌈5!*(√5+5)⌉)',
 925: '(5*(555/⌈√5⌉))',
 926: '⌊⌊(5+5!)*√55⌋-.5⌋',
 927: '⌊√55*⌊5!+5.5⌋⌋',
 928: '⌈√55*⌊5!+5.5⌋⌉',
 929: '⌊5!*√⌊5+55.5⌋⌋',
 930: '⌈5!*√⌊5+55.5⌋⌉',
 931: '⌊(5+5!)*√55.5⌋',
 932: '⌈(5+5!)*√55.5⌉',
 933: '⌊5!*√(5+55.5)⌋',
 934: '⌈5!*√(5+55.5)⌉',
 935: '(55*⌈5!/√55⌉)',
 936: '⌈(5+5!)*√⌈55.5⌉⌉',
 937: '⌊5!*√⌈5+55.5⌉⌋',
 938: '⌈5!*√⌈5+55.5⌉⌉',
 939: '⌊5.5/(.5**√55)⌋',
 940: '⌈5.5/(.5**√55)⌉',
 941: '⌊√55*⌊5!+√55⌋⌋',
 942: '⌊⌊5**5.5⌋/√55⌋',
 943: '⌈⌊5**5.5⌋/√55⌉',
 944: '(55+⌊5!*√55⌋)',
 945: '(55+⌈5!*√55⌉)',
 946: '(5.5*⌊(5+5)**√5⌋)',
 947: '⌊(√.5+⌈.5⌉)*555⌋',
 948: '⌊5.55**⌊5-.5⌋⌋',
 949: '⌈5.55**⌊5-.5⌋⌉',
 950: '(5*(5*⌈5*√55⌉))',
 951: '⌊5.5*⌈(5+5)**√5⌉⌋',
 952: '⌊5!*√⌈55+√55⌉⌋',
 953: '⌈5!*√⌈55+√55⌉⌉',
 954: '⌊(5!+555)/√.5⌋',
 955: '⌊5!*(.55+√55)⌋',
 956: '⌈5!*(.55+√55)⌉',
 957: '⌊5!*(.5+√⌈55.5⌉)⌋',
 958: '⌈5!*(.5+√⌈55.5⌉)⌉',
 959: '⌊(5!*⌈√55⌉)-.55⌋',
 960: '(5!*⌈55/√55⌉)',
 961: '⌊√⌈.5*5⌉*555⌋',
 962: '⌊5.5*(5!+55)⌋',
 963: '⌈5.5*(5!+55)⌉',
 964: '⌈(√5-.5)*555⌉',
 965: '⌊(5!/5.55)**√5⌋',
 966: '⌈(5!/5.55)**√5⌉',
 967: '⌊5!*√⌈5!-55.5⌉⌋',
 968: '⌈5!*√⌈5!-55.5⌉⌉',
 969: '((⌊5-.5⌋**5)-55)',
 970: '(5*⌈5!**(5.5/5)⌉)',
 971: '(⌈5*(5!/.55)⌉-5!)',
 972: '⌊√5*(555-5!)⌋',
 973: '⌈√5*(555-5!)⌉',
 974: '⌊5!*√⌊5!*.555⌋⌋',
 975: '⌈5!*√⌊5!*.555⌋⌉',
 976: '(⌈√55⌉*⌊√5*55⌋)',
 977: '⌈(5+5)*((.5*5)**5)⌉',
 978: '⌊5!*(√.5+√55.5)⌋',
 979: '⌊5!*(5+√⌊5+5.5⌋)⌋',
 980: '⌈5!*(5+√⌊5+5.5⌋)⌉',
 981: '((5-.5)*⌊5!/.55⌋)',
 982: '⌊5!*√⌈5!*.555⌉⌋',
 983: '⌈5!*√⌈5!*.555⌉⌉',
 984: '(⌈√55⌉*⌈√5*55⌉)',
 985: '⌊(5-.5)*⌈5!/.55⌉⌋',
 986: '⌈(5-.5)*⌈5!/.55⌉⌉',
 987: '⌊√⌈√5*5⌉**5.55⌋',
 988: '⌊5!*(√5+⌈5.55⌉)⌋',
 989: '⌈5!*(√5+⌈5.55⌉)⌉',
 990: '((555/.5)-5!)',
 991: '⌊5!*(5-(√5-5.5))⌋',
 992: '⌈5!*(5-(√5-5.5))⌉',
 993: '⌈√5*⌊⌈√5⌉**5.55⌋⌉',
 994: '⌊5!*(5*√(5*.55))⌋',
 995: '(⌈5.5⌉!+(5*55))',
 996: '⌊⌈5**(5-√.5)⌉-5.5⌋',
 997: '⌊5!*(5+√(55/5))⌋',
 998: '⌊⌊5**5.5⌋/⌊√55⌋⌋',
 999: '⌈⌊5**5.5⌋/⌊√55⌋⌉',
 ...}

The output got truncated by Jupyter Notebook after 1000 entries. Let's see what the first unmakeable integer actually is:

In [40]:
unmakeable(ff)
Out[40]:
23308

I think we've conquered the five 5s problem.

Conclusion

We were able to solve the puzzles, and we now have some tools to explore new puzzles. What can you discover?