Hexagony kaynak kodunun açılması


52

Giriş

Hexagony'e aşina değilseniz , Martin Büttner tarafından oluşturulan ezoterik bir dildir. Mesele şu ki bu dil program için çok sayıda form kabul ediyor. Aşağıdaki programların hepsi eşdeğerdir:

abcdefg

ve

 a b
c d e
 f g

Bu yüzden, temel olarak, kod düzenli bir altıgene çevrildi. Ancak, koda yeni bir komut eklenmesinin abcdefghaşağıdaki programla sonuçlanacağına dikkat edin:

  a b c
 d e f g
h . . . .
 . . . .
  . . .

Gördüğünüz gibi, ilk adım kodu bir altıgene çeviriyor ve bundan sonra altıgen no-ops ( .) ile bir sonraki ortalanmış altıgen numaraya dolduruluyor .

Göreviniz basit, bir dize (kaynak kodu) verildiğinde, tam altıgen kaynak kodunun çıktısını almak.

Kurallar

  • Bir program veya işlev sunabilirsiniz.
  • Önde gelen boşluklara izin verilir, ancak yalnızca altıgen biçimini alamadığında
  • İzleyen boşlukta izin var.
  • Programdaki boşlukların dikkate alınmadığını unutmayın . Yani a b ceşittirabc
  • Yalnızca yazdırılabilir ASCII karakterleri ( 32 - 126) kullanılır, bu nedenle yalnızca normal Spacekarakter yoksayılır.
  • Dize uzunluğunun 0'dan büyük olduğunu varsayalım.
  • Bu , bu yüzden en az sayıda bayt olan gönderim kazanıyor!

Test durumları

