Преобразование строки нотации Форсайта-Эдвардса в искусство ASCII


9

В шахматах нотация Форсайта-Эдвардса , более часто называемая «FEN», является текстовым способом расшифровки досок. Он описывает каждый из восьми рядов доски (называемых «шахматами» в шахматном порядке) сверху вниз с точки зрения белых. Части написаны как K (король), Q (ферзь), R (ладья), B (слон), N (рыцарь) и P (пешка). Черные фигуры используют эти буквы в нижнем регистре, а белые фигуры используют эти буквы в верхнем регистре. Пустые пробелы обозначаются цифрами от 1 до 8, указывающими, сколько существует последовательных пустых пробелов. Было бы совершенно пустое звание, была бы 8одна черная ладья в крайнем правом столбце (в шахматах называемая «файлами») 7rи две белые пешки на каждом конце ряда PP4PP. Ряды разделены/, Обычно добавляется другая информация, указывающая, какая сторона должна двигаться, рокировка и права прохода , номер хода и часы полуоборота, но мы будем игнорировать их для целей этой задачи.

вход

Строка FEN, из командной строки или STDIN, как вам угодно. Вы можете предположить, что эта строка всегда действительна.

Вывод

Напишите в STDOUT простое ASCII-изображение доски, как оно выглядит на самом деле:

  • Части представлены их персонажем в FEN
  • Пустые квадраты представлены пробелами
  • Куски и квадраты разделены трубкой, |и на каждой стороне доски есть трубы

Таким образом, пустая доска, написанная как 8/8/8/8/8/8/8/8в FEN, будет выглядеть как

| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |

Начальная позиция шахматной игры записывается как rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRи будет выглядеть как

|r|n|b|q|k|b|n|r|
|p|p|p|p|p|p|p|p|
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
|P|P|P|P|P|P|P|P|
|R|N|B|Q|K|B|N|R|

Финальная позиция Андерсена-Кизерицкого в 1851 году , называемая «Бессмертная игра» в шахматном сообществе, записывается как r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1, и ваша программа при подаче этого ввода выдаст:

|r| |b|k| | | |r|
|p| | |p|B|p|N|p|
|n| | | | |n| | |
| |p| |N|P| | |P|
| | | | | | |P| |
| | | |P| | | | |
|P| |P| |K| | | |
|q| | | | | |b| |

Допустимо ли писать функцию, которая принимает ввод и возвращает вывод, а не записывать ее в STDOUT?
Фонд Моника иск

@QPaysTaxes По умолчанию мы разрешаем это, и действительно, несколько решений уже это делают. В конечном счете, все зависит от OP, хотя в этом случае нет необходимости переопределять наши значения по умолчанию.
Алекс А.

2
Ответ, который вы приняли, не самый короткий. Независимо от ваших чувств к языкам игры в гольф, гольф-код означает, что выигрывает самый короткий код .
Деннис

3
Вы также не можете оштрафовать их или принять произвольный ответ . Весь сайт построен вокруг объективных критериев выигрыша.
Деннис

1
+1за интересный вызов. -2за принятие неправильного ответа без уважительной причины
Джеймс

Ответы:


9

Perl, 28 байт

Включает +2 для -lp

Внести вклад в STDIN

fen.pl <<< "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1"

fen.pl:

#!/usr/bin/perl -lp
s/\d/$"x$&/eg;s/|/|/g;y;/;

На самом деле в лиге некоторых гольф-языков ...

Обратите внимание, что файловая версия нуждается в последней новой строке в файле, так что в действительности она составляет 29 байт. Но версия командной строки не нуждается в этой дополнительной новой строке, и поэтому код считается 28 байтами:

perl -lpe 's/\d/$"x$&/eg;s/|/|/g;y;/;' <<< "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1"

1
Отсутствует Шебанг?
user253751

15

Сетчатка, 13 байт

\d
$* 
/
¶

|

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

объяснение

Первая часть (обратите внимание на завершающий пробел):

\d
$* 

это преобразовать в определенное количество пробелов. Retina имеет $*функцию, чтобы повторить. Это работает так: <num>$*<char>если нет <num>, Retina примет $&или совпадает строку, в этом случае совпадает число.

Следующая часть:

/
¶

довольно просто, он заменяет все /с которой является символом новой строки.

Последняя часть работает так же:

    
|

