Converti una stringa di notazione Forsyth-Edwards in arte ASCII


9

Negli scacchi, la notazione di Forsyth-Edwards , più comunemente chiamata "FEN", è un modo testuale di trascrivere le schede. Descrive ciascuna delle otto file della scacchiera (chiamate "ranghi" negli scacchi) dall'alto verso il basso dalla prospettiva di White. I pezzi sono scritti come K (re), Q (regina), R (torre), B (vescovo), N (cavaliere) e P (pedone). I pezzi neri usano queste lettere in minuscolo e i pezzi bianchi usano queste lettere in maiuscolo. Gli spazi vuoti sono indicati da un numero da 1 a 8 che indica quanti spazi vuoti consecutivi ci sono. Un rango completamente vuoto sarebbe 8, una singola torre nera nella colonna più a destra (chiamata "file" negli scacchi) 7re due pedine bianche su ciascuna estremità di una fila PP4PP. I ranghi sono separati da a/. Di solito vengono aggiunte altre informazioni, che indicano da che parte devono spostarsi, i diritti di castling e en passant , il numero di movimento e l'orologio a metà movimento, ma li ignoreremo ai fini di questa sfida.

Ingresso

Una stringa FEN, dalla riga di comando o STDIN, come preferisci. Puoi presumere che questa stringa sia sempre valida.

Produzione

Scrivi a STDOUT una semplice rappresentazione in arte ASCII della lavagna come sembrerebbe effettivamente:

  • I pezzi sono rappresentati dal loro personaggio in FEN
  • I quadrati vuoti sono rappresentati da spazi
  • Pezzi e quadrati sono separati da un tubo |e ci sono tubi su ciascun lato del tabellone

Quindi 8/8/8/8/8/8/8/8appare una lavagna vuota, scritta come in FEN

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

La posizione iniziale di una partita a scacchi è scritta come rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRe apparirebbe come

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

La posizione finale di Anderssen-Kieseritzky 1851 , chiamata "The Immortal Game" nella comunità degli scacchi, è scritta come r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1, e il tuo programma quando alimentato quell'input produrrebbe:

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

È accettabile scrivere una funzione che accetta input e restituisce output, anziché scriverlo su STDOUT?
Finanzia la causa di Monica il

@QPaysTaxes Per impostazione predefinita lo consentiamo e in effetti diverse soluzioni lo fanno già. Alla fine spetta all'OP, anche se in questo caso non sembra necessario sostituire le nostre impostazioni predefinite.
Alex A.

2
La risposta che hai accettato non è la più breve. Indipendentemente dai tuoi sentimenti verso le lingue del golf, il codice golf significa che vince il codice più corto .
Dennis,

3
Inoltre, non puoi penalizzarli o accettare una risposta arbitraria . L'intero sito è costruito attorno a criteri vincenti oggettivi .
Dennis,

1
+1per una sfida interessante. -2per aver accettato la risposta sbagliata senza una buona ragione
James,

Risposte:


9

Perl, 28 byte

Include +2 per -lp

Dare input su STDIN

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

fen.pl:

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

In realtà nella lega di alcune lingue del golf ...

Si noti che la versione basata su file richiede la nuova riga finale nel file in modo che uno sia in realtà 29 byte. Ma la versione da riga di comando non ha bisogno di quella nuova riga aggiuntiva e quindi il codice conta come 28 byte:

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

1
Missbang mancante?
user253751

15

Retina, 13 byte

\d
$* 
/
¶

|

Provalo online!

Spiegazione

La prima parte (notare lo spazio finale):

\d
$* 

è convertire a nel numero specifico di spazi. Retina ha una $*funzione da ripetere. Il modo in cui funziona è: <num>$*<char>se non c'è <num>, Retina assumerà $&o la stringa corrispondente, in questo caso il numero corrispondente.

La prossima parte:

/
¶

è piuttosto semplice, sostituisce tutto ciò /con cui è una nuova riga.

L'ultima parte funziona allo stesso modo:

    
|

