Bisakah nilai ini dibuat dengan koin dan / atau catatan unik?

29

Tulis program yang menghitung jika nilai moneter yang dimasukkan, sebagai bilangan bulat, dapat diwakili oleh kombinasi unik koin dan / atau catatan, yang berarti koin / catatan yang sama tidak dapat digunakan lebih dari satu kali.

Program Anda harus mengambil nilai sebagai input, dan dapat mengambil daftar nilai koin / catatan baik melalui input atau melalui bahasa yang setara dengan array. Daftar koin / catatan harus dapat diubah, jadi pastikan sudah jelas di mana ini didefinisikan jika Anda menggunakan konstanta.

Program Anda harus menampilkan nilai kebenaran / kepalsuan masing-masing.

Harap dicatat bahwa mengeluarkan daftar koin / catatan yang membentuk nilai tidak diperlukan.

CONTOH

Menggunakan pound Inggris, (£ 1,00 = 100 dan £ 420,69 = 42069)

coins = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000]

Berikut ini akan menampilkan true:

6 (1, 5)
15 (10, 5)
88 (1, 2, 5, 10, 20, 50)
512 (500, 10, 2)
7003 (5000, 2000, 2, 1)

Berikut ini akan menampilkan false:

4
209
8889
4242424242
[ANYTHING ABOVE 8888]

DATA UJI ALTERNATIF (Dolar AS)

coins = [1, 5, 10, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000]

Semoga berhasil!

Eddie Hart
sumber
4
Saya berharap kami memiliki lebih banyak pendatang baru seperti Anda ...
Leaky Nun
Terkait
Adnan
2
Anda harus menambahkan beberapa testcases menggunakan set koin yang berbeda
Leaky Nun
2
Saya sarankan menambahkan test case yang tidak dapat diselesaikan dengan heuristik rakus mengambil koin terbesar yang tidak terpakai yaitu paling banyak nilai yang tersisa. Akan lebih baik jika ada yang inputnya tidak diurutkan dan di mana suatu nilai dapat dibuat lebih dari satu arah. Biasanya baik untuk kasus uji untuk menghindari kemungkinan seseorang melakukan upaya yang masuk akal pada masalah yang bekerja untuk kasus uji tanpa benar dalam segala hal.
xnor
2
Terkait . Juga terkait . Pertanyaan sebelumnya adalah duplikat, tetapi pertanyaan ini IMO dirancang lebih baik dan jika kita ingin menutupnya sebagai duplikat, saya lebih suka menutup yang lebih tua.

Jawaban:

13

Brachylog 2 (TIO Nexus), 2 byte

⊇+

Cobalah online!

Mengambil daftar koin baik melalui input standar atau melalui menambahkannya ke awal program sebagai array literal (keduanya akan bekerja, jadi terserah Anda yang Anda rasa "lebih sah"; yang pertama diizinkan secara default Aturan PPCG, yang terakhir secara khusus diizinkan oleh pertanyaan); dan mengambil nilai untuk menghasilkan sebagai argumen baris perintah.

Penjelasan

Program ini memanfaatkan detail implementasi dari cara pembungkus TIO Nexus untuk fungsi Brachylog; khusus, ini memungkinkan Anda memberikan argumen baris perintah untuk memberikan input melalui Output. (Ini tidak dipertimbangkan dalam desain asli untuk Brachylog; namun, bahasa didefinisikan oleh implementasinya di PPCG, dan jika implementasi muncul yang terjadi untuk melakukan apa yang saya butuhkan, maka saya dapat mengambil keuntungan darinya.) Itu berarti Program terlihat seperti ini:

⊇+
⊇   Some subset of {standard input}
 +  sums to {the first command-line argument}

Sebagai program penuh, ia mengembalikan nilai boolean; true.jika semua asersi dalam program dapat secara bersamaan dipenuhi, atau false.jika tidak bisa.

(Pengingat, atau untuk orang yang belum tahu: Brachylog 2 menggunakan pengkodean karakter sendiri yang panjangnya satu byte.)


