Código: Mathematica, Saída: 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]]
];
A função pega um número e retorna a menor string que encontra. Atualmente, ele aplica quatro otimizações simples (devo acrescentar mais amanhã).
Você pode aplicá-lo ao arquivo inteiro (para medir sua pontuação) da seguinte maneira:
input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Observe que algumas dessas otimizações pressupõem que você esteja em uma Julia de 64 bits, de modo que literais inteiros fornecem um int64por padrão. Caso contrário, você estará transbordando de qualquer maneira para números inteiros maiores que 2 31 . Usando essa suposição, podemos aplicar algumas otimizações cujas etapas intermediárias são realmente ainda maiores que 2 32 .
EDIT: Eu adicionei a otimização sugerida nos exemplos do OP para x ou dois grandes números em notação científica (na verdade, para todos os xor , ou e e ). Nota que o alargamento do xormap, ormape andmappara incluir operando além do 2 32 poderia ajudar a encontrar otimizações adicionais, mas ele não funciona para os casos de teste dadas e só aumenta o tempo de execução por algo como um fator de 10.
EDIT: eu raspei fora outros 16 bytes, verificando tudo n-9, n-8, ..., n+8, n+9para se qualquer um daqueles pode ser reduzido, caso em que eu representava o número com base nisso, adicionando ou subtraindo a diferença. Existem alguns casos em que um desses 18 números pode ser representado com 3 ou mais caracteres a menos que nele próprio; nesse caso, posso fazer uma economia extra. Agora são necessários cerca de 30 segundos para executá-lo em todos os casos de teste, mas é claro que, se alguém realmente "utilizasse" essa função, ele a executaria apenas em um único número, por isso ainda está bem em menos de um segundo.
EDIT: Outros incríveis 4 bytes, fazendo o mesmo para multiplicação e divisão. Agora estão 50 segundos (os divididos não demoram tanto, porque só estou verificando se o número é realmente divisível pelo fator de interesse).
EDIT: Outra otimização que realmente não ajuda com o conjunto de testes fornecido. Este poderia salvar um byte para coisas como 2 30 ou 2 31 . Se tivéssemos uint64s, haveria muitos números em que isso seria uma grande economia (basicamente, sempre que a representação de bits terminar em 1s).
EDIT: Removido o xor , ou , e otimizações por completo. Acabei de notar que eles nem sequer funcionam em Julia, porque (obviamente) a notação científica oferece uma flutuação em que os operadores pouco inteligentes nem são definidos. Curiosamente, uma ou mais das otimizações mais recentes parecem capturar todos os casos que foram encurtados por essas otimizações, porque a pontuação não mudou.