Стимпанк: Clacker анимация

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

Дублирование этой последовательности заставит фигуру появляться и исчезать.

НММ не Микки Маус

Анимация большего размера может быть составлена ​​не по порядку, указав различные «кадры» в поле последовательности.

   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
Что касается звука, вы думаете о чем-то вроде железнодорожной доски объявлений? Например, доска Solari на вокзале Gare Du Nord в Париже или Split-flap Display - схема самостоятельного вождения . Или вы думаете больше механических звуков реле?
Скотт Лидли

Ответы:

3

Mathematica, 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

Пример Ungolfed Postscript

Это программа в стиле «протокол-пролог», поэтому данные сразу же следуют в том же исходном файле. Анимационные файлы 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