再帰的なASCIIスパイラル


21

この競争は終わりました。エソラン以外の興味深いエントリーに感謝し、JakujeがJavaScriptを受賞したことを祝福します。

このサイトのASCIIアートチャレンジの偉大な伝統に、もう1つあります。入力が与えられたら、らせんを描きます。

&>----v
||>--v|
|||>v||
|||@|||
||^-<||
|^---<|
^-----<

簡単ですね ふふふふ...うん...

ASCII Dragons Curve投稿と、オプティマイザーのASCII Art of the Day投稿に触発されました)

入力

入力は、通常のSTDIN /関数の引数などから取得される一連のパラメーターの形式で、4つの部分で構成される同等の言語になります。これらの部分は、4つの引数、4つ、サイズ4の配列などになります。チャレンジ全体を通して単純さと一貫性を保つために、入力を1つの単語として表します。

  • 2 ≤ x ≤ 20スパイラルのサイズを「正方形」で指定する整数。各印刷文字は1つの「正方形」を表します。理論的にはこれは非常に範囲が広いかもしれませんが、ASCIIアートを描いていることを考えると、これは画面上である程度適切に収まるように、これの安全な上限は20になります。
  • d u rまたはの1文字。l開始「正方形」からの最初の動き(下、上、右、左)を示します。
  • c「反時計回り」を示すオプションの。cが省略された場合、スパイラルが時計回りに回転すると仮定します。
  • 1 ≤ y ≤ 10前のスパイラルの仕上げ「正方形」を新しいものの開始「正方形」として使用して、スパイラルの描画を再帰する回数を指定する最後の整数。描画をある時点で終了させるため、上限の10を選択しています。
  • いくつかの入力例: 20lc5 13d2 2rc1

興味深いことに、サイズ入力の奇数の値は@常にスパイラルの正確な中心になりますが、偶数の値は、初期の方向に応じて、4つの斜め方向のいずれかで開始「正方形」オフセットを持つ場合があることに注意してください旅行。これにより、いくつかの...興味深い...パターンが生じる可能性があります。以下の2つの偶数の例を参照してください。

入力仕様に従っていない入力(例11q#s:)は未定義であり、プログラムが適切にbarfすることを完全に期待しています。:)

出力

出力は、言語と同等のSTDOUTを介したASCII印刷可能な出力であり、次の仕様があります。

  • (各再帰の)開始「正方形」は、アットマークでマークする必要があります@
  • 最後の「正方形」は、アンパサンドでマークする必要があります&。複数の再帰の場合、最後の「正方形」のみをマークする必要があり&ます。
  • スパイラルパスの角は、を使用して、進行方向を「指す」必要があり< > v ^ます。
  • 垂直移動はパイプで引く必要があります|
  • 水平移動はダッシュで描く必要があります-
  • 後の再帰によって上書きされる「正方形」は、最新の移動方向を表示する必要があります。これにより、「古い」再帰の上に「新しい」再帰が重ねられているように見えます。4rc3以下の例を参照してください。
  • 最後の改行は問題ありません。先頭のスペースは必須なので、許可されますが、末尾のスペースは許可されません。
  • エスケープシーケンスを使用してASCIIアートをSTDOUTに描画する場合はドッキングしませんが、黙って失望します。(それらを使用する場合、引き続き賞金の資格があります)

2d4 =直径2、下降、時計回り、4回の再帰から開始

&@@@@
^<<<<

この例では、描画は右上から始まり、@下に1つ、左に1つ、上に1つ行きます。この時点で、その2d部分を終了したので、2回目の再帰を開始し@ます。その後、3回目の再帰。その後、4番目と最後に&

4rc3 =直径4、右回り、反時計回り、3回の再帰から開始

&--<
v-<|
|@^|<
>--^|
 |@^|<
 >--^|
  |@^|
  >--^

この例では、描画は下から始まり、@右に1つ、上に1つ、中央に到達して@その4rc部分が終わるまで螺旋状に動きます。次に、これをさらに2回繰り返して、要求された3つの再帰をすべて取得します。4rc1これは、この例の左上の4x4ブロックにすぎないことに注意してください。

7u1 =直径7、時計回り、1回の再帰で開始(開始はイントロと同じです)

&>----v
||>--v|
|||>v||
|||@|||
||^-<||
|^---<|
^-----<

勝ちと制限

これはCode Golfなので、バイト単位の最小の答えが勝ちです。提出は、プログラム/機能/ CJamコードブロックなどの通常の形式で行う必要があります。標準の抜け穴の制限が適用されます。クローズドコースのプロのドライバー。刺激が続く場合は、使用を中止し、医師に相談してください。


3
詳細はかなり異なりますが、参考までに、以前のスパイラル描画の課題があります:codegolf.stackexchange.com/questions/52494/…
レトコラディ

2
ナイスチャレンジ。「クローズドコースのプロドライバー」の+1
jrich

3
> <>回答を求めます。
The_Basset_Hound

2
「さあ、みんな... Common Lispを勝ち取ろうとするのか?;-)」それが今まで見た賞金の最も陽気な理由です。ありがとう
コアダンプ

