Um dos paradigmas de programação menos conhecidos que parece bastante adequado para o golfe com código é a Programação Orientada por Sobreposição (OOP) *. Ao escrever código parcialmente idêntico, muitos bytes podem ser salvos simplesmente sobrepondo as partes idênticas e lembrando de alguma maneira que as duas linhas de código originais começam. Sua tarefa é escrever dois programas ou funções sobrepostoscompress
e decompress
com a seguinte especificação:
* Não use no código de produção, provavelmente.
compress
compress
pega duas strings em qualquer formato conveniente e as sobrepõe o máximo possível. Essa é uma string s
com comprimento mínimo retornada de forma que ambas as strings de entrada sejam substrings de s
. Além disso, é retornada alguma saída que identifica os índices inicial e final de ambas as seqüências.
Exemplos: (O formato exato de IO depende de você)
compress("abcd", "deab") -> "deabcd" ((2,5),(0,3))
compress("abcd", "bc") -> "abcd" ((0,3),(1,2))
compress("abc", "def") -> "abcdef" ((0,2),(3,5)) or "defabc" ((3,5),(0,2))
decompress
decompress
calcula a função inversa de compress
, que recebe uma sequência e dois índices inicial e final (no formato em que são retornados pelo seu compress
), retorna as duas sequências originais. Você só precisa manipular entradas válidas. A seguir a igualdade deveria valer para todas as cordas s1
, s2
:
(s1, s2) == decompress (compress (s1, s2))
Exemplos: (inversos de compress
exemplos)
decompress "deabcd" ((2,5),(0,3)) -> "abcd" "deab"
decompress "abcd" ((0,3),(1,2)) -> "abcd" "bc"
decompress "abcdef" ((0,2),(3,5)) -> "abc" "def"
or (whichever version your "compress" generates)
decompress "defabc" ((3,5),(0,2)) -> "abc" "def"
Pontuação
Sua pontuação é o tamanho da string retornada chamando compress("<code of compress>", "<code of decompress>")
. Como este é um código de golfe, uma pontuação menor é melhor.
Exemplo:
Suponha que o código para sua função compress
seja c=abcd
e o código para decompress
seja d=efghi
. Então compress("c=abcd", "d=efghi")
produz "c=abcd=efghi"
(e os índices, mas esses não afetam a pontuação), então a pontuação é length "c=abcd=efghi" = 12
.
Regras adicionais
- No espírito deste desafio, você deve
compress
edecompress
deve se sobrepor em pelo menos um personagem. Você pode conseguir isso trivialmente adicionando um comentário, mas observe que isso aumentará sua pontuação e poderá haver soluções mais curtas usando código inerentemente sobreposto. compress
edecompress
deve ser capaz de lidar com cadeias de caracteres que contenham caracteres ASCII imprimíveis, além de todos os caracteres usados para definircompress
edecompress
.- Os índices podem ser zero ou um indexados.
- Seus programas ou funções não precisam ser nomeados
compress
edecompress
.
Respostas:
GNU Prolog, 105 pontos
(Isso requer o GNU Prolog porque
prefix
esuffix
não é portátil.)O Prolog tem uma grande vantagem interessante para esse desafio; você pode escrever uma função para lidar com vários padrões de chamada (ou seja, não apenas pode fornecer uma função para obter uma saída correspondente, mas também pode fornecer uma função para obter uma entrada correspondente). Como tal, podemos definir uma função que pode lidar com compactação e descompactação, levando a um envio de 105 bytes que define uma função
o
que funciona nos dois sentidos. (Aliás, eu principalmente escrevi como um descompressor - como é mais simples - e adquiri o compressor "de graça".) Em geral, poderíamos esperar um programa muito curto no Prolog para essa tarefa, se não pelo fato de ser tão ruim. no tratamento de strings (tanto em termos de primitivas ausentes quanto em termos de primitivas em questão com nomes terrivelmente longos).O primeiro argumento para
o
é uma tupla de strings, por exemplo"abcd"-"deab"
. O segundo argumento tem uma forma como"deabcd"-4/6-4/4
; essa é uma tupla aninhada bastante padrão e significa que a string é "deabcd", a primeira string tem comprimento 4 e termina no sexto caractere, a segunda string tem comprimento 4 e termina no quarto caractere. (Observe que uma string no GNU Prolog é apenas uma lista de códigos de caracteres, o que torna a depuração irritante porque a implementação prefere a última interpretação por padrão.) Se você fornecero
um argumento, ele produzirá o outro para você (trabalhando assim como um compressor se você der o primeiro argumento e um descompressor se você der o segundo). Se você fornecer os dois argumentos, verificará se a representação compactada corresponde às seqüências fornecidas. Se você der zero argumentos, ele gerará uma saída como esta:A descrição acima do formato de E / S também é basicamente apenas uma descrição do programa; não há muito no programa. A única sutileza está relacionada às dicas de ordem de avaliação; precisamos garantir que o programa não use apenas uma estratégia de pesquisa com garantia de término, mas também produza a menor string de saída possível.
Ao compactar, começamos com
length(C,_)
("C
tem um comprimento"), que é um truque que já usei em muitas respostas do Prolog e Brachylog; se essa é a primeira coisa que o Prolog vê, fará com que ele priorize a redução do tamanho deC
qualquer outra coisa. Isso garante que tenhamos um comprimento mínimoC
. A ordenação das restriçõess
é cuidadosamente escolhida para que a pesquisa leve um tempo finito para cada comprimento possível de candidatoC
;A
é limitado porC
(não sabemosC
, mas sabemos o valor-alvo que temos para o seu comprimento),M
porA
,U
porA
eL
porU
, para que nenhuma das pesquisas demore um tempo ilimitado.Ao descompactar, somos dados
C
diretamente pelo usuário. Isso novamente garante que o programa seja executado em tempo finito, devido à mesma sequência de restrições. (As pessoas que estão cientes da ordem de avaliação do Prolog notarão que a definição des
é muito ineficiente ao descomprimir; colocarlength(A,M)
elength(U,L)
primeiro seria mais rápido, mas passarlength(A,M)
para o início pode causar um loop infinito na compactação, porque nemA
nemM
está vinculado a nada no momento .)fonte
Braquilog ,
5046 bytesExperimente online!
Descomprimir:
Experimente online!
Guardado 5 bytes graças a @ ais523
Explicação
O lado bom das linguagens declarativas é que podemos reutilizar o mesmo código para compactar e descompactar. Como tal, o código para compactar é exatamente o mesmo que para descomprimir , com um adicional
~
no início.Isso
~
informa ao Brachylog para reverter a ordem dos argumentos (ou seja, use a Entrada como saída e a Saída como entrada). Como o compress não possui~
, ele realmente executa o predicado na ordem padrão. Como a descompactação possui apenas um, ele é executado com a Entrada como saída e a Saída como entrada.Dessa forma, podemos usar o mesmo código (módulo extra
~
) para compactar e descompactar: a compactação está fornecendo as duas cadeias como entrada e uma variável como saída, e a descompactação está fornecendo os índices e a cadeia compactada como saída e uma variável como Entrada .Obviamente, isso também significa que precisamos ser um pouco explícitos sobre nosso código de compressão, para que o intérprete seja capaz de executá-lo "de trás para frente". É por isso que o próprio compressor é um pouco longo.
Aqui está um detalhamento do código para Compress (e, portanto, também para descompactar):
fonte
Geléia ,
5850 bytes-1 byte graças a ais523 (use
⁾
para uma string de dois bytes)Isso pode muito bem ser jogável ...
A compactação usa dois argumentos de sequência e retorna uma lista:
[[[startA, lengthA], [startB, lengthB]], compressedString]
A descompressão pega um argumento (como essa lista) e retorna duas * strings:
Código sobreposto:
Um indexado.
* isso pode não ser óbvio devido à formatação implícita de impressão da Jelly, portanto, o código no TryItOnline vinculado acima tem um byte extra (a
Y
no final) para inserir um avanço de linha entre os dois na saída impressa.Comecei com um único programa, que usava a profundidade do primeiro (ou único) argumento para decidir entre compactação e descompactação, mas ter um link não utilizado no código de descompactação (a primeira linha) e um único byte sobreposto é menor em sete bytes .
Quão?
fonte
“ṫḣ”
pode ter um byte de 1 byte usando a sintaxe de Jelly para seqüências de caracteres de 2 caracteres.