Forsyth-Edwards Notasyonu dizesini ASCII sanatına dönüştürme


9

Satrançta, daha yaygın olarak "FEN" olarak adlandırılan Forsyth-Edwards Notasyonu , tahtaları kopyalamanın metinsel bir yoludur. Tahtanın sekiz satırının her birini (satrançta "rütbe" olarak adlandırılır) yukarıdan aşağıya White'ın bakış açısından tanımlar. Eserler K (kral), Q (kraliçe), R (kale), B (fil), N (şövalye) ve P (piyon) olarak yazılır. Siyah parçalar bu harfleri küçük harflerle, beyaz parçalar ise bu harfleri büyük harflerle kullanır. Boş alanlar, ardışık kaç boş alan olduğunu gösteren 1'den 8'e kadar bir sayı ile gösterilir. Tamamen boş bir rütbe 8, en sağdaki sütunda tek bir siyah kale (satrançta "dosyalar" olarak adlandırılır) 7rve bir satırın her iki ucunda iki beyaz piyon olurdu PP4PP. Rütbeler bir/. Eklenen diğer bilgiler, hareket rok ve hangi tarafı gösteren normalde yoktur passant tr hakları, hareket sayısı ve halfmove saat, ama biz bu meydan amaçları için onları göz ardı eder.

Giriş

İstediğiniz gibi komut satırından veya STDIN'den bir FEN dizesi. Bu dizenin her zaman geçerli olduğunu varsayabilirsiniz.

Çıktı

STDOUT'a anakartın göründüğü gibi basit bir ASCII sanat temsilini yazın:

  • Parçalar FEN'deki karakterleriyle temsil edilir
  • Boş kareler boşluklarla temsil edilir
  • Parçalar ve kareler bir boru ile ayrılır |ve tahtanın her iki tarafında borular vardır

Yani 8/8/8/8/8/8/8/8FEN'de olduğu gibi yazılmış boş bir tahta

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

Bir satranç oyununun başlangıç ​​pozisyonu şu şekilde yazılır rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNRve

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

Satranç topluluğunda "Ölümsüz Oyun" olarak adlandırılan Anderssen-Kieseritzky 1851'in son pozisyonu olarak yazılır r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1ve bu girdiyi beslerken programınız çıktı verir:

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

STDOUT'a yazmak yerine girdi ve çıktı döndüren bir fonksiyon yazmak kabul edilebilir mi?
Monica'nın Davası

@QPaysTaxes Varsayılan olarak buna izin veriyoruz ve gerçekten de birkaç çözüm bunu zaten yapıyor. Bu durumda varsayılanlarımızı geçersiz kılmak gereksiz görünse de, sonuçta OP'ye kalmış.
Alex

2
Kabul ettiğin cevap en kısa cevap değil. Golf dillerine karşı hisleriniz ne olursa olsun, kod golf en kısa kodun kazanacağı anlamına gelir .
Dennis

3
Ayrıca onları cezalandıramaz veya keyfi bir cevabı kabul edemezsiniz . Sitenin tamamı objektif kazanma kriterleri üzerine inşa edilmiştir .
Dennis

1
+1ilginç bir meydan okuma için. iyi bir sebep olmadan-2 yanlış cevabı kabul ettikleri için
James

Yanıtlar:


9

Perl, 28 bayt

İçin +2 içerir -lp

STDIN'e giriş verin

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

fen.pl:

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

Aslında bazı golf dilleri liginde ...

Dosya tabanlı sürümün dosyadaki son yeni satıra ihtiyaç duyduğuna dikkat edin, böylece gerçekten 29 bayt olur. Ancak komut satırı sürümü için ekstra satırsonu gerekmez ve bu nedenle kod 28 bayt olarak sayılır:

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

1
Mesele mi eksik?
user253751

15

Retina, 13 bayt

\d
$* 
/
¶

|

Çevrimiçi deneyin!

açıklama

İlk bölüm (sondaki boşluğa dikkat edin):

