p
\Ai
\&
>(&]&|0
<*&d
&~bN
10
( )/+
/*
Çevrimiçi deneyin!
açıklama
Bu, şu ana kadar Jellyfish'te yazdığım en ayrıntılı (ve aynı zamanda en uzun program) program. Bunu anlaşılır bir şekilde çözebilecek miyim, hiçbir fikrim yok, ama denemek zorundayım sanırım.
Denizanası \
"Nth şey bulma" konusunda çok yardımcı olan oldukça genel bir yineleme operatörü sağlar . Anlambilimcilerinden biri "ayrı bir test işlevi bir şeyler gerçeğe varana kadar bir değer üzerinde bir işlevi yinelemektir" (aslında, test işlevi hem akımı hem de son öğeyi alır, ancak yalnızca mevcut öğeye bakacağız) . Bunu "bir sonraki geçerli sayı" işlevini uygulamak için kullanabiliriz. Bir başka aşırı yüklenme \
"N kere başlangıç değerindeki bir fonksiyonu yinelemektir". Önceki fonksiyonumuzu kullanabilir ve 0
N defa gireriz ; burada N, girişdir. Bunların hepsi, kodun bu kısmı ile tam bir şekilde kurulmuştur:
p
\Ai
\&
> 0
( 0
Sonuçta ortaya çıkan işlevin asıl girişinin nedenleri bitmiştir, burada biraz karışık ve bunlara girmeyeceğim.)
Tüm bunlarla ilgili sorun şu ki, mevcut değeri test fonksiyonuna manuel olarak aktarmayacağız. \
Operatör bizim için yapacağız. Bu yüzden şimdi bir sayı alan ve geçerli bir sayı olup olmadığını söyleyen tek bir tekli fonksiyon (kompozisyonlar, kancalar, çatallar ve saç kurutma makinesi) kurduk. Bu, tartışmaya atıfta bulunmadığınızda oldukça önemsizdir. Hiç. Bu güzellik:
(&]&|
<*&d
&~bN
10
( )/+
/*
(
Bir tekli bir kanca aşağıda fonksiyon (çağırır araçları, f
kendi girişi) (akım değeri x
) ve ardından sağa doğru (test işlevine her ikisi de geçer g
bu hesaplar olan), g(f(x), x)
.
Bizim durumumuzda, f(x)
rakam ürün ve rakam toplamı ile bir çift elde eden başka bir bileşik fonksiyondur x
. Bu , geçerli g
olup olmadığını kontrol etmek için üç değerin de bulunduğu bir işlev anlamına gelir x
.
f
Rakam toplamının ve rakam ürününün nasıl hesaplandığına bakarak başlayacağız . Bu f
:
&~b
10
( )/*
/+
&
aynı zamanda kompozisyondur (ama tam tersidir). ~
Körleme işlemi 10~b
bir sayının ondalık basamağını hesaplayan bir işlev verir ve bunu &
sağdan geçirdiğimizden beri , girişte gerçekleşecek ilk şey budur x
. Kalan kısım, toplamını ve ürününü hesaplamak için bu rakam listesini kullanır.
Bir toplamı hesaplamak için, üzerine katlama yapabiliriz /+
. Aynı şekilde, ürünü hesaplamak için çarpma işlemini bunun üzerine katlıyoruz /*
. Bu sonuçların her ikisini de bir çift halinde birleştirmek için bir çift kanca kullanırız (
ve )
. Bunun yapısı:
()g
f
(Nerede f
ve g
sırasıyla, ürün ve toplamıdır.) Bu bize bir çift verir neden edelim deneyin anlamaya f(x)
ve g(x)
. Sağ kancanın )
sadece bir argüman olduğuna dikkat edin . Bu durumda, diğer argüman, ;
argümanlarını bir çifte sardığı anlamına gelir. Ayrıca, kancalar ikili fonksiyonlar olarak da kullanılabilir (buradaki durum bu olacaktır), bu durumda iç fonksiyonu sadece bir argümana uygularlar. Yani gerçekten )
tek g
bir fonksiyon üzerinde hesaplayan bir fonksiyon verir [x, g(y)]
. Bunu sol kancayla birlikte kullanarak f
elde ediyoruz [f(x), g(y)]
. Bu, sırayla, tek bir bağlamda kullanılır, bu aslında onunla çağrıldığı x == y
ve dolayısıyla gerektiği gibi sonuçlandığımız anlamına gelir [f(x), g(x)]
. Uf.
Bu, daha önceki test fonksiyonumuz olan tek bir şey bırakır g
. Halen geçerli giriş değerinin g([p, s], x)
neresi olarak çağrılacağını , rakam ürününün ve rakam toplamının olduğunu hatırlayın . Bu :x
p
s
g
&]&|
<*&d
N
Bölünebilirliği test etmek için, açıkça |
Denizanası'ndaki modulo'yu kullanacağız . Biraz alışılmadık bir şekilde, sağ operand modülünü sol operandını alır, yani argümanlar g
zaten doğru sıradadır (bunun gibi aritmetik fonksiyonlar otomatik olarak listelerde yer alır, bu nedenle bu iki ayrı modülü ücretsiz olarak hesaplar) . Sonuç bir çift sıfırsa, sayımız hem ürün hem de toplam tarafından bölünebilir. Durumun böyle olup olmadığını kontrol etmek için, çifte baz-2 rakamlarının ( d
) bir listesi gibi davranıyoruz . Bunun sonucu sıfırdır, sadece çiftin her iki öğesi de sıfır olduğunda, bu nedenle N
her iki değerin girişi bölüşüp bölmediğine ilişkin bir gerçek değer elde etmek için bunun ( ) sonucunu ihmal edebiliriz. Not |
, d
veN
sadece hepsi bir çift &
s ile birlikte oluşur .
Ne yazık ki, tam hikaye bu değil. Rakam ürün sıfırsa ne olur? Bölünme ve modulo sıfır olarak Denizanası'nda sıfıra geri döner. Bu biraz garip bir kongre gibi görünse de, aslında biraz faydalı olduğu ortaya çıkıyor (çünkü modulo yapmadan önce sıfırı kontrol etmemize gerek yok). Bununla birlikte, rakam toplamı girişi böldüğü halde yanlış bir artı değer alabileceğimiz anlamına gelir, ancak rakam ürün sıfırdır (örneğin, giriş 10
).
Bunu, bölünebilirlik sonucumuzu rakam ürünüyle çarparak düzeltebiliriz (eğer rakam rakam sıfırsa, gerçeğe uygun değerimizi de sıfıra çevirir). Bölünebilirlik sonucunu ürün çifti ve toplamı ile çarpmak ve sonucu daha sonra üründen çıkarmak daha basit hale geldi.
Sonucu parite ile çarpmak için daha erken bir değere (parite) geri dönmemiz gerekir. Bu bir çatalla ( ]
) yapılır. Çatallar steroidlerin kancası gibidir. Onlara iki işlevi verirsek f
ve g
bunlar hesaplar ikili işlevini temsil f(a, g(a, b))
. Bizim durumumuzda a
ürün / toplam çifti, b
mevcut girdi değeri, g
bölünebilirlik testimiz ve çarpımdır f
. Yani tüm bu hesaplar [p, s] * ([p, s] % x == [0, 0])
.
Şimdi kalan tek şey, iteratörde kullanılan test fonksiyonunun son değeri olan ilk değerini çıkarmak. Bu, listenin ilk değerini döndüren kafa işlevli &
çatalı beslemek ( ) kadar basittir .<