Код: Mathematica, Вихід: Julia, ~ 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-бітну Джулію, так що цілі літерали дають вам int64
за замовчуванням. В іншому випадку ви все одно будете переповнені цілими числами більше 2 31 . Використовуючи це припущення, ми можемо застосувати кілька оптимізацій, проміжні кроки яких насправді навіть перевищують 2 32 .
EDIT: Я додав оптимізацію, запропоновану в прикладах ОП, щоб розрядити два великі числа в наукових позначеннях (власне, для всіх xor , або і та ). Зверніть увагу , що розширення xormap
, ormap
і andmap
включити операнди за межами 2 32 можуть допомогти знайти додаткові оптимізації, але вона не працює для даних тестів і тільки збільшує час виконання що - щось на зразок в 10 рази .
EDIT: Я поголив ще 16 байт, перевіривши всі, n-9, n-8, ..., n+8, n+9
чи можна скоротити будь-який із них , і в такому випадку я представляв число на основі цього, додаючи чи віднімаючи різницю. Є кілька випадків, коли одне з цих 18 чисел може бути представлене на 3 і більше символів менше n
самого себе, і в цьому випадку я можу зробити додаткову економію. На це потрібно близько 30 секунд, щоб запустити його у всіх тестових випадках, але, звичайно, якщо хтось насправді "використав" цю функцію, він запустив би її лише на одному номері, тож це все ще добре за секунду.
EDIT: Ще один неймовірний 4 байт, зробивши те саме для множення та ділення. 50 секунд зараз (розділені не займають стільки часу, тому що я перевіряю їх лише, якщо число насправді ділиться на коефіцієнт інтересу).
EDIT: Ще одна оптимізація, яка насправді не допомагає даному тестовому набору. Цей міг би зберегти байт для таких речей, як 2 30 або 2 31 . Якби у нас замість цього були uint64, було б дуже багато цифр, де це могло б бути величезною економією (в основному, щоразу, коли представлення бітів закінчується через багато одиниць).
EDIT: Прибрана XOR , або , і оптимізації взагалі. Я щойно помітив, що вони навіть не працюють в Джулії, тому що (цілком очевидно, що наукові позначення дають вам плаву, де розрядні оператори навіть не визначені. Цікаво, що одна чи кілька нових оптимізацій, схоже, охоплюють усі випадки, які були вкорочені цими оптимізаціями, оскільки оцінка взагалі не змінилася.