1
ここに座っているのは、Common LispとLuaがコードゴルフの問題でトップの座を争っている2つの言語だということです。:)
AdmBorkBork

回答:


6

Javascript、 578575553478、377バイト

打ちのめされたLuaの後、私はよりコンパクトな言語に切り替え、競争をJavascriptに移しました。

s=function(w,d,c,r){d="dlur".indexOf(d)
j=i=G=H=I=J=w*r;o=[];for(x=0;x<J*2;x++){o[x]=[]
for(y=0;y<J*2;)o[x][y++]=' '}for(;r--;){a=d;m=l=z=1;o[i][j]="@"
for(k=w*w-1;k--;){G=G<i?G:i;H=H>i?H:i;I=I<j?I:j;J=J>j?J:j
o[i+=(1-a)%2][j+=a?a-2:0]=l++==m?(a+=c=="c"?3:1,m+=z=!z,l=1,"v<^>"[a%=4]):k?"|-"[a%2]:"&"}}for(i=G;i<=H;)console.log(o[i++].slice(I,J+1).join("").replace(/\s+$/g,''))}

アルゴリズムは同じですが、よりコンパクトな言語で記述されているため、悪のLispに勝つことができました:)

編集:Lispの下に再び到達し、末尾の空白を削除するには、いくつかの構造上の変更が必要でした。しかし、私たちは再びここにいます。

編集2:500未満になるために考慮されたいくつかの抽象化。それで十分であることを望みます:)

Edit3:@Timwiに感謝します。コードはさらに100文字細くなっています。説明はまだ更新していません。

テスト(オンラインバージョン、Chromeでテスト):

----| 2d4 |---
s.js:9 &@@@@
s.js:9 ^<<<<
ss.html:7 ----| 4rc3 |---
s.js:9 &--<
s.js:9 v-<|
s.js:9 |@^|<
s.js:9 >--^|
s.js:9  |@^|<
s.js:9  >--^|
s.js:9   |@^|
s.js:9   >--^
ss.html:9 ----| 7u1 |---
s.js:9 &>----v
s.js:9 ||>--v|
s.js:9 |||>v||
s.js:9 |||@|||
s.js:9 ||^-<||
s.js:9 |^---<|
s.js:9 ^-----<
ss.html:11 ----| 8r3 |---
s.js:9       >------v
s.js:9       |>----v|
s.js:9       ||>--v||
s.js:9       |||@v|||
s.js:9    >------v|||
s.js:9    |>----v|<||
s.js:9    ||>--v||-<|
s.js:9    |||@v|||--<
s.js:9 >------v|||
s.js:9 |>----v|<||
s.js:9 ||>--v||-<|
s.js:9 |||@v|||--<
s.js:9 ||^-<|||
s.js:9 |^---<||
s.js:9 ^-----<|
s.js:9 &------<
ss.html:13 ----| 8rc3 |---
s.js:9 &------<
s.js:9 v-----<|
s.js:9 |v---<||
s.js:9 ||v-<|||
s.js:9 |||@^|||--<
s.js:9 ||>--^||-<|
s.js:9 |>----^|<||
s.js:9 >------^|||
s.js:9    |||@^|||--<
s.js:9    ||>--^||-<|
s.js:9    |>----^|<||
s.js:9    >------^|||
s.js:9       |||@^|||
s.js:9       ||>--^||
s.js:9       |>----^|
s.js:9       >------^

公平を期すために、公正な説明があります。

