Brainfuck'ta golf oynamak için ipuçları


23

Beyin fırtınasında golf oynamak için hangi genel ipuçlarına sahipsiniz? Genel olarak golf problemlerini kodlamak için uygulanabilecek fikirlere bakıyorum (en azından beyin fırtınasına özgüdür (örneğin, "yorumları kaldır" bir cevap değildir). Lütfen cevap başına bir ipucu gönderin.

Yanıtlar:


25

Cevap başına bir ipucu koymak çok fazla cevap olabilir.

  • Brainfuck'ta düşünmeyi öğrenin. Her şeyden çok farklı. Beyin fırtınası programlarını okuyun ve yeniden yazın ve yeniden yazın. Dil size çalışmanız için fazla bir şey vermiyor, bu yüzden size esnek ve verimli bir şekilde kullanması önemlidir. Herhangi bir soyutlamanın seninle dilin arasına girmesine izin verme - içeri gir ve onunla uğraş.

  • Tahribatsız akış kontrolü ile çok rahat olun. Bir karar döngüsünden çıkmak için, başlangıç ​​hücresini başka bir yere kopyalayarak sıfırlamak ve ardından döngüyü terk ettikten sonra geri kopyalamak yerine, işaretçiyi yakındaki önceden var olan bir sıfıra taşımak daha iyidir. Evet, bu, işaretçinin döngüden geçip geçmediğinize bağlı olarak farklı yerlerde olacağı anlamına gelir, ancak bu, muhtemelen bu yerlerin başka bir döngü kullanarak işaretçi konumunu yeniden bağlamak için kullanabileceğiniz yakınlardaki sıfır ve sıfır olmayan farklı düzenlemelere sahip olduğu anlamına gelir. Bu teknik Brainfuck'ın iyi programlanması için temeldir ve çeşitli formları sürekli olarak yararlı olacaktır.

  • Bu ve her birinin >ya da <maliyetin, bellek düzeninin detaylarının önemli olduğu anlamına gelmesi. Mizanpajınızın çeşitliliğini, sabrınız olduğu kadar deneyin. Ve unutmayın, bellek düzeninizin verilerin konumlara katı bir şekilde eşleştirilmesi gerekmez. İnfaz sürecinde morph olabilir.

  • Daha büyük ölçekte, çeşitli algoritmalar kullanmayı düşünün ve hatta deneyin. Başlangıçta, hangi algoritmanın en iyi olacağı tam olarak belli olmayacak; Hangi temel yaklaşımın en iyisi olacağı bile belli olmayabilir ve muhtemelen normal bir dilde en iyi olandan farklı bir şey olacaktır.

  • Büyük veya değişken boyutlu verilerle uğraşıyorsanız, bunun ne kadar büyük olduğunu veya içindeki sayısal konumunuzu takip etmek zorunda kalmadan yerel olarak ele alabileceğiniz herhangi bir yol olup olmadığını görün.

  • Aynı veri iki farklı şey olabilir. (Çoğu zaman, bir sayı veya karakter ve sıfır olmayan bir konum belirteci. Ancak , bir bit sayacının hücresel otomatın bir hücresinin değeri olarak ikiye katlandığı rastgele.b'ye bakın .)

  • Aynı kod iki farklı şey yapabilir ve bunu kodun olduğu kadar genel bir dilde yapması çok daha kolaydır <+<. Bu gibi olasılıklara karşı dikkatli olun. Aslında, zaman zaman, iyi yazılmış bir program olarak görünse bile, tamamen silinebilecek küçük bölümlerin olduğunu, hiçbir şey eklenmediğini ve olayın hala kusursuz bir şekilde çalışacağını fark edebilirsiniz.

  • Çoğu dilde, programınızın davranışını kontrol etmek için sık sık bir derleyici veya tercüman kullanırsınız. Brainfuck dili daha fazla kavramsal kontrol gerektiriyor; Eğer programınızın ne yaptığını söylemek için bir derleyiciye ihtiyacınız varsa, programınızı yeterince kavrayamazsınız ve muhtemelen biraz daha yakından bakmanız gerekir - en azından yeterince net bir görüntü elde etmek istiyorsanız benzer programların kavramsal halo golf iyi olması. Uygulamada, birini çalıştırmayı denemeden önce programınızın bir düzine sürümünü üreteceksiniz ve bu noktada en kısa sürenin doğru şekilde çalışacağından% 95 emin olacaksınız.

  • İyi şanslar! Çok az insan Brainfuck'ı kesin olarak yazmakta zorlanıyor, ancak bence dilin sürekli dikkatini haklı çıkarmanın tek yolu bu - şaşırtıcı derecede karanlık bir sanat formu.


3
Bunu okumak beni şimdi Brainfuck'ta programlamayı denemek istememi sağlıyor ..
Claudiu

Kahretsin, adını tanıdığımı sanıyordum. Brainfuck programlarınızın büyük hayranı, özellikle süper kısa tercümanınız!
Jo King,

“zaman zaman, tamamen silinebilecek küçük parçaların olduğunu, hiçbir şeyin eklenmediğini ve olayın hala kusursuz bir şekilde çalışacağını fark edebilirsiniz.” Bu, özellikle yeni başlayanlar için çok doğru. BF'de hatırlayabildiğim kadarıyla sadece bir cevap yazdım, ancak gözden geçirme geçmişinde programla oynadığım ve rastgele gittiğim en az 3 örnek var. " "
ETHProductions


9

Burada birkaç ipucu:

Sabitler:

Esolangs' sabitleri sayfa özgü değerleri oluşturmak için en kısa yollardan son derece yararlı bir listesi vardır. Kendimi bu sayfa için program başına en az iki kez danışmanlık yaparken buluyorum.

Her şeyin başlangıcı:

+++[[<+>>++<-]>]

Bu, kaseti 3 * n ^ 2 biçiminde ayarlar;

3 6 12 24 48 96 192 128 0 0 '

Bu neden bu kadar önemli?

Hadi listeden aşağıya gidelim:

  • 3 ve 6 sıkıcı
  • 12: 10'a (yeni satır) veya 13'e (satır başı) yakın. 0-9 için sayaç için de kullanılabilir
  • 24: 26'ya yakın, alfabedeki harf sayısı
  • 48: için ASCII 0
  • 96: 97'ye yakın, ASCII. a
  • 196 ve 128: 196-128 = 64, 65'e yakın, ASCII A.

Bu bir algoritmadan ASCII serisindeki pratik olarak her dizinin başındayız, her biri için bir sayaç ve kolay ulaşılabilecek bir yeni satır.

Pratik bir örnek:

Tüm büyük ve küçük harf ve rakamların yazdırılması.

Algoritması ile:

+++[[<+>>++<-]>]<<[-<->]<<<<++[->>+.>+.<<<]<--[>>.+<<-]

olmadan:

+++++++++++++[->+++++++>++>+++++>++++>+<<<<<]>+++++>[-<+.>>.+<]>>---->---[-<.+>]

İkinci örnekte kaseti başlatmak için baytların çoğunu harcıyoruz . Bunlardan bazıları ilk örnekteki ekstra hareketlerle dengelenmiştir, ancak bu yöntemin açıkça avantajı vardır.

Aynı damardaki birkaç ilginç algoritma:

3 * 2 ^ n + 1:

+++[[<+>>++<-]+>]
Tape: 4 7 13 25 49 65 197 129 1 0'

Bu, değerleri bir kaç şeyi gerçekleştiren 1'e kadar dengeler. 12'ye bir satır başı, 64 tanesi büyük harfli alfabenin gerçek başlangıcı ve 24 tanesi 26'ya yaklaşıyor.

2 ^ N:

+[[<+>>++<-]>]
Tape: 1 2 4 8 16 32 64 128

64 büyük harfler için iyi, 32, alan için ASCII ve 128 26 için sayaç olarak kullanılabilir (130/5 = 26). Bu, sayılar ve küçük harflerin gerekli olmadığı bazı durumlarda baytları kurtarabilir.

Soruya uyan uygulamayı seçin:

  • Negatif hücreler neredeyse her zaman faydalıdır ve bunlardan kaçınmak için hiçbir neden yoktur (bytecount'unuzu değiştirmezseniz).
  • Sarma hücreleriyle hemen hemen aynı şey, hatta daha fazlası, çünkü çoğu sabit sargı kullanır.
  • Rasgele hücre boyutları, Fibonacci dizisini sonsuz olarak ( +[[-<+>>+>+<<]>]) hesaplamak veya daha büyük / negatif sayıları işlemek gibi sonsuz matematik dizileri için kullanışlıdır . Olumsuz gibi bazı yaygın yöntemler, yani [-]ve [->+<]sayı negatifse, her ihtimale güvenerek edilemez.
  • 0, -1 olarak EOF veya değişiklik yok. Ekstra kontroller olmadan tüm giriş boyunca dolaşabileceğiniz için 0 genellikle tercih edilir. Dizi yapıları üzerinde döngü yaparken -1 yararlıdır. Henüz bir değişiklik yapmanın bir yolunu bulamadım :(.

Frick'in neler olup bittiğini takip et:

Her zaman işaretçinin, etrafındaki verilerle ilişkili olması gerektiği konusunda yorumlarda bulunmalı ve her hücrenin olası değerlerinin aralığını bildiğinizden emin olmalısınız. Bu özellikle sonradan tekrar biraraya iki ihtimal katılmak isteyeceksiniz çünkü bir döngü önce işaretçi ayrılmışlar zaman önemli.

Herhangi bir noktada, kodum bunun gibi görünen diğer tüm satırlarda yorumlarla doludur:

*0 *dat a_1 ?  0' !0 0*
 or
*0 *dat 0' ap1 0  !0 0*

Bazı ekstra tavsiyeler, sembollere özel anlamlar atamaktır. Yukarıdaki örnekte, 'işaretçinin olduğu yerde, *bu yönde tekrarlama ?anlamına gelir, bilinmeyen değeri olan bir hücre !0anlamına gelir , sıfır olmayan bir hücre anlamına gelir _, bunun yerine geçer -ve pyerine geçer +. orTeybin her iki gösterime de benzeyebileceğini ve bunun gibi ele alınması gerektiğini ima eder.

Simge planınız mutlaka benimkiyle aynı olmak zorunda değildir (birkaç kusurludur), sadece tutarlı olmalıdır. Bu hata ayıklama sırasında da son derece kullanışlıdır, çünkü bu noktaya kadar çalıştırabilir ve gerçek bandı, olması gereken ile karşılaştırabilirsiniz; bu, kodunuzdaki olası kusurları gösterebilir.


5

Asıl tavsiyem olmaz .

Tamam, tamam, bundan daha kullanışlı bir şey istiyorsun. BF zaten çok özlü bir dildir, ancak sizi asıl öldüren şey, etkili bir şekilde bir arada yapılması gereken aritmetiktir. Büyük sayıları tam olarak nasıl yazacağınızı seçmek ve mümkün olan her yerde sarmayı kullanmak için Esolang'daki sabitler sayfasından okumaya değer .

Hafıza erişimi de çok pahalıdır. Bir kasetten okuduğunuzdan, herhangi bir zamanda kafanızın nerede hareket ettiğini aklınızda tutmanız gerekir. Sadece yazma diğer dillere aksine a, b, c, bf içinde size ne depolamak nereye dikkatli olmalı böylece açıkça, bayt bazı sayı sağa veya sola kafasını taşımak zorunda. Hafızanızı en iyi şekilde organize etmenin NP-zor olduğundan eminim, bu konuda iyi şanslar.


5

Bu cevabı birçok kez kasetteki belirli bir hücreye havale edeceğim. Hangi hücre olduğu önemli değil, ama tüm cevap boyunca aynı hücre. Bu yazının amaçları doğrultusunda, bu hücreye "Todd" diyeceğim.

Bir hücreyi sabit bir değere ayarlamaya çalışırken, bazen hemen bitirmemesi gerekir. Örneğin, Todd’un 30’u içermesini istediğinizi söyleyin. Daha sonra kodunuzda (bu, Todd’un değerini değiştirebilir, ancak asla okumaz), Todd’a geri dönersiniz. Todd'un değeri 0 ise, programdan çıkar. Aksi takdirde, Todd'un değeri sonsuza kadar yazdırılır.

Esolangs.org sayfasına göre beyin fırtınası sabitleri (muhtemelen kendi başına bir bahşiş konusu olabilir!) 30 elde etmenin en kısa yoludur >+[--[<]>>+<-]>+. Bu kılavuz >sadece işaretçinin solundaki hiçbir şeyin değiştirilmediğinden emin olmak için vardır, ancak bu durumda bunu umursamadığımızı ve bırakacağımızı varsayacağız. Bu kodu kullanarak kodunuz şuna benzer:

+[--[<]>>+<-]>+(MISC. CODE)(GO TO TODD)[.]

Bunun gibi ilk kod öbeğini düşünebilirsiniz:

(SET TODD TO 30)(MISC. CODE)(GO TO TODD)[.]

Ama bu öbekte son iki karakter hatırlayın: >+. Bu şekilde düşünmek de aynı şekilde geçerli:

(SET TODD TO 29)(GO TO TODD)(ADD 1 TO TODD)(MISC. CODE)(GO TO TODD)[.]

Dikkat et (GO TO TODD)iki kere! Bunun yerine kodunuzu şu şekilde yazabilirsiniz:

(SET TODD TO 29)(MISC. CODE)(GO TO TODD)(ADD 1 TO TODD)[.]
+[--[<]>>+<-](MISC. CODE)(GO TO TODD)+[.]

Bayt sayısının (GO TO TODD)daha önce aynı olduğunu varsayarsak , bir daha az hareket == bir daha az bayt! Bazen başlangıç ​​pozisyonunuzun değişmiş olması bu kazancı ortadan kaldırır, ancak her zaman değil.


0

Girdi olmayan zorluklar için küçük bir ipucu. Sen kullanabilirsiniz ,yerine [-](TIO.run biri dahil) tercüman çoğu EOF gösterimi sıfır olmasının hücre içeriğini belirleyecektir gibi, hızla hücreyi temizleyin gerekirse,. Bu, programları küçük bir noktaya değmez hale getirir, ancak yine de kod golf ile ilgilenen var mı?

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.