mathpack sayısal değişmez değerleri


10

önsöz

Çok ısınmış bir durumda golf ile daha da ileri gitmelisiniz.
(örneğin, cevabınızın 100 karakter uzunluğunda olduğu ve bunu yapamayacağınız için utanç verici bir
durum söz konusuysa ) 99) Bu durumda, şu andan itibaren kazananın algoritmasını kullanacaksınız :)

hedef

Bir uint32 alan ve en sıkıştırılmış formu döndüren bir program yazmanız gerekir.

$ mathpack 147456
9<<14
  • Bir sayı için birden fazla çözüm olacaktır. En kısa olanı seçin
  • Sıkıştırılmış form orijinal numaradan daha uzun veya ona eşitse, orijinal numarayı döndürün

kurallar

  • herhangi bir dilde yaz - herhangi bir dilde çıktı
  • C 'abc'olduğunu 6382179biliyorum ve bu dönüşüm ile oldukça iyi sonuçlar elde edebilirsiniz. ancak diller bu meydan okumada ayrılmıştır, bu yüzden kalbi kaybetmeyin
  • harici değişkenlerin kullanılması yasaktır. sadece operatörler, değişmez değerler ve matematikle ilgili işlevler!

puanlama

İşte test senaryoları : pastebin.com/0bYPzUhX
Puanınız (yüzde)
byte_size_of_your_output / byte_size_of_the_list satır kesmeleri oranı olacaktır .
(sadece durumda en iyi kodları doğrulayacağım gibi bunu kendiniz yapmak zorundasınız)
kazananlar puan ve çıktı dili ile seçilecek !

örnekler:

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

Güzel bir meydan okuma, ancak sert kodlamaya karşı bir kural eklemelisiniz.
Julıʇǝɥʇuʎs

y-10k vakaları hardcoding mi demek istiyorsun? Her ne kadar ben bu meydan okuma rafine bazı destek almak için mutlu olurdu
bebe

anlaşılır olması için (tekrar tekrar ...) düzenlenmiştir. tavsiyeler için teşekkürler.
bebe

Bu da [rosetta-stone] olmaz mı? Ayrıca: write in any language - output in any language- iki dil farklı olabilir, değil mi?
Julıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎs [rosetta taşı] hakkında aslında sen mümkün olduğunca çok dilde olduğu gibi bunu çözme. Ve son sorunuza evet - bu aynı soruyu soran yanıt olarak düzenlendi.
Martin Ender

Yanıtlar:


1

Kod: Mathematica, Çıktı: C, ~ 62.1518% (12674/20392)

Bu komik karakter değişmezleri nedeniyle C'yi de deneyeceğim diye düşündüm. Şu anda bu cevabın denediği tek şey bu ve oldukça iyi çalışıyor.

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

Umarım hiçbir şeyi kaçırmadım, ancak bu cevap ters eğik çizgilerden, tek tırnak işaretlerinden ve trigrafilerden kaçmayı sağlar. Yazdırılamayan karakterler için sekizli veya diğer kaçış dizilerini kullanan bazı yorumlanmış kodlar var, ancak bunun aslında gerekli olduğunu düşünmüyorum, çünkü C karakter değişmezlerinde, afaikteki herhangi bir baytla başa çıkabilmelidir (lütfen eğer yanılıyorum).

Diğer gönderilerde olduğu gibi bunu

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

(En azından benim sistemimde) GCC, 10 ( \n) ve 13 ( \r) dışında tek tırnak içinde herhangi bir baytı kabul edecektir . Sıfır bayt, Tamam, ancak hata iletisiyle derlenir warning: null character(s) preserved in literal.
r3mainer

@squeamishossifrage Teşekkürler, düzeltildi!
Martin Ender

3

Kod: Mathematica, Çıktı: Julia, ~ 98.9457% (20177/20392 bytes)

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

İşlev bir sayı alır ve bulduğu en kısa dizeyi döndürür . Şu anda dört basit optimizasyon uygulanmaktadır (yarın daha fazlasını ekleyebilirim).

Dosyayı (puanını ölçmek için) aşağıdaki gibi tüm dosyaya uygulayabilirsiniz:

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

