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!


¿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!


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.



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


@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
)

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!



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!


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


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.



1
24 bytes:Max[Length@Split@#-1,0]&
JungHwan Min

23:Length@Split@#~Max~1-1&
Martin Ender


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.
_=___                                       

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.

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



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.


+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.


@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.


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 「$_」
}

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.

2

JavaScript (ES6), 35 bytes

a=>a.filter((e,i)=>e-a[i+1]).length

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

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



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!


[:+/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!


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
}

¿Podría agregar un enlace a un entorno de prueba en línea?
Jonathan Frech

@JonathanFrech Añadido
pizzapants184

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.