Codificar - Aleatório - Decodificar


23

Desafio

Sua tarefa é codificar um número inteiro como uma sequência de caracteres ASCII e decodificá-la com êxito depois que a sequência for aleatoriamente embaralhada.

Você escreverá dois programas / funções , que serão chamados de codificador e decodificador .

Codificador

  • Entrada: um número inteiro n no intervalo [0,2311] .
  • Saída: uma sequência s de caracteres ASCII (não necessariamente imprimíveis).

Decodificador

  • Entrada: uma permutação aleatória s da string s .
  • Saída: o número inteiro n .

Pontuação

Seja A o comprimento máximo de s em todos os valores possíveis de n . Se o codificador agir de forma não determinística (o que é permitido, veja abaixo), então A será o comprimento máximo de s que pode ocorrer (possivelmente ).

Seja LE o comprimento do codificador em bytes e LD o comprimento do decodificador em bytes.

Então sua pontuação é A(LE+LD) .

A vitória é atribuída à finalização com a menor pontuação .

Prazo

Há um limite de tempo um tanto arbitrário de 1 minuto no tempo de execução do codificador e do decodificador para uma única caixa de teste (ou seja, um valor único de n ).

O objetivo é evitar soluções que considerem a codificação forçada, enumerando todas as seqüências com determinadas propriedades. Se sua solução fizer algo mais inteligente que isso, provavelmente se ajustará à restrição de tempo e será considerada válida. Da mesma forma, se funcionar no TIO para alguns valores selecionados aleatoriamente de n , será considerado válido. Caso contrário, testarei na minha máquina, mas observe que, se sua solução for pura força bruta, ela quase certamente falhará.

Regras

  • O codificador e o decodificador devem ser escritos no mesmo idioma .
  • O decodificador deve emitir o número inteiro correto n para todas as permutações possíveis s da string s retornada pelo codificador .
  • O codificador e o decodificador não têm permissão para compartilhar informações de nenhuma maneira (por exemplo, por meio de variáveis ​​ou arquivos globais).
  • A saída do codificador não precisa ser determinística (ou seja, a mesma entrada n pode produzir cadeias de saída diferentes se o codificador for executado várias vezes), mas o decodificador sempre deve adivinhar o número inteiro correto n .
  • O codificador e o decodificador podem pegar e retornar o número inteiro n de qualquer maneira conveniente (por exemplo, se n=14 é bom que a entrada seja 14, "14"ou [1,4]).
  • O codificador pode saída a cadeia s quer por imprimindo -o no stdout ou por devolver uma cadeia, uma lista / matriz de caracteres ou uma lista / matriz de inteiros no intervalo [0,127] ; note que o decodificador receberá como entrada uma permutação de s retornada pelo codificador , portanto, deve aceitar a string s no mesmo formato que s .
  • As brechas padrão são proibidas.
  • Se possível, explique como seu código funciona e por que a pontuação reivindicada está correta.

Exemplo

Suponha que n=14 .

  • O codificador recebe 14como entrada. Pode sair "qwerty".
  • O decodificador recebe uma permutação de "qwerty"como entrada, por exemplo "tweyqr". Ele deve gerar 14(em qualquer formato conveniente).

O codificador também poderia ter retornado [113,119,101,114,116,121]; nesse caso, o decodificador teria recebido (por exemplo) [116,119,101,121,113,114].

Observe que a string retornada pelo codificador também pode incluir caracteres ASCII não imprimíveis (mas sempre no intervalo [0x00, ..., 0x7F]).


Certamente o comprimento de saída não pode ser infinito, você não pode arrastar uma seqüência infinita
H.PWiz

@ H.PWiz Não, não pode, mas o comprimento pode ser ilimitada se o codificador é não-determinístico
Delfad0r

"O codificador e o decodificador não têm permissão para compartilhar informações de nenhuma maneira" Isso inclui funções auxiliares? função personalizada ou seja, um que calcula N factoriais mais três (exemplo aleatório)
pizzapants184

O nosso codificador pode retornar uma lista / string vazia?
Pizzapants184

2
@ Kroppeb Sim, a partir de agora as regras dizem que você deve contar os bytes duas vezes. Estou muito interessado em ver uma submissão com dois programas idênticos, no entanto.
precisa saber é o seguinte

Respostas:


12

Gelatina , (17 bytes + 18 bytes) × comprimento 6 = 210 pontos

b36µỤỤ + × 3µŒ¿b3U + Ṣ
Ṣ: 3_J
3% 3Uḅ3œ? Çḅ36

Experimente online! (ou com informações adicionais sobre depuração)

Depois de tentar resolver esse desafio, visando a condição de vitória declarada, pensei que seria interessante optar por uma hipótese alternativa de vitória: com um comprimento máximo possível mínimo para a saída.

Explicação

Codificação

O primeiro passo na codificação é representar a entrada como base 36 ( b36). 36 6 = 2176782336> 2147483647, portanto, haverá no máximo 6 dígitos no resultado, cada um no intervalo de 0 a 35.

