Пьяный епископ

42

В криптографии с открытым ключом отпечаток открытого ключа - это короткая последовательность байтов, используемая для идентификации более длинного открытого ключа.

В частности, в SSH их можно использовать для проверки того, что сервер на самом деле является сервером, с которым я ожидаю установить связь, и на меня не нацелена атака «человек посередине».

Обычно они представлены в виде строки шестнадцатеричных цифр, поэтому сравнивать их с отпечатком пальца может быть довольно скучно и утомительно:

37:e4:6a:2d:48:38:1a:0a:f3:72:6d:d9:17:6b:bd:5e

Чтобы сделать это немного проще, OpenSSH представила метод визуализации отпечатков пальцев как ASCII-арт, который будет выглядеть следующим образом:

+-----------------+
|                 |
|                 |
|          .      |
|     .   o       |
|o . o . S +      |
|.+ + = . B .     |
|o + + o B o E    |
| o .   + . o     |
|         .o      |
+-----------------+

При этом я мог бы попытаться вспомнить грубую форму искусства ASCII и затем (теоретически) распознать его, когда отпечаток пальца сервера изменился и изображение выглядит иначе.

Как это работает

Взято из Дирк Лосс, Тобиас Лиммер, Александр фон Гернлер. 2009. Пьяный епископ: анализ алгоритма визуализации отпечатков пальцев OpenSSH .

Сетка имеет ширину 17 символов и высоту 9 символов. «Епископ» начинается в строке 4 / колонке 8 (в центре). Каждую позицию можно обозначить как [x, y], то есть [8,4] для начальной позиции слона.

            1111111
  01234567890123456
 +-----------------+
0|                 |
1|                 |
2|                 |
3|                 |
4|        S        |
5|                 |
6|                 |
7|                 |
8|                 |
 +-----------------+

Епископ использует отпечатки пальцев, чтобы передвигаться. Он читает его побайтно слева направо и от младшего к старшему:

Fingerprint      37      :       e4      :       6a      :  ...  :       5e
Bits        00 11 01 11  :  11 10 01 00  :  01 10 10 10  :  ...  :  01 01 11 10
             |  |  |  |      |  |  |  |      |  |  |  |              |  |  |  |
Step         4  3  2  1      8  7  6  5     12 11 10  9             64 63 62 61

Епископ будет двигаться по следующему плану:

Bits   Direction
-----------------
00     Up/Left
01     Up/Right
10     Down/Left
11     Down/Right

Особые случаи:

  • Если епископ окажется в углу и снова войдет в угол, он вообще не будет двигаться. то есть: епископ в [0,0]и его следующим шагом будет 00. Он остается в[0,0]
  • Если епископ находится в углу или у стены и двигается в одну из стен, он движется только горизонтально или вертикально. то есть: епископ в [0,5]и его следующим шагом будет 01. Он не может идти налево, поэтому он просто движется вверх, к [0,4].

Каждая позиция содержит значение того, как часто епископ посещал это поле:

Value      | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11| 12| 13| 14| 15| 16|
Character  |   | . | o | + | = | * | B | O | X | @ | % | & | # | / | ^ | S | E |

Значения 15 (S) и 16 (E) отличаются тем, что они обозначают начальную и конечную позиции слона соответственно и перезаписывают реальное значение соответствующей позиции.

Цель

Создайте программу, которая принимает буквенно-цифровой отпечаток в качестве входных данных и создает свое художественное представление ASCII, как показано в примерах.

Примеры

Input:
16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48

Output:
+-----------------+
|        .        |
|       + .       |
|      . B .      |
|     o * +       |
|    X * S        |
|   + O o . .     |
|    .   E . o    |
|       . . o     |
|        . .      |
+-----------------+

Input:
b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b

Output:
+-----------------+
|            o.o  |
|            .= E.|
|             .B.o|
|              .= |
|        S     = .|
|       . o .  .= |
|        . . . oo.|
|             . o+|
|              .o.|
+-----------------+

Input:
05:1e:1e:c1:ac:b9:d1:1c:6a:60:ce:0f:77:6c:78:47

Output:
+-----------------+
|       o=.       |
|    o  o++E      |
|   + . Ooo.      |
|    + O B..      |
|     = *S.       |
|      o          |
|                 |
|                 |
|                 |
+-----------------+

