Skor game Go

23

Game Scoring a Go adalah tugas yang tidak terlalu mudah. Di masa lalu ada beberapa perdebatan tentang bagaimana merancang aturan untuk mencakup semua kasus sudut aneh yang mungkin terjadi. Untungnya, dalam tugas ini Anda tidak perlu melakukan hal-hal rumit seperti hidup dan mati atau deteksi seki. Dalam tugas ini, Anda harus menerapkan program yang mencetak permainan sesuai dengan aturan Tromp-Taylor tanpa Komi.
Prosedur penilaiannya cukup sederhana:

sebuah titik P, bukan berwarna C, dikatakan mencapai C, jika ada jalur titik-titik warna P yang berdekatan (secara vertikal atau horizontal) dari P ke titik warna C.
Skor pemain adalah jumlah titik warnanya , ditambah jumlah titik kosong yang hanya mencapai warnanya.

Sebagai contoh, perhatikan papan berikut. X, Odan -menunjukkan persimpangan hitam, putih dan tidak berwarna:

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

Menerapkan aturan penilaian menghasilkan hasil berikut. x, odan -mewakili persimpangan tidak berwarna yang dihitung sebagai titik hitam, putih, dan tidak ada orang.

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

Menurut diagram, hitam memiliki 23 poin, putih memiliki 29 titik wilayah. Dengan demikian, program Anda harus mencetak W+6untuk board ini.

Saya harap ini cukup jelas seperti ini.

Masukan dan keluaran

Input adalah sebuah string yang berisi persis n ² karakter X, O, -di mana n tidak diketahui pada waktu kompilasi. Program Anda harus mengabaikan semua karakter lain di aliran input. Perilaku tidak terdefinisi jika tidak ada bilangan bulat n sehingga jumlah XO-karakter sama dengan . Anda dapat menganggap bahwa n ada di [0, 255] .

Urutan karakter harus ditafsirkan sebagai papan tulis dari n baris dan kolom. Output adalah nilai absolut dari perbedaan jumlah total titik putih dan hitam dalam representasi desimal. Jika putih memiliki lebih banyak poin, itu diawali oleh W+, jika hitam memiliki lebih banyak poin itu diawali oleh B+. Jika kedua pemain memiliki jumlah poin yang sama, hasilnya adalah Jigo.

Input harus dibaca dengan cara yang ditentukan implementasi. Masukan mungkin bukan bagian dari kode sumber.

Kondisi menang

Ini adalah kode-golf. Konvensi kode-golf biasa berlaku. Pengajuan dengan jumlah karakter paling sedikit di sumbernya akan menang. Hanya program yang menerapkan spesifikasi sepenuhnya yang dapat menang.

Uji kasus

Memasukkan:

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

Keluaran: W+6

Memasukkan:

Xavier is insane -- says Oliver

Keluaran: Jigo

Inpout:

Code-Golf

Keluaran: Jigo

Memasukkan:

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

Keluaran: B+21

Memasukkan:

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

Keluaran: B+6

Lebih banyak testcases akan segera hadir.

implementasi referensi

Saya telah membuat implementasi referensi yang ditulis dalam ANSI C. Implementasi ini membaca input dari input standar dan menulis output ke output standar.

