Reagrupando listas rápidamente

17

La agrupación toma una lista y la divide en nuevas listas de elementos adyacentes iguales. Por ejemplo

[1,1,2,1,1] -> [[1,1],[2],[1,1]]

Si luego tomas la longitud de estos grupos, obtienes una nueva lista de enteros

[1,1,2,1,1] -> [2,1,2]

Su tarea es escribir un programa que tome una lista de enteros positivos y encuentre la cantidad de veces que puede agruparlo y extenderlo antes de que la lista resultante tenga un solo elemento. Por ejemplo, la lista [1,2,3,3,2,1]puede reagruparse 4 veces

[1,2,3,3,2,1]
[1,1,2,1,1]
[2,1,2]
[1,1,1]
[3]

Este es el por lo que las respuestas se puntuarán en bytes con menos bytes mejor.

Casos de prueba

[1,2,3,3,2,1] -> 4
[1,2,3,4,5,6,7] -> 2
[1,1,1,1,1,1] -> 1
[2] -> 0
[1,2,4] -> 2
[1,2,2,1,1,2] -> 4
[1,2,2,1,1,2,1,2,2] -> 5
[1] -> 0
Post Rock Garf Hunter
fuente
3
Esto es básicamente codificación de longitud de ejecución sin almacenar los valores.
12Me21
[1]es una entrada válida y debe dar 0, ¿correcto?
ETHproductions
@ETHproductions Sí, lo agregaré porque es un caso un poco complicado.
Post Rock Garf Hunter

Respuestas:

3

Japt , 12 bytes

ÊÉ©1+ßUò¦ ml

¡Pruébelo en línea!

Explicación

 Ê É © 1+ßUò¦  ml
Ul -1&&1+ßUò!= ml    Ungolfed
                     Implicit: U = input array
Ul -1                Take U.length - 1.
     &&              If this is non-zero:
          Uò!=         Split U between non-equal elements.
               ml      Take the length of each run of equal elements.
         ß             Run the entire program again on the resulting array.
       1+              Add one to the return value.

La recursión es un enfoque realmente no convencional para Japt, pero parece ser 4 bytes más corto que la próxima alternativa ...

ETHproducciones
fuente
@Shaggy Mi versión de 16 bytes F.a()aún es accesible a través del historial de revisiones. ¡Sin embargo, me encantaría ver a tu 14 byter!
ETHproductions
3

Brachylog , 12 bytes

;.{ḅlᵐ}ⁱ⁾l1∧

Pruébalo en línea!

Explicación

;.{   }ⁱ⁾        Iterate Output times the following predicate on the input:
   ḅ               Group consecutive equal elements together
    lᵐ             Map length
         l1∧     The result of this iteration must have length 1
Fatalizar
fuente
2

C (gcc) , 108 bytes

j,k,n;f(A,l)int*A;{for(j=k=n=0;j<l;j++)if(n++,A[j]-A[k])A[k++]=--n,A[k]=A[j],n=1;A=l>1?-~f(A,k,A[k++]=n):0;}

Pruébalo en línea!

Explicación

j,k,n;                // array pos, group pos, group val
f(A,l)int*A;{         // function takes array and length
 for(j=k=n=0;j<l;j++) // initialize, loop through array
  if(n++,             // increase n (*), check if group ended
  A[j]-A[k])          // group ended
   A[k++]=--n,        // advance group pos, decrease n, counteracting (*)
   A[k]=A[j],         // store new group type
   n=1;               // group is at least one long
 A=l>1?               // check if array length is larger than one
  -~f(A,k,A[k++]=n)   // fix last group length, enter recursion
  :0;}                // array length is less than two, return zero

Pruébalo en línea!

Jonathan Frech
fuente
2

JavaScript (ES6), 67 65 63 bytes

f=a=>a[1]?1+f(q=j=i=[],a.map(x=>x^a[++i]?j=!q.push(++j):++j)):0

Por extraño que parezca, JavaScript y Japt parecen tener el mismo algoritmo más corto por una vez ...

ETHproducciones
fuente
2

K (oK) , 20 19 bytes

Solución:

#2_{#:'(&~~':x)_x}\

Pruébalo en línea!

Ejemplos:

#2_{#:'(&~~':x)_x}\1 2 3 3 2 1
4
#2_{#:'(&~~':x)_x}\1 2 3 4 5 6 7
2
#2_{#:'(&~~':x)_x}\1 1 1 1 1 1
1
#2_{#:'(&~~':x)_x}\1#2
0
#2_{#:'(&~~':x)_x}\1 2 4
2

Explicación:

Este es bastante simple, aunque me pregunto si hay un enfoque aún mejor ... Encuentre los índices en los que difiere la entrada, divídalos en esos índices y luego cuente la longitud de cada sublista. Iterar hasta que los resultados converjan a 1.

#2_{#:'(&~~':x)_x}\ / the solution
   {             }\ / scan over lambda until results converge
                x   / implicit input
               _    / cut at indices
       (      )     / do this together
         ~~':x      / differ... not (~) match (~) each-previous (':) x)
        &           / indices where true
    #:'             / count (#:) each (')
 2_                 / drop first two results
