Converter uma sequência de notação Forsyth-Edwards em arte ASCII

9

No xadrez, a notação de Forsyth-Edwards , mais comumente chamada "FEN", é uma maneira textual de transcrever quadros. Ele descreve cada uma das oito linhas do tabuleiro (chamadas de "fileiras" no xadrez) de cima para baixo da perspectiva de White. As peças são escritas como K (rei), Q (rainha), R (torre), B (bispo), N (cavaleiro) e P (peão). Peças pretas usam essas letras em minúsculas e peças brancas usam essas letras em maiúsculas. Os espaços vazios são indicados por um número de 1 a 8, indicando quantos espaços vazios consecutivos existem. Uma classificação completamente vazia seria 8, uma única torre preta na coluna mais à direita (chamada "arquivos" no xadrez) seria 7re dois peões brancos em cada extremidade de uma linha seriam PP4PP. As classificações são separadas por um/. Normalmente, há outras informações adicionadas, indicando de que lado se deve mover, direitos de passagem e de passagem , número de movimentação e relógio meio movimento, mas os ignoraremos para os propósitos deste desafio.

Entrada

Uma string FEN, na linha de comando ou STDIN, como desejar. Você pode assumir que essa sequência é sempre válida.

Resultado

Escreva para STDOUT uma representação artística ASCII simples do quadro, como ele realmente apareceria:

  • As peças são representadas pelo seu caráter na FEN
  • Quadrados vazios são representados por espaços
  • Peças e quadrados são separados por um cano |e existem canos em cada lado do tabuleiro

Portanto, um quadro vazio, escrito como 8/8/8/8/8/8/8/8no FEN, apareceria como

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

A posição inicial de um jogo de xadrez é escrita como rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRe deve aparecer como

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

A posição final de Anderssen-Kieseritzky 1851 , chamada "O Jogo Imortal" na comunidade de xadrez, é escrita como r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1e seu programa, quando alimentado com essa entrada, produziria:

|r| |b|k| | | |r|
|p| | |p|B|p|N|p|
|n| | | | |n| | |
| |p| |N|P| | |P|
| | | | | | |P| |
| | | |P| | | | |
|P| |P| |K| | | |
|q| | | | | |b| |
EMBLEMA
fonte
É aceitável escrever uma função que recebe entrada e retorna a saída, em vez de gravá-la em STDOUT?
Fund Monica's Lawsuit
@QPaysTaxes Por padrão, permitimos e, de fato, várias soluções já o fazem. Por fim, cabe ao OP, embora pareça desnecessário substituir nossos padrões neste caso.
Alex A.
2
A resposta que você aceitou não é a mais curta. Independentemente de seus sentimentos em relação aos idiomas do golfe, o código de golfe significa que o código mais curto vence.
Dennis
3
Você também não pode penalizá-los ou aceitar uma resposta arbitrária . Todo o site é construído em torno de critérios objetivos de vitória.
Dennis
11
+1para um desafio interessante. -2por aceitar a resposta errada, sem uma boa razão #
James James

Respostas:

9

Perl, 28 bytes

Inclui +2 para -lp

Dê entrada no STDIN

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

fen.pl:

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

Na verdade, na liga de algumas línguas de golfe ...

Observe que a versão baseada em arquivo precisa da nova linha final no arquivo, de modo que uma tenha realmente 29 bytes. Mas a versão da linha de comando não precisa dessa nova linha extra e, portanto, o código conta como 28 bytes:

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

Retina, 13 bytes

\d
$* 
/
¶

|

Experimente online!

Explicação

A primeira parte (observe o espaço à direita):

\d
$* 

é converter a para o número específico de espaços. A retina tem um $*recurso para repetir. A maneira como funciona é: <num>$*<char>se não houver <num>, Retina assumirá $&ou a sequência correspondente, nesse caso, o número correspondente.

A próxima parte:

/
¶

é bastante simples, substitui tudo /com o que é uma nova linha.

A última parte funciona da mesma maneira:

    
|

Isso substituirá tudo (por isso, não há nada na primeira linha) por |. Colocando um em |todo lugar.

