Ini adalah kode-golf .
Dalam tantangan ini, kita akan menulis program / fungsi yang memecahkan teka-teki " Knights and Knaves ".
Latar Belakang
Anda menemukan diri Anda di sebuah pulau ... dll ... setiap orang di pulau kecuali untuk Anda adalah baik ksatria atau penjahat .
Ksatria hanya bisa membuat pernyataan yang benar .
Knave hanya bisa membuat pernyataan palsu .
Saya tidak ingin mendefinisikan "pernyataan," tetapi kami akan mengatakan bahwa pernyataan adalah segala sesuatu yang "benar" atau "salah." Perhatikan bahwa ini tidak termasuk kalimat paradoks.
Untuk keperluan tantangan ini, Anda akan menjumpai sekelompok pulau; mereka akan membuat pernyataan kepada Anda.
Tugas Anda adalah menentukan siapa yang seorang Ksatria dan siapa yang Knave.
Memasukkan:
Anda akan diberi (dalam format apa pun yang masuk akal) informasi berikut:
Daftar orang-orang yang hadir. Mereka akan diberi nama dengan karakter alfabet huruf besar "AZ". Batas jumlah orang yang diberlakukan oleh ini tidak akan terlampaui.
Pernyataan yang dibuat setiap orang. Lihat di bawah untuk detail penting tentang ini.
Keluaran
Anda kemudian akan menampilkan (dalam format apa pun yang masuk akal) apa yang masing-masing orang. Misalnya, jika ada pemain A B C D
dan A
adalah seorang ksatria, tetapi sisanya adalah para ksatria, Anda bisa menghasilkan
A: 1
B: 0
C: 0
D: 0
Detail penting:
Huruf alfabet huruf besar AZ mengacu pada penduduk pulau.
Karakter
0
(nol) dan1
(satu) masing-masing merujuk pada "Knave" dan "Knight". (Anda dapat menggunakan dua karakter non AZ lainnya, selama Anda tentukan)Setiap pulau yang hadir dapat membuat sejumlah pernyataan, atau mungkin memilih untuk tidak mengatakan apa pun.
Operator logika normal dapat digunakan dalam pernyataan ( IS *, DAN, ATAU, TIDAK ). Di atas ini, Hukum dan Kondisional De Morgan dapat digunakan. Berikut ini adalah contoh bagaimana mereka dapat disajikan dalam puzzle yang diucapkan diikuti oleh bagaimana mereka dapat dimasukkan ke dalam program Anda.
(* pada catatan yang lebih teknis. Operator "IS" benar-benar digunakan sebagai penahanan (yang bukan operator logis). Ketika saya mengatakan "A adalah seorang Ksatria", saya benar-benar berarti "A adalah anggota dari set Ksatria ". Operator sejati yang digunakan adalah 'ϵ'. Demi kesederhanaan, kita akan menggunakan '='.)
Saya menggunakan yang berikut ini (Anda dapat menggunakan apa pun, asalkan masuk akal dan konsisten):
^
DANv
ATAU=
ADALAH~
TIDAK=>
TERSIRATX:
Orang X mengklaim bahwa ...
Orang Z dapat membuat kombinasi dari salah satu dari jenis pernyataan berikut:
Orang Z mengatakan bahwa ...
Orang A adalah seorang Ksatria.
Z: A = 1
Orang Q adalah seorang Knave.
Z: Q = 0
Saya seorang Ksatria.
Z: Z = 1
Orang A adalah Ksatria ATAU Orang B adalah Ksatria.
Z: ( A = 1 ) v ( B = 1)
Orang C adalah Ksatria DAN Saya seorang Knave.
Z: ( C = 1 ) ^ ( Z = 0 )
Orang R BUKAN Ksatria.
Z: ~( R = 1 )
Di atas ini, input juga dapat menggunakan Hukum De Morgan
BUKANLAH benar bahwa baik orang A maupun orang B adalah Knave
Z: ~( ( A = 0 ) ^ ( B = 0 ) )
Adalah salah bahwa orang A atau orang B adalah Ksatria
Z: ~( ( A = 1 ) v ( B = 1) )
Akhirnya, persyaratan dan negasinya dapat digunakan
Jika saya seorang Ksatria, maka orang B adalah seorang Knave
Z: ( Z = 1 ) => ( B = 0 )
BUKANLAH jika orang B adalah seorang Ksatria, maka Orang C adalah seorang Knave.
Z: ~( ( B = 1 ) => ( C = 0 ) )
Catatan tentang persyaratan
Lihat wikipedia untuk info lebih lanjut.
Pernyataan bersyarat mengambil bentuk p => q , di mana p dan q sendiri adalah pernyataan. p adalah "anteseden" dan q adalah "konsekuen". Berikut ini beberapa info bermanfaat
Negasi dari suatu kondisi terlihat seperti ini: ~ (p => q) setara dengan p ^ ~ q
Premis palsu menyiratkan apa pun. Yaitu: jika p salah, maka pernyataan apa pun p => q benar, terlepas dari apa q itu. Misalnya: "jika 2 + 2 = 5 maka saya Spiderman" adalah pernyataan yang benar.
Beberapa test case sederhana
Kasus-kasus ini diberikan dengan cara berikut (1) bagaimana kita akan menimbulkan masalah dalam perkataan (2) bagaimana kita dapat mengajukannya ke komputer (3) hasil yang benar yang mungkin diberikan oleh komputer.
Orang A dan Orang B mendekati Anda di jalan dan membuat pernyataan berikut:
A: B adalah knave atau saya seorang knight.
B: A adalah seorang ksatria.
Menjawab:
B adalah Ksatria dan A adalah Ksatria.
Memasukkan:
A B # Cast of Characters
A: ( B = 0 ) v ( A = 1)
B: A = 1
Keluaran:
A = 1 B = 1
Orang A, B, dan F mendekati Anda di jalan dan membuat pernyataan berikut:
A: Jika saya seorang Ksatria, maka B adalah Knave.
B: Jika itu benar, maka F juga Knave.
Menjawab:
A adalah Knight, B adalah Knave, F adalah Knight.
Memasukkan
A B F
A: ( A = 1 ) => ( B = 0 )
B: ( A = 1 ) => ( F = 0 )
Keluaran:
A = 1 B = 0 F = 1
Q, X, dan W mendekati Anda di jalan dan membuat pernyataan berikut:
W: Tidak benar bahwa Q dan X adalah Knights.
T: Itu benar.
X: Jika apa yang dikatakan W benar, maka apa yang dikatakan Q itu salah.
Menjawab:
W dan Q adalah Knights. X adalah Knave.
Memasukkan
Q X W
W: ~( ( Q = 1 ) ^ ( X = 1 ) )
Q: W = 1
X: ( W = 1 ) => ( Q = 0 )
Keluaran
W = 1 Q = 1 X = 0
Ada tantangan serupa dari 3 tahun lalu yang berfokus pada penguraian dan tidak mengandung persyaratan atau De Morgan. Dan oleh karena itu, saya berpendapat, cukup berbeda dalam fokus dan implementasi untuk menghindari ini menjadi penipuan.
Tantangan ini ditutup sebentar sebagai penipu. Sejak itu telah dibuka kembali.
Saya mengklaim bahwa tantangan ini, pertama, berbeda dalam fokus. Tantangan lain berfokus pada penguraian bahasa Inggris, ini tidak. Kedua hanya menggunakan AND dan OR sedangkan ini menggunakan kondisi dan memungkinkan untuk memecahkan lebih banyak teka-teki. Pada akhirnya, pertanyaannya adalah apakah jawaban atau tidak dari tantangan itu dapat diganti secara sepele untuk yang satu ini, dan saya percaya bahwa penyertaan kondisional dan negasi bersyarat menambah kompleksitas yang cukup sehingga perubahan yang lebih kuat perlu dilakukan secara berurutan agar sesuai dengan tantangan ini.
(B=1)=>(C=0)
?~((B=1)=>(C=0))
atau(B=1)=>(C=1)
sesuatu yang lain?OR
, bisa jadiA:1 B:1
atauA:1 B:0
karena BB=1
bisa salah sementara A masih benar.(B=1)^(C=1)
sesuai dengan bagaimana kondisi biasanya ditanganiJawaban:
Python 3,
450342307 byteEdit: ternyata saya lupa impor ...
Solusi pertama saya memanfaatkan penamaan yang fleksibel untuk kueri
Anda dapat memanggil yang di atas dengan
Yang berikutnya di sini menggunakan format kueri yang sama seperti yang terlihat di OP, itu juga tidak memiliki beberapa modifikasi yang saya buat untuk yang pertama. Ini adalah 417 byte karena mengkonversi antara dua format.
Dan itu bisa disebut dengan:
Mereka berdua kembali
Penjelasan Tidak Dikunci:
Juga, solusi kedua membutuhkan 3,5 (bukan 3,4) karena penggunaan PEP 448
sumber
Mathematica, 80 byte
Penjelasan
Fungsi ini
F
mengambil dua argumen,c
adalah daftar nama semua karakter,s
adalah daftar pernyataan, yang masing-masing berisi dua bagian - siapa bilang apa.Misalnya, ada tiga karakter, Q, X dan W.
Dan mereka berkata,
di mana
True
danFalse
berarti Ksatria dan Knave masing-masing. Kemudianakan memberikan
{{q->True, x->False, w->True}}
, yang berarti hanya ada satu solusi yang Q dan W adalah Knights sementara X adalah Knave. Jika ada lebih dari satu solusi, hasilnya akan terlihat seperti{{...},{...},...}
Algoritma ini sangat sederhana.
{True,False}~Tuples~Length@c
memberikan semua kemungkinan kombinasi Knights and Knaves di antara para karakter. KemudianThread[c->#]&/@
buat susunan aturan berdasarkan kombinasi ini. Dalam kasus dua karakter A dan B, array akan menjadiMengganti pernyataan dengan satu baris aturan ini, kita akan mendapatkan tampilan seperti array
Kolom pertama dari array ini adalah identitas pembicara, dan kolom kedua menunjukkan apakah pernyataan mereka benar atau salah. Solusi yang valid membutuhkan kesesuaian antara identitas pembicara dan pernyataan mereka. Array di atas berarti bahwa kombinasi ini bukan solusi, karena pembicara kedua, Knight, membuat pernyataan yang salah.
melakukan pergantian dan memilih kombinasi yang memenuhi syarat.
sumber
Ruby, 128
Ini adalah algoritme yang sama dengan yang lainnya, cobalah semua kemungkinan kombinasi knave dan knight dan lihat stik mana. Saya punya yang lain yang sedang saya kerjakan, tapi saya pikir itu akan lebih lama (meskipun lebih menarik).
Input pernyataan harus:
&
DAN|
ATAU==
ADALAH!
TIDAK>
TERSIRATX:
Orang X mengklaim bahwa ...Saya juga mengharuskan setiap pernyataan dan sub-pernyataan berada dalam tanda kurung. Satu-satunya masalah dengan versi ini adalah bahwa ia melewati paling banyak 2 ^ 26 iterasi, dan jika mereka tidak semua tahu, setidaknya 2 ^ (26-n) iterasi ! Untuk menempatkan itu dalam perspektif, itu berarti bahwa jika ada dua orang, dan setidaknya satu bukanlah suatu pertalian, itu akan mengambil minimal 16.777.216 iterasi !
Untuk membatasi itu, saya mengirimkan berikut ini di 168 byte. Masuk
26
untuk#{o.size}
memotongnya kembali ke 161.Tetapi jika saya bisa menggunakan array orang dan peta pernyataan misalnya:
Lalu saya turunkan ke 128.
sumber