Grupos de artículos repetidos


10

Descripción del desafío

Dada una lista / matriz de elementos, muestra todos los grupos de elementos repetidos consecutivos.

Descripción de entrada / salida

Su entrada es una lista / matriz de elementos (puede suponer que todos son del mismo tipo). No necesita admitir todos los tipos que tiene su idioma, pero debe admitir al menos uno (preferiblemente int, pero tipos como boolean, aunque no muy interesantes, también están bien). Resultados de muestra:

[4, 4, 2, 2, 9, 9] -> [[4, 4], [2, 2], [9, 9]]
[1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4] -> [[1, 1, 1], [2, 2], [3, 3, 3], [4, 4, 4, 4]]
[1, 1, 1, 3, 3, 1, 1, 2, 2, 2, 1, 1, 3] -> [[1, 1, 1], [3, 3], [1, 1], [2, 2, 2], [1, 1], [3]]
[9, 7, 8, 6, 5] -> [[9], [7], [8], [6], [5]]
[5, 5, 5] -> [[5, 5, 5]]
['A', 'B', 'B', 'B', 'C', 'D', 'X', 'Y', 'Y', 'Z'] -> [['A'], ['B', 'B', 'B'], ['C'], ['D'], ['X'], ['Y', 'Y'], ['Z']]
[True, True, True, False, False, True, False, False, True, True, True] -> [[True, True, True], [False, False], [True], [False, False], [True, True, True]]
[0] -> [[0]]

En cuanto a las listas vacías, la salida no está definida, puede ser nada, una lista vacía o una excepción, lo que mejor se adapte a sus propósitos de golf. Tampoco tiene que crear una lista separada de listas, por lo que este también es un resultado perfectamente válido:

[1, 1, 1, 2, 2, 3, 3, 3, 4, 9] ->

1 1 1
2 2
3 3 3
4
9

Lo importante es mantener a los grupos separados de alguna manera.


¿Quizás sacamos una lista que tiene un valor separador especial?
xnor

@xnor: ¿Puedes dar un ejemplo? Una serie de ints por separado, por ejemplo, 0s sería una mala idea ya que no puede haber 0s en la entrada ...
shooqie

Por ejemplo, [4, 4, '', 2, 2, '', 9, 9]o [4, 4, [], 2, 2, [], 9, 9].
xnor

En realidad, qué tipos tenemos que soportar. ¿Pueden los elementos mismos ser listas? Me imagino que algunos idiomas tienen tipos incorporados que no se pueden imprimir o tienen una extraña verificación de igualdad.
xnor

@xnor: Sí, eso es lo que me preocupaba: si tu entrada tiene listas dentro, usar una lista vacía como separador puede ser confuso. Es por eso que incluí "puedes asumir que todos los artículos son del mismo tipo", para que puedas usar un tipo diferente como separador.
shooqie

Respuestas:




8

Retina , 15 8 bytes

Gracias a Lynn por sugerir un formato de E / S más simple.

!`(.)\1*

Trata la entrada como una lista de caracteres (y usa saltos de línea para separar grupos).

Pruébalo en línea!

Esto simplemente funciona haciendo coincidir grupos e imprimiéndolos todos (que usa la separación de salto de línea automáticamente).


Le pregunté sobre abbcccddda bb ccc dddser un formato de E / S aceptable, y el OP lo aprobó, ¿así que supongo que !`(.)\1*está bien?
Lynn

@ Lynn Oh, eso es mucho más simple, gracias.
Martin Ender

4

JavaScript (ES6), 39 37 bytes

f=
s=>s.replace(/(\w+) (?!\1\b)/g,`$1
`)
;
<input oninput=o.textContent=f(this.value);><pre id=o>

Funciona en cualquier token de palabras separadas por espacios. Guardado 2 bytes gracias a @ MartinEnder ♦. Lo mejor que puedo hacer para la entrada de matriz y el retorno es 68:

a=>a.reduce((l,r)=>(l==r?c.push(r):b.push(c=[r]),r),b=[c=[a[0]]])&&b


4

MATL , 9 bytes

Y'v"@Z}Y"

Y'     % Take input. Run-length encoding. Gives two row arrays: values and run lengths
v      % Concatenate vertically   
"      % For each column
  @Z}  %   Push column and split into its two elements
  Y"   %   Run-length decoding
       % End for. Implicitly display

La entrada es una serie de filas de números , con espacios o comas como separadores.

Pruébalo en línea! Prueba con números no enteros .


MATL, 11 bytes

lidgvYsG7XQ

La entrada es una matriz de columnas de números o caracteres , que se usa ;como separador.

