Diberikan:
- Sejumlah alami S .
- Daftar bobot rasional W yang menjumlahkan ke 1.
Kembalikan daftar L dari N bilangan bulat non-negatif, sehingga:
(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal
Dengan kata lain, perkiraan S⋅W_i
s dengan bilangan bulat sedekat mungkin.
Contoh:
1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]
Aturan:
- Anda dapat menggunakan format input apa pun, atau hanya menyediakan fungsi yang menerima input sebagai argumen.
Latar Belakang:
Masalah ini muncul ketika menampilkan S dari berbagai jenis item dalam proporsi berbeda W i berkaitan dengan jenis.
Contoh lain dari masalah ini adalah perwakilan politik proporsional, lihat paradoks pembagian . Dua kasus uji terakhir dikenal sebagai Alabama paradox.
Sebagai ahli statistik, saya mengenali masalah ini sebagai setara dengan masalah yang ditemukan dalam mengidentifikasi ukuran sampel ketika melakukan sampel bertingkat. Dalam situasi itu, kami ingin membuat proporsi setiap strata dalam sampel sama dengan proporsi setiap strata dalam populasi. - @tomi
code-golf
number
arithmetic
Glebm
sumber
sumber
round(A + B) != round(A) + round(B)
, solusi singkat memerlukan wawasan tentang apa yang terjadi di sini.L[i] - S*W[i]
kuadrat, bukannya aturan 2 dan aturan 3. Ini akan mendekatiS*W[i]
.[0 1 2 2]
merupakan solusi lain yang mungkin untuk5 [0.1 0.2 0.3 0.4]
Jawaban:
APL, 21
Ini adalah terjemahan dari jawaban CJam 37 byte aditsu .
Uji secara online .
Penjelasan
sumber
Python 2,
9583132125143Algoritma pertama (dan kedua) (dan ketiga) saya mengalami masalah sehingga setelah penulisan ulang (yang lain!) Dan lebih banyak pengujian, inilah (saya sangat berharap) solusi yang benar dan cepat:
Sumber sebelum minifier sekarang terlihat seperti:
Tes kembali:
Algoritma ini mirip dengan jawaban lain di sini. Ini adalah O (1) untuk num sehingga memiliki waktu berjalan yang sama untuk bilangan bulat 10 dan 1000000. Secara teoritis O (nlogn) untuk jumlah bobot (karena jenisnya). Jika ini tahan semua kasus input rumit lainnya, itu akan menggantikan algoritma di bawah ini di kotak alat pemrograman saya.
Tolong jangan gunakan algoritma itu dengan apa pun yang tidak golf. Saya membuat kompromi dalam kecepatan untuk meminimalkan ukuran sumber. Kode berikut menggunakan logika yang sama tetapi jauh lebih cepat dan lebih bermanfaat:
Nilai num tidak mempengaruhi kecepatan secara signifikan. Saya telah mengujinya dengan nilai dari 1 hingga 10 ^ 19. Waktu pelaksanaan bervariasi secara linear dengan jumlah bobot. Di komputer saya dibutuhkan 0,15 detik dengan bobot 10 ^ 5 dan 15 detik dengan bobot 10 ^ 7. Perhatikan bahwa bobot tidak terbatas pada fraksi yang berjumlah satu. Teknik pengurutan yang digunakan di sini juga sekitar dua kali lebih cepat dari
sorted((v,i) for i,v in enumerate...)
gaya tradisional .Algoritma Asli
Ini adalah fungsi di kotak alat saya, dimodifikasi sedikit untuk golf. Ini berasal dari jawaban SO . Dan itu salah.
Ini memberikan perkiraan, tetapi tidak selalu benar, meskipun jumlah (outseq) == num dipertahankan. Cepat tapi tidak disarankan.
Terima kasih kepada @alephalpha dan @ user23013 untuk mengetahui kesalahannya.
EDIT: Tetapkan totalw (d) menjadi 1 karena OP menentukan jumlah bobot akan selalu menjadi 1. Sekarang 83 byte.
EDIT2: Fixed bug ditemukan untuk [0,4, 0,3, 0,3], 1.
EDIT3: Algoritma cacat yang ditinggalkan. Menambahkan yang lebih baik.
EDIT4: Ini menjadi konyol. Diganti dengan algoritma yang benar (saya sangat berharap demikian).
EDIT5: Menambahkan kode tidak-golf untuk orang lain yang mungkin ingin menggunakan algoritma ini.
sumber
a([0.4, 0.3, 0.3], 1)
kembali[0, 1, 0]
, sedangkan jawaban yang benar adalah[1, 0, 0]
.a([0.11,0.3,0.59],4)
dikembalikan[0, 1, 3]
. Seharusnya[1, 1, 2]
.f([0.47,0.47,0.06],10)
dikembalikan[5, 4, 1]
. Seharusnya[5, 5, 0]
.Mathematica,
67504645 karakterTidak Disatukan:
Contoh:
sumber
CJam - 37
Cobalah online
Penjelasan:
Catatan:
Ide berbeda - 46
Cobalah online
Ini jauh lebih mudah dan efisien, tetapi sayangnya, sedikit lebih lama. Idenya di sini adalah mulai dengan L_i = lantai (S * W_i), tentukan perbedaan (katakanlah D) antara S dan jumlah mereka, temukan indeks D dengan bagian pecahan terbesar dari S * W_i (dengan menyortir dan mengambil D atas) dan kenaikan L_i untuk indeks tersebut. Kompleksitas O (N * log (N)).
sumber
:e<
.JavaScript (ES6) 126
130 104 115 156 162 194Setelah semua komentar dan test case dalam jawaban @ CarpetPython, kembali ke algoritma pertama saya. Sayangnya, solusi cerdas tidak berhasil. Implementasinya diperpendek sedikit, masih mencoba semua solusi yang mungkin, menghitung jarak kuadrat dan menjaga minimum.
Edit Untuk setiap elemen keluaran bobot w, 'semua' nilai yang mungkin hanya 2: trunc (w * s) dan trunc (w * s) +1, sehingga hanya ada (2 ** elemensts) solusi yang mungkin untuk dicoba.
Uji di Firefox / konsol FireBug
Keluaran
Itu solusi yang lebih cerdas. Lulus tunggal pada susunan bobot.Untuk setiap pass saya menemukan nilai maks saat ini di w. Saya mengubah nilai ini di tempat dengan nilai integer tertimbang (dibulatkan), jadi jika s == 21 dan w = 0,4, kami mendapat 0,5 * 21 -> 10,5 -> 11. Saya menyimpan nilai ini dinegasikan, sehingga tidak bisa dapat ditemukan sebagai maks di loop berikutnya. Kemudian saya mengurangi jumlah total yang sesuai (s = s-11) dan juga mengurangi total bobot dalam variabel f.
Loop berakhir ketika tidak ada maks di atas 0 yang dapat ditemukan (semua nilai! = 0 telah dikelola).
Akhirnya saya mengembalikan nilai yang diubah menjadi positif lagi. Peringatan kode ini mengubah array bobot di tempat, sehingga harus dipanggil dengan salinan array asli
Percobaan pertama saya
Bukan solusi yang cerdas. Untuk setiap kemungkinan hasil, ini mengevaluasi perbedaan, dan menjaga minimum.
Tidak Diikat Dan dijelaskan
sumber
CJam, 48 byte
Solusi lurus ke depan untuk masalah ini.
Inputnya seperti
Penjelasan:
Cobalah online di sini
sumber
Pyth: 40 byte
Ini mendefinisikan fungsi
g
dengan 2 parameter. Anda bisa menyebutnya sepertiMhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4
.Cobalah secara online: Pyth Compiler / Executor
Penjelasan:
Ini menciptakan semua solusi yang mungkin
L
, di manaL[i] = floor(S*W[i])
atauL[i] = floor(S*W[i]+1)
. Misalnya, input4 [0.3 0.4 0.3
menciptakan[[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]]
.Hanya
[[2, 1, 1], [1, 2, 1], [1, 1, 2]]
tinggal.sumber
Mathematica 108
Penjelasan
Tidak disatukan
IntegerPartitions[s,{Length@w},0~Range~s]
mengembalikan semua partisi integers
, menggunakan elemen yang diambil dari set{0, 1, 2, ...s}
dengan batasan bahwa output harus mengandung jumlah elemen yang sama seperti pada set bobotw
,.Permutations
memberikan semua pengaturan yang dipesan dari setiap partisi integer.{Tr[(s *w-#)^2],#}
mengembalikan daftar pasangan yang dipesan,{error, permutation}
untuk setiap permutasi.Sort[...]
mengurutkan daftar{{error1, permutation1},{error2, permutation2}...according to the size of the error.
[[1,2]]]
atauPart[<list>,{1,2}]
mengembalikan item kedua dari elemen pertama dalam daftar diurutkan dari{{error, permutation}...}
. Dengan kata lain, itu mengembalikan permutasi dengan kesalahan terkecil.sumber
R,
858076Menggunakan metode Kuota Kelinci.
Menghapus pasangan setelah melihat spesifikasi bahwa W akan berjumlah 1
Uji coba
sumber
Python,
139128117 byteSolusi itertools sebelumnya, 139 byte
sumber
O(S^len(W))
sebenarnya: P. Solusi baru jauh lebih cepat, tetapi masih lambatOktaf,
8776Golf:
Tidak Disatukan:
(Blasted "endfor" dan "endfunction"! Saya tidak akan pernah menang tetapi saya menikmati bermain golf dengan bahasa "nyata".)
sumber
zeros(size(w))
dengan0*w
.T-SQL,
167265Karena saya suka mencoba dan melakukan tantangan ini dalam kueri juga.
Mengubahnya menjadi fungsi inline agar lebih sesuai dengan spesifikasi dan membuat tipe untuk data tabel. Harganya sedikit, tapi ini tidak akan pernah menjadi pesaing. Setiap pernyataan harus dijalankan secara terpisah.
Digunakan
sumber