Hexagonyソースコードの展開


52

前書き

Hexagonyに詳しくない場合は、MartinBüttnerによって作成された難解な言語です。問題は、この言語がプログラムの複数のフォームを受け入れることです。次のプログラムはすべて同等です。

abcdefg

そして

 a b
c d e
 f g

したがって、基本的に、コードは通常の六角形にまとめられています。ただし、コードに新しいコマンドを追加するとabcdefgh、次のプログラムが作成されることに注意してください。

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

ご覧のとおり、最初のステップはコードを六角形にロールアップし、その後、六角形は.次の中央の六角形の番号に何もしない()で埋められます。

タスクは単純です。文字列(ソースコード)を指定すると、六角形のソースコード全体が出力されます。

ルール

  • プログラムまたは機能を提供できます。
  • 先頭の空白は許可されますが、六角形の形が崩れない場合のみ
  • 末尾の空白は許可されます。
  • プログラム内の空白は無視されることに注意してください。だから、a b cに等しいですabc
  • 印刷可能なASCII文字(32 - 126)のみが使用されるため、通常のSpace文字のみが無視されます。
  • 文字列の長さが0より大きいと仮定します。
  • これはであるため、バイト数が最小の提出が勝ちです!

テストケース

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
また、あなたがその好き嫌いになりたいかどうかはわかりませんが、バックティックは次の文字に注釈を付けるため、コード幅を決定するプロセスでは無視されます。だからabc`defg実際にpastebin.com/ZrdJmHiR
Martin Ender

2
@MartinBüttnerああ、私はそれを知りませんでした:)。このチャレンジでは、バックティックは無視されません。
アドナン

18
私は本当にこの質問に対する六角形の答えを見たいです。
アークトゥルス

2
@Adnanおそらく、より良い応答は、「入力にデバッグフラグ(`文字)が含まれていないと仮定できます」でしょう。
ライキング

4
@Ampora Askすると受け取ります。
マーティンエンダー

回答:


13

ピス、57 54 50 49 48 46

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

テストスイート

各行の先頭にスペースを印刷します。

このバージョンでは、すべてのn> = 1に対して10 ^ n> = 3n(n-1)+ 1の証明が必要です。証明を提供してくれたANerdIErickWongに感謝します。

これらの不等式以下:10 ^ N>(1 + 3)^ N = 1 + 3N + 9N(N - 1)+ ...> 3N(N - 1)+ 1つ容易このために正しいことを確認することができ、N> = 2n = 1のケースを調べるのはかなり簡単で、10> 1になります。

あるいは、これらの方程式の導関数を2回取ると、10 ^ nがすべてのn> = 1に対してより大きい2次導関数を持ち、それが1次導関数にカスケードされ、最後に元の方程式にカスケードされることが示されます。

説明

              ##  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
まず、n> = 1の場合、ln(10)* 10 ^ n> 6n-3(導関数)であることを証明する必要があります。これらの式の導関数はln(10)^ 2 10 ^ nおよび6であるため、これは簡単です。10^ nは単調に増加し、10 ^ 1> 6 * 1なので、10 ^ nはすべてに対して6n-3より大きいn> = 1。同じロジックを使用して、10 ^ nおよび3n(n-1)+1の証明を完了することができます。
アークトゥルス

@Amporaおかげで、デリバティブの使用を検討していましたが、それは汚れているように見えました。しかし、より良い方法を見つけることができなかったので、とても感謝しています!
FryAmTheEggman

喜んでお手伝いします。Calcは時々非常に見苦しくなります。
アークトゥルス

上記のリンクpyth.herokuapp.com/?code=etcで、コンパイラが実行されていないことがわかりました
...-RosLuP

1
@FryAmTheEggman n> = 1の場合、はるかに強い境界4 ^ n> 3n(n-1)+ 1を表示する非常に簡単な方法があり、計算は不要です。(1 + 3)^ n = 1 + 3n + 9n(n-1)/ 2 + ...という事実を二項展開によって使用します。第1項と第3項は1 + 3n(n-1)を直接メジャー化するため、第3項が存在する場合(つまり、n> = 2の場合)、不等式は即時になります。この葉のみRHSが1であることから自明である場合はn = 1
エリック・ウォン

90

六角形、271バイト

六角形の通訳の最初の3%を紹介します...

