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

[rosetta-stone]도 아니겠습니까? 또한 : write in any language - output in any language-두 언어가 다를 수 있습니다.
ɐɔıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎs [rosetta-stone]은 실제로 가능한 많은 언어로 그것을 해결하는 것에 관한 입니다. 그리고 당신의 후자의 질문에 그렇습니다-그것은 같은 질문을하는 것에 응답하여 편집되었습니다.
마틴 엔더

답변:


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

나는 아무것도 놓치지 않기를 희망하지만이 대답은 백 슬래시뿐만 아니라 백 슬래시, 작은 따옴표를 피해야합니다. 인쇄 할 수없는 문자에 8 진수 또는 다른 이스케이프 시퀀스를 사용하는 주석 처리 된 코드가 있지만 C가 문자 리터럴의 바이트를 처리 할 수 ​​있기 때문에 실제로 필요하다고 생각하지 않습니다. 잘못되었습니다).

다른 제출물과 마찬가지로

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

(내 시스템에서) GCC는 10 ( \n) 및 13 ( \r)을 제외한 작은 따옴표로 된 바이트를 허용합니다 . 0 바이트는 정상적으로 컴파일되지만 오류 메시지가 표시 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 <> ""]]

이러한 최적화 중 일부는 정수 리터럴 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에서도 작동하지 않는다는 것을 알아 차 렸습니다. 왜냐하면 과학적 표기법은 비트 연산자가 정의되지 않은 부동 소수점을 제공하기 때문입니다. 흥미롭게도, 새로운 최적화 중 하나 이상은 점수가 전혀 변하지 않았기 때문에 이러한 최적화로 단축 된 모든 사례를 포착하는 것 같습니다.


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 rock이 있습니다.

여기에 이미지 설명을 입력하십시오


읽을 수 없으므로 문자를 인쇄 할 수 없거나 문자가 \ , ?또는 '? 인 경우 어떻게해야합니까?
마틴 엔더

@ m.buettner 아무것도 (아직), 나는 여전히 그것을 위해 무언가를
만들어야

대신 m&u@:v, m u v소중한 캐릭터를 저장하고 가독성을 높이기 위해 사용하십시오. 코드에이 적용, 우리가 얻을 수 f =: [: (,~ 0 $~ 8 - 8 | #) #:g =: [: ($~ 8 ,~ # % 8:) f마지막으로와 toCString =: a. {~ [: #. g. 우리가 얻는 모든 결합 a. {~ [: #. [: ($~ 8 ,~ # % 8:) [: (,~ 0 $~ 8 - 8 | #) #:은 정말 읽기 쉽습니다.
FUZxxl
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.