λ計算で数値のリストをソートする


8

純粋な型付けされていないラムダ計算に、教会でエンコードされた数値のリストに適用されると、昇順または降順で並べ替えられた数値を返す用語を記述します。教会のリストと番号は、通常のADTの折りたたみとしてエンコードする必要があります。

-- Usual ADTs for Lists and Nats (in Haskell, for example)
data List a = Cons a (List a) | Nil
data Nat a  = Succ (Nat a) | Zero

-- Their respective folds are the λ-calculus representation used on this challenge
church_list = (λ c n . (c ... (c ... (c ... n))))
church_num  = (λ succ zero . (succ (succ (succ ... zero))))

入力例:

(λ cons nil .
    (cons (λ f x . (f x))                         -- 1
    (cons (λ f x . (f (f (f (f (f (f (f x)))))))) -- 7
    (cons (λ f x . (f (f x)))                     -- 2
    (cons (λ f x . (f (f (f x))))                 -- 3
    nil)))))

出力例:

(λ cons nil . 
    (cons (λ f x . (f x))                         -- 1
    (cons (λ f x . (f (f x)))                     -- 2
    (cons (λ f x . (f (f (f x))))                 -- 3
    (cons (λ f x . (f (f (f (f (f (f (f x)))))))) -- 7
    nil)))))

提出物のスコアは次のように計算されます。

score(x)    = 1
score(λx.t) = score(t) + 1
score(t s)  = score(t) + score(s) + 1

最も低いスコアが勝ちます。


7
リンクされたページは、リストに対して3つの異なる教会のエンコーディングを提供し、将来変更されるのを止めるものは何もありません。質問を明確にするために、質問で明確に考えている特定のエンコーディングを定義する必要があります。(数値のエンコードを定義することもお勧めします)。
Peter Taylor

1
昇順または降順 -なぜ選択するのですか?
リン

私はそれを制限する理由を見つけられませんでした。何故なの?
MaiaVictor

回答:


3

私はなんとか自分のマークを打ち負かした:

sort = λabcd.a(λef.f(λghi.g(λj.h(λkl.kj(ikl)))(hi))e(λgh.h))
       (λe.d)(λe.b(λf.e(f(λghi.hg)(λgh.cfh))))

ただし、注意点があります。この用語には、考慮される自然の最大サイズに関する追加の引数が必要です。たとえば、sort 4 [1,7,3,6,5][1,3]4以上の値を無視してを返します。もちろん、無限大(つまり、Yコンビネーター)を指定することもできます。

sort = λbcd.(λfx.f(x x))(λfx.f(x x))(λef.f(λghi.g(λj.h(λkl.kj(ikl)))
       (hi))e(λgh.h))(λe.d)(λe.b(λf.e(f(λghi.hg)(λgh.cfh))))

そして、それは自然数の任意のリストをソートしますが、この用語は明らかにもはや正規形を持っていません。


1

121文字/スコア91

sort = λabc.a(λdefg.f(d(λhij.j(λkl.k(λmn.mhi)l)(h(λkl.l)i))
       (λhi.i(λjk.bd(jhk))(bd(h(λjk.j(λlm.m)k)c))))e)(λde.e)
       (λde.d(λfg.g)e)c

これは通常の形式であり、一般的な部分式を削除することで短くすることができます。


1

これは挿入ソートの実装です:

let nil =       \f x.x in
let cons = \h t.\f x.f h (t f x) in
let 0 =       \f x.x in
let succ = \n.\f x.f (n f x) in
let None =    \a b.b in
let Some = \x.\a b.a x in
let pred = \n.n (\opt.opt (\m.Some(succ m)) (Some 0)) None in
let optpred = \opt.opt pred None in
let - = \m n.n optpred (Some m) in
let < = \m n.\trueval falseval.- m n (\diff.falseval) trueval in
let pair = \x y.\f.f x y in
let snd = \p.p (\x y.y) in
let insert = \n l.snd (l (\h recpair.recpair (\rawtail insertedtail.
  let rawlist = cons h rawtail in
    pair rawlist (< h n (cons h insertedtail) (cons n rawlist))))
  (pair nil (cons n nil))) in
\l.l insert nil

ここでは、pred nの要素を返しますoption natpred 0れるNone一方pred (n+1)ですSome n。次に、- m nその要素option natSome (m-n)if m>=nまたはNoneif である要素を返しますm<n< m nブール値を返します。最後に、insertペアを返す内部関数を使用しますf l = (l, insert n l)(リストの末尾を取得するためのかなり典型的な方法で、再帰的な値とともに再帰に渡されます)。

今、将来のゴルフ仕事のためのいくつかのノートは:実際にはnil0None正式に同じ関数であることが起こる(と、それはまたに表示されますsnd)。次に、letステートメントでベータ削減を実行することを検討します(もちろん、これは通常の構文シュガーであり、let a = x in y平均が(\a.y)xあり、そのためスコアがありますscore(x) + score(y) + 2)。これにより、どのケースでスコアが削減されるかを確認します。一度だけ使用されます。

次に、よりトリッキーなことが起こります。たとえば、ソート関数の定義が、、に正式pred = pair (pair (\m.Some(succ m)) (Some 0)) Noneになりoptpred = pair pred None、スコアが少し低下する可能性があることに気づきました。- = \m.pair optpred (Some m)pair insert nil


スコアを計算し、回答に
ナサニエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.