Cuenta los cambios en una matriz

20

Su tarea hoy es escribir un programa o función que tome una matriz de enteros y cuente la cantidad de veces, leyéndola de izquierda a derecha, que el valor cambia. Esto es más fácil de mostrar con un ejemplo:[1 1 1 2 2 5 5 5 5 17 3] => [1 1 1 **2** 2 **5** 5 5 5 **17** **3**] => 4

Caso de prueba:

Input           |   Output
[]              |   0
[0]             |   0
[0 1]           |   1
[0 0]           |   0
[1 2 3 17]      |   3
[1 1 1 2 2 3]   |   2
[-3 3 3 -3 0]   |   3

Este es el , ¡la menor cantidad de bytes gana!

Pavel
fuente
¿Es válida mi respuesta si el resultado siempre se calcula correctamente, pero si es 0, Falsese imprime en su lugar?
FlipTack
1
@FlipTack Eso depende del idioma. En general, si puedo decir 2+Falsey errores, no está bien, pero si lo consigo 2, está bien.
Pavel
@FlipTack Por defecto, este es el consenso.
Totalmente humano
¿La salida vacía es 0aceptable?
Titus
@Titus sí lo es.
Pavel

Respuestas:

9

Python 3 , 38 bytes

f=lambda x=0,*y:y>()and(x!=y[0])+f(*y)

Pruébalo en línea!

Dennis
fuente
2
Huh, sabía que podría usar un argumento predeterminado como ese, un buen hallazgo.
xnor
@Dennis ¿Cómo sale la función del bucle recursivo cuando la matriz está vacía? No veo cómo esto no termina en a maximum recursion depth exceeded.
Ioannes
@Ioannes Una vez que solo quede un elemento ( x ), y>()se evaluará como False , para que el siguiente código andno se ejecute.
Dennis
7

Haskell , 33 bytes

f(a:b:r)=sum[1|a/=b]+f(b:r)
f _=0

Pruébalo en línea!


Bonus: versión aritmética sin puntos algo curiosa (44 bytes)

sum.(tail>>=zipWith((((0^).(0^).abs).).(-)))

Pruébalo en línea!

Dada una entrada [1,1,4,3,3,3], primero tomamos la diferencia de entradas adyacentes ( [0,3,-1,0,0]), entonces el absvalor oluta: [0,3,1,0,0]. Tomar cero a la potencia de cada elemento la primera vez produce [1,0,0,1,1], y una segunda vez invierte la lista: [0,1,1,0,0]( (1-)también funcionaría aquí en lugar de (0^)). Finalmente tomamos el sumde la lista para obtener 2.

Laikoni
fuente
5

Brain-Flak , 50 bytes

([][()]){{}({}[({})]){{}<>({}())(<>)}{}([][()])}<>

Pruébalo en línea!

No produce nada para 0, que en brain-flak es equivalente. Si esto no es aceptable, entonces agregue esto para +4bytes:({})

Explicación:

#Push stack-height-1
([][()])

#While true:
{

    #Pop the stack-height-1 off
    {}

    #If 'a' is the element on top of the stack, and 'b' is the element underneath it, then
    #Pop 'a' off, and push (a - b)
    ({}[({})])

    #If (a-b) is not 0...
    {
        #Pop (a-b) off
        {}

        #Switch stacks
        <>

        #Increment the value on the other stack
        ({}())

        #Push a 0 back to the main stack
        (<>)

    #Endif
    }

    #Pop either (a-b) or the 0 we pushed
    {}

    #Push stack-height-1
    ([][()])

#Endwhile
}

#Toggle to the alternate stack and display the counter
<>
DJMcMayhem
fuente
@Riley Bien hecho! :)
DJMcMayhem
1
@WheatWizard También probé eso, pero se repite para siempre en la entrada vacía. -0+1 = 1
H.PWiz
5

Brain-Flak , 50 bytes

(([][()]){[{}]<({}[({})])>{(<{}>)()}{}([][()])}<>)

Pruébalo en línea!

