Énumérer chaque série de numéros identiques sur place


27

Étant donné une liste d'entiers strictement positifs, parcourez chaque nombre distinct et remplacez-en toutes les occurrences par des indices successifs (zéro ou un basés) d'une nouvelle série.

Exemples

[][]/[]

[42][0]/[1]

[7,7,7][0,1,2]/[1,2,3]

[10,20,30][0,0,0]/[1,1,1]

[5,12,10,12,12,10][0,0,0,1,2,1]/[1,1,1,2,3,2]

[2,7,1,8,2,8,1,8,2,8][0,0,0,0,1,1,1,2,2,3]/[1,1,1,1,2,2,2,3,3,4]

[3,1,4,1,5,9,2,6,5,3,5,9][0,0,0,1,0,0,0,0,1,1,2,1]/[1,1,1,2,1,1,1,1,2,2,3,2]


2
Donc, fondamentalement, le nombre de fois où la séquence est apparue jusqu'à présent?
Jo King

1
@JoKing Oui, c'est une autre façon de le dire, mais "jusqu'à présent" implique une base zéro, et "jusqu'à et y compris" implique une base. Je voulais garder le choix.
Adám

Réponses:


23

JavaScript (ES6), 26 octets

1 indexé.

a=>a.map(o=x=>o[x]=-~o[x])

Essayez-le en ligne!

Commenté

a =>                // a[] = input array
  a.map(o =         // assign the callback function of map() to the variable o, so that
                    // we have an object that can be used to store the counters
    x =>            // for each value x in a[]:
      o[x] = -~o[x] //   increment o[x] and yield the result
                    //   the '-~' syntax allows to go from undefined to 1
  )                 // end of map()

1
Je n'ai aucune idée de comment cela fonctionne, mais ça a l'air élégant.
Adám

Je ne l'ai jamais vu -~auparavant - c'est un joyau absolu.
DaveMongoose

Alternativement, il est possible d'utiliser apour stocker les valeurs, mais il est requis pour -/ ~l'index afin qu'aucun octet ne soit enregistré.
user202729


1
@DaveMongoose -~est en fait une alternative couramment utilisée +1(car il a une priorité différente) dans de nombreuses langues
ASCII uniquement le

10

R , 27 octets

function(x)ave(x,x,FUN=seq)

Essayez-le en ligne!

Explication:

ave(x,x,FUN=seq)divise le vecteur xen sous-vecteurs en utilisant les valeurs de xcomme clés de regroupement. Ensuite, la seqfonction est appelée pour chaque groupe et chaque résultat est réorganisé dans la position de groupe d'origine.

Mieux vaut voir un exemple:

x <- c(5,7,5,5,7,6)
ave(x, x, FUN=seq) # returns 1,1,2,3,2


 ┌───┬───┬───┬───┬───┐
 │ 57557 │
 └───┴───┴───┴───┴───┘            
   |   |   |    |  ||   ▼    ▼  |
 GROUP A : seq(c(5,5,5)) = c(1,2,3)
   |   |   |    |  ||   ▼    ▼  |
 ┌───┐ | ┌───┬───┐ |1|23|
 └───┘ | └───┴───┘ |
       ▼           ▼
 GROUP B : seq(c(7,7)) = c(1,2)
       |           |
       ▼           ▼
     ┌───┐       ┌───┐
     │ 1 │       │ 2 │
     └───┘       └───┘ 

   |   |   |   |   |
   ▼   ▼   ▼   ▼   ▼ 
 ┌───┬───┬───┬───┬───┐
 │ 11232 │
 └───┴───┴───┴───┴───┘  

Remarque :

seq(y)La fonction retourne une séquence 1:length(y)au cas où yhas length(y) > 1, mais renvoie une séquence de 1:y[1]if yne contient qu'un seul élément.
Ce n'est heureusement pas un problème car dans ce cas R - se plaignant de nombreux avertissements - ne sélectionne que la première valeur qui est d'ailleurs ce que nous voulons :)


2
Brillant! Je vais ajouter une prime pour cela. Jamais vu aveauparavant.
Giuseppe