правила

  • Это . Код в наименьшем количестве байтов побеждает.
  • Вы не можете использовать существующую библиотеку, которая производит изображение.
  • Используйте любой язык, который вы предпочитаете!
  • Ваша заявка должна быть полной программой
Padarom
источник
3
Можно ли предположить, что ни одна клетка не будет посещена более 14 раз?
Мартин Эндер
2
Есть несколько угловых случаев минимального охвата, в результате которых несколько полей будут посещены более 14 раз. 33:33:33:...:33, cc:cc:cc:...:ccБудет примером для этого. Отпечаток пальца обычно является хешем MD5, поэтому маловероятно, что вы получите такой результат. Я не нашел надежных источников о том, как с этим справиться, поэтому пока скажу: предположим, что ни одна клетка не будет посещена более 14 раз.
Падаром

Ответы:

2

Pyth, 125 байт

Jj*17\-"++"JVc9XXsm@"^ .o+=*BOX@%&#/"hdrS+*U9U17K.u.e@S[0b*8hk)1.b+tNyYNYsm_c4.[08jxsM^.HM16 2d2cz\:,4 8 8ieK17\E76\SjN"||")J

Попробуйте онлайн: демонстрация или тест-сьют

Я написал несколько дней назад, но не опубликовал это, потому что я не был очень рад этому.

Объяснение:

Основная идея заключается в следующем. Я начинаю с пары (4, 8). В каждом шаге (m1,m2)я иду от (x, y)к (x-1+2*m1, y-1+2*m2). Чтобы убедиться в том, что эти координаты не выходят за пределы границ, я сделаю некоторые списки, сортировать их и вернуть средний элемент: (sorted(0,8,newx)[1], sorted(0,16,newy)[1]).

Я отслеживаю все позиции. К этому списку позиций я добавляю список всех возможных позиций, сортирую их и кодирую по длине прогона. Что дает мне номер для каждой позиции. С этим номером я могу выбрать правильный символ и в конце перезаписать символы начальной и конечной позиции.

Jakube
источник
9

Дьялог АПЛ (178)

{⎕ML←3⋄F←9 17⍴0⋄5 9{(⍺⌷F)+←1⋄×⍴⍵:(1 1⌈9 17⌊⍺-1 1-2×↑⍵)∇1↓⍵⋄(⍺⌷F)←16⋄F[5;9]←15⋄K⍪(M,' .o+=*BOX@%&#/^SE'[1+F],M←'|')⍪K←'+','+',⍨17⍴'-'}⊃,/{↓⊖4 2⍴⍉(4/2)⊤¯1+⍵⍳⍨⎕D,'abcdef'}¨⍵⊂⍨':'≠⍵}

Это функция, которая принимает строку в качестве правого аргумента и возвращает матрицу символов, содержащую художественное представление ASCII, например:

      F←{⎕ML←3⋄F←9 17⍴0⋄5 9{(⍺⌷F)+←1⋄×⍴⍵:(1 1⌈9 17⌊⍺-1 1-2×↑⍵)∇1↓⍵⋄(⍺⌷F)←16⋄F[5;9]←15⋄K⍪(M,' .o+=*BOX@%&#/^SE'[1+F],M←'|')⍪K←'+','+',⍨17⍴'-'}⊃,/{↓⊖4 2⍴⍉(4/2)⊤¯1+⍵⍳⍨⎕D,'abcdef'}¨⍵⊂⍨':'≠⍵}


      F '16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48'
+-----------------+
|        .        |
|       + .       |
|      . B .      |
|     o * +       |
|    X * S        |
|   + O o . .     |
|    .   E . o    |
|       . . o     |
|        . .      |
+-----------------+
      F 'b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b'
+-----------------+
|            o.o  |
|            .= E.|
|             .B.o|
|              .= |
|        S     = .|
|       . o .  .= |
|        . . . oo.|
|             . o+|
|              .o.|
+-----------------+

