Argyle ASCII Art

27

Napisz program (lub funkcję), który przyjmuje dodatnią liczbę całkowitą.

Jeśli dane wejściowe są 1, wydrukuj (lub zwróć) dwa diamenty sąsiadujące obok siebie, każdy o boku długości 1 ukośnika:

/\/\
\/\/

Dla każdego wejścia Nwiększego niż 1, spójrz na wynik dla N-1każdej pary sąsiednich diamentów, włóż między nimi nowy diament, którego długość boku jest sumą długości boku dwóch sąsiadów. Wydrukuj (lub zwróć) ten nowy wzór diamentu.

Kiedy 2jest wprowadzany, patrzymy na wynik 1i widzimy, że są dwa sąsiednie diamenty, oba o długości boku 1. Więc wstawiamy między nimi diament długości 2 (1 + 1):

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

3Jako dane wejściowe patrzymy na wynik 2i dodajemy dwa diamenty o długości boku 3 (1 + 2 i 2 + 1) pomiędzy dwiema parami sąsiednich diamentów:

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

Kontynuując wzorzec, wynikiem 4jest:

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

I tak dalej.

Twoje dane wyjściowe mogą mieć końcowe spacje w dowolnych wierszach, ale tylko do jednej nowej linii (bez żadnych nowych linii).

Najkrótszy kod w bajtach wygrywa.

Hobby Calvina
źródło
1
Odpowiedni OEIS: oeis.org/A002487 .
orlp

Odpowiedzi:

8

Pyth, 50 49 bajtów

L.rR"\/"_bjbyK.tsm+Jm+*\ k\\dyJu.iGsM.:G2tQjT9djK

Demonstracja

Wyjaśnienie:

L.rR"\/"_bjbyK.tsm+Jm+*\ k\\dyJu.iGsM.:G2tQjT9djK
                                                     Implicit:
                                                     Q = eval(input())
                                                     T = 10
                                                     d = ' '
                                                     b = '\n'
L                                                    def y(b): return
 .rR"\/"                                             Swap \ and / in
        _b                                           reversed input.
                                                     This effectively vertically
                                                     mirrors the input.
                               u                     Apply the function repeatedly
                                           jT9       Starting with [1, 1]
                                         tQ          and repeating Q - 1 times
                                .iG                  interlace G (input) with
                                     .:G2            All 2 element substrings of G
                                   sM                mapped to their sums.
                 m                                   map over these values
                                                     implicitly cast to ranges
                    m       d                        map over the range values
                                                     impicitly cast to ranges
                     +*\ k\\                         to k spaces followed by
                                                     a backslash.
                   J                                 Save to J, which is roughly:
                                                     \
                                                      \
                  +          yJ                      And add on y(J), giving
                                                     \
                                                      \
                                                      /
                                                     /
                s                                    Combine the half diamonds
                                                     into one list.
              .t                              d      Traspose, filling with ' '.
             K                                       Save to K, giving
                                                     something like:
                                                     \  /
                                                      \/
            y                                        Vertically mirror.
          jb                                         Join on newlines and print.
                                               jK    Join K on (implicitly)
                                                     newlines and print.
isaacg
źródło
1
Jakie są szanse? Ja też dokładnie mają u.iGsM.:G2tQjT9w roztworze moim (częściowego). Nigdy nie spojrzałem na twoją odpowiedź ...
lub
2
@orlp Często istnieje tylko jeden najlepszy sposób na zrobienie czegoś.
isaacg
5

Common Lisp, 425