Bu optimizasyonların bazılarının, tamsayı değişmez değerleri size int64varsayılan olarak bir değer verecek şekilde 64 bit Julia'da olduğunuzu varsaydığını unutmayın. Aksi takdirde, 2 31'den büyük tamsayılar için yine de taşacaksınız . Bu varsayımı kullanarak, ara adımları aslında 2 32'den bile büyük olan birkaç optimizasyon uygulayabiliriz .

DÜZENLEME: Ben Bitsel için OP'ın örneklerde önerilen optimizasyon eklendi xor (tümü için aslında bilimsel gösterimde iki büyük sayılar xor , ya ve ve ). Uzanan o Not xormap, ormapve andmap2 ötesine işlenen içerecek şekilde 32 kudreti yardım ek optimizasyon bulmakta, ancak verilen test durumları için çalışmalarını yapmaz ve sadece 10 faktör gibi bir şey tarafından işletilen süreyi artırır.

DÜZENLEME: Bunlarınn-9, n-8, ..., n+8, n+9 herhangi birinin kısaltıp kısaltılamayacağını kontrol ederek 16 bayt daha tıraş ettim , bu durumda sayıyı buna dayalı olarak temsil ettim, farkı ekledim veya çıkardım. Bu 18 rakamdan birinin kendisinden 3 veya daha az karakterle temsil edilebileceği birkaç durum vardır, bu durumda bazı ekstra tasarruflar yapabilirim. Şimdi tüm test senaryolarında çalıştırmak yaklaşık 30 saniye sürüyor, ancak elbette, birisi bu işlevi gerçekten "kullandıysa", sadece tek bir sayı üzerinde çalıştırır, bu yüzden hala bir saniyenin altında.n

EDIT: Çarpma ve bölme için aynı yaparak başka bir inanılmaz 4 bayt. Şimdi 50 saniye (bölünmüş olanlar çok uzun sürmüyor, çünkü bunları sadece sayı gerçekten ilgi faktörüne bölünebiliyorsa kontrol ediyorum).

EDIT: Verilen test seti ile gerçekten yardımcı olmayan başka bir optimizasyon. Bu, 2 30 veya 2 31 gibi şeyler için bir bayt kaydedebilir . Bunun yerine uint64'lerimiz olsaydı, bunun büyük bir tasarruf olabileceği çok sayıda sayı olurdu (temel olarak, bit temsili 1'lerde sona erdiğinde).

DÜZENLEME: Kaldırılan xor , ya , ve tamamen optimizasyon. Julia'da bile çalışmadıklarını fark ettim, çünkü (oldukça açık bir şekilde) bilimsel gösterim size biraz akıllı operatörlerin bile tanımlanmadığı bir şamandıra veriyor. İlginç bir şekilde, yeni optimizasyonlardan bir veya daha fazlası bu optimizasyonlarla kısaltılmış tüm vakaları yakalar gibi görünüyor, çünkü puan hiç değişmedi.


1

J'den C'ye (denenmemiş, ancak çoğu durumda çalışır, bir tür temel cevap.)

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

C'ye girilirse, sayıyı (OP'de belirtildiği gibi) temsil eden bir dize hazır bilgisi verir. Bu ciddi bir sunum değil, J becerilerimi güçlendirecek bir şey, paylaşacağımı düşündüm.

Alternatif tek astarlı:

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

Girdiğinizde J bu konuda ne yapmaya çalışır:

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

Çok teşekkürler, J. Ayrıca, J hakkında 'bilinenler' için, daha karmaşık fonksiyonlar yaratmak için visio kayalar:

resim açıklamasını buraya girin


Ben bunun okuyamadığı için: ya bu karakter olmayan basılabilir, ya karakter ise eğer işe yarar \ , ?ya '?
Martin Ender

@ m.buettner Hiçbir şey (henüz), hala bunun için bir şeyler inşa
etmem gerekiyor

Yerine m&u@:v, kullanmak m u vdeğerli karakterleri kaydetmek ve okunabilirliği artırmak için. Kodunuza bu uygulama, elde ederiz f =: [: (,~ 0 $~ 8 - 8 | #) #:ve g =: [: ($~ 8 ,~ # % 8:) fson olarak ve toCString =: a. {~ [: #. g. Hepsi bir araya geldi a. {~ [: #. [: ($~ 8 ,~ # % 8:) [: (,~ 0 $~ 8 - 8 | #) #:, okumak gerçekten kolay.
FUZxxl
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.