Özyinelemeli ASCII Spiralleri


21

Bu yarışma bitti. İlginç esolang’ın girişleri için teşekkürler ve kazanan JavaScript gönderimi için Jakuje’ye tebrikler .

Bu sitede ASCII Art Challenges'in büyük geleneğinde, işte bir tane daha. Bir giriş verildiğinde, bir spiral çizin.

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

Basit, evet? Heh, heh, heh ... Evet ...

( ASCII Dragons Curve post ve Optimizer'ın ASCII Art of the Day yayınlarından ilham alınmıştır )

Giriş

Girdi, dil eşdeğeri ne olursa olsun, dört bölümden oluşan, her zamanki STDIN / function argümanından / etc den alınan bir dizi parametre şeklinde olacaktır. Bu bölümler dört ayrı argüman, dörtlü, 4 büyüklükte bir dizi vb. Olabilir. Meydan okuma boyunca basitlik ve tutarlılık için girişi tek bir kelime olarak temsil edeceğim.

  • Spiralin 2 ≤ x ≤ 20boyutunu "kare" cinsinden belirten ve her basılan karakterin bir tane "kare" olduğunu gösteren bir tam sayı . Teorik olarak bu, kapsam açısından muazzam olabilir, ancak ASCII sanatını çizdiğimize göre, güvenli bir üst limit 20 olacak, böylece ekrana biraz yakışacaktı.
  • Başlangıçtaki "kareden" (aşağı, yukarı, sağ, sol) ilk hareketi gösteren tek bir harf d u rveya l.
  • c"Saatin tersi yönünde" belirten isteğe bağlı . cİhmal edilirse, spiral için saat yönünde döndürmeyi farz edin.
  • 1 ≤ y ≤ 10Spiral çizmeyi kaç kez tekrarlayacağını belirten son bir tamsayı , önceki spiralin "karesini" kullanarak yenisinin başlangıç ​​"karesini" kullanır. 10 üst limiti seçiyorum çünkü çizimin bir noktada bitmesini istiyorum.
  • Birkaç örnek giriş: 20lc5 13d2 2rc1

İlgi çekici olan, boyut girişi için tek değerlerin @her zaman bir spiralin tam merkezi olmasına yol açacağını unutmayın; ancak değerler bile, başlangıç ​​yönüne bağlı olarak dört çapraz yönden herhangi birinde başlangıç ​​"kare" kaymasına sahip olabilir. seyahat. Bu bazı ilginç ... sonuçlara neden olabilir. Aşağıdaki iki çift örneğe bakın.

Giriş şartnamesine uymayan giriş (örn. 11q#s) Tanımsızdır ve programın uygun şekilde programlanmasını bekliyorum. :)

Çıktı

Çıktı, aşağıdaki özelliklere sahip, dil eşdeğeri STDOUT aracılığıyla yazdırılabilir bir ASCII çıkışıdır:

  • (Her bir özyinelemenin) başlangıç ​​"karesi" bir işaret ile işaretlenmelidir @.
  • Son "kare" bir ve işareti ile işaretlenmiş olmalıdır &. Birden fazla tekrarlama durumunda, sadece son “kare” işaretlenmelidir &.
  • Spiral yolun köşeleri kullanılarak hareket yönünde "işaret" gerekir < > v ^.
  • Dikey seyahat borularla çizilmesi gerekir |.
  • Yatay seyahatin kısa çizgilerle çizilmesi gerekir -.
  • Daha sonra tekrarlananların üzerine yazılan "Kareler", en yeni seyahat yönünü göstermelidir. Bu, "eski" özyinelemelerin üzerine yerleştirilmiş gibi görünen "daha yeni" özyinelemelere yol açacaktır. Bkz 4rc3aşağıdaki örneğe.
  • Sondaki bir son satırda tamam, baştaki boşluklar şart olabilir ve buna izin verilir, ancak sondaki alanlara izin verilmez.
  • ASCII sanatını STDOUT'a çekmek için kaçış dizileri kullanırsan seni yanaşmam, ama senin içinde sessizce hayal kırıklığına uğradım. (Eğer kullanırsanız, yine de ödül için uygun olacaksınız)

Örnekler

2d4 = 2 çap, aşağı doğru, saat yönünde, 4 tekrarlama yaparak başlar

&@@@@
^<<<<

Bu örnekte, çizim sağ üstte başlar, @biri aşağıya, biri yukarı sola doğru gider. Bu noktada, 2dkısmı bitirdik ve böylece 2. özyinelemeyi başlattık, böylece bir @tane, bir tane sol, bir tane yukarı; daha sonra 3. özyineleme; sonra dördüncü ve son olarak bizim &.

4rc3 = 4 çap, sağa doğru ilerleyerek başlar, saat yönünün tersine, 3 tekrarlar

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

Bu örnekte, çizim alttan başlar @, birinden yukarıya doğru gider, ortasına gelene @ve 4rckısmı bitirene kadar etrafında spiraller . Bu daha sonra istenen 3 özyinelemeyi almak için iki kez daha tekrar eder. 4rc1Bu örneğin sadece sol üst 4x4 bloğu olacağını unutmayın .

7u1 = 7 çap, saat yönünde, 1 özyinelemeyle başlayarak başlar (intro ile aynı olduğuna dikkat edin)

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

Kazanma ve Kısıtlamalar

Bu Code Golf, bayt cinsinden en küçük cevap kazanıyor. Gönderimler olağan program / function / CJam Kod Bloğu / etc biçiminde olmalıdır. Standart Loophole Kısıtlamaları geçerlidir. Kapalı yolda profesyonel sürücü. Tahriş devam ederse, kullanmayı bırakın ve doktorunuza danışın.


3
Özellikler oldukça farklı, ancak sadece referans olması için işte size daha önce yapılmış bir spiral çizim mücadelesi: codegolf.stackexchange.com/questions/52494/… .
Reto Koradi

2
Güzel meydan okuma. + Kapalı kursta profesyonel şoför için +1
jrich

3
Bir> <> cevap ister.
The_Basset_Hound

2
"Hadi, millet ... Common Lisp'in kazanmasına izin verecek misiniz? ;-)" Bu gördüğüm bir ödülün en komik nedeni. Thanks
coredump

1
Burada oturup Common Lisp ve Lua’nın kod-golf sorusunda en üst sıraya çıkan iki dil olduğunu söylüyorlar. :)
AdmBorkBork

Yanıtlar:


6

JavaScript, 578, 575, 553, 478, 377 Bayt

Dövüldüğüm Lua'dan sonra daha kompakt bir dile geçtim ve rekabeti Javascript'e taşıdım:

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,''))}

