ハリケーンマシューとライトニングボルト


27

チャレンジ

この挑戦と厄介なハリケーンマシューに触発され、私たちはいくつかの稲妻を動的に生成します。

n = 15:

   \
   /\
  /  \
 /   /
/\  /\
 /  \ \
/   / /\
   /\ \
  / /  \
 /\ \  /\
  /  \ \
 /\  /  
   \
    \
    /\

入力

正の整数nは、落雷の深さを決定します。

ルールと制約

  • /そして、\使用すべきです
  • 雷の方向を導く確率は次のとおりです。
    • 25%が2つのパスに分割
    • 25%パスが行き止まりに達する
    • 25%が残ります
    • 25%が適切
    • 以下に、重複および行き止まりに関するいくつかの例外があります。
  • コードは確定的であってはならず、毎回新しい稲妻がランダムに生成される必要があります
  • ボルトはオーバーラップしてはなりません。たとえば、現在のボルトの左側にすでにボルトがある場合、現在のボルトは終了または右に移動する必要がありますが、左または分割にはなりません(確率は適用され、この場合は50%になります) / 50%right)
  • 使用可能な別の分割パスが存在しない場合、パスは終了してはなりません。たとえば、パスが1つしかない場合は最初で、分割するまでパスは終了しません。 、(確率は33%分割/ 33%左/ 33%右になりますあなたの目標は底に到達することです
  • 空白を左側に追加できます(必要なのは高さ1のみです)
  • ただし、ボルトを生成するのはあなた次第です。下から上、左から右などに移動できます。上記のすべてのルールが満たされている限り、

もう一つの例

n = 10

 \
 /
 \
 /\
  /\
 / /
/\ \
 / /\
 \   \
 /

ハリケーンマシューはどうやらスプライトと呼ばれる赤いボルトを空に発射しているようです

安全にゴルフを楽しんでください! 安全な場所にいるときのみ責任を持ってゴルフをしてください!!


7
Stay safe and have fun golfing!また、EASが攻撃された場合、すべてを放棄し、命令に従うように指定することもできます。このような状況では、ゴルフコードは優先事項ではありません。
エリックアウトゴルファー

17
@EriktheGolferあなたは本当のゴルファーではありません。
ブルー

4
「中心にある経路が地上に到達する経路であるべきだ」とは、残りのランダム生成記述と一致するとは思わない。たとえば、元のボルトが2回分割され、中央の2本のボルトが終了することはランダムに可能です。示された確率を維持しながら、この可能性をどのようにオーバーライドできますか?
グレッグマーティン

また、(たとえば)最初の2つのステップが両方とも分割されている場合はどうなりますか?次に、中央の2本のボルトが互いに接触します。これは問題があるように見えますが、特殊なケースによって除外されていません。
グレッグマーティン

@GregMartin中央部分の良い点、元々はバランスのとれたボルトを生成することを望んでいましたが、今ではその制約がなくても約50%の深さのどこかで終わることを考えています15のうち、右または左のパスが着地する確率は1〜2%だけです。そのルールを削除します。また、2つのステップを分割する部分については、2つのパスが2つのパスを結合すること\/はありません。
ズカベルグ

回答:


6

Perl、92 90 89 84バイト

+1を含む -n

STDINの高さを指定:

perl -M5.010 bolt.pl <<< 15

bolt.pl

#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_

説明

開始点0のオフセットを呼び出すと(ポイントは文字ボックスの隅にあります)、次の行で左または右に移動する(または移動しない)ことができ、オフセット上のポイントで終わる可能性があります-1,1。次の行は-2,0,2可能な限りのオフセットなどを示します。それらはすべて2 ずつ異なります。ポイントの左下の文字を偶数、右下の文字を呼び出すと、各文字位置に偶数または奇数を割り当てることができます。偶数と奇数が交互に並ぶような行(実際には、プレーン全体がチェッカーボードパターンで並べられています)。偶数ポジションには/、奇数位置が持つことができます\

aの直前の文字/は奇数の位置にあるため、\またはのいずれかになる可能性があります\/が、禁止されているのでのみ可能です。同様に、aの後の文字はaで\ なければなりませ(行の境界が問題にならないように、行の左右に十分なスペースが埋め込まれていると仮定します)。そのため、稲妻は常にaの直下\または直下の次の行に続きます/。いずれの場合も、下のポイントは中央にあり、次の行はこれらの4つの展開のいずれかを等しい確率で持つことができます(最初の文字をor で、2番目の文字をorで個別に置き換えることもできます)。perlでは、次のような方法でこれを行うことができます。/\又は/\直接トップ2文字以下です。だから私は、単にいずれかを置き換えることができ、次の行を生成します\か、//\

s#\\ | /#("  "," \\","/ ","/\\")[rand 4]#eg

ただし、結果の行に\/(禁止された結合)が含まれている/\、まったく含まれていないか、またはまったく含まれていない場合(ボルトは死に、底に到達しない)、結果は無効です。その場合、行全体を破棄して、もう一度やり直します。有効な継続は常に存在し、頻繁に試行すると、十分な継続が見つかります(たとえば、1つのフローを除いてすべてが停止します)。これは、推奨されるオーバーラップ防止アルゴリズムとはわずかに異なる確率分布ですが、方向性バイアスがないため、実際にはこれが優れていると思います。有効性は、以下を使用してゴルフっぽい方法でテストできます。

m#\\|/#>m#\\/#

ここでの問題は、ランダムな置換が非常に多く、これらの\エスケープもすべてバイトを消費することです。だから私は、数字の文字列を使用して、私の行を構築し、して、適切な数字を変更することを決定した/\だけ印刷前に。基本的なランダム置換は

53|16*rand

これの一つ与え535561または63等しい確率を有します。それから私は解釈して5とし1、とし3\そしてとし6/。行の印刷について説明します。

say y|3615|\\/ |r

本格的なゴルフ大会では、代替の魔法の公式を体系的に検討し始めますが、これはかなり良いはずです(3バイト以内で最適)

プログラムの残りのコンポーネント:

1x$_.6

これ$_により、高さのスペースに続いてが初期化されます(次のマップを参照)/。これは、印刷される最初の行の上にある不可視の行であり、フィールドが十分に広いことを確認して、ボルトが左側のスペースを使い果たすことがないようにします

map{ ... ; say ...}(1x$_.6)x$_

この同じ初期文字列の高さを処理し、毎回新しい行を印刷します

$_=$;until$;=$_,...

現在の行をに保存します$;。交換は、リストア無効であることが判明した場合$_から$;

s/.6|3.?/53|16*rand/eg

実際の置換を行います。スペースである必要があるため、前/または後を確認\する必要はありません。スペースは1またはで表すことができるため、これは便利5です。文字列を左にパディングするのは、スペース\がまだ存在しない場合もあるため、その文字をオプションにする

/3|6/>/36/

新しい行が有効かどうかを確認します


+1きちんと!このオンラインテスター を含める必要がありますperl -M5.010 main.pl <<< 25、私はいくつかの素晴らしい出力を得ています!
ズカバーグ

それがどのように機能するかを少し説明する心?私はそれらを生成するのがとても楽しかったです。
ズカバーグ

残念ながら、スペースとダッシュもカウントするため、に3バイトを追加する必要があり-nます。同じルールがコマンドライン引数にも適用されます。「特別な呼び出し」、2番目の箇条書きを参照してください。文字カウントの違いとして、それらを含まない最短の同等の呼び出しとカウントします。
エリックアウトゴルファー16年

1
このプログラムは、使用してコマンドラインから罰金を動作するため@EriktheGolferいいえ、1はOKである-nEだけで1文字以上である-E。(あなたは、参照記事を参照してください。これはまたの必要性を取り除きます-M5.010)私は常にファイルとして私のコードを提示しているためより便利ですが、常に次のようなオプションを数えます:コマンドラインから実行できる場合、スペースとダッシュは数えません。それは場合にしなければならない(それが使用しているため、例えばファイルにあるdo$0)私がやるスペースやダッシュカウント
トンHospel

@TonHospelああ、私はあなたが使っ-Eたことを知りませんでした。もしそうなら、あなたは良いです。
エリックアウトゴルファー16年

0

JavaScript(ES6)、154バイト

f=(n,r=[],s=" ".repeat(n)+"/",t=s.replace(/ \/|\\ |\\$/g,_=>"  /  \\/\\".substr(Math.random()*8&6,2)))=>n?/^ +$|\\\//.test(t)?f(n,r,s):f(n-1,[...r,t],t):r
<input type="number" min=1 oninput=o.textContent=f(this.value).join`\n`><pre id=o>

@TonHospelの答えを見るまで実装に苦労しましたが、@ TonHospelの答えはポートに縮退しただけです。サンプル出力:

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