mathpack valori letterali numerici


10

prefazione

In una situazione molto calda devi andare ancora oltre con il golf.
(ad esempio in una sfida in cui la tua risposta è lunga 100 caratteri ed è solo imbarazzante non riuscire a farcela 99)
In tal caso, da ora in poi usi l'algoritmo del vincitore di questa sfida :)

obbiettivo

Devi scrivere un programma che prende un uint32 e restituisce il modulo più compresso.

$ mathpack 147456
9<<14
  • Ci saranno più soluzioni per un numero. Scegli quello più corto
  • Se il modulo compresso è più lungo o uguale al numero originale, restituisce il numero originale

regole

  • scrivere in qualsiasi lingua - output in qualsiasi lingua
  • ne sono consapevole e in C 'abc'è 6382179possibile ottenere risultati abbastanza buoni con questa conversione. ma le lingue sono separate in questa sfida, quindi non perdete d'animo
  • è vietato l'uso di variabili esterne. solo operatori e letterali e funzioni matematiche correlate!

punteggio

ecco i casi di test: pastebin.com/0bYPzUhX il
tuo punteggio (percentuale) sarà il rapporto
byte_size_of_your_output / byte_size_of_the_list senza interruzioni di riga .
(devi farlo da solo poiché verificherò i codici migliori per ogni evenienza) i
vincitori saranno scelti in base al punteggio e alla lingua dell'output !

esempi:

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

Bella sfida, ma dovresti aggiungere una regola contro la codifica rigida.
ɐɔıʇǝɥʇuʎs

y-intendi hardcoding 10k casi? anche se sarei felice di ricevere supporto su come affinare questa sfida
bebe

modificato (ancora e ancora ...) per chiarezza. grazie per i consigli.
Bebe,

Non sarebbe anche questo [rosetta-stone]? Inoltre: write in any language - output in any language- le due lingue possono essere diverse, giusto?
ɐɔıʇǝɥʇuʎs

@ ɐɔıʇǝɥʇuʎs [rosetta-stone] riguarda in realtà la tua risoluzione in quante più lingue possibile. E sì alla tua ultima domanda - che è stata modificata in risposta alla mia domanda.
Martin Ender,

Risposte:


1

Codice: Mathematica, Uscita: C, ~ 62.1518% (12674/20392)

Ho pensato di provare anche C a causa di quei divertenti personaggi letterali. Attualmente questa è l'unica cosa che questa risposta sta provando e funziona abbastanza bene.

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

Spero di non aver perso nulla, ma questa risposta assicura di sfuggire a barre rovesciate, virgolette singole e trigrafi. Esiste un codice commentato che utilizza sequenze ottali o altre sequenze di escape per caratteri non stampabili, ma non penso che sia effettivamente necessario, poiché C dovrebbe essere in grado di gestire eventuali byte in caratteri letterali, afaik (correggimi se sbaglio).

Come con l'altro invio, prova questo con

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

(Almeno sul mio sistema) GCC accetterà qualsiasi byte tra virgolette singole tranne 10 ( \n) e 13 ( \r). Un byte zero verrà compilato OK, ma con il messaggio di errore warning: null character(s) preserved in literal.
r3mainer,

@squeamishossifrage Grazie, risolto!
Martin Ender,

3

Codice: Mathematica, Output: Julia, ~ 98.9457% (20177/20392 byte)

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

La funzione accetta un numero e restituisce la stringa più corta che trova. Attualmente applica quattro semplici ottimizzazioni (potrei aggiungerne altre domani).

Puoi applicarlo all'intero file (per misurarne il punteggio) come segue:

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

Nota che alcune di queste ottimizzazioni presumono che tu sia su una Julia a 64 bit, in modo tale che i valori letterali interi ti danno un int64valore predefinito. Altrimenti, trabocca comunque per numeri interi superiori a 2 31 . Usando questo presupposto possiamo applicare alcune ottimizzazioni i cui passaggi intermedi sono in realtà anche più grandi di 2 32 .

EDIT: ho aggiunto l'ottimizzazione suggerita negli esempi del PO per x bit a bit due grandi numeri in notazione scientifica (in realtà, per tutto di xor , o e e ). Notare che l'estensione di xormap, ormape andmapl'inclusione di operandi oltre 2 32 potrebbe aiutare a trovare ulteriori ottimizzazioni, ma non funziona per i casi di test dati e aumenta il tempo di esecuzione di qualcosa come un fattore 10.

EDIT: mi sono rasato altri 16 byte, controllando tutto n-9, n-8, ..., n+8, n+9se qualcuno di questi può essere abbreviato, nel qual caso ho rappresentato il numero in base a quello, aggiungendo o sottraendo la differenza. Ci sono alcuni casi in cui uno di quei 18 numeri può essere rappresentato con 3 o più caratteri in meno di nse stesso, nel qual caso posso fare qualche risparmio extra. Ora ci vogliono circa 30 secondi per eseguirlo su tutti i casi di test, ma ovviamente, se qualcuno avesse effettivamente "usato" questa funzione, l'avrebbe eseguita solo su un singolo numero, quindi è ancora ben al di sotto di un secondo.

EDIT: un altro incredibile 4 byte facendo lo stesso per moltiplicazione e divisione. 50 secondi ora (quelli divisi non richiedono molto tempo, perché li sto verificando solo se il numero è effettivamente divisibile per il fattore di interesse).

EDIT: un'altra ottimizzazione che in realtà non aiuta con il set di test fornito. Questo potrebbe salvare un byte per cose come 2 30 o 2 31 . Se invece avessimo uint64s, ci sarebbero molti numeri in cui questo potrebbe essere un enorme risparmio (in pratica, ogni volta che la rappresentazione dei bit termina in molti secondi).

EDIT: rimosso xor , o , e ottimizzazioni del tutto. Ho appena notato che non funzionano nemmeno a Julia, perché (ovviamente) la notazione scientifica ti dà un galleggiante dove gli operatori bit-saggio non sono nemmeno definiti. È interessante notare che una o più delle più recenti ottimizzazioni sembrano catturare tutti i casi che sono stati abbreviati da queste ottimizzazioni, perché il punteggio non è cambiato affatto.


1

Da J a C (non testato, ma funziona nella maggior parte dei casi, tipo di risposta di base.)

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

Emette una stringa letterale che, se inserita in C, rappresenta il numero (come indicato nell'OP). Questa non è una presentazione seria, ma piuttosto qualcosa per rafforzare le mie abilità di J, che ho pensato di condividere.

One-liner alternativo:

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

Cosa J prova a fare di questo quando lo inserisci:

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

Grazie mille, J. Inoltre, per coloro che conoscono J, visio rock per aver creato funzioni più complesse:

inserisci qui la descrizione dell'immagine


Dal momento che non riesco a leggerlo: cosa fa questo se il personaggio non è stampabile, o se il personaggio lo è \ , ?o '?
Martin Ender,

@ m.buettner Niente (ancora), devo ancora costruire qualcosa per quello
Julıʇǝɥʇuʎs

Invece di m&u@:v, usa m u vper salvare personaggi preziosi e per migliorare la leggibilità. Applicando questo al codice, otteniamo f =: [: (,~ 0 $~ 8 - 8 | #) #:e g =: [: ($~ 8 ,~ # % 8:) fed infine toCString =: a. {~ [: #. g. Tutto sommato otteniamo a. {~ [: #. [: ($~ 8 ,~ # % 8:) [: (,~ 0 $~ 8 - 8 | #) #:, il che è davvero facile da leggere.
FUZxxl,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.