Steampunk: Animasi Clacker

11

Dalam novel Steampunk yang sangat diremehkan, The Difference Engine , setara dengan rumah bioskop menghasilkan gambar bergerak pixelated yang ditampilkan oleh ubin yang bisa diputar secara mekanis. Mesin kontrol untuk mengatur pergerakan ubin ini adalah mesin berisik besar yang dikendalikan oleh setumpuk kartu berlubang.

Tugas Anda adalah meniru mesin seperti itu dan menampilkan animasi pixelated seperti yang ditentukan oleh file input. Input terdiri dari garis-garis dalam format lebar-tetap, tetapi Anda dapat mengasumsikan apa pun yang sesuai untuk indikasi akhir baris. Formatnya adalah:

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)

Input secara eksplisit diurutkan (jika Anda pernah menjatuhkan setumpuk kartu di lantai, Anda akan berterima kasih kepada saya untuk bagian ini). Itu berarti program harus melakukan semacam garis input stabil menggunakan bidang urutan sebagai kunci pengurutan. Garis dengan nomor urut yang sama harus mempertahankan urutan relatif aslinya. (Ini harus bekerja dengan pengurutan yang tidak stabil, jika Anda menambahkan nomor baris aktual ke kunci.) Bidang urutan kosong harus ditafsirkan lebih rendah daripada angka apa pun (urutan pengumpulan ascii).

Baris pernyataan tunggal hanya dapat memengaruhi koordinat y tunggal, tetapi dapat menentukan rentang nilai x yang berdekatan. Nilai x akhir dapat dibiarkan kosong atau mungkin identik dengan nilai awal untuk mempengaruhi satu piksel.

Opcode adalah digit heksadesimal yang menentukan Kode Fungsi Biner Universal yang digunakan sebagai rasterop. Argumennya adalah 0 atau 1. Operasi raster yang dilakukan adalah

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

Jadi nilai asli piksel masuk sebagai X dalam tabel UBF, dan nilai argumen dari pernyataan masuk sebagai Y. Hasil fungsi ini adalah nilai baru piksel. Dan operasi ini dilakukan pada setiap pasangan x, y dari xx, YY ke XX, YY yang ditentukan dalam pernyataan. Rentang yang ditentukan oleh xx dan XX mencakup titik akhir. Begitu

0000 0 010F1

harus menetapkan piksel 0,1,2,3,4,5,6,7,8,9,10 pada baris 0.

Dimensi keluaran ( m x n ) minimal harus 20 x 20, tetapi mungkin lebih besar jika diinginkan. Tapi biji - bijian harus menunjukkan, Anda tahu? Seharusnya pixelated . Output grafis dan ASCII-art dapat diterima.

Jika misalnya, kami ingin membuat gambar dari gambar pixel:

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

   ###
   # #
   # #

Jika kita menggambarnya dengan op yang sedikit terbalik, seperti XOR, itu dapat ditarik dan dihapus terlepas dari apakah layarnya hitam atau putih.

    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

Menggandakan urutan ini akan membuat gambar muncul dan menghilang.

NMM bukan Mickey Mouse

Animasi yang lebih besar dapat dibuat tidak berurutan, dengan menentukan "bidikan" yang berbeda di bidang urutan.

   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

Memproduksi:

hitam / putih vs putih / hitam

Ini adalah sehingga program tersingkat (berdasarkan byte) menang. Bonus (-50) jika mesin mengeluarkan bunyi klik-klak.

luser droog
sumber
3
Biasanya satu meminta klarifikasi dengan memposting ke kotak pasir. Apakah Anda mencoba menutup kotak pasir?
John Dvorak
5
Bagi saya pribadi, kotak pasir adalah jalan buntu. Saya terlalu pandai menunda-nunda untuk menyelesaikannya. Di sini, hidup, aku tidak bisa mengabaikan api di bawah pantatku.
luser droog
1
Bagaimana cara kerja konektor Boolean? Apakah hanya digabungkan dengan nomor urut yang sama? Jika mereka dicampur, apakah ada beberapa bentuk prioritas operator? Apakah Anda memiliki test case yang mengandalkan konektor Boolean? Mengapa kasing yang Anda poskan tidak memiliki nomor urut? Apakah xcoord akhir selalu inklusif?
Peter Taylor
5
Berikut adalah beberapa bunyi klik klak . Apakah saya mendapat bonus? ;-)
Trauma Digital
1
Untuk suara, apakah Anda memikirkan sesuatu seperti papan tulis stasiun kereta? Misalnya papan solari di stasiun kereta gare du nord di paris atau Split-flap Display - sirkuit driver DIY . Atau Anda berpikir lebih banyak suara relai mekanis?
Scott Leadley

Jawaban:

3

Mathematica, 306 281 byte

Ini mengharapkan string input disimpan dalam variabel 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}]]]

Dan di sini dengan spasi putih:

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}]
   ]]

Ini jadi sangat lama. Tantangan ini berisi banyak detail fiddly, dan terutama parsing input membutuhkan banyak kode dalam Mathematica (hampir setengahnya, 137 byte, hanya mengurai input). Saya akhirnya beralih bahasa dua kali sebelum menetap di Mathematica (saya pikir saya bisa menghemat input parsing dengan menggunakan Ruby, tetapi kemudian saya menyadari hasilnya perlu dianimasikan , jadi saya kembali ke Mathematica).

Martin Ender
sumber
2

Contoh Postscript yang Tidak Disatukan

Ini adalah program gaya "protokol-prolog", sehingga data segera mengikuti dalam file sumber yang sama. File gif animasi dapat diproduksi dengan ImageMagick ini convertutilitas (kegunaan 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
luser droog
sumber
Info kotak pembatas ditemukan dengan menjalankan gs -sDEVICE=bbox clack.ps.
luser droog