Enumera un array, raggruppando i duplicati


24

L'obiettivo di questa sfida è prendere una serie di numeri interi positivi ed enumerare i suoi indici, raggruppandoli come elementi.

Un'enumerazione senza duplicati viene eseguita semplicemente emettendo una matrice di coppie (value, index), ad esempio [3, 4, 13, 9, 2]=> [[3,1],[4,2],[13,3],[9,4],[2,5]].

Tuttavia, se un dato elemento appare una seconda volta, non gli viene data la sua stessa coppia, ma viene invece aggiunto al gruppo della sua prima occorrenza. Se nell'esempio precedente abbiamo sostituito il 9 con 3, poi in uscita avremmo rimuovere [9,4]e sostituire [3,1]con [3,1,4].

Nell'output, i gruppi devono essere ordinati in base alla prima occorrenza e gli indici devono essere in ordine crescente. L'elemento deve essere il primo in un gruppo, prima dei suoi indici. L'output può essere 0 o 1 indicizzato. Si può presumere che l'array abbia almeno un elemento.

Casi test:

Input           | Output (One-indexed)
[3, 2, 2, 3]    | [[3, 1, 4], [2, 2, 3]]
[17]            | [[17, 1]]
[1, 1]          | [[1, 1, 2]]
[1, 1, 2]       | [[1, 1, 2], [2, 3]]
[1, 2, 3, 4]    | [[1, 1], [2, 2], [3, 3], [4, 4]]
[1, 1, 1, 1]    | [[1, 1, 2, 3, 4]]

Questo è , vince meno byte!


Sarebbe accettabile che gli indidi vengano emessi come stringhe, ad esempio [[17,"1"]]? (Non so ancora se posso salvare qualche byte in quel modo, ancora lavorando su di esso!)
Shaggy

@shaggy certo, va bene
Pavel


1
Possiamo [[3, [1, 4]], [2, [2, 3]]]invece produrre qualcosa del genere ?
Conor O'Brien,

1
@Pavel non è un motivo: p ma certo
Conor O'Brien il

Risposte:


9

Dyalog APL, 5 byte

(⊂,)⌸

Provalo online!

,⌸per 2 byte quasi funziona, ma ha zero finali: /


Cosa nel mondo fa ?
Mr. Xcoder,

@ Mr.Xcoder ottiene gli indici di ogni cosa e chiama l'operatore di sinistra con la cosa e gli indici in cui esiste
dzaima

Poiché l'isue con ,⌸sta trascinando gli zero e gli zero non saranno mai nell'input, sarebbe possibile eliminare tutti gli zero in meno di 3 byte?
Pavel,

@Pavel il motivo per cui ci sono gli zero è che il risultato è una matrice, che deve avere dimensioni esatte, quindi c'è solo 1 byte per far cadere gli zero per ogni guadagno di byte. Sento che questo potrebbe essere golfable però.
dzaima,

2
Formato di output dell'array "fancy af" : provalo online!
Adám,

7

J , 12 byte

~.,&.><@I.@=

Zero indicizzati.

Provalo online!

Se riesci a rimuovere tutto il lavoro che sto facendo con le scatole, probabilmente puoi ridurre di un po 'il bytecount. Vedrò se riesco a capirlo.

Spiegazione

Questo probabilmente è troppo presto per essere spiegato (ci dovrebbero essere più golf).

~. ,&.> <@I.@=
             =  Self-classify (comparison of each unique element to array)
            @   Composed with
          I.    Indices of ones (where it's equal)
         @      Composed with
        <       Boxed (how we deal with arrays of unequal length)
   ,&.>         Joined with
      >          Unbox each
   ,             Concatenate
    &.           Box again
~.              Unique elements

2
Quel formato di output dell'array è elegante
Pavel,

@Pavel sta prendendo anche molti byte Π.Π
cole

5

05AB1E , 10 byte

ÙεDIQƶ0K)˜

Provalo online!

Spiegazione

Ù             # remove duplicates
 ε            # apply to each element
  D           # duplicate
   IQ         # compare for equality with input
     ƶ        # multiply each element by its index (1-based)
      0K      # remove zeroes
        )˜    # wrap in a flattened list

5

Python 3 , 83 82 byte

-1 byte grazie a Mego

