Скала: 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(_,_,(_+_))))
неозорений:
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 (_, _, (_ + _))))
пояснення:
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
плюс, mul, високий (: = pow), тетрація, все працює однаково. Загальну схему можна отримати як рекурсивний метод, який займає два BigInts та основну функцію:
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(_,_, (_+_))))
Підкреслення є заповнювачем для чогось, що викликається в цій послідовності, наприклад додавання плюс (a, b) = (a + b); тому ( + ) - це функція, яка бере два аргументи і додає їх (a + b).
на жаль, у мене виникають проблеми з розміром стека. Він працює для малих значень для 4 (наприклад: 2) або якщо я зменшу глибину на один крок:
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(_,_,(_+_))))
Оригінальний код - 112 символів і набрав би, якщо дійсний, 107. Можливо, я дізнаюся, як збільшити стек.
Розширений алгоритм може бути перетворений на рекурсивні виклики:
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
Хвостовий рекурсивний виклик довший, ніж оригінальний метод, але не викликав поточного потоку у довгому варіанті - однак це не дає результату у розумні строки. t (2,4) добре, але t (3,3) мене вже зупинили через 5 хв. Однак це дуже елегантно, чи не так?
// 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,(_+_))))
І тепер те саме, що вище: використовуйте смердюче множення (ми навіть отримуємо прибуток, відкидаючи бонус 5, тому що ми економимо 7 символів: win = 4 символи :)
// 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,(_*_)))
виклик:
timed ("t(4,3)")(t(4,3))
t(4,3): 1
scala> t(4,3)
res89: B = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096
тривалість виконання: 1 мс.
*
є множення в деяких контекстах, але це також простий цикл оператора:{block}N*
еквівалентно C-стиліfor(i=0;i<N;i++){block}
. Складний крайний край - це множення рядків / масивів ('a'3*
дає'aaa'
), але це навряд чи буде проблемою, враховуючи, що масив4***3
елементів переповнить оперативну пам’ять.