|./...\..._..>}{<$}=<;>'<..../;<_'\{*46\..8._~;/;{{;<..|M..'{.>{{=.<.).|.."~....._.>(=</.\=\'$/}{<}.\../>../..._>../_....@/{$|....>...</..~\.>,<$/'";{}({/>-'(<\=&\><${~-"~<$)<....'.>=&'*){=&')&}\'\'2"'23}}_}&<_3.>.'*)'-<>{=/{\*={(&)'){\$<....={\>}}}\&32'-<=._.)}=)+'_+'&<

オンラインでお試しください!自身で実行することもできますが、約5〜10秒かかります。

原則として、これはサイド長9(217以下のスコア)に収まるかもしれません。これはこれが201コマンドのみを使用し、最初に(サイド長30で)書いた非ゴルフバージョンが178コマンドしか必要としないためです。ただし、すべてを実際に適合させるには永遠にかかると確信しているので、実際に試してみるかどうかはわかりません。

最後の1行または2行の使用を避けることで、サイズ10でこれを少しゴルフすることも可能です。これにより、後続のノーオペレーションを省略できますが、最初のパスの1つとして大幅な書き換えが必要になります。結合は左下隅を利用します。

説明

コードを展開し、制御フローパスに注釈を付けることから始めましょう。

ここに画像の説明を入力してください

それはまだかなり厄介ですので、ここに私が最初に書いた「改変されていない」コードの同じ図があります(実際、これはサイドレングス20であり、もともとサイドレングス30でコードを書きましたが、それはあまりにもまばらでした可読性はまったく向上しないので、サイズを少し合理化するために少し圧縮しました):

ここに画像の説明を入力してください
クリックして拡大版をご覧ください。

いくつかの非常に小さな詳細を除き、色はまったく同じですが、非制御フローコマンドもまったく同じです。それで、私はこれが非ゴルフバージョンに基づいてどのように機能するかを説明します、そしてあなたが本当にゴルフされたものがどのように動作するか知りたいなら、あなたは大きな六角形のどの部分に対応する部分を確認できます。(唯一の落とし穴は、実際のコードが左に行く右隅から始まるように、ゴルフのコードが鏡で始まることです。)

基本的なアルゴリズムは、私のCJamの回答とほぼ同じです。2つの違いがあります。

  • 中心化された六角形の方程式を解く代わりに、入力の長さ以上になるまで連続した中心化された六角形の数を計算します。これは、Hexagonyには平方根を計算する簡単な方法がないためです。
  • 入力に何も入力せずにすぐにパディングする代わりに、入力のコマンドがすでに使い果たされているかどうかを後で確認し、ある場合は.代わりにaを出力します。

つまり、基本的な考え方は次のように要約されます。

  • 入力文字列の長さを計算しながら読み取り、保存します。
  • 入力全体を保持できる最小の辺の長さN(および対応する中央の六角形の数値hex(N))を見つけます。
  • 直径を計算し2N-1ます。
  • 行ごとに、インデントとセル数(合計2N-1)を計算します。インデントを印刷し、セルを印刷します(.入力がすでに使い果たされている場合に使用)、改行を印刷します。

何もしないので、実際のコードは左隅から始まります($を飛び越える>ので、実際,には暗い灰色のパスから始まります)。

初期メモリグリッドは次のとおりです。

ここに画像の説明を入力してください

そのため、メモリポインターはinputというラベルが付いたエッジから始まり、北を指します。,STDINからバイトを読み取るか、-1そのエッジにEOFがヒットした場合。したがって、<直後はすべての入力を読んだかどうかの条件です。とりあえず入力ループのままにしておきましょう。次に実行するコードは

{&32'-

これは、スペースとラベル付けされたエッジに32を書き込み、それからdiffとラベル付けされたエッジの入力値からそれを減算します。入力には印刷可能なASCIIのみが含まれることが保証されているため、これが負になることはありません。入力がスペースの場合、ゼロになります。(Timwiが指摘しているように、入力に改行またはタブが含まれる場合でもこれは機能しますが、32未満の文字コードを持つ他のすべての印刷不能文字も削除します。)その場合、<命令ポインター(IP)そして明るい灰色のパスが取られます。そのパスは単にMPの位置をリセットし{=、次の文字を読み取ります。したがって、スペースはスキップされます。それ以外の場合、文字がスペースではない場合、実行します

=}}})&'+'+)=}

これはまず、diffエッジの反対側まで、長さエッジを六角形の周りに移動します。反対側からそれをコピー値の長さにエッジ辺、及び増分それと。なぜこれが理にかなっているのかはすぐにわかるでしょう。最後に、新しいエッジを移動します:=}}})&'+'+)=}

