Kilise Çıkarma


13

Kilise Çıkarma

Lambda hesabı her zaman benim bir büyüleme olmuştur ve işlevleri birbirine geçirmenin ortaya çıkan davranışları son derece karmaşıktır. Kilise rakamları , bir fonksiyonun tekrarlanan uygulamasından (normalde bir sabitin tekli eklenmesi) oluşturulan doğal sayıların temsilidir. Örneğin, sıfır sayısı x değerini döndürür ve giriş işlevini "yok sayar", biri f(x), iki, f(f(x))vb.:

ident = lambda x: x
zero = lambda f: ident
succ = lambda n: lambda f: lambda x: f(n(f)(x))
one = succ(zero)
add1 = lambda x: x + 1
to_int = lambda f: f(add1)(0)
print(to_int(one))
>>> 1

Buradan, ilk fonksiyonun x'e ilk fonksiyonunun ardından x'e ikinci fonksiyonun uygulanmasıyla gerçekleştirildiğini kolayca görebiliriz:

add = lambda m: lambda n: lambda f: lambda x: n(f)(m(f)(x))
print(to_int(add(one)(two)))
>>> 3

Toplamanın anlaşılması nispeten kolaydır. Ancak, yeni gelen biri için Kilise kodlu bir sayı sisteminde çıkartmanın nasıl göründüğünü düşünmek akıl almaz olabilir. Bir işlevi uygulamaktan vazgeçmek ne anlama gelir?

Meydan okuma

Çıkarma işlevini Kilise kodlu bir sayı sisteminde uygulayın. Çıkarma işleminin monus işlemini gerçekleştirmesi ve nsonuç sıfırdan büyük veya sıfırdan büyükse bir işlev süresinin kaldırılması. Bu kod golf çok kısa kod kazanır.

Giriş

Dil seçiminize göre kodlanmış iki Kilise rakamı. Giriş konumsal veya curried olabilir. Bunlar gerçek Kilise rakamlarını kanıtlamak için herhangi bir işlev alıp defalarca uygulamak zorunda kalacak ( add1örneklerde verilmiştir ama olabilir add25, mult7ya da başka herhangi tekli fonksiyonu.)

Çıktı

Kilise sayısı. Eğer m < no m - nzaman kimlik fonksiyonu ile her zaman aynı olduğu unutulmamalıdır .

Örnekler:

minus(two)(one) = one
minus(one)(two) = zero
...

ayrıca kabul edilebilir:

minus(two, one) = one
minus(one, two) = zero

Kredi:

Bu github bana Kilise Rakamlarının python uygulamasını verdi.


1
(Özetteki yorum yanlıştır; elbette exp(m, n)hesaplar m^n.)
Neil

1
"Girdi konumsal veya curried olabilir" demek istediğinizden emin değilim. Ana işlevi yerine lambda m,n,f:apply f m-n times(veya çift lambda m,n,f,x:apply f m-n times to x) olarak tanımlamak uygun lambda m,n:lambda f:...mudur? Ya da bu sadece iki girişine geçerlidir mve n?
xnor

Ayrıca, argümanları mve ndiğer sırayla alabilir miyiz? Bu köriliğe yardımcı olur.
xnor

@xnor, iki kilise rakamını çıkardığını kanıtlayabildiğiniz sürece, girişleri istediğiniz gibi alabilirsiniz.
Ryan Schaefer

Yanıtlar:


9

Haskell , 35 bayt

(r%s)f x=s(x:)(iterate f x)!!r(+1)0

Çevrimiçi deneyin!

Bunu söyle rve skilise kodlamaları mve n. Başlangıç ​​değerine zaman r%suygulamak istiyoruz . Önce sonsuz listeyi üretiyoruzf m-nx

iterate f x = [x, f x, f (f x), f (f (f x)), ...]

daha sonra , her bir değer endeksinin kopyalarını s(x:)başına eklemek için kullanınnxn

s(x:)(iterate f x) = [x, x, x, ...,  x, f x, f (f x), f (f (f x)), ...]

