Scambia indici e valori


29

L'obiettivo

Scrivi un programma o una funzione il cui input è un elenco / array X di numeri interi e il cui output è un elenco di set di numeri interi Y , in modo tale che per ciascun elemento e in ciascun set Y [ i ], X [ e ] = i e tale che il numero totale di elementi negli insiemi di Y è uguale al numero di elementi in X .

(Questa è sostanzialmente la stessa operazione di invertire un hashtable / dizionario, tranne invece che si applica agli array.)

Esempi

Questi esempi presuppongono l'indicizzazione basata su 1, ma è possibile utilizzare l'indicizzazione basata su 0 se si preferisce.

X             Y
[4]           [{},{},{},{1}]
[1,2,3]       [{1},{2},{3}]
[2,2,2]       [{},{1,2,3}]
[5,5,6,6]     [{},{},{},{},{1,2},{3,4}]
[6,6,5,5]     [{},{},{},{},{3,4},{1,2}]

chiarimenti

  • Se lo desideri, puoi rappresentare un set come elenco. Se lo fai, l'ordine dei suoi elementi non ha importanza, ma potresti non ripetere gli elementi.
  • È possibile utilizzare qualsiasi formato I / O inequivocabile; ad esempio, è possibile separare gli elementi di un set con spazi e i set stessi con nuove righe.
  • Y dovrebbe essere finemente lungo e almeno abbastanza lungo da avere tutti gli elementi di X come indici di array. Tuttavia, potrebbe essere più lungo dell'elemento massimo di X (gli elementi extra sarebbero insiemi vuoti).
  • Gli elementi di X saranno tutti indici di array validi, cioè numeri interi non negativi se si utilizza l'indicizzazione basata su 0 o numeri interi positivi se si utilizza l'indicizzazione basata su 1.

Condizione di vittoria

Come una sfida di , più breve è meglio.


Correlato . Nel post di Sandbox (ora eliminato, ma puoi visualizzarlo se hai la reputazione), abbiamo deciso che probabilmente non era un duplicato, ma sentiti libero di votare per chiudere se non sei d'accordo.

"L'ordine dei suoi elementi non ha importanza" significa che i risultati di [5,5,6,6]e [6,6,5,5]possono essere identici?
Leaky Nun,

1
@LeakyNun L'ordine degli elementi degli insiemi nell'elenco di output non ha importanza. Quindi [5,5,6,6]e [6,6,5,5]non può avere un output identico, ma anche l'output per [5,5,6,6]potrebbe essere stato, ad esempio [{},{},{},{},{2,1},{4,3}].
ngenesi,

Esiste un valore massimo ipotizzabile di un indice in X? Inoltre, gli insiemi vuoti possono contenere uno 0 anziché essere effettivamente vuoti? Ad esempio sarebbe [{0},{0},{0},{0},{1,2},{3,4}]un output valido per [5,5,6,6]?
Skidsdev,

@Mayube: No alla prima risposta (anche se se stai usando una lingua che ha un intervallo limitato sugli interi, puoi scrivere il programma come se gli interi potessero essere illimitati e non preoccuparti che si rompa se qualcuno ti dà un out- intero di gamma come input). Rispetto alla seconda domanda, si tratta di una sintassi non ambigua (se strana) quando si utilizza l'indicizzazione basata su 1, quindi sì in quel caso (ovviamente, no se si utilizza l'indicizzazione basata su 0 perché allora lo 0 significherebbe qualcosa altro.)

Risposte:


9

MATL , 8 byte

tn:IXQ&D

L'input è un vettore di colonna, con ;come separatore (ad esempio[2;2;2] ). L'output è la rappresentazione in formato stringa di una matrice di celle di vettori di riga (ad esempio {[]; [1 2 3]}). Un vettore di riga di un singolo elemento è uguale a un numero (quindi {1; 2; 3}verrebbe generato invece di {[1]; [2]; [3]}).

Provalo online!Oppure verifica tutti i casi di test .

Spiegazione

