Converti un campione in un indice


12

Stiamo mettendo le palline in un numero fisso un bidone. Questi bidoni iniziano vuoti.

Empty bin (a=4): 0 0 0 0 

E uno per uno aggiungiamo le palle ai bidoni.

0 0 0 1  or
0 0 1 0  or
0 1 0 0  or
1 0 0 0

Abbiamo bisogno di un modo rapido per passare in rassegna tutti i possibili stati dei bin, senza duplicati e senza perderne nessuno e non vogliamo elencare tutti i possibili bin. Quindi invece assegniamo a ciascun bin-configuration un indice.

Assegniamo l'indice ordinando le possibili configurazioni in un modo specifico:

  1. Ordinamento crescente per somma: quindi prima 0 0 0 0, quindi le possibili configurazioni con 1 palla aggiunta, quindi 2, ecc.
  2. Quindi ordina all'interno di ogni somma in ordine crescente, dal primo cestino all'ultimo:

    0 0 0 2
    0 0 1 1
    0 0 2 0 
    0 1 0 1
    0 1 1 0 
    0 2 0 0 
    etc
    
  3. L'indice viene quindi assegnato in ordine crescente attraverso questo elenco:

    0 0 0 0  -> 1
    0 0 0 1  -> 2
    0 0 1 0  -> 3
    0 1 0 0  -> 4
    1 0 0 0  -> 5
    0 0 0 2  -> 6
    0 0 1 1  -> 7
    0 0 2 0  -> 8
    0 1 0 1  -> 9
    0 1 1 0  -> 10
    0 2 0 0  -> 11 
    

Regole

Crea una funzione o un programma che prende un elenco di qualsiasi dimensione con numeri interi non negativi e stampa o genera il suo indice. È possibile supporre un essere almeno 2. vittorie codice breve. È possibile utilizzare output indicizzato 0 o indicizzato 1, ma specificare quale utilizzare. NB: tutti gli esempi qui sono 1 indicizzati.

Codice di esempio

Non giocato a golf, in R:

nodetoindex <- function(node){
  a <- length(node)
  t <- sum(node)
  if(t == 0) return(1)

  index <- choose(t-1 + a, a)

  while(sum(node) != 0){
    x <- node[1]
    sumrest <- sum(node)
    if(x == 0){
      node <- node[-1]
      next
    }
    a <- length(node[-1])
    index <- index + choose(sumrest + a, a) - choose(sumrest - x + a, a)
    node <- node[-1]
  }
  return(index + 1)
} 

Casi test

10 10 10 10 -> 130571
3 1 4 1 5 9 -> 424407
2 9 -> 69
0 0 0 -> 1
0 0 1 -> 2
0 0 0 0 0 0 -> 1
1 0 0 0 0 1 -> 23

Come funziona l'ordinamento tramite il valore numerico della concatenazione quando i conteggi hanno numeri diversi di cifre?
TheBikingViking il

@TheBikingViking hmm, non ci avevo pensato, ho cambiato il testo per riflettere il codice di esempio e i casi di test. All'interno di ogni somma, le configurazioni sono ordinate prima nel primo contenitore, quindi nel secondo e così via.
JAD,

Risposte:


3

Gelatina , 8 byte

S0rṗLSÞi

Provalo online!

Soluzione a forza bruta. Il primo test case è troppo per TIO, ma l'ho verificato localmente sul mio laptop. Il secondo caso di test richiede troppa RAM, anche per il mio computer desktop.

Come funziona

S0rṗLSÞi  Main link. Argument: A (array)

S         Compute the sum s of A.
 0r       Create the range [0, ..., s].
    L     Yield the length l of A.
   ṗ      Cartesian power; yield the array of all l-tuples over [0, ..., s], in
          lexicographical order.
     SÞ   Sort the l-tuples by their sums. The sorting mechanism is stable, so
          l-tuples with the same sum are still ordered lexicographically.
       i  Find the index of A in the generated array of tuples.

Bello. La tua osservazione sulla RAM mi ha ricordato l'origine di questa sfida. Per la mia tesi ho dovuto passare in rassegna tutti gli array possibili per alcune palle a = 8 e il più in alto possibile. L'idea di trasformare le matrici in indici e limitarsi a superarle è venuta esattamente dalla limitazione della RAM: P
JAD

Questo è anche il motivo per cui il codice di esempio è così prolisso: P
JAD

1

Clojure, 152 byte

#(loop[v[(vec(repeat(count %)0))]i 1](if-let[r((zipmap v(range))%)](+ r i)(recur(sort(set(for[v v i(range(count v))](update v i inc))))(+ i(count v)))))

Non facile come pensavo. Versione meno giocata a golf:

(def f (fn[t](loop[v[(vec(repeat(count t)0))]i 1]
               (if-let[r((zipmap v(range))t)](+ r i)
                 (recur (sort-by (fn[v][(apply + v)v]) (set(for[v v i(range(count v))](update v i inc))))
                        (+ i(count v)))))))

Passa sopra gli stati attuali v, crea una mappa hash dagli elementi del vloro rango, se viene trovato lo stato cercato, viene restituito il suo rango (+ il numero di stati visti in precedenza). Se non trovato, ricorre con un nuovo set di stati possibili.

Oh, in realtà non abbiamo bisogno di quella funzione di ordinamento personalizzata poiché tutti gli stati all'interno di ogni ciclo hanno la stessa somma. Questo non è così lento come mi aspettavo in [3 1 4 1 5 9]soli 2,6 secondi.


1

Mathematica, 50 byte

Una risposta alla porta di Jelly di Dennis .

0~Range~Tr@#~Tuples~Length@#~SortBy~Tr~Position~#&

Funzione senza nome che prende un elenco di numeri interi come input e restituisce un elenco di profondità 2 con un singolo numero intero come output; ad esempio, l'input per l'ultimo caso di test è {1,0,0,0,0,1}e l'output è {{23}}.

Una versione leggermente non golfata è:

Position[SortBy[Tuples[Range[0,Tr[#]],Length[#]],Tr],#]&

Spesso possiamo salvare singoli byte in Mathematica usando la notazione prefisso ( function@ninvece di function[n]) e la notazione infisso ( a~function~binvece di function[a,b]). Questo funziona solo quando il codice risultante si combina bene con l'ordine di precedenza intrinseco di Mathematica per l'applicazione delle funzioni. Sono stato un po 'stupito qui che, con sei serie di parentesi quadre, ha effettivamente funzionato per rimuoverle tutte e salvare sei byte con il codice inviato (piacevolmente senza parentesi).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.