今日のランダムアスキーアート#5:ダイヤモンドのタイル


21

マッシュアップタイム!

これは、私のランダムゴルフオブザデイとオプティマイザーのASCIIアートオブザデイシリーズの両方の第5回です。このチャレンジでの投稿は、両方のリーダーボードにカウントされます(リンクされた投稿を見つけることができます)。もちろん、これを他のコードゴルフチャレンジと同様に扱い、いずれかのシリーズについてまったく心配することなく答えることができます。

穴5:ダイヤモンドのタイル

通常の六角形は、常に次のようにダイヤモンドでタイル化できます。

これらのタイルのASCIIアート表現を使用します。辺の長さが2の六角形には、このようなタイルが20個あります。

   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /\_\_\   /\_\_\   /\_\_\   /\_\_\   /_/\_\   /_/\_\   /\_\_\   /_/\_\   /_/\_\   /_/\_\ 
 /\/\_\_\ /\/_/\_\ /\/_/_/\ /\/_/\_\ /\_\/\_\ /\_\/_/\ /\/_/_/\ /\_\/\_\ /\_\/_/\ /_/\/\_\
 \/\/_/_/ \/\_\/_/ \/\_\_\/ \/_/\/_/ \/\_\/_/ \/\_\_\/ \/_/\_\/ \/_/\/_/ \/_/\_\/ \_\/\/_/
  \/_/_/   \/_/_/   \/_/_/   \_\/_/   \/_/_/   \/_/_/   \_\/_/   \_\/_/   \_\/_/   \_\/_/ 
   ____     ____     ____     ____     ____     ____     ____     ____     ____     ____  
  /_/_/\   /\_\_\   /_/\_\   /_/_/\   /_/\_\   /_/\_\   /_/_/\   /_/_/\   /_/_/\   /_/_/\ 
 /\_\_\/\ /\/_/_/\ /_/\/_/\ /\_\_\/\ /\_\/_/\ /_/\/_/\ /_/\_\/\ /\_\_\/\ /_/\_\/\ /_/_/\/\
 \/\_\_\/ \/_/_/\/ \_\/\_\/ \/_/\_\/ \/_/_/\/ \_\/_/\/ \_\/\_\/ \/_/_/\/ \_\/_/\/ \_\_\/\/
  \/_/_/   \_\_\/   \_\/_/   \_\/_/   \_\_\/   \_\_\/   \_\/_/   \_\_\/   \_\_\/   \_\_\/ 

辺の長さNを指定すると、辺の長さの六角形のタイルをNランダムに生成する必要があります。正確な分布は重要ではありませんが、各タイルはゼロ以外の確率で返される必要があります。

のためにN ≤ 4、あなたの提出物は、少なくとも80%の時間で1分以内にタイルを作成しなければならず、少なくとも80%のタイルは1分以内に生成される可能性があります。ほとんどのアプローチでは、このルールを心配する必要はありません(非常に寛大です)-これは、タイルになるまで任意の文字列を生成する非常に単純な拒否ベースのアルゴリズムを除外するためです。

特定のNの可能なタイルの総数は、OEIS A008793で確認できます。

完全なプログラムまたは関数を作成し、STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を受け取り、STDOUT(または最も近い代替)、関数の戻り値または関数(out)パラメーターを介して出力を生成できます。

六角形を揃えるのに必要なスペースよりも多くの先行スペースを出力しないでください(つまり、六角形の左隅にはスペースがありません)。各行には最大でN末尾のスペースが含まれる場合があります(必ずしも一貫性があるとは限りません。そのため、たとえば、四角形の出力を使用して、六角形の境界ボックスを印刷できます)。

これはコードゴルフであるため、最短の提出(バイト単位)が優先されます。そしてもちろん、ユーザーごとの最短投稿もシリーズの総合リーダーボードに入ります。

リーダーボード

各シリーズの最初の投稿でリーダーボードが生成されます。

回答が表示されるようにするには、次のマークダウンテンプレートを使用して、すべての回答を見出しで開始してください。

# Language Name, N bytes

N提出物のサイズはどこですか。スコアを改善する場合、古いスコアを打つことで見出しに残すことができます。例えば:

# Ruby, <s>104</s> <s>101</s> 96 bytes

(言語は現在表示されていませんが、スニペットはそれを必要とし、解析します。将来、言語ごとのリーダーボードを追加するかもしれません。)


3
3Dでサンプル画像を見続けるのは私だけですか?
LegionMammal978

3
@ LegionMammal978いいえ、それはまったく普通のことです。;)(また、おそらく挑戦にアプローチするための良い方法です。)
マーティンエンダー

For N ≤ 4, your submission must produce a tiling within 1 minute at least 80% of the time.簡単すぎる:時間の80%と同じ、基本的なタイリングは、それ以外の場合はI私が好きな時間に別のタイリングを見つける
edc65

@ edc65良い点は、それを言い換えさせてください。
マーティンエンダー

回答:


10

CJam、105バイト

