Máximo disfrute del bolo

17

Te han dado una bolsa de bolos. Todo el mundo sabe que para apreciar más los diferentes sabores, debes rotar entre los sabores.

Lo esencial:

  1. Solo puedes comer 1 bolo a la vez
  2. El orden en que comas tus bolos debe ser periódico.
  3. Cada período no puede contener un sabor particular más de una vez.
  4. Tu bolso solo tiene muchos bolos. No puede comer más de un sabor particular de bolos de lo que aparece en su bolsa.
  5. Desea comer tantos bolos como pueda (puede que no siempre sea posible)

Ejemplos:

Digamos que comienzas con 3 bolos rojos, 2 azules y 3 verdes:

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)

De entrada y salida

  • Se le pasa una lista no vacía de enteros positivos para los recuentos de colores. (El ejemplo anterior sería [3,2,3]).
  • Debe devolver una lista que contenga un pedido válido y óptimo.
  • En lugar de usar colores, usará los índices de la lista de entrada. (El último ejemplo de salida anterior sería [2,0,1,2,0,1,2,0]).
  • Su salida puede estar indexada a 0 o indexada a 1. Mis ejemplos estarán indexados a 0

Casos de prueba

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

Este es un , ¡así que haga sus soluciones lo más cortas posible en su idioma favorito!

Nathan Merrill
fuente
1
Bien podría estar relacionado con esto
Jonathan Allan
2
@JonathanAllan y es por eso que necesito una computadora para garantizar mi disfrute de skittle :)
Nathan Merrill

Respuestas:

4

JavaScript (ES6), 177 175 bytes

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)

Formateado y comentado

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

Fórmula utilizada

A continuación se muestra una tabla que muestra cómo funciona la fórmula F(i, j) = minimum(value[j], value[i] + 1), aquí con i = 0y la entrada [ 5, 2, 2 ].

Esta fórmula se puede interpretar de la siguiente manera: para cada tipo de Skittle, no podemos seleccionar más que el número del tipo menos disponible más uno.

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

Casos de prueba

Arnauld
fuente
¿Las reducidas inicializaciones de la suma (0) y el mestar al final de los "bucles" son inducidas por el golf o es simplemente cómo es JS?
Jonathan Allan
@JonathanAllan Esa es la forma JS : el valor inicial de reduce () se encuentra después de la devolución de llamada. m=0Sin embargo, poner aquí es inducido por el golf, porque no me importa el valor inicial de este ciclo (se sobrescribirá de todos modos). Inicializar mallí es conveniente.
Arnauld
Ah, veo que es más como una llamada de función que un bucle (como la función de reducción de Python tiene un valor inicial opcional).
Jonathan Allan
@ JonathanAllan Sí, exactamente. [1,2,3].reduce((x, y) => x+y, 10)en JS estaría reduce(lambda x,y: x+y, [1,2,3], 10)en Python (creo), ambos resultando en 16.
Arnauld
2

Jalea , 22 bytes

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

Indexación basada en 1.

Pruébalo en línea!

¿Cómo?

Repite cada prefijo de los índices ordenados por valor que desciende una vez más de lo que sería posible con la bolsa de bolos dada, luego elimina el bollo final o bolos de cada uno de estos según sea necesario para que sean alcanzables, y devuelve el que tenga más bolos .

El número que debe eliminarse de una repetición periódica adicional es solo el número con el recuento mínimo en ese prefijo.

ỤṚ;\Ṛẋ"‘Ṣ$ḣ"Ç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
fuente
1

Python3, 174 172 167 bytes

Idea

Dado, por ejemplo, 3 bolos rojos, 2 azules y 3 verdes, uno puede organizarlos en una cuadrícula, ordenados por color y cantidad:

r g
r g b
r g b

Si uno intenta comer exactamente los bolos, al menos puede comer bolos i * c en total, donde c es el número de bolos en la columna r-ésima, por ejemplo, para i = 2 uno puede comer al menos 6 bolos.

r g
# # #
# # #

Lo único que queda por hacer es contar cuántos bolos adicionales se pueden comer por un período incompleto.

Golfed

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

Comentado

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

Pruébalo en línea!

Editar: se ha sustituido (i+1)con -~ipara guardar 2 bytes.

Editar: -5 bytes gracias a Dead Possum

Elvorfirilmathredia
fuente
Puedes cambiar sum(1for e in b if e[0]>c)a sum(c<e[0]for e in b). Convertirá True a 1 implícitamente y le ahorrará 5 bytes
Dead Possum