# Get ready to push the answer
(

# Push stack height - 1
([][()])

# Loop until 0 (until the stack has a height of 1)
{

  # Pop the old stack height and subtract it 
  #(cancels the loop counter from the final answer)
  [{}]

  # Pop the top of the stack and subtract the next element from that
  # Don't include this in the final answer
  <({}[({})])>

  # If not 0
  {

    # Pop the difference between the last two numbers
    # Don't include this in the final answer
    (<{}>)

    # Add 1 to the final answer
    ()

  # End if
  }{}

  # Push stack height - 1
  ([][()])

# End while
}

# Switch to the off stack so we don't print anything extra
<>

# Push the total sum. This is the number of times the if was true
)
Riley
fuente
1
¡Felicidades por 10k rep!
Pavel
@Pavel ¡Gracias! Me llevó una eternidad obtener los últimos cientos. He estado demasiado ocupado con otras cosas :(
Riley
Tuve esto
H.PWiz
@ H.PWiz Tuve eso en un momento, pero me gusta cómo el pop cancela el impulso de altura de la pila.
Riley
5

Haskell , 35 bytes

-8 bytes gracias a H.PWiz.

Fuera de golf por una versión recursiva . Haskell es prácticamente el mejor en recursión y me lo perdí. > _ <

f l=sum[1|x<-zipWith(/=)l$tail l,x]

Pruébalo en línea!

Sería increíble si alguien descubriera cómo emplear este consejo .

Solución alternativa, 36 bytes.

f l=sum[1|True<-zipWith(/=)l$tail l]

Pruébalo en línea!

totalmente humano
fuente
1
También 35
H.PWiz
Ese consejo omite el hecho crucial de que necesitarías uncurryla función fpara que funcione. Este sum.map fromEnum.(zipWith(/=)=<<tail)es probablemente el más cercano que se obtiene, pero no funcionará con []y es de 37 bytes ..
ბიმო
5

Java (OpenJDK 8) , 65 bytes

No es tan corto como me gustaría, pero eso es solo Java para ti.

Pruebe pasando la matriz como una lista delimitada por comas.

a->{int s=0,i=1;for(;i<a.length;s+=a[i-1]!=a[i++]?1:0);return s;}

Pruébalo en línea!

Luke Stevens
fuente
2
Si la matriz vacía no fuera un caso de prueba (y no lo encuentro realmente relevante, en realidad), se podría haber usado: a->{int s=0,p=a[0];for(int n:a)s+=p==(p=n)?0:1;return s;}(57 bytes).
Olivier Grégoire
@ OlivierGrégoire lo sé! Escribí eso y pensé que había logrado reducir los bytes, pero falló en ese primer caso.
Luke Stevens
3
56 bytes:a->{int s=0;for(int i:a)s+=a[0]!=(a[0]=i)?1:0;return s;}
Nevay
4

Casco , 3 bytes

Ltg

Pruébalo en línea!

Explicación

Ltg    Input: [1,1,1,2,2,3]
  g    Group equal elements together: [[1,1,1],[2,2],[3]]
 t     Drop the first group (if any): [[2,2],[3]]
L      Return the length of the list: 2
León
fuente
4

Ohm v2 , 3 bytes

ΔyΣ

Pruébalo en línea!

Explicación

Δ     absolute differences between consecutive elements
 y    sign: 1 if positive, -1 if negative, 0 if zero
  Σ   sum
Cinaski
fuente
Uso inteligente de la signconstrucción!
Nick Clifford
@NickClifford ¡Gracias!
Cinaski
4

Wolfram Language (Mathematica) , 2324 26 29 bytes

Length@Split@#~Max~1-1&

Pruébalo en línea!

  • -1 byte gracias a Martin Ender!
  • -2 bytes gracias a JungHwan Min! buen uso de Split[].
  • -3 bytes gracias a totalmente humano!

una pequeña explicación

Splitdividirá una matriz en una lista de listas (de los mismos elementos), es decir, se convertirá {1, 2, 2, 3, 1, 1}en {{1}, {2, 2}, {3}, {1, 1}}. Entonces, Length@Split@#es la cantidad de segmentos consecutivos. Max[*****-1, 0]se utiliza para lidiar con la {}entrada.

Keyu Gan
fuente
1
26 bytes.
Totalmente humano
1
24 bytes:Max[Length@Split@#-1,0]&
JungHwan Min
23:Length@Split@#~Max~1-1&
Martin Ender
4

Retina , 24 21 16 bytes

Gracias a @MartinEnder por -3 bytes y notando un error
-1 byte gracias a @tsh
-4 bytes gracias a @Leo

m`^(\S+)¶(?!\1$)

Pruébalo en línea!

ovs
fuente
4

Simbólicos Python , 120 117 bytes

Golfó 3 bytes al eliminar una conversión explícita a entero (usando unario +) para la variable de contador; esto significa que si no hay cambios en la matriz, la salida será en Falselugar de 0, pero esto está permitido por meta .

___=-~(_==_)
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___)
_=___

Pruébalo en línea!

# LINE 1: Generate value '2' for utility
___=-~(_==_)

# LINE 2: Get len(input) - 1
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
   '___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)'     # Generate string '___=~-len(_)'
            `_>_`[___::___]                       #    'le' spliced from 'False'
                           +`__`[-~___]           #    'n' indexed from '<function ...>'
   '___=~-'+                           +'(_)'     #    Remaining characters in plaintext
__(                                          )    # Execute this to get len(input) - 1

# LINE 3: Main calculation loop
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___) 
__(                                               ) # Execute:
   '__=___=_>_'                                     #   Set var1, var2 to 0
               +';                           '*___  #   len(input) - 1 times do:
                       _[__]!=_[-~__]               #   Compare input[var1, var1 + 1]
                  ___+=              ;              #   Add this to var2
                                      __=-~__       #   Increment var1

# LINE 4: Set output variable ('_') to the result calculated.
_=___                                       
FlipTack
fuente
2
= _ = ¿Qué es esta magia?
Totalmente humano
3

Jalea , 3 bytes

ITL

Pruébalo en línea!

Cómo funciona

ITL - Programa completo.

I - Incrementos (deltas).
 T - Obtiene los índices de valores de verdad (obtiene los índices de elementos que no son 0).
  L - Longitud.
Sr. Xcoder
fuente
3

K (oK) , 8 bytes

Solución:

+/1_~~':

Pruébalo en línea!

Ejemplos:

+/1_~~':1 1 1 2 2 5 5 5 5 17 3
4
+/1_~~':()
0
+/1_~~':-3 3 3 -3 0
3

Explicación:

Interpretado de derecha a izquierda:

+/1_~~': / the solution
     ~': / equal each-previous
    ~    / not (ie differ)
  1_     / 1 drop, remove first as this is different to null
+/       / sum up trues
callejero
fuente
3

R , 24 bytes

cat(sum(!!diff(scan())))

Pruébalo en línea!

Igual que la respuesta MATL, solo se usa sum(!!diff))porque no hay nnz.

Giuseppe
fuente
+1 pensé que usar rlesería más corto, pero no, length(rle()$v)usa demasiados caracteres y está apagado por uno.
Neal Fultz
¡@NealFultz probablemente todavía valga la pena publicarlo como respuesta! Siempre es bueno ver otro enfoque. Y deberías usar en sum(rle()$v|1)lugar de lengthtodos modos. :)
Giuseppe
3

Cubix , 24 bytes

UpO@0I>I!^-u>q.uvv$!^;)p

Pruébalo en línea

Tenga en cuenta que Cubix usa 0 para indicar que no hay más entradas, por lo que 0 no puede estar en la lista.

Explicación

Desplegado:

    U p
    O @
0 I > I ! ^ - u
> q . u v v $ !
    ^ ;
    ) p

Comenzamos en el 0, empujando el contador (inicializado con 0) y la primera entrada ( I) en la pila.

Luego entramos en el bucle. En cada iteración del ciclo, obtenemos la siguiente entrada con I. Si es 0, nos hemos quedado sin entradas, por lo que rotamos el contador hacia arriba ( p), Output y exit (@ ).

De lo contrario, tomamos la diferencia de los dos elementos superiores. Si no es cero, giramos el contador hacia arriba, lo incrementamos y lo volvemos a la parte inferior con p)q. Luego resaltamos la diferencia ;antes de pasar a la siguiente iteración.

Todos los caracteres no mencionados aquí son solo control de flujo. Suelen existir muchos de esos en los programas Cubix.


fuente
@MickyT Buen enfoque, pero parece que estás contando en exceso por 1. Puedes cambiar el 0por a (, pero eso falla en la entrada vacía.
disculpas, lo miraré de nuevo
MickyT
3

Brain-Flak , 50 bytes

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

Pruébalo en línea!

Como todos están publicando sus soluciones de 50 bytes, aquí es mía (tengo una de 48 bytes, pero fue una simple modificación de DjMcMayhem, así que sentí que valía la pena publicarla)

Explicación

Esta respuesta utiliza ampliamente la cancelación de valor.

Sin golf parece

([][()])({<{}({}[({})])>{<{}>()(<()>)}{}<([][()])>}<>)

Aquí calculamos los deltas hasta que a la pila le quede un elemento, cada vez que acumulamos un valor del bucle interno si el delta no es cero.

Esta es una forma bastante directa de hacerlo.

Para hacer esto golfístico, comenzamos a cancelar el valor. El primero y el que debería ser obvio para cualquier golfista con ataques cerebrales es la altura de la pila. Es un hecho bien conocido que

([])({<{}>...<([])>}{})

es lo mismo que

(([]){[{}]...([])}{})

Cuando los valores son modificados por uno, se mantiene lo mismo. Esto nos da

(([][()]){[{}]<({}[({})])>{<{}>()(<()>)}{}([][()])}<>)

Puede notar que esto ni siquiera nos ahorró bytes, pero no se preocupe, será más útil a medida que avancemos.

Podemos realizar otra reducción, si ve una declaración

<(...)>{<{}> ...

en realidad puedes reducirlo a

[(...)]{{} ...

Esto funciona porque si ingresamos al ciclo [(...)]y {}cancelaremos, y si no lo hacemos, el valor de [(...)]ya era cero en primer lugar y no necesita ser cancelado. Como tenemos una aparición de este patrón en nuestro código, podemos reducirlo.

(([][()]){[{}][({}[({})])]{{}()(<()>)}{}([][()])}<>)

Eso nos ahorró 2 bytes pero también puso dos negs uno al lado del otro. Estos se pueden combinar para salvarnos otros 2.

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

Y ese es nuestro código.

Asistente de trigo
fuente
3

Perl 6 , 18 bytes

{sum $_ Z!= .skip}

Pruébalo

Expandido:

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

  sum         # count the number of True values

      $_      # the input
    Z!=       # zip using &infix:«!=»
      .skip   # the input, but starting from the second value
              # (implicit method call on 「$_」
}
Brad Gilbert b2gills
fuente
3

Gaia , 2 bytes

ėl

Pruébalo en línea!

Esto abusa de un error (o función) de Gaia, que la codificación de longitud de ejecución no tiene en cuenta la última ejecución de elementos. Tenga en cuenta que lo he verificado dos veces, funciona para todos los casos de prueba.

  • ė - Ejecute la codificación de longitud (con la falla descrita anteriormente).
  • l - Longitud.
Sr. Xcoder
fuente
2

JavaScript (ES6), 35 bytes

a=>a.filter((e,i)=>e-a[i+1]).length
Neil
fuente
Me pregunto si podría acortarse usando la recursividad. Pero mi mejor intento es también 35:f=([a,...b])=>1/a?!!(a-b[0])+f(b):0
Arnauld
@Arnauld También lo intenté, pero conté mal y pensé que era 36 bytes, de lo contrario lo habría agregado como alternativa.
Neil
2

Pyth, 5 bytes

l #.+

Banco de pruebas.

Explicación:

   .+  Deltas
  #    Filter on identity (space)
l      Get length 
Steven H.
fuente
2

APL (Dyalog) , 8 bytes

+/2≠/⊃,⊢

Pruébalo en línea!

¿Cómo?

⊃,⊢ - la lista, con el primer valor repetido para el caso de un solo elemento

2≠/ - lista de cambios, no igual por cada 2 elementos

+/ suma

Uriel
fuente
2

J, 10 bytes

[:+/2~:/\]

Infijos de longitud 2 ... ¿son desiguales? 2 ~:/\ ]

Resumiendo la lista resultante de 0s y 1s:+/

Pruébalo en línea!

Jonás
fuente
[:+/0=-/\ Debería funcionar para creo 9 bytes.
cole
2

Ruby , 31 bytes

->a{a.chunk{|x|x}.drop(1).size}

Pruébalo en línea!

Jordán
fuente
En lugar de .drop(1)que puedas hacerlo[1..-1]
Cyoce
@Cyoce Desafortunadamente dropdevuelve un enumerador , no una matriz, por lo que no funciona.
Jordan
eh Devuelve una matriz en mi versión.
Cyoce
@Cyoce ¿Qué versión?
Jordan
Estoy en 1.9.3, pero ¿por qué no puedes tomar la sizematriz de todos modos?
Cyoce
2

C (gcc 5.4.0), 61 bytes

f(c,v)int*v;{int*p=v,s=0;for(;p<v+c-1;s+=*p++!=*p);return s;}

Pruébalo en línea!

f es una función que toma la longitud de la matriz y un puntero al primer elemento de la matriz y devuelve el número de cambios en la matriz;

Este envío utiliza un comportamiento indefinido ( *p++!=*p, p se usa dos veces en una expresión en la que se cambia), que funciona en mi máquina (gcc 5.4.0) y en TIO, pero puede no funcionar en otras implementaciones o versiones.

Explicación:

f(c,v)int*v;{ // old-style declaration for v, and implicit-int for c and return value
    int*p=v,s=0; // p is a pointer to the current item, s is the number of changes
    for(;p<v+c-1;s+=*p++!=*p); // for each consecutive pair of integers, if they are different, add one to the number of changes
    return s; // return the number of changes
}
pizzapants184
fuente
¿Podría agregar un enlace a un entorno de prueba en línea?
Jonathan Frech
@JonathanFrech Añadido
pizzapants184
2

05AB1E , 3 bytes

γ¦g

Pruébalo en línea!

Una alternativa a la respuesta de Erik.

γ¦g ~ Programa completo.

γ ~ Agrupar en series de elementos adyacentes iguales.
 ¦ ~ Elimine el primer grupo (si hay alguno).
  g ~ longitud.
Sr. Xcoder
fuente
Ah, extrañé que ese fuera un caso.
Urna mágica de pulpo