Gozo máximo de Skittle


17

Você recebeu uma sacola de Skittles. Todo mundo sabe que, para apreciar mais os diferentes sabores, é preciso alternar entre os sabores.

Fundamentos:

  1. Você só pode comer 1 pino de cada vez
  2. A ordem em que você come seus skittles deve ser periódica.
  3. Cada período não pode conter um sabor específico mais de uma vez.
  4. Sua mala possui apenas tantos skittles. Você não pode comer mais de um sabor específico de skittle do que aparece na sua bolsa.
  5. Você quer comer tantos skittles quanto possível (nem sempre é possível)

Exemplos:

Digamos que você comece com 3 skittles vermelhos, 2 azuis e 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)

Entrada / Saída

  • Você recebe uma lista não vazia de números inteiros positivos para as contagens de cores. (O exemplo acima seria [3,2,3]).
  • Você precisa retornar uma lista contendo pedidos válidos e ideais.
  • Em vez de usar cores, você usará os índices da lista de entrada. (O último exemplo de saída acima seria [2,0,1,2,0,1,2,0]).
  • Sua saída pode ser 0 ou 1. Meus exemplos serão indexados em 0

Casos de teste

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 é um , então faça suas soluções o mais curto possível no seu idioma favorito!


11
Também pode estar ligado a este
Jonathan Allan

2
@JonathanAllan e é por isso que preciso de um computador para garantir minha diversão :)
Nathan Merrill

Respostas:


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)

Formatado e 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 usada

Abaixo está uma tabela mostrando como a fórmula F(i, j) = minimum(value[j], value[i] + 1)está funcionando, aqui com i = 0e a entrada [ 5, 2, 2 ].

Essa fórmula pode ser interpretada da seguinte maneira: para cada tipo de Skittle, não podemos selecionar mais que o número do tipo menos disponível mais um.

 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 teste


As inicializações reduzidas da soma (0) e mno final dos "loops" são induzidas pelo golfe ou é exatamente como JS é?
Jonathan Allan

@ JonathanAllan Essa é a maneira JS : o valor inicial de reduzir () é localizado após o retorno de chamada. Colocar m=0aqui é induzido pelo golfe, no entanto, porque eu não me importo com o valor inicial desse loop (ele será sobrescrito de qualquer maneira). Inicializar mé conveniente.
Arnauld

Ah, eu vejo que é mais uma chamada de função do que um loop (como a função de redução do Python tem um valor inicial opcional).
Jonathan Allan

@JonathanAllan Sim, exatamente. [1,2,3].reduce((x, y) => x+y, 10)em JS seria reduce(lambda x,y: x+y, [1,2,3], 10)em Python (eu acho), ambos resultando em 16.
Arnauld

2

Gelatina , 22 bytes

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

Indexação baseada em 1.

Experimente online!

Quão?

Repete cada prefixo dos índices classificados por valor decrescente mais uma vez do que seria possível com a bolsa de skittles fornecida, remove o skittle ou skittles finais de cada um deles conforme necessário para torná-los viáveis ​​e retorna o com mais skittles .

O número que deve ser removido de uma repetição periódica extra é apenas o número com a contagem mínima nesse prefixo.

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

1

Python3, 174 172 167 bytes

Idéia

Dado, por exemplo, 3 skittles vermelhos, 2 azuis e 3 verdes, é possível organizá-los em uma grade, classificados por cor e quantidade:

r g
r g b
r g b

Se alguém tentar comer exatamente i skittles, pode-se comer pelo menos i * c skittles no total, onde c é o número de skittles na r-ésima coluna, por exemplo, para i = 2, é possível comer pelo menos 6 skittles.

r g
# # #
# # #

A única coisa que resta a fazer é contar quantos skittles adicionais podem ser consumidos por um período incompleto.

Golfe

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

Experimente online!

Editar: Substituído (i+1)por -~ipara salvar 2 bytes.

Edit: -5 bytes graças ao Dead Possum


Você pode mudar sum(1for e in b if e[0]>c)para sum(c<e[0]for e in b). Seria converter Fiel a 1 implicitamente e poupar 5 bytes
Morto Possum
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.