Em seguida, transformamos isso em uma representação que contém 6 dígitos diferentes . Existem vários algoritmos possíveis para isso, mas o usado aqui é adicionar 1 ao dígito menor, 2 ao segundo menor, 3 ao terceiro menor e assim por diante. Isso significa que, se dois dígitos forem iguais, um deles será arbitrariamente considerado menor e, portanto, eles se tornarão diferentes; e, obviamente, esse algoritmo não pode fazer com que dois dígitos diferentes se tornem iguais. Para representar isso no Jelly, usamos ("classificar índices por valores") para obter uma lista dos índices em ordem classificada; novamente para inverter isso, mapeando efetivamente cada elemento do original para sua posição em ordem classificada; eµ…+ acréscimo do original à nova lista. O resultado é uma representação do número de entrada como seis dígitos diferentes no intervalo de 1 a 41 (mínimo 0 + 1, máximo 35 + 6).

Então, dividir esta em ainda uma outra forma: uma ordenada lista de dígitos no intervalo 1-41, juntamente com um número de 1 a 720 que representa qual das 720 permutas possíveis os dígitos foram em (O. Œ¿E extrair o número de permutações e classificados lista respectivamente.)

Por fim, convertemos o número de 1 a 720 na base 3 ( b3), invertemos ( U) e codificamos os seis dígitos da base 3 e seis dígitos de 1 a 41, compactando-os em um único caractere ASCII usando o divmod reverso (o valor de o caractere mod 3 é o dígito base 3, o valor dividido por 3 é o dígito 1–41). O intervalo possível de resultados é (1 × 3) + 0 = 3 no mínimo e (41 × 3) + 2 = 125 no máximo, dentro da nossa faixa ASCII. O empacotamento é feito via ×3e +, junto com um adicional, µpara garantir que cada comando opere no bit certo de dados. (Há um truque aqui no golfe, no qual fazemos a multiplicação por 3 antes de extrair a permutação; isso evita a necessidade de gastar um byte em um caractere de agrupamento.)

Aliás, o motivo para reverter o número base 3 é porque ele pode ter menos dígitos que o número 1–41. (Ele não pode ter mais; o menor número para o qual n !> 3 n está um pouco acima de 6.) O Jelly efetivamente insere zeros à direita ao adicionar dois números de comprimentos diferentes, a fim de combiná-los; zeros à direita afetariam a interpretação do número, mas zeros à esquerda não, portanto, o inverso é usado para garantir que os zeros extras terminem em algum lugar que não atrapalhem nossa resposta.

Decodificação

O primeiro passo na decodificação é extrair os dois números (o número base 3 e o número 1–41). Podemos obter os dígitos com facilidade com divisão ( :3) e módulo ( .) Portanto, ambas as extrações começam com , seguidas por ou conforme apropriado.%3 ), respectivamente, mas como saber em que ordem eles estavam? Bem, o número 1-41 teve seus dígitos na ordem de classificação, e os dígitos nas posições correspondentes dos dois números foram armazenados nos mesmos caracteres; portanto, podemos descobrir em que ordem os dígitos do número 1-41 foram embaralhados (observando seus valores relativos) e sabemos que os dígitos do número base-3 devem ter sido embaralhados da mesma maneira. De fato, como os caracteres de nossa codificação ASCII são classificados da mesma maneira que os dígitos do número 1–41 (todos eram distintos e são mais significativos que os números base 3),%3:3

Enquanto os dígitos do número de 1 a 41 ainda estão na ordem de classificação, temos uma maneira muito conveniente / concisa de voltar aos dígitos de 0 a 35 da base 36; basta subtrair 1 do primeiro, 2 do segundo, 3 do terceiro e assim por diante. No Jelly, podemos fazer isso com _J("subtrair índice").

Enquanto isso, no outro ramo da decodificação, invertemos os dígitos do número da base 3 novamente na ordem ( U) e convertemos da base 3 novamente em um índice de permutação com ḅ3.

Podemos então combinar os dois ramos com œ?Ç; œ?significa "permute dado esse índice de permutação" e Çsignifica "o resultado da aplicação da linha acima", ou seja, é o que diz ao Jelly para executar as duas linhas separadamente na mesma entrada.

O que temos agora são os dígitos do número original, na base 36 (devido ao _J) e na ordem original (devido ao œ?), para que possamos simplesmente fazer um ḅ36para converter de volta da base 36 em um único número inteiro.

Comentário

O TIO! O link acima usa 312699167 como o número a ser codificado. Esse número na base 36 é [5, 6, 6, 8, 7, 35]e, portanto, mostra todos os aspectos da codificação: o 35 testa o limite do intervalo de 0 a 127 que temos; os 6s duplicados testam a resolução de dígitos idênticos na base original 36; e o fato de os dígitos serem quase (mas não completamente) classificados significa que o número de permutação é muito pequeno, fornecendo muito menos dígitos que o número base 36 e, portanto, mostrando a necessidade de revertê-lo antes de adicioná-lo ao original.