Je suis honoré, merci beaucoup! :)
digEmAll

6

MATL , 4 octets

&=Rs

Cette solution est basée sur 1

Essayez-le sur MATL Online !

Explication

Utilise [1,2,3,2]comme exemple

    # Implicitly grab the input array of length N
    #
    #   [1,2,3,2]
    #
&=  # Create an N x N boolean matrix by performing an element-wise comparison
    # between the original array and its transpose:
    #
    #     1 2 3 2
    #     -------
    # 1 | 1 0 0 0
    # 2 | 0 1 0 1
    # 3 | 0 0 1 0
    # 2 | 0 1 0 1
    #
R   # Take the upper-triangular portion of this matrix (sets below-diagonal to 0)
    #
    #   [1 0 0 0
    #    0 1 0 1
    #    0 0 1 0
    #    0 0 0 1]
    #
s   # Compute the sum down the columns
    #
    #   [1,1,1,2]
    #
    # Implicitly display the result

2
ah, je savais qu'il y avait un vieux problème qui m'a fait penser à quelque chose de similaire, c'est Unique is Cheap, et la solution MATL il y a un caractère différent!
Giuseppe

5

APL (Dyalog Unicode) , 7 octets

Un grand merci à H.PWiz, Adám et dzaima pour toute leur aide dans le débogage et la correction de cela.

+/¨⊢=,\

Essayez-le en ligne!

Explication

La version non tacite de 10 octets sera plus facile à expliquer en premier

{+/¨⍵=,\⍵}

{         } A user-defined function, a dfn
      ,\⍵  The list of prefixes of our input list 
           (⍵ more generally means the right argument of a dfn)
           \ is 'scan' which both gives us our prefixes 
           and applies ,/ over each prefix, which keeps each prefix as-is
    ⍵=     Checks each element of  against its corresponding prefix
           This checks each prefix for occurrences of the last element of that prefix
           This gives us several lists of 0s and 1s
 +/¨       This sums over each list of 0s and 1s to give us the enumeration we are looking for

La version tacite fait trois choses

  • Tout d'abord, il supprime l'instance de used in ,\⍵as ,\à droite par lui-même peut implicitement comprendre qu'il est censé fonctionner sur le bon argument.
  • Deuxièmement, pour ⍵=, nous remplaçons le par , qui représente le bon argument
  • Troisièmement, maintenant que nous n'avons pas d'arguments explicites (dans ce cas, ), nous pouvons supprimer les accolades {}car les fonctions tacites ne les utilisent pas


5

J , 7 octets

1#.]=]\

Essayez-le en ligne!

1 indexé.

Explication:

]\ all the prefixes (filled with zeros, but there won't be any 0s in the input):
   ]\ 5 12 10 12 12 10
5  0  0  0  0  0
5 12  0  0  0  0
5 12 10  0  0  0
5 12 10 12  0  0
5 12 10 12 12  0
5 12 10 12 12 10

]= is each number from the input equal to the prefix:
   (]=]\) 5 12 10 12 12 10
1 0 0 0 0 0
0 1 0 0 0 0
0 0 1 0 0 0
0 1 0 1 0 0
0 1 0 1 1 0
0 0 1 0 0 1