Pruébalo en línea! Prueba con números arbitrarios . Prueba con personajes .

l     % Push 1
i     % Take input, say [4;4;2;2;9;9]
d     % Consecutive differences of input: [0;-2;0;7;0]
g     % Convert to logical: gives 1 if consecutive entries were different: [0;1;0;1;0]
v     % Concatenate vertically with the initial 1: [1;0;1;0;1;0]
Ys    % Cumulative sum. Each value is a group label: [1;1;2;2;3;3]
G     % Push input again
7XQ   % Split into horizontal arrays as indicated by group labels: {[4 4];[2 2];[9 9]}
      % Implicitly display

3

gs2, 2 bytes

c-

Pruébalo en línea!

ces una agrupación integrada que hace exactamente esto, por lo que lo llamamos en STDIN (que es una cadena, es decir, una lista de caracteres) y obtenemos una lista de cadenas. Lamentablemente, el resultado es indistinguible de la entrada, por lo que debemos agregar separadores. -(unirse por espacios) hace el truco.

Una respuesta alternativa es (2 bytes de CP437), que simplemente se ajusta ca una función anónima.


2

Brachylog , 13 bytes

:{s.dl1}fs.c?

Advertencia: esto es extremadamente ineficiente, y entenderá por qué en la explicación.

Esto espera una lista (por ejemplo [1:1:2:2:2]) como entrada. Los elementos dentro de la lista pueden ser prácticamente cualquier cosa.

Explicación

:{     }f       Find all ordered subsets of the Input with a unique element in them
  s.                Output is a subset of the input
    dl1             Output minus all duplicates has a length of 1 (i.e. one unique value)
         s.     Output is an ordered subset of those subsets
           c?   The concatenation of those subsets is the Input

Esto funciona solo por la forma en que se s - Subsetunifica: los conjuntos más pequeños están al final. Por lo tanto, lo primero que encuentra que se concatena con la entrada son las ejecuciones más largas, por ejemplo, [[1:1]:[2:2:2]]y no por ejemplo [[1:1]:[2:2]:[2]].


2

J , 13 bytes

<;.1~1,2~:/\]

Como J no admite matrices irregulares, cada ejecución de elementos iguales está encuadrada. La entrada es una matriz de valores y la salida es una matriz de matrices en caja.

Uso

   f =: <;.1~1,2~:/\]
   f 4 4 2 2 9 9
┌───┬───┬───┐
│4 4│2 2│9 9│
└───┴───┴───┘
   f 1 1 1 3 3 1 1 2 2 2 1 1 3
┌─────┬───┬───┬─────┬───┬─┐
│1 1 1│3 3│1 1│2 2 2│1 1│3│
└─────┴───┴───┴─────┴───┴─┘
   f 'ABBBCDXYYZ'
┌─┬───┬─┬─┬─┬──┬─┐
│A│BBB│C│D│X│YY│Z│
└─┴───┴─┴─┴─┴──┴─┘
   f 0
┌─┐
│0│
└─┘

Explicación

<;.1~1,2~:/\]  Input: s
            ]  Identify function to get s
       2       The constant 2
           \   Operate on each overlapping sublist of size 2
        ~:/      Are the two values unequal, 1 if true else 0
     1,        Prepend a 1 to it
<;.1~          Using the list just made, chop s at each index equal to 1 and box it
               Return this as the result

2

Dyalog APL , 9 bytes

⊢⊂⍨1,2≠/⊢

el argumento
⊂⍨particionado en
1el primer elemento
,y luego
2≠/donde los pares posteriores difieren
en el argumento


2

Python 2, 43 bytes

p=-1
for x in input():print"|"[:x^p],x,;p=x

Funciona en listas de booleanos. Ejemplo:

>> [True,True,False,False,False,True,False,True,False]
 True  True | False  False  False | True | False | True | False

Itera a través de la lista de entrada, almacenando el último elemento visto. Se imprime una barra separadora antes de cada elemento que es diferente a la anterior, verificada como que tiene bit xor ^de 0. La inicialización p=-1evita un separador antes del primer elemento.


Lástima que groupbysea ​​un dolor ...
Sp3000

2

CJam, 9 bytes

Dos soluciones:

{e`:a:e~}
{e`{(*}%}

Pruébalo aquí.

Explicación

e`   e# Run-length encode (gives a list of pairs [run-length value]).
:a   e# Wrap each pair in a singleton list.
:e~  e# Run-length decode each list.

O

e`   e# Run-length encode.
{    e# Map this block over each pair...
  (  e#   Pull out the run length.
  *  e#   Repeat the list containing only the value that many times.
}%


2

MATL, 8 7 bytes

Eliminado 1 byte gracias a @Suever

ly&Y'Y{

Funciona con enteros / flotantes / caracteres / booleanos / puntos de unicornio / otras entradas imaginarias.
Para booleanos, las entradas son T/F, las salidas son 1/0.

Pruébalo en línea!


Agrupado y repetido

ly&Y'Y{
l          % push 1 onto the stack
 y         % duplicate the input
  &Y'      % run-length encoding (secondary output only)
     Y{    % break up array into cell array of subarrays

1

C #, 117 bytes

void f(List<String>m){Console.Write(m[0]+String.Join("",m.GetRange(1,m.Count()-1).Select((i,j)=>i==m[j]?i:"\n"+i)));}

sin golf (no realmente)

    public static void f(List<String>m)
    {
        Console.Write(m[0]+String.Join("",m.GetRange(1,m.Count()-1).Select((i,j)=>i==m[j]?i:"\n"+i)));
    }

1

Pyth, 9 7 bytes

mr9]dr8

¡Crédito a @LeakyNun por 2 bytes!

Explicación:

             input
     r8      run-length decode
m            for each...
   ]d        ...treat each run as standalone encoded form...
 r9          ...decode 
             print

Respuesta anterior, 12 bytes

hf.Am!t{dT./

Olvidé la longitud de ejecución incorporada, pero creo que este es un enfoque correcto, así que lo mantuve.

Explicación:

                input
          ./    all possible partitions
 f       T      filter by...
  .A            ...whether all groups of integers...
    m!t{d       ...have length one after deduplication
h               get the first element (first one has no adjacent [1,1] and [1])
                print

Esto es 7 bytes
Leaky Nun

@LeakyNun ¡Oh cierto! Eso es genial.
busukxuan

1
Creo que esto funciona para 6.
FryAmTheEggman

@FryAmTheEggman Agradable abuso de m.
Leaky Nun

@FryAmTheEggman Wow, no entiendo oO
busukxuan

1

Pyth , 36 35 bytes

VQIqNk=hZ).?=+Y]*]kZ=Z1=kN;t+Y]*]kZ

Enlace de prueba

Editar: explicación:

                                      standard variables: Y=[], Z=0, k='', Q=input
VQ                                    iterate over input
  IqNk                                if the current entity is equal to k:
      =hZ)                            increase Z.
          .?                          else:
               ]*]kZ                  list of length Z filled with k
            =+Y                       add it to Y
                    =Z1               set Z to 1
                       =kN            set k to the current entity
                          ;           end loop
                              ]*]kZ   list of length Z filled with k
                            +Y        add it to Y
                           t          implicitly print the tail of Y (removing the first element)

1

Retina , 24 22 bytes

2 bytes gracias a Martin Ender.

Una respuesta 15 bytes ya existe, por lo que este es sólo otro enfoque que cuesta más bytes.