É realmente conveniente como todas as constantes aqui se encaixam. 36 6 é apenas o suficiente para caber 2 31 , 3 6 é apenas o suficiente para caber 6! E (36 + 6) × 3 é apenas o suficiente para caber dentro das 128 possibilidades que temos. (A última restrição aqui é a menos rígida, porque poderíamos usar a indexação 0 em vez da indexação 1 para usar caracteres no intervalo 0-2. Ainda assim, isso daria espaço suficiente para usar 37 como base, em vez de 36.)


9

Gelatina , ( 4 3 bytes + 6 5 bytes) × comprimento 8 = 80 64 pontos

b⁴Ä
ṢŻIḅ⁴

Experimente online!

Gelatina , ( 2 1 byte + 4 3 bytes) × comprimento 10 = 60 40 pontos

UMA
ṢŻI

Experimente online!

Explicação

Solução 1

Isso está usando um algoritmo diferente da maioria das outras respostas. Começamos codificando o valor em hexadecimal ( b⁴), como nas outras respostas, e obtemos uma soma cumulativa (Ä ). Cada entrada fornecerá claramente uma saída diferente (pois ambas as operações são reversíveis) e, como a codificação hexadecimal conterá no máximo 8 dígitos cujos máximos são 7 (para o oitavo último dígito) e 15 (para o último ao sétimo) últimos dígitos), o número máximo na lista de saída será 7+ (7 × 15) = 112, menor que o 127 exigido pela pergunta. Além disso, a saída será necessariamente na ordem de classificação, permitindo reverter o shuffle.

Para o decodificador, primeiro invertemos o shuffle com um sort ( ); depois inverta a soma acumulada, acrescentando um zero ( Ż) e calculando a diferença de pares consecutivos ( I); depois converta novamente de hexadecimal ( ḅ⁴).

Solução 2

A questão realmente permite que tomemos a entrada como uma lista de dígitos (presumivelmente decimais), para que possamos "trapacear" simplesmente removendo a conversão básica; o número máximo usado na saída será 2 + (9 × 9) = 83 (na verdade, 82 porque 2999999999 está fora da faixa, portanto a pior entrada possível é 1999999999). A codificação resultante é bastante terrível para as codificações desse problema, mas tem a vantagem de ser muito concisa para gerar, o que supera a verbosidade da codificação.

Essa resposta parece uma trapaça que não é minha solução principal para esse problema, mas parece que vale a pena acrescentar, porque ela está tecnicamente em conformidade com as regras e produz uma pontuação melhor.

Comentário

Eu tenho alguns algoritmos em mente para ficar abaixo do comprimento 8, mas parece improvável que você possa implementar um algoritmo de comprimento 7 em ≤9 bytes (sem trapaça) ou ≤5 bytes (trapaça), portanto, pela pontuação na pergunta, isso é provavelmente a melhor maneira de fazê-lo. (Eu poderia tentar uma solução para o desafio alternativo "minimizar a duração da codificação" de qualquer maneira, apenas por diversão.)

Ao contrário de algumas das soluções, o uso de 16 como base aqui não é crítico; existem muitos outros números que funcionariam para uma solução de comprimento 8 (por exemplo, 18). Escolhi 16 para a primeira solução simplesmente porque o Jelly possui uma maneira de 1 byte para representar isso, e outras bases viáveis ​​precisariam usar vários bytes do programa. Obviamente, a segunda solução precisa usar 10 como base para explorar a brecha.

Agradecemos ao @Dennis por apontar alguns comandos Jelly mais recentes que tornaram esse algoritmo ainda mais difícil de escrever.


3
Äé curto +\, Żé curto 0;.
Dennis

7

Linguagem de programação de Shakespeare , 10 * (264 + 494) = 8650 7910 7580

Codificador: 264 bytes

,.Ajax,.Ford,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Be you nicer zero?You be the sum ofyou the product ofthe sum ofI a big big pig the sum ofa big big big big cat a big big pig.If soSpeak thy.Ford:You are the sum ofyou a cat.If soLet usAct I.

Experimente online!

Decodificador: 494

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Is you nicer a pig?If soRemember you.If soLet usAct I.Scene V:.Ford:Remember I.Ajax:Recall.Is you worse the sum ofPage twice the sum ofa big big cat a cat?If soYou be the difference betweenyou Page.If soOpen heart.If notlet usScene V.Scene X:.Ford:Recall.Ajax:Be I nicer zero?If soRemember I.If soLet usScene X.[Exit Ajax][Enter Page]Ford:You be the sum ofyou twice twice the sum ofa big big cat a pig.Let usAct I.

Experimente online!

Isso foi uma coisa.

O codificador codifica cada dígito como dígito mais o índice do dígito vezes doze. O decodificador armazena toda a entrada na memória do Ford e circula sobre um contador, produzindo e excluindo cada dígito abaixo do contador * 12 + 10.

Explicação:

Codificador

,.Ajax,.Ford,.Act I:.Scene I:.      Boilerplate introducing the two characters
[Exeunt][Enter Ajax and Ford]       Enter the two characters Ajax and Ford
                                    Ford will be handling the input
                                    Ajax will be the counter