Algoritma aynı, fakat daha kompakt bir dilde yazılmış, bu yüzden kötü Lisp'i yenmeyi başardım :)

Düzenleme: Lisp'in altına tekrar ulaşmak ve izleyen boşlukları ortadan kaldırmak için bazı yapısal değişikliklere ihtiyaç vardı. Ama yine buradayız.

Düzen2: 500'ün altına girmek için dikkate alınan bazı soyutlamalar. Yeterli olacağını umuyorum :)

Edit3: Thanks @Timwi, kod başka 100 karakter daha incedir. Açıklamayı henüz güncellemedım.

Testler ( çevrimiçi sürüm , Chrome'da test edilmiştir):

----| 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       >------^

Adil olmak gerekirse, adil bir açıklaması var:

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, ''))
}

Çok hoş. Kurallar ve örnek aşağıdakilere göre, ben kaldırmak için karar &optional576 ... verir 10 bayt, kurtarmak için anahtar kelime (ve bir boşluk) kötü kahkaha iyi (, bunu böylece, biraz daha golf yapabileceğimi söyledi yenmek zor olmamalı; biri Pyth'e 60 baytlık bir cevap yazana kadar elbette).
coredump

@coredump Mücadelesi kabul edildi :) Beklediğimden daha zor, ama yine de mümkün :) İnanıyorum ki, bunu yapabileceğini inanıyorum, ama kimse bunu anlayamayacak, bu yüzden karmaşıklığın bu dilin olanakları üzerinde olduğuna inanıyorum.
Jakuje

3
Atamaları i=M/2;j=i;G=i;H=i;I=i;J=i;içine i=j=G=H=I=J=M/2;ve m=1;l=1;içine zincirlerseniz m=l=1;12 bayt kaydedebilirsiniz
SLuck49 10:15

2
Bu çözüm oldukça zekice. Ancak, golf oynayabilecek başka yerler buldum: 377 byte
Timwi

1
@ Jakuje 377 bayt versiyonunu almanın ve cevabınızı kullanmanız için düzenlemenin sizin niyetiniz olduğuna inanıyorum. ;) (Aksi takdirde az önce ayrı bir cevap
Martin Ender

7

Ortak 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)))))

Bütün testler hala geçiyor. Ungolfed fonksiyonu da yorumlardaki gibi değişiklikleri yansıtacak şekilde güncellendi. Sonunda remove-duplicateskodu kısaltmak için kurtuldum , ama şimdi nerede daha fazla bayt bulacağımı bilmiyorum. Aferin Jakuje.

Örnekler

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

&@@@@
^<<<<

Ayrıca bakınız 20lc10(pastebin).

Ungolfed

Burada hiçbir özyineleme yoktur, sadece döngüler içeren basit bir Kaplumbağa grafik yaklaşımı:

  1. (x y char)Bir yığını içine üçler depolayarak spiralleri bellekte çizin .
  2. Göre kararlı-sıralama elemanları yvex
  3. Yinelemelerden (önceki izler) kaçınırken bu listeyi yineleyin ve soldan sağa doğru yazdırın.
(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 Bayt

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'i yenmek için bazı algoritmalar uygulamaya çalışmanın eğlenceli olacağını düşünmüştüm, ancak Lua muhtemelen en iyi seçenek değil. Bunun için çok fazla zaman harcıyorum, bu çirkin olanla çalışmak için bazı bölümleri fazlaca tasarladım, ancak çalışan bir çözüm. Muhtemelen daha sonra Lisp'i yenmek için farklı bir dil deneyeceğim, çünkü bu algoritmadan alamayacağım 90 karakter var.

Test çıktıları:

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 bayt

Bu partiye geç geldim. Benim PHP çözümüm ne en küçük ne de en zekidir. Sadece işe yarıyor.

$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";}

Nasıl çalıştırılır:

$ 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||
|||@|||
||^-<||
|^---<|
^-----<

Testler, açıklama ve diğer güzellikler içeren ayrıntılı versiyon github'da bulunabilir .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.