Saya memiliki masalah kombinatorik yang ingin saya gunakan pada OEIS — masalahnya adalah saya tidak memiliki persyaratan yang cukup. Tantangan kode ini adalah untuk membantu saya menghitung lebih banyak istilah, dan pemenangnya adalah pengguna dengan kiriman yang berisi jumlah syarat terbesar.
Masalah
Misalkan saya memberi Anda array segitiga bola lampu dengan panjang sisi :
o
o o
o o o
o o o o
o o o o o
o o o o o o
1 2 ... n
Saya akan menyalakan tiga bola lampu yang membentuk segitiga sama sisi "tegak" seperti dalam contoh berikut:
o
o x
o o o
o o o o
o x o o x
o o o o o o
Sebelum saya menyalakan lampu, tugas Anda adalah menghilangkan sebanyak mungkin bola lampu dari array — tanpa kehilangan kemampuan untuk menyimpulkan segitiga bola lampu yang telah dinyalakan. Untuk menjadi jelas, jika bola lampu telah dilepas, itu tidak menyala ketika posisinya dihidupkan.
Misalnya, jika Anda melepas lampu berikut (ditandai oleh .
), Anda hanya akan melihat dua lampu berikut menyala (ditandai oleh x
), yang cukup unik untuk menyimpulkan posisi ketiga (tidak menyala):
. .
. o . x
. . o . . o
o o o . => o o o .
o o o o . o x o o . <- the third unlit position
o . . . o o o . . . o o
Membiarkan a(n)
menjadi jumlah maksimum umbi yang dapat dihapus tanpa memperkenalkan ambiguitas.
Contoh
Dengan algoritma naif, saya telah memeriksa nilai hingga segitiga dengan panjang sisi 7, seperti yang terlihat di bawah ini:
.
. . o
. . o o . o
. . . . . o . o o .
. . . . o o o o o . o o . o .
. . . . o o o o . o o o o o . o . o . o o
. . . o o . o o o o . . o o o . . . o o o . o . o o o
a(2) = 3 a(3) = 4 a(4) = 5 a(5) = 7 a(6) = 9 a(7) = 11
Mencetak gol
Kiriman yang menghitung urutan [a(2), a(3), ..., a(n)]
untuk n terbesar menang. Jika dua pengiriman memiliki urutan yang sama, maka yang dikirim sebelumnya menang.
Meskipun tidak perlu untuk pengajuan, akan bermanfaat bagi saya jika Anda memposting konstruksi array triangluar yang dihasilkan, seperti pada contoh di atas.
sumber
Jawaban:
Python 3 ,
n=8
Menggunakan pemecah CP-SAT Google OR-Tools .
Setelah berjalan selama ~ 30 detik, ini menghasilkan yang berikut:
n=9
a(9)=15
n=8
Bagaimana itu bekerja
Dengan demikian pertanyaan tersebut dapat diulang sebagai masalah SAT, dengan satu kendala untuk setiap pasangan segitiga.
PS: Saya sangat ingin memasukkan contoh
n=8
, tapi saya mengalami masalah dengan pemecah SAT yang tampaknya ingin menyimpan semua solusi untuk dirinya sendiri.sumber
Mendapatkan solusi dari program @ Delfad0r
Saya memperluas program @ Delfad0r untuk menghasilkan solusi. Ini juga memberikan hasil menengah, sehingga Anda mendapatkan output seperti ini:
Perhitungan ini memakan waktu beberapa jam.
Jika Anda menjadi tidak sabar dan menekan
Ctrl-C
setelah beberapa solusi yang mungkin tidak optimal ditemukan, program akan menunjukkan solusi itu. Jadi tidak butuh waktu lama untuk mendapatkan ini:Berikut adalah program lanjutannya:
sumber
Python 3
Didasarkan kuat pada jawaban Delfad0r , sebagian besar mengikuti perkembangan logika yang sama dengan memeriksa pasangan segitiga dan memvalidasi konfigurasi jika tidak mengandung pasangan segitiga yang gagal validasi ini. Karena saya tidak menggunakan perpustakaan apa pun selain itertools dan salin, saya memiliki kontrol penuh untuk menyimpan contoh yang ditemukan di seluruh program.
Masalahnya, itu tidak terlalu efisien. Ini berjalan sangat cepat hingga
n=5
, tetapi mulai melambat secara signifikan melewati titik itu. Padan=6
, dibutuhkan sekitar satu menit untuk berlari, dan itu jauh lebih lambatn=7
. Saya membayangkan ada banyak perbaikan efisiensi yang dapat dilakukan dengan program ini, tetapi ini merupakan rancangan kasar dari solusi yang baik dengan lebih banyak fleksibilitas untuk memeriksa cara kerja metode ini. Saya akan secara bertahap mengerjakan ini dari waktu ke waktu.sumber