Encode - Shuffle - Decode


23

Défi

Votre tâche consiste à coder un entier sous forme de chaîne de caractères ASCII , puis à le décoder avec succès après que ladite chaîne a été mélangée de manière aléatoire.

Vous écrirez deux programmes / fonctions , qui seront appelés Encodeur et Décodeur .

Encodeur

  • Entrée: un entier dans la plage .n[0,231-1]
  • Sortie: une chaîne de caractères ASCII (pas nécessairement imprimable).s

Décodeur

  • Entrée: une permutation aléatoire de la chaîne .ss
  • Sortie: l'entier .n

Notation

Soit la longueur maximale de sur toutes les valeurs possibles de . Si l' encodeur agit de manière non déterministe (ce qui est autorisé, voir ci-dessous), alors le sera la longueur maximale de qui peut se produire (éventuellement ).UNEs n A s snUNEs

Soit la longueur du codeur en octets et la longueur du décodeur en octets.LEL DL

Votre score est alors .UNE(LE+L)

La victoire est attribuée à la soumission avec le score le plus bas .

Limite de temps

Il y a une limite de temps quelque peu arbitraire de 1 minute sur le temps d'exécution à la fois de l' encodeur et du décodeur pour un seul testcase (c'est-à-dire une seule valeur de ).n

Le but est d'éviter les solutions qui trouvent que le codage force brute en énumérant toutes les séquences avec certaines propriétés. Si votre solution fait quelque chose de plus intelligent que cela, elle s'adaptera très probablement à la contrainte de temps et sera considérée comme valide. De même, s'il fonctionne sur TIO pour certaines valeurs de sélectionnées au hasard, il sera considéré comme valide. Sinon, je vais le tester sur ma machine, mais notez que si votre solution est pure force brute, elle échouera presque certainement.n

Règles

  • L' encodeur et le décodeur doivent être écrits dans la même langue .
  • Le décodeur doit sortir le bon entier pour chaque permutation possible de la chaîne retournée par l' encodeur .nss
  • L' encodeur et le décodeur ne sont en aucun cas autorisés à partager des informations (par exemple au moyen de variables globales ou de fichiers).
  • La sortie de l' encodeur n'a pas besoin d' être déterministe (c'est-à-dire que la même entrée peut produire des chaînes de sortie différentes si l' encodeur est exécuté plusieurs fois), mais le décodeur doit toujours deviner le bon entier .nnn
  • L' encodeur et le décodeur peuvent prendre et renvoyer l'entier de n'importe quelle manière appropriée (par exemple, si il convient que l'entrée soit , ou ).nn = 14n=1414"14"[1,4]
  • Le codeur peut délivrer en sortie la chaîne , soit par l' impression sur ou par le retour d' une chaîne, une liste / tableau de caractères ou une liste / tableau d'entiers dans l'intervalle [ 0 , 127 ] ; notez que le décodeur recevra en entrée une permutation de s telle que renvoyée par l' encodeur , il devrait donc accepter la chaîne s ' au même format que s .sstdout [0,127]sss
  • Les failles standard sont interdites.
  • Si possible, expliquez comment fonctionne votre code et pourquoi le score que vous revendiquez est correct.

Exemple

