Énumérer un tableau, regrouper les doublons

24

L'objectif de ce défi est de prendre un tableau d'entiers positifs et d'énumérer ses indices, en les regroupant comme des éléments.

Une énumération sans doublons se fait en sortant simplement un tableau de paires (value, index), par exemple, [3, 4, 13, 9, 2]=> [[3,1],[4,2],[13,3],[9,4],[2,5]].

Cependant, si un élément donné apparaît une deuxième fois, il ne reçoit pas sa propre paire, mais est plutôt ajouté au groupe de sa première occurrence. Si dans notre exemple ci-dessus, nous avons remplacé le 9 par 3, alors dans la sortie, nous supprimerions [9,4]et remplacerions [3,1]par [3,1,4].

Dans la sortie, les groupes doivent être classés par leur première occurrence et les indices doivent être en ordre croissant. L'élément doit être le premier d'un groupe, avant ses indices. La sortie peut être indexée 0 ou 1. Vous pouvez supposer que le tableau contient au moins un élément.

Cas de 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]]

C'est du , le moins d'octets gagne!

Pavel
la source
Serait-il acceptable que les indides soient sortis sous forme de chaînes, par exemple [[17,"1"]]? (Je ne sais pas encore si je peux enregistrer des octets de cette façon, en travaillant toujours dessus!)
Shaggy
@shaggy bien sûr, ça va
Pavel
3
Copie possible.
totalement humain le
1
Pouvons-nous produire quelque chose comme à la [[3, [1, 4]], [2, [2, 3]]]place?
Conor O'Brien
1
@ Pavel ce n'est pas une raison: p mais bien sûr
Conor O'Brien

Réponses:

9

Dyalog APL, 5 octets

(⊂,)⌸

Essayez-le en ligne!

,⌸pour 2 octets fonctionne presque , mais a des zéros de fin: /

dzaima
la source
Que fait le monde ?
M. Xcoder
@ Mr.Xcoder obtient les index de chaque chose et appelle l'opérateur de gauche avec la chose et les index là où ils existent
dzaima
Étant donné que le fichier avec ,⌸des zéros de fin et que les zéros ne seront jamais en entrée, serait-il possible de supprimer tous les zéros en moins de 3 octets?
Pavel
@Pavel la raison pour laquelle il y a des zéros est que le résultat est une matrice, qui doit avoir des dimensions exactes, donc il n'y a qu'un octet pour supprimer les zéros pour tout gain d'octets. Je pense que cela pourrait être jouable au golf.
dzaima
2
Format de sortie du tableau "fancy af" : Essayez-le en ligne!
2018
7

J , 12 octets

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

Zéro indexé.

Essayez-le en ligne!

Si vous pouvez supprimer tout le travail que je fais avec les boîtes, vous pouvez probablement réduire considérablement le nombre de bytecount. Je vais voir si je peux comprendre cela.

Explication

C'est probablement trop tôt pour l'expliquer (il devrait y avoir plus de golfs).

~. ,&.> <@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
cole
la source
2
Ce format de sortie du tableau est fantaisie af
Pavel
@Pavel, ça prend aussi beaucoup d'octets Π.Π
cole
5

05AB1E , 10 octets

ÙεDIQƶ0K)˜

Essayez-le en ligne!

Explication

Ù             # 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
Emigna
la source
5

Python 3 , 83 82 octets

-1 octet grâce à Mego

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

Essayez-le en ligne!

Barre
la source
1
j+1-> j(les indices peuvent être indexés à zéro)
Mego
5

Attaché , 15 octets

Flat=>Positions

Essayez-le en ligne!

Ceci est un cas intéressant de =>, la forme opérateur de Map. Administré deux arguments fonctionnels fet g, Maprenvoie une fonction f => g[x]plus x. Autrement dit, le RHS est appliqué à l'entrée, puis le LHS est mappé.

La fonction intégrée Positionsgénère un tableau représentant le regroupement des entrées par index. Par défaut, lorsqu'il n'est pas fourni avec un deuxième argument, Positionsutilise le premier argument. Flatest ensuite mappé sur chaque élément, car c'est ce que la question requiert.

Solutions alternatives

31 octets

