바둑 경기 득점


23

Go 게임 득점은 너무 쉬운 일이 아닙니다. 과거에는 발생할 수있는 모든 이상한 상황을 다루는 규칙을 설계하는 방법에 대한 몇 가지 논쟁이있었습니다. 운 좋게도이 작업에서는 삶과 죽음 또는 세키 감지와 같은 복잡한 작업을 수행 할 필요가 없습니다. 이 작업에서는 Komi가없는 Tromp-Taylor 규칙 에 따라 게임의 점수를 매기는 프로그램을 구현해야합니다 .
채점 절차는 매우 간단합니다.

C 착색되지 점 P는 색 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 은 컴파일 타임에 알려지지 않습니다. 프로그램은 입력 스트림의 다른 모든 문자를 무시해야합니다. 문자 수가 과 같 도록 정수 n 이없는 경우 동작이 정의되지 않습니다 . n[0, 255] 에 있다고 가정 할 수 있습니다 .XO-

일련의 문자는 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

더 많은 테스트 케이스가 곧 올 것입니다.

참조 구현

I는 생성 한 참조 구현 이 구현은 표준 입력에서 입력을 판독하고, 표준 출력으로 출력을 기록 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"가 "Black"대신 독일 "Schwarz"에서 온 것으로 가정합니다.
Howard

오 ... 네 말이 맞아 죄송합니다
FUZxxl

답변:


2

GolfScript (105 바이트)

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

온라인 데모 .

이 초기 답변 에서 홍수로 채운다 .

이 솔루션은 원본 보드의 사본 하나를 X로 채우고 다른 사본은 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. b0으로 초기화 되었다는 가정 하에서 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

대체 &하여 %네 문자의 중괄호를 제거 할 수 있습니다. 9 개 정도의 문자 (예!)에 대한 입력 루프로 제곱근을 융합하고 if하나의 문자를 제거했습니다 .

323 → 298

H자주 발생하고 부피가 큰 b[d*g+e]구조물 을 대체하기 위해 매크로 를 도입했습니다 .

298 → 294

변화 a&=~4a&=3우리가 매의 가장 낮은 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
switch 문을 {b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}여러 문자를 저장 하는 것과 같은 것으로 바꿀 수 있습니다 .
Howard

@Howard : 네. 정말 잘 작동했습니다! 감사합니다
FUZxxl

"가독성 향상"— 마치.
tomsmeding

@tomsmeding 음, 한 줄을 스크롤하는 것은 읽기 쉽지 않습니다. 또한 주석이 달린 버전이 연결됩니다.
FUZxxl

@FUZxxl 그것은 농담이었다. :) 또한 1 줄보다 낫다는 말이 맞습니다.
초에 tomsmed

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.