mathpack数値リテラル


10

序文

非常に白熱した状況では、ゴルフをさらに進める必要があります。
(例えば、あなたの答えが100文字で、それを99にすることができなかったことが恥ずかしいチャレンジの
場合)その場合、これからはこのチャレンジの勝者のアルゴリズムを使用します:)

ゴール

uint32を取り、最も圧縮された形式を返すプログラムを作成する必要があります。

$ mathpack 147456
9<<14
  • 数に対して複数のソリューションがあります。一番短いものを選んでください
  • 圧縮されたフォームが元の数以上の場合、元の数を返します

ルール

  • 任意の言語で記述-任意の言語で出力
  • 私はCのそれを知ってる'abc'6382179、あなたは、この変換でかなり良い結果を得ることができます。しかし、この課題では言語が分離されているので、失望しないでください
  • 外部変数の使用は禁止されています。演算子とリテラルと数学関連の関数のみ!

得点

テストケースは次のとおりです。pastebin.com / 0bYPzUhX
スコア(パーセント)は、
byte_size_of_your_output / byte_size_of_the_list 改行なしの比率になります。
(万が一に備えて最高のコードを確認するので、自分でこれを行う必要があります)
勝者はスコアと出力の言語によって選択されます

例:

$ mathpack 147456 | mathpack 97787584 |  mathpack 387420489
            9<<14 |           9e7^9e6 |            pow(9,9)

素敵な挑戦ですが、ハードコーディングに対するルールを追加する必要があります。
ɐɔıʇǝɥʇuʎs

y-10kケースをハードコーディングするという意味ですか?この課題を改善する方法についていくつかのサポートをいただければ
幸いです

明確にするために(何度も繰り返し...)編集した。アドバイスをありがとう。
2014

これも【ロゼッタストーン】じゃないの?また:write in any language - output in any language-2つの言語は異なる場合がありますよね?
ɐɔıʇǝɥʇuʎs

@ɐɔıʇǝɥʇuʎs[rosetta-stone]は実際には、できるだけ多くの言語でそれ解決することです。そして、あなたの後者の質問へのはい-それは私が同じ質問をするのに応えて編集されました。
マーティンエンダー2014

回答:


1

コード:Mathematica、出力:C、〜62.1518%(12674/20392)

これらの面白い文字リテラルのため、Cも試してみると思いました。現在、これはこの答えが試みている唯一のものであり、非常にうまく機能しています。

mathpack[n_] := Module[{versions, charLiteral},
   charLiteral = "'" <> StringReplace[Map[
        Switch[#,
          (*d_ /; d < 32,
          "\\" <> IntegerString[#, 8],*)
          10,
          "\\n",
          13,
          "\\r"
          39,
          "\\'",
          92 ,
          "\\\\",
          _,
          FromCharacterCode@#] &,
        FromDigits[#, 
           2] & /@ (Partition[PadLeft[IntegerDigits[n, 2], 32], 
            8] //. {{0 ..} .., x__} :> {x})
        ] <> "",
      {(*"\\10" -> "\\b",
       "\\11" -> "\\t",
       "\\13" -> "\\v",
       "\\14" -> "\\f",*)
       RegularExpression["(?!<=\?)\?\?(?=[=/()!<>-]|$)"] -> "?\\?"
       }
      ] <> "'";
   versions = {ToString@n, charLiteral};
   SortBy[versions, StringLength][[1]]
 ];

見逃していないことを願っていますが、この回答により、バックスラッシュ、単一引用符、および3文字表記を確実にエスケープできます。印刷できない文字に8進数またはその他のエスケープシーケンスを使用するコメントアウトされたコードがいくつかありますが、Cは文字リテラルの任意のバイトを処理できるはずなので、実際には必要ないと思います(afaik間違っている)。

他の提出と同様に、これをテストします

input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]

(少なくとも私のシステムでは)GCCは、10(\n)と13(\r)を除いて、単一引用符で囲まれたバイトを受け入れます。ゼロバイトはコンパイルできますが、エラーメッセージが表示されますwarning: null character(s) preserved in literal
r3mainer 2014

@squeamishossifrageありがとう、修正しました!
マーティンエンダー2014

3

コード: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]]
 ];

この関数は数値を受け取り、見つかった最も短い文字列を返します。現在、4つの単純な最適化が適用されています(明日はさらに追加する可能性があります)。