MapArgs[Concat#~Indices,Unique]

Essayez-le en ligne!

Une alternative assez courte et intégrée. MapArgsest une fonction comme Map, sauf que vous pouvez y ajouter des arguments supplémentaires. Par exemple, MapArgs[{_1 + _2}, 1..3, 3]est [4, 5, 6]. Comme Map, il devient curry lorsqu'il est fourni avec deux arguments fonctionnels. La fonction à mapper est Concat#~Indices, qui est une fourchette. Cette fourchette est appliquée aux Uniqueéléments de l'entrée et à l'entrée elle-même. Cela se traduit par Concat[_, Indices[_2, _]](avec les arguments de Indicesswapped through ~), qui associe l'élément en cours de mappage ( _) avec les indices dudit élément _dans le tableau d'entrée, qui est _2(tel que ffed through MapArgs).

43 octets

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

Essayez-le en ligne!

C'est vraiment juste une combinaison plus verbeuse (mais un peu plus lisible) des solutions # 1 et # 2.

Conor O'Brien
la source
4

Gelée , 6 octets

Q;"ĠṢ$

Essayez-le en ligne!

Explication:

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
Erik le Outgolfer
la source
Ne fonctionne pas pour le dernier cas de test . Le tableau doit être imbriqué dans une autre couche, la sortie est toujours bidimensionnelle.
Pavel
@ Pavel oui c'est vrai , j'ai juste oublié d'ajouter un pied de page (la réponse est une fonction)
Erik the Outgolfer
Ok alors, cool. Explication bientôt, oui? : P
Pavel
@Pavel a ajouté une explication
Erik the Outgolfer
4

Pyth , 7 octets

0 indexé.

{+VQxRQ

Essayez-le ici! Alternative.

Comment?

{+ VQxRQ - Programme complet.

     RQ - Pour chaque élément ...
    x - Obtenez tous ses indices.
 + V - Et appliquer la concaténation vectorisée.
   Q - Avec l'entrée.
{- Dédupliquer.
M. Xcoder
la source
4

MATL , 8 octets

u"@tG=fh

Essayez-le sur MATL Online

Explication

        # 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
Suever
la source
ooooohhh c'est intelligent! J'avais comme 18 octets à essayer &fmais je ne l'ai jamais fait fonctionner.
Giuseppe
3

En fait , 24 octets

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

Essayez-le en ligne!

Explication:

;;╗⌠╝╜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
Mego
la source
3

R , 56 octets

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

Essayez-le en ligne!


Ceci est ma première tentative de codegolf, donc tout commentaire est le bienvenu!

Florian
la source
3
Bienvenue chez PPCG! Belle première réponse.
Pavel
1
Salut Florian! Très belle réponse. Il s'agit en fait d'un extrait plutôt que d'un programme ou d'une fonction - il suppose que l'entrée est codée en dur x, mais il doit y avoir un moyen de lire l'entrée - généralement, nous utilisons scanou définissons une fonction. De plus, il doit sortir, donc il faudrait envelopper cela dans un printou un cat.
Giuseppe
1
voir cette question pour des astuces de golf R plus pratiques :)
Giuseppe
1
Merci les gars! Et le lien vers les astuces r est certainement utile!
Florian
2
@Florian R n'est pas aussi mauvais que vous le pensez (sauf sur les défis de cordes ...) tant que vous vous souvenez que vous jouez contre d'autres golfeurs R! N'hésitez pas à me cingler dans le chat si vous avez des questions. Il y a quelques golfeurs R qui sont actifs, et ils vous proposeront certainement des suggestions et apprécieront également la vôtre! Bienvenue au golf :)
Giuseppe
3

Wolfram Language (Mathematica) , 40 octets

Un octet enregistré grâce à Martin Ender.

KeyValueMap[{#,##&@@#2}&]@*PositionIndex

Essayez-le en ligne!

alephalpha
la source
Comment ça @*PositionIndexmarche?
Pavel
@ Pavel @*est la composition des fonctions. PositionIndexfait essentiellement tout le travail, mais renvoie une association au lieu d'une liste.
alephalpha
1
{#,##&@@#2}&enregistre un octet.
Martin Ender
3

JavaScript (ES6), 64 octets

0 indexé

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

Notez que cela suppose que les nombres d'entrée sont positifs, donc v> 0

Test légèrement modifié (1 indexé) pour correspondre aux cas de 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))
})

edc65
la source
3

APL NARS, 24 octets, 12 caractères

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

-4 octets grâce au 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
└∊───────────┘
RosLuP
la source
Rasez un 4 octets / 2 caractères:{∪⍵,¨⍸¨⍵=⊂⍵}
Adám
3

SWI-Prolog , 165117 octets

-48 octets grâce aux conseils de 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)).