Questo sostituirà tutto (quindi perché non c'è nulla nella prima riga) con |. Mettere un |ovunque.


1
Puoi persino fare tutto in ASCII per lo stesso conteggio dei byte S`/del secondo stadio.
Martin Ender,

12

Rubino - 75 82 78 76 75 62 59 58 57 56 byte

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

Risparmio di pochi byte grazie a Ventero

Lasciami spiegare (con la \nsostituzione della nuova riga letterale):

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

Ciò restituisce implicitamente il valore della stringa, ciascuna /sostituita con una nuova riga (per impostazione predefinita, $/contiene una nuova riga)

"|#{...}|"

Questo è super semplice; è solo una stringa contenente una pipe, interpolazione di stringhe e un'altra pipe. Viene valutata l'interpolazione di stringhe

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

Questo sostituisce ogni numero con tanti spazi. Posso salvare qualche byte trovando anche nuove righe qui; perché hexrestituisce 0 se la stringa non è un numero valido, quando trova una nuova riga –- cioè quella alla fine del risultato getsdi-- la sostituisce con una stringa di lunghezza 0, eliminandola efficacemente. Senza questo, ci sarebbe un tubo finale.

$&è una variabile magica che rappresenta il testo completo dell'ultima variabile variabile, che mi consente di salvare un byte eliminando |d|. Posso salvare un altro byte usando .hexinvece di .to_i, il che funziona perché ogni numero è inferiore a 9, il che significa che esadecimale e decimale hanno gli stessi valori.

.chars*?|

Questo mette un tubo tra ogni personaggio. Si noti che questo è ciò che mette le pipe su entrambi i lati delle linee (tranne la prima e l'ultima) perché le barre, che alla fine si trasformano in nuove linee tr, contano come caratteri e sono quindi circondate da pipe. Il ?|giusto significa "la stringa di un carattere "|"".

E ... tutto qui. È un programma francamente scandalosamente semplice. Utilizza solo molti trucchi per la sintassi subdoli.


2
Puoi salvare altri 4 personaggi applicando alcuni semplici trucchi: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(ovviamente, sostituiscili \ncon una nuova riga letterale).
Ventero,

5

Pyth - 24 22 21 byte

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

Test Suite .

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

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

Provalo online!

Come funziona:

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 byte

È una funzione anonima che accetta una stringa come input.

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

Valutazione solo ES6 a 80 byte.

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

Spiegazione

Usiamo una comprensione di array per scorrere l'elenco:

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

Ciò equivale a:

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

Se è un numero, abbiamo quel numero di spazi. Se è un /, abbiamo una nuova riga. Altrimenti, abbiamo il personaggio. Quindi, uniamo la comprensione con niente per creare una stringa.

Quindi, creiamo un array di lunghezza 3 [,...that,"\n"]. ...divide la comprensione unita in caratteri. Unendo questo si ottiene il risultato.


Non intendi ES6? ES7 non è ancora uscito, credo.
ericw31415,

@ ericw31415 Non è fuori, hai ragione, ma alcuni browser hanno iniziato a implementare parte delle specifiche ES7.
Conor O'Brien,

Oh va bene. Ma il tuo codice non utilizza nessuna delle funzionalità ES7, giusto?
ericw31415,

1
@ ericw31415 In realtà, lo fa. Le comprensioni dell'array ( [x for(x of a)]) sono ES7.
Conor O'Brien,

Le comprensioni dell'array non sono state rimosse dalle specifiche, MDN afferma che lo erano
MayorMonty

3

Julia, 62 byte

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

Questa è una funzione anonima che accetta una stringa e restituisce una matrice di stringhe. Per chiamarlo, assegnarlo a una variabile.

L'approccio è lo stesso che nel intelligente Rubino QPaysTaxes' risposta . Sostituiamo ogni cifra nell'input con tanti spazi, posizioniamo |tra ciascun personaggio, virate |sul fronte e sul retro e divisi in un array /.

Provalo online!


Yay ho ispirato le cose: D
Finanzi la causa di Monica l'

@QPaysTaxes L'hai fatto davvero. Bella soluzione!
Alex A.


2

JavaScript (ES6), 69 67 62 byte

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

Le virgole aggiuntive creano valori vuoti nella divisione esterna che crea i caratteri iniziale e finale |. Sono necessarie due virgole finali perché le virgole finali sono facoltative alla fine degli elenchi, quindi la prima fa ancora parte dell'elemento precedente.

Modifica: salvato 5 byte grazie a @ user81655.


Funzionerebbe /[\d/]/g,c=>+c?` `.repeat(c):`\n`?
user81655

1
@ user81655 Grazie, ma la tua emoticon non mi è piaciuta, quindi l'ho sostituita con una faccia irritata con gli occhiali.
Neil,

1

Retina , 50 45 byte

Questo è stato divertente haha. Non solo sono un noob in Retina, ma anche in regex in generale ... Probabilmente questo può essere giocato a golf molto , quindi farò qualche ricerca in più.

Codice:

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

1

/
¶

|

Provalo online!


Prova a utilizzare la $*funzionalità :)
Leaky Nun,



1

C, 252 byte

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

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

1

JavaScript (FireFox 30+), 61

Utilizzo della comprensione dell'array che non è più lo standard 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>


1

Lua, 106 byte

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

print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("/","|\n"):gsub("([^%d%s|])","|%1").."|")per lo stesso conteggio byte.
Leaky Nun,

print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")è 101 byte
Leaky Nun,

1

R (fuori concorso)

Scusate se non è appropriato pubblicare questo, ma ho pensato che fosse bello avere una funzione che funziona davvero per questa domanda senza modificarla! Tuttavia, stampa l'output Unicode anziché ASCII. Non ricordo bene perché l'ho scritto, ma non era per rispondere a una sfida.

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)

}

Le regole delineate nel nostro centro assistenza affermano che tutte le soluzioni alle sfide devono essere un serio contendente per i criteri vincenti in uso. Per il golf del codice, ciò significa che tutte le risposte devono essere giocate a golf.
Dennis,

Tecnicamente, è golf. Solo non molto bene.
Flounderer,

0

Haskell, 110 byte

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 byte

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

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

È possibile salvare un paio di byte utilizzando i numeri interi anziché i caratteri letterali nei confronti
Blue

@Blue note prese
Khaled.K

0

Pyke, 25 20 byte

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

Spiegazione:

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

Provalo qui!


0

Python, 84 byte

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

Spiegazione:

        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 byte

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

4 byte sprecati a causa di problemi di allineamento, ma non sono sicuro di come giocarli. ¯ \ _ (ツ) _ / ¯

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.