Tutta la tua base biiettiva ci appartiene


25

sfondo

Una numerazione b di base biiettiva , dove b è un numero intero positivo, è una notazione posizionale biiettiva che utilizza simboli b con valori associati da 1 a b .

A differenza della sua controparte non biiettiva, nessun simbolo ha un valore di 0 . In questo modo, ogni numero intero non negativo n ha una rappresentazione univoca nella base biiettiva b .

Le numerazioni biiettive popolari includono unaria, base biiettiva 2 (utilizzata nella codifica della lunghezza di esecuzione di bzip2 ) e base biiettiva 26 (utilizzata per numerare le colonne nei fogli di calcolo).

Definizione

In questa sfida, definiamo l'insieme M di simboli come

123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz<=>

e una funzione i da M al numero naturale tale che i ('1') = 1,…, i ('>') = 64 .

Data una base b tra 1 e 64 (entrambi inclusi), definiamo che ogni intero non negativo n corrisponde alla stringa a k … a 0 , costituita da simboli di M , tale che n = b k i (a k ) + … + B 0 i (a 0 ) .

Questa corrispondenza è ben definita e biiettiva. Poiché una somma vuota è definita come 0 , l'intero 0 può essere codificato come una stringa vuota.

Compito

Accetta tre stringhe come input:

  • Una base di input b tra 1 e 64 , codificata come stringa 64 di base biiettiva .

  • Un numero intero non negativo n , codificato come stringa b di base biettiva .

  • Una base di output B compresa tra 1 e 64 , codificata come stringa 64 di base biiettiva .

Dati questi tre input, codificare n come stringa B di base biiettiva .

Casi test

Tutti i casi di test specificano l'ingresso nell'ordine b , n , B .

Input:  "4" "" "8"
Output: ""

Input:  "A" "16" "2"
Output: "1112"

Input:  "2" "122" "A"
Output: "A"

Input:  "3" "31" "1"
Output: "1111111111"

Input:  ">" "Fe" "a"
Output: "RS"

Regole

  • Puoi leggere le tre stringhe in qualsiasi ordine conveniente, in quanto tale, una matrice di stringhe, una rappresentazione delle stringhe della stessa, concatenata o separata da delimitatori a carattere singolo di tua scelta.

  • Se si sceglie di stampare l'output su STDOUT, è possibile stampare solo i simboli e (facoltativamente) una nuova riga finale.

  • Sono consentiti incorporamenti di conversione di base di tutti i tipi.

  • Si applicano le regole standard del .

Risposte:


6

CJam, 43

qA,s"?[a{A<":,:^+:Mf#):B;(bLa{(Bmd)M=\j\+}j

3 byte sradicati con l' aiuto di Dennis :) Provalo online

Spiegazione:

L'input viene preso come bnB, concatenato in una singola stringa.

q           read the input
A,s         make an array of numbers from 0 to 9 and convert to string
"?[a{A<"    push this string, which contains the ends of 3 character ranges:
             uppercase letters: ['A'…'[')
             lowercase letters: ['a'…'{')
             "<=>": ['<'…'?')
             they're in a special order for the symmetric difference below
:,          for each character, make a range of all characters smaller than it
:^          fold/reduce these 6 ranges using symmetric difference
+           concatenate with the digits before
:M          save in M; this is like the M from the statement,
             except it starts with a zero (for matching indexes)
f#          find the indexes in M of all characters from the input string
)           take out the last value from the array
:B;         save it in B and pop it
(           take out the first value
b           use it as a base and convert the remaining array to a number
             this works even if some of the digits are not in the "normal" range
La{…}j      calculate with memoized recursion, using an empty string for value 0
  (         decrement the number
  Bmd       divide by B and get the quotient and remainder
  )         increment the remainder (this is the last digit in bijective base B)
  M=        get the corresponding character from M
  \j        swap with the quotient, and convert the quotient recursively
  \+        swap again and concatenate

Oh, puoi effettivamente utilizzare il normale operatore di conversione base per la prima conversione base? Ora mi sento sciocco per aver usato tutto il codice che ho nella mia soluzione. :) Non mi rendevo conto che avrebbe funzionato con valori che sono al di fuori dell'intervallo della base. Bene, col senno di poi, non c'è una buona ragione per cui non dovrebbe.
Reto Koradi,

@RetoKoradi sì, puoi farlo; un giorno sarà documentato :)
aditsu,

Ti dispiace se cambio la mia soluzione per utilizzare la conversione di base? Di solito cerco di evitare di prendere idee da altre soluzioni. Ma mi dà davvero fastidio lasciare il mio in piedi con un approccio così non ottimale. È molto probabile che la tua soluzione sarà ancora più breve.
Reto Koradi,

@RetoKoradi nessun problema, vai avanti
aditsu

4

Pip, 84 80 78 byte

m:J[,tAZLCAZ"<=>"]p:$+(m@?^b)*(m@?a)**RV,#bs:m@?cWn:px:(mn-(p:n//s-!n%s)*s).xx