Это заменит все (следовательно, почему в первой строке ничего нет) на |. Выкладывать |везде.


1
Вы даже можете сделать все это в ASCII для того же количества байтов, S`/что и на втором этапе.
Мартин Эндер

12

Рубин - 75 82 78 76 75 62 59 58 57 56 байт

->n{"|#{n.gsub(/\d|
/){' '*$&.hex}.chars*?|}|".tr'/',$/}

Сохранено несколько байтов благодаря Ventero

Позвольте мне объяснить (с \nзаменой буквального перевода строки):

->n{"...".tr'/',$/}

Это неявно возвращает значение строки, каждая из которых /заменяется новой строкой (по умолчанию $/содержит новую строку )

"|#{...}|"

Это супер просто; это просто строка, содержащая трубу, интерполяцию строки и другую трубу. Интерполяция строки оценивается

n.gsub(/\d|\n/){' '*$&.hex}...

Это заменяет каждое число таким количеством пробелов. Я могу сэкономить несколько байтов, также найдя здесь новые строки; Потому что hexвозвращает 0, если строка не является допустимым числом, когда она находит новую строку - то есть ту, что находится в конце результата gets-, она заменяет ее строкой 0 длины, эффективно удаляя ее. Без этого не было бы задней трубы.

$&является магической переменной, которая представляет полный текст последнего совпадения переменных, что позволяет мне сохранить байт путем исключения |d|. Я могу сохранить другой байт, используя .hexвместо .to_i, что работает, потому что каждое число меньше 9, что означает, что шестнадцатеричный и десятичный имеют одинаковые значения.

.chars*?|

Это ставит трубу между каждым персонажем. Обратите внимание, что это то, что ставит каналы по обе стороны от строк (кроме первой и последней), потому что косые черты, которые в конечном итоге превращаются в символы новой строки tr, считаются символами и поэтому окружены каналами. В ?|просто означает «строка из одного символа "|"».

И это все. Это откровенно скандально простая программа. Он просто использует множество хитрых синтаксических трюков.


2
Вы можете сохранить еще 4 символа, применив несколько простых приемов: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(разумеется, \nснова замените символ буквальным переводом строки).
Вентеро

5

Pyth - 24 22 21 байт

.i*\|72jcu:G`H*Hd9z\/

Тестовый пакет .

+                     Concatenate
 K\|                  Store "|" in K and use value
