Encode - Shuffle - Decode


23

Sfida

Il tuo compito è codificare un numero intero come una stringa di caratteri ASCII , quindi decodificarlo correttamente dopo che la stringa è stata mescolata casualmente.

Scriverete due programmi / funzioni , che saranno chiamati Encoder e Decoder .

Codificatore

  • Input: un numero intero n nell'intervallo [0,2311] .
  • Output: una stringa s di ASCII caratteri (non necessariamente stampabile).

decoder

  • Input: una permutazione casuale s della stringa s .
  • Output: l'intero n .

punteggio

Sia A la lunghezza massima di s per tutti i possibili valori di n . Se l' encoder agisce in modo non deterministico (il che è consentito, vedere di seguito), allora A sarà la lunghezza massima di s che può verificarsi (possibilmente ).

Sia LE la lunghezza dell'encoder in byte e LD la lunghezza del decoder in byte.

Quindi il tuo punteggio è A(LE+LD) .

Alla vittoria viene assegnato il punteggio più basso .

Limite di tempo

C'è un limite al tempo arbitrario di 1 minuto sul tempo di esecuzione sia dell'Encoder che del Decoder per un singolo testcase (cioè un singolo valore di n ).

L'obiettivo è quello di evitare una soluzione che trovi quella forza bruta della codifica enumerando tutte le sequenze con determinate proprietà. Se la tua soluzione fa qualcosa di più intelligente di così, molto probabilmente si adatta al vincolo di tempo e sarà considerata valida. Allo stesso modo, se funziona su TIO per alcuni valori casuali di n sarà considerato valido. Altrimenti lo proverò sulla mia macchina, ma nota che se la tua soluzione è pura forza bruta quasi sicuramente fallirà.

