将Forsyth-Edwards表示法字符串转换为ASCII美工


9

在国际象棋中,通常被称为“ FEN”的福赛斯·爱德华兹符号是一种抄写木板的文字方式。它从怀特的角度从上到下描述了董事会八行中的每一行(在国际象棋中称为“等级”)。这些片段被写为K(国王),Q(女王),R(流氓),B(主教),N(骑士)和P(典当)。黑色小写使用这些字母,白色小写使用这些字母。空格由1到8的数字表示,表示有多少个连续的空格。一个完全为空的等级将是8,最右边一列(在国际象棋中称为“文件”)将是一个黑色的白嘴鸦,7r一行的每一端将是两个白棋子。通常还会添加其他信息,指示要移动哪一侧,PP4PP。等级之间用a分隔/顺便权利,移动号码,halfmove时钟,但我们会忽略他们的这一挑战的目的。

输入项

根据需要,从命令行或STDIN发送FEN字符串。您可以假定此字符串始终有效。

输出量

将实际出现的板子的简单ASCII艺术表现形式写入STDOUT:

  • 作品以他们在FEN中的角色来表示
  • 空方格用空格表示
  • 碎片和正方形由管道分开,|并且板的每一侧都有管道

因此,用8/8/8/8/8/8/8/8FEN 编写的空板将显示为

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

国际象棋游戏的起始位置写为rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR,并显示为

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

Anderssen-Kieseritzky 1851在国际象棋社区中的最终位置称为“不朽游戏”,其书写方式为r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1,输入该程序后,您的程序将输出:

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

编写一个接受输入并返回输出而不是将其写入STDOUT的函数是否可以接受?
Fund Monica的诉讼

@QPaysTaxes默认情况下,我们允许它,确实有几种解决方案已经做到了。最终由OP决定,尽管在这种情况下似乎不必覆盖我们的默认值。
Alex A.

2
您接受的答案不是最短的答案。无论您对打高尔夫球的语言有什么看法,打高尔夫球都意味着最短的打赢代码
丹尼斯

3
您也不能惩罚他们接受任意答案。整个网站都建立在客观的获胜标准之上。
丹尼斯

1
+1一个有趣的挑战。-2因无正当理由接受错误答案的原因
詹姆斯•詹姆士(James)

Answers:


9

Perl,28个字节

包括+2 -lp

在STDIN上输入

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

fen.pl

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

实际上在某些高尔夫语言联盟中...

请注意,基于文件的版本需要文件中的最后一个换行符,因此实际上是29个字节。但是命令行版本不需要多余的换行符,因此代码计数为28个字节:

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

1
想念shebang吗?
user253751 '16

15

视网膜,13字节

\d
$* 
/
¶

|

在线尝试!

说明

第一部分(注意尾随空格):

\d
$* 

是将a转换为特定数量的空格。视网膜具有$*重复功能。它的工作方式是:<num>$*<char>如果没有<num>,则Retina将采用$&或匹配的字符串,在这种情况下为匹配的数字。

下一部分:

/
¶

很简单,它取代所有/它是一个换行符。

最后一部分的工作原理相同:

    
|

这将用替换所有内容(因此第一行什么都没有)|。放到|处都是。


