The Algoritma Tunai ini adalah algoritma untuk membuat perubahan dalam jumlah minimal koin yang bekerja cukup baik untuk sebagian besar sistem mata uang. Namun seperti kebanyakan algoritma serakah itu bukan tanpa kekurangannya. Jika sistem mata uang diatur tepat (atau salah) ada nilai-nilai tertentu di mana Algoritma Kasir akan gagal menemukan perubahan optimal.
Ambil contoh berikut:
Kami memiliki 4 ¢, 3 ¢, dan 1 ¢ koin. Kami ingin membuat 6 ¢.
Algoritma Kasir pertama-tama akan memilih sebanyak mungkin koin terbesar (satu 4 ¢ untuk memulai) dan kurangi dan ulangi. Ini akan menghasilkan satu koin 4 ¢ dan dua koin 1 ¢, dengan total 3 koin.
Sayangnya untuk Algoritma ada cara untuk membuat 6 ¢ dengan hanya dua koin (dua koin 3 ¢).
Sistem perubahan akan dianggap iff kanonik untuk semua nilai integer Algoritma Kasir akan menemukan jumlah koin yang optimal.
Tugas
Tugas Anda adalah mengambil sistem sebagai wadah tidak berurutan atau wadah bilangan bulat berurutan yang diurutkan yang mewakili nilai koin dan menghasilkan nilai kebenaran jika input sistem kanonik dan palsu sebaliknya.
Program Anda harus bekerja untuk semua sistem yang dapat menciptakan nilai apa pun. (yaitu semua sistem akan memiliki koin 1 ¢)
Ini adalah kode golf paling tidak byte yang menang.
Uji kasus
Daftar ini sama sekali tidak lengkap, program Anda harus bekerja untuk semua input yang valid
1, 3, 4 -> 0
1, 5, 10, 25 -> 1
1, 6, 10, 25 -> 0
1, 2, 3 -> 1
1, 8, 17, 30 -> 0
1, 3, 8, 12 -> 0
1, 2, 8, 13 -> 0
1, 2, 4, 6, 8 -> 1
sumber
25, 9, 4, 1
(dari pos matematika ini. SE ) - meskipun setiap koin lebih besar dari jumlah yang lebih kecil, yang tidak serakah25, 4, 4, 4
mengalahkan yang serakah25, 9, 1, 1, 1
.9, 4, 1
->4, 4, 4
menjadi lebih baik daripada9, 1, 1, 1
contoh yang lebih ketat.Jawaban:
Haskell,
948782 bytesolusi ini bekerja dengan mendefinisikan fungsi
j
yang menjalankan algoritma kasir dan memberi tahu kami berapa banyak koin yang digunakan kasir. kami kemudian memeriksa hingga dua kali angka terbesar dalam daftar, dengan asumsi bahwa sistem telah kanonik untuk semua angka sebelumnya, bahwa mengambil koin sebanyak mungkin adalah pilihan yang tepat.solusi ini mengasumsikan input diurutkan.
bukti memeriksa hingga dua kali jumlah terbesar sudah cukup: anggap sistem tidak kanonik untuk beberapa nomor
i
, dan biarkank
nomor terbesar dalam daftar tidak lebih besar darii
. menganggap itui >= 2k
dan sistem adalah kanonik untuk semua angka kurang darii
.mengambil beberapa cara optimal untuk membuat
i
koin, dan menganggap itu tidak mengandung koink
. jika kita membuang salah satu koin, jumlah koin yang baru harus lebih besar daripadak
dan lebih kecil darii
- tetapi algoritma kasir pada nomor ini akan menggunakank
koin - dan karenanya, set koin ini dapat diganti dengan set koin yang sama mengandung koink
, dan oleh karena itu ada satu set koin yang berisi koink
untuk nomor tersebuti
, dan dengan induksi algoritma kasir mengembalikan pilihan optimal.argumen ini benar-benar menunjukkan bahwa kita hanya perlu memeriksa sampai jumlah dari dua elemen terbesar - tetapi lebih panjang untuk melakukannya.
Sunting: lepas lima byte berkat Ørjan Johansen!
sumber
let
alih-alihwhere
. Anda bisa meletakkannya sebagai|let ...
penjaga pola setelahf s
, atau di dalam pemahaman daftar.j i=last$0:[1+j(i-k)|k<-s,k<i]
.Pyth,
1815 byteSuite uji
Semacam kekuatan brutal yang berbeda. Ini dimulai dengan membentuk semua koleksi koin hingga masing-masing k, di mana k adalah koin terbesar, yang dianggap sebagai koin terakhir. Saya percaya ini selalu cukup untuk membentuk dua set koin dengan jumlah yang sama, satu serakah dan satu lebih pendek, setiap kali pasangan semacam itu ada.
Saya kemudian menemukan pasangan seperti itu sebagai berikut:
Subhimpunan dihasilkan dalam urutan ukuran meningkat, dan secara leksikografis oleh posisi di input kedua. Kelompokkan koleksi koin dengan jumlah mereka, secara stabil. Setiap koleksi koin dihasilkan dalam urutan menurun, sehingga solusi serakah akan menjadi elemen pertama grup jika dan hanya jika solusi serakah optimal, dan itu akan menjadi elemen terakhir grup secara leksikografis. Jadi, kami menemukan solusi serakah, dan memfilter pada indeks bukan nol di grup. Jika set koin adalah kanonis, ini akan memfilter semuanya, jadi kami secara logis meniadakan hasil dan output.
Penjelasan:
sumber
/opt/tryitonline/bin/pyth: line 5: 28070 Killed ... Exit code: 137
di TIO? Kehabisan memori?PHP, 323 Bytes
Cara yang sama seperti lainnya menghitung koin sampai jumlah dari dua elemen terakhir dalam array
Jawaban terbaik dan terpanjang saya, saya percaya> 370 Bytes
Saya hanya memberikan versi yang diperluas karena lebih lama dari jawaban saya sebelumnya
Penjelasan untuk jawaban ini
Versi Online
Setel semua dalam array ke false == X
Setel semua angka dalam larik yang Anda kontrol ke S
Ditemukan perbedaan antara S terakhir dan S lainnya atau 0
Mulai S terakhir dalam array
Setel semua angka ke D Di mana S Terakhir adalah salah satu dari semua perbedaan
Mulai sama sekali D
SET "T" ke nilai D dalam array
GOTO 5 Ulangi dengan semua yang ditemukan DI tidak melakukannya dalam kode
Jika item berikutnya dalam Array memiliki X itu adalah kasus yang salah lagi Benar
Perbedaan Langkah Tambahan dalam kasus dalam cuplikan 3 Antara 1 dan 4 adalah 2 X Ini berarti Anda memerlukan D kedua pada Langkah 5. Setelah nilai ini dalam kasus ini 10 semuanya benar, saya bisa melihat sejauh ini bahwa ada hubungan antara perbedaan dan jumlah dalam array yang Anda kontrol untuk menghitung berapa banyak D (Langkah 5) yang Anda butuhkan untuk mendapatkan poin sebelum Anda menemukan kasus palsu terakhir.
Anda menetapkan beberapa nilai dari item terakhir langsung ke true. Poin-poin ini dapat membuat perbedaan untuk memutuskan apakah bisa saja jumlah serakah dari koin dengan nilai berikutnya sama maka kelipatan yang terakhir dalam array. Di sisi lain Anda dapat mengatur musuh
Tetapkan musuh pertama di 1 + S Terakhir
Dari titik ini, tambahkan setiap nilai dalam array untuk mengatur musuh berikutnya
Mulai dengan Goto 2 musuh terakhir
Jika sekarang Anda memiliki musuh dan kasus nyata di dalamnya probabilitas tumbuh bahwa jumlah bisa sama Dengan lebih banyak D probabilitas tenggelam.
plus? Bytes Terima Kasih @JonathanAllan memberi saya test case yang salah
262 Bytes Hampir tidak cukup baik 4 testcase salah saat ini
kasus uji [1,16.256] sebelumnya harus benar setelah salah
Urutan Array yang Meningkat
Penjelasan
Sepertinya tabel yang saya lihat berisi nilai dari [1,2,3,4,5,6] dan saya hanya mengubah item terakhir sampai 9. untuk 2to3 dan 4to5 kita membuat nilai dari nilai yang lebih rendah di perhitungan modulo
sumber
", "
ketika Anda bisa berpisah","
; mengapa Anda berpisah ketika Anda bisa mengambil daftar; mengapa Anda menyortir ketika Anda bisa mengambil daftar yang diurutkan? (Saya juga masih tidak yakin apakah metode yang Anda gunakan itu sempurna, sudahkah Anda membuktikannya, karena literatur yang saya baca sekilas sepertinya menyarankan itu lebih sulit daripada apa yang saya pikir kode Anda lakukan.)[1,2,5,11,17]
adalah kanonik. Mungkin melihat kertas yang ditautkan dalam jawaban saya.JavaScript (ES6), 116
125 130Ini membutuhkan array input yang diurutkan dalam urutan menurun. Untuk setiap nilai dari 2N hingga 2 (N menjadi nilai maksimum koin), ia menemukan jumlah koin dari algoritme serakah dan mencoba menemukan kumpulan koin yang lebih kecil.
Kurang golf
Uji
sumber
Python,
218 211205 byte-1 byte berkat @TuukkaX (spasi dapat dihapus antara
<3
danor
)repl.it
Masukan dalam urutan menurun.
Kekuatan brutal yang mengerikan. Setiap set koin satuan tunggal dan beberapa koin lainnya adalah kanonik. Untuk set yang lebih besar, case kegagalan terkecil, jika ada, akan lebih besar dari atau sama dengan koin terkecil ke-3 (tidak yakin sendiri bagaimana bisa setara!) Dan kurang dari jumlah dua koin terbesar - lihat tulisan ini (yang sebenarnya referensi yang lain tetapi juga memberikan metode O (n ^ 3)).
g
menghitung koin yang digunakan dengan metode serakah, dan fungsi yang tidak disebutkan namanya melintasi kandidat yang mungkin (sebenarnya dari 0 menjadi satu kurang dari dua kali koin terbesar untuk menghemat byte) dan mencari koleksi koin yang lebih sedikit yang juga menjumlahkan jumlah itu.g
bekerja dengan melakukan apa yang akan dilakukan seorang kasir, secara rekursif mengambil koin terbesar kurang dari atau sama dengan jumlah yang masih dibuat,[v for v in c if v<=x][0]
hilang, dan menghitung jumlah koin yang digunakann
,.Fungsi yang tidak disebutkan namanya mengembalikan 1 jika
len(c)
kurang dari 3, dan sebaliknya menguji bahwa tidak demikian halnya,,1-...
bahwa nilai apa pun dalam kisaran kemungkinan,range(c[0]*2)))
dimungkinkan dengan koin yang lebih sedikiti in range(g(x,c))
,, dengan membuat koleksi yang banyak dari setiap koin,c*i
, dan memeriksa semua kombinasii
koincombinations(c*i,i)
,, untuk melihat apakah ada jumlah dengan nilai yang sama.sumber
3or
harus bekerja.not(...)
dengan1-...
Jelly ( garpu ),
1514 byteSolusi ini menggunakan batas untuk contoh tandingan dari makalah ini . Di sana, penulis menggunakan ikatan ketat untuk contoh tandingan, tetapi untuk kepentingan bermain golf, kisaran jumlah denominasi koin digunakan yang lebih besar dan berisi ikatan itu.
Program ini menghitung semua test case dalam waktu kurang dari sedetik di mesin saya.
Sayangnya, ini bergantung pada cabang Jelly tempat saya bekerja mengimplementasikan atom pemecah Frobenius sehingga Anda tidak dapat mencobanya secara online.
Pemakaian
Performanya bagus dan dapat menyelesaikan semua kasus uji sekaligus dalam waktu kurang dari satu detik.
Penjelasan
sumber
JavaScript (ES6),
144132124122110 byteMembutuhkan array yang akan diurutkan dalam urutan menurun. Menggunakan pengamatan di kertas yang ditautkan bahwa jika sistem ini tidak kanonik maka ada setidaknya satu nilai kurang dari 2a [0] yang membutuhkan lebih sedikit koin ketika didekomposisi menggunakan koin yang tidak digunakan dari algoritma serakah awal.
Sunting: Disimpan 12 byte dengan menyadari bahwa saya dapat memeriksa semua koin meskipun saya telah mencapai nilai target. Disimpan 8 byte dengan mengalihkan output antara saya dari
[l,b]
ke[b,-l]
; ini memungkinkan saya untuk melewatkan hasil pertama secara langsung sebagai parameter dari panggilan kedua, ditambah juga penghematan kecil yang mendeteksi apakah panggilan kedua berhasil. Disimpan 2 byte dengan memindahkan definisig
ke dalamsome
callback, memungkinkan saya untuk menghindari yang tidak perlu melewati variabel loop dua kali. Disimpan 12 byte dengan beralih dari fungsi pembantu rekursif saya ke panggilan kefilter
(dimungkinkan oleh saklar keluaran antara saya).sumber
Perl, 69 byte
Termasuk +2 untuk
-pa
Berikan koin dalam urutan menurun pada STDIN. Anda dapat meninggalkan
1
koin secara opsional .coins.pl
:Membangun jumlah koin yang digunakan oleh algoritma kasir
@G
untuk jumlah 1 hingga dua kali koin terbesar. Untuk setiap jumlah memeriksa bahwa jika jumlah itu dikurangi dengan 1 nilai koin, algoritma kasir membutuhkan paling banyak 1 koin kurang. Jika tidak, ini adalah sampel tandingan (atau ada sampel tandingan sebelumnya). Saya bisa berhenti pada counterexample pertama tetapi itu membutuhkan lebih banyak byte. Jadi kompleksitas waktuO(max_coin * coins)
dan kompleksitas ruangO(max_coin)
sumber