mathpack littéraux numériques

10

préface

Dans une situation très chaude, il faut aller encore plus loin avec le golf.
(par exemple, dans un défi où votre réponse comporte 100 caractères et il est juste embarrassant que vous ne puissiez pas le faire 99)
Dans ce cas, vous utilisez désormais l'algorithme du gagnant de ce défi :)

objectif

Vous devez écrire un programme qui prend un uint32 et retourne le formulaire le plus compressé.

$ mathpack 147456
9<<14
  • Il y aura plusieurs solutions pour un certain nombre. Choisissez le plus court
  • Si le formulaire compressé est plus long ou égal au numéro d'origine, renvoyez le numéro d'origine

règles

  • écrire dans n'importe quelle langue - sortie dans n'importe quelle langue
  • Je suis conscient que C 'abc'est 6382179et vous pouvez obtenir de jolis bons résultats avec cette conversion. mais les langues sont séparées dans ce défi alors ne vous découragez pas
  • il est interdit d'utiliser des variables externes. uniquement des opérateurs et des littéraux et des fonctions mathématiques!

notation

voici les cas de test: pastebin.com/0bYPzUhX
votre score (en pourcentage) sera le ratio
byte_size_of_your_output / byte_size_of_the_list sans saut de ligne .
(vous devez le faire vous-même car je vais juste vérifier les meilleurs codes au cas où) les
gagnants seront choisis par score et langue de sortie !

exemples:

$ mathpack 147456 | mathpack 97787584 |  mathpack 387420489
            9<<14 |           9e7^9e6 |            pow(9,9)
être
la source
Beau défi, mais vous devriez ajouter une règle contre le codage en dur.
ɐɔıʇǝɥʇuʎs
y-vous voulez dire les cas 10k de codage en dur? bien que je serais heureux d'obtenir un soutien sur la façon d'affiner ce défi
bebe
édité (encore et encore ...) pour plus de clarté. merci pour les conseils.
bebe
Ne serait-ce pas aussi [pierre de rosette]? Aussi: write in any language - output in any language- les deux langues peuvent être différentes, non?
ɐɔıʇǝɥʇuʎs
@ ɐɔıʇǝɥʇuʎs [rosetta-pierre] est en fait de vous résoudre dans autant de langues que possible. Et oui à votre dernière question - qui a été modifiée en réponse à ma question.
Martin Ender

Réponses:

1

Code: Mathematica, sortie: C, ~ 62,1518% (12674/20392)

Je pensais que j'allais aussi essayer C à cause de ces littéraux de personnages amusants. Actuellement, c'est la seule chose que cette réponse essaie, et cela fonctionne assez bien.

