Konwertuj ciąg notacji Forsyth-Edwards na grafikę ASCII

9

W szachach notacja Forsyth-Edwards , częściej nazywana „FEN”, jest tekstowym sposobem przepisywania tablic. Opisuje każdy z ośmiu rzędów planszy (zwanych „szachami” w szachach) od góry do dołu z perspektywy Białego. Utwory są zapisywane jako K (król), Q (królowa), R (wieża), B (biskup), N (rycerz) i P (pionek). Czarne litery używają tych liter małymi literami, a białe litery używają tych wielkich liter. Puste spacje są oznaczone liczbą od 1 do 8 wskazującą, ile jest kolejnych pustych spacji. Byłaby to zupełnie pusta ranga 8, pojedyncza czarna wieża w prawej kolumnie (zwana „plikami” w szachach) 7r, a dwa białe pionki na każdym końcu rzędu PP4PP. Rangi są oddzielone znakiem/. Zwykle dodaje się inne informacje, wskazujące, która strona ma się poruszyć, prawa rycerskie i en passant , numer ruchu i zegar o połowie ruchu, ale zignorujemy je na potrzeby tego wyzwania.

Wejście

Ciąg FEN, z wiersza poleceń lub STDIN, jak chcesz. Możesz założyć, że ten ciąg jest zawsze poprawny.

Wynik

Napisz do STDOUT prostą graficzną reprezentację tablicy ASCII, tak jak by się to faktycznie wydawało:

  • Kawałki są reprezentowane przez ich postać w FEN
  • Puste kwadraty są reprezentowane przez spacje
  • Kawałki i kwadraty są oddzielone rurą, |a po każdej stronie planszy znajdują się rury

Tak więc pusta tablica, napisana jak 8/8/8/8/8/8/8/8w FEN, wyglądałaby jak

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

Pozycja początkowa gry w szachy jest zapisana jako rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRi wyglądałaby jak

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

Końcowa pozycja Anderssen-Kieseritzky 1851 , zwana „Nieśmiertelną grą” w społeczności szachowej, jest zapisana jako r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1, a twój program po podaniu tego wejścia wyprowadziłby:

|r| |b|k| | | |r|
|p| | |p|B|p|N|p|
|n| | | | |n| | |
| |p| |N|P| | |P|
| | | | | | |P| |
| | | |P| | | | |
|P| |P| |K| | | |
|q| | | | | |b| |
GODŁO
źródło
Czy dopuszczalne jest napisanie funkcji, która pobiera dane wejściowe i zwraca dane wyjściowe, zamiast zapisywać je w STDOUT?
Pozew Fund Moniki w dniu
@QPaysTaxes Domyślnie zezwalamy na to i rzeczywiście kilka rozwiązań już to robi. Ostatecznie to zależy od OP, choć w tym przypadku nie ma potrzeby zastępowania naszych domyślnych ustawień.
Alex A.,
2
Odpowiedź, którą zaakceptowałeś, nie jest najkrótsza. Niezależnie od twoich uczuć do języków golfowych, kod golfowy oznacza, że wygrywa najkrótszy kod .
Dennis
3
Nie możesz ich również ukarać ani zaakceptować arbitralnej odpowiedzi . Cała strona oparta jest na obiektywnych kryteriach wygranej.
Dennis,
1
+1na ciekawe wyzwanie. -2za zaakceptowanie złej odpowiedzi bez uzasadnionego powodu
James

Odpowiedzi:

9

Perl, 28 bajtów

Obejmuje +2 za -lp

Podaj dane na STDIN

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

fen.pl:

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

Właściwie w lidze niektórych języków golfowych ...

Zauważ, że wersja oparta na plikach potrzebuje ostatniej nowej linii w pliku, tak że jeden ma naprawdę 29 bajtów. Ale wersja wiersza poleceń nie potrzebuje tej nowej linii i dlatego kod liczy się jako 28 bajtów:

perl -lpe 's/\d/$"x$&/eg;s/|/|/g;y;/;' <<< "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1"
Ton Hospel
źródło
1
Brakuje shebang?
user253751,
15

Siatkówka, 13 bajtów

\d
$* 
/
¶

|

Wypróbuj online!

Wyjaśnienie

Pierwsza część (zwróć uwagę na spację końcową):

\d
$* 

jest konwersja a na określoną liczbę spacji. Siatkówka ma $*funkcję do powtórzenia. Działa to tak: <num>$*<char>jeśli nie <num>, Retina przyjmie $&lub dopasuje ciąg, w tym przypadku dopasowany numer.

Następna część:

/
¶

