Reparar os intervalos

30

Dada a entrada de uma lista de números inteiros positivos com alguns substituídos por 0, imprima a lista com os números ausentes que foram alterados para 0substituídos.

Características da lista de entrada:

  • A lista sempre terá um comprimento de pelo menos 2.

  • Vamos definir a lista de entrada como ae a "lista original" (ou seja, a lista antes dos números serem substituídos por 0s) como b. Para qualquer n, a[n]é b[n]ou 0.

  • Para qualquer n, b[n]é b[n-1] + 1ou b[n-1] - 1. Ou seja, os números em bsempre serão alterados 1em cada índice em relação ao anterior. O primeiro elemento é, obviamente, isento desta regra.

  • Para cada corrida de zeros em a(isto é, elementos consecutivos substituídos com 0), com xo que representa o índice de início do funcionamento e y que representa o fim, a[x-1]para a[y+1]irá sempre ser quer unicamente aumentando ou diminuindo exclusivamente. Portanto, haverá apenas uma maneira possível de preencher os zeros.

    • Isso também significa que nem o primeiro nem o último elemento da matriz pode ser zero.

Em termos mais simples, para preencher uma sequência de zeros, basta substituí-lo por um intervalo do número anterior ao número seguinte. Por exemplo, uma entrada de

1 2 0 0 0 6 7

deve produzir

1 2 3 4 5 6 7

Como esse é o , o código mais curto em bytes será vencedor.

Casos de teste:

In                      Out
-----------------------------------------------------
1 0 0 0 5 6 0 4 0 0 1 | 1 2 3 4 5 6 5 4 3 2 1
7 6 0 0 3 0 0 0 7 0 5 | 7 6 5 4 3 4 5 6 7 6 5
1 0 3 0 5 0 3 0 5 0 7 | 1 2 3 4 5 4 3 4 5 6 7
14 0 0 0 0 0 0 0 0 23 | 14 15 16 17 18 19 20 21 22 23
Maçaneta da porta
fonte
Em vez de 0nosso programa pode ter outro valor, como null?
Downgoat
@Downgoat Não, os números ausentes devem ser dados como 0.
Maçaneta

Respostas:

15

JavaScript (ES6), 72 66 64 54 53 bytes

Economizou 12 bytes graças a @Neil!

Guardado 1 byte graças a @IsmaelMiguel

a=>a.map((l,i)=>l?b=l:b+=a.find((q,r)=>r>i&&q)>b||-1)

Muito bom para JavaScript.


Experimente online (todos os navegadores funcionam)

Explicação

a=>  // Function with arg `a`
  a.map((l,i)=>  // Loop through input
    l?             // If nonzero
      b=l          // Set `b` to current number
    :a.find((q,r)=>r>i&q) // Otherwise look for the next nonzero number
     >b?           // If it's increased since nonzero last number   
       ++b:--b)    // Increasing? increase `b` (the previous nonzero number)
                   // otherwise decrease `b`
Downgoat
fonte
1
Eu acho que a.find((q,r)=>r>i&&q)>b?++b:--bé o mesmo queb+=a.find((q,r)=>r>i&&q)>b||-1
Ismael Miguel
@IsmaelMiguel isso é inteligente, obrigado!
Downgoat
De nada. Estou feliz que funcionou para você.
Ismael Miguel
Eu acho que você pode substituir && com apenas & (Só notei que você tem um & na explicação e dois na resposta)
Charlie Wynn
7

MATL , 11 12 bytes

fGXzGn:3$Yn

Funciona com a versão atual (13.0.0) do idioma / compilador.

Experimente online!

f        % implicitly input array. Indices of nonzero elements (*)
GXz      % push input and get its nonzero elements (**)
Gn:      % vector [1,2,...,n], where n is input length (***)
3$Yn     % interpolate at positions (***) from data (**) defined at positions (*)
Luis Mendo
fonte
7

Haskell, 68 61 58 bytes

g(a:b:r)=[a..b-1]++[a,a-1..b+1]++g(b:r)
g x=x
g.filter(>0)

Exemplo de uso: g.filter(>0) $ [7,6,0,0,3,0,0,0,7,0,5]-> [7,6,5,4,3,4,5,6,7,6,5].