Daha sonra mdoğrudan olarak hesaplar r(+1)0ve mbu listenin 'elemanını' olarak alırız !!r(+1)0. Bunun yerine head$r tail$..., dizin oluşturma gerektirmeyen bir çözüm yapabilir , yani ilk öğe msürelerini bırakıp ilk öğeyi alır, ancak dizin oluşturma sözdizimi çok daha kısadır.

O Not klasik çözüm güçlü yazarak selefi çalışmasını temsil edemez çünkü uzantıları olmadan Haskell çalışmaz.


3

Python 2 , 82 80 bayt

eval('!u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!u:x)(!u:u))(u)'.replace('!','lambda '))

Çevrimiçi deneyin!

Nick Kennedy'ye 2 bayt teşekkürler, ihtiyaç duyulmayan bir çift parense dikkat çekti.

Eksi uygulayan anonim işlev.

Çoğunlukla bu, Wikipedia sayfasında bulunan tanımı sıkıştırmaktır; henüz kodu gerçekten anlamak gibi değil. Ama ilginç!


Belirtilen gist dayanarak, !u:!v:v(!n:!f:!x:n(!g:!h:h(g(f)))(!y:x)(!x:x))(u)2 bayt tasarruf gibi görünüyor, ama gerçekten kodu anlamıyorum!
Nick Kennedy

Eğer ilgileniyorsanız @NickKennedy gettingsharper.de/2012/08/30/…
Ryan Schaefer

@Ryan Schaefer: Güzel "Hile"!
Chas Brown

3

Python 2 , 77 bayt

lambda r,s:s(lambda r:lambda f:lambda x:r(lambda(_,x):(x,f(x)))((x,x))[0])(r)

Çevrimiçi deneyin!

Her iterasyon için önceki değeri takip ederek ve sonunda bunu çıkararak Kilise azalmasını yapıyoruz. Kod uzunluğunun% 39'u "lambda"...


Güzel! Sadece gists uygulamasına bakmakla kalmadı, golflü bir python cevabı bekliyordum. Bunu daha fazla golf oynamak için diğer cevap gibi eval kullanmayı düşündünüz mü?
Ryan Schaefer

@RyanSchaefer Diğer yanıtı gördüğümde eval / replace şeyi kontrol ettim, ama aslında yerine 5 lambdas ile 2 bayt daha uzun. Python maalesef hem tanımlayıcı işlevlere hem de dize manipülasyonuna gerçekten düşkündür. Ve bir lambdas tabakasını kurtaracak yerleşik bir "beste" yok.
xnor

2

C ++ (clang) , 112 bayt

#define L(x,y)[&](auto x){return y;}
auto m=L(u,L(v,v(L(n,L(f,L(x,n(L(g,L(h,h(g(f)))))(L(u,x))(L(u,u))))))(u)));

Çevrimiçi deneyin!

Bu şimdiye kadar yazdığım en anlaşılmaz C ++ kodu. Bununla birlikte, bu kodu çözmenin sadece daha da kötüleşeceğini düşünüyorum.


2

Düşük yük , 37 bayt

(~(((!())~):*^(~!:(:)~*(*)*)~^^!)~^^)

Çevrimiçi deneyin!

İç (((!())~):*^(~!:(:)~*(*)*)~^^!)olan predçiftleri üzerinden uygulanan fonksiyonu:

(               ( start pred function )!
  (
    (!())~      ( push zero below argument )!
  ):*^          ( do that twice )!

  (             ( start pair-increasing function )!
    ~!          ( remove second argument)!
    :           ( duplicate first argument )!
    (:)~*(*)*   ( increment first return value )!
  )
  ~^^           ( run pair-increasing function n times )
  !             ( remove first in returned pair )!
)


1

JavaScript (Node.js) , 87 85 81 76 74 bayt

f=>g=>h=>x=>f(([x,[g,a]])=>[g(x),a])([x,g(a=>[x=>x,a])(f(a=>[h,a])())])[0]

Çevrimiçi deneyin! Hiçbir ödül kazanamayacaktım, ama farklı bir yaklaşım deneyeceğim diye düşündüm.