次のように、それをファイル全体に適用して(スコアを測定するため)できます。

input = StringSplit[Import["path/to/benchmark.txt"]];
numbers = ToExpression /@ input;
output = mathpack /@ numbers;
N[StringLength[output <> ""]/StringLength[input <> ""]]

これらの最適化の一部は、64ビットのジュリアを使用していることを前提としているため、整数リテラルint64がデフォルトでを与えることに注意してください。それ以外の場合は、2 31より大きい整数がとにかくオーバーフローします。その仮定を使用して、中間ステップが実際には2 32よりもさらに大きいいくつかの最適化を適用できます。

編集:私はOPの例で提案されている最適化をビット表記のxorに 2つの大きな数値の科学的表記法で追加しました(実際には、すべてのxorまたは and および)。を拡張しxormap、2 32を超えるオペランドを含めるormapandmap、追加の最適化を見つけるのに役立つ場合がありますが、特定のテストケースでは機能せず、実行時間を10倍程度増やすだけです。

編集:私はすべてをチェックすることにより、別の16バイト削り取らn-9, n-8, ..., n+8, n+9のいずれかどうかのためにそれらを短くすることができ、その場合、私が追加または差を減算、それに基づいて数値を表しました。それらの18の数値の1 nつがそれ自体よりも3文字以上少ない文字で表すことができる場合がいくつかあります。その場合、さらに節約できます。すべてのテストケースで実行するのに約30秒かかりますが、もちろん、誰かがこの関数を実際に「使用」した場合、1つの数値でのみ実行するので、1秒もかかりません。

編集:乗算と除算について同じことを行うことによる別の信じられないほどの4バイト。今50秒(分割されたものはそれほど長くはかかりません。なぜなら、数が実際に関心のある因子で割り切れる場合にのみこれらをチェックしているためです)。

編集:与えられたテストセットを実際に支援しない別の最適化。これは2 30や2 31のようなもののためにバイトを節約できます。代わりにuint64を使用した場合、これにより大幅な節約ができる数が多くなります(基本的に、ビット表現が1で終了するときはいつでも)。

編集:xororおよび最適化を完全に削除しました。ジュリアでは動作しないことにも気づきました。(明らかに)科学的記法を使用すると、ビット単位の演算子が定義されていない浮動小数点数が得られるためです。興味深いことに、スコアがまったく変化しなかったため、新しい最適化の1つ以上がこれらの最適化によって短縮されたすべてのケースをキャッチしているようです。


1

JからC(テストされていませんが、ほとんどの場合、ベースラインの回答のように機能します。)

    f=:(,~ (($&0) @: (8&-) @: (8&|) @: #)) @: #:
    g=:($~ ((,&8) @: (%&8) @: #))@:f
    toCString=:({&a.)@:#.@:g
    toCString 6382179
abc    

Cで入力された場合に、数値を表す文字列リテラルを出力します(OPで言及)。これは真面目な投稿ではなく、Jスキルを強化するためのものです。

代替ワンライナー:

toCString=:({&a.) @: #. @: ($~ ((,&8) @: (%&8) @: #))@: (,~ (($&0) @: (8&-) @: (8&|) @: #)) @: #:

入力時にJがこれを作ろうとするもの:

{&a.@:#.@:($~ ,&8@:(%&8)@:#)@:(,~ $&0@:(8&-)@:(8&|)@:#)@:#:

たくさんのJさんに感謝します。また、Jについて「知っている」人にとって、visioはより複雑な関数を作成するのに役立ちます。

ここに画像の説明を入力してください


私はそれのいずれかを読み取ることができませんので:文字が印刷不可能である場合、または文字がある場合、これは何をするのか\ ?または'
マーティンエンダー2014

m.buettnerナッシング(まだ)@、私はまだそのため、ビルドに何かを持っている
ɐɔıʇǝɥʇuʎs

の代わりにm&u@:v、を使用m u vして貴重な文字を保存し、読みやすさを向上させます。これをコードに適用するf =: [: (,~ 0 $~ 8 - 8 | #) #:g =: [: ($~ 8 ,~ # % 8:) f、そして最後にtoCString =: a. {~ [: #. g。すべてを組み合わせるとa. {~ [: #. [: ($~ 8 ,~ # % 8:) [: (,~ 0 $~ 8 - 8 | #) #:、非常に読みやすくなります。
FUZxxl 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.