Delapan koin untuk raja yang adil


22

Ini adalah "rekanan" dari teka-teki lain, Delapan koin untuk raja yang adil di Puzzling.SE.

Anda dapat membaca puzzle di atas sebagai latar belakang. Rincian tentang teka-teki ini adalah sebagai berikut.

Seperangkat 8 jenis koin dengan nilai berbeda dibuat, raja ingin Anda mengetahui N maksimum sehingga sejumlah harga dari 0 hingga N dapat dibayarkan dengan kombinasi tidak lebih dari 8 koin dan tanpa biaya.

Misalnya, (diambil dari jawaban Glorfindel). Jika satu set koin nilai 1, 2, 5, 13, 34, 89, 233, 610 diberikan, program Anda harus menghasilkan 1596, karena setiap angka antara 0 dan 1596 (inklusif) dapat diwakili dengan jumlah tidak lebih dari 8 angka dari daftar yang diberikan (angka dapat diulang), sementara 1597 tidak dapat direpresentasikan dengan cara itu.

Secara matematis, jika input adalah himpunan S yang terdiri dari 8 bilangan bulat positif, output N yang diinginkan memuaskan bahwa untuk setiap bilangan n antara 0 dan N, terdapat x1, x2, x3, ..., x8 sedemikian rupa sehingga

x1+x2+...+x8=ndanx1,x2,...,x8{0}S

Tujuan Anda adalah menulis program, fungsi, atau cuplikan yang menggunakan 8 angka sebagai input, dan menghasilkan maksimum N seperti dijelaskan di atas.

Aturan:

  • I / O fleksibel diizinkan, sehingga program Anda dapat mengambil input dalam bentuk apa pun yang paling cocok. Anda dapat berasumsi bahwa angka-angka input diurutkan dengan cara yang paling sesuai dengan program Anda.
    • Harap sebutkan dalam jawaban Anda jika program Anda bergantung pada urutan input
  • Input adalah satu set 8 bilangan bulat positif yang berbeda (tanpa nol). Outputnya adalah satu bilangan bulat non-negatif.
    • Dalam hal tidak ada 1 dalam set input, program Anda harus menampilkan 0 karena angka dari 0 hingga 0 memenuhi persyaratan.
    • Dalam hal input tidak valid (set berisi angka nol, negatif atau duplikat), program Anda dapat melakukan apa saja.
  • Celah standar dilarang.
  • Program Anda akan berjalan dalam beberapa menit di komputer modern.

Kasus uji (sebagian besar diambil dari jawaban di bawah pertanyaan terkait tentang membingungkan):

[1, 2, 3, 4, 5, 6, 7, 8] => 64
[2, 3, 4, 5, 6, 7, 8, 9] => 0
[1, 3, 4, 5, 6, 7, 8, 9] => 72
[1, 2, 5, 13, 34, 89, 233, 610] => 1596
[1, 5, 16, 51, 130, 332, 471, 1082] => 2721
[1, 6, 20, 75, 175, 474, 756, 785] => 3356

Ini adalah , jadi program atau cuplikan terpendek di setiap bahasa menang!


1
Teka-teki yang bagus, tetapi saya pribadi berpikir bahwa beberapa kasus uji lagi akan membantu untuk menguji kiriman kami.
Tn. Xcoder

Bukankah lebih baik menjadikan ukuran input sebagai parameter? Pendekatan brute force akan berjuang dengan 8
Luis Mendo

1
@ iBug Maka aturan yang biasa adalah sesuatu seperti "pengiriman harus berjalan dalam satu menit di komputer modern". Ini kabur, tetapi biasanya cukup baik, karena perbedaan antara brute force dan pendekatan efisien sangat besar
Luis Mendo

1
Brute force masih dimungkinkan dengan batas waktu Anda "beberapa menit". Versi jawaban saya yang sedikit dimodifikasi menjalankan test case terakhir dalam 1m20s pada laptop saya yang berusia 7 tahun.
nimi

1
@Arnauld Dijelaskan
iBug

Jawaban:



9

Jelly , 12 byte

œċⱮ8Ẏ§ṢQJƑƤS

Cobalah online!

Diperlukan waktu rata-rata ~ 3,7 detik untuk menjalankan semua kasus uji pada TIO di ponsel saya, sehingga sangat cepat.

Penjelasan

œċⱮ8Ẏ§ṢQJƑƤS     Monadic link / Full program.
  Ɱ8             Promote 8 to [1 ... 8] and for each value k:
œċ                    Generate all combinations of k elements from the list.
    Ẏ§           Tighten, then sum. Flatten to a 2D list then sum each.
      ṢQ         Sort the result and remove equal entries.
        JƑƤ      For each prefix of this list, return 1 if it is equal to its length range, 0 otherwise.
           S     Finally, sum the result (counts the 1's which is equivalent to what is being asked).

7

Haskell, 56 50 byte

g c=[x|x<-[1..],all((/=x).sum)$mapM(0:)$c<$c]!!0-1

Cobalah online!

Pendekatan brute force. Tambahkan 0ke daftar koin dan coba semua kombinasi 8 pilihan. Temukan nomor pertama nyang tidak sama dengan jumlah dari setiap pengambilan dan pengembalian n-1.

Memakan waktu sekitar 5m30 untuk [1, 2, 5, 13, 34, 89, 233, 610]perangkat keras laptop saya yang berusia 7 tahun.

Edit: -6 byte terima kasih kepada @ Ørjan Johansen

Versi yang lebih pendek (-2 byte, sekali lagi terima kasih kepada @ Ørjan Johansen)

Haskell, 48 byte

g c=[x|x<-[1..],all((/=x).sum)$mapM(:0:c)c]!!0-1

tetapi secara signifikan menggunakan lebih banyak memori dan menjalankan paging yang berat pada mesin saya dan tidak selesai "dalam beberapa menit".


1
Anda bisa menggunakannya mapM(0:)$c<$c. (Sebenarnya mapM(:0:c)cseharusnya bekerja, tetapi time out pada TIO untuk test case yang diberikan.)
Ørjan Johansen

4

Jelly , 9 byte

Żœċ8§ḟ’$Ṃ

Cobalah online!

Bagaimana itu bekerja

Żœċ8§ḟ’$Ṃ  Main link. Argument: A (array)

Ż          Prepend a 0 to A.
 œċ8       Take all combinations of length 8, with repetitions.
    §      Take the sum of each combination.
       $   Combine the two links to the left into a monadic chain.
      ’      Decrement all sums.
     ḟ       Filterfalse; keep only sums that do not appear in the decremented sums.
        Ṃ  Take the minimum.

2
Żṗ8§ḟ’$Ṃmenghemat satu byte, tetapi saya tidak yakin apakah 8,5 menit dihitung sebagai beberapa .
Dennis


4

JavaScript (ES6),  100 88 80  76 byte

Ini pada dasarnya adalah pencarian kasar, tetapi ditingkatkan dengan pemangkasan untuk mempercepatnya. Waktu eksekusi rata-rata untuk kasus uji hampir 1 detik pada TIO.

Mengasumsikan bahwa array input diurutkan dari tertinggi ke terendah.

a=>[...Array(a[0]*9)].findIndex(g=(i=8,s)=>s*i>0?a.every(x=>g(i-1,s-x)):s)-1

Cobalah online!

Berkomentar

a =>                      // a[] = input array
  [...Array(a[0] * 9)]    // create an array of 9 * max(a) entries
  .findIndex(             // find the position of the first truthy result
    g = (i = 8, s) =>     // g = recursive function taking a counter i, initialized to 8
                          //     and a sum s, initialized to the position in the above array
      s * i > 0 ?         //   if s is positive and i is not equal to 0:
        a.every(x =>      //     for each value x in a[]:
          g(i - 1, s - x) //       do a recursive call with i - 1 and s - x
        )                 //     end of every()
      :                   //   else:
        s                 //     yield s (s = 0 means success and makes findIndex go on)
  ) - 1                   // end of findIndex(); decrement the result


3

Pari / GP , 57 byte

a->n=-1;while(polcoeff((1+sum(i=1,8,x^a[i]))^8,n++),);n-1

Cobalah online!


Apakah ini menggunakan fungsi menghasilkan?
don cerah

1
@donbright Ya.
alephalpha

1
itu luar biasa .. salah satu dari beberapa jawaban tidak memaksa solusi. banyak bahasa mungkin tidak dibangun di fitur simbolik polinomial. Pari GP itu keren.
don cerah

2

Python 2 , 125 115 111 byte

lambda c:sum(i==j for i,j in enumerate(sorted(set(map(sum,product([0]+c,repeat=8))))))-1
from itertools import*

Cobalah online!

Mengharapkan daftar bilangan bulat sebagai input.

Penjelasan:

# an anonymous function
lambda c:
                                                          # get all length-8 combinations of values, from (0,0,0,0,0,0,0,0) to (8,8,8,8,8,8,8,8)
                                                          # zero is added to ensure that combinations of fewer than 8 coins are represented Ex:(1,0,0,0,0,0,0,0)
                                                          product([0]+c,repeat=8)
                                                  # for each combination, sum the values
                                                  map(sum,.......................)
                                       # get unique values, then sort them smallest to largest
                                       sorted(set(................................))
             # for each index, value pair, return if the index is equal to the value
             i==j for i,j in enumerate(.............................................)
         # in Python arithmetic, False is 0 and True is 1. So, count how many items match their index.
         # Since zero was added to the list, there will always be one extra match (0==0). So offset by one.
         sum(........................................................................)-1
from itertools import*

2

Perl6, 65 63 41 byte ( 39 37 karakter)

{@_=(0,|@_)X+(0,|@_)for ^3;($_ if $_==$++for @_.sort.unique)-1}

Cobalah online!

Ini adalah blok anonim yang melewati data sebagai array. Ini (0,|@_)adalah cara cepat untuk menambahkan 0ke @_, dan meskipun itu dilakukan dua kali, itu masih sedikit lebih pendek daripada @_.push: 0;yang kemudian membutuhkan ruang setelah _. Ini adalah pendekatan brute force yang sedikit menonjolkan fakta bahwa itu adalah 8 kombinasi. Setelah menambahkan silang, daftar anonim dibuat untuk nilai berurutan. Dengan operator matematika, daftar mengevaluasi panjangnya, sehingga -1 menarik tugas ganda: menghitung 0 dan memaksa ke Int.

Ini dapat mengambil waktu manis, tapi dengan mengubah salah satu atau kedua (0,|@_)untuk (0,|@_.unique)sebelum pertama foritu dapat dipercepat jauh. Itu menambah +7 (runtime <60s) atau +14 (runtime <10s) ke skor jika Anda merasa yang pertama terlalu lambat (saya melakukan ini untuk kode tertaut untuk menghindari waktu habis setelah 60 detik).

Sunting: Bergabung dalam komentar meningkatkannya (ide yang sama, menambahkan silang, lalu mengembalikan hasil berturut-turut terakhir) ke 39 karakter yang menakjubkan (41 byte):

{(@_=@_ X+0,|@_)xx 3;first *+1@_,^∞}

Cobalah online!

Tabulasi terakhir tidak membutuhkan 0, menyimpan beberapa byte dengan hanya perlu menambahkan 0 sekaligus. The xx 3meniru untuk loop (masih keju pada koin menjadi kekuatan 2). The firstsub mengembalikan nomor pertama dalam daftar tak terbatas 0..*( ^Infmungkin juga, tapi tidak menghemat ruang) yang +1bukan anggota dari daftar ditambahkan lintas. Seperti milik saya, ini lambat, jadi tambahkan +7 untuk uniquesetelah yang pertama sama dengan jika Anda merasa itu terlalu lambat untuk pedoman.


1
48 byte . Secara teknis, uniqueini tidak diperlukan, tetapi mempercepatnya
Jo King

@ Bersenang-senang, saya tidak tahu mengapa saya tidak berpikir untuk menggunakan xx. Saya tahu harus ada cara untuk melakukan tabulasi akhir dengan cara yang jauh lebih pendek menggunakan fungsi yang ditetapkan, tetapi otak saya tidak berfungsi.
user0721090601

The xx 1harusxx 3
Jo Raja

@ Bersenang-senang diperbaiki. Saya juga menyadari dua karakter (tetapi tanpa byte) dapat disimpan dengan menggunakan^∞
user0721090601

Sebenarnya, Anda dapat menyimpan beberapa byte dengan (1...*∉@_)-1daripada menggunakan first, (yang saya sadari adalah metode yang sama yang saya gunakan di sini )
Jo King

1

JavaScript (Node.js) , 171 145 115 byte

f=(s,n=3)=>n?f(s=new Set(a=[0,...s]),n-1,a.map(m=>a.map(n=>s.add(m+n)))):Math.min(...[...s].filter(m=>!s.has(m+1)))

Cobalah online! Port of @ Mark's Python 3 menjawab. 108 byte di Firefox 30-57:

f=(s,n=3)=>n?f(new Set((for(n of s=[0,...s])for(m of s)n+m)),n-1):Math.min(...[...s].filter(m=>!s.has(m+1)))

1

Bahasa Wolfram (Mathematica) , 46 byte

0//.x_/;Min[Tr/@FrobeniusSolve[#,x+1]]<9:>x+1&

Cobalah online!

Pendekatan brute force: memeriksa bilangan bulat yang menghitung ke atas hingga mencapai nilai yang tidak dapat dibayar dalam 8 koin. Sangat, sangat lambat (tio times out), tapi saya cukup yakin kondisinya benar.


0

Bersih , 161 byte

import StdEnv,Data.List
$l=:[1:_]#k=sort(nub(map sum(iter 8(concatMap(\[h:t]=[[e,h:t]\\e<-[0:l]|e>=h]))[[0]])))
=length(takeWhile((>=)1)(zipWith(-)(tl k)k))
$_=0

Cobalah online!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.