t     % Implicit input, say x. Duplicate
n     % Number of elements, say N
:     % Range: [1 2 ... N]
IXQ   % accumarray(x, [1 2 ... N], [], @(x){sort(x).'})
&D    % String representation

Gran parte del lavoro viene svolto dalla funzione di ordine superiore di Matlab accumarray, che raggruppa gli elementi nel secondo input in base ai valori corrispondenti nel primo e applica una funzione specifica a ciascun gruppo. La funzione in questo caso è @(x){sort(x).'}, che genera gli elementi ordinati in ciascun gruppo e fa impacchettare i risultati per tutti i gruppi in un array di celle.


7

Python, 69 byte

lambda s:[[j for j,x in enumerate(s)if x==i]for i in range(max(s)+1)]

Utilizza l'indicizzazione basata su 0.


7

Gelatina , 7 5 byte

=þṀT€

Provalo online!

Come funziona

=þṀT€  Main link. Argument: A (array)

  Ṁ    Yield m, the maximum of A.
=þ     Equals table; for each t in [1, ..., m], compare all elemnts of A with t,
       yielding a 2D Boolean array.
   T€  Truth each; for each Boolean array, yield all indices of 1.

5

Gelatina , 8 byte

Jẋ"Ṭ€;"/

Provalo online!

Come funziona

Jẋ"Ṭ€;"/  argument: z           eg. [6,6,4,4]
J         [1 .. len(z)]             [1,2,3,4]
   Ṭ€     untruth each of z         [[0,0,0,0,0,1],
                                     [0,0,0,0,0,1],
                                     [0,0,0,1],
                                     [0,0,0,1]]
 ẋ"       repeat each of ^^         [[[],[],[],[],[],[1]],
          as many times as           [[],[],[],[],[],[2]],
          each of ^                  [[],[],[],[3]],
                                     [[],[],[],[4]]]
       /  reduce by...
     ;"   vectorized concatenation  [[],[],[],[3,4],[],[1,2]]

4

Mathematica, 36 byte

Join@@@#~Position~n~Table~{n,Max@#}&

Spiegazione

enter image description here

Per ogni nin {1, 2, ..., Max@#}, dove Max@#è il numero intero più grande nell'elenco di input, calcola le Positions dove nappare nell'elenco di input #. Poiché Position[{6,6,5,5},5](per esempio) ritorna {{3},{4}}, passiamo quindi Apply Joina tutti gli elementi a livello {1}del risultato.


3

Haskell , 45 byte

sprende un elenco di numeri interi e restituisce un elenco di elenchi. 1-indicizzato per mantenere immodificati gli input del test case (anche se l'output ottiene alcuni elenchi vuoti extra).

s l=[[i|(i,y)<-zip[1..]l,y==x]|x<-[1..sum l]]

Provalo online!

Queste sono comprensioni dell'elenco nidificato piuttosto semplici. L'unica leggera modifica sta sfruttando l'opzione per fare un elenco più lungo usando suminvece di maximum.


3

PHP, 55 byte

<?while($i<=max($_GET))print_r(array_keys($_GET,$i++));

0-indicizzati.


3

R, 68 49 47 byte

lapply(1:max(x<-scan()),function(y)which(y==x)) 

Sorprendentemente, molto più semplice rispetto alle soluzioni più lunghe. Prende un vettore xda STDIN, crea un vettore da 1a max(x), genera implicitamente un elenco di lunghezze max(x)e verifica quali indici xcorrispondono a quelli del nuovo elenco. Stampa implicitamente l'output.

Versione precedente:

o=vector('list',max(x<-scan()));for(i in x)o[[i]]=c(o[[i]],F<-F+1);o

Approccio leggermente diverso all'altra risposta R. Porta un vettore a STDIN, crea un elenco con lunghezza pari al valore massimo nell'input. Passa sopra l'input e aggiunge l'indice nel posto giusto.

Utilizza l'indicizzazione basata su 1.


2

Python 2 , 91 86 85 byte

Sto programmando sul mio telefono ma questa sfida mi è piaciuta molto. Posso sicuramente giocare a golf ulteriormente.

def f(a):
 r=[[]for i in range(max(a)+1)]
 for i,j in enumerate(a):r[j]+=[i]
 print r

Provalo online!


Superato di nuovo da una comprensione della lista nidificata. : D
totalmente umano

2

Gelatina , 9 byte

Ṭ+\ịĠȧ@"Ṭ

1 indicizzati, insiemi vuoti rappresentati come 0, insiemi di un oggetto rappresentati come Ninsiemi di più elementi rappresentati come[M,N,...]

Provalo online!

Come?

Ṭ+\ịĠȧ@"Ṭ - Main link: list a        e.g. [6,6,4,4]
Ṭ         - untruth a                     [0,0,0,1,0,1]
  \       - cumulative reduce with:
 +        -   addition                    [0,0,0,1,1,2]
    Ġ     - group indices of a by value   [[3,4],[1,2]]
   ị      - index into                    [[1,2],[1,2],[1,2],[3,4],[3,4],[1,2]]
        Ṭ - untruth a                     [0,0,0,1,0,1]
       "  - zip with:
     ȧ@   -   and with reversed @rguments [0,0,0,[3,4],0,[1,2]]

2

JavaScript (ES6), 64 62 byte

Salvato 2 byte grazie a @SteveBennett


Accetta input indicizzato 0. Restituisce un elenco di insiemi separati da virgole.

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&`{${o.join`},{`}}`

Casi test


Versione alternativa, 53 byte

Se un output semplificato come '||||3,2|1,0'è accettabile, possiamo semplicemente fare:

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&o.join`|`

Wow. Sono così confuso come `{${o.join`},{`}}`è legale ES2015.
Steve Bennett,

@SteveBennett, è un modello letterale . Nelle versioni precedenti di JS lo sarebbe "{" + o.join("},{") + "}", se ciò lo rendesse più chiaro.
Shaggy,

No, ne sono a conoscenza - è il backquote dopo la parola join che mi confonde. Quello sta chiudendo la stringa (in questo caso wtf) o è così che sfuggite a una parentesi graffa stretta?
Steve Bennett,

Hmm, ok, quindi in questo contesto join`è equivalente a join('. Non avevo idea che tu potessi farlo.
Steve Bennett,

Ah, ora vedo. È un modello con tag letterale. Che si può abusare di salvare un paio di personaggi ogni volta che chiama una funzione che prende un argomento stringa (e ignora gli altri): array.join` `. Super confuso qui perché lo stai incorporando in una stringa di modello, e ancora più confusamente, la stringa di unione è },{, che per coincidenza sembrava parte della stringa di modello ... ed è comunque solo strana e brutta. :)
Steve Bennett,

1

Bash , 109 byte

Peccato che non sia integrato per il valore massimo dell'array.

a=($@)
for((x=m=1;x<=m;x++)){ for((y=0;y<$#;)){((m<a[y]))&&((m=a[y]));((a[y++]==x))&&printf "%d " $y;};echo;}

Provalo online!


1

Mathematica 62 byte

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&

Lo eseguirò per te

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&[{4,5,2,3,3,8,6,3}]

{{}, {3}, {4, 5, 8}, {1}, {2}, {7}, {}, {6}}

Provalo online (basta incollare il codice con ctrl-v e premere maiusc + invio)
non dimenticare di incollare l'elenco di input alla fine come nell'esempio sopra


Benvenuti in PPCG! È possibile salvare un byte utilizzando la notazione infissa per AppendTo. Inoltre, {j,1,Length[#1]}potrebbe essere solo {j,Length@#}, o anche più breve, {j,Tr[1^#]}. Tr[1^#]è un trucco piuttosto comune per salvare un byte sull'uso Length.
ngenesi,

1

Perl 6 ,  36 32  29 byte

->\a{map {a.grep(*==$_):k},1..a.max}

Provalo

{map {.grep(*==$^a):k},1.. .max}

Provalo

{map {.grep($^a):k},1.. .max}

Provalo


Allargato:

{  # bare block lambda with implicit parameter 「$_」

  map

    {  # bare block lambda with placeholder parameter 「$a」

      .grep(  # grep for the values in 「$_」
        $^a   # that are equal to the currently tested value (and declare param)
      ) :k    # return the key (index) rather than the value
    },

    1 .. .max # Range from 1 to the maximum value in 「$_」

}

Restituisce indici in base zero, per ottenere 1 in base usare l'operatore incrociato ( X) combinato con +op . (33 byte)

{1 X+.grep($^a):k}

Per farlo restituire Set s giusto aggiungerloset (totale 37 byte)

{set 1 X+.grep($^a):k}

1

R, 80 72 byte

1-indicizzato, prende Xdallo stdin. Restituisce un elenco di vettori degli indici, conNULL come set vuoto.

X=scan();Y=vector('list',max(X));Y[X]=lapply(X,function(x)which(X==x));Y

Provalo online!

vecchia versione:

X=scan();Y=vector('list',max(X));for(i in 1:length(X))Y[[X[i]]]=c(Y[[X[i]]],i);Y

Provalo online!


Penso che Y=list();funzioni altrettanto bene
rturnbull,

Riuscito a radere un fewbyte nella mia risposta :) codegolf.stackexchange.com/a/120024/59530
JAD


0

Röda , 51 byte

f s{seq(1,max(s))|[[s()|enum|[_2+1]if[_1=i]]]for i}

È una porta della risposta Python di Uriel .

Un'altra versione (88 byte):

f a{I=indexOf;seq(1,max(a))|{|i|b=a[:]c=[]x=1{c+=x+I(i,b)b-=i;x++}until[I(i,b)<0];[c]}_}

Provalo online!

Entrambi 1 indicizzati.



0

GNU Make , 214 213 208 204 byte

X=$(MAKECMDGOALS)
M=0
P=$(eval N=$(word $1,$X))$(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),$(eval M=$N),)$(eval A$N+=$1$(call $0,$(shell expr $1 + 1))),)
$(call P,1)$(foreach K,$(shell seq $M),$(info $(A$K)))

I / O: array di input tramite argomenti, output su stdout, uno per riga, separato da spazi.

$ make -f swap.mk 2 2 2

3 2 1
make: *** No rule to make target `2'.  Stop.

Spiegazione

X=$(MAKECMDGOALS)     # Input array
M=0                   # Max value encountered in X
P=$(eval
    N=$(word $1,$X))  # Get next word from X
  $(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),
    $(eval M=$N),)    # Update M
    $(eval A$N+=$1    # Append index to a variable named after value
      $(call $0,      # Recurse (call returns empty string)
        $(shell expr $1 + 1))),)
$(call P,1)           # Initial call to P. 1 is the first index
$(foreach K,          # Print all values of A* variables
  $(shell seq $M),
  $(info $(A$K)))     # Uninitialized ones default to empty strings

L'ordine degli indici negli insiemi viene invertito perché si Pchiama ricorsivamente prima dell'aggiornamento A$2(chiamata eseguita nella valutazione del lato destro).


Ha makeun modo di fare l'aritmetica stessa? Richiamare programmi esterni per farlo è un po 'come imbrogliare, perché probabilmente potresti inserire molto più algoritmo in quei programmi e finire con un programma più breve.

@ ais523 No. Versione precedente utilizzata bce grep. Potrei anche usare teste $?. dcha una sintassi più terser, ma francamente tutti questi sembrano uguali.
eush77,

0

Lisp comune, 91 byte

(lambda(x &aux(l(make-list(eval`(max,@x))))(i 0))(dolist(y x l)(push(incf i)(nth(1- y)l))))

Indicizzazione basata su 1, restituisce gli insiemi come elenchi.

Provalo online!


0

k , 13 byte

{(=x)@!1+|/x}

Questo è 0-indicizzato.

Provalo online!

{           } /function(x)
 (=x)         /make a map/dictionary of values to their indices
         |/x  /get maximum value in x
      !1+     /make a range from 0 to the value, inclusive
     @        /get map value at each of the values in the range
              /    0N is given where there is no result
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.