Regole

  • L' encoder e il decoder devono essere scritte nella stessa lingua .
  • Il decodificatore deve emettere il numero intero corretto n per ogni possibile permutazione s della stringa s restituita dall'encoder .
  • L' Encoder e il Decoder non sono autorizzati a condividere informazioni in alcun modo (ad es. Tramite variabili o file globali).
  • L'output dell'Encoder non deve necessariamente essere deterministico (ovvero, lo stesso input n può produrre stringhe di output diverse se l' Encoder viene eseguito più volte), ma il Decoder deve sempre indovinare il numero intero corretto n .
  • L' encoder e il decodificatore possono accettare e restituire l'intero n in qualsiasi modo conveniente (ad es. Se n=14 va bene che l'ingresso sia 14, "14"o [1,4]).
  • Il codificatore può restituire la stringa s mediante stampa su stdout o da restituendo una stringa, una lista / array di caratteri o un elenco / array di interi nell'intervallo [0,127] ; nota che il Decoder riceverà come input una permutazione di s come restituito dall'encoder , quindi dovrebbe accettare la stringa s nello stesso formato di s .
  • Sono vietate le scappatoie standard .
  • Se possibile, spiega come funziona il tuo codice e perché il punteggio che rivendichi è corretto.

Esempio

Supponiamo che n=14 .

  • L' encoder riceve 14come input. Potrebbe emettere "qwerty".
  • Il decodificatore riceve una permutazione di "qwerty"come input, ad esempio "tweyqr". Deve produrre 14(in qualsiasi formato conveniente).

Anche l' Encoder avrebbe potuto essere restituito [113,119,101,114,116,121], nel qual caso il Decoder avrebbe ricevuto (ad esempio) [116,119,101,121,113,114].

Si noti che la stringa restituita dall'encoder può includere anche caratteri ASCII non stampabili (ma sempre nell'intervallo [0x00, ..., 0x7F]).


Sicuramente la lunghezza dell'output non può essere infinita, non è possibile mescolare una stringa infinita
H.Piz,

@ H.PWiz No non può, ma la lunghezza può essere illimitata se l' Encoder non è deterministico
Delfad0r

"L'encoder e il decoder non sono autorizzati a condividere le informazioni in alcun modo" Sono incluse le funzioni di supporto? cioè una funzione personalizzata che calcola N fattoriale più tre (esempio casuale)
pizzapants184

Il nostro Encoder può restituire una stringa / lista vuota?
pizzapants184

2
@Kroppeb Sì, fin d'ora le regole dicono che dovresti contare i byte due volte. Sono molto interessato a vedere una presentazione con due programmi identici, però.
Delfad0r

Risposte:


12

Gelatina , (17 byte + 18 byte) × lunghezza 6 = 210 punti

b36μỤỤ + × 3μŒ¿b3U + s
S: 3_J
S% 3Uḅ3œ? CB36

Provalo online! (o con ulteriori informazioni di debug)

Avendo tentato di risolvere questa sfida puntando alla condizione di vittoria dichiarata, ho pensato che sarebbe stato interessante cercare un'ipotetica condizione di vittoria alternativa: il con una lunghezza massima minima possibile per l'output.

Spiegazione

Codifica

Il primo passo nella codifica è rappresentare l'input come base 36 ( b36). 36 6 = 2176782336> 2147483647, quindi ci saranno al massimo 6 cifre nel risultato, ognuna delle quali è compresa nell'intervallo 0–35.

Successivamente, lo trasformiamo in una rappresentazione che contiene 6 cifre diverse . Esistono diversi algoritmi possibili per questo, ma quello utilizzato qui è quello di aggiungere 1 alla cifra più piccola, 2 al secondo più piccolo, 3 al terzo più piccolo e così via. Ciò significa che se due cifre erano uguali, una di esse verrà arbitrariamente considerata più piccola, e quindi diventeranno diverse; e ovviamente, questo algoritmo non può far sì che due cifre diverse diventino uguali. Per rappresentarlo in Jelly, utilizziamo ("ordina gli indici per valori") per ottenere un elenco degli indici in ordine ordinato; di nuovo per invertire ciò, mappando efficacemente ogni elemento dell'originale nella sua posizione in ordine ordinato; eµ…+per aggiungere l'originale al nuovo elenco. Il risultato è una rappresentazione del numero di input come sei cifre diverse nell'intervallo 1–41 (minimo 0 + 1, massimo 35 + 6).

Abbiamo poi diviso questo in un'altra forma: un ordinato lista di cifre nel range 1-41, a fianco di un certo numero 1-720 che rappresenta quale delle 720 possibili permutazioni le cifre erano in (La. Œ¿Ed estrarre il numero permutazione e ordinati lista rispettivamente.)

Infine, convertiamo il numero da 1 a 720 in base 3 ( b3), invertiamo ( U) e codifichiamo le sei cifre della base 3 e le sei 1-41 cifre impacchettandole ognuna in un singolo carattere ASCII usando il divmod inverso (il valore di il carattere mod 3 è la cifra di base 3, il valore diviso per 3 è la cifra 1–41). La possibile gamma di risultati è (1 × 3) + 0 = 3 al minimo e (41 × 3) + 2 = 125 al massimo, adattandosi alla nostra gamma ASCII. L'imballaggio viene eseguito tramite ×3e +, insieme a un ulteriore, µper assicurarsi che ogni comando operi sul giusto bit di dati. (C'è un po 'di un trucco da golf qui, in quanto facciamo la moltiplicazione per 3 prima di estrarre la permutazione; ciò evita la necessità di spendere un byte su un personaggio di raggruppamento.)

Per inciso, il motivo per invertire il numero di base 3 è perché potrebbe avere meno cifre rispetto al numero 1-41. (Non può avere di più; il numero più piccolo per cui n !> 3 n è leggermente superiore a 6.) Jelly inserisce efficacemente zeri finali quando si sommano due numeri di lunghezze diverse, al fine di farli corrispondere; zeri finali avrebbero influenzare l'interpretazione del numero, ma che portano gli zeri non sarebbe, quindi il contrario viene utilizzato per garantire che gli zeri in più finiscono da qualche parte che non rovinare la nostra risposta.

decodifica

Il primo passo nella decodifica consiste nell'estrarre i due numeri (il numero di base 3 e il numero 1–41). Possiamo ottenere le cifre abbastanza facilmente rispettivamente con division ( :3) e modulo ( %3), ma come sapere in quale ordine erano? Bene, il numero 1–41 aveva le sue cifre in ordine, e le cifre nelle posizioni corrispondenti dei due numeri erano memorizzate negli stessi caratteri; quindi, possiamo capire in quale ordine sono state mescolate le cifre del numero 1-41 (osservando i loro valori relativi) e sapere che le cifre del numero base-3 devono essere state mischiate allo stesso modo. Infatti, poiché i caratteri della nostra codifica ASCII ordinano allo stesso modo delle cifre del numero 1-41 (erano tutte distinte e sono più significative rispetto al numero di base 3),. Quindi entrambe le estrazioni iniziano con , seguito da %3o :3come appropriato.

Mentre le cifre del numero 1-41 sono ancora in ordine, abbiamo un modo molto conveniente / conciso per tornare alle cifre 0–35 della base 36; sottrai solo 1 dal primo, 2 dal secondo, 3 dal terzo e così via. In Jelly, possiamo farlo con _J("sottrai indice").

Nel frattempo, nell'altro ramo della decodifica, invertiamo nuovamente le cifre del numero di base 3 in order ( U) e lo convertiamo dalla base 3 in un indice di permutazione con ḅ3.

Possiamo quindi combinare i due rami con œ?Ç; œ?significa "permuto dato questo indice di permutazione" e Çsignifica "il risultato dell'applicazione della riga sopra", ovvero è ciò che dice a Jelly di eseguire entrambe le linee separatamente sullo stesso input.

Ciò che abbiamo ora sono le cifre del numero originale, in base 36 (a causa di _J), e nell'ordine originale (a causa di œ?), quindi possiamo semplicemente fare un ḅ36per riconvertire dalla base 36 in un singolo numero intero.

Commento

Il TIO! il link sopra utilizza 312699167 come numero da codificare. Questo numero nella base 36 è [5, 6, 6, 8, 7, 35], e quindi mostra tutti gli aspetti della codifica: il 35 verifica il limite dell'intervallo 0-127 che abbiamo; i duplicati 6 testano la risoluzione di cifre identiche nella base originale 36; e il fatto che le cifre siano quasi (ma non del tutto) ordinate significa che il numero di permutazione è molto piccolo, dandogli molte meno cifre rispetto al numero di base 36 e mostrando quindi la necessità di invertirlo prima di aggiungerlo all'originale.

È davvero conveniente come tutte le costanti qui si incastrino. 36 6 è solo appena abbastanza alto per adattarsi 2 31 , 3 6 è solo appena abbastanza alto per adattarsi 6 !, e (36 + 6) × 3 è solo appena abbastanza alto per adattarsi entro i 128 possibilità che abbiamo. (L'ultimo vincolo qui è il meno stretto, perché potremmo usare l'indicizzazione 0 anziché l'indicizzazione 1 per utilizzare i caratteri nell'intervallo 0-2. Tuttavia, ciò darebbe solo abbastanza spazio per usare 37 come base piuttosto di 36.)


9

Gelatina , ( 4 3 byte + 6 5 byte) × lunghezza 8 = 80 64 punti

b⁴Ä
ṢŻIḅ⁴

Provalo online!

Gelatina , ( 2 1 byte + 4 3 byte) × lunghezza 10 = 60 40 punti

UN
Szi

Provalo online!

Spiegazione

Soluzione 1

Questo utilizza un algoritmo diverso dalla maggior parte delle altre risposte. Iniziamo codificando il valore in esadecimale ( b⁴), come con le altre risposte, quindi prendiamo una somma cumulativa ( Ä). Ogni input fornirà chiaramente un output diverso (poiché entrambe queste operazioni sono reversibili) e dato che la codifica esadecimale conterrà al massimo 8 cifre i cui valori massimi sono 7 (per l'ottava ultima cifra) e 15 (per l'ultimo al 7o- ultime cifre), il numero massimo nell'elenco di output sarà 7+ (7 × 15) = 112, inferiore ai 127 richiesti dalla domanda. Inoltre, l'output sarà necessariamente in ordine, permettendoci di invertire lo shuffle.

Per il decodificatore, per prima cosa invertiamo lo shuffle con un ordinamento ( ); quindi invertire la somma cumulativa, anticipando uno zero ( Ż) e prendendo la differenza di coppie consecutive ( I); quindi riconvertire da esadecimale ( ḅ⁴).

Soluzione 2

La domanda in realtà ci consente di prendere l'input come un elenco di cifre (presumibilmente decimali), quindi possiamo "imbrogliare" semplicemente rimuovendo la conversione di base; il numero massimo utilizzato nell'output sarà quindi 2 + (9 × 9) = 83 (in realtà 82 perché 2999999999 non è compreso nell'intervallo, quindi l'ingresso peggiore possibile è 1999999999). La codifica risultante è piuttosto terribile come vanno le codifiche per questo problema, ma ha il vantaggio di essere molto concisa da generare, il che supera la verbosità della codifica.

Questa risposta sembra talmente ingannevole che non è la mia soluzione principale per questo problema, ma sembra che valga la pena aggiungerla perché tecnicamente è conforme alle regole e produce un punteggio migliore.

Commento

Ho in mente alcuni algoritmi per scendere sotto la lunghezza 8, ma sembra improbabile che tu possa implementare un algoritmo di lunghezza 7 in ≤9 byte (non imbrogliare) o ≤5 byte (imbrogliare), quindi dal punteggio nella domanda, questo è probabilmente il modo migliore per farlo. (Potrei comunque provare una soluzione per la sfida alternativa "minimizza la lunghezza della codifica", comunque, solo per divertimento.)

A differenza di alcune delle soluzioni, l'uso di 16 come base qui non è critico; ci sono molti altri numeri che funzionerebbero per una soluzione di lunghezza 8 (es. 18). Ho scelto 16 per la prima soluzione semplicemente perché Jelly ha un modo a 1 byte per rappresentarlo, e altre basi vitali avrebbero bisogno di utilizzare più byte dal programma. Naturalmente, la seconda soluzione deve usare 10 come base per sfruttare la scappatoia.

Grazie a @Dennis per aver segnalato alcuni nuovi comandi Jelly che hanno reso questo algoritmo ancora più difficile da scrivere.


3
Äè l'abbreviazione di +\, Żè l'abbreviazione di 0;.
Dennis,

7

Shakespeare Programming Language , 10 * (264 + 494) = 8650 7910 7580

Encoder: 264 byte

,.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.

Provalo online!

Decodificatore: 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.

Provalo online!

Questa era una cosa.

Il codificatore codifica ogni cifra come cifra più l'indice della cifra per dodici. Il decodificatore memorizza tutti gli input nella memoria della Ford e quindi passa su un contatore, emettendo quindi eliminando ogni cifra inferiore al contatore * 12 + 10.

Spiegazione:

Codificatore

,.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.

decoder

,.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

Encoder ( 69 52 byte):

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

Decodificatore ( 41 37 byte):

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

Memorizza tutti i bit diversi da zero nel numero di input come valori ASCII. Il valore del carattere ascii memorizza la posizione del bit impostato. Ad esempio il valore "a" significherebbe che è impostato il 97 ° bit.

Alcuni miglioramenti, grazie a @ Delfad0r

Provalo online!


Benvenuti in PPGC! Puoi rilasciare il e = e d = all'inizio - le funzioni anonime sono perfettamente a posto. Inoltre, tieni presente che l'istruzione problematica dice chiaramente che l' Encoder potrebbe restituire un elenco di numeri interi anziché caratteri, in modo da poter evitare la conversione intero-> carattere-> intero. Inoltre, è possibile utilizzare n&(1<<i)anziché n&(1<<i)>0e salvare 2 byte. Infine, il limite superiore per i(127) è troppo, 32 è sufficiente e salva 1 byte.
Delfad0r

1
Si prega di indicare il proprio punteggio in base alla sezione Punteggio nell'istruzione del problema.
Delfad0r

@ Delfad0r Il punteggio è corretto ora? E grazie per i suggerimenti.
Hein Wessels,

Penso che il punteggio sia (52+37)*31=2759dal momento che il più lungo è quando sono impostati tutti e 31 i bit.
Jonathan Allan,

L'encoder può essere lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]per salvare 6 byte.
mypetlion,

5

Stax , punteggio 8 × (10 + 9) = 152

Encoder, 10 byte

Ç·MÉJ'♀τ│½

Esegui ed esegui il debug

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

L'encoder emette la stringa in ordine crescente.

Decodificatore, 9 byte

üL∟n╫k∞‼9

Esegui ed esegui il debug

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

Encoder (45 byte):

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

Decodificatore (38 byte):

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

Provalo online!


1
Puoi rimuovere gli spazi prima di "for", lambda l:sum(x%16<<x//16*4for x in l)funziona bene :)
FatalError

4
Questo non funziona. L'output non è semplice ASCII (nell'intervallo 0..127)
GB

2
@ GB mio errore. L'ho rotto con la mia ultima modifica. Ripristino ora
Curtis Bechtel,

salva 3 byte nell'encoder: lambda n:[n>>4*i&15|i<<4for i in range(8)]e 1 nel decoder: lambda l:sum(x%16<<x//16*4for x in l)per un punteggio totale di 632
Aaron,

4

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

L'encoder emette un array di 0 a 8interi. Il decodificatore assume lo stesso formato di input.

Encoder (40 byte)

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

Decodificatore (32 byte)

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

dimostrazione

Provalo online!

Come?

L'ingresso è diviso in 8 blocchi di 4 bit e ogni blocco è codificato con 1 tra 16 possibili caratteri. Il bit più significativo dell'ultimo blocco non viene mai impostato.

       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) byte * 8 lunghezza massima = 136

