Steampunk: animazione di Clacker


11

Nel romanzo di Steampunk, altamente sottovalutato, The Difference Engine , l'equivalente delle sale cinematografiche forniva un'immagine in movimento pixelata visualizzata da tessere che potevano essere girate meccanicamente. Il motore di controllo per orchestrare il movimento di queste tessere era una grande macchina rumorosa controllata da un mazzo di carte perforate.

Il tuo compito è emulare tale motore e visualizzare un'animazione pixelata come specificato da un file di input. L'input è costituito da linee in un formato a larghezza fissa, ma si può presumere qualunque cosa sia conveniente per un'indicazione di fine riga. Il formato è:

SSSSYYxxXXOA
SSSS: 4 digit sequence no. may be padded by blanks or all blank
    YY: the y coordinate affected by this line (descending, top is 0, bottom is m-1)
      xx: the starting x coordinate
        XX: the ending x coordinate
          O: hexadecimal opcode
           A: argument (0 or 1)

L'input è esplicitamente sequenziato (se lasci cadere il tuo mazzo di carte sul pavimento, mi ringrazierai per questa parte). Ciò significa che il programma deve eseguire un ordinamento stabile delle righe di input utilizzando il campo sequenza come chiave di ordinamento. Le righe con lo stesso numero di sequenza devono mantenere il loro ordinamento relativo originale. (Dovrebbe funzionare con un ordinamento instabile, se si aggiunge il numero di riga effettivo alla chiave.) Un campo di sequenza vuoto deve essere interpretato come inferiore a qualsiasi numero (sequenza di confronto ASCII).

Una singola riga di istruzione può influire solo su una singola coordinata y, ma può specificare un intervallo contiguo di valori x. Il valore x finale può essere lasciato in bianco o potrebbe essere identico al valore iniziale per influire su un singolo pixel.

Il codice operativo è una cifra esadecimale che specifica il codice di funzione binaria universale utilizzato come rasterop. L'argomento è 0 o 1. L'operazione raster eseguita è

pixel = pixel OP argument          infix expression
         --or-- 
        OP(pixel, argument)        function call expression

Quindi il valore originale del pixel viene inserito come X nella tabella UBF e il valore dell'argomento dall'istruzione viene inserito come Y. Il risultato di questa funzione è il nuovo valore del pixel. E questa operazione viene eseguita su ogni coppia x, y da xx, YY a XX, YY specificata nell'istruzione. L'intervallo specificato da xx e XX include entrambi i punti finali. Così

0000 0 010F1

dovrebbe impostare pixel 0,1,2,3,4,5,6,7,8,9,10 sulla riga 0.

Le dimensioni di uscita ( m x n ) devono essere almeno 20 x 20, ma possono essere più grandi se lo si desidera. Ma il grano dovrebbe mostrare, sai? Dovrebbe essere pixelato . Sono accettabili sia l'output grafico che quello ASCII.

Se, ad esempio, volessimo creare un'immagine di una figura pixelata:

  #   #
   ###
   ##
   ####
    #
#### ####
   # #

   ###
   # #
   # #

Se lo disegniamo con un'opzione che lancia bit, come XOR, può essere disegnato e cancellato indipendentemente dal fatto che lo schermo sia bianco o nero.

    00020261
     0 6 661
     1 3 561
     2 3 461
     3 3 661
     4 4 461
     5 0 361
     5 5 861
     6 3 361
     6 5 561
     8 3 561
     9 3 361
     9 5 561
    10 3 361
    10 5 561

La duplicazione di questa sequenza farà apparire e scomparire la figura.

NMM non è Topolino

