得分围棋


23

进行围棋比赛得分并非易事。过去,关于如何设计规则以涵盖可能发生的所有奇特拐角案例的争论一直存在。幸运的是,在此任务中,您不必做复杂的工作,如生死攸关或检测出关。在此任务中,您必须实现一个根据Tromp-Taylor规则在没有Komi的情况下为游戏评分的程序。
计分程序非常简单:

如果P色的相邻点(从P到C点)之间存在(垂直或水平)相邻点的路径,则称为P点(未着色的C点)到达C
点。 ,再加上仅达到她的颜色的空白点数。

例如,考虑以下电路板。XO-表示黑色,白色和无色交叉点:

- - - X - O - - -
- - - X - O - - -
- - - X - O - - -
- - - X O - - O -
X X X O - O O - -
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

应用计分规则将产生以下结果。xo-代表被视为黑色,白色和无人点的无色交叉点。

x x x X - O o o o
x x x X - O o o o
x x x X - O o o o
x x x X O o o O o
X X X O o O O o o
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

根据图表,黑色占23点,白色占29点。因此,您的程序应W+6为此板打印。

我希望这样清楚。

输入输出

输入是一个包含恰好一个字符串的字符XO-其中Ñ在编译时是未知的。您的程序应忽略输入流中的所有其他字符。如果没有整数n使得XO-字符数等于,则行为是不确定的。您可以假设n[0,255]中

字符序列应解释为n行和列的Go-board 。输出是用十进制表示的白色和黑色总点数之差的绝对值。如果白色具有更多点,则以前缀。W+如果黑色具有更多点,则以前缀B+。如果两个玩家的积分相等,则输出为Jigo

输入应以实现定义的方式读取。输入内容可能不是源代码的一部分。

获奖条件

这是代码高尔夫球。通常使用代码高尔夫球约定。源中字符最少的提交将获胜。只有完全实现该规范的程序才有可能获胜。

测试用例

输入:

- - - X - O - - -
- - - X - O - - -
- - - X - O - - -
- - - X O - - O -
X X X O - O O - -
- - - X O - - O O
- - - X - O - - -
- - - X - O - X -
- - - - - O - - -

输出: W+6

输入:

Xavier is insane -- says Oliver

输出: Jigo

输入:

Code-Golf

输出: Jigo

输入:

-XXXXXXX-XOOOOOOOXXO-OXXXOXXXOX--XOXXOOX
-
XOOXXOX--XOXXXOXXXO-OXXOOOOOOOX-XXXXXXX-

输出: B+21

输入:

- - X O O O O X X - - - - - - X O O -
- X X O X O X X O X X X X X X - X O -
- X O O X X X - O O O X O O X X X O -
- X O O O X X O O O O O O X X X O - -
- - X X O X - X X X X O O O O O O O -
- - X O O X X X - X X X O O O X X O -
- - X O - O X O X O O O O O X X X O -
- X O O - O O O X X X X X O O X O - -
- X X X O - - - O X O X X X O X O - -
X O O O O - - O - O O O O X X X O O -
X X O - - - O - - O O X X - - X X O O
X O O O - - O - O O X - - - - X O O X
- X X X O O X O O X X - - - - X X X X
X - X X X O X X O O X - - X X O X O O
X X O O X O X O X X - - - X O O O O -
X O - O X X X O X - - - - - X O - - -
O O - O X O O O O X X - X X X X O - -
O O - O O O X O X X - - X - X X O - -
- - O - - O X X X - - - - X O O O - -

输出: B+6

更多的测试用例即将推出。

参考实施

我创建了一个用ANSI C编写的参考实现。该实现从标准输入读取输入,并将输出写入标准输出。

/* http://codegolf.stackexchange.com/q/6693/134
 * reference implementation
 * by user FUZxxl
 */

#include <stdio.h>
#include <stdlib.h>

#define MAXBOARD 256

/* bit 0x01: black colour
 * bit 0x02: white colour
 * bit 0x04: there is a stone on the intersection
 */

enum colour {
    UNCOLOURED    = 0x0,
    BLACK_REACHED = 0x1,
    WHITE_REACHED = 0x2,
    BOTH_REACHED  = 0x3,
    HAS_STONE     = 0x4,
    BLACK         = 0x5,
    WHITE         = 0x6
};