b⁴+J’Ɗ⁴¡

Encoder (il piè di pagina formatta l'elenco come Python farebbe per chiarezza)

Ṣ_J‘Ɗ⁴¡ḅ⁴

decoder

È teoricamente possibile avere una lunghezza massima di sei, può essere fatto in 22 byte o meno?

Da allora è impossibile con una lunghezza massima di cinque Σio=0io=5(127+io127)=321402081<231-1

Come?

Da 231-1è codificabile come 8 cifre esadecimali ( 7fffffffo [7,15,15,15,15,15,15,15]) potremmo quindi aggiungere l'indice in base zero di ogni cifra esadecimale moltiplicata per 16 per garantire che tale conversione sia sempre in ordine, mantenendo anche il valore più giusto nei limiti (es [7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127].). La decodifica sta quindi invertendo questo stesso processo.

Encoder :

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]

Decodificatore :

Ṣ_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

"cifre esadecimali", certo. ("le cifre che usano un semplice esadecimale" sono più lunghe e le "cifre" da sole implicano il decimale.)
Erik the Outgolfer

L'ho cambiato anche se avrebbe dovuto essere ovvio dal contesto dato che mi riferivo immediatamente alle cifre esadecimali.
Jonathan Allan,

Il tuo calcolo è fuori di uno: ci sono 321402081 combinazioni con sostituzione con una lunghezza massima di 5 e 7177979809 con una lunghezza massima di 6.
Anders Kaseorg

