Dalam tantangan ini, Anda akan menerima daftar bobot yang dipisahkan koma sebagai input, seperti
1,3,4,7,8,11
Dan Anda harus menampilkan jumlah bobot terkecil yang dapat ditambahkan ke set itu. Misalnya, output untuk set ini adalah
1,3,7
Karena Anda bisa mewakili semua bobot itu hanya dengan ketiganya:
1 = 1
3 = 3
1+3 = 4
7 = 7
1+7 = 8
1+3+7 = 11
Mungkin ada lebih dari satu solusi. Misalnya, solusi Anda untuk input 1,2
bisa 1,1
atau 1,2
. Selama menemukan jumlah bobot minimum yang dapat mewakili set input, ini adalah solusi yang valid.
Bobot tidak boleh digunakan lebih dari sekali. Jika Anda perlu menggunakannya dua kali, Anda harus mengeluarkannya dua kali. Misalnya, 2,3
bukan solusi yang valid untuk 2,3,5,7
karena Anda tidak dapat menggunakan 2
dua kali untuk 2+2+3=7
.
Input dijamin tidak memiliki nomor duplikat.
Ini adalah kode-golf sehingga kode terpendek menurut jumlah karakter menang.
Akses jaringan dilarang (jadi tidak ada wget
solusi "pintar" Anda @JohannesKuhn batuk batuk );)
Kasus paling sederhana:
1,5,6,9,10,14,15 => 1,5,9
7,14,15,21,22,29 => 7,14,15
4,5,6,7,9,10,11,12,13,15,16,18 => 4,5,6,7
2,3,5,7 => 2,2,3 or 2,3,7
Dan beberapa yang lebih rumit:
10,16,19,23,26,27,30,37,41,43,44,46,50,53,57,60,61,64,68,71,77,80,84,87
=> 3,7,16,27,34
20,30,36,50,56,63,66,73,79,86
=> 7,13,23,43
27,35,44,46,51,53,55,60,63,64,68,69,72,77,79,81,86,88,90,95,97,105,106,114,123,132
=> 9,18,26,37,42
7,7,7,8
atas), yang meningkatkan kerumitan banyak kali.n
bobot masukan danm
merupakan yang terbesar, sebutkan semua urutan(1..m)
dan untuk setiap urutan , sebutkan setiap kombinasi antara 1 dann
contoh masing-masing elemen urutan.)Jawaban:
Mathematica
8075Pembaruan: Lihat di bagian bawah pembaruan tentang tes terakhir Doorknob yang menantang, ditambahkan pada 5 November
Ini melewati semua kecuali tes terakhir. Namun, ia tidak berusaha menggunakan angka lebih dari sekali. Dan itu hanya mencari dari solusi yang merupakan himpunan bagian dari kumpulan data yang lebih besar.
Fungsi menghasilkan semua himpunan bagian dari himpunan data input dan kemudian menguji himpunan bagian yang dapat digunakan untuk membangun himpunan lengkap. Setelah himpunan bagian yang layak ditemukan, ia memilih set terkecil.
Tes
Memperbarui
Di bawah ini saya akan memberikan analisis awal yang dapat membantu memulai menuju solusi.
Data:
Berbeda dari pendekatan sebelumnya, kami ingin mempertimbangkan, dalam set solusi, angka-angka yang TIDAK muncul dalam set data.
Pendekatan ini memanfaatkan perbedaan mutlak antara pasangan angka dalam kumpulan data.
Mari kita lihat berapa kali setiap perbedaan muncul; kami hanya akan mengambil 8 kasus pertama, mulai dari perbedaan paling umum].
14 pasang berbeda dengan 7; 13 pasang berbeda 27, dan seterusnya.
Sekarang mari kita uji himpunan bagian dimulai dengan {difference1}, {difference1, difference2}, dan seterusnya, sampai kita semoga dapat menjelaskan semua elemen asli dalam kumpulan data.
h
mengungkapkan angka-angka dari himpunan asli yang tidak dapat dibangun dengan menyusun jumlah dari himpunan bagian.Pada percobaan kelima, masih ada 10 elemen yang tidak dapat dibentuk dari {7, 27, 34, 3, 20}:
Tetapi pada percobaan berikutnya, semua angka dari set data dicatat:
Ini masih tidak ekonomis seperti {3,7,16,27,34}, tapi sudah dekat.
Masih ada beberapa hal tambahan yang perlu diperhatikan.
Ini lebih banyak masalah daripada yang bisa saya tangani saat ini. Tapi saya harap ini memberikan sedikit cahaya pada tantangan yang sangat menarik ini.
sumber
w
diulang, maka solusi yang sama dengan salah satu dariw
s berubah2 * w
juga berfungsi, karena Anda dapat menggunakan di2 * w
mana - mana Anda gunakanw + w
sebelumnya. Ini dapat diulang sampai solusi tidak memiliki pengulangan. Oleh karena itu, Anda tidak perlu mencoba menggunakan pengulangan.s=Subsets;
keluar dari fungsiRuby 289
Ini adalah penghitungan langsung, sehingga akan mendapatkan solusi minimal, tetapi mungkin butuh bertahun-tahun - mungkin tahun cahaya - untuk menyelesaikan beberapa masalah. Semua "kasus paling sederhana" menyelesaikan paling banyak beberapa detik (meskipun saya mendapat masing-masing 7,8,14 dan 1,2,4 untuk kasus ke-3 dan ke-5). Tricky # 2 diselesaikan dalam waktu sekitar 3 jam, tetapi dua lainnya terlalu besar untuk dihitung, paling tidak untuk cara saya melakukannya.
Array ukuran
n
yang menghasilkan array yang diberikan dengan menjumlahkan himpunan bagian dari elemen-elemennya adalah ukuran minimal jika dapat ditunjukkan bahwa tidak ada array ukuran< n
yang melakukan itu. Saya tidak bisa melihat cara lain untuk membuktikan optimalitas, jadi saya memulai penghitungan dengan himpunan bagian ukuranm
, di manam
batas bawah diketahui, dan kemudian menambah ukuranm+1
setelah menghitung himpunan bagian ukuranm
dan menunjukkan mereka tidak ada "rentang" yang diberikan array, dan sebagainya, sampai saya menemukan yang optimal. Tentu saja, jika saya telah menghitung semua himpunan bagian hingga ukuran n, saya bisa menggunakan heuristik untuk ukuran n +1, sehingga jika saya menemukan array spanning ukuran itu, saya akan tahu itu optimal. Adakah yang bisa menyarankan cara alternatif untuk membuktikan solusi yang optimal dalam kasus umum?Saya telah menyertakan beberapa pemeriksaan opsional untuk menghilangkan beberapa kombinasi sejak awal. Menghapus cek itu akan menghemat 87 karakter. Mereka adalah sebagai berikut (
a
adalah array yang diberikan):n
dapat menghasilkan paling2^n-1
banyak angka positif yang berbeda; karenanya,,2^n-1 >= a.size
ataun >= log2(a.size).ceil
("batas bawah" yang saya sebutkan di atas).b
ukurann
dapat dikesampingkan jika:b.min > a.min
sum of elements of b < a.max
ataub.max < v
, dimanav = a.max.to_f/n+(n-1).to_f/2.ceil
(to_f
sedang konversi ke float).Yang terakhir ini, yang diperiksa terlebih dahulu, mengimplementasikan
Catatan
v
konstan untuk semua array ukuran generatorn
.Saya juga menggunakan pengamatan sangat kuat @ cardboard_box bahwa tidak perlu mempertimbangkan duplikat dalam array menghasilkan.
Dalam kode saya,
menghasilkan semua kombinasi angka 1
a.max
, diambiln
pada satu waktu (di manaa.max = a.last = a[-1]
). Untuk setiap kombinasib
:mengisi hash
h
dengan semua angka yang jumlah dari himpunan bagian tidak kosong darib
. Kunci hash adalah angka-angka itu; nilai-nilai itu berubah-ubah. (Saya memilih untuk mengatur yang terakhir ke nol.)memeriksa apakah setiap elemen dari array yang diberikan
a
adalah kunci dalam hash (h[e] != nil
, atau justh[e]
).Seharusnya
Lalu kami beralih pada rentang:
Representasi biner dari setiap angka dalam kisaran ini digunakan untuk menusuk elemen-elemen dari
b
penjumlahan. Untukj = 3
(j
menjadi indeks rentang),Kode:
sumber