jest dość prosta, to zastępuje wszystkie /z którym jest znak nowej linii.

Ostatnia część działa tak samo:

    
|

Zastąpi to wszystko (stąd, dlaczego w pierwszym wierszu nie ma nic) |. Stawianie |wszędzie.

Downgoat
źródło
1
Możesz nawet zrobić to wszystko w ASCII dla tej samej liczby bajtów, S`/co w drugim etapie.
Martin Ender,
12

Rubinowy - 75 82 78 76 75 62 59 58 57 56 bajtów

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

Zaoszczędź kilka bajtów dzięki Ventero

Pozwól mi wyjaśnić (z \nzastąpieniem dosłownego nowego wiersza):

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

Powoduje to niejawne zwrócenie wartości ciągu, a każdy z nich /zastępowany jest nową linią (domyślnie $/zawiera nową linię)

"|#{...}|"

To jest bardzo proste; to tylko ciąg zawierający potok, interpolację ciągu i inną potok. Interpolacja ciągów jest oceniana

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

Zastępuje każdą liczbę tyloma spacjami. Mogę zaoszczędzić kilka bajtów, znajdując tutaj również nowe wiersze; ponieważ hexzwraca 0, jeśli ciąg nie jest prawidłową liczbą, gdy znajdzie nowy wiersz - tj. ten na końcu wyniku gets- - zastępuje go ciągiem o długości 0, skutecznie go usuwając. Bez tego istniałaby tylna rura.

$&to magiczna zmienna, która reprezentuje pełny tekst najnowszego dopasowania zmiennej, co pozwala mi zaoszczędzić bajt poprzez wyeliminowanie |d|. Mogę zapisać kolejny bajt, używając .hexzamiast .to_i, co działa, ponieważ każda liczba jest mniejsza niż 9, co oznacza, że ​​szesnastkowy i dziesiętny mają te same wartości.

.chars*?|

To stawia fajkę między każdą postacią. Zauważ, że właśnie to umieszcza rury po obu stronach linii (z wyjątkiem pierwszej i ostatniej), ponieważ ukośniki, które ostatecznie zmieniają się w nowe linie tr, liczą się jako znaki, a zatem są otoczone rurami. Po ?|prostu oznacza „ciąg jednoznakowy "|"”.

I to wszystko. To szczerze skandalicznie prosty program. Po prostu używa wielu podstępnych sztuczek składniowych.

Powództwo Fund Moniki
źródło
2
Możesz zapisać 4 dodatkowe znaki, stosując kilka prostych sztuczek: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(oczywiście zastąp \nponownie dosłowną nową linią).
Ventero
5

Pyth - 24 22 21 bajtów

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

Pakiet testowy .

+                     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
Maltysen
źródło
4

Pyth, 23 bajty

VT=:Q`N*dN;jc.i*\|72Q\/

Wypróbuj online!

Jak to działa:

VT=:Q`N*dN;jc.i*\|72Q\/
VT        ;                for N in range(10):
  =:Q`N*dN                     Q = Q.replace(`N`,repeat(' ',N))
             .i*\|72Q      temp = interweave(repeat('|',72), Q)
            c        \/    temp = chop(temp,'/')
           j               temp = join(temp,'\n')
                           print temp
Leaky Nun
źródło
4

JavaScript ES7, 80 70 bajtów

Jest anonimową funkcją, która przyjmuje ciąg jako dane wejściowe.

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

80-bajtowa funkcja tylko dla ES6.

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

Wyjaśnienie

Używamy rozumienia tablicowego, aby przeglądać listę:

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

Jest to równoważne z:

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

Jeśli jest to liczba, mamy taką liczbę spacji. Jeśli tak /, mamy nową linię. W przeciwnym razie mamy postać. Następnie łączymy się ze zrozumieniem, nie tworząc nici.

Następnie tworzymy tablicę o długości 3 [,...that,"\n"]. ...dzieli połączone zrozumienie na znaki. Dołączenie do tego daje wynik.

Conor O'Brien
źródło
Nie masz na myśli ES6? ES7 nie jest jeszcze dostępny.
ericw31415
@ ericw31415 To nie jest koniec, masz rację, ale niektóre przeglądarki zaczęły implementować część specyfikacji ES7.
Conor O'Brien
Oh ok Ale nadal twój kod nie korzysta z żadnej funkcji ES7, prawda?
ericw31415
1
@ ericw31415 Właściwie to robi. Zrozumienia tablic ( [x for(x of a)]) są ES7.
Conor O'Brien
3

Julia, 62 bajty

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