s = function(w, d, c, r) {
    // width, direction, "c" as counter-clockwise and number of repetition
    // transfer direction to internal numerical representation
    d=d=="d"?0:d=="u"?2:d=="l"?1:3;
    // output strings
    x="v<^>"
    y="|-"
    // this is size of our canvas. Could be smaller, but this is shorter
    M = w * r * 2;
    // fill canvas with spaces to have something to build upon
    o = [];
    for (i = 0; i < M; i++) {
        o[i] = [];
        for (j = 0; j < M; j++)
            o[i][j] = ' '
    }
    // i,j is starting position
    // G,H,I,J are current boundaries (maximum and minimum values of i and j during the time)
    j = i = G = H = I = J = M / 2
    for (q = 0; q < r; q++) { // number of repeats
        a = d; // reset original direction
        // m is the expected length of side
        // l counts the of current side length
        m = l = 1;
        z = 0; // counts occurrences of the length
        o[i][j] = "@" // write initial character
        for (k = w * w; k > 1; k--) { // cycle over the whole spiral
            // update boundaries
            G = G < i ? G : i;
            H = H > i ? H : i;
            I = I < j ? I : j;
            J = J > j ? J : j;
            // move to the next position according to direction
            i+=a<3?1-a:0;
            j+=a>0?a-2:0
            if (k == 2) // we reached the end
                o[i][j] = "&"
            else if (l == m) {
                // we reached the corner so we need to count next direction
                a=(c=="c"?a+3:a+1)%4;
                // and write according sign
                o[i][j]=x[a]
                // first occurrence of this length
                if (z == 0)
                    z = 1; // wait for finish of the other
                else {
                    m++; // increase length of side
                    z = 0 // wait again for the first one
                }
                l = 1 // start the side counter over
            } else {
                l++ // another part of this side
                // according side character
                o[i][j] = y[a%2]
            }
        }
    }
    // blow it all out
    for (i = G; i <= H; i++)
        console.log(o[i].slice(I, J + 1).join("").replace(/\s+$/g, ''))
}

非常に素晴らしい。ルールに従って、あなたの例に従って、&optional10バイトを節約するためにキーワード(およびスペース)を削除することにしました。これは576 ... 悪笑いを与えます(まあ、あなたはもう少しゴルフができると言ったので、これはもちろん、誰かがPythで60バイトの回答を書くまでは、打つのは難しくないはずです)。
コアダンプ

@coredumpチャレンジは受け入れられました:)予想以上に難しいですが、それでも可能です:)あなたはピスでそれを行うことができると信じていますが、誰もそれを理解することはないので、複雑さはそのような言語の可能性を超えていると思います。
Jakuje

3
あなたは割り当てをチェーンした場合i=M/2;j=i;G=i;H=i;I=i;J=i;i=j=G=H=I=J=M/2;m=1;l=1;m=l=1;、あなたは12のバイト保存することができます
SLuck49

2
このソリューションはかなり賢いです。しかし、ゴルフができる場所がさらにいくつか見つかりました。377バイト
-Timwi

1
@Jakuje 377バイトバージョンを使用し、回答を編集して使用することが、Timwiの意図だったと思います。;)(そうでなければ、彼は別の答えを投稿したでしょう。)
マーティンエンダー

7

Common Lisp、 649 617 605 586 576 565 554 527 518

