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 0N defa gireriz ; burada N, girişdir. Bunların hepsi, kodun bu kısmı ile tam bir şekilde kurulmuştur:
p
\Ai
\&
> 0
( 0Sonuç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ı, fkendi girişi) (akım değeri x) ve ardından sağa doğru (test işlevine her ikisi de geçer gbu 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 golup olmadığını kontrol etmek için üç değerin de bulunduğu bir işlev anlamına gelir x.
fRakam 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~bbir 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 fve gsı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 gbir fonksiyon üzerinde hesaplayan bir fonksiyon verir [x, g(y)]. Bunu sol kancayla birlikte kullanarak felde ediyoruz [f(x), g(y)]. Bu, sırayla, tek bir bağlamda kullanılır, bu aslında onunla çağrıldığı x == yve 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 :xpsg
&]&|
<*&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 gzaten 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 Nher 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 |, dveNsadece 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 fve gbunlar hesaplar ikili işlevini temsil f(a, g(a, b)). Bizim durumumuzda aürün / toplam çifti, bmevcut girdi değeri, gbö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 .<