Genera codice Schema piramide


32

Pyramid Scheme è un linguaggio sviluppato da @ ConorO'Brien . In Pyramid Scheme, il codice che scrivi è simile al seguente:

      ^         ^
     / \       /3\
    /   \      ---
   /  +  \
  ^-------^
 /9\     /3\
/123\    ---
-----

Ora, quel codice ha due ovvie qualità: è difficile da analizzare ed è difficile da scrivere. Conor ha risolto il primo, tuttavia sarà tuo compito risolvere il secondo problema.


Il codice precedente viene elaborato dall'interprete PyramidScheme in una matrice di stringhe nidificate, in questo modo:

[["+", ["9123", "3"]], "3"]

Il tuo compito è scrivere un programma o una funzione che fornisca una matrice nidificata di stringhe, produca o restituisca il codice PyramidScheme ricreato. Si può presumere che l'array di input sia sempre valido.

Una piramide è un triangolo isoscele. La parte superiore è ^, i lati si inclinano diagonalmente con /e \, e la parte inferiore è -. I due angoli inferiori sono vuoti o contengono l'inizio di altre piramidi, che sono argomenti. Il centro è pieno del nome della piramide, ignorando le interruzioni di riga.

Ecco come il parser converte il codice in un formato utilizzabile. Innanzitutto, cerca una piramide di livello superiore. Se non accetta argomenti, lo rappresenta con una singola stringa e va avanti. Altrimenti, rappresenta è come un array ["name",[arg1,arg2]]o ["name",[arg1]]. Gli argomenti sono le piramidi in basso a sinistra e in basso a destra della piramide, che possono essere stringhe o più matrici descritte come sopra. Potresti notare che in qualche modo assomiglia a Lisp, nel qual caso potresti anche aver notato il terribile gioco di parole che è il nome della lingua. Dopo che la piramide è stata completamente rappresentata, il parser passa a quello successivo.

Questo è , vince il codice più corto!

Casi di test: questi non sono gli unici output validi, questi sono esempi di output validi.

[["+", ["9123", "3"]], "3"]

      ^         ^
     / \       /3\
    /   \      ---
   /  +  \
  ^-------^
 /9\     /3\
/123\    ---
-----

[["out", [["chr", ["72"]], ["chr", ["101"]]]], ["out", [["chr", ["108"]]]], ["out", [["chr", ["108"]]]], ["out", [["chr", ["111"]]]]]

        ^      ^     ^     ^
       / \    / \   / \   / \
      /out\  /out\ /out\ /out\
     ^-----^ -----^----- -----^
    / \   / \    / \         / \
   /chr\ /chr\  /chr\       /chr\
  ^----- -----^ -----^     ^-----
 / \         / \    / \   / \
/72 \       /101\  /108\ /111\
-----       -----  ----- -----

[ ["+", [ ["asdfghjkl"], ["do", [ "1" ]] ]] ]

       ^
      / \
     / + \
    /     \
   ^-------^
  /a\     /d\
 /sdf\   /o  \
/ghjkl\ ^-----
-------/1\
       ---

Nel secondo caso di test, la seconda e la terza outpiramide hanno entrambe ["chr", ["108"]]un parametro as, che viene compresso in una pila di piramide condivisa da due di livello superiore. Questa è un'ottimizzazione valida che il tuo codice può supportare, ma è completamente opzionale; il punteggio non si basa sulla lunghezza dell'output.

Per i curiosi, il primo caso viene visualizzato a 9126 3causa della stampa implicita di piramidi di livello superiore, il secondo viene stampato Helloe l'ultimo è un errore di sintassi, incluso solo perché ha una struttura ordinata.


