Enumerasi Ubah Masalah Koin Menggunakan N Koin Dan Setiap Denominasi

13

Masalah perubahan koin didokumentasikan dengan sangat baik. Diberikan pasokan koin denominasi tanpa batas x_1kepada x_mAnda, Anda perlu menemukan jumlah kombinasi yang berjumlah hingga y. Misalnya, diberikan x = {1,2,3}dan y = 4kami memiliki empat kombinasi:

  1. {1,1,1,1}
  2. {1,1,2}
  3. {1,3}
  4. {2,2}

pengantar

Ada beberapa variasi masalah perubahan koin. Dalam variasi ini kami memiliki dua batasan tambahan:

  1. Setiap denominasi harus digunakan setidaknya satu kali.
  2. Jumlah koin yang pasti harus digunakan secara total.

Misalnya, diberikan x = {1,2,3}, y = 36dan di n = 15mana njumlah total koin yang harus digunakan, kami mendapatkan empat kombinasi:

  1. {1,2,2,2,2,2,2,2,3,3,3,3,3,3,3} (1 yang, 7 dua, 7 bertiga)
  2. {1,1,2,2,2,2,2,3,3,3,3,3,3,3,3} (2 orang, 5 pasangan, 8 bertiga)
  3. {1,1,1,2,2,2,3,3,3,3,3,3,3,3,3} (3 yang, 3 dua, 9 bertiga)
  4. {1,1,1,1,2,3,3,3,3,3,3,3,3,3,3} (4 orang, 1 dua, 10 bertiga)

Tantangan

Tantangannya adalah untuk menulis fungsi enumeratedalam bahasa pilihan Anda yang menyebutkan semua kombinasi seperti dijelaskan di atas:

  1. Daftar denominasi. Sebagai contoh {1,5,10,25}. Anda dapat menggunakan daftar atau array.
  2. Integer non-negatif yyang menunjukkan jumlah setiap kombinasi.
  3. Bilangan bulat non-negatif nyang menunjukkan jumlah total koin.

Urutan argumen tidak masalah. Fungsi pointfree diizinkan.

Output dari enumeratefungsi harus berupa daftar kombinasi. Setiap kombinasi harus unik dan harus berupa daftar nbilangan bulat yang ditambahkan y. Setiap denominasi harus muncul setidaknya sekali dalam setiap kombinasi dan tidak ada kombinasi yang harus hilang. Urutan bilangan bulat dan kombinasinya tidak masalah. Anda dapat menggunakan daftar atau array untuk output.

Ingatlah kasus tepi berikut:

  1. Jika keduanya ydan nnol dan daftar denominasi kosong maka output adalah daftar satu kombinasi, kombinasi kosong (yaitu {{}}).
  2. Kalau tidak, jika ynol, nadalah nol atau daftar denominasi kosong maka outputnya adalah daftar kombinasi nol (yaitu {}).
  3. Lebih umum, jika ylebih kecil dari jumlah denominasi atau nkurang dari jumlah denominasi maka hasilnya adalah daftar kombinasi nol.

Penilaian akan didasarkan pada ukuran seluruh program dalam byte. Perhatikan bahwa ini termasuk enumeratefungsi, fungsi pembantu, pernyataan impor, dll. Ini tidak termasuk kasus uji.

Aadit M Shah
sumber
Cukup yakin saya telah melihat tantangan ini di suatu tempat ...
Leaky Nun
Saya harap pertanyaan ini bukan duplikat. Saya tidak dapat menemukan pertanyaan yang sama pada Code Golf. Karenanya, saya mempostingnya.
Aadit M Shah
@PeterTaylor Jika ykurang dari jumlah denominasi maka pada beberapa titik dalam solusi rekursif Anda, Anda akan mencapai kasus dasar di mana daftar denominasi kosong. Oleh karena itu, jawabannya adalah {}(yaitu tidak ada solusi yang ditemukan). Jika nkurang dari jumlah denominasi maka pada akhirnya Anda akan mencapai kasus dasar di mana n = 0tetapi y != 0. Karenanya, jawabannya akan kembali {}.
Aadit M Shah
@PeterTaylor Memang. Saya mungkin berasumsi terlalu banyak tentang detail implementasi. Apakah Anda tahu cara memperbaikinya?
Aadit M Shah
10
Saya sarankan Anda menghapus bendera "Diterima" sampai Anda mendapatkan jawaban yang berfungsi. Dan secara umum masuk akal untuk menunggu beberapa hari sebelum menerima.
Peter Taylor

Jawaban:

2

05AB1E, 20 byte

g-¹sã€{Ùvy¹«DO³Qiˆ}¯

