Há um eco na minha matriz ... eco na minha matriz ... minha matriz

34

Socorro! Parece que tenho um eco irritante em algumas das minhas matrizes e gostaria de me livrar dele. Quando isso ocorre, a matriz original se repete em algum lugar no meio, fazendo com que os valores sejam adicionados um ao outro.

Por exemplo, a matriz [ 422, 375, 527, 375, 859, 451, 754, 451 ]contém um eco de si mesmo assim:

[ 422, 375, 527, 375, 859, 451, 754, 451 ] <-- array with echo (input)

[ 422, 375, 105,   0, 754, 451           ] <-- original array (output)
[           422, 375, 105,   0, 754, 451 ] <-- echo of original array

Exemplo 2:

[ 321, 526, 1072, 899, 6563, 798, 7038, 3302, 3032, 3478, 1806, 601 ] <-- input

[ 321, 526,  751, 373, 5812, 425, 1226, 2877, 1806,  601            ] <-- output
[            321, 526,  751, 373, 5812,  425, 1226, 2877, 1806, 601 ]

Também é possível que não haja eco na matriz; nesse caso, retorne a matriz original:

Exemplo 3:

[ 623, 533, 494, 382 ] <-- input
[ 623, 533, 494, 382 ] <-- output

Desafio:

Dada uma matriz que pode conter um eco, remova-a e retorne a matriz sem um eco.

Entrada:

  • Uma matriz, lista, sequência delimitada, cartões perfurados ou seu equivalente adequado à plataforma, contendo três ou mais números inteiros, no intervalo de 0 0n<10000 com pelo menos um elemento >0 0 .
  • O eco não pode começar no primeiro ou após o último elemento.
  • O eco ocorrerá apenas uma vez ou não dentro da entrada.

Saída:

  • Uma matriz, lista etc. de números inteiros 0 0n<10000 , com o eco removido.
  • Se não houver eco, retorne a matriz original.

Regras e pontuação:

Casos de teste:

Com eco:

[ 422, 375, 527, 375, 859, 451, 754, 451 ]
[ 422, 375, 105, 0, 754, 451 ]

[ 321, 526, 1072, 899, 6563, 798, 7038, 3302, 3032, 3478, 1806, 601 ]
[ 321, 526, 751, 373, 5812, 425, 1226, 2877, 1806, 601 ]

[ 4330, 3748, 363, 135, 2758, 3299, 1674, 1336, 4834, 2486, 4087, 1099, 4098, 4942, 2159, 460, 4400, 4106, 1216, 3257, 1638, 2848, 3616, 3554, 1605, 490, 1308, 2773, 3322, 3284, 4037, 7109, 4171, 5349, 2675, 3056, 4702, 4229, 1726, 5423, 6039, 8076, 6047, 7088, 9437, 4894, 1946, 7501, 5331, 3625, 5810, 6289, 2858, 6610, 4063, 5565, 2200, 3493, 4573, 4906, 3585, 4147, 3748, 3488, 5625, 6173, 3842, 5671, 2555, 390, 589, 3553, 3989, 4948, 2990, 4495, 2735, 1486, 3101, 1225, 2409, 2553, 4651, 10, 2994, 509, 3960, 1710, 2185, 1800, 1584, 301, 110, 969, 3065, 639, 3633, 3544, 4268 ]
[ 4330, 3748, 363, 135, 2758, 3299, 1674, 1336, 4834, 2486, 4087, 1099, 4098, 4942, 2159, 460, 4400, 4106, 1216, 3257, 1638, 2848, 3616, 3554, 1605, 490, 1308, 2773, 3322, 3284, 4037, 2779, 423, 4986, 2540, 298, 1403, 2555, 390, 589, 3553, 3989, 4948, 2990, 4495, 2735, 1486, 3101, 1225, 2409, 2553, 4651, 10, 2994, 509, 3960, 1710, 2185, 1800, 1584, 301, 110, 969, 3065, 639, 3633, 3544, 4268 ]