Supposons que n=14 .

  • L' encodeur reçoit 14en entrée. Il peut sortir "qwerty".
  • Le décodeur reçoit une permutation de "qwerty"comme entrée, par exemple "tweyqr". Il doit sortir 14(dans n'importe quel format pratique).

L' encodeur aurait pu également être retourné [113,119,101,114,116,121], auquel cas le décodeur aurait reçu (par exemple) [116,119,101,121,113,114].

Notez que la chaîne renvoyée par l' encodeur peut également inclure des caractères ASCII non imprimables (mais toujours dans la plage [0x00, ..., 0x7F]).


Certes, la longueur de sortie ne peut pas être infinie, vous ne pouvez pas mélanger une chaîne infinie
H.PWiz

@ H.PWiz Non, cela ne peut pas, mais la longueur peut être illimitée si l' encodeur n'est pas déterministe
Delfad0r

"L'encodeur et le décodeur ne sont en aucun cas autorisés à partager des informations" Cela inclut-il les fonctions d'assistance? c'est-à-dire une fonction personnalisée qui calcule N factoriel plus trois (exemple aléatoire)
pizzapants184

Notre encodeur peut-il renvoyer une chaîne / liste vide?
pizzapants184

2
@ Kroppeb Oui, à partir de maintenant, les règles stipulent que vous devez compter les octets deux fois. Je suis très intéressé à voir une soumission avec deux programmes identiques, cependant.
Delfad0r

Réponses:


12

Gelée , (17 octets + 18 octets) × longueur 6 = 210 points

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

Essayez-le en ligne! (ou avec des informations de débogage supplémentaires)

Ayant essayé de résoudre ce défi en visant la condition de victoire déclarée, j'ai pensé qu'il serait intéressant d'opter pour une hypothétique condition de victoire alternative: le étant donné une longueur maximale minimale possible pour la sortie.

Explication

Codage

La première étape du codage consiste à représenter l'entrée comme base 36 ( b36). 36 6 = 2176782336> 2147483647, il y aura donc au plus 6 chiffres dans le résultat, chacun étant compris entre 0 et 35.

Ensuite, nous transformons cela en une représentation qui contient 6 chiffres différents . Il existe plusieurs algorithmes possibles pour cela, mais celui utilisé ici est d'ajouter 1 au plus petit chiffre, 2 au deuxième plus petit, 3 au troisième plus petit, et ainsi de suite. Cela signifie que si deux chiffres étaient identiques, l'un d'eux sera arbitrairement considéré comme plus petit, et donc ils deviendront différents; et évidemment, cet algorithme ne peut pas faire en sorte que deux chiffres différents deviennent identiques. Afin de représenter cela dans Jelly, nous utilisons ("trier les index par valeurs") pour obtenir une liste des index dans l'ordre trié; à nouveau pour inverser cela, en mappant efficacement chaque élément de l'original à sa position dans l'ordre trié; etµ…+pour ajouter l'original à la nouvelle liste. Le résultat est une représentation du numéro d'entrée sous la forme de six chiffres différents dans la plage 1–41 (minimum 0 + 1, maximum 35 + 6).

Nous avons ensuite divisé cela en une autre forme: une liste triée de chiffres dans la plage 1–41, à côté d'un nombre de 1 à 720 qui représente laquelle des 720 permutations possibles les chiffres étaient. (Le Œ¿et extraire le numéro de permutation et trié respectivement.)

Enfin, nous convertissons le nombre de 1 à 720 en base 3 ( b3), l'inversons ( U) et encodons les six chiffres de base 3 et six 1-41 chiffres en les emballant chacun en un seul caractère ASCII à l'aide de divmod inverse (la valeur de le caractère mod 3 est le chiffre de base 3, la valeur divisée par 3 est le chiffre 1–41). La plage de résultats possible est (1 × 3) + 0 = 3 au minimum et (41 × 3) + 2 = 125 au maximum, correspondant à notre plage ASCII. L'empaquetage est effectué via ×3et +, avec un complément µpour vous assurer que chaque commande fonctionne sur le bon bit de données. (Il y a un peu d'astuce de golf ici, en ce sens que nous faisons la multiplication par 3 avant d' extraire la permutation; cela évite d'avoir à dépenser un octet sur un caractère de regroupement.)

Soit dit en passant, la raison pour inverser le nombre de base 3 est qu'il peut avoir moins de chiffres que le nombre 1–41. (Il ne peut pas en avoir plus; le plus petit nombre pour lequel n !> 3 n est légèrement supérieur à 6.) Jelly insère efficacement des zéros de fin lors de l'addition de deux nombres de longueurs différentes, afin de les faire correspondre; les zéros à la fin affecteraient l'interprétation du nombre, mais pas les zéros à gauche, donc l'inverse est utilisé pour s'assurer que les zéros supplémentaires finissent quelque part qui ne gâchera pas notre réponse.

Décodage

La première étape du décodage consiste à extraire les deux nombres (le nombre de base 3 et le nombre 1–41). Nous pouvons obtenir leurs chiffres assez facilement avec division ( :3) et modulo ( %3) respectivement, mais comment savoir dans quel ordre ils se trouvaient? Eh bien, le nombre 1–41 avait ses chiffres dans l'ordre trié, et les chiffres dans les positions correspondantes des deux nombres étaient stockés dans les mêmes caractères; ainsi, nous pouvons déterminer dans quel ordre les chiffres du nombre 1–41 ont été mélangés (en examinant leurs valeurs relatives) et savoir que les chiffres du numéro de base 3 doivent avoir été mélangés de la même manière. En fait, parce que les caractères de notre codage ASCII sont triés de la même manière que les chiffres du nombre 1–41 (ils étaient tous distincts et ils sont plus significatifs que les nombres de base 3),. Les deux extractions commencent donc par , suivies de %3ou :3selon le cas.

