Faça um contador Geiger


29

Um contador Geiger é um dispositivo usado para detectar radiação.

Faremos um programa de contador Geiger.

Como todos sabemos, quando a radiação atinge um programa de computador, ela remove exatamente 1 byte aleatoriamente. Portanto, um programa de contador Geiger é um programa que não faz nada, mas quando qualquer byte é removido, o programa modificado é impresso beep, para indicar a presença de radiação.

As respostas serão pontuadas em bytes, com menos bytes sendo melhores. As respostas devem ter pelo menos 1 byte.

Seu programa pode imprimir beepcom uma linha nova à direita ou uma nova linha para saída vazia, desde que seja consistente. Seu programa também pode usar um caso diferente para beeptais como BEEP, bEEPou Beeptanto tempo como ele faz isso de forma consistente.



7
Podemos usar o caractere de controle BEL para emitir um sinal sonoro real?
Jo rei

2
@JoKing Eu brinquei com a idéia, é divertida, mas tenho que dizer não. É muito substancialmente diferente.
Wheat Wizard

2
Eu quero ver uma solução na Retina.
mbomb007

3
Estou tentando descobrir como fazer isso no SMBF ... mas a única maneira de comparar duas células envolve alterá-las. E no SMBF, as células que você precisa verificar são as células em que o programa está sendo executado no momento. Portanto, é como o Princípio da Incerteza de Heisenberg. Portanto, você deve determinar se alguma coisa mudou usando apenas o fluxo de controle.
mbomb007

Respostas:


24

Perdido , 303 293 263 253 238 228 bytes