Input adalah dalam urutan: list of values, nr of coins, sum to reach.

Penjelasan singkatnya

  1. Dapatkan semua permutasi dari daftar panjang koin: final length - length of unique coin list
  2. Tambahkan daftar koin unik ke daftar ini.
  3. Jika jumlahnya sama dengan jumlah yang dicari, simpan daftarnya
  4. Keluarkan semua daftar yang disimpan

Cobalah online

Kompiler online tidak dapat menangani sejumlah besar koin.

Emigna
sumber
4

MATL , 22 byte

Z^!S!Xu!tsi=Z)"1G@m?@!

Input order adalah: array denominasi, jumlah koin yang diambil ( n), jumlah yang diinginkan ( y).

Setiap kombinasi ditampilkan pada garis yang berbeda. Output kosong ditampilkan sebagai string kosong (jadi tidak ada).

Cobalah online!

Kode kehabisan memori dalam kompiler online untuk contoh dalam tantangan, tetapi bekerja offline dengan komputer standar yang cukup modern:

>> matl
 > Z^!S!Xu!tsi=Z)"1G@m?@!
 > 
> [1 2 3]
> 15
> 36
1 1 1 1 2 3 3 3 3 3 3 3 3 3 3
1 1 1 2 2 2 3 3 3 3 3 3 3 3 3
1 1 2 2 2 2 2 3 3 3 3 3 3 3 3
1 2 2 2 2 2 2 2 3 3 3 3 3 3 3

Penjelasan

Z^      % Implicitly input array of denomminations and number of coins n. Compute 
        % Cartesian power. This gives 2D array with each "combination"
        % on a different row
!S!     % Sort each row
Xu      % Deduplicate rows
!       % Transpose: rows become columns. Call this array A
ts      % Push a copy, compute sum of each column
i       % Input y (desired sum)
=       % Logical array that contains true if the "combination" has the desired sum
Z)      % Keep only those columns in array A
"       % For each column
  1G    %   Push array of denominations again
  @     %   Push current column
  m     %   Is each denomination present in the column?
  ?     %   If so
    @!  %     Push current column again. Transpose into a row
        %   End if
        % End for
        % Implicitly display stack contents
Luis Mendo
sumber
3

Python 3, 120 106 byte

from itertools import*
lambda d,t,l:[i+d for i in combinations_with_replacement(d,l-len(d))if sum(i+d)==t]

Fungsi anonim yang mengambil input dari tupel denominasi formulir (x_1, x_2, x_3 ... , x_k), nilai target, dan sejumlah koin melalui argumen, dan mengembalikan daftar tupel formulir [(solution_1), (solution_2), (solution_3), ... (solution_k)].

Bagaimana itu bekerja

Itertools's combinations_with_replacementfungsi digunakan untuk menghasilkan semua l-len(d)kombinasi, dengan penggantian, dari denominasi. Dengan menambahkan dke masing-masing kombinasi ini, dijamin bahwa setiap denominasi muncul setidaknya satu kali, dan bahwa kombinasi baru memiliki panjang l. Jika elemen-elemen dari kombinasi berjumlah t, kombinasi ditambahkan ke daftar kembali sebagai tupel.

Cobalah di Ideone


Metode alternatif untuk 108 byte

from itertools import*
lambda d,t,l:set(tuple(sorted(i+d))for i in product(d,repeat=l-len(d))if sum(i+d)==t)

Fungsi anonim yang mengambil input dari tupel denominasi formulir (x_1, x_2, x_3 ... , x_k), nilai target, dan sejumlah koin melalui argumen, dan mengembalikan satu set tupel formulir {(solution_1), (solution_2), (solution_3), ... (solution_k)}.

Bagaimana cara kerjanya (versi lain)

Ini menggunakan productfungsi dari itertoolsuntuk menghasilkan semua l-len(d)pengaturan denominasi. Dengan menambahkan dke masing-masing kombinasi ini, dijamin bahwa setiap denominasi muncul setidaknya satu kali, dan bahwa kombinasi baru memiliki panjang l. Jika elemen-elemen dari kombinasi berjumlah t, kombinasi diurutkan, dikonversi dari daftar ke tuple, dan ditambahkan ke tupel kembali. Akhirnya, panggilan setmenghapus duplikat apa pun.

Cobalah di Ideone (versi lain)

TheBikingViking
sumber
0

JavaScript (ES6), 135 byte

g=(a,n,y,r)=>n>0?y>0&&a.map((x,i)=>g(a.slice(i),n-1,y-x,[...r,x])):n|y||console.log(r)
(a,n,y)=>g(a,n-a.length,a.reduce((y,x)=>y-x,y),a)
Neil
sumber