[ 24, 12, 52, 125, 154, 3, 567, 198, 49, 382, 53, 911, 166, 18, 635, 213, 113, 718, 56, 811, 67, 94, 80, 241, 343, 548, 68, 481, 96, 79, 12, 226, 255, 200, 13, 456, 41 ]
[ 24, 12, 52, 125, 154, 3, 567, 198, 25, 370, 1, 786, 12, 15, 68, 15, 88, 348, 55, 25, 55, 79, 12, 226, 255, 200, 13, 456, 41 ]

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

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

Sem eco:

[ 623, 533, 494, 382 ]
[ 623, 533, 494, 382 ]

[ 1141, 1198, 3106, 538, 3442, 4597, 4380, 3653, 1370, 3987, 1964, 4615, 1844, 5035, 2463, 6345, 4964, 4111, 5192, 8555, 5331, 3331, 4875, 6586, 5728, 4532, 5972, 2305, 3491, 6317, 2256, 2415, 5788, 4873, 6480, 2080, 5319, 4551, 6527, 5267, 4315, 2178, 2615, 5735, 5950, 6220, 7114, 6259, 5000, 4183, 6822, 6927, 7150, 8003, 5603, 3154, 8231, 5005, 5743, 6779, 4530, 4029, 5336, 6105, 4777, 6183, 6838, 5725, 6819, 8584, 3142, 3840, 3291, 4284, 2933, 4859, 2906, 5176, 2853, 2110, 2048, 4389, 4501, 2267, 2704, 431, 1495, 2712, 3008, 187, 3487, 630 ]
[ 1141, 1198, 3106, 538, 3442, 4597, 4380, 3653, 1370, 3987, 1964, 4615, 1844, 5035, 2463, 6345, 4964, 4111, 5192, 8555, 5331, 3331, 4875, 6586, 5728, 4532, 5972, 2305, 3491, 6317, 2256, 2415, 5788, 4873, 6480, 2080, 5319, 4551, 6527, 5267, 4315, 2178, 2615, 5735, 5950, 6220, 7114, 6259, 5000, 4183, 6822, 6927, 7150, 8003, 5603, 3154, 8231, 5005, 5743, 6779, 4530, 4029, 5336, 6105, 4777, 6183, 6838, 5725, 6819, 8584, 3142, 3840, 3291, 4284, 2933, 4859, 2906, 5176, 2853, 2110, 2048, 4389, 4501, 2267, 2704, 431, 1495, 2712, 3008, 187, 3487, 630 ]

[ 4791, 1647, 480, 3994, 1507, 99, 61, 3245, 2932, 8358, 6618, 1083, 5391, 3498, 4865, 1441, 3729, 5322, 5371, 6271, 2392, 1649, 5553, 9126, 3945, 2179, 3672, 2201, 4433, 5473, 4924, 6585, 6407, 3862, 6505, 1530, 5293, 4792, 6419, 6739, 3258, 3839, 3891, 7599, 2576, 5969, 5659, 6077, 5189, 1325, 4490, 5694, 6567, 6367, 5724, 5756, 6450, 5863, 4360, 2697, 3100, 3779, 4040, 4653, 1755, 3109, 2741, 3269 ]
[ 4791, 1647, 480, 3994, 1507, 99, 61, 3245, 2932, 8358, 6618, 1083, 5391, 3498, 4865, 1441, 3729, 5322, 5371, 6271, 2392, 1649, 5553, 9126, 3945, 2179, 3672, 2201, 4433, 5473, 4924, 6585, 6407, 3862, 6505, 1530, 5293, 4792, 6419, 6739, 3258, 3839, 3891, 7599, 2576, 5969, 5659, 6077, 5189, 1325, 4490, 5694, 6567, 6367, 5724, 5756, 6450, 5863, 4360, 2697, 3100, 3779, 4040, 4653, 1755, 3109, 2741, 3269 ]

[ 235, 121, 52, 1249, 154, 26, 5672, 1975, 482, 3817, 532, 9104, 1661, 171, 6347, 2124, 1122, 7175, 558, 8101, 667, 934, 798, 2404, 3424, 5479, 672, 4808, 956, 789, 123, 2255, 2549, 200, 126, 4562, 41 ]
[ 235, 121, 52, 1249, 154, 26, 5672, 1975, 482, 3817, 532, 9104, 1661, 171, 6347, 2124, 1122, 7175, 558, 8101, 667, 934, 798, 2404, 3424, 5479, 672, 4808, 956, 789, 123, 2255, 2549, 200, 126, 4562, 41 ]