Como funciona: remova zeros da entrada e ligue g. Seja ao primeiro e o bsegundo elemento da lista restante. Concatenar as listas de acima para b-1e de abaixo para b+1(um deles estará vazia) e uma chamada recursiva com adescartado.

Edit: @Zgarb salvou 3 bytes. Obrigado!

nimi
fonte
6

Mathematica, 59 bytes

#//.{a___,x_,0..,y_,b___}:>{a,##&@@Range[x,y,Sign[y-x]],b}&

Caso de teste

%[{1,0,3,0,5,0,3,0,5,0,7}]
(* {1,2,3,4,5,4,3,4,5,6,7} *)
njpipeorgan
fonte
4

Perl, 47 45 44 39 37 bytes

Inclui +1 para -p

s%\S+%$p+=/\G(0 )+/?$'<=>$p:$&-$p%eg

Espera a lista em stdin. Exemplo: eco 1 0 3 0 1 | perl -p file.pl

Ton Hospel
fonte
Eu vejo uma cópia colando aqui .. ;-) Bem feito btw.
Kenney
3

Geléia, 12 11 bytes

ḢWW;ḟ0Ṫr¥\F

Experimente online!

Versão alternativa, 8 bytes (não concorrente)

Infelizmente, o Jelly's popnão lançou para iterável, na versão mais recente que antecede esse desafio. Isso foi corrigido e o seguinte funciona na versão atual.

ḟ0Ṫr¥\FḊ

Experimente online!

Como funciona

ḢWW;ḟ0Ṫr¥\F  Main link. Input: A (list)

Ḣ            Pop the first element of A. Let's call it a.
 WW          Yield [[a]].
   ;         Concatenate with the popped A.
             This wraps the first element of A in an array.
    ḟ0       Filter; remove all zeroes.
        ¥    Create a dyadic chain:
      Ṫ        Pop the last element of the left argument.
       r       Call range on the popped element and the right argument.
         \   Reduce the modified A by this chain.
          F  Flatten the resulting list of ranges.

Na versão alternativa, ḢWW;torna-se desnecessário. No entanto, como o primeiro elemento é convertido em iterável antes do popping, ele não é realmente modificado. O final remove a duplicata do primeiro elemento.

Dennis
fonte
3

Retina, 39 34 31 bytes

3 bytes salvos graças a @Martin.

