Mengonversi string Notasi Forsyth-Edwards ke ASCII art

9

Dalam catur, Forsyth-Edwards Notation , lebih umum disebut "FEN", adalah cara tekstual papan transkrip. Ini menggambarkan masing-masing dari delapan baris papan (disebut "peringkat" dalam catur) dari atas ke bawah dari perspektif White. Potongan ditulis sebagai K (raja), Q (ratu), R (benteng), B (uskup), N (ksatria), dan P (gadai). Potongan hitam menggunakan huruf-huruf ini dalam huruf kecil, dan potongan putih menggunakan huruf-huruf ini dalam huruf besar. Ruang kosong ditandai dengan angka dari 1 hingga 8 yang menunjukkan berapa banyak ruang kosong berturut-turut. Pangkat yang benar-benar kosong adalah 8, satu benteng hitam di kolom paling kanan (disebut "file" dalam catur) 7r, dan dua pion putih di setiap ujung baris akan menjadi PP4PP. Peringkat dipisahkan oleh a/. Biasanya ada informasi lain yang ditambahkan, menunjukkan sisi yang bergerak, Castling dan en passant hak, jumlah bergerak, dan jam halfmove, tapi kami akan mengabaikan mereka untuk tujuan tantangan ini.

Memasukkan

Sebuah string FEN, dari baris perintah atau STDIN, sesuka Anda. Anda dapat mengasumsikan bahwa string ini selalu valid.

Keluaran

Menulis ke STDOUT representasi seni sederhana ASCII dari papan seperti yang sebenarnya akan muncul:

  • Potongan diwakili oleh karakter mereka di FEN
  • Kotak kosong diwakili oleh spasi
  • Potongan dan kotak dipisahkan oleh pipa |dan ada pipa di setiap sisi papan

Jadi papan kosong, ditulis seperti 8/8/8/8/8/8/8/8dalam FEN, akan muncul sebagai

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

Posisi awal permainan catur ditulis sebagai rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR, dan akan muncul sebagai

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

Posisi akhir dari Anderssen-Kieseritzky 1851 , yang disebut "The Immortal Game" di komunitas catur, ditulis sebagai r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1, dan program Anda ketika diumpankan bahwa input akan menghasilkan:

|r| |b|k| | | |r|
|p| | |p|B|p|N|p|
|n| | | | |n| | |
| |p| |N|P| | |P|
| | | | | | |P| |
| | | |P| | | | |
|P| |P| |K| | | |
|q| | | | | |b| |
LAMBANG
sumber
Apakah bisa menulis fungsi yang mengambil input dan mengembalikan output, daripada menulisnya ke STDOUT?
Dana Gugatan Monica
@QPaysTaxes Secara default kami mengizinkannya dan memang beberapa solusi sudah melakukannya. Pada akhirnya terserah OP meskipun tampaknya tidak perlu untuk menimpa default kami dalam kasus ini.
Alex A.
2
Jawaban yang Anda terima bukan yang terpendek. Terlepas dari perasaan Anda terhadap bahasa golf, kode golf berarti bahwa kode terpendek menang.
Dennis
3
Anda juga tidak dapat menghukum mereka atau menerima jawaban yang sewenang-wenang . Seluruh situs dibangun berdasarkan kriteria pemenang objektif .
Dennis
1
+1untuk tantangan yang menarik. -2karena menerima jawaban yang salah tanpa alasan yang baik
James

Jawaban:

9

Perl, 28 byte

Termasuk +2 untuk -lp

Berikan masukan pada STDIN

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

fen.pl:

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

Sebenarnya di liga beberapa bahasa golf ...

Perhatikan bahwa versi berbasis file membutuhkan baris terakhir dalam file sehingga satu benar-benar 29 byte. Tetapi versi commandline tidak memerlukan baris baru tambahan dan oleh karena itu kode ini dihitung sebagai 28 byte:

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

Retina, 13 byte

\d
$* 
/
¶

|

Cobalah online!

Penjelasan

Bagian pertama (perhatikan spasi tambahan):

\d
$* 

