Стімпанк: анімація Клакер


11

У романі з сильно заниженим Стімпанку "Двигун різниці " еквівалент кінотеатрів поставив пікселізоване рухоме зображення, відображене плитками, які можна було перевернути механічно. Двигун управління для оркестрування руху цих плиток був великою галасливою машиною, керованою колодою перфокарт.

Ваше завдання - емуляція такого двигуна та показ пікселізованої анімації, визначеної вхідним файлом. Вхід складається з рядків у форматі фіксованої ширини, але ви можете вважати, що зручно для індикації закінчення рядка. Формат:

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)

Вхід явно послідовно (якщо ви коли-небудь скинете колоду карт на підлогу, ви подякуєте мені за цю частину). Це означає, що програма повинна виконувати стабільний тип рядків введення, використовуючи поле послідовності як ключ сортування. Рядки з однаковим порядковим номером повинні підтримувати своє початкове відносне впорядкування. (Це повинно працювати з нестабільним сортуванням, якщо ви додасте фактичний номер рядка до клавіші.) Поле порожньої послідовності повинно бути інтерпретоване як менше, ніж будь-яке число (послідовність співставлення ascii).

Один рядок оператора може впливати лише на одну координату y, але може задавати суміжний діапазон значень x. Значення закінчення x може залишатися порожнім або може бути ідентичним початковому значенню для впливу на один піксель.

Опкод - це шістнадцяткова цифра, яка вказує Універсальний двійковий код функції, який використовується як растероп. Аргумент 0 або 1. Виконана растрова операція є

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

Тож початкове значення пікселя вводиться як X у таблиці UBF, а значення аргументу з оператора вводиться як Y. Результатом цієї функції є нове значення пікселя. І ця операція виконується для кожної пари x, y від xx, YY до XX, YY, зазначених у виписці. Діапазон, визначений xx та XX, включає обидві кінцеві точки. Так

0000 0 010F1

слід встановити пікселі 0,1,2,3,4,5,6,7,8,9,10 у рядку 0.

Вихідні розміри ( m x n ) повинні бути як мінімум 20 x 20, але можуть бути більшими за бажанням. Але зерно повинно показати, знаєте? Він повинен бути пікселізованим . Як графічний, так і ASCII-графічний вихід є прийнятними.

Якщо, наприклад, ми хотіли зробити зображення пікселізованої фігури:

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

   ###
   # #
   # #

Якщо ми намалюємо його з дещо перегортаючим виглядом, як XOR, він може бути намальований і стертий незалежно від того, екран чи чорний або білий.

    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

Дублювання цієї послідовності призведе до того, що фігура з’явиться і зникне.

NMM - це не Мікі Маус

Більшу анімацію можна скласти поза порядком, вказавши в полі послідовності різні "кадри".

   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

Виробництво:

чорний / білий проти білий / чорний

Це тому найкоротша програма (за кількістю байтів) виграє. Бонус (-50), якщо двигун видає шум клацання клацанням.


3
Зазвичай кожен вимагає роз'яснення, розмістивши його в пісочниці. Ви намагаєтесь вимкнути пісочницю?
Іван Дворак

5
Для мене особисто пісочниці - тупик. Я занадто хороший у зволіканні, щоб закінчити їх. Ось, живі, я не можу ігнорувати вогонь під дупкою.
luser droog

1
Як працює булевий роз'єм? Чи приєднується він лише до рядків з однаковим порядковим номером? Якщо вони змішані, чи існує якась форма переваги оператора? Чи є у вас тестові випадки, які покладаються на булеві роз'єми? Чому в тестовому випадку, який ви розмістили, немає жодних порядкових номерів? Чи xзавжди координата закінчення завжди включена?
Пітер Тейлор

5
Ось кілька галасливих шумів клак . Чи отримую я бонус? ;-)
Цифрова травма

1
Що стосується звуку, ви думаєте щось на зразок фліпбордів залізничного вокзалу? Наприклад, дошка для солярів на залізничному вокзалі в Нор-Парі в Парижі або на дисплеї з роздвоєним клаптем - схема самостійного водія . Або ти думаєш більше механічних звуків ретрансляції?
Скотт Лідлі

Відповіді:


3

Математика, 306 281 байт

Це очікує, що вхідний рядок буде збережений у змінній 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}]]]

І ось з пробілом:

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

Це було досить чортово довго. Цей виклик містив безліч чудернацьких деталей, і, особливо, вхідний аналіз займає багато коду в Mathematica (майже половина його, 137 байт, просто розбирає вхід). Я закінчив перемикати мову двічі перед тим, як влаштуватися на Mathematica (я думав, що можу заощадити на синтаксичному розборі за допомогою Ruby, але потім зрозумів, що результат потрібно анімувати , тому повернувся до Mathematica).


2

Приклад безгольового допису

Це програма "протокол-пролог", тому дані негайно випливають у тому самому вихідному файлі. Анімаційні файли GIF можуть бути зроблені з ImageMagick в convertкорисності (використовує 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

Інформація про обмежувальну скриньку була виявлена ​​за допомогою запуску gs -sDEVICE=bbox clack.ps.
luser droog
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.