कोड: गणितज्ञ, आउटपुट: जूलिया, ~ 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 से भी बड़े हैं ।
संपादित करें: मैं अनुकूलन ओपी के उदाहरण में सुझाव दिया बिटवाइज़ को जोड़ा गया 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 होते, तो बहुत सारी संख्याएँ होतीं जहाँ यह बहुत बड़ी बचत हो सकती है (मूल रूप से, जब भी बिट प्रतिनिधित्व 1s के बहुत में समाप्त होता है)।
संपादित करें: पूरी तरह से xor , या , और अनुकूलन को हटा दिया। मैंने अभी देखा कि वे जूलिया में भी काम नहीं करते हैं, क्योंकि (स्पष्ट रूप से) वैज्ञानिक संकेतन आपको एक फ्लोट देता है जहां बिट-वार ऑपरेटरों को भी परिभाषित नहीं किया जाता है। दिलचस्प बात यह है कि एक या एक से अधिक नए ऑप्टिमाइज़ेशन उन सभी मामलों को पकड़ने लगते हैं, जिन्हें इन ऑप्टिमाइज़ेशनों द्वारा छोटा किया गया था, क्योंकि स्कोर बिल्कुल भी नहीं बदला था।