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

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"

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.


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.


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

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

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.


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!


Ja, ich habe Dinge inspiriert: D
Fund Monicas Klage

@QPaysTaxes Du hast es tatsächlich getan. Schöne Lösung!
Alex A.


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.


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!


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



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

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>


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

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)

}

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

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

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!


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

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. ¯ \ _ (ツ) _ / ¯

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.