Contar as alterações em uma matriz


20

Sua tarefa hoje é escrever um programa ou função que utilize uma matriz de números inteiros e conte o número de vezes, lendo da esquerda para a direita, que o valor muda. Isso é mais fácil de mostrar com um exemplo:[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 teste:

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

Isso é , o menor número de bytes vence!


Minha resposta é válida se o resultado for sempre calculado corretamente, mas se for 0, Falseserá impresso?
FlipTack

1
@FlipTack Isso depende do idioma. Em geral, se eu posso dizer 2+Falsee erros, não está bem, mas se eu conseguir 2, tudo bem.
Pavel

@FlipTack Por padrão, este é o consenso.
totallyhuman

A saída vazia é 0aceitável?
Titus

@ Titus sim, é.
Pavel

Respostas:



9

Python 3 , 38 bytes

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

Experimente online!


2
Ah, sabia que você poderia usar um argumento padrão como esse, boa descoberta.
Xnor


@Dennis Como a função sai do loop recursivo quando a matriz está vazia? Não vejo como isso não termina em um maximum recursion depth exceeded.
Ioannes 27/10

@Ioannes Quando houver apenas um elemento ( x ) restante, y>()será avaliado como False , para que o código a seguir andnão seja executado.
Dennis

7

Haskell , 33 bytes

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

Experimente online!


Bônus: Versão aritmética um pouco curiosa e sem pontos (44 bytes)

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

Experimente online!

Dada uma entrada [1,1,4,3,3,3], primeiro pegamos a diferença das entradas adjacentes ( [0,3,-1,0,0]), depois o absvalor olute:[0,3,1,0,0] . Levando zero à potência de cada elemento na primeira vez [1,0,0,1,1], e uma segunda vez inverte a lista: [0,1,1,0,0]( (1-)também funcionaria aqui em vez de (0^)). Finalmente, pegamos o sumda lista para obter 2.



5

Flacidez cerebral , 50 bytes

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

Experimente online!

Não produz nada para 0, o que no cérebro é equivalente. Se isso não for aceitável, acrescente-o a+4 bytes:({})

Explicação:

#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 Bem feito! :)
DJMcMayhem


1
@WheatWizard Eu tentei isso também, mas fica para sempre na entrada vazia. -0+1 = 1
H.PWiz

5

Flacidez cerebral , 50 bytes

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

Experimente online!

# 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
Parabéns por 10k rep!
Pavel

@Pavel Obrigado! Levei uma eternidade para conseguir as últimas centenas. Eu estive muito ocupado com outras coisas :(
Riley

Eu tinha isso
H.PWiz 26/10

@ H.PWiz Eu tive isso em um ponto, mas eu gosto de como o pop cancela o push da altura da pilha.
Riley

5

Haskell , 35 bytes

-8 bytes graças a H.PWiz.

Out-golfed por uma versão recursiva . Haskell é praticamente o melhor em recursão e eu perdi. > _ <

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

Experimente online!

Seria incrível se alguém descobrisse como empregar essa dica .

Solução alternativa, 36 bytes

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

Experimente online!



Essa dica perde o fato crucial de que você precisaria uncurryda função fpara fazê-la funcionar. Este sum.map fromEnum.(zipWith(/=)=<<tail)é provavelmente o mais próximo que você começa, mas não vai trabalhar com []e é de 37 bytes ..
ბიმო

5

Java (OpenJDK 8) , 65 bytes

Não é tão curto quanto eu gostaria, mas isso é apenas Java para você.

Teste passando a matriz como uma lista delimitada por vírgula.

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

Experimente online!


2
Se a matriz vazia não fosse um caso de teste (e eu não acho realmente relevante, na verdade), alguém poderia ter 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 eu sei! Eu escrevi isso e pensei que tinha conseguido reduzir os bytes, mas ele falhou no primeiro 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 27/10

4

Casca , 3 bytes

Ltg

Experimente online!

Explicação

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

Língua Wolfram (Mathematica) , 2324 26 29 bytes

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

Experimente online!

  • -1 byte graças a Martin Ender!
  • -2 bytes graças a JungHwan Min! bom uso de Split[].
  • -3 bytes graças a totallyhuman!

uma pequena explicação:

Splitdividirá uma matriz em uma lista de listas (dos mesmos elementos), ou seja, se transformará {1, 2, 2, 3, 1, 1}em {{1}, {2, 2}, {3}, {1, 1}}. Então, Length@Split@#é a quantidade de segmentos consecutivos. Max[*****-1, 0]é usado para lidar com {}entrada.



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

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

4

Retina , 24 21 16 bytes

Graças a @MartinEnder por -3 bytes e percebendo um erro
-1 byte graças a @tsh
-4 bytes graças a @Leo

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

Experimente online!


4

Python simbólico , 120 117 bytes

Golpeou 3 bytes removendo uma conversão explícita para inteiro (usando unário +) para a variável do contador - isso significa que, se não houver alterações na matriz, a saída será em Falsevez de 0, mas isso é permitido por meta .

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

Experimente online!

# 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
= _ = o que é essa magia?
totallyhuman

3

Gelatina , 3 bytes

ITL

Experimente online!

Como funciona

ITL - Programa completo.

I - incrementos (deltas).
 T - Obtenha os índices de valores reais (obtém os índices de elementos diferentes de 0).
  L - comprimento.

3

K (oK) , 8 bytes

Solução:

+/1_~~':

Experimente online!

Exemplos:

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

Explicação:

Interpretado da direita para a esquerda:

+/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())))

Experimente online!

