Steampunk: Clacker animasyonu


11

Oldukça küçültülmüş Steampunk romanı The Difference Engine'de , sinema evlerinin eşdeğeri, mekanik olarak çevrilebilen karolar tarafından görüntülenen pikselli hareketli bir görüntü verdi. Bu karoların hareketini düzenlemek için kontrol motoru, delikli kart destesi tarafından kontrol edilen büyük bir gürültülü makineydi.

Göreviniz böyle bir motoru taklit etmek ve bir girdi dosyası tarafından belirtilen pikselli bir animasyonu görüntülemek. Giriş, sabit genişlikli formattaki satırlardan oluşur, ancak satır sonu göstergesi için neyin uygun olduğunu varsayabilirsiniz. Biçim:

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)

Giriş açıkça sıralanmıştır (eğer kart destenizi yere bırakırsanız, bu bölüm için bana teşekkür edersiniz). Bu, programın, sıralama alanını bir sıralama anahtarı olarak kullanarak giriş satırlarının sabit bir türünü gerçekleştirmesi gerektiği anlamına gelir. Aynı sıra numarasına sahip satırlar orijinal göreli sıralarını korumalıdır. (Eğer anahtara gerçek satır numarasını eklerseniz kararsız bir sıralama ile çalışmalıdır.) Boş bir sıra alanı herhangi bir sayıdan daha düşük olarak yorumlanmalıdır (ascii harmanlama sırası).

Tek bir ifade satırı yalnızca tek bir y koordinatını etkileyebilir, ancak bitişik bir x değeri aralığı belirleyebilir. Bitiş x değeri boş bırakılabilir veya tek bir pikseli etkilemek için başlangıç ​​değeri ile aynı olabilir.

Opcode, rasterop olarak kullanılan Evrensel İkili İşlev Kodunu belirten onaltılık bir rakamdır. Argüman 0 veya 1'dir. Gerçekleştirilen tarama işlemi

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

Böylece, pikselin orijinal değeri UBF tablosuna X olarak girilir ve ifadedeki argüman değeri Y olarak girilir. Bu işlevin sonucu, pikselin yeni değeridir. Ve bu işlem, ifadede belirtilen her bir x, y çifti üzerinde xx, YY - XX, YY arasında gerçekleştirilir. Xx ve XX ile belirtilen aralık her iki bitiş noktasını da içerir. Yani

0000 0 010F1

0 satırında 0,1,2,3,4,5,6,7,8,9,10 piksel ayarlamalıdır.

Çıktı boyutları ( m x n ) minimum 20 x 20 olmalıdır, ancak istenirse daha büyük olabilir. Ama tahıl göstermeli, biliyor musun? Pikselli olması gerekiyordu . Hem grafik hem de ASCII-art çıktı kabul edilebilir.

Örneğin, pikselli bir şeklin resmini yapmak isteseydik:

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

   ###
   # #
   # #

Onu XOR gibi biraz saydam bir op ile çizersek, ekranın siyah veya beyaz olmasına bakılmaksızın çizilebilir ve silinebilir.

    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

Bu dizinin çoğaltılması rakamın görünmesini ve kaybolmasını sağlayacaktır.

NMM Mickey Mouse Değil

Dizi alanında farklı "çekimler" belirtilerek daha büyük bir animasyon sıra dışı oluşturulabilir.

   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

üreten:

siyah / beyaz vs beyaz / siyah

Bu çok kısa bir program (byte-count) kazanır. Motor tıkırtı sesi çıkarırsa bonus (-50).


3
Normalde bir kişi sanal alana göndererek açıklama ister. Korumalı alanı kapatmaya mı çalışıyorsunuz?
John Dvorak

5
Şahsen benim için kum havuzları çıkmaz sokak. Onları bitirmek için ertelemede çok iyiyim. Burada yaşa, kıçımın altındaki ateşi görmezden gelemem.
luser droog

1
Boolean konektörü nasıl çalışır? Yalnızca aynı sıra numarasına sahip satırları birleştiriyor mu? Karıştırılırlarsa, bir tür operatör önceliği var mı? Boolean konektörlerine dayanan test durumunuz var mı? Gönderdiğiniz test senaryosunda neden sıra numarası yok? Bitiş xkoordinatı her zaman kapsayıcı mı?
Peter Taylor

5
İşte bazı tıkırtı sesler . Bonus alır mıyım? ;-)
Dijital Travma

1
Ses için, tren istasyonu panosu gibi bir şey mi düşünüyorsunuz? Paris'te gare du nord tren istasyonunda eg solary kurulu veya Split flap Ekran - DIY sürücü devresi . Yoksa daha fazla mekanik röle sesi mi düşünüyorsunuz?
Scott Leadley

Yanıtlar:


3

Mathematica, 306 281 bayt

Bu, giriş dizesinin değişken içinde saklanmasını bekler 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}]]]

Ve burada bazı boşluklarla:

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

Bu çok uzun sürdü. Bu zorluk çok fazla ayrıntı içeriyordu ve özellikle girdi ayrıştırma işlemi Mathematica'da çok fazla kod gerektiriyor (neredeyse yarısı, 137 bayt, girdiyi ayrıştırıyor). Mathematica'ya yerleşmeden önce dili iki kez değiştirdim (Ruby kullanarak giriş ayrıştırma işleminden tasarruf edebileceğimi düşündüm, ancak daha sonra sonucun canlandırılması gerektiğini fark ettim , bu yüzden Mathematica'ya geri döndüm).


2

Ungolfed Postscript örneği

Bu bir "protokol-prolog" tarzı programdır, bu nedenle veriler hemen aynı kaynak dosyada izler. Animasyon gif dosyaları ImageMagick en ile üretilebilir convertyarar (kullanımları 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

Sınırlayıcı kutu bilgisi çalıştırılarak keşfedildi gs -sDEVICE=bbox clack.ps.
luser droog
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.