adalah untuk mengonversi a ke jumlah ruang tertentu. Retina memiliki $*fitur untuk diulang. Cara kerjanya adalah: <num>$*<char>jika tidak ada <num>, Retina akan menganggap $&atau string yang cocok, dalam hal ini nomor yang cocok.

Bagian selanjutnya:

/
¶

cukup sederhana, itu menggantikan semua /dengan yang baris baru.

Bagian terakhir berfungsi sama:

    
|

Ini akan menggantikan semuanya (karenanya mengapa tidak ada pada baris pertama) dengan |. Menempatkan di |mana - mana.

Downgoat
sumber
1
Anda bahkan dapat melakukan semuanya di ASCII untuk jumlah byte yang sama dengan S`/tahap kedua.
Martin Ender
12

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

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

Disimpan beberapa byte berkat Ventero

Biarkan saya jelaskan (dengan \nmengganti baris literal):

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

Ini secara implisit mengembalikan nilai string, dengan masing-masing /diganti dengan baris baru (secara default, $/berisi baris baru)

"|#{...}|"

Ini sangat sederhana; itu hanya string yang berisi pipa, interpolasi string, dan pipa lain. Interpolasi string dievaluasi

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

Ini menggantikan setiap angka dengan banyak ruang. Saya dapat menyimpan beberapa byte dengan juga menemukan baris baru di sini; karena hexmengembalikan 0 jika string bukan angka yang valid, ketika ia menemukan baris baru - yaitu baris di akhir hasil gets- menggantikannya dengan string 0 panjang, secara efektif menghapusnya. Tanpa ini, akan ada pipa trailing.

$&adalah variabel ajaib yang mewakili teks lengkap dari pencocokan variabel terbaru, yang memungkinkan saya menyimpan byte dengan menghilangkan |d|. Saya dapat menyimpan byte lain dengan menggunakan .hexalih-alih .to_i, yang berfungsi karena setiap angka kurang dari 9, yang berarti bahwa hex dan desimal memiliki nilai yang sama.

.chars*?|

Ini menempatkan pipa di antara setiap karakter. Perhatikan bahwa inilah yang menempatkan pipa di kedua sisi garis (kecuali yang pertama dan terakhir) karena garis miring, yang akhirnya berubah menjadi garis baru melalui tr, dihitung sebagai karakter, dan karena itu dikelilingi oleh pipa. The ?|hanya berarti "string satu karakter "|"".

Dan ... itu saja. Ini adalah program sederhana yang sangat memalukan. Itu hanya menggunakan banyak trik sintaksis yang licik.

Dana Gugatan Monica
sumber
2
Anda dapat menyimpan 4 karakter lagi dengan menerapkan beberapa trik sederhana: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(tentu saja, ganti \ndengan baris baru literal lagi).
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
Maltysen
sumber
4

Pyth, 23 byte

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

Cobalah online!

Bagaimana itu bekerja:

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
Biarawati Bocor
sumber
4

JavaScript ES7, 80 70 byte

Merupakan fungsi anonim yang menerima string sebagai input.

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

Appraoch 80-byte ES6 saja.

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

Penjelasan

Kami menggunakan pemahaman array untuk mengulang daftar:

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

Ini setara dengan:

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

Jika itu angka, kita punya jumlah spasi itu. Jika a /, kami memiliki baris baru. Kalau tidak, kita punya karakter. Kemudian, kami bergabung dengan pemahaman tanpa membuat string.

Kemudian, kami membuat array dengan panjang 3 [,...that,"\n"]. ...memecah pemahaman gabungan menjadi karakter. Bergabung dengan ini menghasilkan hasilnya.

Conor O'Brien
sumber
Bukankah maksud Anda ES6? ES7 belum keluar saya percaya.
ericw31415
@ ericw31415 Itu tidak keluar, Anda benar, tetapi beberapa browser sudah mulai menerapkan bagian dari spesifikasi ES7.
Conor O'Brien
Oh oke. Tapi tetap saja kode Anda tidak menggunakan salah satu fitur ES7, kan?
ericw31415
1
@ ericw31415 Sebenarnya, itu benar. Pemahaman array ( [x for(x of a)]) adalah ES7.
Conor O'Brien
Weron't Array Comprehensions dihapus dari spec, MDN mengatakan mereka
MayorMonty
3

Julia, 62 byte

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

Ini adalah fungsi anonim yang menerima string dan mengembalikan array string. Untuk menyebutnya, tetapkan ke variabel.

Pendekatan ini sama seperti di QPaysTaxes' pintar Ruby jawabannya . Kami mengganti setiap digit dalam input dengan banyak spasi, tempat di |antara setiap karakter, |tempelkan ke depan dan belakang, dan pisahkan menjadi larik /.

Cobalah online!

Alex A.
sumber
Yay I menginspirasi hal-hal: D
Gugatan Monica's
@QPaysTaxes Anda benar-benar melakukannya. Solusi bagus!
Alex A.
2

05AB1E , 21 byte

Kode:

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

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

Menggunakan pengodean CP-1252 . Cobalah online! .

Adnan
sumber
2

JavaScript (ES6), 69 67 62 byte

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

Koma ekstra membuat nilai kosong di pemisahan luar yang membuat karakter awal dan akhir |. Anda memerlukan dua koma trailing karena trailing koma adalah opsional di akhir daftar, jadi yang pertama masih merupakan bagian dari item sebelumnya.

Sunting: Disimpan 5 byte berkat @ user81655.

Neil
sumber
Akan /[\d/]/g,c=>+c?` `.repeat(c):`\n`bekerja
user81655
1
@ user81655 Terima kasih, tapi saya tidak suka emoticon Anda, jadi saya menggantinya dengan wajah kesal dengan kacamata.
Neil
1

Retina , 50 45 byte

Ini menyenangkan haha. Tidak hanya saya seorang noob di Retina, tetapi juga di regex secara umum ... Ini mungkin bisa bermain golf banyak , jadi saya akan melakukan riset lebih lanjut.

Kode:

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

1

/
¶

|

Cobalah online!

Adnan
sumber
Coba gunakan $*fungsi :)
Leaky Nun
1

Jolf, 28 byte

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

Ganti dengan karakter \x05, atau coba di sini!

Conor O'Brien
sumber
1

Python 3.5, 112 byte:

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

Cobalah online! (Ideone)

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

Detail coba 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
sumber
1

JavaScript (FireFox 30+), 61

Menggunakan pemahaman array yang bukan standar EcmaScript lagi

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

Uji

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

Lua, 106 Bytes

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

Tidak disatukan

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
sumber
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").."|")untuk byte-count yang sama.
Leaky Nun
print((...):gsub("%d",function(c)return("| "):rep(c)end):gsub("([^%d |])","|%1"):gsub("/","\n").."|")is 101 bytes
Leaky Nun
1

R (keluar dari kompetisi)

Maaf jika tidak pantas memposting ini, tapi saya pikir itu keren bahwa saya kebetulan memiliki fungsi yang sebenarnya berfungsi untuk pertanyaan ini tanpa mengedit! Ia mencetak keluaran unicode daripada ascii. Saya tidak ingat mengapa saya menulisnya, tetapi itu bukan untuk menjawab tantangan.

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)

}
Flounderer
sumber
Aturan yang diuraikan dalam pusat bantuan kami menyatakan bahwa semua solusi untuk tantangan harus menjadi pesaing serius untuk kriteria kemenangan yang digunakan. Untuk golf kode, ini artinya semua jawaban harus golf.
Dennis
Secara teknis, golf. Tidak begitu baik.
Flounderer
0

Haskell, 110 Bytes

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

Tidak Disatukan:

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

Detail coba 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
sumber
Anda dapat menyimpan beberapa byte menggunakan integer alih-alih char literals dalam perbandingan
Blue
@Blue notes diambil
Khaled.K
0

Pyke, 25 20 byte

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

Penjelasan:

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

Coba di sini!

Biru
sumber
0

Python, 84 byte

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

Penjelasan:

        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
Biru
sumber
0

> <>, 64 byte

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

4 byte terbuang karena masalah penyelarasan, tidak yakin bagaimana cara membuatnya. ¯ \ _ (ツ) _ / ¯

Sok
sumber