sfondo
Sono stato ispirato dal recente video di 3Blue1Brown sul problema della divisione della collana (o come lo chiama lui, il problema della collana rubata) e sulla sua relazione con il teorema di Borsuk-Ulam .
In questo problema, due ladri hanno rubato una preziosa collana composta da diversi tipi di gioielli. Esiste un numero pari di ogni tipo di gioiello e i ladri desiderano dividere ogni tipo di gioiello in modo uniforme tra i due. Il trucco è che devono farlo dividendo la collana in un certo numero di segmenti contigui e distribuendo i segmenti tra loro due.
Ecco un esempio con quattro tipi gioiello indicati S
, E
, D
, e R
(per zaffiro, smeraldo, diamante e rubino, rispettivamente). Diciamo che la collana è la seguente:
[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]
Ci sono 8
zaffiri, 10
smeraldi, 4
diamanti e 6
rubini. Possiamo dividere la collana come segue:
[[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
Quindi se diamo il primo, il terzo e il quinto segmento a un ladro e il secondo e il quarto segmento all'altro ladro, ognuno finirà con 4
zaffiri, 5
smeraldi, 2
diamanti e 3
rubini:
[S], [S,E,S,D,E,R,S], [R,R,D,E,E,E]
[S], [R,E,S,S,S,D,R,E,E,R,E,D,E],
Usando 0
-indexing, questi tagli si verificano negli indici [1,2,9,22]
.
Obbiettivo
Si scopre che una divisione così equa può sempre essere fatta usando al massimo i n
tagli, dove si n
trova il numero di tipi di gioielli. Il tuo compito è quello di scrivere un programma o una funzione completa che accetta una collana come input e genera una divisione minima (il minor numero di tagli).
Ingresso
L'input può essere in qualsiasi formato conveniente. La collana dovrebbe essere una sequenza di gioielli e niente di più; ad esempio un elenco di numeri interi, un dizionario con chiavi che rappresentano i tipi di gioiello e i valori che sono elenchi di indici. Puoi facoltativamente includere la lunghezza della collana o il numero di tipi di gioiello distinti, ma non dovresti prendere altri input.
Si può presumere che la collana di input sia valida. Non è necessario gestire il caso in cui esiste un numero dispari di gioielli di un determinato tipo o la collana è vuota.
Produzione
Ancora una volta, l'output può essere in qualsiasi formato conveniente; ad esempio un elenco di segmenti, un elenco di posizioni di taglio, un dizionario con chiavi che rappresentano i due ladri e valori che sono elenchi di segmenti, ecc. I segmenti possono essere rappresentati dal loro indice iniziale, indice finale, elenco di indici consecutivi, elenco di gioielli, le loro lunghezze, ecc. Puoi usare 0
- o 1
- l'indicizzazione. Se l'ordinamento non è significativo per il tuo formato, l'output potrebbe essere in qualsiasi ordine. Ecco l'output sopra in diversi formati:
list of segments: [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
list of cuts: [1,2,9,22]
list of lengths: [1,1,7,13,6]
dictionary: {'thief1' : [(R,R,D,E,E,E),(S),(S,E,S,D,E,R,S)], 'thief2' : [(S),(R,E,S,S,S,D,R,E,E,R,E,D,E)]}
Si noti che l'ordine è importante nell'elenco dei segmenti (i segmenti si alternano tra i ladri) e l'elenco delle lunghezze (per identificare i segmenti), ma non nell'elenco dei tagli o nel dizionario. Modifica: Greg Martin ha sottolineato che questi non sarebbero risultati validi poiché una divisione equa può essere ottenuta in due tagli
Casi test
[1,2,1,2,1,3,1,3,3,2,2,3] -> [[1,2,1],[2,1,3,1],[3,3,2],[2,3]]
[1,1,1,1,2,2,3,3,3,3,3,3] -> [[1,1],[1,1,2],[2,3,3,3],[3,3,3]]
[1,1,1,1,1,1,1,1,1,1,1,1] -> [[1,1,1,1,1,1],[1,1,1,1,1,1]]
[1,1,1,1,2,3,4,2,3,4,2,2] -> [[1,1],[1,1,2,3,4,2],[3,4,2,2]]
Appunti
- Sono vietate le scappatoie standard .
- Questo è code-golf ; la risposta più breve (in byte) vince.
[S,S,S,E,S,D,E,R,S,R,E,S,S,S,D,R,E,E,R,E,D,E,R,R,D,E,E,E]
, sembra che l'output dovrebbe essere [[S,S,S,E,S,D,E,R],[S,R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
, dal momento che ha meno tagli di [[S],[S],[S,E,S,D,E,R,S],[R,E,S,S,S,D,R,E,E,R,E,D,E],[R,R,D,E,E,E]]
. Comprendo correttamente le specifiche?