Код: Mathematica, выход: Юлия, ~ 98,9457% (20177/20392 байта)
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]]
];
Функция берет число и возвращает самую короткую найденную строку . В настоящее время применяется четыре простых оптимизации (я могу добавить еще завтра).
Вы можете применить его ко всему файлу (чтобы измерить его оценку) следующим образом:
input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Обратите внимание, что некоторые из этих оптимизаций предполагают, что вы используете 64-разрядную версию Julia, так что целочисленные литералы дают вам int64 по умолчанию. В противном случае вы будете переполнены для целых чисел больше 2 31 . Используя это предположение, мы можем применить несколько оптимизаций, промежуточные шаги которых на самом деле даже больше 2 32 .
РЕДАКТИРОВАТЬ: я добавил оптимизацию, предложенную в примерах OP, чтобы поразрядно xor два больших числа в научной нотации (фактически, для всех xor , или и и и ). Обратите внимание, что расширение xormap,ormap и andmapвключить операнды за пределами 2 32 могут помочь найти дополнительные оптимизации, но она не работает для данных тестов и только увеличивает время выполнения что - то вроде в 10 разы .
РЕДАКТИРОВАТЬ: я сбрил еще 16 байтов, проверив все на n-9, n-8, ..., n+8, n+9наличие какого-либо из возможности сокращения них , и в этом случае я представлял число на основе этого, добавляя или вычитая разницу. Есть несколько случаев, когда одно из этих 18 чисел может быть представлено на 3 или более символов меньше его nсамого, и в этом случае я могу сделать дополнительную экономию. Теперь требуется около 30 секунд, чтобы запустить его во всех тестовых случаях, но, конечно, если бы кто-то на самом деле «использовал» эту функцию, он бы запустил ее только для одного числа, так что это все еще намного меньше секунды.
РЕДАКТИРОВАТЬ: один невероятный 4 байта, делая то же самое для умножения и деления. 50 секунд (разделенные не занимают так много времени, потому что я проверяю их, только если число на самом деле делится на интересующий фактор).
РЕДАКТИРОВАТЬ: еще одна оптимизация, которая на самом деле не помогает с данным набором тестов. Этот может сохранить байт для таких вещей, как 2 30 или 2 31 . Если бы вместо этого у нас были uint64s, было бы много чисел, где это могло бы принести огромную экономию (в основном, всякий раз, когда представление битов заканчивалось многими единицами).
РЕДАКТИРОВАТЬ: Убрал XOR , или , и оптимизация в целом. Я только заметил, что они даже не работают в Джулии, потому что (совершенно очевидно) научная запись дает вам плавающее число, где побитовые операторы даже не определены. Интересно, что одна или несколько новых оптимизаций, кажется, охватывают все случаи, которые были сокращены этими оптимизациями, потому что оценка не изменилась вообще.