ri:A" __"e*A,2f*:B,[W1]{J+B:):B,{N1$S*"\/"J%A2*4$-:D*
0{;B{_1&!2mr+J*m1e>D(2*e<}%__:)&}g:B{'_t}/+@J+}*}fJ;

スクロールを避けるために改行が追加されました。オンラインで試す

説明:

このソリューションは、各行をジグザグとして開始し、前の行の位置といくつかのルールに基づいて、N個の下線をその上に配置します。出力を文字のプレーンな2Dマトリックスとして見ながら、一連の観察からこれを取得しました。

  • 各行には正確にN個の下線があります
  • アンダースコアを/または\に置き換えて、完全に繰り返されるジグザグパターンを作成できます(/\上半分、\/下半分)
  • アンダースコアは側面に触れることができず、別のアンダースコアに隣接することはできません
  • 次の行に移動すると、各アンダースコアの位置が-1、0、または1変化します
  • それ以上、/_/-1または0 \_\だけ変更でき、0または1だけ変更できます
  • 最初のアンダースコアの位置には、"_ "パターンまたはパターンのいずれかを使用できます" _"。両方とも問題ありません
  • 上記のルールは、すべてのタイルを取得するのに十分です

そこで、以前のアンダースコアの位置を保持し、ランダムファクター(アンダースコアごとに2つの選択肢)でそれらを変更し、ルールが満たされるまで繰り返すことで実装することにしました。最適化のプロセスでは、六角形の左側(スペースを含まない)に対して下線の位置に切り替えました。

ri:A" __"e*       read the input (A) and generate the top line
A,2f*:B           make an array [0 2 4 ... 2A-2] and store in B
                  these are the initial positions for the underscores
,                 B's length = A, used as the initial number of leading spaces
                  let's call it C
[W1]{…}fJ         for J in [-1 1] (top half, bottom half)
  J+              add J to C
  B:):B           increment the underscore positions (adjustment before each half)
  ,{…}*           repeat A times
    N1$S*         add a newline and C spaces
    "\/"J%        take "\/" and reverse it if J=-1 (zigzag pattern)
    A2*4$-:D*     calculate D=A*2-C and repeat the pattern
    0             dummy value (for the next loop)
    {…}g          do-while
      ;B          pop last value and push B
      {…}%        apply block to each item (say x)
        _1&!      duplicate x and calculate !(x&1) (for /_/ vs \_\)
        2mr+      randomly add 0 or 1
        J*m       multiply by J and subtract from x
        1e>       limit the minimum value to 1
        D(2*e<    and the maximum value to 2*(D-1)
      __:)&       check if the modified array has any adjacent values
    :B            store the new positions in B
    {'_t}/        place underscores over the zigzag pattern
    +@J+          bring C to the top and add J to it
;                 pop C

古い「3D」バージョン、189バイト:

ri:A" __"e*aA4*S*aA2**+[0-2XXW1]:C;"/\_\\\/_/":D;A3m*{{C2/.f*:.+~
A(2*+:V;A+:U;2{UI+1$1$=4{_V+D4/I=@=t}/t}fI}:F~}/[0Y1WWW]:C;
"/_/\\\_\/":D;AaA*:B;A{A[_{_BI=e<)mr}fI]:B;{BQ={[PQR]F}fR}fQ}fPN*

オンラインで試す


素晴らしい仕事のために+1し、もう1回投票すると10k repになりますが、ほとんどがすばらしい仕事のためです。(ああ、それを見てください。10kでおめでとう:))
アレックスA.

パターンの優れた分析!答えに使用します。
アナトリグ

6

Python 2、337 335 324 318 311 300 296バイト

from random import*
n=input()
R=range(n*2)
b=[]
l=[]
for i in R:o=abs(i-n)-(i<n);b+=[o];l+=[list(' '*o+'\//\\'[i<n::2]*(n*2-o))]
for i in R[:n]:
 o=1;p=n+i*2
 for j in R:r=randint(0,p<n*3+i*2-j);p+=(r or-1)*(o==r);q=p<=b[j];o=r|q;p+=q;l[j][p]='_';b[j]=p+1
for s in[' '*n+'__'*n]+l:print''.join(s)

このアイデアは、最初に次のようなダイヤモンドの六角形を作成することです:

  ____
 /\/\/\
/\/\/\/\
\/\/\/\/
 \/\/\/

そして、次のように、アンダースコアの下向きのパスでそれを埋めます:

  ____                          ____
 /_/\/\                        /\_\/\
/_/\/\/\    or maybe this:    /\/_/\/\
\_\/\/\/                      \/_/\/\/
 \_\/\/                        \_\/\/

すべてのパスが追加された最終結果は、次のようになります。

  ____                          ____  
 /_/\_\                        /\_\_\ 
/_/\/_/\    or maybe this:    /\/_/\_\
\_\/_/\/                      \/_/\/_/
 \_\_\/                        \_\/_/ 

これらのパスが範囲外になったり、互いに交差したりしないように、かなりの量のコードが使用されます。

改変されていないコード:

# Initialize l with all diamonds
blocked = []
l = [[] for _ in range(n*2)]
for i in range(n*2):
    offset = n-i-1 if i<n else i-n
    blocked.append(offset)
    l[i] += ' '*offset + ('/\\' if i<n else '\/')*(2*n - offset)

# Generate the random _'s
for i in range(n):
    oldright = True
    pos = n + i*2
    for j in range(n*2):
        # Go randomly right (true) or left (false), except when you out of bounds on the right side
        right = randint(0, 1) and pos < n*3 + i*2 - j
        if right == oldright:
            pos += 1 if right else -1
        if pos <= blocked[j]:
            right = True
            pos += 1
        l[j][pos] = '_'
        blocked[j] = pos + 1
        oldright = right

# Print the result
print ' '*n + '__'*n
for s in l:
    print ''.join(s)

1
私はあなたの出力が間違っているように見えることに気づきました。2つの例の結果(右上と右下)に三角形があります。
マーティンエンダー

1
@MartinEnderこの例では、アルゴリズムの概念を示すために、「アンダースコアのパス」を1つだけ示しました。最終出力にはすべてのパス(この場合は2)があり、三角形が削除されます。最終出力の例にも追加しました。
マティー

なるほど、それは理にかなっています。説明をありがとう。
マーティンエンダー

2
私はあなたが短くなることができると思いますrandint(0,1)*(p<n*3+i*2-j)randint(0,p<n*3+i*2-j)
12Me21

ああ、ありがとう!
マティ

4

Perl、174 168 166 161

#!perl -n
for$l(-$_..$_){$t=/_/?join'',map'/_'x($%=rand
1+(@z=/__?/g)).'/\\'.'_\\'x(@z-$%),split/\/\\/:__
x$_;$l>0&&$t!~s!^.(\\.*/).$!$1!?redo:print$"x abs$l-.5,$_=$t.$/}

私を試してください


常に同じタイリングを生成するようです(少なくともideoneで)
aditsu

@aditsu、Ideoneは、リンクをクリックするだけでキャッシュされた結果を表示します。実際に再実行するにはフォークする必要があります。
-nutki

2

JavaScript(ES6)、376 416 494

そこにいるだけで...

これにより、すべてのタイルが構築され、ランダムなタイルが選択されます。私のラップトップでは、N = 4の232848タイルの時間は約45秒です。N = 5を試しませんでした。

EcmaScript 6であるため、Firefoxでのみ実行されます。

F=n=>{
  for(i=s=r=b='';i<n;i++)
    s='\n'+b+'/\\'[R='repeat'](n-i)+'_\\'[R](n)+s,
    r+='\n'+b+'\\/'[R](n-i)+'_/'[R](n),
    b+=' ';
  for(h=[t=0],x=[s+r];s=x[t];t++)
    for(d='';!d[n*3];d+='.')
      if(l=s.match(r=RegExp("(\n"+d+"/)\\\\_(.*\n"+d+"\\\\)/_","g")))
        for(j=2<<l.length;j-=2;h[z]||(h[z]=x.push(z)))
          z=s.replace(r,(r,g,h)=>(k+=k)&j?g+'_/'+h+'_\\':r,k=1);
  return b+'__'[R](n)+x[Math.random()*t|0]
}


function go()
{
  var n = N.value | 0,
  t0 = performance.now(),
  r = F(n),
  t1 = performance.now();
  
  O.innerHTML = r+'\n\nTime (msec): '+(t1-t0)
}
N: <input id=N value=3><button onclick="go()">GO</button>
<pre id=O></pre>


Chromium 42で「Uncaught SyntaxError:Unexpected token =>」および「Uncaught ReferenceError:go is not defined」
15年

1
@aditsuそれはES6、Chrome:いいえFirefox:はい。それはよく知られた事実ではありませんか?
edc65

見当がつかなかったので、Chromiumが最新で最高の、見かけ上JavaScriptではないものを使用することを期待していました。説明してくれてありがとう。
-aditsu

今Firefox(31.5.3)で実行し、N = 1、2または3で動作しますが、N = 4では約10秒間実行され、終了し、何も表示されません(そしてコンソールにエラーはありません) )
aditsu

@aditsuわからない...おそらく制限時間を超えると、サンドボックス内のjavascriptが静かに殺されますdom.max_script_run_time。about:configのグローバル設定で、私の設定は30です。
edc6515年

1

SmileBASIC、241バイト

INPUT N
T=N*2CLS?" "*N;"__"*N
DIM B[T]FOR I=-1TO N-1O=1P=N+I*2FOR J=0TO T-1IF I<0THEN O=ABS(J0N+.5)<<0B[J]=O?" "*O;MID$("\/\",J<N,2)*(T-O)ELSE R=P<N*3+I*2-J&&RND(2)P=P+(R*2-1)*(O==R)A=P<=B[J]R=R||A:P=P+A:LOCATE P,J+1?"_"B[J]=P+1O=R
NEXT
NEXT

マティの答えに大きく基づいている

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