sumber
Anda mengatakan bahwa ⊇ adalah byte tunggal di Brachylog, mengapa Anda tidak menempelkan byte di sini? Saya yakin ada alasan untuk itu, saya hanya tertarik, sedikit karakter-encoding nub.
theonlygusti
1
Mereka dikodekan pada disk sebagai 08 2B(Anda dapat melihat pengkodean di sini ). Alasan saya tidak mencantumkan pengkodean spesifik adalah bahwa itu tidak relevan; yang paling penting adalah bahwa Brachylog menggunakan tidak lebih dari 256 karakter unik, sehingga masing-masing dapat direpresentasikan dalam satu byte tunggal. Ini biasanya dilakukan oleh bahasa golf untuk membuat kode lebih mudah dibaca; mereka bisa menggunakan pengkodean seperti kode halaman 437 sebagai gantinya, tetapi jika Anda melakukannya tidak ada yang bisa membacanya .
10

05AB1E , 4 byte

æOså

Penjelasan:

æ      Calculate the powerset of the first input
 O     Sum each element
  s    Put the second input at the top of the stack
   å   Check whether the input is in the powerset sum.

Cobalah online!

Okx
sumber
Sepertinya Anda telah secara resmi menyesatkan semua orang untuk memadatkan daftar; p
Leaky Nun
Setelah Anda menghapus daftar terkompresi dan memindahkannya ke input, saya akan menghapus jawaban saya (karena pada saat jawaban kami akan sama)
Leaky Nun
Komunitas ini penuh dengan para genius.
Tobi
5

Mathematica, 25 byte

!FreeQ[Tr/@Subsets@#,#2]&

Fungsi murni mengambil array nilai koin sebagai argumen pertama dan integer target sebagai argumen kedua, dan mengembalikan Trueatau False.

Greg Martin
sumber
4

Jelly, 6 byte

ŒPS€e@

Cobalah online!

-2 bytes berkat Leaky Nun
-13 bytes berkat Leaky Nun (cerita panjang)

HyperNeutrino
sumber
termasuk Anda
Leaky Nun
@ LeakyNun Heh, ada solusi yang lebih baik, bukan?
HyperNeutrino
@ Jonathan Allan Oh, wah. Terima kasih!
HyperNeutrino
Menambahkan tautan TIO;)
Okx
3

Retina , 52 31 byte

\d+
$*
^((1+) |1+ )+(?<-2>\2)+$

Cobalah online! Mengambil input sebagai daftar koin dan catatan yang dipisahkan ruang diikuti oleh nilai yang diinginkan. Sunting: Disimpan 18 byte berkat @Kobi yang mendebug kode saya. Penjelasan: Dua baris pertama cukup mengkonversi dari desimal ke unary. Baris ketiga kemudian menangkap daftar koin dan catatan. Pergantian ini memungkinkan engine untuk mundur dan memilih untuk tidak menangkap koin / catatan tertentu. Kelompok penyeimbang kemudian mencocokkan nilai dengan semua sufiks dari daftar tangkap (tidak perlu tetapi pegolf).

Neil
sumber
Opsi kedua tidak berfungsi karena mesin tidak mundur ke grup 0-panjang (optimasi yang mengganggu). Anda dapat menggunakan ^((1+) )+(\2?(?<-2>)|){99}$(34 byte, dengan batasan jumlah koin), atau ^((1+) |1+ )+(\2?(?<-2>))+$(juga 34 byte).
Kobi
1
@Kobi Cantik! Saya menyimpan 2 byte dari kedua jawaban karena saya lupa itu (?<-2>\2?)berfungsi, ditambah byte lebih lanjut dari jawaban kedua Anda karena ?tidak lagi diperlukan.
Neil
2

Brachylog , 7 byte

tT&h⊇+T

Cobalah online!

Bagaimana itu bekerja

tT&h⊇+T
tT      the second input is T
  &     and
   h    the first input
    ⊇   is a superset of a set
     +  that sums up to
      T T

Termasuk kombinasinya, 9 byte

tT&h⊇.+T∧

Cobalah online!

Biarawati Bocor
sumber
2

Java (OpenJDK 8) , 125 byte

boolean f(int[]c,int n){int l=c.length;if(l<1)return n==0;int[]a=java.util.Arrays.copyOf(c,l-1);return f(a,n-c[l-1])|f(a,n);}

Cobalah online!

