Somente bytes pares

64

O cenário

Ultimamente você tem notado algum comportamento estranho com seu editor de texto favorito. A princípio, parecia que estava ignorando caracteres aleatórios no seu código ao gravar no disco. Depois de um tempo você notou um padrão; caracteres com valores ASCII ímpares estavam sendo ignorados. Sob uma inspeção mais aprofundada, você descobriu que só pode gravar arquivos corretamente se cada oitavo bit for zero. Agora você precisa saber se seus arquivos valiosos foram afetados por esse bug estranho.

A tarefa

Você deve escrever um programa completo que determine se um arquivo contém bytes ímpares (demonstrando que não está corrompido). Mas, devido ao seu editor de texto, você não pode escrever bytes ímpares no seu código-fonte. Você pode assumir qualquer codificação preexistente para entrada, mas ainda deve verificar cada byte individual, não apenas caracteres.

Entrada

Seu programa pegará o conteúdo ou o caminho para um arquivo a partir do stdin ou da linha de comando.

Resultado

Seu programa produzirá para stdout um valor verdadeiro se o arquivo fornecido contiver um byte ímpar ou um falso se cada oitavo bit for zero.

Critério

Este é o código golf, o programa mais curto que completa a tarefa ganha. Para ser um envio válido, cada oitavo bit no código-fonte dos arquivos deve ser zero. Eu recomendaria incluir uma cópia dos binários do seu código-fonte no seu envio.

Aplicam-se brechas padrão .

Casos de teste

(Na codificação ASCII) Entrada:

"$&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~

Output:
falsy

Input:
!#%')+-/13579;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}

Output:
truthy

Input:
LOREMIPSVMDOLORSITAMETCONSECTETVRADIPISCINGELITSEDDOEIVSMODTEMPORINCIDIDVNTVTLABOREETDOLOREMAGNAALIQVA
VTENIMADMINIMVENIAMQVISNOSTRVDEXERCITATIONVLLAMCOLABORISNISIVTALIQVIPEXEACOMMODOCONSEQVAT
DVISAVTEIRVREDOLORINREPREHENDERITINVOLVPTATEVELITESSECILLVMDOLOREEVFVGIATNVLLAPARIATVR
EXCEPTEVRSINTOCCAECATCVPIDATATNONPROIDENTSVNTINCVLPAQVIOFFICIADESERVNTMOLLITANIMIDESTLABORVM

Output:
truthy

Dicas

  • Escolha sabiamente o idioma. Esse desafio pode não ser possível em todos os idiomas.

  • O comando Unix xxd -b <file name>imprimirá os binários de um arquivo no console (junto com algumas coisas extras de formatação)

  • Você pode usar outras codificações que não sejam ASCII, como UTF-8, desde que todas as outras regras sejam seguidas

Assistente de Trigo
fonte
2
Alguns idiomas têm dificuldade em ler entradas de várias linhas, mas não é como se esse desafio fosse fácil, então provavelmente está OK. : P A entrada pode estar vazia?
Dennis
9
!#%')+-/13579;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}são os caracteres ASCII imprimíveis proibidos, para quem se importa. Os caracteres ASCII imprimíveis permitidos são" $&(*,.02468:<>@BDFHJLNPRTVXZ\^`bdfhjlnprtvxz|~
Patrick Roberts
9
Bastante útil que todas as vogais são proibidos ... ;-)
owacoder
4
Welp, tanto para a BF ter uma chance neste desafio.
TLW
2
Observe também que, se houver alguma quebra de linha em um arquivo DOS / Windows, o [CR]bit será ímpar. Eu esperava que o WhiteSpace estivesse seguro, mas infelizmente [TAB]. Se você quer ir para a velha escola, o EBCDIC oferece três vogais.
GuitarPicker 8/08/16

Respostas:

26

GS2 , 4 bytes