@AndersKaseorg oops, così è - quindi è possibile con una lunghezza massima di 6 ... dando 22 byte con cui giocare!
Jonathan Allan,

4

Shakespeare Programming Language , 31 * (472 + 383 379 344) = 26505 26381 25296

Punteggio precedente: 16909322 * (246 + 217) = 7829016086

Questo è ancora molto alto, ma è il più basso che mi viene in mente in questo momento.

Codificatore:

,.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.

Provalo online!

decoder:

,.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

Provalo online!

Fondamentalmente, se la stringa contiene un carattere con il codice ASCII (n + 1), viene impostata l'ennesima cifra binaria.


344 byte per il decodificatore
Jo King,

3

Python 3, (208 byte + 200 byte) * 6 lunghezza = 2448

Provalo online!(contiene entrambi, il byte aggiuntivo è la nuova riga tra di loro).

-4 byte (punteggio -24) utilizzando l'elenco vuoto (che ha permesso a più cose di iniziare da 0)

Encoder (208 byte)

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

Decodificatore (200 byte)

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

osservazioni:

  • Il mescolamento può essere invertito senza perdita di dati per elenchi strettamente non in aumento (ovvero ordinati).

  • Elenchi numerici rigorosamente non crescenti della stessa lunghezza possono essere totalmente ordinati (come in Python).

  • Possiamo definire che gli elenchi sono ordinati per lunghezza per primi per formare un ordine totale di tutti gli elenchi ordinati.

  • Possiamo formare una sequenza indicizzabile di queste liste se si definisce che i soli valori validi in una lista sono numeri interi da 0a 127inclusivo (cioè esiste un numero finito di liste valide con lunghezza L).