Biarawati Bocor
sumber
Melakukan ini dalam lambda bisa membuatnya lebih pendek.
Okx
@ OKx Ini bersifat rekursif (jadi akan lebih lama), ditambah lagi saya tidak melakukan lambdas bahkan jika mereka akan lebih pendek.
Leaky Nun
1
Versi berulang algoritme Anda jauh lebih pendek saat Anda menghapus kebutuhan untuk menyalin larik: boolean f(int[]c,int n){for(int l=c.length;l-->0;n-=n<c[l]?0:c[l]);return n<1;}(79 byte). Dengan Java 8 dan lambda-nya, dapat dikurangi menjadi 62 byte. Mengenai jawaban Anda seperti saat ini, int l=c.length-1maka menggunakan lbukan l-1juga lebih pendek.
Olivier Grégoire
2

Prolog (SWI) , 46 byte

a([],0).
a([H|T],X):-Y is X-H,(a(T,Y);a(T,X)).

Cobalah online!

Garpu jawaban Python saya .

Biarawati Bocor
sumber
2
Anda mungkin dapat menyimpan 2 byte dengan menggunakan GNU Prolog sebagai gantinya (memungkinkan Anda mengeja issebagai #=, yang akan memungkinkan Anda menghapus beberapa spasi putih).
2

JavaScript (ES6), 81 69 67 64 byte

Mengambil daftar koin cdan jumlah target adalam sintaks currying (c)(a). Pengembalian 0atau true.

c=>g=(a,m=1)=>c.map((c,i)=>x-=c*(m>>i&1),x=a)&&!x||x-a&&g(a,m+1)

Uji kasus

Arnauld
sumber
Apakah Anda diizinkan mengambil daftar koin?
Leaky Nun
@LeakyNun "... dan dapat mengambil daftar nilai koin / catatan ..."
Martin Ender
1
Jadi saya menyandikan daftar itu dengan gratis ...
Leaky Nun
@ LeakyNun Sepertinya begitu
Eddie Hart
2

Haskell , 28 byte

Fungsi operator (#)mengambil bilangan bulat dan daftar bilangan bulat (atau, lebih umum, Traversablewadah angka apa saja) dan mengembalikan a Bool.

Gunakan sebagai 6#[1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000].

c#l=elem c$sum<$>mapM(:[0])l

Cobalah online!

Bagaimana itu bekerja

  • cadalah nilai yang diinginkan dan ldaftar nilai koin.
  • mapM(:[0])lmemetakan (:[0])lebih dari l, memasangkan setiap nilai dengan 0, dan kemudian membangun produk kartesius, memberikan daftar di mana setiap elemen baik nilai yang sesuai di dalam l, atau 0.
  • sum<$>jumlah setiap kombinasi, dan elem c$periksa apakah cada dalam daftar yang dihasilkan.
Ørjan Johansen
sumber
2

R, 88 83 byte

-5 byte terima kasih kepada @Jarko Dubbeldam

mengembalikan fungsi anonim. Ini menghasilkan semua kemungkinan kombinasi koin (menggunakan expand.gridpasangan T,F) dan memeriksa apakah nilainya ada. kadalah koin karena cmerupakan kata yang dilindungi undang-undang di R. Dapat memeriksa beberapa nilai sekaligus.

function(k,v)v%in%apply(expand.grid(Map(function(x)!0:1,k)),1,function(x)sum(k[x]))

Cobalah online!

Giuseppe
sumber
Anda dapat menggantinya c(T,F)dengan !0:1, dan rep(list(!0:1),length(k))olehlapply(k,function(x)!0:1)
JAD
1
Sebenarnya, buat ituMap(function(x)!0:1,k)
JAD
1

Japt , 7 byte

à mx èN

Cobalah online! Keluaran 0untuk falsy, bilangan bulat positif untuk kebenaran.

Penjelasan

à mx èN
          // Implicit: U = input array, V = input integer, N = array of all inputs
à         // Take all combinations of U.
  mx      // Map each combination to its sum.
     è    // Count the number of items in the result which also exist in
      N   //   the array of inputs.
          // This returns 0 if no combination sums to V, a positive integer otherwise.
          // Implicit: output result of last expression
Produksi ETH
sumber
1

Ruby , 39 byte

Mengembalikan nilsebagai nilai falsy, dan nilai koin terkecil dalam daftar yang menjadikan angka sebagai benar (semua angka benar di Ruby).

f=->c,n{n!=0?c.find{|i|f[c-[i],n-i]}:1}

Berhati-hatilah, bagaimanapun, bahwa algoritma ini sangat lambat, dengan O(C!)kompleksitas waktu, di mana Cpanjang daftar koin. Ini akhirnya selesai, tetapi sebagian besar kasus uji akan time out pada sebagian besar penerjemah online f(UK_POUND, 5).

Ini adalah versi 41-byte yang selesai jauh lebih cepat dengan menambahkan kondisi akhir tambahan, dan jauh lebih sulit untuk benar-benar kehabisan waktu

f=->c,n{n>0?c.find{|i|f[c-[i],n-i]}:n==0}

Cobalah online!

Nilai Tinta
sumber
1

Utilitas Bash + GNU, 56 39

printf %$2s|egrep "^ {${1//,/\}? {}}?$"

Daftar denominasi input (tidak disortir) diberikan sebagai daftar yang dipisahkan koma. Daftar input dan nilai diberikan sebagai parameter baris perintah.

Output yang diberikan dalam bentuk kode pengembalian shell. Periksa dengan echo $?setelah menjalankan skrip. 0berarti jujur, 1berarti palsu.

Cobalah online .

  • printf %$2smenghasilkan serangkaian valuespasi
  • "^ {${1//,/\}? {}}?$"adalah ekspansi shell yang memperluas daftar denominasi ke seperti regex ^ {1}? {2}? {5}? {10}? ... $. Ternyata egrepmesin regex cukup pintar untuk mencocokkan dengan benar, terlepas dari apa urutan denominasi
  • egrep memeriksa apakah string spasi cocok dengan regex
Trauma Digital
sumber
1

C, 66 byte

m;v;f(n){for(m=1e5;m/=10;)for(v=5;n-=n<v*m?0:v*m,v/=2;);return!n;}

Lihat berhasil di sini .

C, 53 byte

g(c,w,n)int*c;{for(;n-=n<c[--w]?0:c[w],w;);return!n;}

Varian ini menggunakan larik koin, yang mengalahkan tujuan dari masalah ini, karena turun ke pengurangan sederhana.

Argumen pertama adalah susunan koin, yang kedua adalah jumlah koin, dan yang ketiga adalah nilainya.

C, 48 byte

g(c,n)int*c;{for(;n-=n<*c?0:*c,*++c;);return!n;}

Alternatif untuk varian sebelumnya. Diasumsikan bahwa susunan koin dapat dibalik dan nol diakhiri.

2501
sumber
0

CJam , 18 17 byte

q~_,2\m*\f.*::+#)

Cobalah online!

Penjelasan

q~                  e# Read and eval input.
  _,                e# Duplicate the money list and take its length.
    2\m*            e# Take the (length)th Cartesian power of [0 1].
        \f.*        e# Element-wise multiplication of each set of 0's and 1's with the money
                    e#   list. This is essentially the powerset, but with 0s instead of 
                    e#   missing elements.
            ::+     e# Sum each set.
               #    e# Find the index of the desired amount in the list. (-1 if not found)
                )   e# Increment. -1 => 0 (falsy), anything else => nonzero (truthy)
Kucing Bisnis
sumber
0

C (gcc) , 91 byte

i,j,c[]={1,2,5};f(n){for(i=1000;i;i/=10)for(j=2;j>=0;j--)n-=n<i*c[j]?0:i*c[j];return n==0;}

Cobalah online!

Cleblanc
sumber
0

PHP, 70 Bytes

mencetak 1 untuk true dan nothing for false

<?foreach($_GET[1]as$v)$i-=$v*$r[]=($i=&$_GET[0])/$v^0;echo max($r)<2;

Cobalah online!

Jörg Hülsermann
sumber
0

Oktaf, 39 byte

 @(L,n)any(cellfun(@sum,powerset(L))==n)

Fungsi anonim yang mengambil array nilai koin sebagai argumen pertama dan integer target sebagai argumen kedua, dan mengembalikan benar atau salah.

Cobalah online!

rahnema1
sumber
0

Mathematica, 42 byte

ListQ@NumberDecompose[#,Sort[#2,Greater]]&

memasukkan

[15, {10,5}]

J42161217
sumber