dΦ("

Experimente online!

Hexdump

0000000: 64 e8 28 22                                      d.("

Como funciona

      (implicit) Read all input and push it on the stack.
 Φ    Map the previous token over all characters in the string:
d       Even; push 1 for even characters, 0 for odd ones.
  (   Take the minimum of the resulting list of Booleans.
   "  Negate the minimum.
Dennis
fonte
21

Befunge, 36 bytes

Sei que essa é uma pergunta antiga, mas queria tentar, porque achei que seria um desafio interessante no Befunge.

>~:0`|
>20`:>$.@
|` " "<
*8*82<^p24*

Experimente online!

É emitido 1se a entrada estiver corrompida (ou seja, contiver um byte ímpar) e 0se estiver OK.

Explicação

O problema é como determinar bytes ímpares sem ter acesso aos comandos /(dividir) ou %(módulo). A solução foi multiplicar o valor por 128 (a sequência 28*8**) e gravar esse resultado no campo de jogo. Em um intérprete estritamente padrão, as células do campo de jogo são assinadas com valores de 8 bits, portanto, um número ímpar multiplicado por 128 fica truncado para -1 enquanto um número par se torna 0.

O outro truque era ler o -1 ou 0 de volta do playfield sem ter acesso ao gcomando (get). A solução alternativa para isso foi gravar o valor no meio de uma sequência de strings existente ( " ") e, em seguida, executar essa sequência para enviar o valor incluído para a pilha. Nesse ponto, determinar a estranheza do byte é um teste simples menor que zero.

Um aspecto final que vale a pena discutir é a saída. No caso falso, alcançamos a >$.sequência com apenas um valor na pilha, $limpando a pilha, tornando a .saída zero. No caso real, seguimos o caminho 20`:>$.. Como dois é maior que zero, a comparação coloca um na pilha e :faz uma cópia duplicada para $que não a solte antes de ser impressa .

James Holderness
fonte
11
Isso pode ser tarde e novo, mas já é a minha resposta favorita.
Wheat Wizard
@ WheatWizard Acabei de perceber agora por que essa resposta está recebendo tanta atenção. Obrigado pela recompensa!
James Holderness
12

CJam (11 bytes)

"r2":(~f&2b

Demonstração online

Retirando os truques para evitar bytes ímpares, isso reduz a

q1f&2b

que lê a entrada, mapeia um AND bit a bit com 1e executa uma conversão base, fornecendo zero se todos os AND eram zero.

Peter Taylor
fonte
3
Este código é triste:(
betseg
Porque ele pode ter apenas a metade dos caracteres @betseg
Roman Gräf
9

Arquivo .COM imprimível, 100 bytes

^FZjfDXVL\,LPXD$$4"PXD,lHPXDjJXDRDX@PXDjtXDH,nPXDj@XD4`@PXD,ZHPXD4,@PXD4:4"PXDH,\PXD4"PXD,hPXDRDX@P\

Hexdump:

00000000  5e 46 5a 6a 66 44 58 56  4c 5c 2c 4c 50 58 44 24  |^FZjfDXVL\,LPXD$|
00000010  24 34 22 50 58 44 2c 6c  48 50 58 44 6a 4a 58 44  |$4"PXD,lHPXDjJXD|
00000020  52 44 58 40 50 58 44 6a  74 58 44 48 2c 6e 50 58  |RDX@PXDjtXDH,nPX|
00000030  44 6a 40 58 44 34 60 40  50 58 44 2c 5a 48 50 58  |Dj@XD4`@PXD,ZHPX|
00000040  44 34 2c 40 50 58 44 34  3a 34 22 50 58 44 48 2c  |D4,@PXD4:4"PXDH,|
00000050  5c 50 58 44 34 22 50 58  44 2c 68 50 58 44 52 44  |\PXD4"PXD,hPXDRD|
00000060  58 40 50 5c                                       |X@P\|
00000064

Usando uma definição muito vaga de fonte como algo que pode ser razoavelmente digitado por um humano e inspirado no Arquivo de Teste Antivírus Padrão da EICAR (mais informações em "Vamos nos divertir com o arquivo de teste da EICAR" no Bugtraq).

Usando apenas bytes ASCII não ímpares imprimíveis (observação: opcodes que afetam palavras tendem a ser ímpares, o bit W é o lsb de alguns opcodes), ele constrói um fragmento de código em SP (que convenientemente definimos após o código de geração) , e a execução acaba caindo no código gerado.

Ele usa o fato de que a pilha contém inicialmente um ponteiro próximo ao início do PSP e que o início do PSP contém a INT 20hinstrução (mais informações sobre isso em https://stackoverflow.com/questions/12591673/ ).

Fonte real:

; we want to generate the following fragment of code

;  5E                pop si             ; zero SI (pop near pointer to start of PSP)
;  46                inc si             ; set SI to 1
; loop:
;  B406              mov ah,0x6         ; \
;  99                cwd                ; >
;  4A                dec dx             ; > D-2106--DLFF
;  CD21              int 0x21           ; > DIRECT CONSOLE INPUT
;  7405              jz end             ; > jump if no more input
;  40                inc ax             ; > lsb 0/1 odd/even
;  21C6              and si,ax          ; > zero SI on first odd byte
;  EBF3              jmp short loop     ; /
; end:
;  96                xchg ax,si         ; return code
;  B44C              mov ah,0x4c        ; D-214C
;  CD21              int 0x21           ; TERMINATE WITH RETURN CODE

 pop si             ; this two opcodes don't need to be encoded
 inc si

 pop dx             ; DX = 20CD (int 0x20 at start of PSP)
 push byte +0x66
 inc sp
 pop ax
 push si
 dec sp
 pop sp             ; SP = 0x0166
 sub al,0x4c        ; B4
 push ax
 pop ax
 inc sp
 and al,0x24
 xor al,0x22        ; 06
 push ax
 pop ax
 inc sp
 sub al,0x6c
 dec ax             ; 99
 push ax
 pop ax
 inc sp
 push byte +0x4a    ; 4A
 pop ax
 inc sp
 push dx            ; [20]CD
 inc sp
 pop ax
 inc ax             ; 21
 push ax
 pop ax
 inc sp
 push byte +0x74    ; 74
 pop ax
 inc sp
 dec ax
 sub al,0x6e        ; 05
 push ax
 pop ax
 inc sp
 push byte +0x40    ; 40
 pop ax
 inc sp
 xor al,0x60
 inc ax             ; 21
 push ax
 pop ax
 inc sp
 sub al,0x5a
 dec ax             ; C6
 push ax
 pop ax
 inc sp
 xor al,0x2c
 inc ax             ; EB
 push ax
 pop ax
 inc sp
 xor al,0x3a
 xor al,0x22        ; F3
 push ax
 pop ax
 inc sp
 dec ax
 sub al,0x5c        ; 96
 push ax
 pop ax
 inc sp
 xor al,0x22        ; B4
 push ax
 pop ax
 inc sp
 sub al,0x68        ; 4C
 push ax
 pop ax
 inc sp
 push dx            ; [20]CD
 inc sp
 pop ax
 inc ax
 push ax            ; 21
 pop sp             ; now get the stack out of the way
ninjalj
fonte
9

MATL , 7 bytes

l$Z$2\z

O código fonte usa codificação UTF-8. Portanto, os bytes de origem são (em decimal)

108    36    90    36    50    92   122

A entrada é um nome de arquivo, tomado como uma cadeia entre aspas simples. A saída é o número de bytes ímpares no arquivo, que é verdadeiro se diferente de zero.

Explicação

l    % Push a 1. We use `l` instead of `1` to have an even value
$    % Input specificication. This indicates that the next function takes 1 input
Z$   % Input file name implicitly, read its raw bytes and push them as an array of chars
2\   % Modulo 2
z    % Number of nonzero values. This gives the number of odd bytes. Implicitly display
Luis Mendo
fonte
8

CJam, 18 17 15 bytes

"<rj":(((*~:|X&

Supõe que o código do idioma esteja definido como Latin-1. Experimente online!

Como funciona

A solução direta é a seguinte.

q       e# Read all input from STDIN and push it as a string on the stack.
 :i     e# Cast each character to its code point.
   :|   e# Take the bitwise OR of all code points.
     X  e# Push 1.
      & e# Take the bitwise AND of the logical OR and 1.

Infelizmente, os caracteres qe inão podem aparecer no código fonte. Para contornar esse problema, criaremos parte do código-fonte acima dinamicamente e depois avaliaremos a string.

"<rj"         e# Push that string on the stack.
     :(       e# Decrement all characters, pushing ";qi".
       (      e# Shift out the first character, pushing "qi" and ';'.
        (     e# Decrement ';' to push ':'.
         *    e# Join "qi" with separator ':', pushing "q:i". 
          ~   e# Evaluate the string "q:i", which behaves as explained before.
Dennis
fonte
7

Pitão, 20 13 bytes

vj0>LhZ.BRj.z

Ou em binário:

00000000: 01110110 01101010 00110000 00111110 01001100 01101000  vj0>Lh
00000006: 01011010 00101110 01000010 01010010 01101010 00101110  Z.BRj.
0000000c: 01111010                                               z

Experimente online

Como funciona

           .z   all lines of input
          j     join on newline
       .BR      convert each character to binary
   >LhZ         take the last (0 + 1) characters of each binary string
 j0             join on 0
v               evaluate as an integer

O inteiro resultante é verdade (diferente de zero) se algum dos bytes for ímpar.

Anders Kaseorg
fonte
4

Jelly , 13 bytes

24‘ịØBvF|\ṪBṪ

Espera a entrada como um argumento de linha de comando entre aspas. Experimente online!

Hexdump

0000000: 32 34 fc d8 12 42 76 46 7c 5c ce 42 ce           24...BvF|\.B.
Dennis
fonte
Se não fosse pela restrição byte impar, isto igualmente trabalhar a 6 bytes: O%2¬Ạ¬.
Erik the Outgolfer
4

Retina , 106 bytes

Remove todos os caracteres permitidos e corresponde aos caracteres restantes. Os valores reais serão o número de caracteres encontrados. Os valores de Falsey serão 0.

`"| |\$|&|\(|\*|,|\.|0|2|4|6|8|:|<|>|@|B|D|F|H|J|L|N|P|R|T|V|X|Z|\\|\^|`|b|d|f|h|j|l|n|p|r|t|v|x|z|\||~

.

Experimente online

Como .não corresponde às novas linhas por padrão, não preciso removê-las.

mbomb007
fonte
1

Perl 5 + -p0, 136 bytes

Semelhante a outras respostas, isso remove todos os bytes pares e deixa os bytes ímpares (que são verdadeiros).

tr<�
 "$&(*,.02468:<>@BDFHJLNPRTVXZ\\^`bdfhjlnprtvxz|~€‚„†ˆŠŒŽ’”–˜šœž ¢¤¦¨ª¬®°²´¶¸º¼¾ÀÂÄÆÈÊÌÎÐÒÔÖØÚÜÞàâäæèêìîðòôöøúüþ><>d

Experimente online!

Dom Hastings
fonte
-0não faz nada para novas linhas. Ele só determina como dividir a entrada, não remove nenhum caractere.
Ørjan Johansen
Ai isso é muito ruim.
Ørjan Johansen
@ ØrjanJohansen Sim, você está certo -0, eu queria fazer todo o bloco como um pedaço, mas isso não deveria importar, mas não posso contornar isso ... Que pena! Vou limpar esses comentários. Obrigado pelo alerta!
Dom Hastings
Então funciona agora? Acho que devo excluir alguns dos comentários. Pela edição, vejo que agora você inclui todos os bytes pares no programa. Eu acho que você pode dizer isso explicitamente, já que nem todos esses personagens aparecem (pelo menos para mim).
Ørjan Johansen
@ ØrjanJohansen yes! Eu acho que entendi agora. Também não acho que todas as outras respostas abranjam todos os bytes pares, acho que apenas algumas funcionam em ASCII imprimível. Estou bastante confiante de que isso faz o que eu queria agora. Espero que sim!
Dom Hastings
0

Japonês , 10 bytes

ø0ôH² ®dZÄ

Experimente online!

A página de código de Japt é ISO-8859-1. O código fornece falsequando ele próprio é inserido como uma sequência, portanto, um envio válido.

Descompactado e como funciona

Uø0ôHp2  mZ{ZdZ+1

Uø      Does input string contain any element in the following array...?
0ôHp2     Range of 0 to 32**2, inclusive
mZ{       Map...
ZdZ+1       Convert the number Z to a char having charcode 2*Z+1

Não ter String.c(obter código ou mapear sobre códigos) foi um problema, mas felizmente existe Number.d(converter número em char).

Acontece que Japt ganha sobre CJam, Pyth e Jelly :)


Sem a restrição, existem algumas maneiras de fazer isso em 6 bytes (parando novamente com CJam e Jelly):

®c uÃn

Unpacked: UmZ{Zc u} n

UmZ{   Map on each char...
Zc u     Convert to charcode modulo 2
}
n      Convert the resulting string to number

"000..000"é convertido para o número 0 (falso), independentemente de quanto tempo é. Por outro lado, qualquer coisa que contenha 1 é convertida em um valor diferente de zero double, ou Infinityse for muito grande (ambos de verdade).

¬d_c u

Unpacked: q dZ{Zc u

q    Convert to array of chars
dZ{  Is something true when mapped with...
Zc u   Convert each char to charcode modulo 2

Abordagem mais direta que produz diretamente trueou false.

Ou uma solução de 5 bytes é possível com a ajuda do -dsinalizador:

¨c u

Unpacked: q mZ{Zc u

q     Convert to array of chars
mZ{   Map...
Zc u    Convert to charcode modulo 2

      Result is array of zeros and ones
-d    Apply .some() on the resulting array
Bubbler
fonte