\d
$* 

a'yı belirli sayıda boşluğa dönüştürmektir. Retina'nın $*tekrarlama özelliği vardır . Çalışma şekli şudur: <num>$*<char>eğer yoksa <num>, Retina varsa $&veya eşleşen dizeyi, bu durumda eşleşen numarayı varsayar .

Sonraki bölüm:

/
¶

hepsi değiştirir, oldukça basit /olan hangi bir satır olduğunu.

Son bölüm aynı şekilde çalışır:

    
|

Bu, her şeyin yerini alacaktır (bu nedenle ilk satırda neden hiçbir şey yoktur) |. |Her yere koyuyorum .


1
Hepsini ASCII'de S`/ikinci aşama ile aynı bayt sayısı için bile yapabilirsiniz .
Martin Ender

12

Yakut - 75 82 78 76 75 62 59 58 57 56 bayt

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

Ventero sayesinde birkaç bayt tasarruf edildi

Açıklamama izin verin ( \ndeğişmez satırsonunu değiştirerek):

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

Bu, dizenin değerini dolaylı olarak döndürür ve her biri /bir satırsonu ile değiştirilir (varsayılan olarak $/satırsonu içerir)

"|#{...}|"

Bu çok basit; bu sadece bir boru, dize enterpolasyonu ve başka bir boru içeren bir dizedir. Dize enterpolasyonu değerlendirilir

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

Bu, her sayıyı bu kadar çok alanla değiştirir. Burada yeni satırlar da bularak birkaç bayt tasarruf edebilirim; çünkü hexdize geçerli bir sayı değilse 0 döndürür, eğer bir satırsonu bulduğunda - yani sonucun sonunda bulunan satır - getsonu 0 uzunluklu bir dize ile değiştirir ve etkin bir şekilde siler. Bu olmadan, bir sondaki boru olurdu.

$&en son değişken eşleşmesinin tam metnini temsil eden sihirli bir değişkendir |d|. Bunun .hexyerine kullanarak başka bir bayt kaydedebilirim .to_i, çünkü her sayı 9'dan küçüktür, bu da onaltılık ve ondalık sayıların aynı değerlere sahip olduğu anlamına gelir.

.chars*?|

Bu, her karakter arasına bir boru koyar. Boruları satırların her iki tarafına da (ilk ve son hariç) koyan şey olduğuna dikkat edin, çünkü sonunda satırlara dönüşen eğik çizgiler trkarakter olarak sayılır ve bu nedenle borularla çevrelenir. ?|Sadece aracı "tek karakter dizesi "|"".

Ve bu kadar. Açıkçası skandal bir şekilde basit bir program. Sadece çok sinsi sözdizimi kullanır.


2
Birkaç basit numara uygulayarak 4 karakter daha kaydedebilirsiniz: puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'(tabii ki, yerine \ntekrar bir gerçek satırsonu ekleyin).
Ventero

5

Pyth - 24 22 21 bayt

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

Test Takımı .

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

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

Çevrimiçi deneyin!

Nasıl çalışır:

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 bayt

Dizeyi giriş olarak kabul eden anonim bir işlevdir.

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

80 baytlık ES6 salt değerlendirme.

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

açıklama

Listenin üzerinden geçmek için bir dizi kavrama kullanırız:

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

Bu şuna eşittir:

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

Bu bir sayı ise, o kadar boşluğa sahibiz. Eğer öyleyse /, bir satırsonumuz var. Aksi takdirde, bizim karakterimiz var. Sonra, bir ip yapmak için hiçbir şey olmadan kavrayışa katılırız.

Ardından, 3 uzunluklu bir dizi oluştururuz [,...that,"\n"]. ...Birleştirilen anlayışı karakterlere uyarır. Buna katılmak sonucu verir.


Bunu mu demek istediniz: ES6 ES7 henüz çıkmadı.
ericw31415

