Mã: Mathicala, Đầu ra: Julia, ~ 98,9456% (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]]
];
Hàm lấy một số và trả về chuỗi ngắn nhất mà nó tìm thấy. Hiện tại nó áp dụng bốn tối ưu hóa đơn giản (tôi có thể thêm nhiều hơn vào ngày mai).
Bạn có thể áp dụng nó cho toàn bộ tập tin (để đo điểm của nó) như sau:
input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]
Lưu ý rằng một số tối ưu hóa này cho rằng bạn đang sử dụng Julia 64 bit, như vậy theo nghĩa đen là số nguyên cho bạn một int64
mặc định. Mặt khác, dù sao bạn cũng sẽ tràn ra số nguyên lớn hơn 2 31 . Sử dụng giả định đó, chúng ta có thể áp dụng một vài tối ưu hóa mà các bước trung gian thực sự thậm chí còn lớn hơn 2 32 .
EDIT: Tôi thêm vào việc tối ưu hóa gợi ý trong các ví dụ của OP để Bitwise xor hai với số lượng lớn trong ký hiệu khoa học (trên thực tế, đối với tất cả các xor , hay và và ). Lưu ý rằng việc mở rộng xormap
, ormap
và andmap
bao gồm toán hạng vượt 2 32 sức giúp đỡ để tìm optimisations bổ sung, nhưng nó không làm việc cho các trường hợp thử nghiệm nhất định và chỉ tăng thời gian chạy bởi một cái gì đó như một yếu tố của 10.
EDIT: Tôi đã loại bỏ 16 byte khác, bằng cách kiểm tra tất cả n-9, n-8, ..., n+8, n+9
xem có thể rút ngắn bất kỳ cái nào trong số đó không, trong trường hợp đó tôi biểu thị số dựa trên đó, thêm hoặc bớt đi sự khác biệt. Có một vài trường hợp, trong đó một trong số 18 số đó có thể được biểu thị với ít hơn 3 ký tự trở n
lên, trong trường hợp đó tôi có thể tiết kiệm thêm. Bây giờ mất khoảng 30 giây để chạy nó trên tất cả các trường hợp thử nghiệm, nhưng tất nhiên, nếu ai đó thực sự "sử dụng" chức năng này, anh ta chỉ chạy nó trên một số duy nhất, vì vậy nó vẫn hoạt động tốt trong một giây.
EDIT: Một 4 byte đáng kinh ngạc khác bằng cách làm tương tự cho phép nhân và chia. 50 giây bây giờ (những người được chia không mất nhiều thời gian, bởi vì tôi chỉ kiểm tra những điều này nếu con số thực sự chia hết cho yếu tố quan tâm).
EDIT: Một tối ưu hóa khác không thực sự có ích với bộ thử nghiệm đã cho. Điều này có thể tiết kiệm một byte cho những thứ như 2 30 hoặc 2 31 . Nếu chúng ta có uint64 thay vào đó, sẽ có rất nhiều con số trong đó đây có thể là một khoản tiết kiệm rất lớn (về cơ bản, bất cứ khi nào việc biểu diễn bit kết thúc trong rất nhiều 1 giây).
EDIT: Đã xóa xor , hoặc , và tối ưu hóa hoàn toàn. Tôi chỉ nhận thấy rằng họ thậm chí không làm việc ở Julia, bởi vì (khá rõ ràng) ký hiệu khoa học mang đến cho bạn một sự nổi bật trong đó các toán tử bit khôn ngoan thậm chí không được xác định. Thật thú vị, một hoặc nhiều tối ưu hóa mới hơn dường như nắm bắt được tất cả các trường hợp được rút ngắn bởi những tối ưu hóa này, bởi vì điểm số không thay đổi gì cả.