mathpack[n_] := Module[{versions, charLiteral},
   charLiteral = "'" <> StringReplace[Map[
        Switch[#,
          (*d_ /; d < 32,
          "\\" <> IntegerString[#, 8],*)
          10,
          "\\n",
          13,
          "\\r"
          39,
          "\\'",
          92 ,
          "\\\\",
          _,
          FromCharacterCode@#] &,
        FromDigits[#, 
           2] & /@ (Partition[PadLeft[IntegerDigits[n, 2], 32], 
            8] //. {{0 ..} .., x__} :> {x})
        ] <> "",
      {(*"\\10" -> "\\b",
       "\\11" -> "\\t",
       "\\13" -> "\\v",
       "\\14" -> "\\f",*)
       RegularExpression["(?!<=\?)\?\?(?=[=/()!<>-]|$)"] -> "?\\?"
       }
      ] <> "'";
   versions = {ToString@n, charLiteral};
   SortBy[versions, StringLength][[1]]
 ];

J'espère que je n'ai rien manqué, mais cette réponse permet d'échapper aux barres obliques inverses, aux guillemets simples ainsi qu'aux trigraphes. Il y a du code commenté qui utilise des séquences octales ou d'autres séquences d'échappement pour les caractères non imprimables, mais je ne pense pas que ce soit réellement nécessaire, car C devrait être capable de gérer tous les octets dans les littéraux de caractères, afaik (veuillez me corriger si je je me trompe).

Comme pour l'autre soumission, testez-la avec

input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Martin Ender
la source
(Sur mon système au moins) GCC acceptera tout octet entre guillemets, sauf 10 ( \n) et 13 ( \r). Un octet zéro compilera OK, mais avec le message d'erreur warning: null character(s) preserved in literal.
r3mainer
@squeamishossifrage Merci, fixe!
Martin Ender
3

Code: Mathematica, sortie: Julia, ~ 98,9457% (20177/20392 octets)

optimise[n_] := 
  Module[{bits, trimmedBits, shift, unshifted, nString, versions, 
    inverted, factorised, digits, trimmedDigits, exponent, base, 
    xored, ored, anded},
   nString = ToString@n;
   versions = {nString};

   (* Try bitshifting *)
   bits = IntegerDigits[n, 2];
   trimmedBits = bits /. {x___, 1, 0 ..} :> {x, 1};
   shift = ToString[Length[bits] - Length[trimmedBits]];
   unshifted = ToString@FromDigits[trimmedBits, 2];
   AppendTo[versions, unshifted <> "<<" <> shift];

   (* Try inverting *)
   inverted = ToString@FromDigits[1 - PadLeft[bits, 32], 2];
   AppendTo[versions, "~" <> inverted];

   (* Try invert/shift/invert *)
   trimmedBits = bits /. {x___, 0, 1 ..} :> {x, 1};
   shift = ToString[Length[bits] - Length[trimmedBits]];
   unshifted = ToString@FromDigits[trimmedBits, 2];
   AppendTo[versions, "~(~" <> unshifted <> "<<" <> shift <> ")"];

   (* Try factoring *)
   factorised = Riffle[
      FactorInteger[n]
        /. {a_, 1} :> ToString@a
       /. {a_Integer, b_Integer} :> ToString[a] <> "^" <> ToString[b]
      , "+"] <> "";
   AppendTo[versions, factorised];

   (* Try scientific notation *)
   digits = IntegerDigits[n, 10];
   trimmedDigits = digits /. {x___, d_ /; d > 0, 0 ..} :> {x, d};
   exponent = ToString[Length[digits] - Length[trimmedDigits]];
   base = ToString@FromDigits[trimmedDigits, 10];
   AppendTo[versions, base <> "e" <> exponent];

   (* Don't try hexadecimal notation. It's never shorter for 32-bit uints. *)
   (* Don't try base-36 or base-62, because parsing those requires 12 characters for
      parseint("...") *)

   SortBy[versions, StringLength][[1]]
  ];

mathpack[n_] := 
 Module[{versions, increments},
  increments = Range@9;
  versions = Join[
    optimise[#2] <> "+" <> ToString@# & @@@ ({#, n - #} &) /@ 
      Reverse@increments,
    {optimise@n},
    optimise[#2] <> "-" <> ToString@# & @@@ ({#, n + #} &) /@ 
      increments,
    optimise[#2] <> "*" <> ToString@# & @@@ 
      Cases[({#, n / #} &) /@ increments, {_, _Integer}],
    optimise[#2] <> "/" <> ToString@# & @@@ ({#, n * #} &) /@ 
      increments
    ];
  SortBy[versions, StringLength][[1]]
 ];

La fonction prend un nombre et renvoie la chaîne la plus courte qu'elle trouve. Actuellement, il applique quatre optimisations simples (je pourrais en ajouter plus demain).

Vous pouvez l'appliquer à l'ensemble du fichier (pour mesurer son score) comme suit:

input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]

Notez que certaines de ces optimisations supposent que vous utilisez une Julia 64 bits, de sorte que les littéraux entiers vous donnent un int64par défaut. Sinon, vous déborderez de toute façon pour les entiers supérieurs à 2 31 . En utilisant cette hypothèse, nous pouvons appliquer quelques optimisations dont les étapes intermédiaires sont en fait encore plus grandes que 2 32 .

EDIT: J'ai ajouté l'optimisation suggérée dans les exemples de l'OP pour xor bit à bit deux grands nombres en notation scientifique (en fait, pour tout xor , ou et et ). Notez que l' extension de la xormap, ormapet andmapd'inclure opérandes au - delà de 2 32 pourrait aider à trouver d' autres optimisations, mais il ne fonctionne pas pour les par quelque chose comme un facteur de 10 cas de test donnés et ne fait qu'augmenter le temps de fonctionner.

EDIT: J'ai rasé 16 autres octets, en vérifiant tous n-9, n-8, ..., n+8, n+9si certains d'entre eux peuvent être raccourcis, auquel cas j'ai représenté le nombre en fonction de cela, en ajoutant ou en soustrayant la différence. Il y a quelques cas, où l'un de ces 18 nombres peut être représenté avec 3 caractères ou plus de moins que nlui-même, auquel cas je peux faire des économies supplémentaires. Cela prend environ 30 secondes maintenant pour l'exécuter sur tous les cas de test, mais bien sûr, si quelqu'un "utilise" réellement cette fonction, il ne l'exécutera que sur un seul numéro, donc c'est encore bien moins d'une seconde.

EDIT: Un autre incroyable 4 octets en faisant de même pour la multiplication et la division. 50 secondes maintenant (celles divisées ne prennent pas autant de temps, car je ne vérifie celles-ci que si le nombre est réellement divisible par le facteur d'intérêt).

EDIT: Une autre optimisation qui n'aide pas vraiment avec l'ensemble de test donné. Celui-ci pourrait enregistrer un octet pour des choses comme 2 30 ou 2 31 . Si nous avions des uint64 à la place, il y aurait beaucoup de nombres où cela pourrait être une énorme économie (en gros, chaque fois que la représentation des bits se termine par beaucoup de 1).

EDIT: Suppression du XOR , ou , et Optimisations tout à fait. Je viens de remarquer qu'ils ne fonctionnent même pas dans Julia, car (bien évidemment) la notation scientifique vous donne un flottant où les opérateurs bit par bit ne sont même pas définis. Fait intéressant, une ou plusieurs des nouvelles optimisations semblent intercepter tous les cas qui ont été raccourcis par ces optimisations, car le score n'a pas changé du tout.

Martin Ender
la source
1

J à C (non testé, mais fonctionne dans la plupart des cas, une sorte de réponse de base.)

    f=:(,~ (($&0) @: (8&-) @: (8&|) @: #)) @: #:
    g=:($~ ((,&8) @: (%&8) @: #))@:f
    toCString=:({&a.)@:#.@:g
    toCString 6382179
abc    

Produit un littéral de chaîne qui, s'il est entré en C, représente le nombre (comme mentionné dans l'OP). Ce n'est pas une soumission sérieuse, mais plutôt quelque chose pour renforcer mes compétences en J, que je pensais partager.

Un revêtement alternatif:

toCString=:({&a.) @: #. @: ($~ ((,&8) @: (%&8) @: #))@: (,~ (($&0) @: (8&-) @: (8&|) @: #)) @: #:

Ce que J essaie de faire de cela lorsque vous le saisissez:

{&a.@:#.@:($~ ,&8@:(%&8)@:#)@:(,~ $&0@:(8&-)@:(8&|)@:#)@:#:

Merci beaucoup, J.Par ailleurs, pour ceux qui connaissent le J, visio est très efficace pour créer des fonctions plus complexes:

entrez la description de l'image ici

ɐɔıʇǝɥʇuʎs
la source
Puisque je ne peux pas lire tout cela: qu'est-ce que cela fait si le caractère n'est pas imprimable, ou si le caractère l'est \ , ?ou '?
Martin Ender
@ m.buettner Rien (encore), je dois encore construire quelque chose pour ça
ɐɔıʇǝɥʇuʎs
Au lieu de m&u@:v, utilisez m u vpour enregistrer des caractères précieux et améliorer la lisibilité. En appliquant cela à votre code, nous obtenons f =: [: (,~ 0 $~ 8 - 8 | #) #:et g =: [: ($~ 8 ,~ # % 8:) fet enfin toCString =: a. {~ [: #. g. Tous combinés, nous obtenons a. {~ [: #. [: ($~ 8 ,~ # % 8:) [: (,~ 0 $~ 8 - 8 | #) #:, ce qui est vraiment facile à lire.
FUZxxl