числові літерали 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

у-ти маєш на увазі жорстке кодування 10k випадків? хоча я був би радий отримати підтримку щодо вдосконалення цього завдання
Bebe

відредаговано (знову і знову ...) для наочності. дякую за поради.
bebe

Хіба це також не було б [камінь-розетка]? Також: write in any language - output in any language- дві мови можуть бути різними, правда?
ɐɔıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎs [камінь-розетка] насправді полягає в тому, щоб ви вирішили це якомога більше мов. І так, на ваше останнє запитання - це було відредаговано у відповідь на те, що я задаю те саме питання.
Мартін Ендер

Відповіді:


1

Код: Mathematica, Вихід: C, ~ 62,1518% (12674/20392)

Я подумав, що я також спробую спробувати через цих кумедних літералів. Наразі це єдине, що намагається відповісти, і це працює досить добре.

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]]
 ];

Я сподіваюся, що я нічого не пропустив, але ця відповідь гарантує уникнути зворотних нахилів, одинарних лапок, а також триграфів. Існує якийсь коментований код, який використовує восьмеричні або інші послідовності евакуації для недрукувальних символів, але я не думаю, що це насправді необхідно, тому що 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). Нульовий байт складе OK, але з повідомленням про помилку warning: null character(s) preserved in literal.
r3mainer

@squeamishossifrage Дякую, виправлено!
Мартін Ендер

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]]
 ];

Функція бере число і повертає найкоротший рядок, який він знайде. В даний час він застосовує чотири прості оптимізації (я можу додати ще завтра).

Ви можете застосувати його до всього файлу (для вимірювання його балу) наступним чином:

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 , або , і оптимізації взагалі. Я щойно помітив, що вони навіть не працюють в Джулії, тому що (цілком очевидно, що наукові позначення дають вам плаву, де розрядні оператори навіть не визначені. Цікаво, що одна чи кілька нових оптимізацій, схоже, охоплюють усі випадки, які були вкорочені цими оптимізаціями, оскільки оцінка взагалі не змінилася.


1

J до C (неперевірений, але працює в більшості випадків, як вихідна відповідь.)

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

Виводить рядковий літерал, який, якщо він введений в C, представляє число (як зазначено в ОП). Це не серйозне подання, а скоріше щось для зміцнення моїх навичок J, що я думав, що поділюсь.

Альтернативний однолінійний:

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

Що J намагається зробити з цього, коли ви вводите його:

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

Дякую, Дж. Також для тих, хто "знає" про J, скелі visio за створення більш складних функцій:

введіть тут опис зображення


Оскільки я не можу прочитати нічого з цього: що це робити, якщо символ не друкується, або якщо символ є \ , ?чи '?
Мартін Ендер

@ 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.