Alors que les chiffres du numéro 1–41 sont toujours dans l'ordre trié, nous avons un moyen très pratique / laconique de revenir aux chiffres 0–35 de la base 36; il suffit de soustraire 1 du premier, 2 du second, 3 du troisième, etc. Dans Jelly, nous pouvons le faire avec _J("soustraire l'indice").

Pendant ce temps, dans l'autre branche du décodage, nous inversons les chiffres du numéro de base 3 dans l'ordre ( U), et le reconvertissons de la base 3 en un indice de permutation avec ḅ3.

On peut alors combiner les deux branches avec œ?Ç; œ?signifie "permuter étant donné cet indice de permutation", et Çsignifie "le résultat de l'application de la ligne ci-dessus", c'est-à-dire c'est ce qui dit à Jelly d'exécuter les deux lignes séparément sur la même entrée.

Ce que nous avons maintenant, ce sont les chiffres du nombre d'origine, en base 36 (en raison de _J) et dans l'ordre d'origine (en raison de œ?), nous pouvons donc simplement faire un ḅ36pour revenir de la base 36 en un seul entier.

Commentaire

Le TIO! le lien ci-dessus utilise 312699167 comme numéro à encoder. Ce nombre dans la base 36 est [5, 6, 6, 8, 7, 35], et montre ainsi tous les aspects du codage: le 35 teste la limite de la plage 0–127 que nous avons; les 6s en double testent la résolution de chiffres identiques dans la base d'origine 36; et le fait que les chiffres sont presque (mais pas tout à fait) triés signifie que le nombre de permutation est très petit, ce qui lui donne beaucoup moins de chiffres que le nombre de base 36, et donc montre la nécessité de l'inverser avant de l'ajouter à l'original.

Il est très pratique de savoir comment toutes les constantes s'emboîtent. 36 6 est juste assez haut pour s'adapter à 2 31 , 3 6 n'est que juste assez haut pour accueillir 6 !, et (36 + 6) × 3 est juste juste assez haut pour tenir dans les 128 possibilités que nous avons. (La dernière contrainte ici est la moins stricte, car nous pourrions utiliser l'indexation 0 plutôt que l'indexation 1 pour utiliser des caractères dans la plage 0-2. Pourtant, cela ne donnerait que suffisamment de place pour utiliser 37 comme base plutôt de 36.)


9

Gelée , ( 4 3 octets + 6 5 octets) × longueur 8 = 80 64 points

b⁴Ä
ṢŻIḅ⁴

Essayez-le en ligne!

Gelée , ( 2 1 octet + 4 3 octets) × longueur 10 = 60 40 points

UNE
ṢŻI

Essayez-le en ligne!

Explication

Solution 1

Cela utilise un algorithme différent de la plupart des autres réponses. Nous commençons par encoder la valeur en hexadécimal ( b⁴), comme avec les autres réponses, puis prenons une somme cumulée ( Ä). Chaque entrée donnera clairement une sortie différente (car ces deux opérations sont réversibles), et étant donné que le codage hexadécimal contiendra au plus 8 chiffres dont le maximum est 7 (pour le 8e dernier chiffre) et 15 (pour le dernier au 7e). derniers chiffres), le nombre maximum dans la liste de sortie sera 7+ (7 × 15) = 112, inférieur aux 127 requis par la question. De plus, la sortie sera nécessairement triée, ce qui nous permettra d'inverser le shuffle.

Pour le décodeur, nous inversons d'abord le shuffle avec un sort ( ); inverser ensuite la somme cumulée, en ajoutant un zéro ( Ż) et en prenant la différence de paires consécutives ( I); puis reconvertissez à partir de hexadécimal ( ḅ⁴).

Solution 2

La question nous permet en fait de prendre l'entrée comme une liste de chiffres (probablement décimaux), afin que nous puissions "tricher" en supprimant simplement la conversion de base; le nombre maximum utilisé dans la sortie sera alors 2 + (9 × 9) = 83 (en fait 82 car 2999999999 est hors plage, donc la pire entrée possible est 1999999999). L'encodage résultant est assez terrible car les encodages pour ce problème disparaissent, mais il a l'avantage d'être très laconique à générer, ce qui l'emporte sur la verbosité de l'encodage.