ここに画像の説明を入力してください

(特定のエッジ値は、チャレンジで指定された最後のテストケースのものです。)この時点で、ループが繰り返されますが、すべてが1つの六角形から北東にシフトされます。したがって、別の文字を読み取った後、次のようになります。

ここに画像の説明を入力してください

北東の対角線に沿って入力(マイナススペース)を徐々に書き込み、文字を1つおきのエッジに書き込み、その文字までの長さをlengthというラベルの付いたエッジと平行に保存していることがわかります。

入力ループを完了すると、メモリは次のようになります(次の部分のいくつかの新しいエッジにラベルを付けています)。

ここに画像の説明を入力してください

%私たちが読んで最後の文字である、29我々は読ん非空白文字の数です。次に、六角形の辺の長さを見つけたいと思います。まず、濃い緑/灰色のパスにいくつかの線形初期化コードがあります。

=&''3{

ここで=&、長さ(この例では29)をlengthというラベルの付いたエッジにコピーします。次に''33というラベルの付いたエッジに移動し、その値を設定します3(計算で定数として必要なだけです)。最後{に、N(N-1)というラベルの付いたエッジに移動します。

次に、青いループに入ります。このループはNNのラベルが付いたセルに格納されます)インクリメントしてから、中心の六角形の数値を計算し、入力長から減算します。それを行う線形コードは次のとおりです。

{)')&({=*'*)'-

ここで、Nに{)移動し、インクリメントします。N-1というラベルの付いたエッジに移動し、そこでコピーしてデクリメントします。N(N-1)の積を計算します。これに定数を乗算し、hex(N)というラベルの付いたエッジで結果をインクリメントします。予想どおり、これはN番目の中央六角形番号です。最後に、その長さと入力長の差を計算します。結果が正の場合、辺の長さはまだ十分に大きくなく、ループが繰り返されます(MPをN(N-1)とラベル付けされたエッジに戻します)。')&(N{=*'*)3'-}}

辺の長さが十分に大きくなると、差はゼロまたは負になり、次のようになります。

ここに画像の説明を入力してください

最初に、出力ループに必要な初期化を行う非常に長い線形の緑のパスがあります。

{=&}}}32'"2'=&'*){=&')&}}

まず{=&差分エッジの結果を長さエッジにコピーすることから始めます。これは、後で非正の値が必要になるためです。space}}}32というラベルの付いたエッジに32を書き込みますdiffの'"2上のラベルのないエッジに定数2を書き込みます。同じラベルで2番目のエッジにコピーします。これを2で乗算し、インクリメントして、上部の2N-1というラベルの付いたエッジで正しい値を取得します。これは六角形の直径です。2N-1というラベルの付いたもう一方の端に直径をコピーします。最後に、上部の2N-1というラベルの付いたエッジに戻ります。'=&N-1'*){=&')&}}

エッジにラベルを付け直しましょう:

ここに画像の説明を入力してください

現在のエッジ(六角形の直径を保持している)を使用して、出力のラインを反復処理します。indentというラベルの付いたエッジは、現在の行に必要なスペースの数を計算します。エッジのラベルが付いたセルは、現在の行のセルの数を反復処理するために使用されます。

indentを計算するピンクのパスになりました。反復子を('-デクリメントし、N-1から(インデントエッジに)減算します。コード内の短い青/灰色の分岐は、結果のモジュラスを計算するだけです(負またはゼロの場合は値を否定し、正の場合は何も起こりません)。ピンクのパスの残りの部分は、セルの端まで直径からインデントを差し引いてから、インデントの端に戻ります。~"-~{

汚れた黄色のパスがインデントを印刷するようになりました。ループの内容は本当にただ

'";{}(

どこ'"に移動スペースエッジは、;それを印刷し、{}移動しに戻りインデント及び(それをデクリメントします。

これが完了すると、(2番目の)濃い灰色のパスが印刷する次の文字を検索します。=}(上手段、位置に移動した細胞の縁、南を指します)。次に{}、保存された文字列の最後に到達するまで、南西の方向に2つのエッジを単純に下に移動する非常にタイトなループがあります。

ここに画像の説明を入力してください

EOFの 1つのエッジにラベルを付け直したことに注意してください。この文字を処理したら{}、次の反復ではなくここでループが終了するように、そのエッジを負にします。

ここに画像の説明を入力してください