Essayez-le en ligne!

Explication

% 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)
    ).
mercator
la source
3

K (oK) , 10 octets

Solution:

(!x),'.x:=

Essayez-le en ligne!

Exemples:

(!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)

Explication:

L'évaluation se fait de droite à gauche. Je pense toujours que c'est plus pratique pour le 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)

Remarques:

  • 14 octets sans déclarer x, (,/)'+(!;.)@'=, a renoncé à cette approche ...
streetster
la source
1
Vous pouvez retourner un résultat indexé 0, donc je pense que vous pouvez ignorer le 1+.
Adám
2

Julia 0,6 , 37 octets

Merci à Pavel pour 1 octet de moins.

y->[[x;findin(y,[x])]for x=unique(y)]

Essayez-le en ligne!

gggg
la source
Supprimez l'espace entre ]et forpour -1 octet.
Pavel
2

JavaScript (ES6), 68 octets

0 indexé.

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

Cas de test

Arnauld
la source
Les nombres en entrée sont! = 0, ce qui pourrait être utile pour éviter l'astuce 1 / x
edc65
2

PHP 4.1, 88 octets

Ouais, c'est assez long.

Cela suppose un fichier par défaut php.ini ( short_open_tag = Onet register_globals = On).

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

Cela présente le tableau d'une manière lisible par l'homme.
Les valeurs peuvent être passées par POST, GET et COOKIE, à l'intérieur de la clé "A".


Pour une version moderne, on peut utiliser (90 octets):

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

Le résultat est le même, sauf que toutes les valeurs doivent être passées sur les paramètres GET à l'intérieur de la clé "A".

Ismael Miguel
la source
2

Perl 6 ,  63  61 octets

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

Testez-le (basé sur 0)

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

Testez-le (même algorithme basé sur 0)

Étendu:

# 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])
Brad Gilbert b2gills
la source
2

Japt , 14 9 octets

0 indexé.

â £ð¶X iX

Essayez-le

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

PHP 7.4+ , 71 octets

* 73 octets pour citer la $_GETclé et éviter les avertissements.

Extrait: ( Démo )

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

Basé sur le représentant, je suppose qu'IsmaelMiguel connaît la meilleure façon de publier du code php dans cette communauté, donc je construis à partir de sa fondation . Il n'est pas clair pour moi s'il <?doit être inclus / compté dans mon extrait de code . Comme c'est mon premier billet, je suis heureux que quiconque explique s'il y a une syntaxe inutile. ps J'ai également lu des conseils pour jouer au golf en PHP qui me semble être un excellent candidat pour la migration vers Meta .

Les améliorations apportées à l'extrait d'Ismael sont les suivantes:

  1. Affectation inconditionnelle du premier élément de chaque sous-tableau (écrasement de valeur)
  2. Splatpacking au lieu dearray_values() réindexer la sortie.
mickmackusa
la source
1

Kotlin , 83 octets

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

Embellie

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

Tester

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

jrtapsell
la source
Cette sollution est un extrait, pas une fonction ou un programme complet. Il nécessite que la variable isoit prédéfinie. Vous pouvez le rendre valide en le convertissant en un lambda qui prend un paramètre i.
Pavel
Retravaillé pour résoudre le problème soulevé par @Pavel
jrtapsell
1

Swift 4, 107 octets

... Ouais.

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

Non golfé:

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
        }
}

Il est dommage que le dictionnaire ne soit plus ordonné, ce qui m'oblige à gaspiller autant de caractères lors d'un nouveau tri. Ce genre d'abus d'arguments implicites de fermeture ( $0, $1...) et les membres de tuple implicites ( .0, .1...) est uhhhhh pas joli.

Alexander - Rétablir Monica
la source
1

Rubis , 54 52 octets

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

Cette version autorise nil (53 octets):

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

Essayez-le en ligne!

Asone Tuhid
la source
Le défi spécifie que le tableau ne contiendra que des entiers positifs et qu'il y aura au moins un élément. niln'est pas un entier positif.
Pavel
@ Pavel merci, j'ai vérifié mais je l'ai raté d'une manière ou d'une autre
Asone Tuhid