(lambda(r v z c &aux(m 0)s(c(if c 1 -1))o p(x 0)i(y 0)j u)(#8=dotimes(_ z)(#7=setf p(aref"ruld"v)i(1-(abs(- p 2)))j(- 1(abs(1- p)))s'@)(#8#($(1- r))#5=(#7#m(min m x)o(cons`(,x,y,s)o)s(aref"-|-|"p)x(+ x i)y(+ y j))#2=(#7#s(*(- c)j)j(* i c)i s p(mod(+ p c)4)s(aref">^<v"p)u(#8#(_(1+ $))#5#))#2#))(#7#s'& u #5#o(#4=stable-sort(#4#o'< :key'car)'> :key'cadr)y(cadar o)x m)(dolist(k o)(do()((>=(cadr k)y))(#7#y(1- y)x m)(terpri))(do()((<=(car k)x))#9=(incf x)(princ" "))(and(=(cadr k)y)(=(car k)x)#9#(princ(caddr k)))))

すべてのテストは引き続き合格します。コメントがあったように、変更されていない関数も更新され、変更が反映されました。私はついにremove-duplicatesコードを短くするために取り除いたが、今ではどこにもっとバイトがあるのか​​わからない。よくやった

(funcall *fun* 8 #\r 3 nil)

      >------v
      |>----v|
      ||>--v||
      |||@v|||
   >------v|||
   |>----v|<||
   ||>--v||-<|
   |||@v|||--<
>------v|||
|>----v|<||
||>--v||-<|
|||@v|||--<
||^-<|||
|^---<||
^-----<|
&------<

(funcall *fun* 8 #\r 3 t) ;; counter-clockwise

&------<
v-----<|
|v---<||
||v-<|||
|||@^|||--<
||>--^||-<|
|>----^|<||
>------^|||
   |||@^|||--<
   ||>--^||-<|
   |>----^|<||
   >------^|||
      |||@^|||
      ||>--^||
      |>----^|
      >------^

(funcall *fun* 7 #\u 1 nil)

&>----v
||>--v|
|||>v||
|||@|||
||^-<||
|^---<|
^-----<

(funcall *fun* 2 #\d 4 nil)

&@@@@
^<<<<

20lc10(pastebin)も参照してください。

非ゴルフ

ここには再帰は含まれていません。ループを使用した基本的なTurtleグラフィックアプローチのみです。

  1. (x y char)トリプルをスタックに格納して、メモリにスパイラルを描きます。
  2. yおよびによる安定ソート要素x
  3. 重複(以前のトレース)を避けながらそのリストを反復処理し、左上から右下に印刷します。
(lambda
    (r v z c
     &aux
       (m 0)       ; minimal x
       s           ; symbol to print (a character)
       (c          ; 1 if clockwise, -1 otherwise
        (if c
            1
            -1))
       o           ; stack of (x y char) traces
       p           ; position of s in ">^<v"
       i           ; move direction of x
       j           ; move direction of y
       (x 0)       ; position in x
       (y 0)       ; position in y
       u           ; auxiliary variable
       )
  ;; repeat for each recursive step
  (dotimes (_ z)
    ;; initialize spiral parameters
    (setf s '@            ; start spiral with @
          p (position v"ruld") ; initialize p according to input V

          ;; Set initial direction in I and J.
          i (1-(abs(- p 2))) ; i(0..3) = ( 1, 0, -1, 0 )
          j (- 1(abs(1- p))) ; j(0..3) = ( 0, 1, 0, -1 )

    ;; Iterate with increasing diameter $. For each iteration, draw a
    ;; "L"-shape that extends previous shape. Here is roughly what
    ;; happens at each step:
    ;;
    ;;   3334
    ;;   3124
    ;;   3224
    ;;   4444
    ;;
    (dotimes($(1- r))

      ;;
      ;; Assign the form to the reader variable #1# in order to
      ;; copy-paste later. This is like declaring a local function,
      ;; but shorter: push trace into list O and move forward.
      ;;
      #1=(setf m (min m x)
               o (cons `(,x ,y ,s) o)
               s (aref "-|-|" p)
               x (+ x i)
               y (+ y j))

      ;;
      ;; Helper function #2#: rotate and draw a line of length $.
      ;;

      #2=(setf u (* (- c) j) ; rotation as a vectorial                   
               j (* i c)     ; product of (i j 0) with (0 0 c).
               u i           ; At first I used PSETF, but now I reuse
                             ; the existing SETF with an auxiliary 
                             ; variable U to shorten the code and get
                             ; rid of PROGN. That's also why I affect
                             ; the result of DOTIMES to U (no need
                             ; for two forms and a PROGN, just SETF).

               p (mod(+ p c)4)   ; ">^<v" is sorted counter-clockwise, which 
               s (aref ">^<v" p) ; means that adding P and C (modulo 4) gives 
                                 ; the next symbol after rotation.

               ;; trace a line by repeatedly invoking code snippet #1#
               u (dotimes(_(1+ $)) #1#))
      ;; 
      ;; Rotate and draw a second line, hence drawing a "L"-shape.
      ;;
      #2#))

  ;; Finally, draw the final symbol &
  (setf s '&)
  #1#

  (setf o

        ;; From inside-out:
        ;;
        ;; - stable sort O according to X
        ;;   (from lowest (left) to highest (right))
        ;;
        ;; - stable sort the result according to Y
        ;;   (from highest (top) to lowest (bottom))
        ;;
        (stable-sort (stable-sort o '< :key 'car) '> :key 'cadr)

        ;; initialize Y with the first Y in O, which is also the
        ;; minimum of all Y.
        y (cadar o)

        ;; initialize X with the minimum of all X
        x m) 

  ;; For each trace in O
  (dolist (k o)

    ;; Add as many lines as needed to advance Y to current trace's Y.
    (do ()
      ((<= y (cadr k)))
      (setf y (1- y)
            x m)
      (terpri))

    ;; Add as many spaces as needed to advance X to current trace's X.
    (do () ((>= x (car k))) (incf x) (princ " "))

    ;; Then, print current trace's character and increment X.
    ;; This happens only when we have a "new" trace, not another
    ;; trace at the same point (which was being overwritten).
    (and(=(car k)x)(=(cadr k)y)(incf x)(princ(caddr k)))

4

Lua 5.2、740バイト

s=io.read W=io.write Z=math.max A=math.min
D="d"U="u"L="l"R="r"function n()G=A(G,i)H=Z(H,i)I=A(I,j)J=Z(J,j)i=(a==D and i+1 or a==U and i-1 or i)j=(a==R and j+1 or a==L and j-1 or j)end
w=s"*n"d=s(1)c=s(1)r=(c=="c")and s"*n"or c
c=c=="c"M=w*(r+1)o={}for i=1,M do o[i]={}for j=1,M do o[i][j]=" "end end
i=M/2 j=i G=i H=i I=i J=i
for q=1,r do a=d m=1 l=1 z=0
o[i][j]="@"for k=3,w^2 do
n()if l==m then
a=c and(a==D and R or a==U and L or a==L and D or a==R and U)or(a==D and L or a==U and R or a==L and U or a==R and D)o[i][j]=(a==D and"v"or a==U and"^"or a==L and"<"or a==R and">")
if z==0 then z=1 else m=m+1;z=0 end
l=1
else
l=l+1
o[i][j]=(a==D or a==U)and"|"or"-"end end
n()o[i][j]="&"end
for i=G,H do for j=I,J do
W(o[i][j])end W("\n")end

Lispに勝つためのアルゴリズムを実装しようとするのは楽しいと思いますが、Luaはおそらく最良の選択肢ではありません。私はそれに時間をかけすぎて、いくつかの部分を過剰に設計して、このい部分だが機能するソリューションで終わるようにしました。おそらく、このアルゴリズムから取り去ることのできない約90の文字があるので、後でLispに勝つために別の言語を試してみるでしょう。

出力のテスト:

jakuje@E6430:/tmp$ echo "2d4" | lua s.lua 
&@@@@
^<<<<
jakuje@E6430:/tmp$ echo "4rc3" | lua s.lua 
&--<  
v-<|  
|@^|< 
>--^| 
 |@^|<
 >--^|
  |@^|
  >--^
jakuje@E6430:/tmp$ echo "7u1" | lua s.lua 
&>----v
||>--v|
|||>v||
|||@|||
||^-<||
|^---<|
^-----<

2

PHP、524バイト

私はこのパーティーに遅れて到着しました。私のPHPソリューションは、最小でもスマートでもありません。それはただ動作します。

$a=$argv;
$b=[['|','^',0,-1],['-','>',1,0],['|',v,0,1],['-','<',-1,$x=$y=$o=$p=$q=$r=0]];
for($t=$a[4];$t;$t--){$d=strpos(urdl,$a[2]);$c=$b[$d];$m[$y][$x]='@';
for($s=0;++$s<$a[1];){for($k=3;--$k;){for($i=$s;--$i;)
$m[$y+=$c[3]][$x+=$c[2]]=$c[0];$x+=$c[2];$y+=$c[3];$c=$b[$d=($d+($a[3]==c?3:1))%4];
$m[$y][$x]=$c[1];}$o=min($x,$o);$p=max($p,$x);$q=min($y,$q);$r=max($r,$y);}
for($i=$s;--$i;)$m[$y+=$c[3]][$x+=$c[2]]=$c[0];$m[$y][$x]='&';}
for($y=$q;$y<=$r;$y++){$l='';for($x=$o;$x<=$p;$x++)$l.=$m[$y][$x]?:' ';
echo rtrim($l)."\n";}

実行方法:

$ php -d error_reporting=0 recursive-ascii-spirals.php 4 r c 3
&--<
v-<|
|@^|<
>--^|
 |@^|<
 >--^|
  |@^|
  >--^
$ php -d error_reporting=0 recursive-ascii-spirals.php 7 u '' 1
&>----v
||>--v|
|||>v||
|||@|||
||^-<||
|^---<|
^-----<

テスト、説明、その他の便利な機能を備えた詳細バージョンは、githubにあります。

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