Cette réponse ressemble tellement à de la triche que ce n'est pas ma principale solution à ce problème, mais il semble que cela vaille la peine d'être ajouté car elle est techniquement conforme aux règles et produit un meilleur score.

Commentaire

J'ai quelques algorithmes à l'esprit pour descendre en dessous de la longueur 8, mais il semble peu probable que vous puissiez implémenter un algorithme de longueur 7 en ≤9 octets (sans tricher) ou ≤5 octets (tricher), donc d'après le score dans la question, ce est probablement la meilleure façon de le faire. (Je pourrais peut-être essayer une solution pour le défi alternatif "minimiser la longueur de l'encodage" de toute façon, juste pour le plaisir.)

Contrairement à certaines des solutions, l'utilisation de 16 comme base ici n'est pas critique; il existe de nombreux autres nombres qui fonctionneraient pour une solution de longueur 8 (par exemple 18). J'ai choisi 16 pour la première solution simplement parce que Jelly a une façon de représenter cela sur 1 octet, et d'autres bases viables devraient utiliser plusieurs octets du programme. Bien sûr, la deuxième solution doit utiliser 10 comme base afin d'exploiter la faille.

Merci à @Dennis d'avoir signalé quelques nouvelles commandes Jelly qui ont rendu cet algorithme encore plus tordu à écrire.


3
Äest l'abréviation de +\, Żest l'abréviation de 0;.
Dennis

7

Langage de programmation Shakespeare , 10 * (264 + 494) = 8650 7910 7580

Encodeur: 264 octets

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

Essayez-le en ligne!

Décodeur: 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.

Essayez-le en ligne!

C'était une chose.

L'encodeur code chaque chiffre comme le chiffre plus l'index du chiffre multiplié par douze. Le décodeur stocke toutes les entrées dans la mémoire du Ford, puis effectue une boucle sur un compteur, émettant puis supprimant chaque chiffre inférieur au compteur * 12 + 10.

Explication:

Encodeur

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

Décodeur

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

Encodeur ( 69 52 octets):

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

Décodeur ( 41 37 octets):

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

Stocke tous les bits non nuls du nombre d'entrée sous forme de valeurs ascii. La valeur du caractère ascii stocke la position du bit défini. Par exemple, la valeur «a» signifierait que le 97e bit est défini.

Quelques améliorations, grâce à @ Delfad0r

Essayez-le en ligne!


Bienvenue à PPGC! Vous pouvez supprimer le e = et le d = au début - les fonctions anonymes conviennent parfaitement. Notez également que l'énoncé du problème indique clairement que l' encodeur peut renvoyer une liste d'entiers au lieu de caractères, afin que vous puissiez éviter la conversion entier-> caractère-> entier. De plus, vous pouvez utiliser n&(1<<i)au lieu de n&(1<<i)>0et enregistrer 2 octets. Enfin, la limite supérieure de i(127) est beaucoup trop, 32 est suffisante et enregistre 1 octet.
Delfad0r

1
Veuillez indiquer votre score selon la section Scoring de l'énoncé du problème.
Delfad0r

@ Delfad0r Le score est-il correct maintenant? Et merci pour les conseils.
Hein Wessels

Je pense que le score est (52+37)*31=2759le plus long lorsque les 31 bits sont définis.
Jonathan Allan

L'encodeur peut consister lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]à économiser 6 octets.
mypetlion

5

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

Encodeur, 10 octets

Ç·MÉJ'♀τ│½

Exécuter et déboguer

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'encodeur sort la chaîne dans un ordre croissant.

Décodeur, 9 octets

üL∟n╫k∞‼9

Exécuter et déboguer

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

Encodeur (45 octets):

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

Décodeur (38 octets):

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

Essayez-le en ligne!