a=>[h,a]uygulayan bir aşamadır hiken, a=>[x=>x,a]geçerli değildir bir aşamadır h. İlk fonksiyon fzamanlarını ve ikinci fonksiyon gzamanlarını uygularız . Daha sonra ters fonksiyon ([f,[g,a]])=>[g(x),a] fsürelerini uygularız . Bu, gikinci aşamaların üzerinden atlar ve f-gistendiği gibi ilk aşamaları gerçekleştirir . Daha sonra nihai değeri çıkarmak kalır.

Tupler elbette aşağıdaki ifadeyle sonuçlanan lambda fonksiyonlarına dönüştürülebilir:

f=>g=>h=>x=>f(e=>e(x=>d=>d(g=>a=>e=>e(g(x))(a))))(e=>e(x)(g(a=>e=>e(x=>x)(a))(f(a=>e=>e(h)(a))())))(x=>a=>x)

1

J , 56 bayt

c=:3 :0
t=.^:y
5!:1<'t'
)
m=.2 :'c 0>.(>:u 5!:0->:v 5!:0)0'

Çevrimiçi deneyin!

Not: -3 bayt kapalı TIO sayısım=.

J'de daha yüksek mertebeden fonksiyonlar, zarflar ve bağlaçlar kullanılarak elde edilir. Burada bir kilise rakamı, "kuvvet" birleşiminin (tekrar tekrar bir fiil uygulayan) ve bir tamsayıyı birleştirerek oluşan zarfın gerund formudur. Aşağıdaki fiil c("create" için), bir tamsayıyı böyle bir miktara dönüştürmek için J'nin Atom Temsilini kullanır :

c=:3 :0
t=.^:y
5!:1<'t'
)

"Eksi" operatörünüz (bir kavşaktır) sağ gerund kilise rakamını soldan çıkarır. Bununla birlikte, fiilimizden gelenler de dahil olmak üzere kilise sayılarının herhangi bir özel uygulamasını varsaymaz c. Bunun yerine, genel tanımı kullanır ile çevrilmesiyle bir zarf içine, her gerund kilise numarası geri döner 5!:0ve daha sonra artış fiil bu zarf uygulanması >:ve daha sonra uygulanması bu 0.

Daha sonra çıkarır ve maksimum değeri 0 ile alır ve cnihai sonucu elde etmek için uygulanır : yeni bir gerund kilise rakamı.


1

Wolfram Dili (Mathematica) , 55 48 47 39 bayt (33 karakter)

#2[(fx#[g#@g@f&][x&][#&])&]@#&

Çevrimiçi deneyin!

 sembolü, sağa oku gösteren özel bir Mathematica kod noktası olan 0xF4A1'dir \[Function]. Daha fazla açıklama için buraya bakın . Mathematica ön ucunda kod şöyle görünür:

resim açıklamasını buraya girin

Biz de yapabiliriz 40 bayt / 32 karakter ölçüm şeması bağlı kısa olabilir,:#2[n⟼f⟼x⟼n[g⟼#@g@f&][x&][#&]]@#&

Golf edilmeyen versiyon, pred'in klasik tanımının gerçek bir çevirisidir :

pred = n \[Function] f \[Function] x \[Function] n[g \[Function] h \[Function] h[g[f]]][u \[Function] x][u \[Function] u];
subtract[m_, n_] := n[pred][m]

Mathematica ön ucunda şöyle görünür:

resim açıklamasını buraya girin

Bu çıkarma fonksiyonu ile tanımlanan Kilise numaraları ile çalışır

c@0=#& &;c@n_=#@*c[n-1][#]&

(un golfed: c[0] = Identity &; c[n_] = Function[a, a@*c[n-1][a]])

ki bizde

Table[c[n][f][x], {n, 0, 6}]
(*    {x, f[x], f[f[x]], f[f[f[x]]], f[f[f[f[x]]]], f[f[f[f[f[x]]]]], f[f[f[f[f[f[x]]]]]]}    *)

ve

subtract[c[7],c[5]][f][x]
(*    f[f[x]]    *)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.