/* 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");
}
FUZxxl
sumber
Mungkin yang Anda maksud adalah output terakhir W+7?
dmckee
Tidak ... Bagaimana Anda sampai pada kesimpulan ini?
FUZxxl
Eh ... Saya berasumsi bahwa S+salah cetak (karena Anda sebelumnya terdaftar mungkin output sebagai baik W+, B+atau Jigo) dan saya melihat keyboard dan melihat Sdekat W... Atau yang Anda gunakan Dvorak?
dmckee
@ dmckee Saya kira "S" berasal dari bahasa Jerman "Schwarz" bukan "Black".
Howard
Oh ... Kamu benar. Maaf untuk itu
FUZxxl

Jawaban:

2

GolfScript (105 byte)

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

Demo online .

Isi banjir diadaptasi dari jawaban saya sebelumnya .

Solusinya mengisi-satu salinan papan asli dengan X, dan yang lain dengan O. Dengan demikian sel-sel kosong yang dapat dijangkau oleh kedua warna diberi skor untuk keduanya, tetapi batalkan dalam pengurangan.

Peter Taylor
sumber
Cukup adil. Anda mungkin memenangkan babak ini.
FUZxxl
6

C ( 438 434 413 382 364 336 322 298 294 292 290 karakter)

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

Semua baris baru kecuali yang pertama dimasukkan untuk meningkatkan keterbacaan. Versi komentar dan sedikit lebih terbaca dapat ditemukan di sini .

Jawaban ini pada dasarnya adalah solusi referensi tetapi dengan semua hal yang tidak berguna (seperti tipe [siapa yang butuh sesuatu yang berbeda int?] Dan kepatuhan standar [nilai pengembalian main? Tolong!])

Koreksi dan perbaikan

438 → 434

Turunkan inisialisasi eksplisit variabel setelah saya meyakinkan diri sendiri bahwa mereka secara otomatis diinisialisasi 0sesuai dengan standar.

434 → 413

Pernyataan kasus yang dihapus: Jika persimpangan tidak berwarna dapat dicapai dari hitam dan putih, kita dapat menghitungnya sebagai satu titik untuk keduanya untuk menyederhanakan program. Beralih dari cabang logis untuk menghindari negasi.

413 → 382

Tetapkan duntuk getchar()+1menyimpan sepasang kurung. Di bawah asumsi yang bdiinisialisasi ke nol, menyusun ulang casepernyataan, membuang semua breakpernyataan. (a>b?c:0)lebih panjang dari (a>b)*c. (d+1)*g+elebih panjang dari d*g+e+g.

382 → 364

Peningkatan perulangan, tidak ada baris baru dalam output, rutinitas keluaran lebih pendek.

364 → 336

Singkirkan switchpernyataan itu. (Terima kasih, Howard!), Lacak perbedaan poin untuk dua karakter. Meniadakan cuntuk satu karakter. empat karakter dalam huruf besar atau klausa.

336 → 323

Mengganti &dengan %memungkinkan penghapusan kawat gigi untuk empat karakter. Menyatu akar kuadrat dengan loop input untuk sembilan atau lebih karakter (yeah!), Dihapus ifuntuk satu karakter.

323 → 298

Memperkenalkan makro Huntuk menggantikan b[d*g+e]konstruksi yang sering terjadi dan besar .

298 → 294

Ubah a&=~4menjadi a&=3karena kami hanya mengamati tiga byte terendah dari a. Juga mengubah tubuh lingkaran dari ((a=I])<3)?a|=...ke I]<3?a=I]|...yang dua karakter lebih pendek. Juga, perkenalkan halih-alih menggunakan kembali c, yang merupakan satu karakter lebih pendek.

294 → 292

Hilangkan hvariabel. Jika kita menguji cdengan !c--bukannya !c++, csama dengan 0 pada akhir loop pengisian banjir dan dengan demikian dapat digunakan untuk tujuan hyang digunakan sebelumnya (yaitu menjaga skor).

292 → 290

Ganti konstruksi d-46?f--:0dengan d-46&&f--yang lebih pendek oleh karakter dan gabungkan dua tugas ke adalam lingkaran dalam.

FUZxxl
sumber
1
Anda dapat mengganti pernyataan beralih dengan sesuatu seperti {b[f]=d-80?d-89?d-46?f--:0:5:6;f++;}menyimpan beberapa karakter.
Howard
@ Howard: Ya. Itu bekerja sangat bagus! Terima kasih
FUZxxl
"Untuk meningkatkan keterbacaan" - seolah-olah.
mulai
@tommeding Nah, menggulir satu baris jauh lebih mudah dibaca. Juga, versi komentar terhubung ke.
FUZxxl
@ Fuzxxl Itu berarti bercanda. :) Juga, Anda benar mengatakan lebih baik daripada di 1 baris.
tommeding
6

J ( 140 136 131 129 119 117 116 karakter)

Setelah meningkatkan keterampilan J saya, saya akhirnya bisa memberikan pengajuan dalam J. Ini agak lama.

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

Algoritma yang diterapkan oleh pengiriman ini sangat mirip dengan implementasi referensi tetapi berbeda dalam cara bidang yang ditangani ditangani.

Inilah solusinya yang dibagi menjadi beberapa bagian agar lebih mudah dipahami. Solusi golf sedikit berbeda dari itu, tetapi perbedaannya tidak terlalu besar.

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
FUZxxl
sumber
5

GolfScript, 190 karakter

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

Script menjadi lebih lama dari yang saya pikirkan di awal. Lewati setiap input pada STDIN dan hasilnya kemudian akan dicetak ketika program berakhir.

Howard
sumber
2

Ruby (314)

dapat dibuat lebih pendek dengan lebih banyak waktu:

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}"
jsvnm
sumber