Repository GitHub per Pip

Algoritmi adattati dall'articolo di Wikipedia. Ecco la spiegazione per una versione precedente leggermente non golfata:

                 Implicit: initialize a,b,c from cmdline args; t=10;
                 AZ=uppercase alphabet; x=""
m:               Build lookup table m:
 (J,t)             0123456789 (i.e. join(range(10)))...
 .AZ               plus A-Z...
 .LCAZ             plus lowercase a-z...
 ."<=>"            plus <=>
f:{              Define f(a,b) to convert a from bijective base b to decimal:
 $+                Sum of...
  (m@?^a)            list of index of each character of a in m
  *                  multiplied item-wise by 
  b**RV,#a           b to the power of each number in reverse(range(len(a)))
}
t:{              Define t(a,b) to convert a from decimal to bijective base b:
 x:""              Reset x to empty string (not needed if only calling the function once)
 Wa{               While a is not zero:
  p:a//b-!a%b        p = ceil(a/b) - 1 (= a//b if a%b!=0, a//b-1 otherwise)
  x:m@(a-p*b).x      Calculate digit a-p*b, look up the corresponding character in m, and
                     prepend to x
  a:p                p becomes the new a
 }
 x                 Return x
}
(t               Return result of calling t with these arguments:
 (f                Result of calling f with these arguments:
  b                  2nd cmdline arg
  m@?a)              1st cmdline arg's decimal value
 m@?c              3rd cmdline arg's decimal value
)
                 Print (implicit)

Esecuzione di esempio:

dlosc@dlosc:~/golf$ python pip.py bijectivebase.pip ">" "Fe" "a"
RS

4

Ottava, 166 byte

function z=b(o,x,n)
M=['1':'9','A':'Z','a':'z','<=>'];N(M)=1:64;n=N(n);x=polyval(N(x),N(o));z='';while x>0 r=mod(x,n);t=n;if r t=r;end;z=[M(t),z];x=fix(x/n)-(r<1);end

Versione multilinea:

function z=b(o,x,n)
   M=['1':'9','A':'Z','a':'z','<=>'];
   N(M)=1:64;
   n=N(n);
   x=polyval(N(x),N(o));
   z='';
   while x>0
      r=mod(x,n);
      t=n;if r t=r;end;
      z=[M(t),z];
      x=fix(x/n)-(r<1);
   end
%end // implicit - not included above

Invece di creare una mappa per convertire un carattere in un valore di indice, ho appena creato la tabella di ricerca inversa Nper i valori ASCII 1..'z'e l'ho popolata con gli indici con i valori appropriati.

polyval valuta l'equazione

c 1 x k + c 2 x k-1 + ... + c k x 0

utilizzando il valore di input convertito decimale come vettore di coefficienti ce la base originale come x. (Sfortunatamente, Octave base2dec()rifiuta i simboli fuori dalla portata normale.)

Una volta che abbiamo il valore di input nella base 10, il calcolo del valore nella nuova base è semplice.

Test driver:

% script bijecttest.m
a=b('4','','8');
disp(a);
a=b('A','16','2');
disp(a);
a=b('2','122','A');
disp(a);
a=b('3','31','1');
disp(a);
a=b('>','Fe','a');
disp(a);

risultati:

>> bijecttest

1112
A
1111111111
RS
>>

2

Perl, 261 248 229 byte

sub t{$b=0;$b*=$_[1],$b+=ord($1=~y/0-9A-Za-z<=>/\0-A/r)while$_[0]=~/(.)/g;return$b}sub r{$n=$_[0];$n-=$m=($n-1)%$_[1]+1,$d=(chr$m)=~y/\0-A/0-9A-Za-z<=>/r.$d,$n/=$_[1]while$n;print$d}@a=split/,/,<>;r(t(@a[1],t@a[0],64),t@a[2],64)

multilinea, mentre i loop non sono stati modificati:

sub t{ # convert bijective base string to number
    $b=0;
    while($_[0]=~/(.)/g)
        {$b*=$_[1];$b+=ord($1=~y/0-9A-Za-z<=>/\0-A/r)}
    return$b}
sub r{ # convert number to bijective base string
    $n=$_[0];
    while($n)
        {$n-=$m=($n-1)%$_[1]+1;$d=(chr$m)=~y/\0-A/0-9A-Za-z<=>/r.$d;$n/=$_[1]}
    print$d}
@a=split/,/,<>; # parse input
r(t(@a[1],t@a[0],64),t@a[2],64)

tè una funzione per analizzare un numero da una stringa di base biiettiva di una data base. rè una funzione per generare una stringa di base biiettiva di una data base da un numero. I 3 parametri separati da virgola vengono analizzati da stdin e le funzioni vengono chiamate secondo necessità.

La conversione di un numero positivo in una stringa di base biiettiva è simile a una base normale. Tuttavia, dove faresti qualcosa del genere per una base normale:

string s = ""
while(n)
{
    c = (n % base)
    s = (c + '0') + s
    n -= c // not necessary because the division will take care of it
    n /= base 
}