Un'animazione più grande può essere composta fuori servizio, specificando diversi "scatti" nel campo sequenza.

   100 016F0
   101 016F0
   102 016F0
   103 016F0
   104 016F0
   105 016F0
   106 016F0
   107 016F0
   108 016F0
   109 016F0
   110 016F0
   111 016F0
   112 016F0
   113 016F0
   114 016F0
   115 016F0
   200020261
   2 0 6 661
   2 1 3 561
   2 2 3 461
   2 3 3 661
   2 4 4 461
   2 5 0 361
   2 5 5 861
   2 6 3 361
   2 6 5 561
   2 8 3 561
   2 9 3 361
   2 9 5 561
   210 3 361
   210 5 561
    00020261
     0 6 661
     1 3 561
     2 3 461
     3 3 661
     4 4 461
     5 0 361
     5 5 861
     6 3 361
     6 5 561
     8 3 561
     9 3 361
     9 5 561
    10 3 361
    10 5 561
   300020261
   3 0 6 661
   3 1 3 561
   3 2 3 461
   3 3 3 661
   3 4 4 461
   3 5 0 361
   3 5 5 861
   3 6 3 361
   3 6 5 561
   3 8 3 561
   3 9 3 361
   3 9 5 561
   310 3 361
   310 5 561
    00020261
     0 6 661
     1 3 561
     2 3 461
     3 3 661
     4 4 461
     5 0 361
     5 5 861
     6 3 361
     6 5 561
     8 3 561
     9 3 361
     9 5 561
    10 3 361
    10 5 561

Produrre:

nero / bianco vs bianco / nero

Questo è quindi il programma più breve (per byte) vince. Bonus (-50) se il motore emette rumori di click-clack.


3
Normalmente si richiedono chiarimenti inviando alla sandbox. Stai cercando di chiudere la sandbox?
John Dvorak,

5
Personalmente, i sandbox sono un vicolo cieco. Sono troppo bravo a procrastinare per finirli. Qui, dal vivo, non posso ignorare il fuoco sotto il mio sedere.
luser droog

1
Come funziona il connettore booleano? Unisce solo le linee con lo stesso numero progressivo? Se sono misti, esiste una qualche forma di precedenza per l'operatore? Avete dei casi di test che si basano su connettori booleani? Perché il caso di test che hai pubblicato non ha numeri di sequenza? Il xcoord finale è sempre inclusivo?
Peter Taylor,

5
Ecco alcuni rumori di rumore di clic . Ricevo un bonus? ;-)
Digital Trauma,

1
Per quanto riguarda il suono, stai pensando a qualcosa come la lavagna della stazione ferroviaria? Ad esempio la scheda solare presso la stazione ferroviaria Gare du Nord di Parigi o Display a ribalta - Circuito driver fai-da-te . O stai pensando più suoni di relè meccanici?
Scott Leadley,

Risposte:


3

Mathematica, 306 281 byte

Questo si aspetta che la stringa di input sia archiviata in una variabile i