S-`(?<=(\d+)) (?!\1\b)

Pruébalo en línea!

Se divide en espacios cuyo número anterior difiere del procedimiento.

Esta es una demostración de lookarounds.


1

05AB1E, 13 bytes

¬svyÊi¶}yðJ?y

Explicado

¬s             # push first element of list to stack and swap with input
  v            # for each X in input
   yÊi¶}       # if X is different from last iteration, push a newline
        yðJ?   # push X followed by a space to stack and join stack to string
            y  # push X to stack for next iterations comparison

Debería funcionar para cualquier lista.
Probado en int y char.

Pruébalo en línea


1

Swift, 43 bytes

var p=0;i.map{print($0==p ?"":",",$0);p=$0}

Supone que i es una matriz de objetos equiparables; funciona para cualquier cosa, desde ints hasta cadenas y objetos personalizados. Un poco descarado, ya que la salida contiene muchas líneas nuevas, pero hacerla más bonita costaría bytes.

Versión más bonita y sin golf:

var prev = Int.max // unlikely to be the first element, but not the end of the world if it happens to be.
i.map { n in
    print(n == prev ? " " : "\n•", n, terminator: "")
    prev = n
}

Esta versión imprime cada grupo en una nueva línea a expensas de más código.

Ideas para mejorar

i.reduce(0){print($0==$1 ?"":"•",$1);return $1}

Esta versión tiene 47 bytes, pero es un enfoque diferente, ¿quizás hay algo para optimizar allí? El mayor problema es la declaración de devolución.


1

C, 88 77 bytes

Movido el strmcmp interior de los printf 11 bytes de ahorro

f(char**a){*a++;char*x;for(;*a;x=*a++)printf(strcmp(*a,x)?"\n%s ":"%s ",*a);}

Uso:

f(char**a){*a++;char*x;for(;*a;x=*a++)printf(strcmp(*a,x)?"\n%s ":"%s ",*a);}
main(c,v)char**v;{f(v);}

Entrada de muestra:

(parámetros de línea de comando)

1 1 1 1 2 2 2 2 3 3 3 3 4 5 6 7777

Salida de muestra:

1 1 1 1
2 2 2 2
3 3 3 3
4
5
6
7777

Probado en:

gcc 4.4.7 (Red Hat 4.4.7-16)  - OK
gcc 5.3.0 (Cygwin)            - Segmetation Fault
gcc 4.8.1 (Windows)           - OK

Estoy tratando de arreglar la falla de segmentación 5.3.0.

88 Versión

f(char**a){*a++;char*x;for(;*a;x=*a++)strcmp(*a,x)?printf("\n%s ",*a):printf("%s ",*a);}

1

Java 134 bytes

void a(String[]a){int i=0,l=a.length;for(;i<l-1;i++)System.out.print(a[i]+((a[i].equals(a[i+1]))?" ":"\n"));System.out.print(a[l-1]);}

itera y decide si se separa con una nueva línea o un espacio.


para empezar, podría eliminar publicy staticpalabras clave. También puede quitar las llaves en el bucle for
user902383

Hecho en user902383
Rohan Jhunjhunwala el

1

ListSharp , 134 bytes

STRG l = READ[<here>+"\\l.txt"]
[FOREACH NUMB IN 1 TO l LENGTH-1 AS i]
{
[IF l[i] ISNOT l[i-1]]
STRG o=o+"\n"
STRG o=o+l[i]
}
SHOW = o

ListSharp no admite funciones, por lo que la matriz se guarda en un archivo local llamado l.txt expediente


1

Rubí , 24 bytes

En Arrayinstancias de ruby tienen un método incorporadogroup_by

Entonces la solución será:

a.group_by{|x| x}.values

0

TSQL, 132 bytes

Esto es un poco diferente de las otras respuestas: sql no tiene matrices, la entrada obvia para sql es una tabla.

Golfizado:

DECLARE @ table(i int identity, v varchar(20))
INSERT @ values(1),(1),(1),(3),(3),(1),(1),(2),(2),(2),(1),(1),(3)

SELECT REPLICATE(v+' ',COUNT(*))FROM(SELECT i,i-row_number()over(partition
by v order by i)x,v FROM @)z GROUP BY x,v ORDER BY max(i)

Sin golf:

DECLARE @ table(i int identity, v varchar(20))
INSERT @ values(1),(1),(1),(3),(3),(1),(1),(2),(2),(2),(1),(1),(3)

SELECT
  REPLICATE(v+' ',COUNT(*))
FROM 
  (
     SELECT
       i,
       i-row_number()over(partition by v order by i)x,
       v
     FROM @
  )z
GROUP BY
  x,v
ORDER BY
  max(i)

Violín


0

Perl 5-39 bytes

print$_.($/)[$_ eq@a[++$-]]for@a=sort@a

0

Pyke, 2 bytes (no competitivo)

Solo admite enteros

$f

Pruébalo aquí!

split_at(input, delta(input))

Se agregó el nodo split_at, divide la entrada cuando el segundo argumento es verdadero


0

sed, 33 23 + 1 = 24 bytes

s/([^ ]+)( \1)* */&\n/g

Necesita la -ropción

Ejemplo de uso:

$ echo '1 1 1 2 2 3 3 3 4 9 9' | sed -r 's/([^ ]+)( \1)* */&\n/g'
1 1 1 
2 2 
3 3 3 
4 
9 9

0

JavaScript (ES6), 56

Entrada: conjunto de números o cadenas

Salida: matriz de matrices

Primera vez que usa una comparación exacta en código de golf

a=>a.map(x=>x!==p?o.push(g=[p=x]):g.push(x),p=o=g=[])&&o

0

Clojure, 19 bytes

#(partition-by + %)

Es una función integrada, pero requiere una función de mapeo. En este caso, +sirve como una función de identidad.


0

Javascript (usando una biblioteca externa) (178 bytes)

(s)=>_.From(s).Aggregate((t,e)=>{if(0===t.Items.length)return t.Items.push([e]),t;var s=t.Items[t.Items.length-1];return s[0]===e?(s.push(e),t):(t.Items.push([e]),t)},{Items:[]})

Descargo de responsabilidad: estoy usando una biblioteca que escribí para implementar LINQ de C # en JS. No me ayudó exactamente a ganar, pero bueno

Imagen

Imagen2

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.