#                   / count result

Notas:

La siguiente solución de 14 bytes funciona para todos, excepto una lista de un solo elemento:

#1_(-':&~~':)\

Pruébalo en línea!

callejero
fuente
2

J , 25 23 bytes

1 byte guardado gracias a streetster

1 byte guardado gracias a FrownyFrog

2#@}.#;.1@(0,2=/\])^:a:

Pruébalo en línea!

Solución inicial:

_2+[:#(#;.1~1,2~:/\])^:a:

Pruébalo en línea!

Explicación

      (               )^:a: - repeat until result stops changing, store each iteration
        ;.1~                - cut the input (args swapped)              
            1,2~:/\]      - where the items are no longer the same
       #                    - and take the length of the sublists
 2+[:#                      - finally subtract 2 from the number of steps
Galen Ivanov
fuente
1
¿Puedes hacer 'soltar dos' y luego 'contar' en lugar de _2+guardar un byte?
StreetSter
1
Creo que #;.1@(0,2=/\])ahorra 1 byte.
FrownyFrog
@ FrownyFrog Sí, lo hace. ¡Gracias!
Galen Ivanov
@streetster Sí, ayuda a guardar un byte. ¡Gracias!
Galen Ivanov
2

Stax , 9 bytes

ÆÑfá╒]`*Ä

Ejecútelo y depúrelo en línea

La representación ascii del mismo programa es esta.

{D}{|RMHgf%

Esto utiliza una característica stax llamada generador que produce valor de acuerdo con la transformación y los bloques de filtro.

{ }            the filter for the generator
 D             tail of array; this is truthy for length >= 2
   {    gf     generator block - termination condition is when the filter fails
    |R         run-length encode into pairs [element, count]
      M        transpose matrix
       H       last element
          %    length of final generated array
recursivo
fuente
2

Python 2 , 84 bytes

f=lambda a:len(a)>1and-~f(eval(''.join('1'+',+'[x==y]for x,y in zip(a,a[1:]))+'1,'))

Pruébalo en línea!

¿Cómo?

fes una función recursiva que, si es su entrada, atiene una longitud de 2 o más ( len(a)>1) devuelve 1+f(x)* donde xes la longitud del grupo de a; mientras que si su entrada es de longitud 1 o 0 devuelve False(igual a 0 en Python), esto se debe a que el lado derecho del andno se evalúa cuando el izquierdo es falsey.

* -~f(x)es -(-1 - f(x))pero puede colindarse con lo andcontrario 1+f(x)o f(x)+1)

Las longitudes de grupo se calculan creando un código que luego se evalúa con eval(...). El código creado es algo parecido a lo 1,1,1+1+1,1,1+1,1,que se evalúa como una tupla (1,1,3,1,2,1).

El código se crea comprimiendo ay asin su encabezado ( ...for x, y in zip(a,a[1:])haciendo xy ycada uno de los pares adyacentes adentro a. Si el par es igual se x==yevalúa como True(1) de lo contrario False(0) - este resultado se usa para indexar en el ,+ rendimiento de la cadena +y ,respectivamente y cada el carácter resultante está precedido por un 1( '1'+...): todo el asunto tiene un final final 1,adjunto, por ejemplo, si así afuera [5,5,2,9,9,9], los x,ypares estarían (5,5)(5,2)(2,9)(9,9)(9,9)haciendo las igualdades que 10011los caracteres +,,++, que con el 1s anterior se convierte 1+1,1,1+1+y el final final1, la toma de1+1,1,1+1+1,que se evalúa (2,1,3)según sea necesario.

Tenga en cuenta que el seguimiento ,garantiza que una entrada con un solo grupo se evalúe como una tupla en lugar de un número entero (es decir, [3,3]-> 1+1,-> en (2)lugar de [3,3]-> 1+1-> 2)

Jonathan Allan
fuente
1

Perl 5 , 53 50 49 45 bytes

Incluye +3 para-p

Dé la lista de números como una línea en STDIN

#!/usr/bin/perl -p
s%%$\+=1<s:\d+:$.++x($'-$&and$.=1):eg%eg}{

Pruébalo en línea!

Ton Hospel
fuente
1

Cáscara , 8 bytes

-1 byte gracias a @Zgarb!

←Vε¡(mLg

Pruébalo en línea!

Explicación

←Vε¡(mLg)  -- example input: [1,2,3,3,2,1]
   ¡(   )  -- repeatedly apply the function & collect results
    (  g)  -- | group: [[1],[2],[3,3],[2],[1]]
    (mL )  -- | map length: [1,1,2,1,1]
           -- : [[1,2,3,3,2,1],[1,1,2,1,1],[2,1,2],[1,1,1],[3],[1],[1],...
 V         -- index where
  ε        -- | length is <= 1: [0,0,0,0,1,1...
           -- : 5
←          -- decrement: 4
ბიმო
fuente
1
←Vεes una verificación más corta para encontrar el índice de la lista singleton.
Zgarb
1

Jalea , 10 bytes

ŒgL€$ḊпL’

Pruébalo en línea!

Dennis
fuente
Esto falla por[1] . Debería poder solucionarlo utilizando dos colas / pops en lugar de_2
Sr. Xcoder
ÐĿno fue una buena opción en primer lugar ... lo reemplazó con un bucle while.
Dennis
1

05AB1E , 9 bytes

[Dg#γ€g]N

Pruébalo en línea!

Explicación

[Dg#   ]     # loop until the length of the current value is 1
    γ        # split into groups of consecutive equal elements
     €g      # get length of each
        N    # push the iteration variable N
Emigna
fuente
1

Wolfram Language (Mathematica) , 32 bytes

Guardado 2 bytes gracias a Martin Ender. Usando la codificación CP-1252, donde± hay un byte.

±{_}=0;±x_:=1+±(Length/@Split@x)

Pruébalo en línea!

alephalpha
fuente
1
La definición de un operador ahorra dos bytes: ±{_}=0;±x_:=1+±(Length/@Split@x)(suponiendo WindowsANSIcodificación)
Martin Ender
1

SmileBASIC, 110 108 bytes

DEF R L,J
K=LEN(L)FOR I=1TO K
N=POP(L)IF O-N THEN UNSHIFT L,0
INC L[0]O=N
NEXT
IF I<3THEN?J ELSE R L,J+1
END

Función de llamada como R list,0; la salida se imprime en la consola.

12Me21
fuente
0

R , 51 45 bytes

f=function(a)"if"(sum(a|1)>1,f(rle(a)$l)+1,0)

Pruébalo en línea!

Recurrentemente tome la longitud de la codificación de longitud de ejecución e incremente el contador.

Giuseppe
fuente
0

Retina 0.8.2 , 31 bytes

,.*
$&_
}`(\b\d+)(,\1)*\b
$#2
_