static enum colour board[MAXBOARD * MAXBOARD] = { 0 };

static int bsize = 0;

static void read_input(void);
static void fill_board(void);
static void show_score(void);

int main()
{
    read_input();
    fill_board();
    show_score();
    return EXIT_SUCCESS;
}

static void read_input(void)
{
    int n = 0;
    int invalue;

    while ((invalue = getchar()) != EOF) {
        switch (invalue) {
            case '-': board[n++] = UNCOLOURED; break;
            case 'X': board[n++] = BLACK; break;
            case 'O': board[n++] = WHITE; break;
        }
    }

    while (bsize * bsize < n) bsize++;

    /* your program may exhibit undefined behaviour if this is true */
    if (bsize * bsize != n) exit(EXIT_FAILURE);
}

static void fill_board(void)
{
    int i,j;
    int changes;
    enum colour here, top, bottom, left, right, accum;

    do {
        changes = 0;

        for (i = 0; i < bsize; ++i) {
            for (j = 0; j < bsize; ++j) {

                here   = board[i * bsize + j];
                if (here >= BOTH_REACHED) continue;

                top    = i == 0 ? UNCOLOURED : board[(i - 1) * bsize + j];
                left   = j == 0 ? UNCOLOURED : board[i * bsize + j - 1];
                bottom = i == bsize-1 ? UNCOLOURED : board[(i + 1) * bsize + j];
                right  = j == bsize-1 ? UNCOLOURED : board[i * bsize + j + 1];

                accum = here | top | bottom | left | right;
                accum &= ~HAS_STONE;

                changes |= board[i * bsize + j] != accum;

                board[i * bsize + j] = accum;

            }
        }

    } while (changes);
}

static void show_score(void) {
    int w = 0, b = 0, n;

    for (n = 0; n < bsize*bsize; ++n) switch (board[n] & ~HAS_STONE) {
        case BLACK_REACHED: ++b; break;
        case WHITE_REACHED: ++w; break;
    }

    if (b != w)
        printf("%s%i\n",b>w?"B+":"W+",abs(b-w));
    else
        printf("Jigo\n");
}

大概您的意思是最后一个输出是W+7
dmckee 2012年

不,您如何得出这个结论?
FUZxxl 2012年

呃......我认为S+是一个错字(因为你前面列出可能的输出要么W+B+Jigo),我看了看我的键盘,看到S附近W...或者你用德沃夏克?
dmckee 2012年

@dmckee我想“ S”来自德语“ Schwarz”而不是“ Black”。
霍华德

哦,你是对的。对不起,那
FUZxxl

Answers:


2

GolfScript(105字节)

{'-XO'?}/]-1-.{2*3%}%{.,:N),{.*N=}?/{{[{.2$+1={+.}*}*]}%zip}N*[]*.1--,\}2*-.{.0>'W+B+'2/=\abs}{;'Jigo'}if

在线演示

洪灾改编自我的较早答案

该解决方案用X填充原始板的一个副本,用O填充另一个副本。因此,对两种颜色都可以到达的空单元格进行评分,但在相减时会抵消。


很公平。您可能会赢得本轮比赛。
FUZxxl 2015年

6

C(438 434 413 382 364 336 322 298 294个 292个 290字符)

#define I b[d*g+e
a;b[65536];c;d;e;f;g;main(){for(;d=getchar()+1;f++)b[f]=d-80?d-89?d-46&&
f--:5:6,g+=g*g<f;while(!c--)for(d=g;d--;)for(e=g;e--;)I]<3?a=3&(I]|!!d*I
-g]|!!e*I-1]|(d<g-1)*I+g]|(e<g-1)*I+1]),c&=I]==a,I]=a:0;while(f--)c+=b[f
]%2-b[f]/2%2;printf(c?"%c+%i":"Jigo",c>0?66:87,abs(c));}

除第一个换行符外,所有换行符均增强了可读性。在这里可以找到带注释的版本,并且可读性更高。