[ 1, 1, 1, 1, 1 ]
[ 1, 1, 1, 1, 1 ]
640KB
fonte
3
E se houver várias saídas possíveis? Entrada: [1, 2, 2, 2, 1]; Saída: [1, 1, 1, 1]vs.[1, 2, 1]
tsh 11/07
3
Qual é a saída esperada para [1, 2, 3, 1, 2, 3], [1, 2, 3, 0, 1, 2, 3], [0, 1, 3, 2, 0]? As respostas atuais não concordam com todas essas entradas.
tsh 11/07
@tsh Qualquer um desses ( [1, 1, 1, 1]vs. [1, 2, 1]) é aceitável. Originalmente, eu tinha uma regra sobre qual escolher, mas a tirei na sandbox porque parecia se aplicar apenas a um pequeno número de casos extremos.
640KB
@tsh, [0, 1, 3, 2, 0]deveria ser [0, 1, 2, 0]- eu adicionei aos casos de teste. Uma resposta esperada nos outros dois poderia ser [1, 2, 3]que eu não consideraria esses casos de teste válidos, pois de acordo com as regras the original array repeats itself somewhere in the middle.
640KB 11/07
1
@nimi Bom. Eu diria que é ambíguo se [0,0,0](ou qualquer 0matriz de todos os tamanhos ) representa um eco de qualquer coisa ou se [0,0,0](sem eco) também seria uma resposta válida para este caso especial, pois simplesmente não há informações suficientes para determinar qual isto é. Atualizarei as regras para impedir que isso seja uma entrada válida, pois isso não invalidará ou alterará nenhuma resposta existente.
640KB 11/07

Respostas:

8

MATL , 16 bytes

t"GX@WQB&Y-~?w]x

Experimente online! Ou verifique todos os casos de teste .

Explicação

Divisão polinomial para a vitória!

t      % Implicit input. Duplicate
"      % For each (do the following as many times as input length)
  G    %   Push input again. This will be the output if no solution exists
  X@   %   Push current iteration index, k
  WQB  %   2 raised to that, add 1, convert to binary. Gives [1 0 ... 0 1] (k-1 zeros)
  &Y-  %   Two-output polynomial division (deconvolution). Gives quotient and remainder
  ~    %   Logical negate: transforms zeros into 1, nonzeros into 0
  ?    %   If all values are nonzero (i.e. if remainder was all zeros): solution found
    w  %      Swap. This moves the copy of the input to top (to be deleted)
  ]    %   End
  x    %   Delete. This deletes the quotient if it was not a solution, or else deletes
       %   the copy of the input
       % End (implicit). Since it is guaranteed that at most one solution exists, at this
       % point the stack contains either the solution or the input
       % Implicit display
Luis Mendo
fonte
Não há compradores no idioma "eso" ou "histórico" nessa matéria ... então a recompensa vai para a popularidade!
640KB
1
@ 640KB Eu não sabia que havia uma recompensa neste desafio! Obrigado!
Luis Mendo
7

Haskell , 167 bytes

Primeiro, é importante notar que, se houver um eco presente, a matriz de entrada é uma convolução de outra matriz com alguma matriz do formulário [1,1],[1,0,1],[1,0,0,1],....

Isso significa que precisamos verificar isso para todas essas matrizes. Mas convolução / deconvolução discreta é o mesmo que multiplicação polinomial / divisão longa, portanto, essa é apenas uma implementação usando polinômios, retornando sempre o quociente, se possível.

Um truque que encurtou um pouco a coisa toda, além das matrizes acima, também foi verificado [1]como um caso base, porque se nenhuma outra matriz funcionar, a desconvolução com [1]funcionará e retornará o polinômio original.

import Math.Polynomial
import Data.Ratio
p=poly LE
c z=last[polyCoeffs LE q|k<-zipWith const[p(take k(1:repeat 0)++[1])|k<-[0..]]z,(q,r)<-[quotRemPoly(p z)k],r==zero] 