1#. sum each row:
   (1#.]=]\) 5 12 10 12 12 10
1 1 1 2 3 2

K (oK) , 11 10 octets

-1 octet grâce à ngn!

{+/'x=,\x}

Essayez-le en ligne!


1
Hé, vous êtes heureux d'avoir rendu les données strictement positives…
Adám

@ Adám Oui, sinon j'aurais besoin d'encadrer les préfixes :)
Galen Ivanov

1
en k: ='->=
ngn






2

R , 41 octets

function(x)diag(diffinv(outer(x,x,"==")))

Essayez-le en ligne!

Curieusement, le retour d'un indice de base zéro est plus court dans R.


Encore une fois Giuseppe, votre connaissance supérieure de R m'a battu. J'avais une méthode décemment ingénieuse à 60 octets, mais hélas, ce n'était pas suffisant!
Sumner18

@ Sumner18 poste quand même! J'apprends toujours beaucoup des approches des autres et obtenir des commentaires est le moyen le plus rapide d'apprendre!
Giuseppe

Merci pour l'encouragement! J'ai publié le mien maintenant et je suis toujours ouvert aux suggestions d'amélioration!
Sumner18

2

Rubis, 35 octets

->a{f=Hash.new 0;a.map{|v|f[v]+=1}}

C'est assez banal, malheureusement - créez un hachage qui stocke le total pour chaque entrée rencontrée jusqu'à présent.

Quelques autres options amusantes qui n'étaient malheureusement pas assez courtes:

->a{a.dup.map{a.count a.pop}.reverse}   # 37
->a{i=-1;a.map{|v|a[0..i+=1].count v}}  # 38

2

R , 62 43 octets

x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z

-19 octets grâce à Giuseppe, en supprimant lequel, et le tableau, et seulement de légères modifications à l'implémentation

Original

x=z=scan();for(i in names(r<-table(x)))z[which(x==i)]=1:r[i];z

Je ne peux pas rivaliser avec les connaissances de Giuseppe, donc ma soumission est un peu plus longue que la sienne, mais en utilisant mes connaissances de base, j'ai senti que cette solution était plutôt ingénieuse.

r<-table(x) compte le nombre de fois que chaque numéro apparaît et le stocke dans r, pour référence future

names() obtient les valeurs de chaque entrée unique dans la table, et nous itérons sur ces noms avec une boucle for.

La partie restante vérifie quelles entrées sont égales aux itérations et stocke une séquence de valeurs (de 1 au nombre d'entrées de l'itération)

Essayez-le en ligne!


vous pouvez supprimer le which()pour enregistrer 7 octets.
Giuseppe

Votre utilisation de 1:r[i]m'a donné l'idée de supprimer table()entièrement: x=z=scan();for(i in x)z[y]=1:sum(y<-x==i);z43 octets! C'est une belle approche!
Giuseppe

On dirait qu'aucun de nous ne peut rivaliser avec la connaissance R de digEmAll !
Giuseppe

J'ai vu ça et j'ai été absolument sidéré!
Sumner18

2

Haskell , 44 octets

([]#)
x#(y:z)=sum[1|a<-x,a==y]:(y:x)#z
_#e=e

Essayez-le en ligne!

Explication

Parcourt la liste de gauche à droite en conservant la liste xdes éléments visités, initialement []:

Pour chaque rencontre d'un ycompte, tous les éléments égaux de la liste x.


1
Un peu plus longtemps mais peut-être quand même intéressant: (#(0*));(x:r)#g=g x:r# \y->0^abs(y-x)+g y;e#g=e essayez-le en ligne!
Laikoni

@Laikoni: Comment avez-vous pensé à ça, vous devriez le publier totalement!
ბიმო


2

Perl 6 , 15 octets

*>>.&{%.{$_}++}

Essayez-le en ligne!

Vous pouvez déplacer le ++vers avant le %pour un index basé sur un.

Explication:

*>>.&{        }  # Map the input to
      %          # An anonymous hash
       .{$_}     # The current element indexed
            ++   # Incremented

2

Haskell , 47 46 octets

(#(*0))
(x:r)#g=g x:r# \y->0^(y-x)^2+g y
e#g=e

Essayez-le en ligne!

Une approche différente de la réponse de BMO qui s'est avérée un peu plus longue. (Et emprunte gentiment leur belle combinaison de test.)

L'idée est de parcourir la liste d'entrée et de garder une trace du nombre de fois où chaque élément s'est produit en mettant à jour une fonction g. Non golfé:

f (const 0)
f g (x:r) = g x : f (\ y -> if x==y then 1 + g y else g y) r
f g []    = []

Deux opportunités de golf intéressantes se sont présentées. D'abord pour la valeur initiale de g, une fonction constante qui ignore son argument et renvoie 0:

const 0  -- the idiomatic way
(\_->0)  -- can be shorter if parenthesis are not needed
min 0    -- only works as inputs are guaranteed to be non-negative
(0*)     -- obvious in hindsight but took me a while to think of

Et d'autre part une expression sur des variables xet yqui donne 1si xégal yet 0sinon:

if x==y then 1else 0  -- yes you don't need a space after the 1
fromEnum$x==y         -- works because Bool is an instance of Enum
sum[1|x==y]           -- uses that the sum of an empty list is zero
0^abs(x-y)            -- uses that 0^0=1 and 0^x=0 for any positive x
0^(x-y)^2             -- Thanks to  Christian Sievers!

Il pourrait encore y avoir des moyens plus courts. Quelqu'un a une idée?


1
Vous pouvez utiliser 0^(x-y)^2.
Christian Sievers


1

Rubis , 34 octets

->a{r=[];a.map{|x|(r<<x).count x}}

Essayez-le en ligne!


Je ne peux pas croire que j'ai essayé ->a{i=-1;a.map{|v|a[0..i+=1].count v}}et que je n'ai pas pensé à construire un nouveau tableau, lol. Bon travail.
DaveMongoose

1

bash, 37 24 octets

f()(for x;{ r+=$[a[x]++]\ ;};echo $r)

TIO

si elle est valide, il y a aussi cette variation, comme suggéré par DigitalTrauma

for x;{ echo $[a[x]++];}

TIO


1
Passez la liste sous la ligne de commande args - tio.run/##S0oszvj/Py2/SKHCuporNTkjX0ElOjG6IlZbO5ar9v///8b/… - seulement 24 octets.
Digital Trauma

@DigitalTrauma, merci cependant je ne sais pas si cela a enfreint les règles. aussi car il a été demandé de remplacer la liste et devrait peut-être être quelque chose comme tio.run/…
Nahuel Fouilleul

2
@NahuelFouilleul C'est bien, les programmes complets sont également autorisés, et c'est une méthode valide d'entrée / sortie d'une liste (IMO)
ASCII uniquement

1

Perl 5, 11 octets

$_=$h{$_}++

TIO

explications après commentaire

  • $_la variable spéciale de perl contenant la ligne courante lors du bouclage sur l'entrée ( -pou-n commutateurs)
  • $h{$_}++ dynamise automatiquement la carte %h et crée une entrée avec clé $_et incréments et donne la valeur avant incrément
  • la variable spéciale est imprimée à cause du -pcommutateur, le -lcommutateur supprime la fin de ligne en entrée et ajoute la fin de ligne en sortie

Cela a l'air incroyable. Soin d'expliquer?
Adám

@ Adám, merci pour vos commentaires, bien sûr, fait
Nahuel Fouilleul



1

Attaché , 23 octets

{`~&>Zip[_,_[0:#_::0]]}

Essayez-le en ligne!

Explication

{`~&>Zip[_,_[0:#_::0]]}
{                     }    _: input (e.g., [5, 12, 10, 12, 12, 10])
             0:#_          range from 0 to length of input (inclusive)
                           e.g., [0, 1, 2, 3, 4, 5, 6]
                 ::0       descending range down to 0 for each element
                           e.g., [[0], [1, 0], [2, 1, 0], [3, 2, 1, 0], [4, 3, 2, 1, 0], [5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]
           _[       ]      get input elements at those indices
                           e.g., [[5], [12, 5], [10, 12, 5], [12, 10, 12, 5], [12, 12, 10, 12, 5], [10, 12, 12, 10, 12, 5], [nil, 10, 12, 12, 10, 12, 5]]
     Zip[_,          ]     concatenate each value with this array
                           e.g., [[5, [5]], [12, [12, 5]], [10, [10, 12, 5]], [12, [12, 10, 12, 5]], [12, [12, 12, 10, 12, 5]], [10, [10, 12, 12, 10, 12, 5]]]
   &>                      using each sub-array spread as arguments...
 `~                            count frequency
                               e.g. [12, [12, 10, 12, 5]] = 12 ~ [12, 10, 12, 5] = 2

1

C (gcc) , 65 62 octets

c,d;f(a,b)int*a;{for(;c=d=b--;a[b]=d)for(;c--;d-=a[c]!=a[b]);}

Essayez-le en ligne!

-2 octets grâce à ASCII uniquement


Cela semblait trop simple, mais je n'arrivais pas à raccourcir avec une approche différente.



@ ASCII uniquement est-ce une réponse valide? Aucun en-tête inclus, aucune déclaration, c'est un extrait de code plus de nombreux avertissements bien qu'il soit généré.
AZTECCO

Les avertissements @AZTECCO sont corrects (stderr est ignoré), tant qu'il fait ce qu'il devrait, c'est acceptable. notez que cela s'agit d' une déclaration de fonction, plus quelques déclarations de variables - vous pouvez la placer n'importe où en tant qu'expression de niveau supérieur et elle se compilera très bien. beaucoup de réponses c (et celles des langues avec une syntaxe moins stricte) n'ont généralement pas mal de mises en garde en raison de bytesaves qui ne sont pas un bon style de code
ASCII seulement

D'accord, je peux comprendre, mais il y a encore quelque chose qui ne me convient pas. Si nous voulons tester avec un ensemble différent (en taille), nous devons modifier le code, même dans la boucle d'impression, plus l'entrée doit être juste l'ensemble, pas sa taille. "Étant donné une liste d'entiers strictement positifs ... "Je pense donc que la contribution ne devrait être que la liste.
AZTECCO

@AZTECCO ne sait pas si cette discussion devrait faire partie des commentaires de cette réponse, mais vous voudrez peut-être jeter un œil à la méta - en particulier sur les E / S et les formats de réponse .
attinat

1

K (ngn / k) , 18 octets

(,/.!'#'=x)@<,/.=x

Essayez-le en ligne!


VIEILLE APPROCHE

K (ngn / k) , 27 23 22 octets

{x[,/.=x]:,/.!'#'=x;x}

Essayez-le en ligne!


ce n'est pas joli ... solution rapide et sale, je vais affiner cela plus tard quand j'aurai la chance de penser à une meilleure approche

explication:

  • =xrenvoie un dict où les clés sont des éléments de x et les valeurs leurs indices ( 3 1 4 5 9 2 6!(0 9;1 3;,2;4 8 10;5 11;,6;,7))
  • i: assigner dict à i
  • #:'compter les valeurs pour chaque clé ( 3 1 4 5 9 2 6!2 2 1 3 2 1 1)
  • !:'énumérer chaque valeur ( 3 1 4 5 9 2 6!(0 1;0 1;,0;0 1 2;0 1;,0;,0))
  • ,/.:extraire des valeurs et aplatir la liste ( 0 1 0 1 0 0 1 2 0 1 0 0)
  • x[,/.:i]: extraire les indices de i, aplatir et attribuer chaque valeur de la liste de droite à ces indices

ennuyeux, la liste est mise à jour mais une valeur nulle est retournée par l'affectation, donc je dois retourner la liste après le point-virgule ( ;x)

modification: suppression des deux-points superflus

edit2: suppression de l'affectation inutile


0

Retina 0.8.2 , 30 octets

\b(\d+)\b(?<=(\b\1\b.*?)+)
$#2

Essayez-le en ligne! Le lien inclut des cas de test. 1 indexé. Explication: La première partie de l'expression régulière correspond à tour de rôle à chaque entier de la liste. Le groupe de lookbehind correspond à chaque occurrence de cet entier sur cette ligne jusqu'à et y compris l'entier actuel. L'entier est ensuite remplacé par le nombre de correspondances.


0

Lot, 61 octets

@setlocal
@for %%n in (%*)do @set/ac=c%%n+=1&call echo %%c%%

1 indexé. Étant donné que la substitution de variables se produit avant l'analyse, la set/acommande finit par incrémenter le nom de variable donné en concaténant la lettre cavec l'entier de la liste (variables numériques par défaut à zéro dans Batch). Le résultat est ensuite copié dans un autre entier pour faciliter la sortie (plus précisément, il enregistre un octet).



0

Japt, 8 octets

£¯YÄ è¶X

Essayez-le ici

£¯YÄ è¶X
             :Implicit input of array U
£            :Map each X at 0-based index Y
 ¯           :  Slice U to index
  YÄ         :    Y+1
     è       :  Count the elements
      ¶X     :    Equal to X
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.