+`1(1*) (?= +((1)\1)?)
$0$1$3$3

Recebe entrada e dá saída em unário.

O código preenche iterativamente todos os lugares vazios (0s) previous_number - 1 + 2 * if_next_nonzero_number_bigger. previous_number - 1é $1e if_next_nonzero_number_biggeré $3.

Com E / S decimal, o código tem 51 bytes, como você pode ver no interpretador online com todos os casos de teste .

randomra
fonte
Você pode salvar outro byte, omitindo o primeiro 1na cabeça de impressão.
Martin Ender
@ MartinBüttner Certo, editado.
randomra
2

GNU Sed (com execextensão usando bash), 61

A pontuação inclui +1 para a -ropção sed.

:
s/( 0)+ /../
s/\w+..\w+/{&}/
s/.*/bash -c 'echo &'/e
/ 0/b
  • Encontre execuções de 0s e substitua-as..
  • Coloque chaves entre os números dos pontos de extremidade para criar uma expansão de chaves de bash como {1..4}nos pontos de extremidade locais. A beleza das expansões de chaves bash aqui é que a sequência gerada sempre será executada na direção certa, independentemente de o início ou o fim ser maior.
  • Use a eopção do scomando para chamar o bash para avaliar essa expansão de chave
  • Se mais 0s forem encontrados, volte ao início.

Ideone.

Trauma Digital
fonte
2

Python 2, 195 111 bytes (obrigado Alex !)

t=input()
z=0
for i,e in enumerate(t):
 if e:
  while z:t[i-z]=e+z if l>e else e-z;z-=1
  l=e
 else:z+=1
print t

Entrada: deve ser um [list]de ints
Saída: [list]de ints

vageli
fonte
Me desculpe por isso! Fixo. Obrigado pela atenção.
vageli
Não se preocupe. Ótima solução. :) Você pode reduzi-lo a 112 bytes usando isso , que é a mesma abordagem, apenas um pouco mais. Também temos uma coleção de dicas para jogar golfe em Python aqui .
Alex A.
1

Perl, 85 82 bytes

inclui +1 para -p

s/(\d+)(( 0)+) (\d+)/$s=$1;$e=$4;$_=$2;$c=$s;s!0!$c+=$e<=>$s!eg;"$s$_ $e"/e&&redo

Espera a lista em stdin. Exemplo: echo 1 0 3 0 1 | perl -p file.pl.

Isso usa um regexp aninhado. Um pouco legível:

s/(\d+)(( 0)+) (\d+)                  # match number, sequence of 0, number
 /
    $s=$1;                            # start number
    $e=$4;                            # end number
    $_=$2;                            # sequence of ' 0'
    $c=$s;                            # initialize counter with start number
    s!0! $c += $s <=> $e !eg          # replace all 0 with (in|de)cremented counter
    "$s$_ $e"                         # return replacement
 /e
&& redo                               # repeat until no more changes.
Kenney
fonte
1

Python 2, 92 88 bytes

(Variável intermediária removida)

t=filter(bool,input())
print sum([range(o,p,cmp(p,o))for o,p in zip(t,t[1:])],[])+t[-1:]
Orez
fonte
1

Pitão, 17 bytes

u+G+treGHHfTtQ[hQ

Como funciona:

u                 reduce
              [hQ     seed: the first element of input, in a list
                      iterable:
          tQ              all except the first element of input
        fT                remove if 0
                      lambda: G is the list to be returned, H is the current item
 +G                       append to return list
    reGH                  a range from the last element of the return list and the current item
   +                      concatenated with
        H                 the last item (this step forms a bidirectional inclusive list)

Em outras palavras: todos os zeros são removidos da entrada e, em seguida, um intervalo exclusivo é inserido entre cada elemento. Esse intervalo é de comprimento zero em elementos separados apenas um.

Cameron McCluskie
fonte
1

Vim: 231 Comandos Chave

Observe que qualquer ^ que precede um caractere significa que você deve manter o controle enquanto digita esse caractere

mbomayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0wmbyiwo@f @d^V^[@z ^["fc0"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0dd`bAe^[0@e 

Etapas para que você possa executar isso também!

  1. Copie a linha no Vim
  2. Digite :s/\^V/<Ctrl-V><Ctrl-V>/ge pressione enter (os dois s devem fornecer um ^ V azul)
  3. Digite :s/\^R/<Ctrl-V><Ctrl-R>/ge pressione enter (você deve ver azul ^ Rs agora)
  4. Digite :s/\^X/<Ctrl-V><Ctrl-X>/ge pressione enter (você verá azul ^ Xs agora)
  5. Digite :s/\^O/<Ctrl-V><Ctrl-O>/ge pressione enter
  6. Digite :s/\^A/<Ctrl-V><Ctrl-A>/ge pressione enter
  7. Digite :s/\^\[/<Ctrl-V><Ctrl-[>/ge pressione enter (este comando é um pouco diferente porque eu precisava escapar do [)
  8. Digite 0"yy$. O comando agora está armazenado no registro y
  9. Configure a entrada em uma linha e execute com @y

Se alguém souber uma maneira melhor de compartilhar o comando, entre em contato. Eu sei que isso é demorado, mas é o melhor que eu poderia fazer.

Entrada / Saída

A sequência de entrada deve estar sozinha em qualquer linha do arquivo. 1 0 0 4 3 0 0 0 7

A saída simplesmente substituirá a sequência de entrada 1 2 3 4 3 4 5 6 7

Explicação

Algoritmo

  1. Comece com um número diferente de zero, verifique se não é o último número
  2. Encontre o próximo número diferente de zero
  3. Pegue a diferença deles. Se a resposta for negativa, você deve diminuir para reparar o intervalo, caso contrário, aumentar para reparar o intervalo.
  4. Volte para o primeiro caractere e substitua cada zero aumentando / diminuindo o número anterior.
  5. Repita até chegar ao último caractere

Macros usadas

@e - Verifique se há fim. O último número terá um e anexado a ele. Se o número sob o cursor tiver um e no final, exclua ee interrompa a execução. Caso contrário, inicie um ciclo de interpolação com @b.

mbyiwo^R"Exe@b^[0fel"ty2ldd`b@t

@b - Inicia o ciclo de interpolação. Salve o número sob o cursor para uma operação de subtração (@s) e encontre o próximo termo diferente de zero (@f)

mayiwo^R"^V^X ^["sy0dd`a@f

@s - Armazena o comando de subtração para usar em @d. É simplesmente (val)^Xonde (val)está o número no início da etapa de interpolação. Isso é definido pelo comando @b.

@f - Encontre o próximo termo diferente de zero. Escreva o valor atual no registro sem nome, depois escreva @f @dna próxima linha e execute @z. Isso repetirá esse comando se o número for zero e executará @d se não for.

wmbyiwo@f @d^[@z

@z - Execução condicional se o registro sem nome for 0. Este comando espera dois comandos em uma nova linha no formato command1 command2. Se o registro sem nome for 0, command1é executado, caso contrário, command2é executado. Observe que nenhum dos comandos pode conter espaços.

 IB0 B^R" ^OWB0 ^OA B0^[0*w"tyiWdd`b@t`

@t - Registro de comando temporário. Armazena vários comandos por um curto período de tempo antes de executá-los. Usado principalmente nas instruções if.

@d - Determina a direção da interpolação. Subtrai o primeiro número da sequência do número sob o cursor (usando @s). Se o resultado for negativo, a interpolação deve diminuir, para que ^ X seja salvo em @a. Caso contrário, devemos incrementar para que ^ A seja salvo em @a. Depois que isso for salvo, volte para o início desse ciclo de interpolação e execute @i para realmente interpolar

yiwo^V^X^R"^[0l@sa^V^A-^[0f-"ayhdd`a@i

@a - Armazena ^Aou ^Xaumenta ou diminui durante a etapa de interpolação. Isso é definido pelo comando @d.

@i - Interpolar. Copie o número no local atual para @x e passe para o próximo número. Se esse número for zero, substitua-o por @x e execute @a para modificá-lo corretamente para cima ou para baixo e repita este comando. Se o número não for zero, chegamos ao final desse ciclo de interpolação. Um novo deve ser iniciado com esse número como o início; portanto, execute @e para verificar o final e execute novamente.

"xyiwwmbyiwocw^V^Rx^V^[@a@i @e^[@z

@x - Registro de armazenamento temporário. Usado no comando interpolar (@i)

Quebrando as teclas digitadas

mbo :Set b mark to current position and open a new line below to write macros
mayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0 :Write to @b and reset line

yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0 :Write to @d and reset line

mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0 :Write to @e and reset line

wmbyiwo@f @d^V^[@z ^["fc0 :Write to @f and reset line

"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0 :Write to @i and reset line

IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0 :Write to @z and reset line

dd`b :Delete this line and move cursor back to original line

Ae^[ :Append an e to the last number

0@e  :Move to the beginning of the line and run
Dominic A.
fonte
0

Python 3.5, 159 bytes

uma solução recursiva

def f(s):
 h=s[0]
 g=lambda s,h,v:h*(h[-1]==s[0])if len(s)==1else(g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v))*(s[0]==0 or h[-1]==s[0])
 return g(s,[h],1)

Ungolfed

def f(s):
    h=s[0]
    def g(s,h,v):
        if len(s)==1:
            if h[-1]!=s[0]:
                r=[]
            else:
                r=h
        else:
            if s[0]==0:
                r=g(s[1:],h+[h[-1]+v],v)
            elif h[-1]!=s[0]:
                r=[]
            else:
                r=g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v)
        return r
return g(s,[h],1)

Na solução de golfe, substituo as condições usando o fato de que h*True=heh*False=[]

Resultado

>>> f([7, 6, 0, 0, 3, 0, 0, 0, 7, 0, 5])
[7, 6, 5, 4, 3, 4, 5, 6, 7, 6, 5]
Erwan
fonte
0

Perl 6 , 54 bytes

{$_=$^a;1 while s/:s(\d+) 0 + (\d+)/{+~$0...+~$1}/;$_}
smls
fonte
0

MATLAB, 39 38 37 bytes

@(a)interp1(find(a),a(a>0),find(a/0))

Função anônima que interpola linearmente entre os pontos em a. find(a)é uma matriz de índices de elementos diferentes de zero ae a(a>0)são os valores positivos. Economizei 1 byte graças à sugestão de um amigo, em >vez de ~=.

MattWH
fonte