Konvertieren Sie eine Forsyth-Edwards-Notationszeichenfolge in ASCII-Grafik

9

Im Schach ist die Forsyth-Edwards-Notation , besser bekannt als "FEN", eine textuelle Methode zum Transkribieren von Brettern. Es beschreibt jede der acht Reihen des Bretts (im Schach "Ränge" genannt) aus der Sicht von Weiß von oben nach unten. Die Stücke sind geschrieben als K (König), Q (Königin), R (Turm), B (Bischof), N (Ritter) und P (Bauer). Schwarze Teile verwenden diese Buchstaben in Kleinbuchstaben und weiße Teile verwenden diese Buchstaben in Großbuchstaben. Leere Leerzeichen werden durch eine Zahl von 1 bis 8 angezeigt, die angibt, wie viele aufeinanderfolgende Leerzeichen vorhanden sind. Ein völlig leerer Rang wäre 8, ein einzelner schwarzer Turm in der Spalte ganz rechts (im Schach "Dateien" genannt) wäre 7rund zwei weiße Bauern an jedem Ende einer Reihe wären PP4PP. Ränge werden durch a getrennt/. Es ist in der Regel andere Informationen hinzugefügt, die angibt , welche Seite zu bewegen ist, Rochade und en passant Rechte, Zugnummer und halfmove Uhr, aber wir werden sie für die Zwecke dieser Herausforderung zu ignorieren.

Eingang

Eine FEN-Zeichenfolge aus der Befehlszeile oder STDIN, wie Sie möchten. Sie können davon ausgehen, dass diese Zeichenfolge immer gültig ist.

Ausgabe

Schreiben Sie an STDOUT eine einfache ASCII-Grafikdarstellung der Tafel, wie sie tatsächlich erscheinen würde:

  • Stücke werden durch ihren Charakter in FEN dargestellt
  • Leere Quadrate werden durch Leerzeichen dargestellt
  • Teile und Quadrate sind durch ein Rohr getrennt |und auf jeder Seite der Platte befinden sich Rohre

Eine leere Tafel, geschrieben wie 8/8/8/8/8/8/8/8in FEN, würde also als erscheinen

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

Die Startposition eines Schachspiels wird als geschrieben rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRund erscheint als

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

Die endgültige Position von Anderssen-Kieseritzky 1851 , genannt "The Immortal Game" in der Schachgemeinschaft, lautet wie folgt: r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1Ihr Programm würde bei Eingabe dieses Inputs Folgendes ausgeben:

|r| |b|k| | | |r|
|p| | |p|B|p|N|p|
|n| | | | |n| | |
| |p| |N|P| | |P|
| | | | | | |P| |
| | | |P| | | | |
|P| |P| |K| | | |
|q| | | | | |b| |
EMBLEM
quelle
Ist es akzeptabel, eine Funktion zu schreiben, die Eingaben akzeptiert und Ausgaben zurückgibt, anstatt sie in STDOUT zu schreiben?
Fund Monica Klage
@QPaysTaxes Standardmäßig erlauben wir dies und tatsächlich tun dies bereits mehrere Lösungen. Letztendlich liegt es am OP, obwohl es in diesem Fall unnötig erscheint, unsere Standardeinstellungen zu überschreiben.
Alex A.
2
Die Antwort, die Sie akzeptiert haben, ist nicht die kürzeste. Unabhängig von Ihren Gefühlen gegenüber Golfsprachen bedeutet Code Golf, dass der kürzeste Code gewinnt.
Dennis
3
Sie können sie auch nicht bestrafen oder eine willkürliche Antwort akzeptieren . Die gesamte Website basiert auf objektiven Gewinnkriterien.
Dennis
1
+1für eine interessante Herausforderung. -2für die Annahme der falschen Antwort ohne guten Grund
James

Antworten:

9

Perl, 28 Bytes

Beinhaltet +2 für -lp

Geben Sie eine Eingabe auf STDIN

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

fen.pl::

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

Eigentlich in der Liga einiger Golfsprachen ...

Beachten Sie, dass die dateibasierte Version den letzten Zeilenumbruch in der Datei benötigt, sodass tatsächlich 29 Byte vorhanden sind. Die Befehlszeilenversion benötigt jedoch keine zusätzliche neue Zeile, und daher zählt der Code als 28 Byte:

perl -lpe 's/\d/$"x$&/eg;s/|/|/g;y;/;' <<< "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1"
Ton Hospel
quelle
1
Vermissen Sie Shebang?
user253751
15

Netzhaut, 13 Bytes

\d
$* 
/
¶

|

Probieren Sie es online aus!

Erläuterung

Der erste Teil (beachten Sie das nachfolgende Leerzeichen):

\d
$* 

ist a in die bestimmte Anzahl von Leerzeichen umzuwandeln. Die Netzhaut muss $*wiederholt werden. Die Art und Weise, wie es funktioniert, ist: <num>$*<char>Wenn es keine gibt <num>, übernimmt Retina $&oder die übereinstimmende Zeichenfolge, in diesem Fall die übereinstimmende Nummer.

