Esse desafio se baseia em uma charada que li em algum livro há um tempo atrás, que encontrei novamente aqui . Trata-se de balas disparadas de uma arma uma vez por segundo em velocidades variadas que viajam em linha reta para sempre. Quando uma bala atinge a outra, ambas são destruídas completamente. (Sinta-se à vontade para substituir todas as instâncias de "bala" por "míssil".)
A tarefa
Dada uma lista de velocidades da bala na ordem em que são disparadas, determine se todas as balas foram destruídas.
As regras
- Entrada é uma lista de números inteiros não negativos, separados por qualquer delimitador e com um caractere opcional antes e depois. Estas são entradas válidas:
1 2 3 4 5 6
e[1,2,3,4,5,6]
. O programador faz a escolha. - Produza um valor verdadeiro se pelo menos uma bala sobreviver para sempre e, caso contrário, um valor falso.
- As velocidades da bala são dadas em unidades por segundo.
- As balas se movem simultaneamente e continuamente.
- As balas podem colidir com compensações fracionárias.
- Múltiplas balas que atingem simultaneamente a mesma posição, seja em um deslocamento integral ou fracionário da origem, colidem umas com as outras.
Exemplos
Nestes diagramas, G
representa a arma, >
as balas e *
são momentos em que as balas colidem e explodem.
Truthy
Entrada: 0
0123456789
Time 0 G>
1 G>
2 G>
...
Resultado: 1
Entrada: 0 0 0
0123456789
Time 0 G>
1 G*
2 G>
3 G>
4 G>
...
Resultado: 1
Entrada: 1
0123456789
Time 0 G>
1 G >
2 G >
3 G >
...
Resultado: 1
Entrada: 2 1
0123456789
Time 0 G>
1 G> >
2 G > >
3 G > >
4 G > >
...
Resultado: 1
Entrada: 2 3 1
0123456789
Time 0 G>
1 G> >
2 G> >>
3 G > *
4 G >
5 G >
...
Resultado: 1
Falsy
Entrada: 1 2 3 4 5 6
Unit 1111111111
01234567890123456789
Time 0 G>
1 G>>
2 G> *
3 G> >
4 G> > >
5 G> > >>
6 G > > *
7 G > >
8 G > >
9 G >>
10 G *
111111111122222222223
0123456789012345678901234567890
Resultado: 0
Entrada: 1 0 0 3
Unit
0123456789
Time 0 G>
1 G>>
2 G* >
3 G> >
4 G >>
5 G *
(A segunda colisão é no momento 4,5)
Saída:0
Entrada: 2 1 2 3 6 5
Unit 1111111111
01234567890123456789
Time 0 G>
1 G> >
2 G>> >
3 G> * >
4 G> > >
5 G> * >
6 G > >
7 G > >
8 G >>
9 G *
1111111111
01234567890123456789
Resultado: 0
Entrada: 2 3 6
Unit
0123456789
Time 0 G>
1 G> >
2 G> >>
3 G *
Resultado: 0
fonte
1<enter>2<enter>3...
?Respostas:
Python 2,
388392388346342336331 bytesMeu Deus, essa coisa é enorme, mas acredito que realmente funciona. Depois de ver todos os meandros, esse desafio é ridiculamente difícil.
Não tenho certeza se posso explicar como funciona em detalhes sem digitar por horas, por isso darei um resumo executivo.
O grande laço while principal fica em loop até a lista de entradas não encolher.
O loop aninhado for (você pode acreditar que um loop aninhado for realmente o mais curto aqui?) Faz um loop sobre a velocidade de cada marcador e
usa-ocálculos em que momento esse marcador colidirá com cada marcador que vem depois. Aqui,numpy.roots
para calcular os""
está sendo usado para significar infinito (sem interseção). Um condicional extra deve ser incluído para garantir que os marcadores interrompidos sejam marcados como colidindo no momento em que aparecem, e não no tempo zero.Para cada número, controlamos qual marcador ele atingirá o mais rápido, se houver, e
o
será atualizado com os tempos mínimos de colisão para os marcadores envolvidos.Depois que esse loop duplo termina, iteramos sobre a lista de entradas e excluímos qualquer marcador que colidirá no mínimo de todos os tempos de colisão, se houver. Isso nos permite excluir simultaneamente um grande número de marcadores se todos colidirem no mesmo momento.
Em seguida, repetimos todo o processo nas balas restantes, pois elas podem conseguir agora que as balas com as quais teriam colidido foram destruídas.
Assim que nenhum marcador for excluído (indicado pela lista não diminuindo), escapamos do loop while e imprimimos o comprimento da lista restante. Portanto, esse programa não apenas imprime verdade se as balas sobrevivem, mas na verdade imprime exatamente o número de balas que sobrevivem.
EDIT: Agradecimentos especiais ao feersum por gerar casos de teste para me ajudar a encontrar bugs.
EDIÇÃO 2: salvou 42 bytes resolvendo manualmente a equação linear em vez de usar numpy e dividindo os horários de início em uma lista separada e reestruturando uma condicional.
EDIT 3: salvou 4 bytes renomeando intervalo
EDIT 4: Salva mais 6 bytes substituindo espaços duplos por tabulações. Além disso, feersum teve a gentileza de fornecer sua implementação usando frações e conjuntos para comparação. Eu joguei um pouco e ele sai para 331 bytes, amarrando minha solução.
EDIÇÃO 5: salvou 5 bytes removendo uma inicialização desnecessária e reescrevendo uma condição
fonte