(labels((a(n)(if(> n 1)(loop for(x y)on(a(1- n))by #'cdr collect x when y collect(+ x y))'(1 1))))(lambda(~ &aux(l(a ~))(h(apply'max l))(w(*(apply'+ l)2))(o(* 2 h))(m(make-array(list o w):initial-element #\ ))(x 0)(y h))(labels((k(^ v)(setf(aref m y x)^(aref m(- o y 1)x)v)(incf x))(d(i)(when(plusp i)(k #\\ #\/)(incf y)(d(1- i))(decf y)(k #\/ #\\))))(mapc #'d l))(dotimes(j o)(fresh-line)(dotimes(i w)(princ(aref m j i))))))

Przykład

(funcall *fun* 4)

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

Nie golfił

(labels
    ((sequence (n)
       (if (> n 1)
           (loop for(x y) on (sequence (1- n)) by #'cdr
                 collect x
                 when y
                   collect(+ x y))
           '(1 1))))
  (defun argyle (input &aux
                  (list (sequence input))
                  (half-height (apply'max list))
                  (width (* (apply '+ list) 2))
                  (height (* 2 half-height))
                  (board (make-array
                          (list height width)
                          :initial-element #\ ))
                  (x 0)
                  (y half-height))
    (labels ((engrave (^ v)
               (setf (aref board y              x) ^ ;; draw UP character
                     (aref board (- height y 1) x) v ;; draw DOWN character (mirrored)
                     )
               (incf x) ;; advance x
               )
             (draw (i)
               (when (plusp i)
                 (engrave #\\ #\/)  ;; write opening "<" shape of diamond
                 (incf y)
                 (draw (1- i))   ;; recursive draw
                 (decf y)
                 (engrave #\/ #\\)  ;; write closing ">" shape of diamond
                 )))
      ;; draw into board for each entry in the sequence
      (mapc #'draw list))

    ;; ACTUAL drawing
    (dotimes(j height)
      (fresh-line)
      (dotimes(i width)
        (princ (aref board j i))))
    board))
rdzeń rdzeniowy
źródło
3

CJam, 59 58 57 bajtów

YXbri({{_2$+\}*]}*:,_:|,S*0'\tf{fm>_W%'\f/'/f*}:+zN*_W%N@

Dzięki @ MartinBüttner za grę w golfa na 1 bajcie.

Wypróbuj online w interpretatorze CJam .

Pomysł

Na przykład dla danych wejściowych 3 generujemy

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

obracając strunę  \i zastępując niektóre ukośniki odwrotne ukośnikami.

Następnie skompresujemy wynikową tablicę (transponujemy wiersze i kolumny), aby uzyskać dolną połowę pożądanego wyniku.

Górna połowa to bajt na bajt równy dolnej połowie w odwrotnej kolejności.

Kod

YXb     e# Push A := [1 1] and 2 in unary.
ri(     e# Read an integer fro STDIN and subtract 1.
{       e# Do the following that many times:
  {     e#   For each I in A but the first:
    _2$ e#     Push a copy of I and the preceding array element.
    +\  e#     Compute the sum of the copies and swap it with I.
  }*    e#
  ]     e#   Collect the entire stack in an array.
}*      e#
:,      e# Replace each I in A with [0 ... I-1].
_       e# Push a copy of A.
:|      e# Perform set union of all the ranges.
,S*     e# Get the length (highest I in A) and push a string of that many spaces.
0'\t    e# Replace the first space with a backslash.
f{      e# For each range in A, push the generated string; then:
  fm>   e#   Rotate the string by each amount in the array.
  _W%   e#   Push a reversed copy of the resulting array of strings.
  '\f/  e#   In each string, split at backslashes.
  '/f*  e#   Join each string, separating with slashes.
}       e#
:+      e# Concatenate the resulting arrays of strings.
zN*     e# Zip and join, separating by linefeeds.
_W%     e# Push a reversed copy of the string.
N@      e# Push a linefeed and rotate the original string on top of it.
Dennis
źródło
1

Rev 1: Ruby 170

Nowa metoda unikania tworzenia dużego diamentu i zmniejszania.

->n{a=[1]
m=1<<n-1
(m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}
(-b=a.max).upto(b-1){|j|0.upto(m){|i|d=' '*q=a[-i]*2
(j*2+1).abs<q&&(d[j%q]=?\\;d[-1-j%q]=?/)   
print d}
puts""}}

Rev 0: Ruby, 187

->n{a=[1]
m=1<<n-1
(m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}
(2*b=a.max).times{|j|
0.upto(m){|i|d=' '*b*2;d[(b+j)%(b*2)]='\\';d[(b-1-j)%(b*2)]=?/
r=b-a[-i]
d.slice!(b-r,r*2)
print d}
puts ""}}

Rozmiary diamentów są obliczane zgodnie z relacją powtarzalności z https://oeis.org/A002487 W ten sposób tworzymy tablicę azawierającą wszystkie elementy dla wszystkich wierszy od 1 do n. Interesują nas tylko ostatnie 1<<n-1elementy (Ruby pozwala nam pobrać je z tablicy przy użyciu indeksów ujemnych, gdzie -1 jest ostatnim elementem w tablicy), a także inital 1z pozycji 0.

Linia po linii i diament za diamentem, rysujemy rząd znaków dla największego diamentu, a następnie wycinamy środkowe kolumny, aby uzyskać rząd wymaganego diamentu. Wersja 1 jest krótsza, ale podobała mi się ta metoda.

Arytmetyka modułowa służy do zawijania, dzięki czemu to samo wyrażenie dodaje wszystko /bezpośrednio, a także jedno wyrażenie dodaje wszystko \bezpośrednio.

Niegolfowany w programie testowym

f=->n{
  a=[1]
  m=1<<n-1
  (m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}                   #concatenate a[i] and a[i]+a[i+1] to the end of a
    (2*b=a.max).times{|j|                                #run through lines (twice the largest number in a
      0.upto(m){|i|                                      #run through an initial '1' plus the last m numbers in a
      d=' '*b*2;d[(b+j)%(b*2)]='\\';d[(b-1-j)%(b*2)]=?/  #d is the correct string for this line of the largest diamond
      r=b-a[-i]                                          #calculate number of characters to be deleted from middle of d
      d.slice!(b-r,r*2)                                  #and delete them
      print d                                            #print the result
    }
    puts ""                                              #at the end of the line, print a newline
  }
}

f.call(gets.to_i)
Level River St
źródło