modifichi la mod per dare un intervallo da 1 a base invece di 0 a base - 1:

string s = ""
while(n)
{
    c = (((n-1) % base)+1)
    s = (c + '0') + s
    n -= c  // necessary in the case c = base
    n /= base 
}

2

Python 2, ... 317 307 298 311 byte

Decisamente golfabile. Odio davvero il modo in cui le stringhe non hanno assegnazione di elementi e le liste no find. Guarderò in un modo migliore della mia soluzione rapida che ho ora.

Il mio metodo è convertire l'input in un numero decimale, quindi nella base di output, quindi convertirlo nella base biiettiva.

Modifica : ho scoperto che il mio programma non funzionava durante la conversione in Unario. Costa 13 byte con cui correggere e=F(o)<2, ecc.

Provalo qui

R=range;M="".join(map(chr,R(48,58)+R(65,91)+R(97,123)))+"<=>"
b,s,o=input()
F=M.find
e=F(o)<2
B=lambda n:n and B(n/F(o)-e)+M[n%F(o)+e]or""
n=B(sum(F(s[~j])*F(b)**j for j in R(len(s))))
i=n.find('0')
n=list(n)
while-~i:n=n[:i-1]+[M[F(n[i-1])-1]]+[o]+n[i+1:];n=n["0"==n[0]:];i="".join(n).find('0')
print"".join(n)

1
Sono d'accordo con i tuoi animali domestici Python.
DLosc

@DLosc Grazie per l'aiuto del golf.
mbomb007,

è questo bowling ? : P
Ottimizzatore

Le liste hanno il .index()metodo .. Perché non usarlo invece di trovare? Inoltre, invece di salvare F(b)e F(o)in variabili, le usi solo una volta, quindi inseriscile dove necessario. Infine, 'n'[2::5]è più corto di ''.join(n)(sostituisce gli apostrofi per i backtick).
Kade,

Inoltre, penso che tu stia complicando eccessivamente questo. La conversione da una stringa M base biiettiva b in decimale non dovrebbe richiedere più di 35-40 byte. I decimali a una stringa di base biiettiva B non saranno molto più di questo.
Kade,

2

Python 2, 167 byte

Non ci sono trucchi speciali qui, tranne che per lo [2::5]slicing per ottenere il set di caratteri con un numero di byte inferiore.

x=range;A=`map(chr,x(49,58)+x(65,91)+x(97,123))`[2::5]+'<=>'
r=A.find
b,n,B=input()
B=r(B)+1
d=0;s=''
for c in n:d=d*-~r(b)+r(c)+1
while d:d-=1;s=A[d%B]+s;d/=B
print s

test:

"4","","8"     >>> (empty string)
">","Fe","a"   >>> RS
"3","31","1"   >>> 1111111111
"A","16","2"   >>> 1112
"2","122","A"  >>> A

2

CJam, 73 70 69 55 51 48 byte

L'ultima versione utilizza l'operatore di conversione della base CJam per la conversione dalla base di origine, a cui non avevo pensato fino a quando non ho visto la soluzione di @ aditsu. Applica anche un suggerimento recente di @Dennis per costruire la stringa "digit" ( /codegolf//a/54348/32852 ), così come alcune altre idee condivise in chat.

lA,s'[,_el^+"<=>"+:Lf#Ll#bLl#:K;{(Kmd)L=\}hs-]W%

Il formato di input è il valore, seguito dalla base di origine e destinazione, con ciascuno di essi su una riga separata. Per la stringa vuota, lascia vuota la prima riga. Esempio di input:

122
2
A

Provalo online

Spiegazione:

l       Get and interpret value from input.
A,s     Build the list of 64 "digits". Start with [0..9]
'[,     Build character sequence from \0 to Z.
_el     Lower case copy of the same sequence.
^       Symmetric set difference gives only letters from both sequences.
+       Concatenate with sequence of decimal digits, creating [0..9A..Za..z].
"<=>"   Remaining 4 characters.
+       Concatenate, resulting in full 64 character "digit" string.
:L      ... and store it in variable L for repeated use.
f#      Look up input characters in digit list.
Ll#     Get source base from input, and look up value in digit list.
b       Base conversion. This produces the input value.
Ll#     Get destination base from input, and look up value in digit list.
:K;     Store it in variable K for use in loop, and pop it off stack.
{       Loop for generating output digits.
  (       Decrement to get ceiling minus 1 after division.
  Kmd     Calculate divmod of current value with destination base.
  )       Increment mod to get 1-based value for digit.
  L=      Look up digit character for digit value.
  \       Swap. Digit stays on stack for output, remaining value is processed
          in next loop iteration until it is 0.
}h      End of loop for generating output digits.
s       Final value is 0. Covert it to a string.
-       And subtract it from second but last value. This eliminates the 0,
        as well as the second but last value if it was a \0 character.
]       Wrap digits in array.
W%      Reverse array, to get result from MSB to LSB.

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.