Experimente online!

flawr
fonte
Bom truque com o case base! Tentei incorporar isso na minha resposta, mas pude reduzir o código
Luis Mendo
4

JavaScript , 211 171 145 bytes

s=>{for(n=x=0,y=s.length;++x<y/2&!n;)for(n=s.slice(i=0,x);i+x<y-x&&n;)n=(n[i+x]=s[i+x]-n[i++])<0?0:n;return n&&n.slice(1-x)+''==s.slice(1-x)?n:s}

Experimente online

40 bytes de Kevin Cruijssen

Outros 26 bytes de Arnauld

Minha primeira resposta ao código de golfe invalida as compensações potenciais e retorna a matriz original ou a nova, dependendo do que encontrar. Se alguém souber como torná-lo mais curto pls me avise, parece um jogo divertido.

Levi Faid
fonte
1
Eu não sou muito habilidoso com JavaScript, mas com alguns campos básicos (por exemplo, removendo colchetes desnecessários, alterando os posicionamentos do ++, alterando &&para &na primeira verificação, alterando ambos .toString()para +''etc.), reduzi seu código para 181 bytes . Se você ainda não os viu, pode ser interessante ler dicas de golfe em JavaScript e dicas de golfe em todos os idiomas . :)
Kevin Cruijssen 26/07
1
Ah, esqueci um ( function q(s)pode ser s=>): 171 bytes . Aproveite sua estadia! :)
Kevin Cruijssen 26/07
Obrigado por isso, vou ler. Eu não sou muito útil com javascript, mas tive que fazer um pouco ultimamente e pensei que isso poderia ser uma boa maneira de melhorar um pouco o meu tempo de inatividade
Levi Faid
1
Jogou golfe um pouco mais (sem todos os testes para que ele se encaixe como uma URL direta neste comentário)
Arnauld
1
Bem-vindo ao Code Golf SE! Esperamos que você aproveite seu tempo jogando golfe aqui!
Giuseppe
3

Haskell, 112 111 110 bytes

l=length
(!)=splitAt
f a=last$a:[x|i<-[1..l a],let (h,t)=i!a;o=h++zipWith(-)t o;(x,y)=l t!o,all(>=0)o,sum y<1]

Experimente online!

f a=                
      i<-[1..l a]                -- for all indices 'i' of the input array 'a'
      (h,t)=i!a                  -- split 'a' at 'i' into 'h' and 't'
                                 -- e.g. a: [1,2,3,4], i: 1 -> h: [1], t:[2,3,4] 
      o=                         -- calculate the original array by
        h++                      --   prepended 'h' to
        zipWith(-)t o            --   the (element-wise) difference of
                                 --   't' and itself
      (x,y)=l t!o                -- split 'o' at position <length of t>
                                 --
                                 -- example:
                                 --      a: [0,1,3,2,0]
                                 --      h: [0]
                                 --      t: [1,3,2,0]
                                 --   now
                                 --      o: [0,1,2,0,0]
                                 --      x: [0,1,2,0]
                                 --      y: [0]
                                 --
    ,                            -- 'o' is valid, if
     all(>=0)o                   --   all elements of 'o' are not negative
    ,sum y<1                     --   and 'y' is all zeros
  [x|         ]                  -- keep 'x' (a valid echo array) if 'o' is valid

 last $ a :[  ]                  -- if there's no echo, the list of 'x's is empty
                                 -- and 'a' is picked, else the last of the 'x's 
nimi
fonte
3

Wolfram Language (Mathematica) , 131 129 120 119 102 98 97 96 95 bytes