v^"peeb"<\>"beepvv"((>@@>>%%>>(((((([[[[[[\
>>>>>>>>>//>>>>>>>>>>>>>>/>>/>>>>>>>>>>>>>\\
>>>>>>>>//>>>>\>>>>>>>>>>/>>>>>>>>>>>>>>>>>\\
>/>>>>>>>/>>>>>>>>>>>>\>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>\\>>>>\>>>>>>>>>>>>>>>>\

Experimente online!

Script de verificação (emprestado da resposta do usuário 202729 ). Infelizmente, isso só pode testar metade do código de cada vez, mas tenha certeza de que testei o programa inteiro.

Ai, essa foi difícil. Vou citar a resposta excluída da WW:

Lost é talvez o idioma mais interessante para esse desafio. Em Lost, o local e a direção de início do ponteiro são inteiramente aleatórios; portanto, para criar programas determinísticos, é necessário considerar todos os locais e direções de início possíveis. Ao mesmo tempo, pela natureza desse desafio, você também deve levar em consideração a remoção de qualquer byte único.

Infelizmente, sua resposta não levou em consideração a remoção de novas linhas, o que estragou tudo.

Explicação:

(observe que alguns bytes podem estar desativados aqui e ali)

Primeiro vamos falar sobre a estrutura geral do código:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\       Processing line
>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\      Beep line
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\     Back-up beep line
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\    Back-up return line
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\    Return line

Tudo, exceto a linha de processamento, deve ser inteiramente composto por um >ou um dos \/. Por quê? Bem, como exemplo, vamos remover uma nova linha:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\

A primeira linha agora é muito mais longa que o resto do bloco. Se um ponteiro aparecer em um não >\/caractere com movimento vertical, ele ficará preso em um loop infinito.


A maior parte do detector de radiação é a seção no final de cada linha.

 \
 \\
 >\\
 >>\\
 >>>\

Normalmente, um IP que passa por isso da primeira linha sai da última linha. No entanto, se algum caractere da linha for removido, essa linha mudará para um, por exemplo:

 \
 \\
 >\\
 >\\
 >>>\

E, em vez disso, o IP sai da linha que está faltando um byte (com exceção da última linha, onde sai do penúltimo para o último).

A partir daí, cada uma das quatro primeiras linhas será redirecionada para a segunda linha:

v
>>>>>>>>>>
>>>>>>>>//
>/

O que levará a um dos dois beep.

v^"peeb"<<\/"beepvv"((>
>>>>>>>>>>//

Se algum dos bytes no primeiro beeper foi removido, ele passa para o segundo:

v^^"peb"<<\/"beepvv"((>
>>>>>>>>>>>//

Os dois beepentão retornam à primeira linha e ao término @.

Algumas outras partes diversas:

O (((((([[[[[[[é usado para limpar a pilha quando o ponteiro começa dentro de um par de aspas e acaba empurrando a primeira linha inteira para empilhar. Infelizmente, isso deve ser longo, porque a primeira nova linha pode ser removida para tornar a primeira linha duas vezes maior. A experiência de gerar a beeparitmética de uso em vez de aspas acabou por mais tempo.

Os \s e /s espalhados pelas linhas existem para bytes de golfe na linha superior do código, redirecionando o ponteiro para as linhas corretas. Como a maioria das linhas de fundo é apenas de preenchimento, apenas a linha de cima pode ser jogada no golfe. Se alguém tiver alguma idéia para uma pilha mais curta à prova de radiação, mais clara do que eu tenho agora, fique à vontade para comentar.


Por curiosidade, quão útil foi a resposta parcial que eu postei no chat? Vi algumas semelhanças nas versões anteriores e gostaria de saber se estava no caminho certo.
Wheat Wizard

@WW eu já tinha trabalhado nele até então, mas a \/separar os beepempurra e o fato de que apenas uma das citações necessária uma cláusula de saída ajudou
Jo rei

20

Hexagonia , 38 bytes

.....;p;<>b;e;/<b;e;;p...@@.......;@..

Experimente online!

Programa de verificação.


Explicação

Utilizamos a detecção automática de hexágonos do comprimento lateral do hexágono aqui.

Se nenhum bytes for removido, o programa terá o comprimento lateral 4 e terá a seguinte aparência:

Programa sem nenhum bytes removido

Se, no entanto, um byte é removido. Existem 2 casos.

  1. O byte removido é após o segundo <.

    O fluxo de execução seria:

    Programa com o último byte removido

    Existem 2 consecutivas @na 5ª linha; portanto, mesmo se uma delas for removida, o IP atingirá com segurança a @.

  2. O byte removido é igual ou antes do segundo <.

    Em seguida, a segunda metade permanecerá intacta, e o IP não será mais redirecionado para cima por isso <. Imagem do fluxo de execução:

    Programa com o segundo <code> <</code> removido


19

Hexagonia , 34 29 bytes

//..>;e;<b@;p;/|/;e;;\.b@;p<@

Experimente online! Verificação!

Explicação:

Aqui está o código normal formatado em um hexágono apropriado usando HexagonyColorer :

Sem câncer ...

A duplicação //no início garante que esse caminho seja sempre seguido. Se qualquer caractere for removido, ele @será removido do caminho, sendo movido um para trás ou sendo removido:

Câncer!

Nesse caso, removemos um caractere após o |, o que o faz seguir esse caminho, imprimindo beep:

Primeiro sinal sonoro

Se, em vez disso, removermos um caractere antes do |(ou do |próprio), seguiremos a outra impressora de bipes:

Segundo bipe

Contamos com todas as possibilidades e usamos apenas beepas partes não irradiadas do programa.


13

Brainfuck auto-modificável , 73 63 bytes

<<[[[[<<]]>[[.>>..>>.[,>]]]]   bbeepp+[<<<]>>[[>]>>>.>>..>>.,+]

Experimente online! Verificação!

Os espaços no meio do código estão realmente representando NUL bytes.

Explicação:

O código é dividido em duas seções por 3 NUL bytes no meio. Ambos basicamente imprimem beepse a outra seção for irradiada (com algumas exceções).

Primeiro, o <<[[princípio é garantir que todos os ]s sejam correspondidos a qualquer momento. [s não tentará procurar uma correspondência ]se a célula for positiva, enquanto ]s o fazem . Se algum ]pular de volta para um desses colchetes, ele geralmente volta imediatamente porque a célula está 0.

A próxima parte, [[<<]]>depois verifica se o comprimento da seção 2 é uniforme. Nesse caso, ele executa a outra metade da seção 1, que é impressa beepusando o bbeeppno início da seção 2.

[[.>>..>>.[,>]]]]

Em seguida, limpa toda a seção 2 para que não seja executada.

Na seção 2, verificamos se o comprimento da seção 1 e os bytes NUL são divisíveis por 3com +[<<<]>>.

[[>]>>>.>>..>>.,+]

Da mesma forma, imprimimos beep.


10

Z80Golf , 53 36 34 bytes

-16 bytes graças a @Lynn
-2 bytes graças a @Neil

Como este é apenas o código de máquina Z80, há muitos imprimíveis neste, portanto, tenha um xxd -rhexdump -reversible:

00000000: ddb6 2120 10dd b615 280c 003e 62ff 3e65  ..! ....(..>b.>e
00000010: ffff 3e70 ff76 003e 62ff 3e65 ffff 3e70  ..>p.v.>b.>e..>p
00000020: ff76                                     .v

Experimente online! (testador exaustivo em Python)

Explicação

z80golf é a hipotética máquina Z80 da Anarchy Golf, onde call $8000é um putchar, call $8003é um getchar, haltfaz com que o intérprete saia, seu programa é colocado $0000e todas as outras memórias são preenchidas com zeros. Tornar os programas à prova de radiação na montagem é bastante difícil, mas uma técnica genericamente útil é usar instruções idempotentes de um byte. Por exemplo,

or c        ; b1    ; a = a | c

é apenas um byte e a | c | c == a | c, portanto, pode ser protegido contra radiação apenas repetindo a instrução. No Z80, uma carga imediata de 8 bits é de dois bytes (onde a imediata está no segundo byte), portanto, você também pode carregar alguns valores nos registros de maneira confiável. Foi o que fiz originalmente no início do programa, para que você possa analisar as variantes mais longas que arquivei na parte inferior da resposta, mas depois percebi que existe uma maneira mais simples.

O programa consiste em duas cargas independentes, onde uma delas pode ter sido danificada pela radiação. Verifico se um byte foi removido e se o byte removido foi anterior à segunda cópia da carga, verificando os valores de alguns endereços de memória absolutos.

Primeiro, precisamos sair se nenhuma radiação for observada:

    or a, (ix+endbyte) ; dd b6 21 ; a |= memory[ix+0x0021]
    jr nz, midbyte     ; 20 10    ; jump to a halt instruction if not zero

Se algum byte foi removido, todos os bytes serão alterados e $0020conterão o último 76, assim $0021será um zero. Podemos nos dar ao luxo de irradiar o início do programa, mesmo que não haja praticamente redundância:

  • Se o deslocamento do salto $10for removido, a radiação será detectada corretamente, o salto não será realizado e o deslocamento não será importante. O primeiro byte da próxima instrução será consumido, mas como ele foi projetado para resistir à remoção de bytes, isso não importa.
  • Se o código de operação do salto $20for removido, o deslocamento do salto $10será decodificado como djnz $ffe4(consumindo o próximo byte de instrução como o deslocamento - veja acima), que é uma instrução de loop - decremento B, e saltará se o resultado não for zero. Como ffe4-ffffé preenchido com zeros nop, o contador do programa é executado, isso executará o início do programa 256 vezes e, finalmente, continuará. Estou surpreso que isso funcione.
  • Remover o $ddfará com que o restante do trecho decodifique como or (hl) / ld ($1020), hle deslize para a próxima parte do programa. A ornão mudará nenhum registros importantes, e porque HL é zero neste ponto, a gravação também vai cancelar.
  • A remoção do $b6decodificador fará com que o restante decodifique ld ($1020), ixe prossiga como acima.
  • Remover o $21fará com que o decodificador coma $20, desencadeando o djnzcomportamento.

Observe que o uso or a, (ix+*)economiza dois bytes, ld a, (**) / and a / and agraças à verificação integrada de zero.

Agora precisamos decidir qual das duas cópias da carga útil executar:

    or (ix+midbyte)  ; dd b6 15
    jr z, otherimpl  ; 28 0c
    nop              ; 00
    ; first payload
    ld a, 'b'        ; 3e 62
    rst $0038        ; ff
    ld a, 'e'        ; 3e 65
    rst $0038        ; ff
    rst $0038        ; ff
    ld a, 'p'        ; 3e 70
    rst $0038        ; ff
midbyte:
    halt             ; 76
otherimpl:
    nop              ; 00
    ld a, 'b'        ; 3e 62
    ; ...            ; ...
    rst $0038        ; ff
endbyte:
    halt             ; 76

As duas cópias são separadas por um nop, pois é usado um salto relativo para escolher entre elas, e a radiação poderia ter mudado o programa de uma maneira que faria o salto pular o primeiro byte após o destino. Além disso, o nop é codificado como zero, o que facilita a detecção de bytes deslocados. Observe que não importa qual carga útil é escolhida se o switch estiver corrompido, porque as duas cópias estarão seguras. Vamos garantir que ele não entre na memória não inicializada:

  • A exclusão $ddfará com que os próximos dois bytes decodifiquem como or (hl) / dec d. Clobbers D. Não é grande coisa.
  • A exclusão $b6criará uma codificação mais longa não documentada para dec d. O mesmo que acima.
  • A exclusão $15lerá o $28deslocamento como deslocamento e a execução prosseguirá no $0c, como abaixo.
  • Quando $28desaparece, o $0cé decodificado como inc c. A carga útil não se importa c.
  • Exclusão $0c- é para isso que serve o nop. Caso contrário, o primeiro byte da carga útil teria sido lido como deslocamento de salto e o programa entraria na memória não inicializada.

A carga útil em si é bem simples. Eu acho que o tamanho pequeno da string torna essa abordagem menor que um loop, e é mais fácil tornar a posição independente dessa maneira. O ein se beeprepete, para que eu possa raspar um ld a. Também, porque toda a memória entre $0038e $8000é zerado, eu posso cair através dele e usar um mais curto rstvariante da callinstrução, que só funciona para $0, $8, $10e assim por diante, até $38.

Abordagens mais antigas

64 bytes

00000000: 2e3f 3f2e 3f3f 7e7e a7a7 201f 1e2b 2b1e  .??.??~~.. ..++.
00000010: 2b2b 6b00 7ea7 2814 003e 62cd 0080 3e65  ++k.~.(..>b...>e
00000020: cd00 80cd 0080 3e70 cd00 8076 003e 62cd  ......>p...v.>b.
00000030: 0080 3e65 cd00 80cd 0080 3e70 cd00 8076  ..>e......>p...v

58 bytes

00000000: 2e39 392e 3939 7e7e a7a7 2019 3a25 00a7  .99.99~~.. .:%..
00000010: 2814 003e 62cd 0080 3e65 cd00 80cd 0080  (..>b...>e......
00000020: 3e70 cd00 8076 003e 62cd 0080 3e65 cd00  >p...v.>b...>e..
00000030: 80cd 0080 3e70 cd00 8076                 ....>p...v

53 bytes

Este tem uma explicação no histórico de edições, mas não é muito diferente.

00000000: 3a34 00a7 a720 193a 2000 a728 1400 3e62  :4... .: ..(..>b
00000010: cd00 803e 65cd 0080 cd00 803e 70cd 0080  ...>e......>p...
00000020: 7600 3e62 cd00 803e 65cd 0080 cd00 803e  v.>b...>e......>
00000030: 70cd 0080 76                             p...v

E se: qualquer saída não vazia foi boa em vez de emitir um sinal sonoro

1 byte

v

halté o programa normalmente, mas se a radiação o remover, a memória estará cheia de zeros, fazendo $8000executar um número infinito de vezes, imprimindo muitos bytes nulos.


Desde que acomeça em zero, você não pode usar em or a, (N);vez de ld a, (N); and a;? Parece que você pode salvar alguns bytes dessa maneira.
Neil

@ Neil Boa pergunta! Infelizmente, no Z80, apenas as instruções de carregamento podem receber endereços como este.
NieDzejkob 08/08/19

Ugh, já faz muito tempo desde que eu fiz alguma programação Z80 ... talvez eu estivesse pensando or a, (ix + N)?
Neil

@ Neil, na verdade, isso existe, e o IX começa com zero também ... infelizmente, salvar um byte nessa área faz com que os bytes sejam alterados de forma que 20 19o início se torne 20 18, e remover o 20cria um salto incondicional para trás; nop deve ser adicionado após o primeiro salto no programa, revertendo o byte save.
NieDzejkob 08/08/19

Ah, isso é uma vergonha. Obrigado por verificar!
Neil


4

Klein , um de cada topologia, totalizando 291 bytes

Depois de ver a resposta da WW usando a 001topologia, decidi ver como seria difícil criar um contador Geiger para cada topologia. (Spoiler: muito difícil. É difícil descobrir para onde o ponteiro vai sem gestos que me fazem parecer que estou descobrindo qual mão é a minha esquerda)

Verificação!

(Também pensei em escrever um programa que seja um contador Geiger válido em todas as topologias, mas isso pode ter que esperar. Se mais alguém quiser tentar, estou oferecendo uma recompensa de 500 representantes)

000 e 010, 21 bytes

<<@"peeb"/
.@"peeb"<\

Experimente 000 online! e tente 010 online!

Isso é portado da minha ><>solução . Obviamente, isso funciona 000, já que essa é a topologia padrão para a maioria das linguagens 2D, mas fiquei surpreso que ela também funcione 010.

001 e 011, 26 bytes

!.<<@"peeb"/
.@"peeb"..<..

Experimente o 001 online! e tente 011 online!

Este é copiado diretamente da resposta da WW . Obrigado!

100, 21 bytes

//@"peeb"\
@"peeb".</

Experimente online!

101, 21 bytes

//@"peeb"/
@"peeb".<!

Experimente online!

110, 26 bytes

<.<@"peeb"\\
.\@."peeb".\<

Experimente online!

111, 24 bytes

<<@"peeb"<\
...@"peeb"//

Experimente online!

200, 21 bytes

<<@"peeb"\
@"peeb".!/

Experimente online!

201, 31 bytes

\\.\.@"peeb"</./
./...@"peeb"<\

Experimente online!

De longe, o mais chato.

210, 26 bytes

/\\@"peeb"</\
/@.."peeb"<\

Experimente online!

211, 27 bytes

\\."peeb"((</
!/@@<"peeb"<\

Experimente online!

O único onde eu tinha que lidar ao entrar no bipe pelo lado direito.


Eu ficarei feliz em segundo a recompensa.
Assistente de trigo


2

Encantos Rúnicos , 29 bytes

>>yyLL@"peeb"/
     @"peeb"L\

Experimente online!

Essencialmente o mesmo que a resposta Klein 000 ou> <> resposta (comecei com a resposta Klein). A única mudança realmente necessária foi transformar o <into Le .into  (tradução dos símbolos de comando), inserir os pontos de entrada IP (necessidade 2, caso contrário, uma exclusão resultaria em um programa não-compilável) e a inserção do ycomando dela para obter o dois IPs para mesclar (imprimindo apenas um beep), novamente, precisando de dois. Também é necessário inserir NOPs adicionais para manter os comprimentos das linhas iguais. Klein também usa convenientemente @para "imprimir e finalizar".

Nenhuma capacidade de utilizar o espaço em branco no canto inferior esquerdo, pois qualquer refletor para mudar de direção inibe a capacidade de detectar radiação. por exemplo (26 bytes, irradiado y):

/yLL@"peeb"/
\<<  @"peeb"L\

Não imprime saída, devido ao segmento de entrada dobrado, causando uma nova reflexão no terminador da linha inferior.



1

Wumpus , 37 34 32 31 bytes

777*7..@ $o&4"beep"|"@peeb"4&o@

Experimente online! Verificação!

Esta solução usa o fato de que .salta para um módulo de posição a duração do programa.

Como alternativa para a mesma quantidade de bytes


" @o&4"beep"}@
@o&4"beep"}$}  

Experimente online! Verificação!

Este utiliza a diferença na direção do ponteiro para comprimentos de linhas pares e ímpares. (Eu realmente não sei como o primeiro "realmente funciona quando a nova linha é removida)


1

Klein (001), 26 bytes

!.<<@"peeb"/
.@"peeb"..<..

Experimente online!

Verificar!

Explicação

Este programa aproveita a topologia exclusiva da Klein, em particular a topologia 001 , que é uma garrafa Klein.

Não editado, o programa segue o caminho da execução:

Caminho laranja

A remoção de um byte do programa pode afetá-lo de 4 maneiras (cada uma em uma cor diferente):

Seções do programa

A primeira coisa a notar é que <<sempre desviará o ip à esquerda da origem no início. Se um dos <s é excluído, o outro substitui. Portanto, se algum byte for removido da seção vermelha, o seguinte caminho de execução será seguido:

Caminho vermelho

Se o byte azul for removido, obtemos o caminho muito simples:

insira a descrição da imagem aqui

Se a nova linha for removida, obtemos o caminho:

Caminho verde

O caminho amarelo é um pouco mais complexo. Como a linha inferior é uma mais longa que a linha superior, quando o programa é elevado ao quadrado no início da execução, um caractere virtual é adicionado ao final da primeira linha para torná-los do mesmo tamanho. Se qualquer byte na segunda linha for removido, a linha será reduzida e esse caractere virtual não será adicionado. Isso é importante porque !normalmente salta sobre o personagem virtual, mas, na sua ausência, salta sobre /ele.

Caminho amarelo


11
Você poderia port minha ><>solução 000para 21 bytes
Jo rei

@JoKing Acho que seria melhor como sua própria resposta.
Assistente de trigo

1

Backhand , 25 21 bytes

vv""ppeeeebb""jjHH@

Experimente online! Verificação!

Isso usa a capacidade do Backhand de alterar o valor da etapa do ponteiro para ignorar uma instrução a cada etapa e resolver com perfeição o problema de redunância. Ele então usa o jcomando para verificar se o código é irradiado, saltando para o último caractere ( @, halt), se não, e saltando para o segundo último ( H, halt e pilha de saída), se houver.

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.