2.}<@>%?<{>$"/\M!8;
Okunabilir:
2 . }
< @ > %
? < { > $
" / \ M
! 8 ;
Çevrimiçi deneyin!
Bu muhtemelen bir veya iki baytlık bir golfle oynanabilir, ancak kaba bir kuvvetle daha kolay bulunabilen bazı gerçekten ustaca bir düzen gerektirebilir (bulması oldukça uzun zaman alabilir).
Yüksek seviye açıklama
Program çoğunlukla bu sözde kodu izler:
while (read number is not zero)
{
if (number is even)
print number;
}
Bu durum, Hexagony'in STDIN boşaldığında bir sayıyı okumaya nasıl istismarı vardır (sıfırı döndürür). Martin'e bu yaklaşımın ortaya çıkmasında yardımcı olduğu için teşekkür ederiz.
Tam açıklama
Timoi'nin harika ezoterik IDE'sini çalıştırmak için hala Mono'yla uğraşmadım , bu yüzden Martin'e bana bazı güzel resimler sağlamak için eğildim!
İlk olarak, Hexagony'deki temel kontrol akışı üzerine küçük bir astar. Bu programda kullanılan ilk komut göstericisi (IP), altıgen kaynak kodunun sol üstünden başlayarak sağa doğru hareket etmeye başlar. IP, altıgenin kenarından her ayrıldığında, side_length - 1
satırları altıgenin ortasına doğru hareket ettirir . Bu program, yan uzunlukta üç altıgen kullandığından, bu olduğunda IP her zaman iki satır hareket edecektir. Bunun tek istisnası, geçerli bellek kenarının değerine bağlı olarak koşullu olarak altıgenin üst veya altına doğru hareket ettiği orta sıradan hareket etmesidir.
Şimdi şartlamalar hakkında biraz. Kontrol akışı için Hexagony tek koşul vardır >
, <
ve altıgen, orta kenar. Bunların hepsi sabit bir kural izler: mevcut bellek kenarındaki değer sıfır ise veya negatif kontrol akışı sola hareket ederse ve pozitifse kontrol doğru akar. Köşeli ayraçlardan büyük ve küçük olanı IP'yi altmış derece açılarla yeniden yönlendirirken, altıgenin kenarı IP'nin hangi satırda sıçradığını kontrol eder.
Hexagony ayrıca, tüm verilerin sonsuz altıgen ızgarasının kenarlarında depolandığı özel bir bellek modeline sahiptir. Bu program sadece üç kenar kullanır: biri ikiyi saklamak için, diğeri halihazırda okunan numara için ve diğeri modulo iki numara için. Bir şeye benziyor:
Mod \ / Input
|
2
Programın açıklanması sırasında her noktada nerede bellekte bulunduğumuzu dikkatlice açıklayamayacağım, bu yüzden bellekte bulunduğumuz yerle kafanız karışırsa buraya geri dönün.
Tüm bunların dışında, gerçek açıklama başlayabilir. İlk önce "2" kenarını 2 ile belleğe yerleştirdik, sonra no-op yürüttük ve bellek imlecini sağa hareket ettiriyoruz ( 2.}
).
Daha sonra ana program döngüsüne başlarız. İlk sayıyı STDIN'den okuduk ve ardından bir koşullu ( ?<
) isabet ediyoruz . STDIN'de hiç sayı kalmadıysa, bu mevcut bellek kenarına bir sıfır okur, bu nedenle @
programı sonlandıran sola dönüyoruz . Aksi taktirde, bir aynadan sekeriz, hafıza işaretçisini geriye ve sola hareket ettiririz, girişi 2'ye bölüp kalanını hesaplamak için altıgenin etrafına sarılır ve sonra bir şartlı ( /"%>
) düğmesine basarız .
Kalan bir tane ise (yani sayı tekse), no-op işlevini tekrar uygulayarak yukarıdaki mavi yolu takip ederek sağa döneriz, sonra altıgenin altına sarılır, geçerli kenarı 10 ile çarpıp sonra ekleriz. sekiz, birkaç aynadan sekerek, aynı çarpımı ve eklemeyi tekrar yapın, geçerli kenardan 188'i alıp, altıgenin üst kısmına geri sarın, no-op'u tekrar uygulayın ve son olarak programı sonlandırın ( .8/\8.@
). Bu sarsılmış sonuç mutlu bir kazaydı, başlangıçta çok daha basit bir mantık yazmıştım, ancak daha fazla Hexagony ruhu içinde olduğunu düşündüğüm no-op'un lehine kaldırabileceğimi fark ettim.
Kalan sıfır ise, yukarıdaki kırmızı yoldan sonra sola döneriz. Bu, bellek işaretçisini sola hareket ettirmemize ve ardından değeri oradaki (giriş değeri) sayı olarak basmamıza neden olur. Karşılaştığımız ayna, hareket ettiğimiz yönden dolayı no-op görevi görür ( {/!
). Ardından, daha önce gelen girdi değeri pozitif olarak test edildiğinden, tek bir sonuçla koşullu olan altıgen kenarına çarptık, bu yüzden her zaman sağa doğru hareket ediyoruz (kendinizi IP yönüne doğru bakacaksanız) . Daha sonra girişi 10 ile çarptık ve sadece iki yön ekliyoruz, sadece yönünü değiştirmek, sarmak ve yeni değeri M, 77 büyük harfinin ascii değeriyle değiştirmek. bir trambolin ile altıgen (2<M\>$
). 77 pozitif olduğundan, altıgenin altına doğru hareket ediyoruz ve trambolin nedeniyle ilk talimatı atlıyoruz ( !
). Daha sonra mevcut bellek kenarını 10 ile çarpıp 8 ekleyerek 778 alıyoruz. Daha sonra bu değeri mod 256 (10) olarak ASCII karakteri olarak çıkardık, bu da yeni satır olur. Sonunda altıgenden çıktık ?
ve bir sonraki giriş değeriyle 778'i geçersiz kılan ilkine geri döndük .