Permainan
Nim adalah permainan strategi matematika, di mana 2 pemain bergiliran mengambil item dari tumpukan yang berbeda. Pada gilirannya, Anda harus mengambil setidaknya satu item, dan Anda dapat mengambil sebanyak yang Anda inginkan, asalkan Anda hanya mengambil dari satu tumpukan. Pemain yang menerima item terakhir menang! Ini adalah permainan yang diselesaikan. Sebelum saya masuk ke strategi, Anda dapat mencoba bermain online di sini .
Strategi
Strategi kemenangan dijelaskan dengan sangat jelas dan sederhana di sini di tautan ini . Saya akan menjelaskannya menggunakan istilah teknis yang lebih sedikit. Cara untuk memenangkan permainan ini, adalah untuk selalu mengambil item sebanyak mungkin sehingga jumlah biner-digital selalu 0. Pertimbangkan papan berikut:
*
* *
* * *
* * * *
* * * * *
1 2 3 4 5
Untuk menemukan jumlah biner-digital-board ini, Anda harus:
Ubah nomor di setiap baris menjadi biner. Jadi kita punya 001, 010, 011, 100 dan 101.
Tambahkan semua angka, dan abaikan semua barang bawaan.
001 010 011 100 +101 ---- 001
Anda juga dapat bitwise-xor setiap nomor, dan ini akan mencapai hasil yang sama.
Sekarang, jika jumlah dalam konfigurasi saat ini adalah 001, maka ini bukan (belum) papan pemenang. Tapi Anda bisa menjadikannya papan pemenang! Jika kami mengambil satu item dari kolom 1, 3 atau 5, jumlahnya akan menjadi 0. Ini adalah papan kemenangan, yang berarti bahwa, asalkan Anda tidak melakukan kesalahan, pemain berikutnya yang akan bergerak akan kalah. Jadi, Anda harus selalu mengakhiri giliran Anda dengan papan kemenangan. Katakanlah Anda mengambil satu item dari kolom 5. Sekarang papan terlihat seperti ini:
* *
* * *
* * * *
* * * * *
1 2 3 4 5
Selama Anda tidak mengacau, Anda dijamin menang. Tidak ada yang bisa dilakukan lawan Anda untuk menghentikan Anda. Katakanlah dia mengambil semua item dari kolom 5.
*
* *
* * *
* * * *
1 2 3 4 5
Kemana kamu akan pergi selanjutnya? Jangan gulir ke bawah, dan coba cari tahu sendiri.
Saat ini, jumlahnya adalah 100. Langkah terbaik (dan hanya langkah menang) adalah mengambil semuanya dari kolom 4. Itu akan meninggalkan papan seperti ini:
*
* *
* * *
1 2 3 4 5
dan jumlahnya seperti ini
001
010
+011
----
000
itu berarti Anda berada di papan pemenang! Yay!
Tantangan
Anda harus menulis program atau fungsi yang, diberikan papan nim, akan mengembalikan langkah menang, atau nilai falsey jika tidak ada langkah menang.
Masukan Anda:
Akan menjadi format daftar asli bahasa Anda, di mana setiap item dalam daftar sesuai dengan jumlah item dalam kolom yang diberikan. Misalnya, input {4, 2, 1, 0, 3} sesuai dengan papan nim berikut:
* * * * * * * * * * 1, 2, 3, 4, 5
(opsional) Jumlah baris. (Untuk bahasa seperti C / C ++ yang tidak diketahui dari daftar itu sendiri.)
Output Anda:
Dapat pergi ke STDOUT atau dikembalikan dari fungsi
Harus terdiri dari dua angka, 1) kolom tempat kita menghapus (Ingat bahwa kolom diindeks 0) dan 2) jumlah item yang harus dihapus dari baris itu. Ini bisa berupa array 2-item, string dari dua angka, dll. Ingatlah bahwa jawabannya mungkin lebih dari 2 digit, jadi mengembalikan string "111" tidak valid karena tidak jelas apakah ini berarti "Hapus satu item dari kolom sebelas" atau "Hapus sebelas item dari kolom satu". "1,11" atau "11,1" akan diterima.
Jika tidak ada jawaban, kembalikan atau cetak nilai yang salah. Jika bahasa Anda hanya dapat mengembalikan satu jenis variabel (sekali lagi, seperti C / C ++), angka negatif untuk kolom, atau 0 atau kurang untuk nomor yang akan dihapus keduanya akan menjadi nilai falsey yang dapat diterima.
Jika nomor kolom atau nomor yang harus dihapus terlalu besar, ini dilihat sebagai output yang tidak valid.
Input / Output Sampel
[1, 2, 3, 4, 5]
---> [0, 1]
atau [4, 1]
atau[2, 1]
[1, 3, 5, 6]
---> [0, 1]
atau [1, 1]
atau[2, 1]
[1, 2, 0, 0, 5]
---> [4, 2]
[1, 2, 3]
---> ERROR
Jika Anda memilih untuk melakukan fungsi alih-alih program penuh, maka Anda harus menulis program lengkap untuk menunjukkan fungsi tersebut dalam tindakan. Ini tidak akan dihitung untuk skor penuh Anda. Selain itu, program diharapkan berjalan dalam jumlah waktu yang wajar. Saya tidak berencana untuk memasukkan input yang terlalu besar, jadi selama program Anda tidak melakukan pencarian kasar di seluruh pohon permainan, Anda harus baik-baik saja.
Seperti biasa, ini adalah kode-golf, jadi lubang loop standar berlaku , dan jawaban dihitung dalam byte.
Papan peringkat
Berikut ini adalah Stack Snippet untuk menghasilkan leaderboard biasa dan gambaran umum pemenang berdasarkan bahasa.
Untuk memastikan bahwa jawaban Anda muncul, silakan mulai jawaban Anda dengan tajuk utama, menggunakan templat Penurunan harga berikut:
# Language Name, N bytes
di mana N
ukuran kiriman Anda. Jika Anda meningkatkan skor Anda, Anda dapat menyimpan skor lama di headline, dengan mencoretnya. Contohnya:
# Ruby, <s>104</s> <s>101</s> 96 bytes
Jawaban:
Pyth,
3322212019 byteAnda dapat mencobanya di kompiler online di sini.
Terima kasih kepada Jakube karena menghapus 12 byte dan Maltysen karena menghapus byte tambahan!
Ini mencetak langkah kemenangan dari posisi saat ini. Jika tidak ada gerakan menang, itu tidak mencetak apa pun.
Saya menggunakan algoritma di wikipedia . Berikut ini rinciannya:
sumber
Pyth, 23 byte
Cobalah online: Peragaan
Ini beralih pada semua kemungkinan gerakan dan bahkan penyortiran. Oleh karena itu ia memiliki kompleksitas waktu
O(N*log(N))
dan kompleksitas memoriO(N)
, di manaN
jumlah dari daftar input atau jumlah item.Karena kompleksitas waktu yang buruk, ini mungkin bukan jawaban yang valid. Meskipun itu memecahkan semua game, bahwa Anda dapat bermain dalam kehidupan nyata dengan benda nyata, secara instan.
Penjelasan:
sumber
CJam,
2120 byteMenyimpan byte dibandingkan dengan versi asli, dan penanganan kesalahan juga berfungsi sekarang:
Cobalah online
Input adalah array CJam, misalnya:
Jika tidak ada solusi yang ditemukan, ia mencetak
-1 0
, yang memenuhi pemahaman saya tentang persyaratan output.Penjelasan:
sumber
Ruby, 95
Saya menulis 2 fungsi anonim yang terpisah. Yang pertama, yang ditetapkan
f
dalam program di bawah ini, mencetak semua solusi, dan yang keduag
(sesuai dengan skor di atas, karena keduanya lebih pendek dan lebih sesuai dengan spesifikasi) hanya mengembalikan solusi yang membutuhkan penghapusan jumlah terbesar.dalam kedua kasus, jumlah digit dijumlahkan dalam
c
. Kemudian array di-looped dan ekspresin=a[i]-(c^a[i])
digunakan untuk menghitung jumlah counter yang akan dihapus (jelas ini hanya dapat dilakukan jika melebihi nol).dalam
f
, semua solusi yang mungkin dicetak (jikac
ditemukan0
,error
dicetak tanpa perulangan.) Saya terkejut melihat bahwa tumpukan yang berbeda dapat membutuhkan jumlah penghitung yang sangat berbeda untuk dihilangkan.dalam
g
array keluaranr
hanya diperbarui jika jumlah counter yang akan dihapus melebihi angka sebelumnya. array r =[pile index, number to be removed]
dikembalikan. Jika tidak ada solusi, jumlah penghitung yang akan dihapus selalu nol,r
tetap tidak berubah, dan nilai awal r =[false,0]
dikembalikan.Penghematan kecil dimungkinkan jika
false
dapat diubah ke misalnya"!"
dan jika ada solusi yang valid daripada yang terbesar dapat dikembalikan (dengan menghapus&&n>r[1]
.)Diformat dalam program uji
sumber
r[1]
selalu paling tidak nol, saya pikir>0&&n>r[1]
bisa disingkat>r[1]
Mathematica, 73 byte
sumber
JavaScript (ES6), 54 byte
Mengembalikan pasangan
[column, number]
atau salahCobalah online!
Berkomentar
sumber