+         K           Concatenate to end
 jK                   Join string by K, this puts "|" between each char
  :                   String substitution
        \/            Replace "/"
         b            With newline
   u                  Reduce
        9             Over [0, 9)
         z            With input as base case
    :G                String substitution current val
     `H               Replace stringifyed int from list we're looping through
     *Hd              With " "*that int


4

JavaScript ES7, 80 70 байт

Анонимная функция, которая принимает строку в качестве входных данных.

a=>[,...[+t?" ".repeat(t):t<"0"?`
`:t for(t of a)].join``,`
`].join`|`

80-байтный ES6-только аппрох.

a=>a.split`/`.map(x=>[,...x.replace(/\d/g,t=>" ".repeat(t)),`
`].join`|`).join``

объяснение

Мы используем понимание массива для обхода списка:

[+t?" ".repeat(t):t<"0"?`
`:t for(t of a)]

Это эквивалентно:

[!isNaN(parseInt(t, 10)) ? " ".repeat(parseInt(t, 10)) : t === "/" ? "\n" : t for(t of a)]

Если это число, у нас есть это количество пробелов. Если это /, у нас есть новая строка. В противном случае у нас есть персонаж. Затем мы присоединяемся к пониманию, и ничто не создает последовательности.

Затем мы создаем массив длиной 3 [,...that,"\n"]. ...разделяет объединенное понимание на символы. Присоединение к этому дает результат.


Разве вы не имеете в виду ES6? ES7 еще не вышел, я верю.
ericw31415

@ ericw31415 Это не так, вы правы, но некоторые браузеры начали реализовывать часть спецификации ES7.
Конор О'Брайен,

О хорошо Но все же ваш код не использует никаких функций ES7, верно?
ericw31415

1
@ ericw31415 На самом деле, это так. [x for(x of a)]Массивы ( ) - это ES7.
Конор О'Брайен,

Были не массив постижений удалены из спецификации, MDN говорит , что они были
MayorMonty

3

Юлия, 62 байта

s->split("|"join(replace(s,r"\d",d->" "^parse(d)),"|")"|","/")

Это анонимная функция, которая принимает строку и возвращает массив строк. Чтобы вызвать его, присвойте его переменной.

Подход такой же, как и в умном Ruby- ответе QPaysTaxes . Мы заменяем каждую цифру во вводе таким количеством пробелов, помещаем |между каждым символом, |прикрепляем вперед и назад и разделяем на массив /.

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


Yay, я вдохновил вещи: D
Фонд Моники Иск

@QPaysTaxes Вы действительно сделали. Отличное решение!
Алекс А.


2

JavaScript (ES6), 69 67 62 байта

s=>[,...s.replace(/[/-8]/g,c=>+c?' '.repeat(c):`
`),,].join`|`

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

Редактировать: 5 байтов сохранено благодаря @ user81655.


Будет /[\d/]/g,c=>+c?` `.repeat(c):`\n`работать?
user81655

1
@ user81655 Спасибо, но мне не понравился твой смайлик, поэтому я заменил его на раздраженное лицо очками.
Нил

1

Сетчатка , 50- 45 байтов

Это было весело, ха-ха. Я не только новичок в Retina, но и в регулярных выражениях в целом ... Это, вероятно, может быть много в гольфе , поэтому я сделаю еще некоторые исследования.

Код:

8
44
7
34
6
42
5
 4
4
22
3
 2
2

1

/
¶

|

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


Попробуйте использовать $*функциональность :)
Leaky Nun



1

C, 252 байта

i=-1,j,s=1,x;C(char*n){while(n[++i])s+=isdigit(n[i])?n[i]*2+1:2;char*m=(char*)malloc(s);for(i=j=-1;n[++i]&(m[++j]='|');)if(n[i]=='/')m[++j]='\n';else if(isdigit(n[i]))for(x=n[i]-'0';x;--x&&(m[++j]='|'))m[++j]=' ';else m[++j]=n[i];m[++j]='\0';return m;}

Подробная попытка онлайн

// input-string, input-string-size
char* C(char*n)
{
    int i=-1,j,s=1,x;

    // figure out required grid size
    while(n[++i])s+=isdigit(n[i])?n[i]*2+1:2;
    char*m=(char*)malloc(s);

    i=j=-1;
    while(n[++i]) // while not end of string
    {
        m[++j]='|'; // seperator

        if (n[i]=='/') // end of row
            m[++j]='\n';
        else if (isdigit(n[i])) // fill spaces
            for(x=n[i]-'0';x;--x&&(m[++j]='|')) m[++j]=' ';
        else
            m[++j]=n[i]; // single literals
    }

    m[++j]='|';
    m[++j]='\0';
    return m;
}

1

JavaScript (FireFox 30+), 61

Использование массива, который больше не является стандартным EcmaScript

f=>'|'+[for(c of f)+c?' |'.repeat(c):c<'A'?`
|`:c+'|'].join``

Тестовое задание

F=f=>'|'+[for(c of f)+c?' |'.repeat(c):c<'A'?`\n|`:c+'|'].join``

console.log=x=>O.textContent+=x+'\n'

;['8/8/8/8/8/8/8/8','rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR',
'r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1']
.forEach(t=>console.log(F(t)+'\n'))
<pre id=O></pre>


1

Луа, 106 байт

print("|"..(...):gsub(".",function(c)return c:find("%d")and(" |"):rep(c)or c=="/"and"\n|"or c.."|"end),'')

Ungolfed

print("|"..                   -- prepend | to the following string
  (...):gsub(".",function(c)  -- iterate over each character in the argument
    return                    -- replaces in the argument
           c:find("%d")       -- if c is a number
             and(" |"):rep(c) --   replace by " |"*c
           or c=="/"          -- elseif c is a slash
             and"\n|"         -- replace by "\n|"
           or c.."|"          -- else (case letter)replace by c
  end)                        -- return the modified string
,'')                          -- add an empty parameter to print
                              -- it suppresses the second output of gsub

print((...):gsub(".",function(c)return(c:find("%d")and("| "):rep(c)or c=="/"and"|\n"or"|"..c)end).."|")
Утренняя монахиня

print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("/","|\n"):gsub("([^%d%s|])","|%1").."|")для того же количества байтов.
Лаки Монахиня

print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")составляет 101 байт
Leaky Nun

1

R (вне конкуренции)

Извините, если это не уместно, но я подумал, что это круто, что у меня просто есть функция, которая работает для этого вопроса без редактирования! Это печатает вывод Unicode, а не ascii, хотя. Я не могу вспомнить, почему я написал это, но это не было ответом на вызов.

function(x){
# x = FEN position, a string
# can be split with / or ,
# example: forsythe("rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R")

allowed <- c(paste(1:64), 
c("k", "q", "r", "b", "n", "p", "K", "Q", "R", "B", "N", "P"))
chars <- strsplit(x, "")[[1]]
chars <- chars[-which(!(chars %in% allowed))]
out <- c()
for (i in 1:length(chars)){
  if (chars[i] %in% paste(1:64)){
    out <- c(out, rep(" ", as.numeric(chars[i])))
  }
  else{
    out <- c(out, chars[i])
  }
}
if (length(out) < 64) out <- c(out, rep(" ", 64-length(out)))

pieces <- strsplit("KQRBNPkqrbnp", "")[[1]]
unicode <- c("\u2654", "\u2655", "\u2656", 
"\u2657", "\u2658", "\u2659", "\u265A", "\u265B", 
"\u265C", "\u265D", "\u265E", "\u265F")

for (i in 1:64){
  if (out[i] %in% pieces){
    out[i] <- unicode[which(pieces==out[i])]
  }
  else{
  }
}
out <- matrix(out, nc=8, byrow=T)
#print(out)

plot(0, xlim=c(0, 8), ylim=c(0, 8), type="n", xaxt="n", yaxt="n",
xlab="", ylab="")
for (i in 0:7){ for (j in 0:7){ rect(i, j, i+1, j+1,
col=ifelse(((i+j) %% 2) == 0, grey(0.95), "white"), border=F) }}

for (i in 0:7){ for (j in 0:7){
  text(i+0.5, j+0.5, out[8-j, i+1], cex=2)  
}}

axis(1, labels=letters[1:8], at=1:8 - 0.5, tick=F)
axis(2, labels=paste(1:8), at=1:8-0.5, las=2, tick=F)

}

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

Технически это игра в гольф. Просто не очень хорошо.
Камбала

0

Haskell, 110 байт

p '/'="\n"
p c|'1'<=c&&c<='8'=replicate(read[c])' '
p c=[c]
main=getLine>>=putStrLn.('|':).(>>=(:"|")).(>>=p)

Ungolfed:

p c | c=='/'           = "\n"
    | '1'<=c && c<='8' = replicate (read [c]) ' '
    | otherwise        = [c]
addPipes string = "|" ++ concatMap (\c -> [c] ++ "|") string
main = getLine >>= putStrLn . addPipes . concatMap p

0

Java 7, 190 184 байта

String Z(int c){String m="";if(c==47)m+="|\n";else if(c>57)m+="|"+c;else while(c-->48)m+="| ";return m;}String C(String n){String m="";for(char x:n.toCharArray())m+=Z(x);return m+"|";}

Подробная попытка онлайн

public static String Z(char c)
{
    String m="";
    if(c=='/')m+="|\n";
    else if(c>'9')m+="|"+c;
    else while(c-->'0')m+="| ";
    return m;
}

public static String C(String n)
{
    String m="";
    for(char x:n.toCharArray())m+=Z(x);
    return m+"|";
}

Вы можете сэкономить пару байтов, используя целые числа вместо литералов в сравнениях
Blue

@ Синие заметки сделаны
Khaled.K


0

Python, 84 байта

lambda a:"".join(c*c.isalpha()or"\n"*(c=="/")or" "*int(c)for c in a).replace("","|")

Объяснение:

        c*c.isalpha()                                                       - if c is alphabetical, use c
                       "\n"*(c=="/")                                        - if it's "|", replace it with a newline
                                      " "*int(c)                            - else its an int.
"".join(                                                  ).replace("","|") - interweave "|" between the chars

0

> <>, 64 байта

<v?(0:i
r\
"<o-*=@"%/":   v?*(@)@":/"::;?(0:o"|
 ^~?="0":-1o" "<

4 потраченных впустую байта из-за проблем с выравниванием, хотя я не уверен, как их убрать. ¯ \ _ (ツ) _ / ¯

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.