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(_,_,(_+_))))
なし:
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
plus、mul、high(:= pow)、tetrationはすべて同じ方法で機能します。共通パターンは、2つの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(_,_, (_+_))))
下線は、このシーケンスで呼び出されるもののプレースホルダーです。たとえば、pluss(a、b)=(a + b); したがって、(+)は2つの引数を取り、それらを追加する関数です(a + b)。
残念ながら、スタックサイズに問題があります。4(たとえば:2)の小さな値、または1ステップの深さを減らす場合に機能します。
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,(_+_))))
そして今、上記と同じ:臭い乗算を使用します(7文字を節約するため、5のボーナスを拒否しながら利益を得ます:win = 4 chars :)
// 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
ランタイム:1ms。
*
では、いくつかのコンテキストで乗算が行われますが、単純なループ演算子でもあります{block}N*
。Cスタイルと同等for(i=0;i<N;i++){block}
です。厄介なエッジのケースは文字列/配列の乗算('a'3*
を与える'aaa'
)ですが、4***3
要素の配列がRAMをオーバーフローさせることを考えると、それは問題になりそうにありません。