Strategia:

  • Encoder: dato un numero N, trova l' Nelenco valido strettamente non crescente.

  • Decodificatore: dato un elenco valido (mischiato), ordinarlo e restituire il suo indice nella sequenza di elenchi validi.

Spiegazione del codice comune:

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

  • Calcolare il nesimo dnumero di -simplex

    • Per d=0sempre1

    • Per d=1, n(il numero di punti in una linea di punti con lunghezza n)

    • Per d=2,Σio=1nio, (il numero di punti in un triangolo di punti con lunghezza laterale n)

    • Per d=3,Σj=1nΣio=1jio, (il numero di punti in un tetraedro di punti con lunghezza laterale n)

Spiegazione dell'encoder:

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

  • nè il numero di input, hè il "valore alto" (ovvero il numero più alto consentito + 1), dè la lunghezza dell'output, sè l'output, lè il "valore basso" (a partire da 0, spiegato più avanti)

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

  • Esistono elenchi di T(h,d)lunghezze validi de il nostro calcolo è più semplice se si ntratta di un indice relativo all'elenco [0]*d(in corrispondenza dell'indice 0) anziché di un indice effettivo, quindi diminuire di nconseguenza. Questo regola anche d(la lunghezza) per essere corretto per il dato n.

  • for i in range(d):

  • In effetti: "per il i+1numero th nell'elenco"

    • Questo è dove spiegherò l, il "valore basso"

    • Dopo che un numero è stato inserito nell'elenco, nessun numero inferiore a quello che può essere inserito nell'elenco (per mantenerlo ordinato), così lè l'ultimo numero che è stato aggiunto all'elenco.

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

    • Se nè troppo grande per essere codificato con un lin questa "cifra", quindi regolare di nconseguenza e incrementarel

    • s+=[l]

    • Codificare ncon un la questa "cifra".

    • Inizialmente, abbiamo le hopzioni per quale "cifra" inserire, ma una volta inserita una "cifra" (a cui è assegnato l), siamo limitati alle h-lopzioni per la "cifra" successiva.

    • All'inizio c'erano T(h,d)elenchi validi, ma abbiamo aggiunto una "cifra" l, diminuendo il numero di "cifre" rimanenti d-1e il numero di "cifre" successive valide a h-l, quindi il numero di elenchi validi dopo questo èT(h-l,d-1)

