Maksymalna przyjemność gry w kręgle

17

Otrzymałeś torbę Kręgli. Wszyscy wiedzą, że aby najbardziej docenić różne smaki, musisz przełączać się między nimi.

Podstawy:

  1. Jednorazowo możesz zjeść tylko 1 kręgle
  2. Kolejność spożywania kręgli musi być okresowa.
  3. Każdy okres nie może zawierać określonego smaku więcej niż jeden raz.
  4. Twoja torba ma tylko tyle kręgli. Nie możesz jeść bardziej określonego smaku kręgu niż pojawia się w twojej torbie.
  5. Chcesz zjeść jak najwięcej kręgli (może nie zawsze być to możliwe)

Przykłady:

Załóżmy, że zaczynasz od 3 czerwonych, 2 niebieskich i 3 zielonych kręgli:

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)

Wejście wyjście

  • Przekazano niepustą listę dodatnich liczb całkowitych dla zliczeń kolorów. (Powyższy przykład to [3,2,3]).
  • Musisz zwrócić listę zawierającą prawidłowe i optymalne zamówienie.
  • Zamiast używać kolorów, użyjesz indeksów z listy danych wejściowych. (Ostatni przykładowy wynik powyżej to [2,0,1,2,0,1,2,0]).
  • Twoje dane wyjściowe mogą być indeksowane 0 lub indeksowane 1. Moje przykłady będą indeksowane 0

Przypadki testowe

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

To jest gra w , więc , aby Twoje rozwiązania były jak najkrótsze w swoim ulubionym języku!

Nathan Merrill
źródło
1
Również może być z tym
Jonathan Allan,
2
@JonathanAllan i dlatego potrzebuję komputera, aby zapewnić sobie przyjemność z gry w kręgle :)
Nathan Merrill

Odpowiedzi:

4

JavaScript (ES6), 177 175 bajtów

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)

Sformatowane i skomentowane

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()

Zastosowana formuła

Poniżej znajduje się tabela pokazująca działanie formuły F(i, j) = minimum(value[j], value[i] + 1), tutaj wraz z i = 0danymi wejściowymi [ 5, 2, 2 ].

Ta formuła może być interpretowana w następujący sposób: dla każdego typu Skittle możemy wybrać nie więcej niż liczbę najmniej dostępnego typu plus jeden.

 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 | /

Przypadki testowe

Arnauld
źródło
Czy zmniejszenie inicjalizacji sumy (0) i mznajdowanie się na końcu „pętli” jest związane z golfem, czy jest to po prostu JS?
Jonathan Allan,
@JonathanAllan To jest sposób JS : początkowa wartość parametru redukcja () znajduje się po wywołaniu zwrotnym. Umieszczenie m=0tutaj jest jednak związane z golfem, ponieważ nie dbam o początkową wartość tej pętli (i tak zostanie ona nadpisana). Inicjowanie mjest wygodne.
Arnauld
Ach, widzę, że bardziej przypomina wywołanie funkcji niż pętlę (jak funkcja redukcji Pythona ma opcjonalną wartość początkową).
Jonathan Allan,
@JonathanAllan Tak, dokładnie. [1,2,3].reduce((x, y) => x+y, 10)w JS będzie reduce(lambda x,y: x+y, [1,2,3], 10)w Pythonie (myślę), oba skutkują 16.
Arnauld,
2

Galaretka , 22 bajty

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

Indeksowanie 1.

Wypróbuj online!

W jaki sposób?

Powtarza każdy prefiks indeksów posortowanych według wartości malejącej jeszcze raz, niż byłoby to możliwe przy danej torbie kręgli, a następnie usuwa końcowy kręgle lub kręgle z każdego z nich, aby były możliwe do osiągnięcia, i zwraca ten z największą liczbą kręgli .

Liczba, którą należy usunąć z jednego dodatkowego okresowego powtórzenia, to tylko liczba z minimalną liczbą w całym tym prefiksie.

ỤṚ;\Ṛẋ"‘Ṣ$ḣ"Ç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
źródło
1

Python3, 174 172 167 bajtów

Pomysł

Biorąc pod uwagę np. 3 czerwone, 2 niebieskie i 3 zielone kręgle, można je ułożyć w siatkę, posortowaną według koloru i ilości:

r g
r g b
r g b

Jeśli ktoś spróbuje dokładnie zjeść kręgle i, może co najmniej zjeść łącznie kręgle i * c, gdzie c jest liczbą kręgli w kolumnie r, np. Dla i = 2 można zjeść przynajmniej 6 kręgli.

r g
# # #
# # #

Pozostaje tylko policzyć, ile dodatkowych kręgli można zjeść w niepełnym okresie.

Grał w golfa

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)]

Skomentował

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)]

Wypróbuj online!

Edit: Wymieniłem (i+1)z -~izaoszczędzić 2 bajty.

Edycja: -5 bajtów dzięki Dead Possum

Elvorfirilmathredia
źródło
Możesz zmienić sum(1for e in b if e[0]>c)na sum(c<e[0]for e in b). Konwertuje Prawdę na 1 domyślnie i oszczędza 5 bajtów
Dead Possum