Jest to anonimowa funkcja, która przyjmuje ciąg i zwraca tablicę ciągów. Aby go wywołać, przypisz go do zmiennej.

Podejście jest takie samo, jak w sprytnej odpowiedzi Ruby na QPaysTaxes . Zamieniamy każdą cyfrę na wejściu na tyle spacji, umieszczamy |między każdym znakiem, przyczepiamy |do przodu i tyłu i dzielimy na tablicę /.

Wypróbuj online!

Alex A.
źródło
Tak, zainspirowałem rzeczy: D
pozew fundacji Moniki
@QPaysTaxes Rzeczywiście zrobiłeś. Fajne rozwiązanie!
Alex A.,
2

05AB1E , 21 bajtów

Kod:

9GNNð×:}S'|ý"|ÿ|"'/¶:

Również 21 bajtów: '|¹9GNNð×:}S'|«JJ'/¶:.

Wykorzystuje kodowanie CP-1252 . Wypróbuj online! .

Adnan
źródło
2

JavaScript (ES6), 69 67 62 bajtów

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

Dodatkowe przecinki tworzą puste wartości w zewnętrznym podziale, który tworzy początkowe i końcowe |znaki. Potrzebujesz dwóch przecinków końcowych, ponieważ przecinki końcowe są opcjonalne na końcu list, więc pierwszy jest nadal częścią poprzedniego elementu.

Edycja: Zapisano 5 bajtów dzięki @ user81655.

Neil
źródło
Czy /[\d/]/g,c=>+c?` `.repeat(c):`\n`zadziała?
user81655 24.04.16
1
@ user81655 Dzięki, ale nie podobał mi się twój emotikon, więc zastąpiłem go zirytowaną twarzą w okularach.
Neil
1

Siatkówka , 50 45 bajtów

To była fajna haha. Nie tylko jestem noobem na Retinie, ale także ogólnie w wyrażeniach regularnych ... Prawdopodobnie można dużo grać w golfa grać w , więc przeprowadzę więcej badań.

Kod:

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

1

/
¶

|

Wypróbuj online!

Adnan
źródło
Spróbuj użyć $*funkcji :)
Leaky Nun
1

Python 3.5, 112 bajtów:

def r(o):print(''.join(['| '*8if h=='8'else'| '*int(h)if h.isdigit()else'|\n'if h=='/'else'|'+h for h in o])+'|')

Wypróbuj online! (Ideone)

R. Kap
źródło
1

C, 252 bajtów

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

Szczegółowa próba online

// 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;
}
Khaled.K
źródło
1

JavaScript (FireFox 30+), 61

Korzystanie ze zrozumienia tablic, które nie jest już standardowym EcmaScript

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

Test

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>

edc65
źródło
1

Lua, 106 bajtów

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

Nie golfił

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
Katenkyo
źródło
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").."|")dla tej samej liczby bajtów.
Leaky Nun
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")ma 101 bajtów
Leaky Nun
1

R (poza zawodami)

Przepraszam, jeśli publikowanie tego nie jest właściwe, ale pomyślałem, że to fajnie, że akurat miałem funkcję, która faktycznie działa na to pytanie bez edycji! Jednak drukuje wyjście w formacie Unicode zamiast ascii. Nie pamiętam dokładnie, dlaczego to napisałem, ale to nie była odpowiedź na wyzwanie.

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)

}
Flądrarz
źródło
Zasady przedstawione w naszym centrum pomocy stanowią, że wszystkie rozwiązania wyzwań muszą poważnie konkurować z zastosowanymi zwycięskimi kryteriami. W przypadku golfa kodowego oznacza to, że wszystkie odpowiedzi muszą być w golfa.
Dennis
Technicznie jest golfem. Po prostu niezbyt dobrze.
Flądrowiec
0

Haskell, 110 bajtów

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

Nie golfowany:

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
viercc
źródło
0

Java 7, 190 184 bajtów

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+"|";}

Szczegółowa próba online

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+"|";
}
Khaled.K
źródło
Możesz zaoszczędzić kilka bajtów używając liczb całkowitych zamiast literałów char w porównaniach
Blue
@Niebieskie notatki zrobione
Khaled.K
0

Pyke, 25 20 bajtów

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

Wyjaśnienie:

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

Wypróbuj tutaj!

niebieski
źródło
0

Python, 84 bajty

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

Wyjaśnienie:

        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
niebieski
źródło
0

> <>, 64 bajty

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

4 zmarnowane bajty z powodu problemów z wyrównaniem, nie wiem jednak, jak je rozegrać. ¯ \ _ (ツ) _ / ¯

Sok
źródło