Size bir Hexagony kendini tercümanın ilk% 3'ünü sunuyorum ...
|./...\..._..>}{<$}=<;>'<..../;<_'\{*46\..8._~;/;{{;<..|M..'{.>{{=.<.).|.."~....._.>(=</.\=\'$/}{<}.\../>../..._>../_....@/{$|....>...</..~\.>,<$/'";{}({/>-'(<\=&\><${~-"~<$)<....'.>=&'*){=&')&}\'\'2"'23}}_}&<_3.>.'*)'-<>{=/{\*={(&)'){\$<....={\>}}}\&32'-<=._.)}=)+'_+'&<
Çevrimiçi deneyin! Ayrıca kendi üzerinde çalıştırabilirsiniz, ancak yaklaşık 5-10 saniye sürer.
Prensip olarak bu, yan uzunluk 9'a (217 ya da daha az puan için) uygun olabilir, çünkü bu sadece 201 komut kullanır ve ilk yazdığım asılsız versiyon (yan uzunluk 30'da) sadece 178 komut gerektiriyordu. Ancak, aslında her şeyi uygun hale getirmek için sonsuza dek süreceğinden eminim, bu yüzden gerçekten denemeye çalışacağımdan emin değilim.
Son bir ya da iki sıranın kullanılmasından kaçınılarak, bunu 10 nolu boyutta golf yapmak da mümkün olmalıdır, öyle ki takip eden no-op'ların atlanabilmesi için, ancak ilk yollardan biri olarak önemli bir yeniden yazma gerektirir. birleşimler sol alt köşeden yararlanır.
açıklama
Kodu açarak ve kontrol akışı yollarını ekleyerek başlayalım:
Bu hala oldukça dağınık, bu yüzden ilk önce yazdığım "asılsız" kod için aynı diyagram var (aslında, bu yan uzunluk 20'dir ve başlangıçta kod yan taraf 30'a yazdım ama bu çok seyrek olacaktı. okunabilirliği hiç geliştirmedim, bu yüzden boyutu biraz daha makul hale getirmek için biraz sıkıştırdım):
Daha büyük versiyon için tıklayınız.
Renkler çok küçük detaylardan tamamen aynıdır, kontrol dışı akış komutları da aynıdır. Bu yüzden bunun eskimiş versiyona göre nasıl çalıştığını açıklayacağım ve eğer golf oyununun nasıl çalıştığını gerçekten bilmek istiyorsanız, hangi altı köşede hangi parçalara karşılık geldiğini kontrol edebilirsiniz. (Tek alıcı, golf kodunun bir ayna ile başlamasıdır, böylece gerçek kod sol köşeden başlayarak başlar.)
Temel algoritma, CJam cevabımla neredeyse aynı . İki fark var:
- Ortalanmış altıgen sayı denklemini çözmek yerine, sadece girişin uzunluğuna eşit veya daha büyük olana kadar ardışık merkezlenmiş altıgen sayılarını hesaplarım. Bunun nedeni, Hexagony'in kare kökü hesaplamak için basit bir yolunun olmamasıdır.
- Girişi hemen op-op olmadan doldurmak yerine, girdilerdeki komutları zaten tükettiğimi kontrol eder ve
.
varsa yazdırabilirim .
Bu, temel fikrin aşağı doğru kaydığı anlamına gelir:
- Uzunluğunu hesaplarken giriş dizesini okuyun ve saklayın.
- Tüm girişi tutabilen en küçük yan uzunluğu
N
(ve karşılık gelen ortalanmış altıgen numarayı hex(N)
) bulun .
- Çapı hesaplayın
2N-1
.
- Her satır için, girintiyi ve hücre sayısını (toplamı
2N-1
) hesaplayın . Girintiyi yazdır, hücreleri yazdır ( .
girdi zaten bitmişse kullanarak ), satır besleme yazdırın.
Yalnızca no-ops olduğuna dikkat edin, bu yüzden gerçek kod sol köşeden başlar ( $
üstünden atlayan >
, gerçekten,
koyu gri yoldan başlıyoruz ).
İşte ilk bellek ızgarası:
Böylece, bellek işaretçisi kuzey işaretli kenarda etiketli giriş üzerinde başlar . ,
STDIN'den bir bayt veya EOF'ye -1
bu kenara çarptığımızda bir okur . Bu nedenle, <
hemen ardından tüm girdileri okuyup okumadığımız için şartlı bir şart var. Şimdilik giriş döngüsünde kalalım. Çalıştırdığımız bir sonraki kod
{&32'-
Bu, 32 işaretli kenara boşluğa bir 32 yazar ve daha sonra dif etiketli kenardaki giriş değerinden çıkarır . Bunun asla negatif olamayacağına dikkat edin çünkü girişin yalnızca yazdırılabilir ASCII içerdiğini garanti ediyoruz. Giriş bir boşluk olduğunda sıfır olacaktır. (Timwi'nin işaret ettiği gibi, giriş satır satırları veya sekmeler içeriyorsa, bu yine de işe yarar, ancak 32'den küçük karakter kodlarıyla diğer tüm yazdırılamayan karakterleri de çıkarır.) Bu durumda, <
yönlendirme işaretçisini (IP) bıraktı ve açık gri renkli yol alınır. Bu yol sadece MP'nin konumunu sıfırlar {=
ve ardından bir sonraki karakteri okur - böylece boşluklar atlanır. Aksi takdirde, karakter bir boşluk değilse,
=}}})&'+'+)=}
Bu, ilk önce altıgen etrafında uzunluk kenarından, dif kenarına zıt olana kadar hareket eder =}}}
. Daha sonra kopya ters gelen değer uzunlukta bir kenarının uzunluğu ile kenar ve artışlarla o )&'+'+)
. Bunun neden anlamlı olduğunu bir saniye sonra göreceğiz. Sonunda yeni kenarı şununla taşıyoruz =}
:
(Özel kenar değerleri, mücadelede verilen son test durumundandır.) Bu noktada, döngü tekrar eder, ancak her şey bir altıgen kuzeydoğuya kaydırılır. Yani başka bir karakter okuduktan sonra, şunu elde ederiz:
Şimdi yavaş yavaş diğer her kenarda karakterlerle, kuzeydoğu diyagonal boyunca girişini (eksi boşluk) yazıyoruz ve bu karaktere uzunluğu kadar kenar etiketli paralel saklanmasını görebilirsiniz uzunluğu .
Giriş döngüsüyle işimiz bittiğinde, bellek şöyle görünecektir (burada bir sonraki bölüm için birkaç yeni kenar etiketledim):
%
Okuduğumuz son karakteridir, 29
okuduğumuz olmayan uzay karakter sayısıdır. Şimdi altıgenin kenar uzunluğunu bulmak istiyoruz. İlk olarak, koyu yeşil / gri yolunda bazı doğrusal başlatma kodları var:
=&''3{
Burada, =&
kenar etiketli kopyalar (bizim örneğimizde 29) uzunluğu uzunluğu . Sonra 3''3
etiketli kenara hareket eder ve değerini (hesaplamada sadece sabit olarak ihtiyacımız olan) olarak ayarlar . Sonunda N (N-1) etiketli kenara gider .3
{
Şimdi mavi döngüye giriyoruz. Bu döngü artışları N
( N etiketli hücrede saklanır ) daha sonra ortalanmış altıgen sayısını hesaplar ve giriş uzunluğundan çıkarır. Bunu yapan doğrusal kod:
{)')&({=*'*)'-
Burada, N'ye{)
taşınır ve yükselir . N-1 etiketli kenara gider , kopyalar ve onu azaltır. Ürünlerini N (N-1) cinsinden hesaplar . bunu sabitle arttırır ve sonucu, hex (N) etiketli kenarda artırır . Beklendiği gibi, bu Ninci merkezli altıgen sayıdır. Sonunda bununla giriş uzunluğu arasındaki farkı hesaplar. Sonuç pozitifse, yan uzunluk henüz yeterince büyük değildir ve döngü tekrar eder ( MP'yi N (N-1) etiketli kenara geri götürür ).')&(
N
{=*
'*)
3
'-
}}
Kenar uzunluğu yeterince büyük olduğunda, fark sıfır ya da negatif olacaktır ve şunu elde ederiz:
Öncelikle, şimdi çıktı döngüsü için bazı gerekli ilklendirmeleri yapan gerçekten uzun doğrusal yeşil yol var:
{=&}}}32'"2'=&'*){=&')&}}
{=&
Sonucu kopyalayarak başlar fark içine kenar uzunluğu daha sonra orada pozitif olmayan bir şeye ihtiyacım çünkü kenar. }}}32
Kenar etiketli bir 32 yazar alanı . dif'"2
üzerindeki etiketlenmemiş kenara sabit bir 2 yazar . aynı etikete sahip ikinci kenara kopyalar . 2 ile çarpar ve üstte 2N-1 etiketli kenardaki doğru değeri elde etmemiz için arttırır . Bu altıgenin çapıdır. çapı 2N-1 etiketli diğer kenara kopyalar . Sonunda üstte 2N-1 etiketli kenara geri döner .'=&
N-1
'*)
{=&')&
}}
Kenarları tekrar etiketleyelim:
Şu anda üzerinde bulunduğumuz kenar (hala altıgenin çapını tutar) çıktının çizgileri üzerinde yineleme yapmak için kullanılacaktır. Kenar etiketli girinti , geçerli satırda kaç boşluk gerektiğini hesaplar. Kenar etiketli hücreler , geçerli satırdaki hücre sayısı üzerinde yineleme yapmak için kullanılacaktır.
Şimdi girintiyi hesaplayan pembe yoldayız . ('-
azaltır hatları yineleyici ve onu çıkarır , N-1 (içine girinti kenar). Koddaki kısa mavi / gri dalı basitçe sonucun modülüsünü hesaplar ( ~
eğer negatifse veya sıfır ise değeri olumsuzlar, pozitifse hiçbir şey olmaz). Pembe yolun geri kalanı "-~{
, girintiyi çaptan hücre kenarına çıkartan ve ardından girintili kenarına geri hareket edendir .
Kirli sarı yol şimdi girintiyi yazdırıyor. Döngü içeriği gerçekten sadece
'";{}(
Burada '"
için hareket alanı kenarı ;
basar, {}
hareket geri girinti ve (
bunu azaltır.
Bununla işimiz bittiğinde (ikinci) koyu gri yol yazdırılacak bir sonraki karakteri arar. =}
(Üzerine gelir, pozisyonda hareket hücreler kenarı, South işaret). Sonra {}
, saklı dize sonuna kadar, sadece Güney-Batı yönünde iki kenarı aşağı doğru hareket ettiren çok sıkı bir ilmeğe sahibiz:
Oradaki bir kenarı yeniden etiketlediğime dikkat et EOF? . Bu karakteri işledikten sonra, bu kenarı negatif yapacağız, böylece {}
döngü bir sonraki yineleme yerine burada sona erecek:
Kodda, koyu gri yolun sonunda, '
bir adım geri giriş karakterine ilerliyoruz. Eğer durum son iki diyagramdan biriyse (yani henüz basmadığımız girdilerden hala bir karakter varsa), o zaman yeşil yolu izliyoruz (en alttaki, yeşil ile iyi olmayan insanlar için ve mavi). Bu oldukça basittir: ;
karakterin kendisini basar. Daha önceki 32'yi hala tutan '
karşılık gelen boşluk kenarına gider ve ;
o alanı yazdırır. Sonra {~
bizim EOF yapar ? Bir sonraki yineleme için negatif, '
geriye doğru bir adım geriye doğru hareket eder , böylece ipin Kuzey-Batı ucuna geri dönebiliriz }{
. Uzunluğu bitiyorhücre ( altıgen altı (N) pozitif olmayan ) Sonunda hücreler kenarına }
geri döner .
Girdiyi zaten tüketmişsek, EOF'u arayan döngü nedir? aslında burada sona erecek:
Bu durumda '
, uzunluk hücresine doğru ilerler ve bunun yerine açık mavi (üstte) yoldan ilerliyoruz , bu da işlem dışı. Bu daldaki kod doğrusaldır:
{*46;{{;{{=
{*46;
Yazma kenarına 46 etiketli herhangi bir-op ve (örneğin, bir süre) basar. Sonra boşluk kenarına {{;
gider ve bunu yazdırır. Bir sonraki yineleme için tekrar hücre kenarına hareket eder .{{=
Bu noktada yollar tekrar bir araya gelir ve hücre kenarını (
azaltır . Yineleyici henüz sıfır değilse, MP'nin yönünü değiştiren açık gri yolu izleriz ve sonra yazdırılacak bir sonraki karakteri ararız.=
Aksi takdirde, şu anki satırın sonuna geldik ve IP bunun yerine mor yolu izleyecektir. Bu noktada bellek ızgarası nasıl görünüyor:
Mor yol bunu içerir:
=M8;~'"=
=
Yine MP yönünü tersine çevirir. M8
oluşturduğunun onun değerini ayarlar 778
(karakter kodu çünkü M
olduğunu 77
ve rakam şimdiki değeri kendilerini ekler). Bu olur 10 (mod 256)
, öyleyse yazdırdığımızda ;
satır sıkıntısı çekeriz. Daha sonra ~
kenar negatif yeniden yapar '"
geri hareket hatları kenar ve =
MP bir kez daha geri döner.
Şimdi çizgi kenarı sıfırsa, bittik. IP @
, programı sonlandıran (çok kısa) kırmızı yolu izleyecektir . Aksi takdirde, başka bir satır yazdırmak için pembe renge geri dönen mor yolda devam ederiz.
Timwi'nin HexagonyColorer ile oluşturulan kontrol akış şemaları . Ezoterik IDE'sinde görsel hata ayıklayıcı ile oluşturulan bellek diyagramları .
abc`defg
aslında pastebin.com/ZrdJmHiR