Объяснение:

  • ⎕ML←3: установите ⎕MLв 3. Это делает более полезным для разделения строк.

  • F←9 17⍴0: сделать матрицу нулей 17 на 9. Fпредставляет, сколько раз каждая позиция была посещена.

  • ⍵⊂⍨':'≠⍵: разделить на :персонажей.

  • {... : для каждой группы:
    • ¯1+⍵⍳⍨⎕D,'abcdef': найти индекс каждого символа в строке '01234567890abcdef'. Вычтите 1, потому что APL по умолчанию индексируется 1.
    • (4/2)⊤: преобразовать значения в их 4-битные представления (теперь должна быть матрица 2 на 4).
    • ↓⊖4 2⍴⍉: поверните матрицу, используйте элементы, чтобы заполнить матрицу 2 на 4, зеркально отразите эту матрицу по горизонтали, а затем получите каждую строку отдельно. Это дает нам 4 2-битных значения, которые нам нужны.
  • ⊃,/: объединить полученные списки вместе, дав список 2-битных шагов.
  • 5 9{... }: дан список шагов и начиная с позиции [9,5]:
    • (⍺⌷F)+←1: увеличить текущую позицию в F.
    • ×⍴⍵:: если список шагов не пуст:
      • ↑⍵: сделать первый шаг из списка
      • ⍺-1 1-2×: получить дельту для этого шага и вычесть ее из текущей позиции
      • 1 1⌈9 17⌊: ограничить движение с точностью до поля
      • (... )∇1↓⍵: продолжить с новой позиции и остальных шагов
    • Если это пустая:
      • (⍺⌷F)←16: установите Fв 16 в конечной позиции
      • F[5;9]←15: установите Fна 15 в начальной позиции
      • ' .o+=*BOX@%&#/^SE'[1+F]: сопоставить каждую позицию с соответствующим символом
      • K⍪(M,... ,M←'|')⍪K←'+','+',⍨17⍴'-': обернуть результат в строки
Мэринус
источник
8

Perl, 300 + 1 (-n) = 301 байт

perl -ne 'sub b{$b=$_[0]+$_[1];$_[0]=$b<0?0:$b>$_[2]?$_[2]:$b}$v=pack"(H2)*",/\w\w/g;($x,$y)=(8,4);$a[b($y,($_&2)-1,8)*17+b($x,($_&1)*2-1,16)]++for map{vec$v,$_,2}0..63;@a[76,$y*17+$x]=(15,16);$c=" .o+=*BOX@%&#/^SE";print$d="+".("-"x17)."+\n",(map{+"|",(map{substr$c,$_,1}@a[$_*17..($_+1)*17-1]),"|\n"}0..8),$d'

Этот ответ отвратителен, но он также является первым для этой головоломки, поэтому он подойдет на данный момент.

-nвзять строку ввода на STDIN и заполнить $_.

# b($v, -1 or 1, max) modifies $v within 0..max
sub b{$b=$_[0]+$_[1];$_[0]=$b<0?0:$b>$_[2]?$_[2]:$b}

# turn $_ into a binary string
$v=pack"(H2)*",/\w\w/g;

# initialize cursor
($x,$y)=(8,4);

# find an element of single-dimensional buffer @a
$a[
    # y += (bitpair & 2) - 1, within 8
    b($y,($_&2)-1,8) * 17
    # x += (bitpair & 1) * 2 - 1, within 17
  + b($x,($_&1)*2-1,16)
# and increment it
]++
# for each bit pair (in the right order!)
  for map{vec$v,$_,2}0..63;

# overwrite the starting and ending positions
@a[76,$y*17+$x]=(15,16);

# ascii art lookup table
$c=" .o+=*BOX@%&#/^SE";

# output
print
  # the top row, saving it for later
  $d="+".("-"x17)."+\n",
  # each of the eight middle rows
  (map{+
    # converting each character in @a in this row as appropriate
    "|",(map{substr$c,$_,1}@a[$_*17..($_+1)*17-1]),"|\n"
  }0..8),
  # the bottom row
  $d
Эрик Вастл
источник
7

R 465 459 410 393 382 357 байт

f=function(a){s=strsplit;C=matrix(as.integer(sapply(strtoi(el(s(a,":")),16),intToBits)[1:8,]),2);C[!C]=-1;n=c(17,9);R=array(0,n);w=c(9,5);for(i in 1:64){w=w+C[,i];w[w<1]=1;w[w>n]=n[w>n];x=w[1];y=w[2];R[x,y]=R[x,y]+1};R[]=el(s(" .o+=*BOX@%&#/^",""))[R+1];R[9,5]="S";R[x,y]="E";z="+-----------------+\n";cat(z);for(i in 1:9)cat("|",R[,i],"|\n",sep="");cat(z)}

С отступами и переносами:

f=function(a){
    s=strsplit
    C=matrix(as.integer(sapply(strtoi(el(s(a,":")),16),intToBits)[1:8,]),2)
    C[!C]=-1
    n=c(17,9)
    R=array(0,n)
    w=c(9,5)
    for(i in 1:64){
        w=w+C[,i]
        w[w<1]=1
        w[w>n]=n[w>n]
        x=w[1]
        y=w[2]
        R[x,y]=R[x,y]+1
    }
    R[]=el(s(" .o+=*BOX@%&#/^",""))[R+1]
    R[9,5]="S"
    R[x,y]="E"
    z="+-----------------+\n"
    cat(z)
    for(i in 1:9)cat("|",R[,i],"|\n",sep="")
    cat(z)
}

Использование:

> f("16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48")
+-----------------+
|        .        |
|       + .       |
|      . B .      |
|     o * +       |
|    X * S        |
|   + O o . .     |
|    .   E . o    |
|       . . o     |
|        . .      |
+-----------------+
> f("37:e4:6a:2d:48:38:1a:0a:f3:72:6d:d9:17:6b:bd:5e")
+-----------------+
|                 |
|                 |
|          .      |
|     .   o       |
|o . o . S +      |
|.+ + = . B .     |
|o + + o B o E    |
| o .   + . o     |
|         .o      |
+-----------------+
plannapus
источник
Можете ли вы сыграть в «матрицу», определив ее один раз как «м»? То же самое для «функции»?
Кузен Кокаин
Я думаю, вам не нужен 'sep =' в функции 'кошка'
CousinCocaine
по умолчанию для sep используется пробел, поэтому мне нужно переопределить его, но на самом деле я мог бы использовать псевдоним матрицы.
plannapus
Кроме того, насколько я знаю, вы не можете использовать псевдоним function.
plannapus
5

Октава, 277

d=reshape(rot90(dec2bin(hex2dec(strsplit(input('','s'),':'))))>'0',2,[])*2-1;p=[9;5];for m=1:64 p=[max(min(p(:,1)+d(:,m),[17;9]),1) p];end;A=' .o+=*BOX@%&#/^SE';F=A(sparse(p(2,:),p(1,:),1,9,17)+1);F(5,9)='S';F(p(2,1),p(1,1))='E';[a='+-----------------+';b=['|||||||||']' F b;a]

Объяснение:

%// convert the input to binary and rearrange it to be
%//   an array of vectors: [x_displacement; y_displacement]
d=reshape(rot90(dec2bin(hex2dec(strsplit(input('','s'),':'))))>'0',2,[])*2-1;

%// start position array with vector for the start position
p=[9;5];
%// for each move, add displacement, clamping to valid values
for m=1:64 p=[max(min(p(:,1)+d(:,m),[17;9]),1) p];end;

%// alphabet for our fingerprint
A=' .o+=*BOX@%&#/^SE';

%// create a sparse matrix, accumulating values for duplicate
%// positions, and replace counts with symbols
F=A(sparse(p(2,:),p(1,:),1,9,17)+1);

%// correct the start and end symbols and construct the final output
F(5,9)='S';F(p(2,1),p(1,1))='E';
[a='+-----------------+';b=['|||||||||']' F b;a]

Образец прогона:

>> bish
b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b
ans =

+-----------------+
|            o.o  |
|            .= E.|
|             .B.o|
|              .= |
|        S     = .|
|       . o .  .= |
|        . . . oo.|
|             . o+|
|              .o.|
+-----------------+
мерный стакан
источник
3

Pyth, 145 143 140

Jm*17]09A,4K8FYcz\:V4AmhtS[0^2d+@,HGdtyv@+_.BiY16*7\0+-4dyN),3 4 X@JGHh@@JGH; X@J4K15 X@JGH16
=Y++\+*17\-\+VJ++\|s@L" .o+=*BOX@%&#/^SE"N\|)Y

Попробуйте онлайн.

Pyth не очень хорош в задачах с итерацией. Я ожидаю, что CJam победит это легко.

PurkkaKoodari
источник
3

JavaScript (ES6) 249 208

редактировать Добавлена ​​пропущенная граница

Попробуйте запустить приведенный ниже фрагмент в любом браузере, совместимом с EcmaScript 6

B=f=>f.replace(/\w+/g,b=>{for(b=`0x1${b}`;b-1;b>>=2)++g[p=(q=(p=(q=p+~-(b&2)*18)>0&q<162?q:p)+b%2*2-1)%18?q:p]},p=81,z=`+${'-'.repeat(17)}+`,g=Array(162).fill(0))&&g.map((v,q)=>q?q-81?q-p?q%18?' .o+=*BOX@%&#/^'[v]:`|
|`:'E':'S':z+`
|`).join``+`|
`+z

// TEST
console.log=x=>O.innerHTML+=x+'\n'

;['37:e4:6a:2d:48:38:1a:0a:f3:72:6d:d9:17:6b:bd:5e'
,'16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48'
,'b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b'
,'05:1e:1e:c1:ac:b9:d1:1c:6a:60:ce:0f:77:6c:78:47'  
].forEach(t=>console.log(t+'\n'+B(t)+'\n'))


// Less golfed

BB=f=>(
  p = 81,
  g = Array(162).fill(0),
  f.replace(/\w+/g, b => {
    for(b = `0x1${b}`;b != 1; b >>= 2)
      q = p+~-(b&2)*18,
      p = q>0&q<162?q:p,
      p = (q=p+b%2*2-1)%18?q:p,
      ++g[p]
  }),
  g.map((v,q) => q-81?q-p?q%18?' .o+=*BOX@%&#/^'[v]:'\n':'E':'S')
  .join``
)
pre { font-family: menlo,consolas; font-size:13px }
<pre id=O></pre>

edc65
источник
Ваш гольф-код сам должен быть способен печатать границы тоже. В настоящее время только ваш тестовый пример печатает верхнюю и нижнюю границы в forEach, вертикальные границы все еще отсутствуют.
Падаром
@Padarom Я неправильно понял ваш «разумный» комментарий, думая, что граница не была запрошена
edc65
Я имел в виду быть разумным в отношении того, какой метод ввода и вывода вы используете. Мои извинения, если это
вводило в
3

Питон, 381 328

-51 благодаря @JonathanFrech

def h(f):
 s=[f'{int(o,16)>>s&3:02b}'for o in f.split(':')for s in(0,2,4,6)];r=[0]*153;p=76;w=17
 for d in s:r[p]+=1;p+=(-(p%w!=0),p%w!=16)[int(d[1])]+(-w*(p//w!=0),w*(p//w!=8))[int(d[0])]
 r[76]=15;r[p]=16;b='+'+'-'*w+'+';print(b);i=0
 while i<153:print(f"|{''.join(' .o+=*BOX@%&#/^SE'[c]for c in r[i:i+w])}|");i+=w
 print(b)

Слегка разгромлен ради объяснения:

def h_(f):
 #Alias 17 because it gets used enough times for this to save bytes
 w=17

 #Input parsing
 s=[f'{int(o,16)>>s&3:02b}'for o in f.split(':')for s in(0,2,4,6)]

 #Room setup
 r=[0]*153
 p=76

 #Apply movements
 for d in s:
  r[p]+=1
  p+=(-(p%w!=0),p%w!=16)[int(d[1])]+(-w*(p//w!=0),w*(p//w!=8))[int(d[0])]
 r[76]=15 #Set start position
 r[p]=16 #Set end position

 #Display result
 b='+'+'-'*w+'+'
 print(b)
 i=0
 while i<153:
  print(f"|{''.join(' .o+=*BOX@%&#/^SE'[c]for c in r[i:i+w])}|")
  i+=w
 print(b)

Этот беспорядок линии:

r[p]+=1;p+=(-(p%w!=0),p%w!=16)[int(d[1])]+(-w*(p//w!=0),w*(p//w!=8))[int(d[0])]

Функционально эквивалентно этому:

if int(d[0]): #Down, Y+
  if p//17!=8:
    p+=17
else: #Up, Y-
  if p//17!=0:
    p-=17
​
if int(d[1]): #Right, X+
  if p%17!=16:
    p+=1
else: #Left, X-
  if p%17!=0:
    p-=1

но вкладывает все условности в этот стиль игры в гольф: (false_value,true_value)[condition] надеюсь, остальное довольно очевидно

тесты

h('16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48')
+-----------------+
|        .        |
|       + .       |
|      . B .      |
|     o * +       |
|    X * S        |
|   + O o . .     |
|    .   E . o    |
|       . . o     |
|        . .      |
+-----------------+

h("b6:dd:b7:1f:bc:25:31:d3:12:f4:92:1c:0b:93:5f:4b")
+-----------------+
|            o.o  |
|            .= E.|
|             .B.o|
|              .= |
|        S     = .|
|       . o .  .= |
|        . . . oo.|
|             . o+|
|              .o.|
+-----------------+

h("05:1e:1e:c1:ac:b9:d1:1c:6a:60:ce:0f:77:6c:78:47")
+-----------------+
|       o=.       |
|    o  o++E      |
|   + . Ooo.      |
|    + O B..      |
|     = *S.       |
|      o          |
|                 |
|                 |
|                 |
+-----------------+
```
senox13
источник
Привет и добро пожаловать в PPCG. Вы можете использовать свой код, используя однобуквенные имена переменных и помещая одну строку для цикла в одну строку. (1,0)[p%17==16]есть +(p%17!=16), или, возможно, даже p%17!=16.
Джонатан Фрех
Кроме того, есть лишнее пространство в ] for.
Джонатан Фрех
Я думаю, что fpдолжно быть f.
Джонатан Фрех
330 байтов .
Джонатан Фрех
2
Почему я использовал ~16? Немного запутывания никогда не повредит вашему гольфу!
Джонатан Фрех
2

Ruby 288

->k{w=17
r=[z=?++?-*w+?+]
(0...w*9).each_slice(w).map{|o|r<<?|+o.map{|x|c=76
q=0
k.split(?:).flat_map{|b|(0..7).map{|i|b.to_i(16)[i]}}.each_slice(2){|h,v|v<1?(c>w&&c-=w):c<w*8&&c+=w
c+=h<1?c%w>0?-1:0:c%w<16?1:0
c==x&&q+=1}
x==76?'S':c==x ?'E':' .o+=*BOX@%&#/^'[q]}.join+?|}
(r+[z]).join'
'}

Попробуйте онлайн: http://ideone.com/QOHAnM

Читаемая версия (с которой я начал играть в гольф) находится здесь: http://ideone.com/XR64km

Кристиан Лупаску
источник
2

С - 488

Должен быть способ сделать это меньше ....

#include<stdio.h>
#define H ++p;h[i]|=(*p-(*p>58?87:48))<<
#define B ((h[j]>>n*2)&3)
#define L puts("+-----------------+")
#define F(m,s)for(m=0;m<s;m++)
int h[16],m[17][9],i,j,n,x=8,y=4;main(w,v)char**v;{char*p=v[1]-1,c[17]={32,46,111,43,61,42,66,79,88,64,37,38,35,47,94,83,69};for(;*p;p++,i++){H 4;H 0;}F(j,16)F(n,4){if(B&1)x+=!(x==16);else x-=!(x==0);if(B&2)y+=!(y==8);else y-=!(y==0);m[x][y]++;}m[8][4]=15;m[x][y]=16;L;F(i,9){printf("|");F(j,17)printf("%c",c[m[j][i]]);puts("|");}L;}
Джерри Иеремия
источник
0

Ржавчина - 509 байт

fn b(s:&str)->String{let(mut v,mut b)=([[0;11];20],[9,5]);v[19]=[19;11];for i in 0..16{let mut c=usize::from_str_radix(&s[i*3..i*3+2],16).unwrap();for k in 0..4{for j in 0..2{v[j*18][i%9+1]=18;v[i+k][j*10]=[17,3][(i+k+17)%18/17];b[j]=match(if c&(j+1)==j+1{b[j]+1}else{b[j]-1},j,){(0,_)=>1,(18,0)=>17,(10,1)=>9,x@_=>x.0 as usize,}}v[b[0]][b[1]]+=1;c>>=2;}}v[9][5]=15;v[b[0]][b[1]]=16;(0..220).fold("\n".to_string(),|s,i|{format!("{}{}",s," .o+=*BOX@%&#/^SE-|\n".chars().nth(v[i%20][i/20] as usize).unwrap())})}

Большой, но ... почти рядом с C. Как обычно, используется много байтов из-за того, что Rust автоматически не преобразует типы друг в друга. Но, возможно, есть место и для улучшения ... возможно, можно использовать некоторые идеи из других решений.

версия без игры в гольф на Rust Playground онлайн

не яркий
источник