该答案本质上是参考解决方案,但包含所有无用的内容(例如类型[谁还需要其他东西int吗?]和标准符合性[main的返回值?

更正和改进

438→434

在我确信自己可以0根据标准自动初始化变量之后,删除了变量的显式初始化。

434→413

已删除的案例陈述:如果黑白两色都可以达到一个无色交点,那么我们可以将其视为一个点,以简化程序。切换逻辑分支以避免求反。

413→382

分配dgetchar()+1保存一对括号。在b初始化为零的假设下,重新排序case语句,丢弃所有break语句。(a>b?c:0)比更长(a>b)*c(d+1)*g+e比更长d*g+e+g

382→364

改进了循环,在输出中没有换行符,缩短了输出例程。

364→336

摆脱了那switch句话。(谢谢,霍华德!),跟踪两个字符的点差。取反c一个字符。big or子句中的四个字符。

336→323

替换&%可以删除四个字符的花括号。用输入循环将平方根与大约9个字符融合在一起(是的!),删除了if一个1个字符的字符。

323→298

引入了宏H以替代经常出现的笨重b[d*g+e]结构。

298→294

更改a&=~4为,a&=3因为我们每个人都观察到的最低三个字节a。也改为循环体从((a=I])<3)?a|=...I]<3?a=I]|...它是两个字符短。另外,引入h而不是重用c,这要短一个字符。

294→292

消除h变量。如果我们测试c!c--代替!c++c在洪水填充循环的结束等于0,因此可以用于目的h是(即记分)之前使用。

292→290

用字符替换较短的构造d-46?f--:0d-46&&f--然后将两个赋值组合到a内部循环中。


1
您可以将switch语句替换为{b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}要保存几个字符的内容。
霍华德

@霍华德:是的。真的很棒!谢谢
FUZxxl 2012年

“增强可读性”-好像。
tomsmeding

@tomsmeding好吧,滚动一行不太清晰。另外,链接到注释版本。
FUZxxl 2014年

@FUZxxl这是在开玩笑。:)另外,您说对了,比说一行要好。
tomsmeding

6

Ĵ(140 136 131 129 119个 117个 116字符)

在提高了J技能之后,我终于可以用J提交内容了。尽管有点长。

exit echo>(*{'Jigo';('B+',":);'W+',":@|)+/,-/1 2=/(]OR(0=[)*[:OR((,.|.)0,i:1)|.!.0])^:_~($~,~@%:@#)3-.~'-XO'i:1!:1]3

此提交实现的算法与参考实现非常相似,但是处理占用字段的方式不同。

以下是将解决方案分成更多部分以便于理解的方法。打高尔夫球的解决方案与此稍有不同,但是差异不是很大。

input =. 3 -.~ '-XO' i: 1!:1 ] 3
board =. ($~ ,~@%:@#) input
NB. shift up, down, left, right
rotm =. (,. |.) 0 , i: 1
fill =. ] OR (0 = [) * [: OR rotm |.!.0 ]
filledboard =. fill^:_~ board
score =. +/ , -/ 1 2 =/ filledboard
echo > (* { 'Jigo' ; ('B+' , ":) ; ('W+', ":@|)) score
exit 0

5

GolfScript,190个字符

{"XO-"?)},:v,.),\{\.*=}+,~:s.*:`0\,{s%!\2*+}/:r;88{0v@{=\2*+}+/}:%~79%1${{:<.r|r^2*|<2/r|r^|<2s?:h/|<h*|1$|1$^2`?(&}`*}:a~@@a\;.2$|2${^2*)2base{+}*}:m~@2$|@m-.{"BW"1/1$0>="+"@abs}{;"Jigo"}if

脚本变得比我一开始想的要长得多。在STDIN上传递任何输入,然后在程序终止时打印输出。


2

红宝石(314)

可以用更多的时间做得更短:

q={?-=>0,?X=>5,?O=>6};b=[];$<.chars{|c|(t=q[c])&&b<<t}
z=Math.sqrt b.size
loop{c=b.each_with_index.map{|h,i|
next h if h>2
x=i%z
y=i/z
u=y<1?0:b[i-z]
l=x<1?0:b[i-1]
d=y>z-2?0:b[i+z]
r=x>z-2?0:b[i+1]
~4&(h|u|d|l|r)}
break if c==b
b=c}
b.map!{|h|h&~4}
s=b.count(1)-b.count(2)
puts s==0?"Jigo":s>0?"B+#{s}":"W+#{-s}"
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.