Ajax:Open mind.                     Set Ford to the next character of input
Be you nicer zero?                  Check if it is EOF
You be the sum of                   Set Ford to the sum of 
    you                             His original value (48 to 58)
    the product of                 
          the sum of               
              I                     Ajax's value
              a big big pig         Minus 4 (this handles the offset of 48)
          the sum of                Multiplied by
              a big big big big cat 2^4
              a big big pig.        + -2^2 = 12
                                    This essentially sets Ford to (F+12*(A-4))
If soSpeak thy.                      If not EOF, print Ford's value
Ford:You are the sum ofyou a cat.   Increment Ajax's value
If soLet usAct I.                   If not EOF, Repeat again.

Decodificador

,.Ajax,.Ford,.Page,.Act I:.Scene I:.  Boilerplate introducing three characters
                                      Ajax is the spare stack
                                      Ford is the storage stack
                                      Puck is the counter, increasing by 12
[Exeunt][Enter Ajax and Ford]            Enter Ajax and Ford onto the stage
Ajax:Open mind.                          Get the next character of input
Is you nicer a pig?                      If not EOF
If soRemember you.                         Store the value in Ford's memory
If soLet usAct I.                          And repeat the loop
Scene V:.                                Otherwise move to the next scene
Ford:Remember I.                         Store Ford's value (initially -1 from EOF) in Ajax's memory
Ajax:Recall.                             Get the next value from Ford's memory
Is you worse the sum of                  Is the value smaller than
        Puck                                  Puck's value
        twice the sum ofa big big cat a cat?  + 10 ?
                                              i.e. is it the next digit?
If soYou be the difference betweenyou Puck.   If so, subtract Puck's value from Ford
If soOpen heart.                              And print Ford's value
If notlet usScene V.                     If that was not the digit, repeat
Scene X:.
Ford:Recall.                             Get the next value from Ajax's memory
Ajax:Be I nicer zero?                    Until the -1
If soRemember I.                         Returning the values to Ford's memory
If soLet us Scene X.                     Repeat until Ajax's memory is exhausted
[Exit Ajax][Enter Page]                  Swap Ajax and Page
Ford:You be the sum of                   Set Puck's value to
              you                        Puck +   
              twice twice the sum of     2*2*(
                           a big big cat      4
                           a pig.             -1) = 12
Let usAct I.                             And start from the beginning again, having removed one number

5

Python 2.7, 31 * (52 + 37) = 2759

Codificador ( 69 52 bytes):

lambda n:[chr(i)if n&(1<<i)else""for i in range(32)]

Decodificador ( 41 37 bytes):

lambda s:sum([1<<(ord(c))for c in s])

Armazena todos os bits diferentes de zero no número de entrada como valores ascii. O valor do caractere ascii armazena a posição do bit definido. Por exemplo, o valor 'a' significaria que o 97º bit está definido.

Algumas melhorias, graças a @ Delfad0r

Experimente online!


Bem-vindo ao PPGC! Você pode largar o e = e d = o início - as funções anônimas estão perfeitamente bem. Além disso, observe que a declaração do problema diz claramente que o codificador pode retornar uma lista de números inteiros em vez de caracteres, para evitar a conversão número inteiro-> caractere-> número inteiro. Além disso, você pode usar em n&(1<<i)vez de n&(1<<i)>0e salvar 2 bytes. Finalmente, o limite superior para i(127) é muito alto , 32 é suficiente e economiza 1 byte.
precisa saber é o seguinte

1
Por favor, indique sua pontuação de acordo com a seção Pontuação na declaração do problema.
precisa saber é o seguinte

@ Delfad0r A pontuação está correta agora? E obrigado pelas dicas.
Hein Wessels

Eu acho que a pontuação é (52+37)*31=2759porque a mais longa é quando todos os 31 bits estão definidos.
Jonathan Allan

O codificador pode lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]salvar 6 bytes.
mypetlion

5

Stax , pontuação 8 × (10 + 9) = 152

Codificador, 10 bytes

Ç·MÉJ'♀τ│½

Execute e depure