Der nächste Teil:

/
¶

ist ziemlich einfach, es ersetzt /mit dem ein Newline ist.

Der letzte Teil funktioniert genauso:

    
|

Dies ersetzt alles (daher steht in der ersten Zeile nichts) durch |. Putting a |überall.

Downgoat
quelle
1
Sie können sogar alles in ASCII für dieselbe Byteanzahl S`/wie in der zweiten Stufe ausführen.
Martin Ender
12

Ruby - 75 82 78 76 75 62 59 58 57 56 Bytes

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

Dank Ventero ein paar Bytes gespart

Lassen Sie mich erklären (mit dem \nErsetzen der wörtlichen Newline):

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

Dies gibt implizit den Wert der Zeichenfolge zurück, wobei jede /durch eine neue Zeile ersetzt wird ( $/enthält standardmäßig eine neue Zeile).

"|#{...}|"

Das ist super einfach; Es ist nur eine Zeichenfolge, die eine Pipe, eine String-Interpolation und eine andere Pipe enthält. Die String-Interpolation wird ausgewertet

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

Dies ersetzt jede Zahl durch so viele Leerzeichen. Ich kann ein paar Bytes sparen, indem ich hier auch Zeilenumbrüche finde. weil hex0 zurückgibt, wenn die Zeichenfolge keine gültige Zahl ist, wenn sie eine neue Zeile findet - dh die am Ende des Ergebnisses von gets-, ersetzt sie diese durch eine Zeichenfolge mit der Länge 0 und löscht sie effektiv. Ohne dies würde es ein nachlaufendes Rohr geben.

$&ist eine magische Variable, die den vollständigen Text der letzten Variablenübereinstimmung darstellt, wodurch ich ein Byte durch Eliminieren speichern kann |d|. Ich kann ein anderes Byte speichern, indem ich .hexanstelle von verwende .to_i, was funktioniert, weil jede Zahl kleiner als 9 ist, was bedeutet, dass Hex und Dezimal die gleichen Werte haben.

.chars*?|

Dies setzt eine Pipe zwischen jedes Zeichen. Beachten Sie, dass dies die Pipes auf beiden Seiten der Linien platziert (mit Ausnahme der ersten und letzten), da die Schrägstriche, die sich schließlich in Zeilenumbrüche verwandeln tr, als Zeichen gelten und daher von Pipes umgeben sind. Das ?|bedeutet nur "die Ein-Zeichen-Zeichenfolge "|"".

Und das ist es. Es ist ein ehrlich gesagt skandalös einfaches Programm. Es werden nur viele hinterhältige Syntaxtricks verwendet.

Fund Monica Klage
quelle
2
Sie können 4 weitere Zeichen speichern, indem Sie ein paar einfache Tricks anwenden: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(Ersetzen Sie die \nnatürlich wieder durch eine wörtliche neue Zeile).
Ventero
5

Pyth - 24 22 21 Bytes

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

Testsuite .

+                     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
quelle
4

Pyth, 23 Bytes

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

Probieren Sie es online aus!

Wie es funktioniert:

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
Undichte Nonne
quelle
4

JavaScript ES7, 80 70 Bytes

Ist eine anonyme Funktion, die eine Zeichenfolge als Eingabe akzeptiert.

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

80-Byte-ES6-Ansatz.

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

Erläuterung

Wir verwenden ein Array-Verständnis, um die Liste zu durchlaufen:

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

Dies entspricht:

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

Wenn es eine Zahl ist, haben wir diese Anzahl von Leerzeichen. Wenn es eine ist /, haben wir eine neue Zeile. Ansonsten haben wir den Charakter. Dann verbinden wir das Verständnis mit nichts, um einen String zu machen.

Dann erstellen wir ein Array der Länge 3 [,...that,"\n"]. ...Splats das verbundene Verständnis in Zeichen. Wenn Sie sich dem anschließen, erhalten Sie das Ergebnis.

Conor O'Brien
quelle
Meinst du nicht ES6? ES7 ist noch nicht raus, glaube ich.
Ericw31415
@ ericw31415 Es ist nicht out, Sie haben Recht, aber einige Browser haben begonnen, einen Teil der ES7-Spezifikation zu implementieren.
Conor O'Brien
Oh ok. Ihr Code verwendet jedoch keine der ES7-Funktionen, oder?
Ericw31415
1
@ ericw31415 Eigentlich tut es. Array-Verständnis ( [x for(x of a)]) sind ES7.
Conor O'Brien
Wurden Array-Verständnisse nicht aus der Spezifikation entfernt, sagt
Fall
3

Julia, 62 Bytes

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

Dies ist eine anonyme Funktion, die eine Zeichenfolge akzeptiert und ein Array von Zeichenfolgen zurückgibt. Um es aufzurufen, weisen Sie es einer Variablen zu.

Der Ansatz ist der gleiche wie in der cleveren Ruby- Antwort von QPaysTaxes . Wir ersetzen jede Ziffer in der Eingabe durch so viele Leerzeichen, platzieren sie |zwischen den einzelnen Zeichen, heften sie |vorne und hinten an und teilen sie in ein Array auf /.

Probieren Sie es online aus!

Alex A.
quelle
Ja, ich habe Dinge inspiriert: D
Fund Monicas Klage
@QPaysTaxes Du hast es tatsächlich getan. Schöne Lösung!
Alex A.
2

05AB1E , 21 Bytes

Code:

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

Auch 21 Bytes : '|¹9GNNð×:}S'|«JJ'/¶:.

Verwendet die CP-1252- Codierung. Probieren Sie es online aus! .

Adnan
quelle
2

JavaScript (ES6), 69 67 62 Byte

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

Die zusätzlichen Kommas erzeugen leere Werte in der äußeren Teilung, wodurch die Anfangs- und Endzeichen erstellt werden |. Sie benötigen zwei nachgestellte Kommas, da nachfolgende Kommas am Ende von Listen optional sind, sodass das erste noch Teil des vorherigen Elements ist.

Bearbeiten: 5 Bytes dank @ user81655 gespeichert.

Neil
quelle
Würde /[\d/]/g,c=>+c?` `.repeat(c):`\n`funktionieren?
user81655
1
@ user81655 Danke, aber ich mochte dein Emoticon nicht, also habe ich es durch ein genervtes Gesicht mit Brille ersetzt.
Neil
1

Netzhaut , 50 45 Bytes

Das hat Spaß gemacht haha. Ich bin nicht nur ein Noob in Retina, sondern auch in Regex im Allgemeinen ... Dies kann wahrscheinlich viel Golf gespielt werden , also werde ich etwas mehr Forschung betreiben .

Code:

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

1

/
¶

|

Probieren Sie es online aus!

Adnan
quelle
Versuchen Sie, die $*Funktionalität zu nutzen :)
Leaky Nun
1

Jolf, 28 Bytes

RΜGi'/dΆγ'|RGρH«\d»d*♣PHEγγS

Ersetzen Sie durch den Charakter \x05oder versuchen Sie es hier!

Conor O'Brien
quelle
1

Python 3.5, 112 Bytes:

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

Probieren Sie es online aus! (Ideone)

R. Kap
quelle
1

C 252 Bytes

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

Detaillierter Online-Versuch

// 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
quelle
1

JavaScript (FireFox 30+), 61

Verwenden des Array-Verständnisses, das nicht mehr Standard-EcmaScript ist

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

Prüfung

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

Lua, 106 Bytes

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
Katenkyo
quelle
print((...):gsub(".",function(c)return(c:find("%d")and("| "):rep(c)or c=="/"and"|\n"or"|"..c)end).."|")
Undichte Nonne
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("/","|\n"):gsub("([^%d%s|])","|%1").."|")für die gleiche Anzahl von Bytes.
Undichte Nonne
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")ist 101 Bytes
Leaky Nun
1

R (außer Konkurrenz)

Es tut mir leid, wenn es nicht angebracht ist, dies zu posten, aber ich fand es cool, dass ich zufällig eine Funktion herumliegen hatte, die für diese Frage tatsächlich funktioniert, ohne sie zu bearbeiten! Es wird jedoch eher eine Unicode-Ausgabe als eine ASCII-Ausgabe gedruckt. Ich kann mich nicht genau erinnern, warum ich es geschrieben habe, aber es war keine Herausforderung zu beantworten.

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)

}
Flunderer
quelle
Die Regeln in unserem skizzierte Hilfe Zustand , dass alle Lösungen für die Herausforderungen ein ernsthafter Anwärter auf die Gewinnkriterien im Einsatz sein müssen. Für Code-Golf bedeutet dies, dass alle Antworten golfen müssen.
Dennis
Technisch ist es Golf. Nur nicht sehr gut.
Flunderer
0

Haskell, 110 Bytes

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
viercc
quelle
0

Java 7, 190 184 Bytes

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

Detaillierter Online-Versuch

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
quelle
Sie können ein paar Bytes speichern, indem Sie in den Vergleichen Ganzzahlen anstelle von Zeichenliteralen verwenden
Blau
@ Blaue Notizen gemacht
Khaled.K
0

Pyke, 25 bis 20 Bytes

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

Erläuterung:

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

Probieren Sie es hier aus!

Blau
quelle
0

Python, 84 Bytes

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

Erläuterung:

        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
Blau
quelle
0

> <>, 64 Bytes

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

4 verschwendete Bytes aufgrund von Ausrichtungsproblemen, aber nicht sicher, wie man sie herausgolft. ¯ \ _ (ツ) _ / ¯

Sok
quelle