(w=#;Do[(w=v/.#)&/@Thread[#==PadLeft[v=Array[x,L-d],L]+v~PadRight~L]~Solve~v,{d,L=Tr[1^#]}];w)&

Experimente online!

-1 byte graças ao attinat : podemos escreverL=Tr[1^#] vez de L=Length@#quando o argumento é uma lista de números.

Explicação do código: Itere através da contração d(diferença entre os comprimentos de entrada e saída). Para cada comprimento da lista de saída, construa uma lista de incógnitas v={x[1],x[2],...,x[L-d]}e adicione-a à esquerda e à direita para o comprimento L(PadLeft[v,L]+PadRight[v,L] ), depois defina essa soma igual à lista de entrada e resolva as incógnitas x[1]...x[L-d]. Escolha a solução mais curta, que é a última gerada: apenas substitua a variável wtoda vez que uma solução for encontrada.

Versão sem golfe:

F = Function[A,                                  (* A is the input list *)
  Module[{L = Length[A],                         (* length of A *)
          v,                                     (* list of unknowns *)
          x,                                     (* unknowns in v *)
          w = A},                                (* variable for solution, defaults to A *)
    Do[                                          (* loop over shrinkage: d = Length[A]-Length[output] *)
      v = Array[x, L - d];                       (* list of unknowns to be determined *)
      (w = v /. #) & /@                          (* overwrite w with every... *) 
        Solve[                                   (* ...solution of... *)
          Thread[PadLeft[v,L]+PadRight[v,L]==A], (* ...v added to itself, left-padded and right-padded, equals A *)
          v],                                    (* solve for elements of v *)
    {d, L}];                                     (* loop for shrinkage from 1 to L (the last case d=L is trivial) *)
    w]];                                         (* return the last solution found *)
romano
fonte
-1 com em Tr[1^#]vez deLength@#
attinat 17/07
2

Geléia , 25 24 bytes

ðsạ\FḣL_¥,+¥Ż⁹¡$µⱮLṪ⁼¥Ƈȯ

Experimente online!

Um link monádico que pega e retorna uma lista de números inteiros. Tecnicamente, os resultados bem-sucedidos são aninhados em duas listas adicionais, mas quando executados como um programa completo, a saída implícita para stdout ignora as listas redundantes.

Nick Kennedy
fonte
2

Python 2 , 113 123 128 127 123 122 bytes

def f(a,i=1):
 e=a[:i]
 for v in a[i:-i]:e+=v-e[-i],
 return i<=len(a)/2and(min(e)>=0<e[-i:]==a[-i:]and e or f(a,i+1))or a

Experimente online!

1 byte thx para TFeld ; e 1 byte thx para Sebastian Kreft .

Em cada chamada para f, construímos um eco potencial de duração len(a)-i. A primeira parte é apenas os primeiros ibytes de a; o restante é calculado para que a 'soma ecoada' esteja correta para a seção 'sobreposta' da soma eco (ou seja, a soma eco está correta atéa[:-i] ).

Então a comparação muito curta, sem golfe, fornece:

if i>=len(a)/2+1:
    return a # because it can't be that short, so there is no echo
else:
    if min(e)>=0                       # all elements are non-negative
                 and e[-i:]==a[-i:]:   # and the tails are the same
        return e                       # it's a match!
    else:
        return f(a,i+1)                # recurse
Chas Brown
fonte
e+=[v-e[-i]]pode sere+=v-e[-i],
TFeld 11/07
você pode barbear mais um personagem fazendoi<=len(a)/2
Sebastian Kreft 18/07
2

Wolfram Language (Mathematica) , 93 bytes

(b=#;Do[a=#;Do[a[[i+j]]-=a[[j]],{j,2k}];a/.{__?(#>=0&),0}:>(b=a~Drop~-i),{i,k=Tr[1^#]/2}];b)&

Experimente online!

Retorna o menor eco presente na lista.

attinat
fonte
Parece que este falha em {1,1,1}e sobre {1,0,1}.
Roman
@ Roman não há eco para nenhum desses casos?
attinat 18/07
Como {1,1,1}não há eco, é necessário retornar a matriz original. Pois {1,0,1}eu diria que o eco é, {1}mas admito que não é claro quais são as regras.
Roman
Ah, certo. Obrigado pela captura!
attinat 19/07
2

PHP , 124 bytes

function($a){while(!$z&&++$y<$c=count($b=$a))for($x=0;$x<$c&$z=0<=$b[$x+$y]-=$b[$x++];);return array_slice($b,0,$c-$y)?:$a;}

Experimente online!

Explicação:

Crie uma cópia da matriz de entrada e faça um loop em cada deslocamento possível do eco. Para cada coluna, subtraia o valor na posição de deslocamento do valor correspondente na posição original para determinar o valor necessário para adicionar a entrada. Se for válido (>0 0), substitua o conteúdo dessa coluna por esse valor. Continue até o fim e, se nenhum valor for inválido, é uma resposta correta.

function( $a ) {
  // iterate through all possible offsets of echo
  while( ! $b && ++$y < $c = count( $b = $a ) ) {
    // create a copy of input array, iterate through all elements
    for( $x = 0; $b && $x < $c; ) {
      // if difference between the elements in the offset copy of 
      // the array is positive, subtract the value in the input array
      // from the offset array in the same column
      if ( ( $b[ $x+$y ] -= $b[ $x++ ] ) < 0 ) {
        // result is not valid, erase array and break out of loop
        $b = 0;
      }
    }
  }
  // truncate output array to correct size. if still contains values, 
  // it is a valid result. otherwise return the original array
  return array_slice( $b, 0, $c-$y ) ?: $a;
}
640KB
fonte
2

Python 3 , 111 bytes

def f(r,l=1):o=r[:l];o+=(v-o[-l]for v in r[l:]);return l<len(r)and(min(o)<any(o[-l:])and f(r,l+1)or o[:-l])or r

Experimente online!

A solução usa algumas idéias da solução do @Chas Brown , como a estrutura recursiva e a construção da matriz de saída. Enquanto isso, também faz algumas alterações nos critérios de julgamento, além de colocar o loop for em uma expressão de gerador para permitir uma solução de linha única. A versão ungolfed é mostrada a seguir. Aqui, a matriz outé calculada até o final da matriz de entrada e, em seguida, verificamos se os últimos lelementos são zero. Nesse caso, os primeiros len(arr)-lelementos serão retornados como resposta se todos eles não forem negativos.

Versão não-gasta e não recursiva

def remove_echo(arr):
    l = 1
    while l < len(arr):
        out = arr[:l]
        out += (v - out[-l] for v in arr[l:])
        if min(out) >= 0 and out[-l:] == [0] * l:
            return out[:-l]
        l += 1
    return arr

Experimente online!

Joel
fonte
1
@ 640KB Verifiquei se a resposta retornada corresponde ao resultado esperado no meu código e imprimo a mensagem apenas se houver uma incompatibilidade. Portanto, nenhuma saída significa que tudo está correto. Admito que isso possa ser confuso à primeira vista e atualizarei mais tarde para imprimir "Correto" em uma correspondência.
Joel
1
@ 640KB Atualizado.
Joel
1

Carvão , 62 bytes

≔⁰ζF⊘Lθ«≔E⊕ι⁰ηFLθ§≔ηκ⁻§θκ§ηκ¿⬤η¬κ≔⊕ιζ»F⁻Lθζ⊞υ⁻§θι∧ζ∧¬‹ιζ§υ±ζIυ

Experimente online! Link é a versão detalhada do código. Explicação:

≔⁰ζ

Suponha que não haja eco.

F⊘Lθ«

Tente todos os possíveis pontos de início de eco. Nota: Talvez eu tenha interpretado mal a pergunta e talvez não esteja tentando tamanhos suficientes de eco. Nesse caso, isso não seria necessário.

≔E⊕ι⁰η

Comece com uma matriz de zeros do mesmo tamanho que o ponto inicial do eco.

FLθ§≔ηκ⁻§θκ§ηκ

Para cada elemento da matriz original, subtraia o elemento da matriz de eco ciclicamente. Cada elemento na matriz de eco constrói assim a soma alternada dos elementos que se afastam.

¿⬤η¬κ≔⊕ιζ»

Se todas as somas alternadas forem zero, salve-o como um possível ponto de partida. (Portanto, se houver mais de uma possibilidade, será utilizado o maior ponto de partida possível.)

F⁻Lθζ⊞υ⁻§θι∧ζ∧¬‹ιζ§υ±ζ

Crie a matriz de eco subtraindo elementos após o ponto inicial do elemento calculado anteriormente apropriado.

Iυ

Transmitir para string para saída implícita em linhas separadas.

Neil
fonte