Kenikmatan Skittle Maksimal

17

Anda telah diberi sekantong Skittles. Semua orang tahu bahwa untuk paling menghargai rasa yang berbeda, Anda perlu memutar di antara rasa.

Dasar-dasar:

  1. Anda hanya bisa makan 1 skittle pada satu waktu
  2. Urutan yang Anda makan skittle Anda harus berkala.
  3. Setiap periode tidak dapat mengandung rasa tertentu lebih dari sekali.
  4. Tas Anda hanya memiliki begitu banyak skittles. Anda tidak bisa makan lebih banyak rasa skittle tertentu daripada yang terlihat di tas Anda.
  5. Anda ingin makan skittles sebanyak yang Anda bisa (itu tidak selalu mungkin)

Contoh:

Katakanlah Anda mulai dengan 3 skittle Merah, 2 Biru, dan 3 Hijau:

R B G R B G R G       Invalid:  The last R must be followed by a B, not a G
R B G R B G R         Valid, but sub-optimal
R R R                 Valid, but sub-optimal
R G B R G B R G       Valid and optimal
G R B G R B G R       Also valid and optimal (there are multiple good solutions)

Input output

  • Anda diberikan daftar bilangan bulat positif yang tidak kosong untuk jumlah warna. (Contoh di atas adalah [3,2,3]).
  • Anda harus mengembalikan daftar berisi pemesanan yang valid dan optimal.
  • Alih-alih menggunakan warna, Anda akan menggunakan indeks dari daftar input. (Contoh keluaran terakhir di atas adalah [2,0,1,2,0,1,2,0]).
  • Output Anda mungkin 0-diindeks atau 1-diindeks. Contoh saya akan diindeks 0

Uji Kasus

1                          0
4                          0 0 0 0
4 1                        0 0 0 0
3 1                        0 1 0                   or  0 0 0
5 2 2                      0 1 2 0 1 2 0
2 3 5                      2 1 0 2 1 0 2 1         or  1 2 0 1 2 0 1 2
2 4 5                      2 1 2 1 2 1 2 1 2
3 4 5                      2 1 0 2 1 0 2 1 0 2 1   or  1 2 0 1 2 0 1 2 0 1 2
1 1 1 1 1 6                5 0 1 2 3 4 5           (lots of other solutions)
1 1 1 1 1 8                5 5 5 5 5 5 5 5
2 4 6 8                    3 2 1 3 2 1 3 2 1 3 2 1 3 2

Ini adalah , jadi buat solusi Anda sesingkat mungkin dalam bahasa favorit Anda!

Nathan Merrill
sumber
1
Semoga dikaitkan dengan ini
Jonathan Allan
2
@Jonathan Allan dan itulah sebabnya saya membutuhkan komputer untuk memastikan kesenangan saya :)
Nathan Merrill

Jawaban:

4

JavaScript (ES6), 177 175 byte

a=>a.map((n,i)=>[n,l=i]).sort((a,b)=>a[0]-b[0]).reduce((P,x,i,a)=>(v=a.reduce((p,c,j)=>j<i?p:p+Math.min(c[0],x[0]+1),0))>m?[...Array(m=v)].map((_,k)=>a[l-k%(l+1-i)][1]):P,m=0)

Diformat dan dikomentari

a => a                              // given an array a:
.map((n, i) => [n, l = i])          // map it to [value, index] arrays / set l = length - 1
.sort((a, b) => a[0] - b[0])        // sort it by values in ascending order
.reduce((P, x, i, a) =>             // for each reference entry x at position i:
  (v = a.reduce((p, c, j) =>        //   for each entry c at position j:
    j < i ?                         //     if c is before x:
      p                             //       keep the previous sum (which is 0)
    :                               //     else:
      p + Math.min(c[0], x[0] + 1), //       add minimum(value[j], value[i] + 1)
    0                               //   initialize the sum at 0
  )) > m ?                          //   if the new sum v is better than our current best m:
    [...Array(m = v)].map((_, k) => //     update m to v and update the result to an array
      a[l - k % (l + 1 - i)][1]     //     of length m filled with indices picked repeatedly
    )                               //     between i and l
  :                                 //   else:
    P,                              //     keep the previous result
  m = 0                             // start with best score m = 0
)                                   // the final result is returned by the outer reduce()

Formula yang digunakan

Di bawah ini adalah tabel yang menunjukkan bagaimana rumus F(i, j) = minimum(value[j], value[i] + 1)bekerja, di sini dengan i = 0dan inputnya [ 5, 2, 2 ].

Rumus ini dapat diartikan sebagai berikut: untuk setiap jenis Skittle, kami dapat memilih tidak lebih dari jumlah jenis yang paling sedikit tersedia ditambah satu.

 j | Sorted    | value[j] | F(0, j) | Selected        | Output
   | input     |          |         | Skittles        | (starting from bottom left)
---+-----------+----------+---------+-----------------+-----------------------------
 0 | 2 2       |     2    |    2    | [2] [2]         | \
 1 | 1 1       |     2    |    2    | [1] [1]         |  > 0 1 2 0 1 2 0
 2 | 0 0 0 0 0 |     5    |    3    | [0] [0] [0] 0 0 | /

Uji kasus

