코드 : 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 <> ""]]
이러한 최적화 중 일부는 정수 리터럴 int64이 기본적으로 64 비트 Julia를 사용한다고 가정합니다 . 그렇지 않으면 어쨌든 2 31 보다 큰 정수에 대해 오버플로가 발생합니다 . 이 가정을 사용하여 중간 단계가 실제로 2 32 보다 큰 최적화를 적용 할 수 있습니다 .
편집 : 나는 비트 단위 위해 OP의 예에서 제안 최적화 추가 XOR (모두를위한 실제로, 과학적 표기법으로 두 개의 큰 숫자를 XOR , 또는 및 및 ). 연재합니다 xormap, ormap그리고 것은 andmap2 이상 피연산자 포함하는 32 힘 도움말 추가 최적화를 찾는하지만 주어진 테스트 케이스에 대한 작업을하지 않는 만 10 배처럼 뭔가에 의해 실행 시간을 증가시킨다.
편집 : 나는 16 비트를 축소 n-9, n-8, ..., n+8, n+9하여 그 중 하나 가 단축 될 수 있는지 여부를 모두 확인 했습니다.이 경우 그 차이를 더하거나 빼는 숫자를 나타냅니다. 18 개의 숫자 중 하나가 3 자 이상의 문자로 표현 될 수있는 몇 가지 경우가 있는데 n,이 경우 추가 절약이 가능합니다. 이제 모든 테스트 사례에서 실행하는 데 약 30 초가 걸리지 만, 누군가가이 기능을 실제로 "사용"한 경우에는 단일 숫자로만 실행되므로 여전히 1 초 미만입니다.
편집 : 곱셈과 나눗셈에 대해 동일한 작업을 수행하여 또 다른 놀라운 4 바이트. 이제 50 초 (분할 된 시간은 오래 걸리지 않습니다. 숫자가 실제로 관심 요인으로 나눌 수있는 경우에만 확인하기 때문에).
편집 : 주어진 테스트 세트에 실제로 도움이되지 않는 또 다른 최적화. 이것은 2 30 또는 2 31 과 같은 것을 위해 바이트를 절약 할 수 있습니다. 우리가 대신 uint64를 가지고 있다면, 이것이 크게 절약 될 수있는 많은 숫자가있을 것입니다 (기본적으로 비트 표현이 많은 1로 끝날 때마다).
편집 : 제거 된 XOR를 , 나 , 그리고 모두 최적화. 나는 그것들이 Julia에서도 작동하지 않는다는 것을 알아 차 렸습니다. 왜냐하면 과학적 표기법은 비트 연산자가 정의되지 않은 부동 소수점을 제공하기 때문입니다. 흥미롭게도, 새로운 최적화 중 하나 이상은 점수가 전혀 변하지 않았기 때문에 이러한 최적화로 단축 된 모든 사례를 포착하는 것 같습니다.