Code: Mathematica, Ausgabe: Julia, ~ 98,9457% (20177/20392 Bytes)
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]]
];
Die Funktion nimmt eine Zahl und gibt die kürzeste gefundene Zeichenfolge zurück . Derzeit werden vier einfache Optimierungen angewendet (ich könnte morgen weitere hinzufügen).
Sie können es wie folgt auf die gesamte Datei anwenden (um die Punktzahl zu messen):
input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Beachten Sie, dass einige dieser Optimierungen davon ausgehen, dass Sie sich auf einer 64-Bit-Julia befinden, sodass Sie int64durch ganzzahlige Literale standardmäßig eine erhalten. Andernfalls werden Sie bei Ganzzahlen größer als 2 31 ohnehin überlaufen . Unter dieser Annahme können wir einige Optimierungen anwenden, deren Zwischenschritte sogar noch größer als 2 32 sind .
EDIT: Ich habe die Optimierung in den Beispielen des OP vorgeschlagen , um bitweise xor zwei große Zahlen in wissenschaftlicher Notation (eigentlich für alle xor , oder und und ). Beachten Sie, dass die Verlängerung xormap, ormapund andmapdarüber hinaus zwei Operanden umfasst 32 könnte Hilfe bei der Suche zusätzliche Optimierungen, aber es funktioniert nicht für die gegebenen Testfälle und erhöht nur die Laufzeit durch so etwas wie ein Faktor von 10.
EDIT: I off weitere 16 Bytes rasiert, indem alle Überprüfung n-9, n-8, ..., n+8, n+9zum Bestimmen, ob jeder diejenigen kann verkürzt werden, wobei in diesem Fall I dargestellt , die Anzahl auf dem basiert, Addieren oder Subtrahieren der Differenz. Es gibt einige Fälle, in denen eine dieser 18 Zahlen mit 3 oder mehr Zeichen weniger als sich nselbst dargestellt werden kann. In diesem Fall kann ich zusätzliche Einsparungen erzielen. Es dauert jetzt ungefähr 30 Sekunden, um es in allen Testfällen auszuführen, aber wenn jemand diese Funktion tatsächlich "verwendet" hat, würde er sie natürlich nur für eine einzelne Nummer ausführen, sodass sie immer noch weit unter einer Sekunde liegt.
BEARBEITEN: Weitere unglaubliche 4 Bytes, indem Sie dasselbe für die Multiplikation und Division tun. 50 Sekunden jetzt (die geteilten dauern nicht so lange, weil ich diese nur überprüfe, wenn die Zahl tatsächlich durch den interessierenden Faktor teilbar ist).
BEARBEITEN: Eine weitere Optimierung, die mit dem angegebenen Testsatz nicht wirklich hilft. Dieser könnte ein Byte für Dinge wie 2 30 oder 2 31 speichern . Wenn wir stattdessen uint64s hätten, gäbe es viele Zahlen, bei denen dies eine enorme Einsparung bedeuten könnte (im Grunde immer dann, wenn die Bitdarstellung mit vielen 1s endet).
EDIT: Entfernt die xor , oder , und Optimierungen zusammen. Mir ist gerade aufgefallen, dass sie in Julia nicht einmal funktionieren, weil (ganz offensichtlich) die wissenschaftliche Notation Ihnen einen Float gibt, in dem bitweise Operatoren nicht einmal definiert sind. Interessanterweise scheinen eine oder mehrere der neueren Optimierungen alle Fälle zu erfassen, die durch diese Optimierungen verkürzt wurden, da sich die Punktzahl überhaupt nicht geändert hat.