コードでは、暗い灰色のパスの最後にあり'、入力文字に1ステップ戻ります。状況が最後の2つの図の1つである場合(つまり、まだ印刷していない入力から文字が残っている場合)、緑のパス(下の緑、緑が苦手な人、青)。これはかなり簡単です;。キャラクター自体を印刷します。'対応するスペースエッジに移動します。スペースエッジは、以前の32を保持し、;そのスペースを印刷します。次に{~EOFを作成しますか?次の反復で負の値を指定'すると、1つ前のステップに戻り、別のタイト}{ループで文字列の北西端に戻ることができます。長さで終わるセル(hex(N)の下の非正のセル。最後}セルの端に戻ります。

すでに入力を使い果たしている場合、EOFを検索するループは?実際にここで終了します:

ここに画像の説明を入力してください

その場合'長さのセルに移動し、代わりに水色(上部)のパスを使用します。このブランチのコードは線形です:

{*46;{{;{{=

{*46;標識されていないエッジに46を書き込む無OP及び印刷それ(すなわち、A期間)。次に{{;スペースの端に移動して印刷します。{{=移動するに戻りセル次の反復のためのエッジ。

この時点で、パスは結合し(直され、セルの端が減ります。イテレータがまだゼロでない場合、ライトグレーのパスを使用します。これは単にMPの方向を反転させ、=次に印刷する次の文字を探します。

そうでない場合、現在の行の終わりに到達し、IPは代わりに紫色のパスを取ります。これは、その時点でのメモリグリッドの外観です。

ここに画像の説明を入力してください

紫色のパスには次のものが含まれます。

=M8;~'"=

=再びMPの方向を反転させます。is の文字コードが現在の値に追加されるため、M8値をセットに設定します。これはたまたまなので、で印刷すると、改行が表示されます。次に、エッジを再びネガティブにし、ラインエッジに戻り、MPをもう一度反転します。778M7710 (mod 256);~'"=

今ならばラインのエッジがゼロである、我々は完了です。IPは(非常に短い)赤いパスを取り@、プログラムを終了します。そうでない場合は、ピンクのパスにループバックする紫色のパスに進み、別の行を印刷します。


TimwiのHexagonyColorerで作成された制御フロー図。Esoteric IDEのビジュアルデバッガで作成されたメモリダイアグラム。


19
私はこれを六面体の答えでたくさん言っています:ちょうどおっと。
コナーオブライエン

5
ええと…。ワット...心=吹き飛ばさ
アドナン

誰かがこれをすることを望みました...わあ。私は言葉がありません。すごい。
アークトゥルス

19
ステップ2-他の97%を記述します。:)
ASCIIThenANSI

ステップ3-最小バイトの答えとして。
トムM

19

CJam、56 52 50 48バイト

最初に考えたのは、「このコードはもう持ってるよ!」しかし、特にゴルフに適していないように思えたので、Rubyコードから必要な部分をまとめることに煩わされることはありませんでした。だから私は代わりにCJamで何か他のものを試しました...

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

ここでテストしてください。

説明

最初に中心の六角形の数についての少しの数学。正六角形の辺の長さがの場合、セルNが含まれます3N(N-1)+1。これはソースコードの長さと等しくなければなりませんkNこれは単純な2次方程式なので、解決できます。

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

負のNが得られるため、負の根を無視できます。これを解決するには、平方根が半整数である必要があります。または、言い換えれば、√(1 + 4(k-1)/3) = √((4k-1)/3)整数である必要があります(幸いなことに、この整数は偶然D = 2N-1六角形の直径であり、とにかく必要です)。そのため、.その条件が満たされるまで繰り返し単一を追加できます。

残りは六角形を配置する単純なループです。この部分の有用な観察は、インデント内のスペースと各行のコード内の非スペースの合計が直径になることです。

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.
}/

二重算術を使用する必要はまったくありません(平方根を除く)。4を乗算するため、3で除算しても衝突は発生せずk、整数平方根を生成する最初のものが必要になります。


8

Perl、203 200 198

+ 1を含む -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

として実行: echo abc | perl -p file.pl

非常に単純なアプローチ:

#!/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 $_

  • update 200はバイト移動変数の割り当てを保存し、別の2はfinalを省略して保存します;。今では200バイト以下でコードを作成しています!
  • 更新198の$s=~/\S+/g代わりに使用して2バイトを節約split/\n/,$s

7

JavaScript(ES6)、162 172

無名関数

六角形のサイズは、ウィキペディアの方程式を解決するために見つかりました

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

解く式は基本的に

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

代数と近似(@ user18655へのthx)を使用すると、

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++]||`.`")

より読みやすい

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
}

テストスニペット(ページ全体の改善-実行時間〜1分)

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
n=...+1-1e-9|0代わりにn=Math.ceil(...)を使用して2バイトを節約できます。ES7を使用して**0.5代わりに使用することもできますがMath.sqrt、それはあなた次第です。答えはES6のままにしておきます。なぜなら、それらは私のブラウザーで動作するからです!
user81655

@ user81655良いヒント、ありがとう
edc65

5

Pyth、52 51バイト

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

オンラインでお試しください。 テストスイート。

OPで許可されているように、各行には1つの余分な先行スペースがあります。

説明

 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

網膜、161バイト

2バイトを節約してくれたFryAmTheEggmanに感謝します。

この答えは非競合です。Retinaはこのチャレンジ以降、いくつかの更新を確認しており、新しい機能のいくつかを使用していると確信しています(チェックしていませんが)。

バイトカウントはISO 8859-1エンコードを前提としています。最初の行には単一のスペースが含まれています。ほとんど·が実際には中央のドット(0xB7)であることに注意してください。

 

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

オンラインでお試しください!

まあ...

説明

最初に単一の文字(·この場合)を使用してレイアウトを構築し、次に結果のレイアウトを入力文字で埋めるのが最も簡単なようです。これの主な理由は、単一の文字を使用すると、後方参照と文字の繰り返しを利用できるため、入力を直接レイアウトするには高価なバランシンググループが必要になるためです。

 

あまり見えませんが、この最初の段階では入力からスペースを削除します。

^
$._$*·¶

最初に、M中央のドットを含む追加の行を追加します。ここMで、入力の長さ(スペースを削除した後)です。

^·¶
¶

入力が単一の文字である場合、その中央のドットを再び削除します。これは、次の段階ではカバーされない不幸な特別なケースです。

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

これにより、必要な辺の長さNから1を引いた値が計算されます。これがどのように機能するかを以下に示し3*N*(N-1) + 1ます。三角形の数はN*(N-1)/2なので、六角形の数は三角形の数の6倍に1を加えたものであることを意味1 + 2 + 3 + ... + Nします。は(^·|\2·)*、可能な最大の三角形の数と一致します。素敵なボーナスとして、$2この三角番号のインデックスを保持します。6で乗算するには、グループにキャプチャし1、さらに5回一致させます。私たちは必ず、少なくとも2以上存在させる··し、·+。このようにして、見つかった三角形の番号のインデックスは、中心の六角形の番号よりも1文字多くなるまで増加しません。

最終的に、この一致により、グループ内の必要な六角形の辺の長さよりも2少ない長さが$2得られN-1ます。

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

これにより、N-1センタードットのストリングがN-1スペース、2N-1センタードット、および別のN-1スペースに変わります。これは最大インデントであり、次に六角形の直径、インデントが続くことに注意してください。

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

これは不愉快なほど長いですが、基本的には、a)長さが1行目の文字、またはb)2行目であるすべての重複する一致を提供し2N-1ます。これにより、前の段階の結果が完全な、しかし奇妙にインデントされた六角形に拡張されます。たとえば、12345678取得する入力:

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

これが、前の段階でもスペースを追加する必要があった理由です。

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

これは、前の行よりも短い行を繰り返しインデントすることで(末尾のスペースを無視して)中央以降の行のインデントを修正するため、次のようになります。

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

ここで、いくつかのスペースを挿入します

·
 ·

それは私たちに与えます:

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

できた。

O$`(·)|\S
$1

入力文字列を中央のドットに埋める時間。これは、ソート段階の助けを借りて行われます。すべての中央のドットと最後の行の各文字を照合し、指定された置換の結果で並べ替えます。この置換は、最後の行の文字と·中央のドットに対して空です。そのため、中央のドットは単純に最後までソートされます(ソートが安定しているため)。これにより、入力文字が所定の位置に移動します。

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

あと2つ残っています。

·
.

これにより、中央のドットが定期的に変わります。

G-2`

そして、これは最後の行を破棄します。


1

JavaScript(ES6)、144バイト

(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`

where \nは、リテラルの改行文字を表します。以前に他のいくつかの回答で使用した六角形を作成するための手法を使用します。ES7の場合、平方根を取ることは、再帰的アプローチよりもわずかに短くなります。

(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バイト

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

オンラインでお試しください!

これは、さまざまなサイズの六角形に対してかなり異なる量の先頭の空白を使用しますが、一般的な形状は残ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.