Scala: 110
type B=BigInt
def r(a:B,b:B,f:(B,B)=>B):B=if(b>1)f(a,r(a,b-1,f))else a
def h(a:B,b:B)=r(a,b,r(_,_,r(_,_,(_+_))))
sin golf:
type B=BigInt
def recursive (a:B, b:B, f:(B,B)=>B): B =
if (b>1) f (a, recursive (a, b-1, f))
else a
recursive (2, 3, recursive (_, _, recursive (_, _, (_ + _))))
explicación:
type B=BigInt
def p (a:B, b:B):B = a+b
def m (a:B, b:B):B = if (b>1) p (a, m (a, b-1)) else a
def h (a:B, b:B):B = if (b>1) m (a, h (a, b-1)) else a
def t (a:B, b:B):B = if (b>1) h (a, t (a, b-1)) else a
plus, mul, high (: = pow), tetration, todos funcionan de la misma manera. El patrón común se puede extraer como método recursivo, que requiere dos BigInts y una función básica:
def r (a:B, b:B, f:(B,B)=>B):B =
if (b>1) f(a, r(a, b-1, f)) else a
r (4, 3, r (_,_, r(_,_, (_+_))))
Los subrayados son marcadores de posición para algo que se llama en esta secuencia, por ejemplo, la suma más (a, b) = (a + b); por lo tanto ( + ) es una función que toma dos argumentos y los agrega (a + b).
desafortunadamente, tengo problemas con el tamaño de la pila. Funciona para valores pequeños para 4 (por ejemplo: 2) o si reduzco la profundidad en un paso:
def h(a:B,b:B)=r(a,b,r(_,_,(_*_))) // size -7, penalty + 5
def h(a:B,b:B)=r(a,b,r(_,_,r(_,_,(_+_))))
El código original tiene 112 caracteres y, si es válido, su puntaje sería 107. Quizás descubra cómo aumentar la pila.
El algoritmo expandido se puede transformar en llamadas recursivas de cola:
type B=BigInt
def p(a:B,b:B):B=a+b
import annotation._
@tailrec
def m(a:B,b:B,c:B=0):B=if(b>0)m(a,b-1,p(a,c))else c
@tailrec
def h(a:B,b:B,c:B=1):B=if(b>0)h(a,b-1,m(a,c))else c
@tailrec
def t(a:B,b:B,c:B=1):B=if(b>0)t(a,b-1,h(a,c))else c
La llamada tailrecursive es más larga que el método original, pero no aumentó el flujo de stackover en la versión larga; sin embargo, no produce un resultado en un tiempo razonable. t (2,4) está bien, pero t (3,3) ya fue detenido por mí después de 5 min. Sin embargo, es muy elegante, ¿no?
// 124 = 119-5 bonus
type B=BigInt
def r(a:B,b:B,c:B,f:(B,B)=>B):B=if(b>0)r(a,b-1,f(a,c),f)else c
def t(a:B,b:B)=r(a,b,1,r(_,_,1,r(_,_,0,(_+_))))
Y ahora lo mismo que antes: use una multiplicación apestosa (incluso nos beneficiamos al rechazar la bonificación de 5, porque ahorramos 7 caracteres: win = 4 caracteres :)
// 115 without bonus
type B=BigInt
def r(a:B,b:B,c:B,f:(B,B)=>B):B=if(b>0)r(a,b-1,f(a,c),f)else c
def t(a:B,b:B)=r(a,b,1,r(_,_,1,(_*_)))
invocación:
timed ("t(4,3)")(t(4,3))
t(4,3): 1
scala> t(4,3)
res89: B = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
Tiempo de ejecución: 1 ms.
*
es la multiplicación en algunos contextos, pero también es la sencilla bucle operador:{block}N*
es equivalente a C-estilofor(i=0;i<N;i++){block}
. El caso difícil es la multiplicación de cadenas / matrices ('a'3*
da'aaa'
), pero es poco probable que sea un problema dado que una matriz de4***3
elementos desbordará la RAM.