Si può supporre che l'ingresso contiene solo ASCII stampabile, esclusi gli spazi, ^, /, \, e -. L'input sarà sempre valido e conterrà almeno una piramide. Non vi è alcun limite alla dimensione dell'array o delle stringhe di input, tuttavia è possibile scrivere il codice come se il tipo intero predefinito della lingua fosse una precisione infinita e che il computer disponga di memoria arbitraria. Se si accetta l'input come singola stringa, è possibile utilizzare qualsiasi cosa ragionevole (virgola, spazio, ecc. Purché sia ​​in ASCII stampabile e non "o []) per delimitare gli array. Non è necessario includere parentesi che circondano l'intera cosa e prendere invece più array separati dal delimitatore.

La tua uscita non deve essere giocata a golf, puoi inserire spazio extra o ingrandire le piramidi del necessario. Le piramidi di Toplevel dovrebbero essere in prima linea. L'output dovrebbe essere una stringa con newline o un elenco di stringhe.

Chiunque fa includere una versione del loro codice che golfs in modo ottimale le piramidi possono ricevere qualche rappresentante in forma di upvotes / premi (ma probabilmente solo upvotes).


8
Sierpinski adorerebbe questa lingua.
mbomb007,

4
Totalmente non ho pubblicato questa sfida perché sono troppo pigro per formattare correttamente i triangoli ...
Pavel

@KodosJohnson L'input può essere un array nativo.
Pavel,

come puoi avere una funzione con più di due argomenti?
Destructible Lemon

@DestructibleWatermelon L'input non conterrà mai un array tale da richiedere il passaggio di due argomenti a una piramide, poiché ciò è impossibile in Pyramid Scheme.
Pavel,

Risposte:


26

Lisp comune - 2524 1890 byte

(defun f(i)(let((s(loop as r in i collect(g r)))(n())(output""))(loop until n do(setf n T)(loop as r in s do(if(cdr r)(progn(setf output(c output(e r))(cdr r)(cdr(cdr r)))(setf n()))(setf output(c output(b(car r))))))(setf output(c output(format()"~%"))))output))(defun g(r)(if(stringp r)(d(m(length r))r)(if(<(length r)2)(d(m(length(car r)))(car r))(if(=(length(e r))1)(let((h(g(car(e r))))(p(d(m(length(car r)))(car r))))(let((o(+ 1(position #\^(e h))))(parent_length(car p)))(if(<(-(car h)o)parent_length)(l(cons(+ o parent_length)())(loop as n in(butlast(cdr p))collect(c(b o)n))(cons(c(subseq(e h)0 o)(car(last p)))())(loop as n in(cdr(cdr h))collect(c n(b (- parent_length(-(car h)o))))))(let((i(-(- o 1)parent_length)))(l(cons(car h)())(loop as n in(butlast(cdr p))collect(c(b o)n(b i)))(cons(c(subseq(nth 1 h)0 o)(car(last p))(b i))())(cddr h))))))(let((l-h(g(car(e r))))(r-h(g(e(e r)))))(let((ll(position #\^(e l-h)))(rl(position #\^(e r-h))))(let((lr(-(car l-h)ll 1))(rr(-(car r-h)rl 1)))(let((p(d(max(m(length(car r)))(ceiling(+ lr rl)2))(car r))))(let((m-pad(if(>(car p)(+ lr rl))(-(car p)lr rl)0)))(l(cons(+ ll 1(car p)1 rr)())(loop as n in(butlast(cdr p))collect(c(b(+ 1 ll))n(b(+ 1 rr))))(cons(c(subseq(e l-h)0(+ 1 ll))(car(last p))(subseq(e r-h)rl))())(loop as y in(append(cddr l-h)(make-list(length l-h):initial-element(b(car l-h))))as z in(append(cdr(cdr r-h))(make-list(length r-h):initial-element(b(car r-h))))collect(c y(b m-pad)z))))))))))))(defun d(r n)(cons(+(* 2 r)1)(l(cons(c(b r)"^"(b r))())(loop as i from 1 to r collect(c(b(- r i))"/"(subseq(c n(b(expt i 2)))(expt(- i 1)2)(expt i 2))"\\"(b(- r i))))(cons(make-string(+ 1(* 2 r)):initial-element #\-)()))))(defun m(l)(+ 1(floor(sqrt l))))(defun b(n)(make-string n :initial-element #\space))(defun c(&rest a)(apply 'concatenate 'string a))(defun l(&rest a)(apply 'concatenate 'list a))(defun e(tree)(nth 1 tree))

Grazie a @coredump per una serie di trucchi per il golf. Esempio di output della domanda:

> (f '(("out" (("chr" ("72")) ("chr" ("101")))) ("out" (("chr" ("108")))) ("out" (("chr" ("108")))) ("out" (("chr" ("111"))))))
          ^               ^          ^          ^  
         /o\             /o\        /o\        /o\ 
        /ut \           /ut \      /ut \      /ut \
       /     \         ^-----     ^-----     ^-----
      /       \       /c\        /c\        /c\    
     ^---------^     /hr \      /hr \      /hr \   
    /c\       /c\   ^-----     ^-----     ^-----   
   /hr \     /hr \ /1\        /1\        /1\       
  ^-----    ^-----/08 \      /08 \      /11 \      
 /7\       /1\    -----      -----      -----      
/2  \     /01 \                                    
-----     -----                                    










> (f '( ("+" ( ("asdfghjkl") ("do" ( "1" )) )) ))
          ^        
         /+\       
        /   \      
       /     \     
      /       \    
     /         \   
    ^-----------^  
   /a\         /d\ 
  /sdf\       /o  \
 /ghjkl\     ^-----
/       \   /1\    
---------  /   \   
           -----   








> (f '(("+" ("9123" "3")) "3"))
       ^        ^  
      /+\      /3\ 
     /   \    /   \
    /     \   -----
   ^-------^       
  /9\     /3\      
 /123\   /   \     
/     \  -----     
-------            

Ecco la versione originale (per lo più) non golfizzata:

(defun f (input)
    (let ((trees (loop for tree in input collect (g tree)))
          (done nil)
          (output ""))
        (loop while (not done)
            do  (setf done T) 
                (loop for tree in trees
                    do  (if (cdr tree)
                            (progn
                                (setf output (conStr output (car (cdr tree))))
                                (setf (cdr tree) (cdr (cdr tree)))
                                (setf done nil))
                            (setf output (conStr output (blank (car tree))))))
                (setf output (conStr output  (format nil "~%"))))
        output))

;creates a single tree
;output is a list, first element is the length of each line, the rest are the lines of text
(defun g (tree)
    (if (stringp tree)
        ;strings should be drawn as just the pyramid for the name
        (draw-body (min-rows (length tree)) tree)

        (if (< (length tree) 2)
            ;lists with no arguments should be drawn as just the pyramid for the name
            (draw-body (min-rows (length (car tree))) (car tree))
            (if (= (length (car (cdr tree))) 1)
                ;single child
                (let ((child (g (car (car (cdr tree))))) (parent (draw-body (min-rows (length (car tree))) (car tree))))
                    (let ((parent_offset (+ 1 (position #\^ (first-line child)))) (parent_length (car parent)))
                        (if (< (- (car child) parent_offset) parent_length)
                            (let ((child-fill (- parent_length (- (car child) parent_offset))))
                                (concatenate 'list 
                                    (cons (+ parent_offset parent_length) nil)
                                    (loop for line in (butlast (cdr parent))
                                        collect (conStr (blank parent_offset) line))
                                    (cons (conStr (subseq (nth 1 child) 0 parent_offset) (car (last parent))) nil)
                                    (loop for line in (cdr (cdr child))
                                        collect (conStr line (blank child-fill)))))
                            (let ((parent-fill (- (- parent_offset 1) parent_length)))
                                (concatenate 'list 
                                    (cons (car child) nil)
                                    (loop for line in (butlast (cdr parent))
                                        collect (conStr (blank parent_offset) line (blank parent-fill)))
                                    (cons (conStr (subseq (nth 1 child) 0 parent_offset) (car (last parent)) (blank parent-fill)) nil)
                                    (cdr (cdr child)))))))
                ;two children
                (let ((l-child (g (car (car (cdr tree))))) (r-child (g (car (cdr (car (cdr tree)))))))
                    (let ((lc-l-width (position #\^ (first-line l-child))) (rc-l-width (position #\^ (first-line r-child))))
                        (let ((lc-r-width (- (car l-child) lc-l-width 1)) (rc-r-width (- (car r-child) rc-l-width 1)))
                            (let ((parent (draw-body (max (min-rows (length (car tree))) (ceiling (+ lc-r-width rc-l-width) 2)) (car tree))))
                                (let ((m-pad (if (> (car parent) (+ lc-r-width rc-l-width))
                                            (- (car parent) lc-r-width rc-l-width)
                                            0)))
                                    (concatenate 'list
                                        (cons (+ lc-l-width 1 (car parent) 1 rc-r-width) nil)
                                        (loop for line in (butlast (cdr parent))
                                            collect (conStr (blank (+ 1 lc-l-width)) line (blank (+ 1 rc-r-width))))
                                        (cons (conStr (subseq (first-line l-child) 0 (+ 1 lc-l-width)) (car (last parent)) (subseq (first-line r-child) rc-l-width)) nil)
                                        (loop for left in (append (cdr (cdr l-child)) (make-list (length l-child) :initial-element (blank (car l-child))))
                                            for right in (append (cdr (cdr r-child)) (make-list (length r-child) :initial-element (blank (car r-child))))
                                            collect (conStr left (blank m-pad) right))))))))))))


;create a single pyramid
; output is a list, first element is the length of each line, the rest are the lines of text
(defun draw-body (rows name)
    (print rows)
    (print name)
    (cons (+ (* 2 rows) 1)
        (concatenate 'list (cons (conStr (blank rows) "^" (blank rows)) nil)
            (loop for i from 1 to rows
                collect (conStr (blank (- rows i)) "/" (subseq (conStr name (blank (expt i 2))) (expt (- i 1) 2) (expt i 2)) "\\" (blank (- rows i))))
            (cons (make-string (+ 1 (* 2 rows)) :initial-element #\-) nil))))

(defun min-rows (l)
    (+ 1 (floor (sqrt l))))

(defun blank (n)
    (make-string n :initial-element #\space))

(defun conStr (&rest args)
    (apply 'concatenate 'string args))

(defun first-line (tree)
    (car (cdr tree)))

Provalo online!


Dovresti essere in grado di giocare a golf molti byte rimuovendo gli spazi non necessari.
clismique,

2
Benvenuti in PPCG e bella prima risposta!
Kritixi Lithos,

Alcuni consigli per giocare a golf CL: nei loop, "for" può anche essere scritto "as"; puoi rimuovere spazi prima e dopo parentesi e virgolette doppie; puoi sostituire NIL con (); puoi anche usare le variabili del lettore, a volte
coredump il

... loop while (not x)è loop until x, (cdr (cdr x))è (cddr x), (setf a b c d)è più breve di(setf a b) seguito (setf c d), ecc. Ma questa è già una buona risposta
coredump,

2
Una generosità totale di 350 reputazione è significativa ... ma questa risposta merita. Una risposta Lisp comune a una domanda sulla costruzione di domande per un dialetto Lisp ... Wow.
wizzwizz4,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.