Перетворити рядок Notation Forsyth-Edwards в арт 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 За замовчуванням ми це дозволяємо, і вже кілька рішень це вже роблять. Зрештою, це залежить від ОП, хоча здається, що в цьому випадку не потрібно перекривати наші дефолти.
Алекс А.

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
Відсутній шебанг?
користувач253751

15

Сітківка, 13 байт

\d
$* 
/
¶

|

Спробуйте в Інтернеті!

Пояснення

Перша частина (відзначте пробіл):

\d
$* 

полягає в перетворенні а на певну кількість пробілів. Сітківка має $*особливість повторення. Як це працює так: <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'/',$/}

Збережено кілька байт завдяки Вентеро

Дозвольте мені пояснити ( \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.
Conor O'Brien

О, добре. Але все ж ваш код не використовує жодної функції ES7, правда?
ericw31415

1
@ ericw31415 Власне, так і є. Поняття масиву ( [x for(x of a)]) - це ES7.
Conor O'Brien


3

Джулія, 62 байти

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

Це анонімна функція, яка приймає рядок і повертає масив рядків. Щоб викликати його, призначте його змінній.

Підхід такий самий, як і у розумній відповіді Ruby Ruby від QPaysTaxes . Заміняємо кожну цифру на вході на стільки пробілів, розміщуємо |між кожним символом, торкаємося |спереду та ззаду та розділяємо на масив на/ .

Спробуйте в Інтернеті!


Так, я надихнувся на речі: 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`працювати?
користувач81655

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),'')

Безумовно

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).."|")
Leaky Nun

print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("/","|\n"):gsub("([^%d%s|])","|%1").."|")для того ж байтового рахунку.
Leaky Nun

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

Хаскелл, 110 байт

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

Безголівки:

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

@Blue зроблено замітки
Khaled.K

0

Пайк, 25 20 байт

FD~u{RIbd*(s\/n:k\|:

Пояснення:

F         (          -    for char in input:
 D~u{RI              -     if char in '0123456789': 
       bd*           -      char = " "*int(char)
           s         -   sum(^)
            \/n:     -  ^.replace("/","\n")
                k\|: - ^.replace("", "|")

Спробуйте тут!


0

Пітон, 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.