16|E{i16*+m Full program, implicit input
16|E        Get hexadecimal digits
    {     m Map:
     i16*+    Add 16 * loop index
            Implicit output as string

O codificador envia a string em uma ordem crescente.

Decodificador, 9 bytes

üL∟n╫k∞‼9

Execute e depure

o{16%m16|E Full program, implicit input
o          Sort string
 {16%m     Module each element by 16
      16|E Interpret as array of hex digits


5

Python 3 , 8 * (45 + 38) = 664

Codificador (45 bytes):

lambda n:[16*i+(n>>4*i)%16 for i in range(8)]

Decodificador (38 bytes):

lambda l:sum(x%16<<x//16*4 for x in l)

Experimente online!


1
Você pode remover os espaços antes "para", lambda l:sum(x%16<<x//16*4for x in l)funciona muito bem :)
FatalError

4
Isso não funciona. A saída não é simples ASCII (no intervalo de 0..127)
GB

2
@GB meu erro. Eu quebrei com a minha última edição. Revertendo agora
Curtis Bechtel

salvar 3 bytes no codificador: lambda n:[n>>4*i&15|i<<4for i in range(8)]e um no descodificador: lambda l:sum(x%16<<x//16*4for x in l)para uma pontuação total de 632
Aaron

4

JavaScript (ES6), 8 * (40 + 32) = 576

0 08

Codificador (40 bytes)

E=(n,k=0)=>n?[k|n&15,...E(n>>4,k+16)]:[]

Decodificador (32 bytes)

s=>s.map(c=>s|=c%16<<(c/4&~3))|s

Demo

Experimente online!

Quão?

A entrada é dividida em 8 blocos de 4 bits e cada bloco é codificado com 1 entre 16 caracteres possíveis. O bit mais significativo do último bloco nunca é definido.

       3222222222211111111110000000000
bit:   0987654321098765432109876543210
       \_/\__/\__/\__/\__/\__/\__/\__/
block:  7  6   5   4   3   2   1   0

block #0 is encoded with char. 00 to 0F (NUL to SI)
block #1 is encoded with char. 10 to 1F (DLE to ES)
block #2 is encoded with char. 20 to 2F (' ' to '/')
block #3 is encoded with char. 30 to 3F ('0' to '?')
block #4 is encoded with char. 40 to 4F ('@' to 'O')
block #5 is encoded with char. 50 to 5F ('P' to '_')
block #6 is encoded with char. 60 to 6F ('`' to 'o')
block #7 is encoded with char. 70 to 77 ('p' to 'w')

4

Gelatina , (8 + 9) bytes * 8 comprimento máximo = 136

b⁴+J’Ɗ⁴¡

Codificador (rodapé formata a lista como Python faria para maior clareza)

Ṣ_J‘Ɗ⁴¡ḅ⁴

Decodificador

Teoricamente, é possível ter um comprimento máximo de seis, isso pode ser feito em 22 bytes ou menos?

É impossível com um comprimento máximo de cinco, pois Eu=0 0Eu=5(127+Eu127)=321402081<231-1

Quão?

Desde a 231-1 é codificável como 8 dígitos hexadecimais (7fffffff ou [7,15,15,15,15,15,15,15]), podemos adicionar o índice baseado em zero de cada dígito hexadecimal multiplicado por 16 para garantir que essa conversão esteja sempre na ordem classificada, mantendo o valor mais à direita dentro dos limites (ou seja [7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127]). A decodificação está revertendo esse mesmo processo.

Codificador :

b⁴+J’Ɗ⁴¡ - Link: integer, n    e.g. 1234
 ⁴       - literal 16               16          
b        - convert to base          [4,13,2]
       ¡ - repeat...
      ⁴  - ...16 times:
     Ɗ   -   last 3 links as a monad:
   J     -     range of length        [1,2,3]     iter 2    iter 3    ...  iter 16
  +      -     add                    [5,15,5]   [5,16,7]   [5,17,9]  ...  [5,30,35]
    ’    -     decrement              [4,14,4]   [4,15,6]   [4,16,8]  ...  [4,29,34]
         -                                                                 [4,29,34]

Decodificador :

Ṣ_J‘Ɗ⁴¡ḅ⁴ - Link: list of integers   e.g. [29,34,4]
Ṣ         - sort                          [4,29,34]
      ¡   - repeat...
     ⁴    - ...16 times:
    Ɗ     -   last 3 links as a monad:
  J       -     range of length           [1,2,3]
 _        -     subtract                  [3,27,31]   [3,26,29]   [3,25,27]  ...  [3,12,1]
   ‘      -     increment                 [4,28,32]   [4,27,30]   [4,26,28]  ...  [4,13,2] 
        ⁴ - literal 16                    16
       ḅ  - from base                     1234

"dígitos hexadecimais", com certeza. ("dígitos usando hexadecimal simples" é mais longo e "dígitos" por si só implica decimal.)
Erik, o Outgolfer, em 23/09/1918

Eu mudei mesmo que devesse ter sido óbvio a partir do contexto, pois imediatamente me referi a dígitos hexadecimais.
Jonathan Allan

O seu cálculo é off por um: existem 321402081 combinações com substituição com um comprimento máximo de 5, e 7177979809, com um comprimento máximo de 6.
Anders Kaseorg

@AndersKaseorg opa, assim é - então é possível com um comprimento máximo de 6 ... dando 22 bytes para brincar!
Jonathan Allan

4

Shakespeare Linguagem de programação , 31 * (472 + 383 379 344) = 26505 26381 25296

Pontuação anterior: 16909322 * (246 + 217) = 7829016086

Ainda é muito alto, mas é o mais baixo em que posso pensar agora.

Codificador:

,.Ajax,.Ford,.Act I:.Scene I:.[Enter Ajax and Ford]Ajax:Remember a pig.Ford:Listen tothy.Scene V:.Ajax:Remember the remainder of the quotient betweenI a big cat.Ford:You be the quotient betweenyou a big cat.Be you nicer zero?If solet usScene V.Remember a pig.Scene X:.Ajax:Recall.Ford:Am I worse zero?If notremember I.If notlet usScene X.Ajax:You zero.Scene L:.Ford:Recall.Ajax:You be the sum ofyou a cat.Am I nicer zero?If sospeak thy.Am I worse zero?If notlet usScene L.

Experimente online!

Decodificador:

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:You cat.Ford:Open mind.Remember the sum ofyou I.Scene V:.Ajax:Am I nicer a cat?If soyou be twice you.Ford:If soyou be the sum ofyou a pig.If solet usScene V.[Exit Ford][Enter Page]Page:Recall.Ajax:Am I worse a cat?If notyou be the sum ofyou Ford.If notlet usAct I.Open heart

Experimente online!

Basicamente, se a sequência contiver um caractere com o código ASCII (n + 1), o enésimo dígito binário será definido.


344 bytes para o decodificador
Jo King

3

Python 3, (208 bytes + 200 bytes) * 6 comprimento = 2448

Experimente online!(contém os dois, o byte extra é a nova linha entre eles).

-4 bytes (pontuação de -24) utilizando a lista vazia (que permitiu que mais coisas começassem em 0)

Codificador (208 bytes)

def E(n,h=128):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    d=l=0
    s=[]
    while n>=T(h,d):
        n-=T(h,d)
        d+=1
    for i in range(d):
        while n>=T(h-l,d+~i):
            n-=T(h-l,d+~i)
            l+=1
        s+=[l]
    return s

Decodificador (200 bytes)

def D(s):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    s.sort()
    l=0
    d=len(s)
    n=sum(T(128,D)for D in range(d))
    for i in s:
        for j in range(l,i):
            n+=T(128-j,d-1)
        l=i
        d-=1
    return n

Observações:

  • A reprodução aleatória pode ser revertida sem perdas para listas estritamente sem aumento (ou seja, classificadas).

  • Listas numéricas estritamente não crescentes do mesmo tamanho podem ser totalmente ordenadas (como estão no Python).

  • Podemos definir que as listas são ordenadas por comprimento primeiro para formar uma ordem total de todas as listas classificadas.

  • Podemos formar uma seqüência indexável dessas listas se definirmos que os valores válidos em uma lista são inteiros de 0que 127inclusive (ou seja, não existe um número finito de listas válidas com comprimento L).

Estratégia:

  • Codificador: dado um número N, encontre a lista Nválida estritamente não crescente.

  • Decodificador: dada uma lista válida (aleatória), classifique-a e retorne seu índice na sequência de listas válidas.

Explicação de código comum:

  • T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1

  • Calcule o n número th- dsimplex

    • Para d=0sempre1

    • Para d=1 , n(o número de pontos em uma linha de pontos com comprimento n)

    • Para d=2,Eu=1nEu, (o número de pontos em um triângulo de pontos com comprimento lateral n)

    • Para d=3,j=1nEu=1jEu, (o número de pontos em um tetraedro de pontos com comprimento lateral n)

Explicação do codificador:

  • def E(n,h=128): d=l=0, s=[]

  • né o número de entrada, hé o "valor alto" (ou seja, o número mais alto permitido + 1), dé o comprimento que a saída será, sé a saída, lé o "valor baixo" (começando em 0, explicado mais adiante)

  • while n>=T(h,d):, n-=T(h,d),d+=1

  • Existem listas de T(h,d)comprimento válidas d, e nosso cálculo é mais fácil se nfor um índice relativo à lista [0]*d(no índice 0) em vez de um índice real; portanto, diminua de nacordo. Isso também ajusta d(o comprimento) para estar correto para o dado n.

  • for i in range(d):

  • Efetivamente: "para o i+1número th na lista"

    • É aqui que eu vou explicar l, o "valor baixo"

    • Depois que um número é colocado na lista, nenhum número menor que ele pode ser colocado na lista (para mantê-lo classificado), assim lcomo o último número que foi adicionado à lista.

    • while n>=T(h-l,d+~i):, n-=T(h-l,d+~i),i+=1

    • Se nfor muito grande para ser codificado com um l"dígito", ajuste-o de nacordo e aumentel

    • s+=[l]

    • Codifique ncom um lneste "dígito".

    • Inicialmente, temos hopções para o "dígito" a ser inserido a seguir, mas uma vez que inserimos o "dígito" (ao qual é atribuído l), estamos limitados às h-lopções para o próximo "dígito".

    • No início, havia T(h,d)listas válidas, mas adicionamos um "dígito" l, diminuindo o número de "dígitos" restantes para d-1e o número de próximos "dígitos" válidos para h-l, portanto, o número de listas válidas depois disso éT(h-l,d-1)

Explicação do decodificador:

  • def D(s):, s.sort(), l=0,d=len(s)

  • sé a lista de entrada (embaralhada), por s.sort()isso; lé o "valor baixo" (h o "valor alto" é apenas literal 128s no código para salvar bytes), né o número de saída, dé o comprimento.

  • n=sum(T(128,D)for D in range(d))

  • Ajustar n para o ponto na sequência de[0]*length

  • for i in s:

  • Para cada dígito:

    • for j in range(l,i):, n+=T(128-j,d-1)

    • Ajustar n para o ponto na sequência de[...prevdigits, thisdigit, 0...]

      • l=i: Defina o "valor baixo" para o dígito mais recente

      • d-=1: Diminua o comprimento desde que usamos um dígito

  • return n: Depois de n ter sido ajustado para todos os dígitos, é o número certo; devolver.

Desculpe se isso não está claro, mas aqui está a minha versão original de depuração sem lobo Experimente-a online! , que não usa a lista vazia, o mesmo ocorre com 1 de todos os números usados ​​nesta versão


3

Ruby , (36 + 29 bytes) * 8, pontuação 520

Codificar:

->n{(0..7).map{|x|(n>>x*=4)%16+x*4}}

Experimente online!

Decodificar:

->a{a.sum{|x|x%16<<(x/4&28)}}

Experimente online!

Como funciona:

O número é codificado usando blocos de 4 bits e um índice de 3 bits.

O decodificador pega a matriz de entrada e coloca cada petisco em seu lugar novamente.


3

Carvão , pontuação 10 * (10 + 15) = 250.

Usa decimal; a solução anterior baseada em 16 teve 328 296 264.

Pode gerar caracteres não imprimíveis. Em particular, o personagem 10 é difícil de inserir no carvão.

Codificador, 10 bytes:

⭆⮌S℅⁺Iι×χκ

Experimente online!Link é a versão detalhada do código.

Decodificador, 15 bytes:

IΣES×﹪℅ιχXχ÷℅ιχ

Experimente online! Link é a versão detalhada do código.

Versão usando uma lista de números inteiros 360 296 (base 16; decimal teria 310):

Codificador, 19 bytes:

NθIE⁸⁺﹪÷θX¹⁶ι¹⁶×¹⁶ι

Experimente online! Link é a versão detalhada do código.

Decodificador, 18 bytes:

IΣEE⁸N×﹪ι¹⁶X¹⁶÷ι¹⁶

Experimente online! Link é a versão detalhada do código.

A versão usando caracteres imprimíveis pontua 360 (era 416 384 368 na base 16):

Codificador, 19 bytes:

⭆⮌S℅⁺Iι×χ⁺κ×⁵⊕׳÷κ⁵

Experimente online! Link é a versão detalhada do código.

Decodificador, 17 bytes:

Fθ⊞υ⌈Φθ¬№υκ⭆υ﹪℅ιχ

Experimente online! Link é a versão detalhada do código.


2

Brachylog , 17 + 18 bytes * 8 comprimento = 280

Codificador:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐ

Decodificador:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐp

Um p pode ser adicionado ao final do codificador sem efeito. O decodificador é executado colocando o resultado (embaralhado) como saída e obtendo o número original na entrada.

Se houvesse um predicado cumulativo (implementado adequadamente), a pontuação poderia cair para 20

Experimente online!


@ Delfad0r adicionando o p para o codificador seria torná-lo ser o mesmo código para codificação e decodificação
Kroppeb

2

05AB1E , pontuação: (2 + 2 bytes ) * 11 comprimento máximo = 44

Codificador (2 bytes ):

Experimente online.

Decodificador (2 bytes ):

Experimente online.

A entrada do codificador e a saída do decodificador são uma lista de dígitos.

Porto da resposta da 2ª geléia de @ ais523 .

Explicação:

    # Undelta (automatically prepends a 0)
      #  i.e. [3,0,4,7,8,2,0,1,9] → [0,3,3,7,14,22,24,24,25,34]

{     # Sort
      #  i.e. [14,7,22,25,24,3,0,24,34,3] → [0,3,3,7,14,22,24,24,25,34]
 ¥    # Deltas
      #  i.e. [0,3,3,7,14,22,24,24,25,34] → [3,0,4,7,8,2,0,1,9]

Como anexa um zero à saída, o comprimento da saída é o comprimento da entrada + 1. Como231-1 tem um comprimento de 10 dígitos, o comprimento máximo da saída é 11.


2

Gol> <> , 8 * (14 + 13) = 216

Codificador Experimente online! , 14 bytes:

I8FfPSD8*L+o|;

Decodificador Experimente online! , 13 bytes:

iEh8SD4*2$X*+

Como isso pode gerar caracteres ascii imprimíveis, interferindo no decodificador, agora existe uma versão usando números na saída / entrada:

Codificador Experimente online! , 14 bytes:

I8FfPSD8*L+N|;

Decodificador Experimente online! , 13 bytes:

IEh8SD4*2$X*+

Codificação:

A codificação funciona dividindo o número especificado em pedaços de 8 x 4 bits. Esses pedaços são deslocados para a direita em 3 bits e a localização original do pedaço é anexada no final como um número entre 0 e 7. Portanto, a codificação se parece com isso:

0AAAABBB
 |__|    -> the original part of the number
     |_| -> the position of the chunk inside the original number 0 = LSB and 7 = MSB

2

Perl 6 , 10 * (10 + 12) = 340 220

Codificador:

{^@_ Z~@_}

Decodificador:

{.sort X%10}

Experimente online!

A função do codificador fecha cada dígito com o índice 0 do número. Em seguida, o codificador classifica a lista de números e obtém o módulo em 10, ou seja, o segundo dígito do número.

O total é 10, pois esse é o comprimento máximo de 2 31 -1.


1

Haskell , 10 * (23 + 51) = 740

Aqui está um programa que codifica, embaralha, decodifica e valida valores: Experimente online!

Codificador, 23 bytes

zipWith((+).(10*))[0..]

Experimente online!

Decodificador, 51 bytes

map snd.sortOn fst.map(`divMod`10)
import Data.List

Experimente online!

Explicação

Como podemos usar a entrada como dígitos decimais, usaremos isso. O codificador mapeia cada dígito que ocorre 10*index + digit, observe que todos os digits estarão inseridos [0..9]para que possamos reverter o acima usando divMod. Depois de restaurar os índices e os dígitos, é apenas uma questão de classificar pelos índices e se livrar deles.

Espera-se que a solução funcione para valores de até 231-1=2147483647 que tem 10 dígitos, então o ponto de código máximo que obtemos será 99=81<128. Além disso, cada dígito será convertido em um "caractere"; portanto, teremos um comprimento máximo de 10.


1

Casca , 10 * (7 + 8) = 150

Porta direta da minha solução Haskell apenas com a observação de que 109=90<128(O Husk's Né baseado em 1):

Codificador, 7 bytes

zo+*10N

Experimente online!

Decodificador, 8 bytes

m→Ö←m‰10

Experimente online!


1

APL (Dyalog Unicode) ,euE+euD=36.;UMA=8288.

d←{16n-16×⍳≢n←⍵[⍋⍵]}
e←(⊢+16×⍳∘≢)16⊥⍣¯1

Experimente online!(contém 5 bytes extras para as atribuições e a nova linha).

Usos ⎕IO←0

Quão:

(⊢+16×⍳∘≢)16⊥⍣¯1  Encoder; input 1234
          16⊥⍣¯1  Convert input to base 16  4 13 2
      ⍳∘≢           [0..length of the list-1]  0 1 2
   16×              times 16  0 16 32
 ⊢+                 plus the original list  4 29 34

{16n-16×⍳≢n←⍵[⍋⍵]}  Decoder; input   34 4 29
              [⍋⍵]   Grade  up  2 0 1
                    Index  with that list  4 29 34
           n        assign that to n
      16×⍳≢          16×[0..length(n)-1]  0 16 32
    n-               subtract that from n  4 13 2
 16                 Decode from base 16  1234

1

PHP, 8 * (44 + 53) = 776

codificador, 44 bytes:

for(;$n=&$argn;$n>>=4)echo$n&15|16*$i++," ";

imprime uma lista de números inteiros separados por espaço. Corra como cano com -nR.

máximo de 8 bytes com 4 bits de dados (mordidela inferior) e 3 bits de peso (mordidela superior).

Simplificando:
Coloque cada dígito hexadecimal em um caractere próprio e use a metade superior do byte para armazenar a posição do dígito.

exemplo:

1457893891( 0x56e5b203) Vai se transformar em
0x03, 0x10, 0x22, 0x3b, 0x45, 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

decodificador, 53 bytes:

while($i++<8)$n+=(15&$x=$argv[$i])<<($x>>4)*4;echo$n;

ou

while($i++<8)$n+=(15&$x=$argv[$i])<<($x/4&~3);echo$n;

ou

for(;$i<9;$x=$argv[++$i])$n+=$x%16<<($x/4&~3);echo$n;

pegue números inteiros dos argumentos da linha de comando. Corra com -nr.


Experimente online .


0

Python 2 , 10 * (68 + 54) = 1220

e=lambda n:"".join(chr(int(`i`+j))for i,j in enumerate(`n`)if j<'L')
d=lambda s:int("".join(`ord(c)%10`for c in sorted(s)))

Experimente online!

EDIT: Obrigado a Jo King pelas dicas - não sei por que eu estava compensando 32, em retrospecto.

Codifica a posição e o valor de cada local como um único caractere, começando com [espaço] (posição 0, valor 0) o byte NUL 0x0.

Decodifica por:

  • classificando a string (Python classificará os caracteres pelo seu valor ordinal)
  • converte cada caractere em seu valor ordinal
  • pega o último dígito de cada número inteiro ordinal
  • junta os números inteiros em uma sequência
  • converte a string unida novamente em um int

Você precisa do 32deslocamento? Além disso, [-1]poderia estar em %10vez disso, no lugar certo
Jo King

0

C (gcc) , 10 * 112 = 1120

c,i;e(i,s)char*s;{for(c=1;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=--c%10*pow(10,c/10));s=i;}

Experimente online!

Eu tenho variáveis ​​globais, mas na verdade elas não estão passando nenhuma informação entre duas funções. A declaração variável para cé usada nas duas funções, economizando 2 bytes de comprimento de código.

Uma versão que usa ASCII imprimível apenas para uma penalidade de 3 5 bytes está aqui:

c,i;e(i,s)char*s;{for(c=32;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=(c-=32)%10*pow(10,c/10));s=i;}

Obrigado @ceilingcat por melhorias de 70 pontos.

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.