1
Vous pouvez supprimer les espaces avant "pour", lambda l:sum(x%16<<x//16*4for x in l)fonctionne très bien :)
FatalError

4
Cela ne fonctionne pas. La sortie n'est pas simple ASCII (dans la plage 0..127)
GB

2
@GB mon erreur. Je l'ai cassé avec mon dernier montage. Revenant maintenant
Curtis Bechtel

enregistrer 3 octets dans l'encodeur: lambda n:[n>>4*i&15|i<<4for i in range(8)]et 1 dans le décodeur: lambda l:sum(x%16<<x//16*4for x in l)pour un score total de 632
Aaron

4

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

08

Encodeur (40 octets)

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

Décodeur (32 octets)

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

Démo

Essayez-le en ligne!

Comment?

L'entrée est divisée en 8 blocs de 4 bits et chaque bloc est codé avec 1 parmi 16 caractères possibles. Le bit le plus significatif du dernier bloc n'est jamais défini.

       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

Gelée , (8 + 9) octets * 8 longueur maximale = 136

b⁴+J’Ɗ⁴¡

Encodeur (le pied de page formate la liste comme le ferait Python pour plus de clarté)

Ṣ_J‘Ɗ⁴¡ḅ⁴

Décodeur

Il est théoriquement possible d'avoir une longueur maximale de six, cela peut-il être fait en 22 octets ou moins?

je=0je=5(127+je127)=321402081<231-1

Comment?

231-17fffffff[7,15,15,15,15,15,15,15][7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127]

Encodeur :

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]

Décodeur :

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

"chiffres hexadécimaux", bien sûr. ("chiffres utilisant hexadécimal simple" est plus long, et "chiffres" seul signifie décimal.)
Erik the Outgolfer

Je l'ai changé même si cela aurait dû être évident dans le contexte car j'ai ensuite immédiatement fait référence aux chiffres hexadécimaux.
Jonathan Allan

Votre calcul est faussé d'un: il existe 321402081 combinaisons avec remplacement d'une longueur maximale de 5 et 7177979809 avec une longueur maximale de 6.
Anders Kaseorg

@AndersKaseorg oups, il en est ainsi - donc c'est possible avec une longueur maximale de 6 ... donnant 22 octets pour jouer avec!
Jonathan Allan

4

Langage de programmation Shakespeare , 31 * (472 + 383 379 344) = 26505 26381 25296

Score précédent: 16909322 * (246 + 217) = 7829016086

C'est encore très élevé, mais c'est le plus bas auquel je puisse penser en ce moment.

Encodeur:

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

Essayez-le en ligne!

Décodeur:

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

Essayez-le en ligne!

Fondamentalement, si la chaîne contient un caractère avec le code ASCII (n + 1), le nième chiffre binaire est défini.


344 octets pour le décodeur
Jo King

3

Python 3, (208 octets + 200 octets) * 6 longueur = 2448