ListAnimate[ArrayPlot/@FoldList[({n,y,x,X,o,a}=#2;MapAt[IntegerDigits[o,2,4][[-1-FromDigits[{#,a},2]]]&,#,{y+1,x+1;;X+1}])&,Array[0&,{20,20}],ToExpression/@MapAt["16^^"<>#&,StringTrim/@SortBy[i~StringSplit~"\n"~StringCases~RegularExpression@"^....|..(?!.?$)|.",{#[[1]]&}],{;;,5}]]]

E qui con alcuni spazi bianchi:

ListAnimate[ArrayPlot /@ FoldList[(
     {n, y, x, X, o, a} = #2;
     MapAt[
      IntegerDigits[o, 2, 4][[-1 - FromDigits[{#, a}, 2]]] &,
      #,
      {y + 1, x + 1 ;; X + 1}
      ]
     ) &,
   Array[0 &, {20, 20}],
   ToExpression /@ 
    MapAt["16^^" <> # &, 
     StringTrim /@ 
      SortBy[i~StringSplit~"\n"~StringCases~
        RegularExpression@"^....|..(?!.?$)|.", {#[[1]] &}], {;; , 5}]
   ]]

Questo è diventato piuttosto dannatamente lungo. Questa sfida conteneva molti dettagli difficili, e in particolare l'analisi dell'input richiede molto codice in Mathematica (quasi la metà, 137 byte, sta solo analizzando l'input). Ho finito per cambiare la lingua due volte prima di optare per Mathematica (pensavo di poter salvare l'input di analisi usando Ruby, ma poi ho capito che il risultato deve essere animato , quindi sono tornato a Mathematica).


2

Esempio Postscript non golfato

Questo è un programma in stile "protocollo-prolog", quindi i dati seguono immediatamente nello stesso file sorgente. File GIF animati possono essere prodotti con ImageMagick di convertutilità (usa Ghostscript): convert clack.ps clack.gif.

%%BoundingBox: 0 0 321 321

/t { token pop exch pop } def
/min { 2 copy gt { exch } if pop } def
/max { 2 copy lt { exch } if pop } def

/m [ 20 { 20 string }repeat ] def
/draw { change {
        m {} forall 20 20 8 [ .0625 0 0 .0625 0 0 ] {} image showpage
    } if } def

%insertion sort from https://groups.google.com/d/topic/comp.lang.postscript/5nDEslzC-vg/discussion
% array greater_function insertionsort array
/insertionsort
{ 1 1 3 index length 1 sub
    { 2 index 1 index get exch % v, j
        { dup 0 eq {exit} if
            3 index 1 index 1 sub get 2 index 4 index exec
            {3 index 1 index 2 copy 1 sub get put 1 sub}
            {exit} ifelse
        } loop
        exch 3 index 3 1 roll put
    } for
    pop
} def

/process {
    x X min 1 x X max { % change? x
        m y get exch  % row-str x_i
        2 copy get  % r x r_x 
        dup         % r x r_x r_x
        0 eq { 0 }{ 1 } ifelse  % r x r_x b(x)
        2 mul a add f exch neg bitshift 1 and   % r x r_x f(x,a)
        0 eq { 0 }{ 255 } ifelse  % r x r_x c(f)
        exch 1 index % r x c(f) r_x c(f)
        ne { /change true def } if
        put
    } for
    draw
} def

{ [ {
     currentfile 15 string
         dup 2 13 getinterval exch 3 1 roll
         readline not{pop pop exit}if
    pop
    [ exch
     /b exch dup 0 1 getinterval exch
     /n exch dup 1 1 getinterval exch
     /seq exch dup 2 4 getinterval exch
     /y exch dup 6 2 getinterval t exch
     /x exch dup 8 2 getinterval t exch
     /X exch dup 10 2 getinterval dup (  ) ne { t exch }{pop 2 index exch} ifelse
     /f exch dup 12 get (16#?) dup 3 4 3 roll put t exch
     /a exch 13 get 48 sub
     /change false def
    >>
}loop ]
dup { /seq get exch /seq get exch gt } insertionsort
true exch
{ begin
    b(A)eq{
        { process } if
    }{
        b(O)eq{
            not { process } if
        }{
            pop
            process
        }ifelse
    }ifelse
    change
    end
} forall
    draw
} exec
   100 016F0
   101 016F0
   102 016F0
   103 016F0
   104 016F0
   105 016F0
   106 016F0
   107 016F0
   108 016F0
   109 016F0
   110 016F0
   111 016F0
   112 016F0
   113 016F0
   114 016F0
   115 016F0
   200020261
   2 0 6 661
   2 1 3 561
   2 2 3 461
   2 3 3 661
   2 4 4 461
   2 5 0 361
   2 5 5 861
   2 6 3 361
   2 6 5 561
   2 8 3 561
   2 9 3 361
   2 9 5 561
   210 3 361
   210 5 561
    00020261
     0 6 661
     1 3 561
     2 3 461
     3 3 661
     4 4 461
     5 0 361
     5 5 861
     6 3 361
     6 5 561
     8 3 561
     9 3 361
     9 5 561
    10 3 361
    10 5 561
   300020261
   3 0 6 661
   3 1 3 561
   3 2 3 461
   3 3 3 661
   3 4 4 461
   3 5 0 361
   3 5 5 861
   3 6 3 361
   3 6 5 561
   3 8 3 561
   3 9 3 361
   3 9 5 561
   310 3 361
   310 5 561
    00020261
     0 6 661
     1 3 561
     2 3 461
     3 3 661
     4 4 461
     5 0 361
     5 5 861
     6 3 361
     6 5 561
     8 3 561
     9 3 361
     9 5 561
    10 3 361
    10 5 561
0000 0 515F1
0000 1 11501
0000 1 115F1

Le informazioni sul rettangolo di selezione sono state scoperte eseguendo gs -sDEVICE=bbox clack.ps.
luser droog,
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.