配管のランダムパス


23

width w、height h、およびstep countの3つの整数を受け取るプログラムまたは関数を作成しますs。あなたは、非自己交差描画されるランダムウォーク sに長いステップを5*wすることにより5*h、すべての5により画素セルが空にされるか(ピュアベージュ)、またはこれらの12の簡単な「パイプ」の1ピクセルの画像:

拡大パイプ

上の画像は詳細を示すために拡大されています。実際のサイズのパイプは次のとおりです。

パイプ

(灰色の線は、パイプタイプを区別するためのものです。)

ランダムウォークは、1つのパイプエンドポイント(下から4つのパイプタイプの1つ)で始まり、別のパイプエンドポイントで終わる単一の連続パイプパスになります。

空で開始wすることによりh、グリッドとランダム開始点であることを一つのセルを選択してください。次に、開始する4つの方向のいずれかをランダムに選択し、対応するパイプエンドポイントを描画します。この開始セルは、ウォークの最初のステップをマークし、新しいセルを描画するか、既存のセルを上書きするたびに、別のステップとしてカウントされます。

ここで、選択された方向が有効な場合、適切なパイプセルを描画して、繰り返しランダムに右、左、または直線に進むことを選択します。完全なsステップパスが形成されるまで方向が有効でない場合は、バックトラックして再選択します。パスは、パイプエンドポイントで終了する必要があります。パイプエンドポイントは、パスがたどった経路に応じて、グリッド上のどこかにある場合があります。

2つの直線パイプセルのみを上書きでき、反対方向の直線パイプセルによってのみ上書きできることに注意してください。結果は交差セルになります。それ以外の場合は、すべてのパイプを空のセルに配置する必要があります。

交差点が描画されるとき、開始セルからさらに遠いパスの部分が一番上に描画されます。

グリッドに周期的境界条件(PBC)があるかどうか、つまり、グリッドの片側から出るパイプが反対側に出るかどうかはあなた次第です。PBCがない場合、グリッドの境界は、他のパイプと同様に遭遇する可能性のある障壁としてカウントされます。