lambda x:[[n]+[j for j,m in enumerate(x)if m==n]for n in sorted({*x},key=x.index)]

Provalo online!


1
j+1-> j(gli indici possono essere a zero)
Mego


5

Attache , 15 byte

Flat=>Positions

Provalo online!

Questo è un caso interessante di =>, la forma dell'operatore di Map. Quando somministrato due argomenti funzionali fe g, Maprestituisce una funzione f => g[x]sopra x. Cioè, l'RHS viene applicato all'ingresso, quindi l'LHS viene mappato.

L'integrato Positionsgenera un array che rappresenta il raggruppamento di voci per indici. Per impostazione predefinita, quando non viene fornito con un secondo argomento, Positionsutilizzerà il primo argomento. Flatviene quindi mappato su ciascun elemento, poiché è quello che richiede la domanda.

Soluzioni alternative

31 byte

MapArgs[Concat#~Indices,Unique]

Provalo online!

Un'alternativa piuttosto breve, senza built-in. MapArgsè una funzione simile Map, tranne per il fatto che è possibile inserire argomenti aggiuntivi. Ad esempio, lo MapArgs[{_1 + _2}, 1..3, 3]è [4, 5, 6]. Come Map, diventa curry se fornito con due argomenti funzionali. La funzione da mappare è Concat#~Indices, che è un fork. Questo fork viene applicato agli Uniqueelementi dell'input e all'input stesso. Questo si traduce in Concat[_, Indices[_2, _]](con gli argomenti di Indicesswapped through ~), che accoppia l'elemento da mappare ( _) con gli indici di detto elemento _nella matrice di input, che è _2(come ffed through MapArgs).

43 byte

{Flat=>Zip[Unique[_],Indices[_,Unique[_]]]}

Provalo online!

Questa è davvero solo una combinazione più dettagliata (ma un po 'più leggibile) delle soluzioni n. 1 e n. 2.


4

Gelatina , 6 byte

Q;"ĠṢ$

Provalo online!

Spiegazione:

Q;"ĠṢ$
Q      Keep the first occurrence of each element
     $ Last two links as a monad
   Ġ    Group indices of equal elements, then sort the resulting list of groups by the element they point to
    Ṣ   Sort; used to re-order the list of groups based on first occurrence instead
  "    Vectorize link between two arguments (the first occurrences and the group list)
 ;      Concatenate

Non funziona per l'ultimo caso di test . L'array dovrebbe essere nidificato su un altro livello, l'output è sempre bidimensionale.
Pavel,

@Pavel , ho appena dimenticato di aggiungere un piè di pagina (la risposta è una funzione)
Erik the Outgolfer

Ok allora, fico. Spiegazione presto, sì? : P
Pavel,

@Pavel ha aggiunto una spiegazione
Erik the Outgolfer,

4

Pyth , 7 byte

0-indicizzati.

{+VQxRQ

Provalo qui! Alternativa.

Come?

{+ VQxRQ - Programma completo.

     RQ - Per ogni elemento ...
    x - Ottieni tutti i suoi indici.
 + V - E applica la concatenazione vettoriale.
   Q - Con l'input.
{- Deduplicato.

4

MATL , 8 byte

u"@tG=fh

Provalo su MATL Online

Spiegazione

        # Implicitly get the input
u       # Compute the unique values
"       # For each unique value, N
  @     # Push the value N to the stack
  t     # Duplicate N
  G     # Grab the input
  =f    # Get the 1-based indices of the elements that equal N
  h     # Horizontally concatenate N with the indices
        # Implicitly display the result

ooooohhh che è intelligente! Avevo 18 byte che cercavano di usare &fma non l'ho mai fatto funzionare.
Giuseppe,

3

In realtà , 24 byte

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔

Provalo online!

Spiegazione:

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔
;;                        make two copies of input
  ╗                       save a copy to register 0
   ⌠╝╜r⌠╜E╛=⌡░⌡M          map over input:
    ╝                       save the element in register 1
     ╜r                     indices for input
       ⌠╜E╛=⌡░              filter:
        ╜E                    element in input at index
          ╛=                  equals element for outer map (from register 1)
                @Z        swap, zip input with map result
                  ⌠♂i⌡M   flatten each element in zipped list
                       ╔  uniquify

3

R , 56 byte

function(x)lapply(unique(x),function(y)c(y,which(x==y)))

Provalo online!


Questo è il mio primo tentativo di codegolf, quindi qualsiasi feedback è il benvenuto!


3
Benvenuti in PPCG! Bella prima risposta.
Pavel,

1
Ehilà Florian! Risposta molto bella Questo è in realtà uno snippet piuttosto che un programma o una funzione - presuppone che l'input sia codificato x, ma ci deve essere un modo per leggere l'input - in genere usiamo scano definiamo una funzione. Inoltre, deve produrre, quindi dovrebbe racchiuderlo in a printo a cat.
Giuseppe,

1
vedi questa domanda per trucchi più utili sul golf R :)
Giuseppe

1
Grazie ragazzi! E il link ai suggerimenti di r è sicuramente utile!
Florian,

2
@Florian R non è poi così male come pensi (tranne che per le sfide con le corde ...) fintanto che ti ricordi che stai giocando a golf contro altri giocatori di R! Sentiti libero di chiamarmi in chat se hai domande. Ci sono un paio di giocatori di golf R che sono attivi e sicuramente offriranno suggerimenti e apprezzeranno anche i tuoi! Benvenuti al golf :)
Giuseppe,


3

JavaScript (ES6), 64 byte

0 indicizzato

a=>a.map((v,i)=>a[-v]?a[-v].push(i):a[-v]=[v,i]).filter(x=>x[0])

Nota, questo presuppone che i numeri di input siano positivi, quindi v> 0

Test leggermente modificato (1 indicizzato) per abbinare i casi di test

var F=
a=>a.map((v,i)=>a[-v]?a[-v].push(i+1):a[-v]=[v,i+1]).filter(x=>x[0])

test = [ // output 1 indexed
  [3, 2, 2, 3],//    | [[3, 1, 4], [2, 2, 3]]
  [17], //           | [[17, 1]]
  [1, 1], //         | [[1, 1, 2]]
  [1, 1, 2], //      | [[1, 1, 2], [2, 3]]
  [1, 2, 3, 4], //   | [[1, 1], [2, 2], [3, 3], [4, 4]]
  [1, 1, 1, 1] //    | [[1, 1, 2, 3, 4]] 
]

test.forEach(t => {
  x = F(t)
  console.log(JSON.stringify(t)+ ' -> ' + JSON.stringify(x))
})


3

APL NARS, 24 byte, 12 caratteri

{∪⍵,¨⍸¨⍵=⊂⍵}

-4 byte grazie al test Adam:

  f←{∪⍵,¨⍸¨⍵=⊂⍵}

  ⎕fmt f 3 2 2 3
┌2────────────────┐
│┌3─────┐ ┌3─────┐│
││ 3 1 4│ │ 2 2 3││
│└~─────┘ └~─────┘2
└∊────────────────┘
  ⎕fmt f 17
┌1──────┐
│┌2────┐│
││ 17 1││
│└~────┘2
└∊──────┘
  ⎕fmt f 1 1
┌1───────┐
│┌3─────┐│
││ 1 1 2││
│└~─────┘2
└∊───────┘
  ⎕fmt f 1 2 3 4
┌4──────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││ 1 1│ │ 2 2│ │ 3 3│ │ 4 4││
│└~───┘ └~───┘ └~───┘ └~───┘2
└∊──────────────────────────┘
  ⎕fmt f 1 1 1 1
┌1───────────┐
│┌5─────────┐│
││ 1 1 2 3 4││
│└~─────────┘2
└∊───────────┘

Radere un 4 byte / 2 caratteri:{∪⍵,¨⍸¨⍵=⊂⍵}
Adám

3

SWI-Prolog , 165 117 byte

-48 byte grazie ai suggerimenti sul golf Prolog .

h(I):-I+[]-1.
[H|T]+R-N:-(select([H|A],R,[H|L],S),!,append(A,[N],L);append(R,[[H,N]],S)),O is N+1,(T+S-O,!;write(S)).

Provalo online!

Spiegazione

% The predicate that prints the grouped duplicates. It's a wrapper because we
% need some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% In the golfed code, operators are used to represent this predicate.
% See /codegolf//a/153160
% Go through the input, build up the result on the way and print it.
enumerate([Head|Tail], Result, Index) :-
    (
        % If our current Result already contains a list that starts with the
        % current first element in our input, Head, NewIndexes will become the
        % new "tail" of that list in our next result list:
        select([Head|OldIndexes], Result, [Head|NewIndexes], NextResult),
        % Don't backtrack before this if goals below this fail:
        !,
        % The as-yet-unknown NewIndexes above should in fact be the same as
        % OldIndexes with our current Index appended:
        append(OldIndexes, [Index], NewIndexes)
    % Use ; instead of separate predicate rules.
    % See /codegolf//a/67032
    ;
        % If our current Result did not already contain Head, append a new list
        % for it with the current index:
        append(Result, [[Head, Index]], NextResult)
    ),
    % Increment our index counter:
    NextIndex is Index + 1,
    (
        % And continue with the rest of our input:
        enumerate(Tail, NextResult, NextIndex),
        % Don't backtrack if the above succeeded:
        !
    ;
        % If Tail is no longer a multi-element list, we're done. Print:
        write(NextResult)
    ).

3

K (oK) , 10 byte

Soluzione:

(!x),'.x:=

Provalo online!

Esempi:

(!x),'.x:=,17
,17 0
(!x),'.x:=1 1
,1 1 2
(!x),'.x:=1 0 1
(1 1 2
2 3)
(!x),'.x:=1 2 3 4
(1 0
2 1
3 2
4 3)

Spiegazione:

La valutazione viene eseguita da destra a sinistra. Penso ancora che questo sia ulteriormente capace di giocare a golf ...

(!x),'.x:= / the solution
         = / group input into dictionary, item!indices
       x:  / save as variable x
      .    / value of x (the indices)
    ,'     / concatenate (,) each-both (') with
(  )       / do this together
 !x        / the key of x (i.e. the items)

Gli appunti:

  • 14 byte senza dichiarare x, (,/)'+(!;.)@'=rinunciato a questo approccio ...

1
È possibile che venga restituito un risultato con indice 0, quindi penso che sia possibile saltare il 1+.
Adám,


2

JavaScript (ES6), 68 byte

0-indicizzati.

a=>a.map(p=(x,i)=>1/p[x]?b[p[x]].push(i):b.push([x,p[x]=i]),b=[])&&b

Casi test


I numeri di input sono! = 0, che potrebbe essere utile per evitare il trucco 1 / x
edc65

2

PHP 4.1, 88 byte

Sì, è piuttosto lungo.

Ciò presuppone un file predefinito php.ini ( short_open_tag = One register_globals = On).

<?foreach($A as$k=>$v){!$b[$v]&&$b[$v]=array($v);$b[$v][]=$k;}print_r(array_values($b));

Questo presenta l'array in un modo leggibile dall'uomo.
I valori possono essere passati da POST, GET e COOKIE, all'interno della chiave "A".


Per una versione moderna, è possibile utilizzare (90 byte):

<?foreach($_GET[A]as$k=>$v){if(!$b[$v])$b[$v]=[$v];$b[$v][]=$k;}print_r(array_values($b));

Il risultato è lo stesso, tranne per il fatto che tutti i valori devono essere passati sui parametri GET all'interno della chiave "A".


2

Perl 6 ,  63  61 byte

*.pairs.classify(*.value).map({.key,|.value».key}).sort(*.[1])

Provalo (basato su 0)

{sort *.[1],map {.key,|.value».key},classify *.value,.pairs}

Provalo (stesso algoritmo basato su 0)

Allargato:

# WhateverCode lambda (this is the parameter) 
*\                                            # [3,2,2,3]

# get a list of Pairs (zero based index => value)
.pairs                                        # (0=>3,1=>2,2=>2,3=>3)

# classify based on the values (unordered result)
.classify(*.value)                            # {2=>[1=>2,2=>2],3=>[0=>3,3=>3]}

# simplify the structure
.map({
  .key,         # the value
  |.value».key  # slip in the indexes
})                                            # ((3,0,3),(2,1,2))

# sort based on first index
.sort(*.[1])

2

Japt , 14 9 byte

0-indicizzati.

â £ð¶X iX

Provalo

â £ð¶X iX
â             :Deduplicate
  £           :Map each X
   ð          :  Get 0-based indices of elements in the input
    ¶X        :    That are equal to X
       iX     :  Prepend X

2

PHP 7.4+ , 71 byte

* 73 byte per citare la $_GETchiave ed evitare avvisi.

Snippet: ( Demo )

<?foreach($_GET[A]as$k=>$v){$b[$v][0]=$v;$b[$v][]=$k;}print_r([...$b]);

Sulla base del rappresentante, presumo che IsmaelMiguel conosca il modo migliore per pubblicare codice php in questa comunità, quindi sto costruendo dalla sua fondazione . Non mi è chiaro se <?debba essere incluso / conteggiato nel mio frammento . Dato che questo è il mio post inaugurale, sono felice che qualcuno spieghi se esiste una sintassi non necessaria. ps ho anche letto Suggerimenti per giocare a golf in PHP che mi sembra un ottimo candidato per la migrazione a Meta .

I miglioramenti apportati allo snippet di Ismael sono:

  1. Assegnazione incondizionata del primo elemento in ciascun subarray (sovrascrittura del valore)
  2. Splatpacking invece diarray_values() reindicizzare l'output.


1

Kotlin , 83 byte

{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

Abbellire

{
    it.mapIndexed { i, c -> c to i }
        .groupBy({ (a, b) -> a }, { (a, b) -> b })
        .map { (a, b) -> listOf(a) + b }
}

Test

var f: (List<Int>) -> List<List<Int>> =
{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

data class Test(val input: List<Int>, val output: List<List<Int>>)

val tests = listOf(
        Test(listOf(3, 2, 2, 3), listOf(listOf(3, 0, 3), listOf(2, 1, 2))),
        Test(listOf(17), listOf(listOf(17, 0))),
        Test(listOf(1, 1), listOf(listOf(1, 0, 1))),
        Test(listOf(1, 1, 2), listOf(listOf(1, 0, 1), listOf(2, 2))),
        Test(listOf(1, 2, 3, 4), listOf(listOf(1, 0), listOf(2, 1), listOf(3, 2), listOf(4, 3))),
        Test(listOf(1, 1, 1, 1), listOf(listOf(1, 0, 1, 2, 3)))
)

fun main(args: Array<String>) {
    for (c in tests) {
        val o = f(c.input)
        if (o != c.output) {
            throw AssertionError("${c.input} -> $o != ${c.output}")
        }
    }
}

TIO

TryItOnline


Questo sollution è uno snippet, non una funzione o un programma completo. Richiede che la variabile isia predefinita. Puoi renderlo valido convertendolo in un lambda che accetta un parametro i.
Pavel,

Rielaborato per risolvere il problema sollevato da @Pavel
jrtapsell il

1

Swift 4, 107 byte

... Yikes.

{a in Dictionary(grouping:a.enumerated()){$0.1}.sorted{$0.1.first!.0<$1.1.first!.0}.map{[$0]+$1.flatMap{$0.0}}}

Ungolfed:

let f = { (input: [Int]) -> [[Int]] in
    return Dictionary(grouping: input.enumerated(), by: { $0.element })
        .sorted { pairA, pairB in // Sort by order of first appearence (lowest offset)
            return pairA.value.first!.offset < pairB.value.first!.offset
        }.map { element, pairs in
            return [element] + pairs.map{ $0.offset /* +1 */} // add 1 here for 1 based indexing
        }
}

È un peccato che il dizionario perda gli ordini, costringendomi a sprecare così tanti personaggi a riordinare di nuovo. Questa sorta di abuso di argomenti di chiusura impliciti ( $0, $1, ...) ei membri tuple impliciti ( .0, .1, ...) è uhhhhh non è abbastanza.



1

Rubino , 54 52 byte

->a{a.map{|i|[i]+(0..a.size).select{|j|a[j]==i}}|[]}

Questa versione consente zero (53 byte):

->a{a.map{|i|[i]+(0...a.size).select{|j|a[j]==i}}|[]}

Provalo online!


La sfida specifica che l'array conterrà solo numeri interi positivi e ci sarà almeno un elemento. nilnon è un numero intero positivo.
Pavel,

@Pavel grazie, ho controllato ma in qualche modo l'ho perso
Solo Tuhid,
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.