Arnauld
sumber
Apakah pengurangan inisialisasi jumlah (0) dan mberada di akhir "loop" yang diinduksi golf atau hanya seberapa JS?
Jonathan Allan
@ JonathanAllan Itulah cara JS : nilai awal dari pengurangan () terletak setelah panggilan balik. Menempatkan di m=0sini adalah golf-induced, karena saya tidak peduli tentang nilai awal dari loop ini (itu akan ditimpa pula). Inisialisasi mada yang mudah.
Arnauld
Ah saya melihat itu lebih seperti pemanggilan fungsi daripada loop (seperti fungsi pengurangan Python memiliki nilai awal opsional).
Jonathan Allan
@ Jonathan Allan Ya, tepatnya. [1,2,3].reduce((x, y) => x+y, 10)di JS akan berada reduce(lambda x,y: x+y, [1,2,3], 10)di Python (saya pikir), keduanya menghasilkan 16.
Arnauld
2

Jelly , 22 byte

ċЀṢN
ỤṚ;\Ṛẋ"‘Ṣ$ḣ"ÇLÞṪ

Pengindeksan berbasis 1.

Cobalah online!

Bagaimana?

Ulangi setiap awalan indeks yang diurutkan berdasarkan nilai menurun sekali lagi daripada yang dapat dicapai dengan kantung skittle yang diberikan, kemudian hapus skittle atau skittle terakhir dari masing-masing yang diperlukan untuk membuatnya dapat dicapai, dan kembalikan yang dengan skittles paling banyak .

Angka yang harus dihapus dari satu pengulangan periodik tambahan hanyalah angka dengan jumlah minimum di awalan itu.

ỤṚ;\Ṛẋ"‘Ṣ$ḣ"ÇLÞṪ - Main link                   e.g. [6,4,2,8]
Ụ                - grade up: sort indices by value  [3,2,1,4]
 Ṛ               - reverse                          [4,1,2,3]
   \             - cumulative reduce with
  ;              -     concatenation (get prefixes) [[4],[4,1],[4,1,2],[4,1,2,3]]
    Ṛ            - reverse                          [[4,1,2,3],[4,1,2],[4,1],[4]]
         $       - last two links as a monad
       ‘         -     increment                    [7,5,3,9]
        Ṣ        -     sort                         [3,5,7,9]
      "          - zip with
     ẋ           -     list repetition              [[4,1,2,3,4,1,2,3,4,1,2,3],[4,1,2,4,1,2,4,1,2,4,1,2,4,1,2],[4,1,4,1,4,1,4,1,4,1,4,1,4,1],[4,4,4,4,4,4,4,4,4]]
            Ç    - call last link (1) as a monad    [-1,-1,-1,-1]
          "      - zip with
           ḣ     - head list to (remove excess)     [[4,1,2,3,4,1,2,3,4,1,2],[4,1,2,4,1,2,4,1,2,4,1,2,4,1],[4,1,4,1,4,1,4,1,4,1,4,1,4],[4,4,4,4,4,4,4,4]]
              Þ  - sort by
             L   -     length                       [[4,4,4,4,4,4,4,4],[4,1,2,3,4,1,2,3,4,1,2],[4,1,4,1,4,1,4,1,4,1,4,1,4],[4,1,2,4,1,2,4,1,2,4,1,2,4,1]]
               Ṫ - tail                             [4,1,2,4,1,2,4,1,2,4,1,2,4,1]

ċЀṢN - Link 1: head amounts (negative of skittle excess of each N+1 repeated period)
   Ṣ  - sort                                        [2,4,6,8]
 Ѐ   - for each mapped over right argument
ċ     - count                                       [1,1,1,1]
    N - negate                                      [-1,-1,-1,-1]
Jonathan Allan
sumber
1

Python3, 174 172 167 Bytes

Ide

Diberikan misalnya 3 Merah, 2 Biru, dan 3 skittles Hijau yang bisa diatur dalam kotak, diurutkan berdasarkan warna dan jumlah:

r g
r g b
r g b

Jika seseorang mencoba untuk makan skittles secara tepat, setidaknya dia bisa makan skittle i * c, di mana c adalah jumlah skittle di kolom ke-r, misalnya untuk i = 2 orang setidaknya bisa makan 6 skittle.

r g
# # #
# # #

Satu-satunya hal yang harus dilakukan adalah menghitung berapa banyak skittles tambahan yang bisa dimakan dalam periode yang tidak lengkap.

Golf

def f(a):
 r=range;f=m=0;s=r(len(a));b=sorted(zip(a,s))[::-1]
 for i in s:
  c=b[i][0];n=-~i*c+sum(c<e[0]for e in b)
  if n>m:f,m=i+1,n
 return[b[j%f][1]for j in r(m)]

Berkomentar

def f(a):
    r = range;
    f = m = 0;                          - Some variables we need later on
    s = r(len(a));                      - Integers from 0 to (num_skittles - 1)
    b = sorted(zip(a,s))[::-1]          - Zip with s to remember initial order,
                                          then sort and reverse
    for i in s:
        c = b[i][0]
        n = (i+1)*c                     - If we attempt to eat i different skittles,
                                          we can surely eat (i+1)*c skittles.
          + sum(1 for e in b if e[0]>c) - The additional sum corresponds to an incomplete period.
        if n>m:                         - If a better way of eating skittles is found:
            f,m = i+1,n                 - update variables
    return [b[j%f][1] for j in r(m)]

Cobalah online!

Sunting: Diganti (i+1)dengan -~iuntuk menyimpan 2 byte.

Sunting: -5 bytes berkat Dead Possum

Elvorfirilmathredia
sumber
Anda bisa berubah sum(1for e in b if e[0]>c)menjadi sum(c<e[0]for e in b). Ini akan mengkonversi True ke 1 secara implisit dan menghemat 5 byte
Dead Possum