Spiegazione del decodificatore:

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

  • sè l'elenco di input (mischiato), quindi s.sort(); lè il "valore basso" ( hil "valore alto" è letteralmente 128s nel codice per salvare i byte), nè il numero di output, dè la lunghezza.

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

  • Regolare nil punto nella sequenza di[0]*length

  • for i in s:

  • Per ogni cifra:

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

    • Regolare nil punto nella sequenza di[...prevdigits, thisdigit, 0...]

      • l=i: Imposta il "valore basso" sulla cifra più recente

      • d-=1: Diminuisce la lunghezza da quando abbiamo usato una cifra

  • return n: Dopo che nè stato regolato per tutte le cifre, è il numero giusto; restituirlo.

Scusate se non è chiaro, ma ecco la mia versione originale di debug non golf Provalo online! , che non utilizza l'elenco vuoto, quindi è 1 su tutti i numeri utilizzati in questa versione


3

Rubino , (36 + 29 byte) * 8, punteggio 520

Codificare:

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

Provalo online!

Decodificare:

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

Provalo online!

Come funziona:

Il numero è codificato usando blocchi di 4 bit e un indice di 3 bit.

Il decodificatore prende l'array di input e rimette al suo posto ogni bocconcino.


3

Carbone di legna , punteggio 10 * (10 + 15) = 250.

