2009-04-10

como sacar numeros del 0 al 9 con los digitos 4 4 4 4 (parte 2)

En la entrada anterior del blog puse el desafío de calcular los números del 1 al 50 haciendo operaciones aritméticas sobre 4 4s, y como generarlos para los números que van del 0 al 9. Pero me quedé con la duda de si es posible hacerlo para todos los números menores a 50, así que escribí un programita en ruby que calcula todas las posibles evaluaciones usando los operadores +, -, *, / y **. Lo único, hay que tener en cuenta que la división es entera, por lo que hay algunos resultados poco intuitivos.

Al final, el primer número imposible es el 10 (por eso no encontraba como armarlo :D). Acá les muestro la salida del programa:

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)))
10 ==
11 ==
12 == (4 * (4 - (4 / 4)))
13 ==
14 ==
15 == ((4 * 4) - (4 / 4))
16 == (4 * (4 ** (4 / 4)))
17 == ((4 / 4) + (4 * 4))
18 ==
19 ==
20 == (4 * (4 + (4 / 4)))
21 ==
22 ==
23 ==
24 == (4 + (4 + (4 * 4)))
25 ==
26 ==
27 ==
28 == ((4 * (4 + 4)) - 4)
29 ==
30 ==
31 ==
32 == ((4 ** 4) / (4 + 4))
33 ==
34 ==
35 ==
36 == (4 + (4 * (4 + 4)))
37 ==
38 ==
39 ==
40 ==
41 ==
42 ==
43 ==
44 ==
45 ==
46 ==
47 ==
48 == (4 * (4 + (4 + 4)))
49 ==
50 ==

Y para los geeks codeadores como yo, este fue el script rubyistico que usé para calcular las cosas:
def template_expressions( leafs = 4 )
  return "4" if leafs == 1
  previous_level = template_expressions( leafs - 1 )
  previous_level.map do
    |expr|
    results = []
    (0...expr.length).each do
      |i|
      if expr[i..i] == "4"
        new_result = expr.clone
        new_result[i] = "(4 o 4)"
        results << new_result
      end
    end
    results
  end.flatten
end

OPERANDS = %W{+ - * / **}

def sample_evaluations( leafs = 4 )
  evaluations = {}
  exprs = template_expressions(leafs)
  exprs.each do
    |expr|
    sample_evaluations0( leafs, expr, evaluations )
  end
  evaluations
end

def sample_evaluations0( leafs, expr, evaluations )
  if leafs == 0
    begin
      evaluations[eval( expr )] = expr
    rescue ZeroDivisionError
    end
    return
  end
  
  OPERANDS.each do
    |op|
    new_expr = expr.sub( /o/, op)
    sample_evaluations0( leafs - 1, new_expr, evaluations )
  end
end

evaluations = sample_evaluations
(0..50).each { |i| puts "#{i} == #{evaluations[i]}" }


Happy hacking,
Aureliano.

1 comentario:

Tordek dijo...

Algunos usan como truco juntar dos 4 para hacer un 44. Si lo usás, entonces (44 - 4)/4 = 10.

Otra opción es usar más operaciones, como sqrt y factorial. En ese caso, 10 = 4+4+(4/sqrt(4)).

Una cosa interesante hubiera sido que pongas todas las formas de hacer los cálculos, como que 0 se puede hacer con (4/4)**4**4, y (4/4**4)**4 también...