Cubix, 16 bytes
$-!u'HIa'@/1@O<
Formulário líquido:
$ -
! u
' H I a ' @ / 1
@ O < . . . . .
. .
. .
Tente você mesmo
Você deve inserir os valores de bytes decimais do arquivo em uma lista separada. O separador não importa, qualquer coisa que não seja um dígito ou sinal de menos é suficiente. O código realmente se importa apenas com o primeiro byte, para que você possa deixar de fora o restante do arquivo, se quiser. O programa gera 0
para sem perdas e 1
com perdas. Experimente aqui ! A entrada padrão usa um cabeçalho FLAC.
Explicação
O bom dos arquivos é que (quase) todos eles têm a chamada mágica. Esses são os primeiros bytes do arquivo. Um bom software não verifica a extensão do arquivo, mas a mágica do arquivo para ver se ele pode lidar com um determinado arquivo.
Dennis encontrou uma maneira de usar essa mágica para encontrar o tipo de compactação, mas o fato de ele ter descartado o primeiro byte me fez querer tentar criar um método que usasse o primeiro byte, e não o segundo. Afinal, essa comunidade tem tudo a ver com salvar bytes.
Aqui está uma lista dos primeiros bytes dos diferentes tipos de arquivos. Ordenei-os em dois grupos: com e sem perdas. Aqui estão os valores do primeiro byte em decimal, hexadecimal e binário. Você já pode ver um padrão ...
Lossy: Lossless:
255:0xFF:0b11111111 102:0x66:0b01100110
79:0x4F:0b01001111 84:0x54:0b01010100
35:0x23:0b00100011 82:0x52:0b01010010
11:0x0B:0b00001011 70:0x46:0b01000110
0:0x00:0b00000000
O padrão que vi foi que o segundo bit (contado da esquerda para a direita) estava sempre ligado nos bytes "sem perdas" e o quinto bit estava sempre desligado. Essa combinação não aparece em nenhum dos formatos com perdas. Para "extrair" isso, nós simplesmente fazemos um AND binário (by 0b01001000 (=72)
) e depois comparamos com 0b01000000 (=64)
. Se ambos são iguais, o formato de entrada é sem perdas, caso contrário, é com perdas.
Infelizmente, o Cubix não possui um operador de comparação, então usei a subtração (se o resultado for 64, isso gera 0 e resulta em 8, -56 ou -64, caso contrário, voltarei a isso mais tarde.
Primeiro, vamos começar no início do programa. O AND binário é feito usando o a
comando:
'HIa
'H # Push 0b01001000 (72)
I # Push input
a # Push input&72
Em seguida, comparamos com 64 usando subtração (observe que atingimos um espelho que reflete o IP na face superior [primeira linha, segundo caractere, apontando para o sul] no meio desta parte).
'@-
'@ # Push 0b01000000 (64)
- # Subtract from (input&72)
# Yields 0 for lossy, non-zero otherwise
Depois que o IP é revertido pelo u
, usamos algum fluxo de controle para enviar a 1
para a pilha se (e somente se) a parte superior da pilha for diferente de zero:
!$1
! # if top = 0:
$1 # do nothing
# else:
1 # push 1
Depois de envolvermos o cubo, atingimos a <
instrução, que aponta o IP para oeste na quarta linha. Tudo o que resta a fazer é produzir e terminar.
O@
O # Output top of the stack as number
@ # End program
Portanto, o programa gera 0
sem perdas e 1
com perdas.