Usa decimale; la precedente soluzione basata su base 16 ha ottenuto 328 296 264.

Può generare caratteri non stampabili. In particolare, il personaggio 10 è difficile da inserire in Carbone.

Encoder, 10 byte:

⭆⮌S℅⁺Iι×χκ

Provalo online! Il collegamento è alla versione dettagliata del codice.

Decodificatore, 15 byte:

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

Provalo online! Il collegamento è alla versione dettagliata del codice.

La versione che utilizza un elenco di numeri interi ottiene 360 296 (base 16; il decimale segnerebbe 310):

Encoder, 19 byte:

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

Provalo online!Il collegamento è alla versione dettagliata del codice.

Decodificatore, 18 byte:

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

Provalo online!Il collegamento è alla versione dettagliata del codice.

Versione utilizzando caratteri stampabili punteggi 360 (era 416 384 368 nella base 16):

Encoder, 19 byte:

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

Provalo online!Il collegamento è alla versione dettagliata del codice.

Decodificatore, 17 byte:

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

Provalo online! Il collegamento è alla versione dettagliata del codice.


2

Brachylog , 17 + 18 byte * 8 lunghezza = 280

Codificatore:

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

decoder:

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

Una p può essere aggiunta alla fine dell'encoder senza alcun effetto. Il decodificatore viene eseguito inserendo il risultato (mischiato) come output e ottenendo il numero originale nell'input.

Se ci fosse un predicato di somma cumulativa (correttamente implementato) il punteggio potrebbe scendere a 20

Provalo online!


@ Delfad0r l'aggiunta della p all'encoder renderebbe lo stesso codice per la codifica e la decodifica
Kroppeb

2

05AB1E , punteggio: (2 + 2 byte ) * 11 lunghezza massima = 44

Encoder (2 byte ):

Provalo online.

Decodificatore (2 byte ):

Provalo online.

L'ingresso dell'encoder e l'uscita del decoder sono un elenco di cifre.

La seconda risposta di Jelly di Port a @ ais523 .

Spiegazione:

    # 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]

Poiché antepone uno zero all'uscita, la lunghezza dell'uscita è la lunghezza dell'ingresso + 1. Da allora231-1 ha una lunghezza di 10 cifre, la lunghezza massima dell'output è 11.


2

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

Encoder Provalo online! , 14 byte:

I8FfPSD8*L+o|;

Decoder Provalo online! , 13 byte:

iEh8SD4*2$X*+

Dal momento che questo può generare caratteri ASCII non stampabili, quindi pasticciare con il decodificatore, ora esiste una versione che utilizza numeri nell'output / input:

Encoder Provalo online! , 14 byte:

I8FfPSD8*L+N|;

Decoder Provalo online! , 13 byte:

IEh8SD4*2$X*+

Codifica:

