Codice: Mathematica, Output: Julia, ~ 98.9457% (20177/20392 byte)
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 funzione accetta un numero e restituisce la stringa più corta che trova. Attualmente applica quattro semplici ottimizzazioni (potrei aggiungerne altre domani).
Puoi applicarlo all'intero file (per misurarne il punteggio) come segue:
input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Nota che alcune di queste ottimizzazioni presumono che tu sia su una Julia a 64 bit, in modo tale che i valori letterali interi ti danno un int64valore predefinito. Altrimenti, trabocca comunque per numeri interi superiori a 2 31 . Usando questo presupposto possiamo applicare alcune ottimizzazioni i cui passaggi intermedi sono in realtà anche più grandi di 2 32 .
EDIT: ho aggiunto l'ottimizzazione suggerita negli esempi del PO per x bit a bit due grandi numeri in notazione scientifica (in realtà, per tutto di xor , o e e ). Notare che l'estensione di xormap, ormape andmapl'inclusione di operandi oltre 2 32 potrebbe aiutare a trovare ulteriori ottimizzazioni, ma non funziona per i casi di test dati e aumenta il tempo di esecuzione di qualcosa come un fattore 10.
EDIT: mi sono rasato altri 16 byte, controllando tutto n-9, n-8, ..., n+8, n+9se qualcuno di questi può essere abbreviato, nel qual caso ho rappresentato il numero in base a quello, aggiungendo o sottraendo la differenza. Ci sono alcuni casi in cui uno di quei 18 numeri può essere rappresentato con 3 o più caratteri in meno di nse stesso, nel qual caso posso fare qualche risparmio extra. Ora ci vogliono circa 30 secondi per eseguirlo su tutti i casi di test, ma ovviamente, se qualcuno avesse effettivamente "usato" questa funzione, l'avrebbe eseguita solo su un singolo numero, quindi è ancora ben al di sotto di un secondo.
EDIT: un altro incredibile 4 byte facendo lo stesso per moltiplicazione e divisione. 50 secondi ora (quelli divisi non richiedono molto tempo, perché li sto verificando solo se il numero è effettivamente divisibile per il fattore di interesse).
EDIT: un'altra ottimizzazione che in realtà non aiuta con il set di test fornito. Questo potrebbe salvare un byte per cose come 2 30 o 2 31 . Se invece avessimo uint64s, ci sarebbero molti numeri in cui questo potrebbe essere un enorme risparmio (in pratica, ogni volta che la rappresentazione dei bit termina in molti secondi).
EDIT: rimosso xor , o , e ottimizzazioni del tutto. Ho appena notato che non funzionano nemmeno a Julia, perché (ovviamente) la notazione scientifica ti dà un galleggiante dove gli operatori bit-saggio non sono nemmeno definiti. È interessante notare che una o più delle più recenti ottimizzazioni sembrano catturare tutti i casi che sono stati abbreviati da queste ottimizzazioni, perché il punteggio non è cambiato affatto.