Essayez-le en ligne! (contient les deux, l'octet supplémentaire est la nouvelle ligne entre eux).

-4 octets (score -24) en utilisant la liste vide (qui a permis à plus de choses de commencer à 0)

Encodeur (208 octets)

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

Décodeur (200 octets)

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

Observations:

  • Le brassage peut être inversé sans perte pour les listes strictement non croissantes (c'est-à-dire triées).

  • Des listes numériques strictement non croissantes de même longueur peuvent être totalement ordonnées (comme elles le sont en Python).

  • Nous pouvons définir que les listes sont d'abord triées par longueur pour former un ordre total de toutes les listes triées.

  • Nous pouvons former une séquence indexable de ces listes si nous définissons que les seules valeurs valides dans une liste sont des entiers de 0à 127inclusif (c'est-à-dire qu'il existe un nombre fini de listes valides de longueur L).

Stratégie:

  • Encodeur: Étant donné un nombre N, trouver la Ne liste valide strictement non croissante.

  • Décodeur: étant donné une liste valide (mélangée), triez-la et retournez son index dans la séquence de listes valides.

Explication du code commun:

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

  • Calculer le nombren th d-simplex

    • Pour d=0, toujours1

    • Pour d=1, n(le nombre de points dans une ligne de points de longueur n)

    • d=2je=1njen

    • d=3j=1nje=1jjen

Explication de l'encodeur:

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

  • nest le numéro d'entrée, hest la "valeur élevée" (c'est-à-dire le nombre le plus élevé autorisé + 1), dest la longueur de la sortie, sest la sortie, lest la "valeur faible" (à partir de 0, expliqué plus loin)

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

  • Il existe des listes de T(h,d)longueurs valides d, et notre calcul est plus facile s'il ns'agit d'un index relatif à la liste [0]*d(à index 0) au lieu d'un index réel, donc décrémenter en nconséquence. Cela ajuste également d(la longueur) pour être correct pour le donné n.

  • for i in range(d):

  • Effectivement: "pour le i+1e numéro de la liste"

    • C'est là que je vais vous expliquer l, la "faible valeur"

    • Après qu'un numéro a été mis dans la liste, aucun nombre inférieur à celui qu'il peut être mis dans la liste (pour le garder trié), tout lcomme le dernier numéro ajouté à la liste.

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

    • Si nest trop grand pour être encodé avec un là ce "chiffre", ajustez en nconséquence et incrémentezl

    • s+=[l]

    • Encode navec un là ce "chiffre".

    • Au début, nous avons des hoptions pour ce "chiffre" à mettre ensuite, mais une fois que nous avons mis un "chiffre" (qui est affecté à l), nous sommes limités aux h-loptions pour le "chiffre" suivant.

    • Au début, il y avait des T(h,d)listes valides, mais nous avons ajouté un "chiffre" l, diminuant le nombre de "chiffres" restants d-1et le nombre de "chiffres" suivants valides h-l, donc le nombre de listes valides après c'estT(h-l,d-1)

Explication du décodeur:

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

  • sest la liste d'entrée (mélangée), donc s.sort()elle; lest la "valeur faible" ( hla "valeur élevée" est juste un 128s littéral dans le code pour économiser des octets), nest le numéro de sortie, dest la longueur.

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

  • Ajustez nle point dans la séquence de[0]*length

  • for i in s:

  • Pour chaque chiffre:

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

    • Ajustez nle point dans la séquence de[...prevdigits, thisdigit, 0...]

      • l=i: Définissez la "valeur faible" sur le chiffre le plus récent

      • d-=1: Décrémenter la longueur puisque nous avons utilisé un chiffre

  • return n: Après navoir été ajusté pour tous les chiffres, c'est le bon numéro; rends le.

Désolé si ce n'est pas clair, mais voici ma version originale de débogage non golfée Essayez-le en ligne! , qui n'utilise pas la liste vide, donc est 1 de tous les numéros utilisés dans cette version


3

Ruby , (36 + 29 octets) * 8, score 520

Encoder:

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

Essayez-le en ligne!

Décoder:

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

Essayez-le en ligne!

Comment ça marche:

Le nombre est codé à l'aide de blocs de 4 bits et d'un index de 3 bits.

Le décodeur prend le tableau d'entrée et remet chaque quartet à sa place.


3

Charbon de bois , score 10 * (10 + 15) = 250.

Utilise décimal; la solution précédente basée sur 16 a obtenu 328 296 264.

Peut produire des caractères non imprimables. En particulier, le caractère 10 est difficile à saisir dans Charcoal.

Encodeur, 10 octets:

⭆⮌S℅⁺Iι×χκ

Essayez-le en ligne! Le lien est vers la version détaillée du code.

Décodeur, 15 octets:

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

Essayez-le en ligne! Le lien est vers la version détaillée du code.

La version utilisant une liste d'entiers obtient un score de 360 296 (base 16; le nombre décimal donnerait 310):

Encodeur, 19 octets:

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

Essayez-le en ligne! Le lien est vers la version détaillée du code.

Décodeur, 18 octets:

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

Essayez-le en ligne! Le lien est vers la version détaillée du code.

La version utilisant des caractères imprimables marque 360 ​​(au lieu de 416 384 368 en base 16):

Encodeur, 19 octets:

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

Essayez-le en ligne! Le lien est vers la version détaillée du code.

Décodeur, 17 octets:

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

Essayez-le en ligne! Le lien est vers la version détaillée du code.


2

Brachylog , 17 + 18 octets * 8 longueur = 280

Encodeur:

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

Décodeur:

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

Un p peut être ajouté à la fin de l'encodeur sans effet. Le décodeur est exécuté en mettant le résultat (mélangé) en sortie et en obtenant le numéro d'origine dans l'entrée.

S'il y avait un prédicat de somme cumulée (correctement mis en œuvre), le score pourrait tomber à 20

Essayez-le en ligne!


@ Delfad0r ajouter le p à l'encodeur rendrait le même code pour l'encodage et le décodage
Kroppeb

2

05AB1E , score: (2 + 2 octets ) * 11 longueur maximale = 44

Encodeur (2 octets ):

Essayez-le en ligne.

Décodeur (2 octets ):

Essayez-le en ligne.

L'entrée de l'encodeur et la sortie du décodeur sont une liste de chiffres.

Port de @ ais523 's 2nd Jelly answer .

Explication:

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

231-1


2

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

Encodeur Essayez-le en ligne! , 14 octets:

I8FfPSD8*L+o|;

Décodeur Essayez-le en ligne! , 13 octets:

iEh8SD4*2$X*+

Comme cela peut produire des caractères ascii non imprimables, jouant ainsi avec le décodeur, il existe maintenant une version utilisant des nombres dans la sortie / entrée:

Encodeur Essayez-le en ligne! , 14 octets:

I8FfPSD8*L+N|;

Décodeur Essayez-le en ligne! , 13 octets:

IEh8SD4*2$X*+

Codage:

L'encodage fonctionne en divisant le nombre donné en morceaux de 8 x 4 bits. Ces morceaux sont ensuite décalés de 3 bits vers la droite et l'emplacement d'origine du morceau est ajouté à la fin sous la forme d'un nombre compris entre 0 et 7. Ainsi, l'encodage ressemble à ceci:

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

Encodeur:

{^@_ Z~@_}

Décodeur:

{.sort X%10}

Essayez-le en ligne!

La fonction d'encodeur zippe chaque chiffre avec l'index 0 du nombre. Ensuite, l'encodeur trie la liste des nombres et obtient le modulo par 10, c'est-à-dire le deuxième chiffre du nombre.

Le total est de 10, car c'est la longueur maximale de 2 31 -1.


1

Haskell , 10 * (23 + 51) = 740

Voici un programme qui encode, mélange, décode et valide les valeurs: Essayez-le en ligne!

Encodeur, 23 octets

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

Essayez-le en ligne!

Décodeur, 51 octets

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

Essayez-le en ligne!

Explication

Puisque nous sommes autorisés à utiliser l'entrée comme chiffres décimaux, nous allons l'utiliser. L'encodeur mappe chaque chiffre qui se produit à 10*index + digit, notez que tous les digits seront dedans [0..9]afin que nous puissions inverser ce qui précède en utilisant divMod. Après avoir restauré les indices et les chiffres, il suffit de trier les indices et de s'en débarrasser.

231-1=214748364799=81<128



1

APL (Dyalog Unicode) , LE+L=36;UNE=8288

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

Essayez-le en ligne! (contient 5 octets supplémentaires pour les affectations et la nouvelle ligne).

Les usages ⎕IO←0

Comment:

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

encodeur, 44 octets:

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

affiche une liste d'entiers séparés par des espaces. Exécuter en tant que tuyau avec -nR.

maximum 8 octets avec 4 bits de données (quartet inférieur) et 3 bits de poids (quartet supérieur).

Autrement dit:
mettez chaque chiffre hexadécimal dans un caractère propre et utilisez la moitié supérieure de l'octet pour stocker la position du chiffre.

Exemple:

1457893891( 0x56e5b203) Va se transformer en
0x03, 0x10,0x22 , 0x3b, 0x45, 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

décodeur, 53 octets:

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;

prendre des entiers à partir des arguments de la ligne de commande. Courez avec -nr.


Essayez-les en ligne .


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

Essayez-le en ligne!

EDIT: Merci à Jo King pour les pointeurs - je ne sais pas pourquoi je compensais par 32, rétrospectivement.

Encode la position et la valeur de chaque place en un seul caractère, en commençant par [espace] (position 0, valeur 0) l'octet NUL 0x0.

Décode par:

  • trier la chaîne (Python triera les caractères par leur valeur ordinale)
  • convertit chaque caractère en sa valeur ordinale
  • prend le dernier chiffre de chaque entier ordinal
  • joint les entiers dans une chaîne
  • reconvertit la chaîne jointe en entier

Avez-vous besoin du 32décalage? Aussi, [-1]pourrait être à la %10place, au bon endroit
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;}

Essayez-le en ligne!

J'ai des variables globales, mais elles ne transmettent en fait aucune information entre deux fonctions. La déclaration de variable pour cest utilisée dans les deux fonctions, ce qui me fait gagner 2 octets de longueur de code.

Une version qui utilise ASCII imprimable uniquement pour une pénalité de 3 5 octets est ici:

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

Merci @ceilingcat pour 70 points d'améliorations.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.