La codifica funziona suddividendo il numero specificato in blocchi di 8 x 4 bit. Questi blocchi vengono quindi spostati a destra di 3 bit e la posizione originale del blocco viene aggiunta alla fine come un numero compreso tra 0 e 7. Quindi la codifica è simile alla seguente:

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

Codificatore:

{^@_ Z~@_}

decoder:

{.sort X%10}

Provalo online!

La funzione encoder comprime ogni cifra con l'indice 0 del numero. Quindi l'encoder ordina l'elenco dei numeri e ottiene il modulo per 10, in altre parole la seconda cifra del numero.

Il totale è 10, poiché questa è la lunghezza massima di 2 31 -1.


1

Haskell , 10 * (23 + 51) = 740

Ecco un programma che codifica, mescola, decodifica e convalida i valori: provalo online!

Encoder, 23 byte

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

Provalo online!

Decodificatore, 51 byte

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

Provalo online!

Spiegazione

Dato che ci è permesso usare l'input come cifre decimali, lo useremo .. L'encoder mappa ogni cifra che si verifica 10*index + digit, nota che tutti gli digits saranno in [0..9]modo da poter invertire quanto sopra usandodivMod . Dopo aver ripristinato gli indici e le cifre, è solo una questione di ordinamento per indici e di eliminarli.

La soluzione dovrebbe funzionare per valori fino a 231-1=2147483647 che è lungo 10 cifre, quindi il massimo punto di codice che otterremo sarà 99=81<128. Inoltre ogni cifra verrà convertita in un "carattere", quindi finiremo con una lunghezza massima di 10.


1

Buccia , 10 * (7 + 8) = 150

Porta diretta della mia soluzione Haskell solo con l'osservazione che 109=90<128(Husk Nè basato su 1):

Encoder, 7 byte

zo+*10N

Provalo online!

Decodificatore, 8 byte

m→Ö←m‰10

Provalo online!


1

APL (Dyalog Unicode) ,LE+LD=36;UN=8288.

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

Provalo online! (contiene 5 byte extra per gli incarichi e la nuova riga).

usi ⎕IO←0

Come:

(⊢+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

encoder, 44 byte:

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

stampa un elenco di numeri interi separati da spazi. Esegui come pipe con -nR.

massimo 8 byte con 4 bit di dati (nibble inferiore) e 3 bit di peso (nibble superiore).

In poche parole:
metti ogni cifra esadecimale in un proprio carattere e usa la metà superiore del byte per memorizzare la posizione della cifra.

esempio:

1457893891( 0x56e5b203) Si trasformerà in
0x03, 0x10, 0x22, 0x3b, 0x45, 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

decodificatore, 53 byte:

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

o

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

o

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

accetta numeri interi dagli argomenti della riga di comando. Corri con -nr.


Provali 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)))

Provalo online!

EDIT: Grazie a Jo King per i suggerimenti - non sono sicuro del motivo per cui mi stavo sfalsando di 32, a posteriori.

Codifica la posizione e il valore di ogni posto come un singolo carattere, iniziando con [spazio] (posizione 0, valore 0) il byte NUL 0x0.

Decodifica per:

  • ordinamento della stringa (Python ordina i caratteri in base al loro valore ordinale)
  • converte ogni carattere nel suo valore ordinale
  • prende l'ultima cifra di ogni intero ordinale
  • unisce gli interi in una stringa
  • converte nuovamente la stringa unita in un int

Hai bisogno 32dell'offset? Inoltre, [-1]potrebbe essere %10invece, nel posto giusto
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;}

Provalo online!

Ho variabili globali, ma in realtà non stanno trasmettendo informazioni tra due funzioni. La dichiarazione di variabile per cviene utilizzata in entrambe le funzioni salvandomi 2 byte nella lunghezza del codice.

Una versione che utilizza ASCII stampabile solo per una penalità di 3 5 byte è qui:

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;}

Grazie a @ceilingcat per i miglioramenti di 70 punti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.