Input: ?({{&2'2':{):!/)'*/

Output:
  ? ( {
 { & 2 '
2 ' : { )
 : ! / )
  ' * /


Input: H;e;l;d;*;r;o;Wl;;o;*433;@.>;23<\4;*/

Output:
   H ; e ;
  l ; d ; *
 ; r ; o ; W
l ; ; o ; * 4
 3 3 ; @ . >
  ; 2 3 < \
   4 ; * /


Input: .?'.) .@@/'/ .!.>   +=(<.!)}    (  $>( <%

Output:
   . ? ' .
  ) . @ @ /
 ' / . ! . >
+ = ( < . ! )
 } ( $ > ( <
  % . . . .
   . . . .

6
Ayrıca, o kadar seçici olmak isteyip istemediğinizden emin değilim, ancak kod genişliğini belirleme sürecinde geri tepmeler yok sayılır, çünkü bir sonraki karakteri eklerler. Öyleyse abc`defgaslında pastebin.com/ZrdJmHiR
Martin Ender 20

2
@ MartinBüttner Oh, bunu bilmiyordum :). Bu zorluk için, geri tepmeler göz ardı edilmeyecek.
Adnan,

18
Bu soru için Hexagony'de bir cevap görmek istiyorum.
Arcturus

2
@Adnan Muhtemelen daha iyi bir cevap "Girişin hata ayıklama bayrakları ( `karakterler) içermediğini varsayabilirsiniz ."
Riking

4
@Ampora Ask ve alacaksınız.
Martin Ender

Yanıtlar:


13

Pyth, 57 54 50 49 48 46

V+UJfgh*6sUTlK-zd1_UtJ+*d-JNjd:.[K\.^TJZ=+Z+JN

Test odası

Her satıra bir satır aralığı yazdırır.

Bu sürüm, tüm n> = 1 için 10 ^ n> = 3n (n - 1) + 1 olduğuna dair bir kanıt gerektirir . ANERDİ ve ErickWong'a kanıt sağladıkları için teşekkürler .

Bu eşitsizliklerin ardından: 10 ^ n> (1 + 3) ^ n = 1 + 3n + 9n (n - 1) + ...> 3n (n - 1) + 1 biri n> ' nin doğru olduğunu kolayca görebilir = 2 . N = 1 vakasını incelemek oldukça önemsizdir, 10> 1 verir .

Alternatif olarak, bu denklemlerin türevlerinin iki kez alınması, 10 ^ n'nin tüm n> = 1 için daha büyük bir ikinci türevine sahip olduğunu gösterir; bu daha sonra ilk türevlere ve son olarak da orijinal denklemlere indirgenebilir.

açıklama

              ##  Implicit: z=input(); Z=0
Jf...1        ##  Save to J the side length of the hexagon the code fills up
              ##  by finding the first number such that:
gh*6sUT       ##  the the T'th hexagonal number is greater than...
              ##  Computes 6 * T'th triangular number (by using sum 1..T-1) + 1
    lK-zd     ##  ...the length of the code without spaces (also save the string value to K)
V+UJ_UtJ      ##  For loop over N = [0, 1, ..., J-1, ..., 0]:
+*d-JN        ##  append J - N spaces to the front of the line
jd            ##  riffle the result of the next operation with spaces
:.[K\.yJ      ##  slice the string given by K padded to be the length of the Jth hexagon
              ##  number with noops
Z=+Z+JN       ##  from Z to Z + J + N, then set Z to be Z + J + N

2
Öncelikle, n> = 1 için ln (10) * 10 ^ n> 6n-3 (türevleri) olduğunu kanıtlamanız gerekir. Bu kolay, çünkü bu ifadelerin türevleri ln (10) ^ 2 10 ^ n ve 6 dır. n> = 1. 10 ^ n ve 3n (n-1) +1 için provayı tamamlamak için aynı mantığı kullanabilirsiniz.
Arcturus,

@Ampora Teşekkürler, türevleri kullanmayı düşünmüştüm ama belirsiz görünüyordu. Daha iyi bir yol bulamadım, çok takdir ediyorum!
FryAmTheEggman

Yardım etmekten memnun oldum. Calc bazen çok çirkinleşebilir.
Arcturus

yukarıdaki pyth.herokuapp.com/?code=etc bağlantısında derleyicinin çalışmadığını
görüyorum

1
@FryAmTheEggman Çok daha güçlü bağlı 4 ^ n> 3n (n-1) + 1'i n> = 1 için göstermenin çok kolay bir yolu var, matematik gerekli değil. Sadece (1 + 3) ^ n = 1 + 3n + 9n (n-1) / 2 + ... değerlerini binom genleşmesiyle kullanın. Birinci ve üçüncü terimler doğrudan 1 + 3n (n-1) değerindedir, bu yüzden üçüncü terim varsa (n> = 2 için) eşitsizlik hemen gerçekleşir. Bu, yalnızca RHS'nin 1 olduğu için önemsiz olan n = 1 vakasını bırakır.
Erick Wong

90

Altıgen , 271 bayt

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:

görüntü tanımını buraya girin

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):

görüntü tanımını buraya girin
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ı:

görüntü tanımını buraya girin

Böylece, bellek işaretçisi kuzey işaretli kenarda etiketli giriş üzerinde başlar . ,STDIN'den bir bayt veya EOF'ye -1bu 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 =}:

görüntü tanımını buraya girin

(Ö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:

görüntü tanımını buraya girin

Ş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):

görüntü tanımını buraya girin

%Okuduğumuz son karakteridir, 29okuduğ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:

görüntü tanımını buraya girin

Ö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. }}}32Kenar 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:

görüntü tanımını buraya girin

Ş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:

görüntü tanımını buraya girin

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:

görüntü tanımını buraya girin

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:

görüntü tanımını buraya girin

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:

görüntü tanımını buraya girin

Mor yol bunu içerir:

=M8;~'"=

=Yine MP yönünü tersine çevirir. M8oluşturduğunun onun değerini ayarlar 778(karakter kodu çünkü Molduğunu 77ve 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ı .


19
Kendimi bu altıgen cevaplarda çok söylerken buluyorum:
Conor O'Brien,

5
Huh ... ama .. wat ... zihin = üflenir
Adnan

Birisinin bunu yapmasını umuyordum ve ... Vay. Söyleyecek söz bulamıyorum. Bu harika.
Arcturus

19
İkinci adım - diğer% 97 değerini yazın. :)
ASCIIThenANSI

Üçüncü adım - en az baytlı cevap olarak.
Tom M

19

CJam, 56 52 50 48 bayt

İlk düşüncem, "hey, bunun için zaten kodum var!" Fakat daha sonra gerekli parçaları Ruby kodundan bir araya getirmek için canımı sıkmadı, çünkü özellikle golf oynamak için çok uygun görünmüyorlardı. Bu yüzden CJam'da başka bir şey denedim ...

lS-{_,4*(3/mq:D1%}{'.+}wD{D(2/-z_S*D@-@/(S*N@s}/

Burada test et.

açıklama

Önce ortalanmış altıgen sayılarla ilgili bir miktar matematik. Düzenli altıgen kenar uzunluğuna sahipse, kaynak kod uzunluğuna eşit olması gereken hücreleri Niçerecektir . Bunu çözebiliriz çünkü basit bir ikinci dereceden denklemdir:3N(N-1)+1kN

N = 1/2 ± √(1/4 + (k-1)/3)

Negatif kökü görmezden gelebiliriz, çünkü bu negatif bir N verir. Bunun bir çözümü olması için karekökün yarı-tam sayı olması gerekir. Başka bir deyişle, √(1 + 4(k-1)/3) = √((4k-1)/3)bir tamsayı olması gerekir (Neyse ki, bu tamsayı D = 2N-1, yine de ihtiyacımız olan altıgenin çapı olur ). Böylece, .bu koşul sağlanana kadar art arda bir tane ekleyebiliriz .

Gerisi altıgen düzenleyen basit bir halkadır. Bu bölüm için yararlı bir gözlem, girintideki boşlukların yanı sıra her satırdaki koddaki boşlukların çapa eklenmesidir.

lS-     e# Read input and remove spaces.
{       e# While the first block yields something truthy, evaluate the second...
  _,    e#   Duplicate the code and get its length k.
  4*(   e#   Compute 4k-1.
  3/    e#   Divide by 3.
  mq    e#   Take the square root.
  :D    e#   Store this in D, just in case we're done, because when we are, this happens
        e#   to be the diameter of the hexagon.
  1%    e#   Take modulo 1. This is 0 for integers, and non-zero for non-integers.
}{      e# ...
  '.+   e#   Append a no-op to the source code.
}w
D{      e# For every i from 0 to D-1...
  D(2/  e#   Compute (D-1)/2 = N, the side length.
  -z    e#   Subtract that from the current i and get its modulus. That's the size of the
        e#   indentation on this line.
  _S*   e#   Duplicate and get a string with that many spaces.
  D@-   e#   Subtract the other copy from D to get the number of characters of code
        e#   in the current line.
  @/    e#   Pull up the source code and split into chunks of this size.
  (S*   e#   Pull off the first chunk and riffle it with spaces.
  N     e#   Push a linefeed character.
  @s    e#   Pull up the remaining chunks and join them back into a single string.
}/

Sonuçta çift aritmetik kullanmamız gerekmiyor (karekök hariç). 4 ile çarpma nedeniyle, 3'e bölünürken çarpışma olmaz kve ilk olarak bir tamsayı karekök veren ilk istenen olacaktır.


8

Perl, 203 200 198

için + 1 içerir -p

s/\s//g;{($l=y///c)>($h=1+3*++$n*($n-1))&&redo}$s=$_.'.'x($h-$l);for($a=$n;$a<($d=2*$n-1);$a++){$s=~s/.{$a}/$&\n/,$s=reverse($s)for 0..1}$_=join$/,map{(' 'x abs($n-$i++-1)).$_}$s=~/\S+/g;s/\S/ $&/g

olarak çalıştırmak: echo abc | perl -p file.pl

Çok saf bir yaklaşım:

#!/usr/bin/perl -p

s/\s//g;                            # ignore spaces and EOL etc.
{                                   # find the smallest hex number:
    ($l=y///c)                      # calc string length
    > ($h=1+3*++$n*($n-1))          # 
    && redo                         # (should use 'and', but..)
}

$s = $_                             # save $_ as it is used in the nested for
   . '.' x ($h-$l);                 # append dots to fill hexagon

for ( $a = $n; $a < ($d=2*$n-1); $a++ )
{
        $s=~s/.{$a}/$&\n/,          # split lines
        $s=reverse($s)              # mirror
    for 0..1                        # twice
}

$_ = join$/,                        # join using newline
map {                               # iterate the lines
    (' 'x abs($n-$i++-1)) .$_       # prepend padding
} $s=~/\S+/g;                       # match lines

s/\S/ $&/g                          # prepend spaces to characters
                                    # -p takes care of printing $_

  • güncelleme 200 bir bayt hareketli değişken atama kaydetme ve bir başka 2 final atlayarak ;; Şimdi 200 baytın altında kendini kodla!
  • güncelleme 198 kullanarak $s=~/\S+/gyerine 2 bayt kaydetsplit/\n/,$s

7

JavaScript (ES6), 162 172

Anonim işlev

Altıgen boyutunun wikipedia denklemini çözdüğü bulundu

3*n*(n-1)-1 = l

Çözme formülü temel olarak

n = ceil(3+sqrt(12*l-3))/6)

Bazı cebir ve bazı yaklaşımlarla (ayrıca @ @ user18655 için thx) olur

n = trunc(sqrt(l/3-1/12)+1.4999....)
s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

Daha okunabilir

s=>{
  s=s.match(/\S/g);
  m=n=Math.sqrt(s.length/3-1/12)+1.49999;
  p=o='';
  for(i=n+n; --i; i>n?++m:--m)
    for(o += '\n'+' '.repeat(n+n-m), j=m; j--; o += ' ')
      o+=s[p++]||'.';
  return o
}

Test snippet'i (daha iyi tam sayfa - çalışma süresi ~ 1 dakika)

f=s=>eval("s=s.match(/\\S/g);m=n=Math.sqrt(s.length/3-1/12)+1.49999|0;p=o=``;for(i=n+n;--i;i>n?++m:--m)for(o+=`\n`+` `.repeat(n+n-m),j=m;j--;o+=` `)o+=s[p++]||`.`")

t=0;
r='0';
(T=_=>t++<816?(O.innerHTML=f(r=t%10+r),setTimeout(T,20)):0)()
pre { font-size: 66% }
<pre id=O></pre>


1
2 bayt kaydetmek n=...+1-1e-9|0yerine kullanabilirsiniz n=Math.ceil(...). Ayrıca ES7'ye gidip **0.5yerine kullanabilirsiniz , Math.sqrtancak bu size kalmış. Genellikle ES6 cevaplarımı saklıyorum çünkü tarayıcımda çalışıyorlar haha!
user81655

@ user81655 iyi ipucu, teşekkürler
edc65

5

Pyth, 52 51 bayt

Jfgh**3TtTl=H-zd1=+H*\.*lHTV+UJt_UJAcH]+JN+*-JNdjdG

Çevrimiçi deneyin. Test odası.

Her hattın OP tarafından izin verildiği şekilde bir tane ekstra boş alan vardır.

açıklama

 f              1          |   find first number n for which
             -zd           |           remove spaces from input
           =H              |         put result in H
          l                |       length of input without spaces
  g                        |     is less than or equal to
   h**3TtT                 |       nth centered hexagonal number
J                          | put result (hexagon side length) in J
                           |
      *lHT                 |      ten times length of input without spaces
   *\.                     |   that amount of dots
=+H                        | append to H
                           |
  UJ                       |    numbers 0 up to side length - 1
 +  t_UJ                   |   add numbers side length - 2 down to 0
V                          | loop over result
            +JN            |       current loop number + side length
         cH]               |     split to two parts at that position
        A                  |   put parts to G and H
                 -JN       |       side length - current loop number - 1
                *   d      |     that many spaces
                     jdG   |     join code on the line (G) by spaces
               +           |   concatenate parts and print

5

Retina , 161 bayt

FryAmTheEggman'e 2 bayt kaydettiği için teşekkür ederiz.

Bu cevap rekabet edici değil. Retina bu zorluktan bu yana birkaç güncelleme gördü ve yeni özelliklerden bazılarını kullandığımdan eminim (kontrol etmeme rağmen).

Bayt sayısı, ISO 8859-1 kodlamasını varsayar. İlk satırda tek bir boşluk var. Çoğu unutmayın ·merkezi noktalar (0xb7) aslında.

 

^
$._$*·¶
^·¶
¶
((^·|\2·)*)·\1{5}·+
$2·
^·*
$.&$* ·$&$&$.&$* 
M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$
+m`^( *·+)· *¶(?=\1)
$& 
·
 ·
O$`(·)|\S
$1
·
.
G-2`

Çevrimiçi deneyin!

İyi...

açıklama

Önce sadece tek bir karakter kullanarak ( ·bu durumda) mizanpajı oluşturmak ve daha sonra ortaya çıkan mizanpajı giriş karakterleriyle doldurmak en kolay yol olarak görünüyor. Bunun ana nedenleri, tek bir karakter kullanmamın, girdiyi doğrudan yerleştirmenin pahalı dengeleme grupları gerektireceği geri referansları ve karakter tekrarını kullanmama izin vermesidir.

 

Her ne kadar çok görünmese de, bu ilk aşama girdilerden boşlukları kaldırır.

^
$._$*·¶

Girişin uzunluğunu (boşlukları çıkardıktan sonra) , Morta nokta içeren ek bir hat hazırlayarak başlıyoruz M.

^·¶
¶

Giriş tek bir karakterse, o merkez noktayı tekrar kaldırırız. Bu, bir sonraki aşamada ele alınmayan talihsiz bir özel durumdur.

((^·|\2·)*)·\1{5}·+
$2·

Bu gerekli yan uzunluğu Neksi 1 hesaplar . İşte nasıl çalışır: ortalanmış altıgen sayılar formdur 3*N*(N-1) + 1. Üçgen sayılar olduğundan N*(N-1)/2, altıgen sayılar altı sayının üçgen sayısının artı 1 olduğu anlamına gelir. Bu 1 + 2 + 3 + ... + N, bir regex içindeki üçgen sayıları (gerçekten sadece sadece ) eşleştirmek , ileriye dönük referanslarla oldukça kolaydır. (^·|\2·)*Maçlar elinden büyük üçgen sayısı. Güzel bir bonus olarak, $2bu üçgen sayının dizinini tutacaktır. 6 ile çarpmak için onu gruba çeker 1ve 5 kez daha eşleştiririz. En az iki tane daha olmadığından emin olun ·ile ·ve·+. Bu şekilde, bulunan üçgen sayının indeksi, ortalanmış altıgen sayıdan daha fazla bir karakter bulunana kadar artmaz.

Sonunda, bu maç bize gruptaki gerekli altıgenin yan uzunluğundan iki kat daha az verir, bu $2yüzden geri almak için bir orta nokta ile birlikte geri yazarız N-1.

^·*
$.&$* ·$&$&$.&$* 

Bu, N-1orta nokta dizimizi N-1boşluklara, 2N-1orta noktalara ve başka N-1alanlara dönüştürür. Bunun maksimum girintinin, ardından altıgenin çapının ve ardından girintinin tekrar olduğunu unutmayın.

M!&m`(?<=(?= *(·)+)^.*)(?<-1>.)+(?(1)!)|^.+$

Bu nahoş bir şekilde uzundur, fakat temel olarak bize sadece a) karakterleri uzun olan ve ilk satırdaki veya b) ikinci satırdaki örtüşen tüm eşleşmeleri verir 2N-1. Bu, önceki aşamadaki sonucu tam fakat tuhaf girintili altıgene genişletir. Örneğin 12345678alacağımız girdi için:

  ···
 ····
·····
···· 
···  
12345678

Bu yüzden önceki aşamada da boşluk eklememiz gerekti.

+m`^( *·+)· *¶(?=\1)
$& 

Bu, merkezden sonraki çizgilerin girintisini, öncekinden daha kısa olan herhangi bir çizgiyi (arkadaki boşlukları yok sayarak) art arda girerek düzeltir, böylece şunu elde ederiz:

  ···
 ····
·····
 ···· 
  ···  
12345678

Şimdi sadece bazı boşluklar ekleyelim.

·
 ·

Bu bize verir:

   · · ·
  · · · ·
 · · · · ·
  · · · · 
   · · ·  
12345678

Phew, bitti.

O$`(·)|\S
$1

Giriş dizesini orta noktalara doldurma zamanı. Bu bir sıralama aşaması yardımı ile yapılır. Tüm merkez noktaları ve her satırdaki karakterleri son satırda eşleştiriyoruz ve verilen değiştirme işleminin sonucuna göre sıralıyoruz. Bu değiştirme, son satırdaki karakterler ve ·orta noktalar için boştur , yani ne olur, merkez noktaların basitçe sona göre sıralanması (sıralama sabit olduğu için). Bu, giriş karakterlerini yerine taşır:

   1 2 3
  4 5 6 7
 8 · · · ·
  · · · · 
   · · ·  
········

Şimdi sadece iki şey kaldı:

·
.

Bu merkez noktalarını normal periyotlara dönüştürür.

G-2`

Ve bu son çizgiyi atar.


1

JavaScript (ES6), 144 bayt

(s,n=1,l=0,p=0,m=s.match(/\S/g))=>m[n]?f(s,n+6*++l,l):[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`

Nerede \nliteral satır karakteri temsil eder. Daha önce diğer birkaç cevaplarında kullandığım altıgen oluşturmak için bir teknik kullanır . ES7 için kare kökler özyinelemeli yaklaşımdan biraz daha kısa çalışır:

(s,p=0,m=s.match(/\S/g),l=(~-m.length/3)**.5+.5|0)=>[...Array(l+l+1)].map((_,i,a)=>a.map((_,j)=>j<l-i|j<i-l?``:m[p++]||`.`).join` `).join`\n`

1

Python 3 , 144 bayt

c=input().replace(' ','')
n=x=1
while x<len(c):x+=n*6;n+=1
c=c.ljust(x,'.')
while c:print(' '*(x-n)+' '.join(c[:n]));c=c[n:];n-=(len(c)<x/2)*2-1

Çevrimiçi deneyin!

Bu, farklı büyüklükteki altıgenler için oldukça değişken bir miktarda beyaz boşluk kullanır, ancak genel şekil hayatta kalır.

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.