Оцінка гри Go


23

Забити гру Go - це завдання, яке не надто просто. У минулому було кілька дебатів про те, як розробити правила, щоб охопити всі дивні кутові випадки, які можуть статися. На щастя, у цьому завданні вам не доведеться робити такі складні речі, як життя та смерть чи виявлення seki. У цьому завданні ви повинні реалізувати програму, яка визначає гру за правилами Tromp-Taylor без комі.
Процедура підрахунку балів досить проста:

вважається, що точка P, не кольорова C, досягає C, якщо є шлях (вертикально або горизонтально) сусідніх точок кольору P від ​​P до точки кольору C.
Оцінка гравця - це кількість очок її кольору , плюс кількість порожніх точок, які досягають лише її кольору.

Наприклад, розглянемо наступну раду. X, Oі -позначають чорні, білі та безбарвні перехрестя:

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

Застосування правила підрахунку балів дає наступний результат. x, 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
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для цієї дошки.

Я сподіваюся, що це досить зрозуміло.

Вхід і вихід

Вхід є рядком , яка містить рівно із символів X, O, -де п не відомий під час компіляції. Ваша програма повинна ігнорувати всі інші символи у вхідному потоці. Поведінка не визначена, якщо не існує цілого числа n такого, що кількість XO-символів дорівнює . Можна припустити, що n знаходиться в [0, 255] .

Послідовність символів слід інтерпретувати як Панель із n рядків та стовпців. Вихід - це абсолютне значення різниці загальної суми точок білого та чорного кольорів у десятковому зображенні. Якщо білий колір має більше точок, він має префікс 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+, B+або Jigo), і я подивився на мою клавіатуру і побачив, що Sпоруч W... Або ви використовуєте Дворак?
dmckee

@dmckee Я вважаю, що "S" походить від німецького "Schwarz" замість "Black".
Говард

Ой ... Ти маєш рацію. Вибачте за це
FUZxxl

Відповіді:


2

GolfScript (105 байт)

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

Інтернет демо .

Заливна плита адаптована з цієї попередньої моєї відповіді .

Розчин заповнює одну копію оригінальної дошки символом X, а іншу - О. Таким чином, порожні комірки, які доступні обома кольорами, набираються для обох, але скасовуються у відніманні.


Досить справедливо. Ви можете виграти цей раунд.
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

Вилучений випадок випадку: Якщо до незабарвленого перехрестя можна дістатись як із чорного, так і з білого, ми можемо вважати це одним пунктом для спрощення програми. Переключення логічних гілок, щоб уникнути заперечення.

413 → 382

Призначте dдля getchar()+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для одного персонажа. чотири символи у великому чи пункті.

336 → 323

Заміна &на %можливість видалення дужок для чотирьох символів. Злитий квадратний корінь з циклом введення для дев'яти і більше символів (так!), Вилучений ifдля одного знака.

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--:0з d-46&&f--якої коротше за характером і об'єднати ці два завдання , щоб aу внутрішньому циклі.


1
Ви можете замінити оператор перемикання чимось на зразок {b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}збереження декількох символів.
Говард

@Howard: Так. Це спрацювало дуже добре! Дякую
FUZxxl

«Для підвищеної розбірливості» - ніби.
tomsmeding

@tomsmeding Ну, прокрутка по одному рядку набагато менш розбірлива. Також коментується версія, пов’язана з.
FUZxxl

@FUZxxl Це малося на увазі жартома. :) Крім того, ти маєш рацію сказати, що це краще, ніж на 1 рядку.
tomsmeding

6

J ( 140 136 131 129 119 117 116 116 символів)

Після нарощування своїх навичок 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}"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.