特殊なケース

  • s0の場合、パイプは描画されず、出力はイメージごとに空白5*wになり5*hます(つまり、すべてベージュ)。
  • 場合s1つの管スタブであります

    拡大パイプスタブ(実寸:パイプスタブ

    ランダムに選択された開始セルに描画する必要があります。

その他の詳細

  • あなたはそれsがせいぜいw*hパスであると仮定するかもしれません。(ただし、交差点により長いパスが可能です。)
  • wそしてh常にポジティブです。
  • すべてのランダムな選択は、一様にランダムでなければなりません。たとえば、問題が簡単になったとしても、可能であれば交差点を作成することを避けるべきではありません。疑似乱数ジェネレーターが許可されています。
  • 黒、青、ベージュの代わりに、視覚的に異なる3色を使用できます。
  • 彼らは実際にあるように、あなたの出力画像が拡大される5*w*kことにより、5*h*k画素のk正の整数です。(あなたkが1 歳であっても、投稿するサンプルを拡大することをお勧めします。)
  • 一般的なロスレス画像ファイル形式を使用でき、画像をファイルに保存したり、表示したり、生のまま標準出力に吐き出したりできます。

バイト単位の最短コードが優先されます。

(すべて500%拡大)。

入力がw=2, h=1, s=0その場合、出力は常に次のようになります。

入力がw=2, h=1, s=1その場合、出力はこれらの画像のいずれかであり、同じチャンスがあります。

入力がw=2, h=1, s=2次の場合、出力は

または多分

グリッドにPBCがあると想定されている場合。

(このようにパスを開始すると、2番目のステップが不可能になることに注意してください。)


w=3, h=2, s=6PBCを想定した、の可能な出力を次に示します。


w=3, h=3, s=9PBCを想定した場合の可能な出力は次のとおりです。

交差点が2つのステップとしてカウントされるため、パスがすべてのセルをカバーする必要がないことに注意してください。また、交差点の陸橋は後で描かれている必要があるため、コーナーの端点が開始セルであると推定できます。したがって、行われたランダムな選択のシーケンスを推測できます。

start at top left, facing east
go straight
go right
go right
go right
go straight
go left
go right
end

最後に、w=4, h=5, s=20との例を示しますw=4, h=5, s=16


1
全体のアイデアはランダムウォークです。
アカンカ

行2:You will be drawing a non-self-intersecting random walk...自己交差するかどうか?
edc65

@ChristianIrwanまあまあではありません。ランダムウォークは通常、自分自身を2倍に戻すか、まったく交差しません。交差点は作成されますが、同じ地面を遡るとはみなされないため、これはユニークなケースです。そして、はい、これはアスキーアート形式か何かでしたが、私は見栄えの良い画像を作るというアイデアが好きです。
カルビンの趣味

2
@ChristianIrwan私はすでに「これはアスキーアート形式か何かであるかもしれないが、見栄えの良い画像を作るというアイデアが好きだ」と言ったときに答えました。私はアスキーアートを使わないことにしました。
カルバンの趣味

1
「結び目」は許可されていますか?
-aditsu

回答:


4

CJam、274

q~:K;:B;:A;{0aA*aB*:M5*5f*:I;K{[Bmr:QAmr:P]5f*:R;3Ym*{R.+:)2{1$0=I=2$W=@tI@0=@t:I;}:F~}/R2f+1FK({MQ=P=:EY4mr:D#&1{{MQMQ=PE2D#+tt:M;}:G~7,1>[W0_1_0_W]2/D=:Off*{[QP]5f*2f+.+_:H1F_OW%.+2FOW%.m2F}/H2FO~P+:P;Q+:Q;MQ=P=:E_5YD2%-*=!JK2-=+*1{D2+4%:D;G}?}?}fJ]}0?}g'P2NA5*SI,N2NI:+N*

オンラインで試す

PBCを使用し、PGM形式で出力します。:+終わり近くを削除して、ブラウザーでより見やすい視覚的な出力を得ることができます。

特にステップカウントが領域に近い場合、入力が大きい場合は非常に遅くなります。

入力の結果の例4 3 10(500%にスケーリング):

例

簡単な説明:

一般的なアプローチは次のとおりです。

  • 成功するまで次のすべての手順を繰り返します。
  • 2つのマトリックスを初期化します:各セルでどちらの側が使用されているかを記録する1つと、画像用に1つ
  • s = 0の場合、完了です。それ以外の場合:
  • ランダムなセルを選択して正方形を描画し、次のs-1回実行します。
  • ランダムな方向を選択します。その側が既に使用されている場合、失敗して最初からやり直す
  • 側面を使用済みとしてマークし、画像に実際のパイプを描画します(現在のセルの中心ピクセルの「直後」から開始し、パイプの終わりを覆うためにドットを追加して、長さ6の隣接する線を3本描画します)
  • 現在の位置を更新する(次のセルに移動する)
  • セルが空であるか、有効な交差点であるかを確認してください。そうでない場合、失敗して最初からやり直す
  • このセルで使用されているように反対方向の側面をマークし、ループを続行します

1

QBasic、517 516バイト

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
1CLS
IF s=0GOTO 9
x=5*INT(RND*w)
y=5*INT(RND*h)
GOSUB 7
FOR k=1TO s-1
r=INT(RND*4)+1
a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)=0GOTO 1
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
9IF c GOTO 1
END
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
  • かかりwhおよびsユーザ入力から、カンマ区切り。
  • 出力は画面に描画されます。プログラムが解決策を探している間、過去の部分的な解決策がちらつくことがあります。
  • 周期的な境界条件を使用しません。パイプの半分がグリッドの片側に、もう半分がもう一方の側にあることを心配することなく、パイプを接続するための描画とテストが簡単であることがわかりました。

ここでのアプローチは、各ステップでランダムな方向を試行し、無効な移動が発生した場合は最初からやり直すことです。方向が決まるとパイプを描画し、POINT有効条件について画面上のポイントをテストするために使用します。グリッドの境界外に移動しない場合、移動は有効です:

  1. 移動先のセルは空です。または
  2. 両方
    1. 移動先のセルには、水平方向または垂直方向にまっすぐに伸びるパイプが含まれています。
    2. 新しいパイプセクションは、既存のパイプセクションを2倍にしません。

同様aditsuのCJam答え、このコードは非常に遅い、とあれば心numbingly遅くなることsの重要な部分ですw*h。QB64のセットアップでは、5,5,19かなり迅速に答えが出ますが、待つつもりだったよりも時間がかかります5,5,20

より大きく/より密集した例を実行したい場合、深さ優先検索を使用した私の元のアプローチを以下に示します。なんと300バイト余分にコストがかかりますが、はるかに効率的です。

RANDOMIZE TIMER
SCREEN 9
INPUT w,h,s
DIM t(s),m(s)
0
FOR z=1TO s
t(z)=-1
NEXT
i=5*INT(RND*w)
j=5*INT(RND*h)
k=1
1CLS
IF s=0GOTO 9
x=i
y=j
GOSUB 7
FOR z=1TO k-1
r=m(z)
GOSUB 6
x=a
y=b
GOSUB 7
o=1AND r
p=x-2+3*o-5*(r=2)
q=y+1-3*o-5*(r=1)
u=p+3-o
v=q+2+o
LINE(p,q)-(u,v),7,B
LINE(p+o,q+1-o)-(u-o,v-1+o),1
NEXT
IF c*(k=s)THEN k=k-1:GOTO 1 ELSE IF k=s GOTO 9
IF k<1GOTO 0
IF t(k)>=0GOTO 4
t(k)=0
f=30
WHILE f
r=INT(RND*4)+1
IF f AND 2^r THEN t(k)=t(k)*5+r:f=f-2^r
WEND
4r=t(k)MOD 5
m(k)=r
t(k)=t(k)\5
GOSUB 6
c=(POINT(a,b+2)*POINT(a+4,b+2)+POINT(a+2,b)*POINT(a+2,b+4))*(0=POINT((a+x)\2+2,(b+y)\2+2))
IF((0=POINT(a+2,b+2))+c)*(a>=0)*(b>=0)*(a<5*w)*(b<5*h)THEN k=k+1 ELSE IF t(k)>0GOTO 4 ELSE t(k)=-1:k=k-1
GOTO 1
6a=x+5*((r=2)-(r=4))
b=y+5*((r=1)-(r=3))
RETURN
7LINE(x+1,y+1)-(x+3,y+3),7,B
PSET(x+2,y+2),1
RETURN
9

入力の出力例10, 10, 100、実際のサイズ:10x10のランダム配管

この要点には、さらに手の込んだバージョンがあります。十分にコメントされていないだけでなく、出力を一定の係数でスケールアップし、ステップ間の遅延を設定できるため、作業中のDFSアルゴリズムを見ることができます。実行例を次に示します。

アクションでデラックスなplumbing.bas

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