Pruébalo en línea! El enlace incluye casos de prueba. Explicación:

,.*
$&_

Si hay una coma, haremos otra iteración, así que agregue un carácter de conteo.

}`(\b\d+)(,\1)*\b
$#2

Reemplace cada ejecución con su longitud disminuida. Las etapas anteriores se repiten hasta que no quedan comas.

_

Cuenta el número de iteraciones.

Neil
fuente
0

Perl 6 , 52 bytes

{+($_,*.comb(/(\d+)[" "$0»]*/).map(+*.words)...^1)}

Pruébalo

Expandido:

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

  + (              # turn the following into a Numeric (get the count)


      $_,          # seed the sequence with the input

      *.comb(      # turn into a string, and grab things that match:

        /          # regex
          ( \d+ )  # a run of digits (number)
          [
            " "    # a space
                   # (gets inserted between elements of list when stringified)

            $0     # another instance of that number
            »      # make sure it isn't in the middle of a number

          ]*       # get as many as possible
        /
      ).map(
        +*.words  # turn each into a count of numbers
      )

      ...^        # keep doing that until (and throw away last value)

      1           # it gives a value that smart-matches with 1
                  # (single element list)
  )
}
Brad Gilbert b2gills
fuente
0

Kotlin , 123 bytes

Acepta List<Int>.

{var a=it;var b=0;while(a.size>1){var c=a[0];var d=0;with(a){a=listOf();forEach{if(it!=c){a+=d;d=0};d++;c=it};a+=d};b++};b}

Más legible:

{ l ->
    var input = l
    var result = 0
    while (input.size > 1) {
        var last = input[0]
        var runSize = 0
        with(input) {
            input = listOf()
            forEach { current ->
                if (current != last) {
                    input += runSize
                    runSize = 0
                }
                runSize++
                last = current
            }
            input += runSize
        }
        result++
    }
    result
}

Pruébalo en línea!


131 bytes, TIO

{l->var a=l;var b=0;while(a.size>1){var c=a[0];var d=0;a.let{a=arrayListOf();for(e in it){if(e!=c){a+=d;d=0};d++;c=e};a+=d};b++};b}

181 bytes, TIO

Incluye 39 para import kotlin.coroutines.experimental.*.

{l->var a=l;var b=0;while(a.size>1){var c=a[0];var d=0;a=buildSequence{for(e in a){if(e!=c){yield(d);d=0;};d++;c=e};yield(d)}.toList();b++};b}
Moira
fuente
0

Rojo , 140 bytes

func[b][n: 0 while[(length? b)> 1][l: copy[]parse split form b" "[any[copy s[set t string! thru any t](append l length? s)]]b: l n: n + 1]n]

Pruébalo en línea!

Solo quería darle otra oportunidad al dialecto de Red's Parse.

Sin golf

f: func [b] [
    n: 0
    while [(length? b) > 1][
        l: copy []
        parse split form b " " [
            any [copy s [set t string! thru any t]
                (append l length? s)]
        ]
        b: l
        n: n + 1
    ]
    n
]
Galen Ivanov
fuente