1
您甚至可以S`/在第二阶段以相同的字节数以ASCII格式完成所有操作。
Martin Ender

12

Ruby- 75 82 78 76 75 62 59 58 57 56字节

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

多亏了Ventero,节省了几个字节

让我解释一下(\n替换文字换行符):

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

这隐式返回字符串的值,每个字符串都/用换行符替换(默认情况下,$/包含换行符)

"|#{...}|"

这非常简单;它只是一个包含管道,字符串插值和另一个管道的字符串。字符串插值被评估

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

这将用那么多空格替换每个数字。我还可以在这里找到换行符来节省一些字节;因为hex如果该字符串不是有效数字,则返回0,因此当它找到一个换行符–即结果的末尾一个gets–时,它将换成长度为0的字符串,从而有效地删除了它。没有这个,就会有尾随的管道。

$&是一个魔术变量,它代表最新变量匹配的完整文本,这使我可以消除来节省一个字节|d|。我可以使用.hex而不是来保存另一个字节.to_i,因为每个数字都小于9,所以可以工作,这意味着十六进制和十进制具有相同的值。

.chars*?|

这在每个字符之间放置了一个管道。请注意,这是将管道放在行的两边(第一行和最后一行除外)的原因,因为斜杠最终通过变成了换行符tr,被视为字符,因此被管道包围。在?|刚刚的意思是”一个字符的字符串"|" ”。

而且...就是这样。坦白讲,这是一个非常简单的程序。它只是使用了许多狡猾的语法技巧。


2
您可以通过应用一些简单的技巧来保存另外4个字符:(puts"|#{gets.gsub(/\d|\n/){' '*$&.hex}.chars*?|}|".split'/'当然,请\n再次用文字换行符替换)。
Ventero '16

5

Pyth- 24 22 21字节

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

测试套件

+                     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个字节

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

在线尝试!

怎么运行的:

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

是一个接受字符串作为输入的匿名函数。

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

80字节的仅限ES6的方式。

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

说明

我们使用数组理解来遍历列表:

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

这等效于:

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

如果是数字,则我们有该数量的空格。如果是/,我们有换行符。否则,我们有角色。然后,我们不带任何内容加入理解,就可以组成一个字符串。

然后,我们创建一个长度为3的数组[,...that,"\n"]...将加入的理解理解为字符。将其合并即可得到结果。


您不是说ES6吗?我相信ES7还没有发布。
ericw31415 '16

@ ericw31415没错,您是对的,但是某些浏览器已开始实现ES7规范的一部分。
Conor O'Brien

哦好的。但是您的代码仍然不使用任何ES7功能,对吗?
ericw31415 '16

1
@ ericw31415确实如此。数组[x for(x of a)]推导()是ES7。
科纳·奥布莱恩

MDN 表示
解析

3

朱莉娅62字节

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

这是一个匿名函数,它接受一个字符串并返回一个字符串数组。要调用它,请将其分配给变量。

该方法与QPaysTaxes的Ruby聪明回答相同。我们用许多空格替换输入中的每个数字,将其放置|在每个字符之间,|固定在正面和背面,并在上拆分为一个数组/

在线尝试!


没错,我启发了事情:D
基金莫妮卡的诉讼

@QPaysTaxes您确实做到了。不错的解决方案!
Alex A.


2

JavaScript(ES6),69 67 62字节

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

多余的逗号在外部拆分中创建空值,从而创建开始和结束|字符。您需要两个尾随逗号,因为尾随逗号在列表末尾是可选的,因此第一个仍然是上一项的一部分。

编辑:由于@ user81655,节省了5个字节。


/[\d/]/g,c=>+c?` `.repeat(c):`\n`工作吗?
user81655 '16

1
@ user81655谢谢,但是我不喜欢你的图释,所以我换了一个戴着眼镜的恼人的脸。
尼尔

1

视网膜50 45字节

哈哈,真有趣。我不仅是视网膜上的菜鸟,还是一般的正则表达式中的菜鸟……这可能很多,所以我会做一些更多的研究。

码:

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

1

/
¶

|

在线尝试!


尝试使用该$*功能:)
Leaky Nun



1

C,252个字节

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

详细 在线试用

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

使用不再是标准EcmaScript的数组理解

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

测试

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

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

不打高尔夫球

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").."|")对于相同的字节数。
Leaky Nun

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

1

R(比赛以外)

抱歉,如果不适合发布此功能,但我觉得很酷,只是碰巧周围有一个函数实际上无需修改就可以解决该问题!不过,它会打印unicode输出而不是ascii。我不记得我为什么写它,但这并不是要回答一个挑战。

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

0

Haskell,110字节

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

取消高尔夫:

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个字节

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

详细 在线试用

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

您可以在比较中使用整数而不是char文字来保存几个字节
Blue Blue

采取@Blue笔记
Khaled.K

0

Pyke,25个 20字节

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

说明:

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

在这里尝试!


0

Python,84个字节

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

说明:

        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个字节

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

由于对齐问题,浪费了4个字节,不过不确定如何将它们打出去。¯\ _(ツ)_ /¯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.