O mesmo que a resposta MATL, usada apenas sum(!!diff))porque não há nnz.


O +1 que eu pensei que usar rleseria mais curto, mas não, length(rle()$v)usa muitos caracteres e está desativado por um.
Neal Fultz

@NealFultz provavelmente ainda vale a pena postar como resposta! Sempre bom ver outra abordagem. E você deve usar em sum(rle()$v|1)vez delength qualquer maneira. :)
Giuseppe

3

Cubix , 24 bytes

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

Experimente online

Observe que o Cubix usa 0 para indicar que não há mais entradas, portanto, 0 não pode estar na lista.

Explicação

Desdobrado:

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

Começamos no 0, pressionando o contador (inicializado com 0) e a primeira entrada (I ) para a pilha.

Em seguida, entramos no loop. A cada iteração do loop, obtemos a próxima entrada com I. Se for 0, ficamos sem entradas, então giramos o contador para top ( p), Output e exit (@ ).

Caso contrário, consideramos a diferença dos dois principais elementos. Se for diferente de zero, giramos o contador para cima, incrementamos e giramos de volta para baixo com p)q. Em seguida, mostramos a diferença ;antes de passar para a próxima iteração.

Todos os caracteres não mencionados aqui são apenas controle de fluxo. Existem muitos programas nos programas Cubix.


@MickyT Boa abordagem, mas você parece estar contando mais de 1. Você pode trocar o 0por a (, mas isso falha na entrada vazia.

desculpas, vamos olhar novamente
MickyT 30/10

3

Flacidez cerebral , 50 bytes

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

Experimente online!

Como todo mundo está postando suas soluções de 50 bytes aqui é minha (eu tenho uma de 48 bytes, mas foi uma modificação simples do DjMcMayhem, então achei que valha a pena postar)

Explicação

Esta resposta usa extensivamente o cancelamento de valor.

Sem golfe parece

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

Aqui, calculamos os delta's até que a pilha tenha um item restante, cada vez que acumulamos um valor do loop interno se o delta for diferente de zero.

Esta é uma maneira bastante direta de fazê-lo.

Para fazer este golfe, começamos o cancelamento de valor. O primeiro e o que deve ser óbvio para qualquer jogador endurecido de ataques cerebrais são as alturas das pilhas. É um fato bem conhecido que

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

é o mesmo que

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

Quando os valores são modificados por um, o mesmo vale. Isso nos dá

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

Você pode notar que isso nem nos salvou bytes, mas não se preocupe, isso se tornará mais útil à medida que prosseguimos.

Podemos realizar outra redução, se você vir uma declaração

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

você pode reduzi-lo a

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

Isso funciona porque se inserirmos o loop [(...)]e {}cancelar, e se não o fizermos, o valor de [(...)]já era zero em primeiro lugar e não precisará ser cancelado. Como temos uma ocorrência desse padrão em nosso código, podemos reduzi-lo.

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

Isso nos salvou 2 bytes, mas também colocou dois pontos negativos um ao lado do outro. Estes podem ser combinados para salvar outros 2.

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

E esse é o nosso código.


3

Perl 6 , 18 bytes

{sum $_ Z!= .skip}

Teste-o

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

Experimente online!

Isso abusa de um bug (ou recurso?) Do Gaia, que a codificação do comprimento da execução não leva em consideração a última execução dos elementos. Observe que eu verifiquei duas vezes, ele funciona para todos os casos de teste.

  • ė - Execute a codificação de comprimento (com a falha descrita acima).
  • l - Comprimento.

2

JavaScript (ES6), 35 bytes

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

Gostaria de saber se poderia ser encurtado usando recursão. Mas a minha melhor tentativa é 35:f=([a,...b])=>1/a?!!(a-b[0])+f(b):0
Arnauld 26/10

@ Arnauld Eu tentei isso também, mas contei mal e achei que eram 36 bytes, caso contrário, eu o adicionaria como alternativa.
27417 Neil


2

APL (Dyalog) , 8 bytes

+/2≠/⊃,⊢

Experimente online!

Quão?

⊃,⊢ - a lista, com o primeiro valor repetido para o caso de elemento único

2≠/ - lista de alterações, não é igual para cada 2 elementos

+/ - soma



2

J, 10 bytes

[:+/2~:/\]

Infixes de comprimento 2 ... são desiguais? 2 ~:/\ ]

Soma a lista resultante de 0s e 1s:+/

Experimente online!


[:+/0=-/\ deve funcionar, acho que 9 bytes.
cole

2

Ruby , 31 bytes

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

Experimente online!


Em vez de .drop(1)você pode fazer[1..-1]
Cyoce

@ Cyy Infelizmente, dropretorna um enumerador , não uma matriz, para que não funcione.
Jordan

Hã. Retorna uma matriz na minha versão.
Cyoce

@Cyoce Qual versão?
Jordan

Estou no 1.9.3, mas por que você não pode tirar o sizede uma matriz de qualquer maneira?
Cyoce 27/10

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

Experimente Online!

f é uma função que leva o comprimento da matriz e um ponteiro para o primeiro elemento da matriz e retorna o número de alterações na matriz;

Este envio utiliza um comportamento indefinido (*p++!=*p , p é usado duas vezes em uma expressão na qual é alterado), que funciona na minha máquina (gcc 5.4.0) e no TIO, mas pode não funcionar em outras implementações ou versões.

Explicação:

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
}

Você poderia adicionar um link a um ambiente de teste online?
Jonathan Frech

@JonathanFrech Adicionado
pizzapants184

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.