Downgoat
fonte
11
Você pode até fazer tudo em ASCII para a mesma contagem de bytes S`/que no segundo estágio.
Martin Ender
12

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

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

Economizou alguns bytes graças a Ventero

Deixe-me explicar (com a \nsubstituição da nova linha literal):

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

Isso retorna implicitamente o valor da sequência, cada uma /substituída por uma nova linha (por padrão, $/contém uma nova linha)

"|#{...}|"

Isso é super simples; é apenas uma string contendo um tubo, interpolação de string e outro pipe. A interpolação de cadeia é avaliada

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

Isso substitui todos os números por tantos espaços. Também posso economizar alguns bytes encontrando novas linhas aqui; porque hexretorna 0 se a string não é um número válido, quando encontra uma nova linha - ou seja, a que está no final do resultado de gets-, ela a substitui por uma string de comprimento 0, excluindo-a efetivamente. Sem isso, haveria um cano à direita.

$&é uma variável mágica que representa o texto completo da última correspondência de variáveis, o que permite salvar um byte ao eliminar |d|. Posso salvar outro byte usando em .hexvez de .to_i, o que funciona porque todo número é menor que 9, o que significa que hex e decimal têm os mesmos valores.

.chars*?|

Isso coloca um cano entre cada personagem. Observe que é isso que coloca os tubos em ambos os lados das linhas (exceto o primeiro e o último), porque as barras, que eventualmente se transformam em novas linhas tr, contam como caracteres e, portanto, são cercadas por tubos. O ?|justo significa "a cadeia de um caractere "|"".

E é isso. É um programa francamente escandalosamente simples. Ele usa muitos truques de sintaxe furtivos.

Fund Processo de Monica
fonte
2
Você pode salvar mais 4 caracteres aplicando alguns truques simples: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(é claro, substitua-o \npor uma nova linha literal novamente).
Ventero
5

Pyth - 24 22 21 bytes

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

Conjunto de Teste .

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

Pitão, 23 bytes

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

Experimente online!

Como funciona:

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
Freira Furada
fonte
4

JavaScript ES7, 80 bytes

É uma função anônima que aceita uma string como entrada.

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

Aproximação somente de ES6 de 80 bytes.

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

Explicação

Usamos uma compreensão de array para percorrer a lista:

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

Isso é equivalente a:

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

Se é um número, temos esse número de espaços. Se for um /, temos uma nova linha. Caso contrário, temos o personagem. Então, juntamos a compreensão sem nada para formar uma corda.

Em seguida, criamos uma matriz de comprimento 3 [,...that,"\n"]. ...divide a compreensão unida em caracteres. Juntar-se a isso produz o resultado.

Conor O'Brien
fonte
Você não quer dizer ES6? ES7 ainda não saiu, acredito.
precisa saber é o seguinte
@ ericw31415 Não está fora, você está correto, mas alguns navegadores começaram a implementar parte das especificações do ES7.
Conor O'Brien
Ah ok. Mas seu código ainda não usa nenhum dos recursos do ES7, certo?
precisa saber é o seguinte
11
@ ericw31415 Na verdade, sim. Compreensões de matriz ( [x for(x of a)]) são ES7.
Conor O'Brien
Não eram Comprehensions matriz removidos do spec, MDN diz que eles eram
MayorMonty
3

Julia, 62 bytes

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

Esta é uma função anônima que aceita uma string e retorna uma matriz de strings. Para chamá-lo, atribua-o a uma variável.

A abordagem é a mesma que em Ruby inteligente QPaysTaxes resposta . Substituímos cada dígito na entrada por tantos espaços, posicionamos |entre cada caractere, aderimos |à frente e atrás e dividimos em uma matriz /.

Experimente online!

Alex A.
fonte
Yay eu inspirou as coisas: D
Fund Monica's Lawsuit
@QPaysTaxes Você fez de fato. Ótima solução!
Alex A.
2

05AB1E , 21 bytes

Código:

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

Também 21 de bytes: '|¹9GNNð×:}S'|«JJ'/¶:.

Usa a codificação CP-1252 .Experimente online! .

Adnan
fonte
2

JavaScript (ES6), 69 67 62 bytes

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

As vírgulas extras criam valores vazios na divisão externa, que cria o começo e o fim | caracteres . Você precisa de duas vírgulas finais, pois as vírgulas finais são opcionais no final das listas; portanto, a primeira ainda faz parte do item anterior.

Editar: salvou 5 bytes graças a @ user81655.

Neil
fonte
Funcionaria /[\d/]/g,c=>+c?` `.repeat(c):`\n`?
precisa saber é o seguinte
11
@ user81655 Obrigado, mas eu não gostei do seu emoticon, então o substitui por um rosto irritado por óculos.
Neil
1

Retina , 50 45 bytes

Isso foi divertido haha. Não sou apenas um noob em Retina, mas também em regex em geral ... Isso provavelmente pode ser muito praticado , então vou fazer mais algumas pesquisas.

Código:

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

1

/
¶

|

Experimente online!

Adnan
fonte
Tente usar a $*funcionalidade :)
Leaky Nun
1

Jolf, 28 bytes

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

Substitua pelo personagem \x05ou tente aqui!

Conor O'Brien
fonte
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])+'|')

Experimente online! (Ideona)

R. Kap
fonte
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;}

Teste detalhado 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
fonte
1

JavaScript (FireFox 30+), 61

Usando compreensão de array que não é mais o padrão EcmaScript

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

Teste

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
fonte
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
fonte
print((...):gsub(".",function(c)return(c:find("%d")and("| "):rep(c)or c=="/"and"|\n"or"|"..c)end).."|")
Freira vazando
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("/","|\n"):gsub("([^%d%s|])","|%1").."|")para a mesma contagem de bytes.
Freira vazando
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")é 101 bytes
Freira vazada
1

R (fora de competição)

Desculpe se não é apropriado postar isso, mas achei legal que por acaso tivesse uma função por aí que realmente funcionasse para essa pergunta sem editar! Porém, ele imprime saída unicode em vez de ascii. Não me lembro bem por que o escrevi, mas não foi para responder a um desafio.

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)

}
Solha
fonte
As regras descritas em nossa central de ajuda afirmam que todas as soluções para os desafios devem ser um candidato sério aos critérios vencedores em uso. Para o código de golfe, isso significa que todas as respostas devem ser golfadas.
Dennis
Tecnicamente, é jogado de golfe. Apenas não muito bem.
quer
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
fonte
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+"|";}

Teste detalhado 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
fonte
Você pode salvar um par de bytes estar usando números inteiros em vez de literais de char nas comparações
Azul
@Blue notes taken
Khaled.K
0

Pyke, 25 20 bytes

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

Explicação:

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

Experimente aqui!

Azul
fonte
0

Python, 84 bytes

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

Explicação:

        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
Azul
fonte
0

> <>, 64 bytes

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

4 bytes desperdiçados devido a problemas de alinhamento, embora não tenha certeza de como usá-los. ¯ \ _ (ツ) _ / ¯

Sok
fonte