Goのゲームを獲得する


23

Goゲームの得点は、それほど簡単ではないタスクです。過去には、発生する可能性のあるすべての奇妙なコーナーケースをカバーするルールを設計する方法について、いくつかの議論がありました。幸いなことに、このタスクでは、生死や関の検出などの複雑な作業を行う必要はありません。このタスクでは、KomiなしでTromp-Taylorルールに従ってゲームを採点するプログラムを実装する必要があります。
スコアリング手順は非常に簡単です。

Pから色Cの点まで(垂直または水平に)隣接する点のパスがある場合、Cの色ではない点Pは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このボード用に印刷する必要があります。

この方法で十分に明確であることを願っています。

入出力

入力は正確に含まれている文字列です文字のXOnはコンパイル時に知られていません。プログラムは、入力ストリーム内の他のすべての文字を無視する必要があります。整数全く存在しない場合は動作は未定義であるNの量ような文字が等しいn²がn[0、255]にあると仮定できます。-XO-

文字のシーケンスは、n行と列のGo-boardとして解釈されます。出力は、10進表現での白と黒のポイントの合計量の差の絶対値です。白にさらにポイントがある場合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

いいえ...どうやってこの結論に至るのですか?
-FUZxxl

えー...それS+はタイプミスであると仮定しました(以前に可能な出力を、、、またはのいずれかW+としてリストしたため)、キーボードを見て、近くにあるのを見ました...またはDvorakを使用していますか?B+JigoSW
dmckee

@dmckee「S」は「Black」ではなくドイツ語の「Schwarz」から来ていると思います。
ハワード

ああ...そうです。ごめんなさい
-FUZxxl

回答:


2

GolfScript(105バイト)

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

オンラインデモ

私のこの以前の答えから適応された洪水充填。

このソリューションでは、元のボードのコピーの1つをXで塗りつぶし、別のコピーをOで塗りつぶします。したがって、両方の色で到達可能な空のセルは両方についてスコア付けされますが、減算ではキャンセルされます。


けっこうだ。このラウンドで勝つかもしれません。
-FUZxxl

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とにかく違うものが必要な人は?]や標準への準拠[メインの戻り値はどうか!]など)

修正と改善

438→434

変数0が標準に従って自動的に初期化されると確信した後、変数の明示的な初期化を削除しました。

434→413

削除されたcaseステートメント:黒と白の両方から色のない交差点に到達できる場合、プログラムを簡素化するために両方の1つのポイントとしてカウントできます。否定を避けるための論理分岐の切り替え。

413→382

に割り当てdgetchar()+1、1組の括弧を保存します。bゼロに初期化されるという仮定の下で、caseステートメントを並べ替え、すべてのbreakステートメントを破棄します。(a>b?c:0)はより大きい(a>b)*c(d+1)*g+eはより大きいd*g+e+g

382→364

ループの改善、出力の改行なし、出力ルーチンの短縮。

364→336

そのswitch文を取り除きました。(ありがとう、ハワード!)、2人のキャラクターのポイントの差を追跡します。c1文字を無効にします。big or句の4文字。

336→323

で置換&すると%、4文字のブレースを削除できます。平方根を入力ループと融合させて、9文字ほどの文字(ええ!)を入力し、if1文字を削除しました。

323→298

H頻繁に発生するかさばるb[d*g+e]構造を置き換えるマクロを導入しました。

298→294

の最下位3バイトのみを観察するように変更a&=~4a&=3ますa。また((a=I])<3)?a|=...I]<3?a=I]|...そこから2文字短いループ本体に変更されました。また、1文字短くなるhを再利用する代わりに導入しcます。

294→292

h変数を削除します。の代わりにテストcする場合、フラッドフィルループの終わりで0 に等しく、したがって以前使用された目的に使用できます(つまり、スコア保持)。!c--!c++ch

292→290

文字だけ短い構造d-46?f--:0を置き換え、内側のループでd-46&&f--2つの割り当てを結合しaます。


1
switchステートメントを{b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}いくつかの文字を保存するようなものに置き換えることができます。
ハワード

@ハワード:ええ。それは本当にうまくいきました!ありがとう
-FUZxxl

「読みやすさを向上させるために」—まるで。
tomsmeding

@tomsmedingさて、1行のスクロールはずっと読みにくいです。また、コメント付きバージョンがリンクされています。
FUZxxl 14

@FUZxxlそれは冗談めかして意味されました。:)また、あなたはそれが1行よりも優れていると言うのは正しい。
tomsmeding

6

J(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}"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.