@ ericw31415 Doğru değil, haklısınız, ancak bazı tarayıcılar ES7 spesifikasyonunun bir bölümünü uygulamaya başladı.
Conor O'Brien

Ah tamam. Ama yine de kodunuz ES7 özelliklerinden hiçbirini kullanmıyor, değil mi?
ericw31415

1
@ ericw31415 Aslında öyle. Dizi [x for(x of a)]anlaşmaları ( ) ES7'dir.
Conor O'Brien

Dizi
Anlaşmalar

3

Julia, 62 bayt

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

Bu, bir dizeyi kabul eden ve bir dizgi dizisi döndüren anonim bir işlevdir. Bunu çağırmak için bir değişkene atayın.

Yaklaşım QPaysTaxes'ın akıllı Ruby cevabı ile aynıdır . Girişteki her rakamı o kadar boşlukla değiştiririz, |her karakter arasına |yerleştiririz, öne ve arkaya yapışır ve bir diziye ayrılırız /.

Çevrimiçi deneyin!


Yay İlham aldım: D
Monica'nın Davası Fonu

@QPaysTaxes Gerçekten yaptın. Güzel çözüm!
Alex A.


2

JavaScript (ES6), 69 67 62 bayt

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

Ek virgüller, dış bölmede başlangıç ​​ve bitiş oluşturan boş değerler oluşturur | karakterlerini . İki virgül gerekir, çünkü virgül listelerin sonunda isteğe bağlıdır, bu nedenle ilk virgül hala önceki öğenin bir parçasıdır.

Düzenleme: @ user81655 sayesinde 5 bayt kaydedildi.


Çalışır mıydı /[\d/]/g,c=>+c?` `.repeat(c):`\n`?
user81655

1
@ user81655 Teşekkürler, ancak ifadenizi beğenmedim, bu yüzden gözlüklü rahatsız bir yüzle değiştirdim.
Neil

1

Retina , 50 45 bayt

Bu eğlenceliydi haha. Sadece ben Retina bir çaylak değilim, ama aynı zamanda genel olarak regex ... Bu muhtemelen bir golfed edilebilir lot Biraz daha araştırma yapacağım, böylece.

Kod:

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

1

/
¶

|

Çevrimiçi deneyin!


$*İşlevselliği kullanmayı deneyin :)
Leaky Nun



1

C, 252 bayt

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

Ayrıntılı çevrimiçi deneyin

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

Artık standart EcmaScript olmayan dizi algılamayı kullanma

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

Ölçek

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 Bayt

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").."|")aynı bayt sayısı için.
Leaky Nun

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

1

R (rekabet dışı)

Bunu göndermek için uygun değilse üzgünüm, ama sadece bu soru için düzenleme olmadan işe yarayan bir fonksiyona sahip olmanın harika olduğunu düşündüm! Yine de ascii yerine unicode çıktı yazdırır. Neden yazdığımı tam olarak hatırlayamıyorum, ama bir meydan okumayı cevaplamak değildi.

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)

}

Yardım merkezimizde belirtilen kurallar , zorluklara yönelik tüm çözümlerin kullanımda kazanma kriterleri için ciddi bir rakip olması gerektiğini belirtmektedir. Kod golf için bu, tüm cevapların golf edilmesi gerektiği anlamına gelir.
Dennis

Teknik olarak golf oynamaktadır. Çok iyi değil.
Flounderer

0

Haskell, 110 Bayt

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 bayt

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

Ayrıntılı çevrimiçi deneyin

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

Karşılaştırmalarda char literals yerine tamsayı kullanarak birkaç bayt kaydedebilirsiniz
Blue

@Blue notları alındı
Khaled.K

0

Pyke, 25 20 bayt

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

Açıklama:

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

Burada deneyin!


0

Python, 84 bayt

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

Açıklama:

        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 bayt

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

Hizalama sorunları nedeniyle 4 boşa bayt, nasıl olsa onları golf emin değilim. ¯ \ _ (ツ) _ / ¯

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.