A codificação Manchester é um protocolo de telecomunicações usado em radiocomunicação que garante a transição de bits em intervalos regulares, para que um receptor possa recuperar a taxa de clock dos próprios dados. Dobra a taxa de bits, mas é barato e simples de implementar. É amplamente utilizado por operadores de rádio amador.
O conceito é muito simples: no nível do hardware, o relógio e as linhas de dados são simplesmente combinadas com XOR. No software, isso é retratado como a conversão de um fluxo de bits de entrada em um fluxo de saída de taxa dupla, com cada entrada '1' traduzida para '01' e cada entrada '0' traduzida para '10'.
Esse é um problema fácil, mas aberto a muitas implementações devido à sua natureza de fluxo de bits. Ou seja, a codificação é conceitualmente um processo bit a bit em vez de um processo byte a byte. Portanto, todos concordamos em endianness, os bits menos significativos da entrada se tornam o byte menos significativo da saída.
Tempo de golfe! Escreva uma função que, dada uma matriz arbitrária de bytes, retorne uma matriz desses dados codificados por manchester.
A entrada e a saída devem ser consideradas little-endian, menos bytes significativos primeiro e bits menos significativos primeiro no fluxo de bits.
Desenho de fluxo de bits ASCII :
bit # 5 4 3 2 1 0 5 4 3 2 1 0
IN ------- 1 0 1 0 1 1 ---> [manchester encoder] --- 01 10 01 10 01 01 ----> OUT
Exemplos :
Example 1 (hex):
LSB MSB <-- least sig BYTE first
IN : [0x10, 0x02]
OUT: [0xAA, 0xA9, 0xA6, 0xAA]
Example 1 (binary):
msb lsb msb lsb <-- translated hex, so msb first
BIN: [00010000, 00000010] <-- least sig NIBBLE...
BIN: [10101010, 10101001, 10100110, 10101010] <-- becomes least sig BYTE
LSB MSB
Example 2
IN : [0xFF, 0x00, 0xAA, 0x55]
OUT: [0x55, 0x55, 0xAA, 0xAA, 0x66, 0x66, 0x99, 0x99]
Example 3
IN : [0x12, 0x34, 0x56, 0x78, 0x90]
OUT: [0xA6, 0xA9, 0x9A, 0xA5, 0x96, 0x99, 0x6A, 0x95, 0xAA, 0x69]
Example 4
IN : [0x01, 0x02, 0x03, 0xF1, 0xF2, 0xF3]
OUT: [0xA9, 0xAA, 0xA6, 0xAA, 0xA5, 0xAA, 0xA9, 0x55, 0xA6, 0x55, 0xA5, 0x55]
Regras :
- A solução requer apenas algoritmo para converter entrada em saída.
- A aquisição de entrada e saída de impressão NÃO é uma parte necessária da solução, mas pode estar incluída. Você deve fornecer seu código de teste / impressão, se não estiver incluído na sua solução.
- A entrada é uma matriz de bytes de 8 bits (o que quer que isso possa significar no seu idioma preferido), NÃO uma sequência de texto. Você pode usar cadeias de caracteres como formato de armazenamento, se for conveniente no seu idioma, mas caracteres não imprimíveis (por exemplo, 0xFF) devem ser suportados. A entrada também pode demorar, se necessário.
A memória para saída deve ser alocada pela sua rotina, não fornecida.editar: requisito desnecessário- A saída também é uma matriz de bytes de 8 bits e um comprimento, se necessário.
- Deve suportar pelo menos 16 KB de entrada
- O desempenho não deve ser muito horrível: <10s para 16 KB
- Byte menos significativo primeiro na memória.
Desafio de canal lateral :
- Desafie a resposta de outro usuário, provando que seu código é mais rápido, mais eficiente em memória ou produz um binário menor!
Respostas:
GolfScript 28 caracteres
Versão equivalente sem otimização ofuscante:
O código aceita a entrada como uma matriz de números inteiros e retorna o mesmo.
Para cada número na matriz, o número é convertido na forma de matriz da base 2 e, em seguida, é convertido novamente em um número como se fosse a base 4, o que tem o efeito de espaçar os bits com um 0 entre cada um. 43691 é subtraído do número e o resultado é binário invertido, isso é equivalente a subtrair o número de 43690 (43690 = 0b1010101010101010). O número é então dividido em duas partes, convertendo-o em uma matriz base 256, a matriz é decomposta e a ordem dos dois números resultantes é invertida.
Exemplo de entrada:
Exemplo de saída:
fonte
{2{base}:|~4|43691-~256|~p p}%
c - 224 caracteres
Eu acredito que isso é funcional, incluindo a alocação de requisitos de memória desde que caiu.
A parte de trabalho do código é um loop sobre os bits de cada caractere, observando que ((bit + 1) exclusivo-ou 3) é o par de bits de saída e aplica muita lógica de deslocamento e mascaramento para alinhar tudo.
Como é de costume, ele funciona nos dados como caracteres. O andaime de teste não aceita 0 bytes (porque c os trata como final de string), mas o código de trabalho não tem essa limitação.
Pode ser jogado um pouco mais, copiando o trabalho de conversão de bytes em linha.
Execução de teste (com andaime de teste aprimorado):
Comentado, menos dependente da máquina e com andaime de teste
fonte
J, 36
Esboço da explicação (consulte o Vocabulário J para referência):
,@:(3 :'...'"0)
aplica o ... a cada entrada "byte" como y, resultando em dois bytes (inteiros) cada. O resultado é achatado por,
.y#:~8#2
é equivalente a2 2 2 2 2 2 2 2 #: y
, ou vetor dos 8 dígitos base-2 menos significativos de y.4|.
troca a frente e para trás 4 bits girando 4 posições.(,.~-.)
é equivalente3 :'(-. y) ,. y'
ou não ao argumento 'costurado' ao argumento (assumindo a forma 8 2).#.2 8$,
nivela o resultado, fornecendo o fluxo de bits, remodelando para 2 linhas de 8 e convertendo da base 2.Exemplo de uso (J, interativo):
Informação de velocidade (J, interativa):
O tempo médio para 16kb é um pouco abaixo de 0,25s, Intel Core Duo 1,83Ghz ou similar.
fonte
Haskell, 76 caracteres
Execuções de teste:
O desempenho está dentro das especificações. a 1 MB em ~ 1,2 s no meu laptop antigo. Ele sofre porque a entrada é convertida para e de uma lista, e não processada como a
ByteArray
.A fonte, 2040-Manchester.hs , inclui o código, testes e função principal de um filtro de linha de comando.
fonte
OCaml + baterias,
138117 caracteresTestes:
Com
Os resultados são:
Como referência, com:
Eu recebo:
no meu MacBook.
fonte
Python, 87 caracteres
M
é a função solicitada no problema. Ele chamaN
cada nybble e junta tudo de volta em uma lista.gera
fonte
APL (Dyalog Extended) , 22 bytes
Experimente online!
Porta da resposta GolfScript.
fonte
C, 164 bytes
Recebe uma série de bytes hexadecimais e converte em fluxo binário de Manchester.
Teste:
Resultado:
Gerador de conjunto de dados de teste de 16kb:
test_data.c:
1.6G i5dual core contra-relógio:
fonte
PHP, 156 bytes
Dada a entrada
[0, 1, 2, 3, 4, 5]
, ela retorna:Ele codifica 16 KiB de dados em 0,015 segundos e 1 MiB de dados em cerca de 0,9 segundos.
O código não-bloqueado, outra implementação (mais longa e cerca de duas vezes mais lenta) e os casos de teste podem ser encontrados na minha página de soluções de código-golfe no Github.
fonte