Custom Number Base Converter


30

Die Befugnisse, die in der Lage sein möchten, jede Zahl, die sie haben, schnell in ihre eigene Zahlenbasis umzuwandeln, und zwar in jedem gewünschten Format.

Eingang

Ihr Programm muss 3 Parameter akzeptieren.

  1. Number: Die zu konvertierende Zeichenfolgennummer
  2. InputFormat: Die Basiszeichenfolge, in der sich die Nummer derzeit befindet
  3. OutputFormat: Die Basiszeichenfolge, in die die Zahl konvertiert werden soll.

Ausgabe

Ihr Programm muss Numberdie alte InputFormatin die neue Nummernbasis konvertierenOutputFormat

Beispiele

("1","0123456789","9876543210") = "8"
("985724","9876543210","0123456789ABCDEF") = "37C3"
("FF","0123456789ABCDEF","0123456789") = "255"
("FF","0123456789ABCDEF","01234567") = "377"
("18457184548971248772157", "0123456789","Aa0Bb1Cc2Dd3Ee4Ff5Gg6Hh7Ii8Jj9Kk,Ll.Mm[Nn]Oo@Pp#Qq}Rr{Ss-Tt+Uu=Vv_Ww!Xx%Yy*Zz") = ",sekYFg_fdXb"

Zusätzlich

Der neue Base 77-Test ist keine Requisite, wenn er funktioniert

  1. Wenn Sie in einer Sprache sind, in der Sie zuerst in eine Zahl konvertieren müssen und die innerhalb von 32 Bit gesperrt ist, können Sie sie überspringen.
  2. da es ein zusätzlicher test ist.

Alle Beispiele wurden von PHP 7.2 mit der Erweiterung bcmath unter Verwendung des folgenden Codes generiert (vars mins, aber code formatiert). Es wird wahrscheinlich einen kürzeren Weg geben. Dies ist genau der Weg, den ich für das System gefunden habe, mit dem ich dies tun musste. Es wäre schön zu sehen, ob jemand eine kürzere Version finden könnte.

PHP 7.2 (Bcmath - Erweiterung) 614 Bytes

<?php
function f($a, $b, $c)
{
    $d= str_split($b,1);
    $e= str_split($c,1);
    $f= str_split($a,1);
    $g=strlen($b);
    $h=strlen($c);
    $k=strlen($a);
    $r='';
    if ($c== '0123456789')
    {
        $r=0;
        for ($i = 1;$i <= $k; $i++)
            $retval = bcadd($retval, bcmul(array_search($f[$i-1], $d),bcpow($g,$k-$i)));
        return $r;
    }
    if ($b!= '0123456789')
        $l=f($a, $b, '0123456789');
    else
        $l= $a;
    if ($l<strlen($c))
        return $e[$l];
    while($l!= '0')
    {
        $r= $e[bcmod($l,$h)].$r;
        $l= bcdiv($l,$h,0);
    }
    return $r;
}

Probieren Sie es online

Wertung

Das ist Code Golf; kürzester Code gewinnt. Es gelten Standardlücken.


5
@WindmillCookies Nach beliebigen Zeichen in den Formatzeichenfolgen.
Adám

6
Schöne erste Frage! :-)
Giuseppe


2
Es kann sich lohnen, einen Testfall für eine "einzigartige" Basis hinzuzufügen - z ["zX", "tXdsyqzSDRP02", "brFNC02bc"] => "cb". (oder was auch immer das eigentlich sein sollte, wenn das nicht stimmt)
Fund Monica's Lawsuit

2
Ich würde einen Testfall mit mehr als 36 Zeichen in den Formaten vorschlagen, um jeden zu fangen, der integrierte Funktionen verwendet, die nur bis zur Basis 36 reichen
Jo King,

Antworten:


13

....................... Sie wissen, ich habe gesehen, dass Zadie Base konvertiert wurde, aber die Dokumente auf matl.suever waren nicht klar, dass sie die Zeichen der Base akzeptierten. also habe ich es nicht ausprobiert. Zerreiße mich!
Giuseppe

@ Giuseppe Haha, ich habe mich nur daran erinnert, weil es wie ein Befehl schien, der reif ist, um in ein oder zwei cleveren Hacks (ab) verwendet zu werden. Es ist erstaunlich, dass ich es zum ersten Mal als integrierte Antwort verwende. :)
Sundar - Reinstate Monica

1
Mein erster Gedanke, als ich "Za" sah, war "Lord, Harry Dresden". +1.
Fund Monica's Lawsuit

8

R , 124 Bytes

function(n,s,t,T=L(t),N=(match(!n,!s)-1)%*%L(s)^(L(n):1-1))intToUtf8((!t)[N%/%T^rev(0:log(N,T))%%T+1])
"!"=utf8ToInt
L=nchar

Probieren Sie es online!

Ugh, das war ein Trottel. Ich verwende die typischen Tricks zur Basiskonvertierung für R, aber String-Manipulationen in R sind immer noch chaotisch!


Leider funktioniert das nicht mit n = "0" ... Sie sollten 2 Bytes addieren, log(N+1,T)aber manchmal eine führende Null verursachen, zB wenn Sie 31 von Basis 10 nach Basis 2 konvertieren :(
digEmAll

Um das "Null-Problem" beim Logarithmus ohne führende Nullen zu vermeiden, sehe ich nicht viele andere Lösungen ... Sie könnten dies log(N+!N,T)natürlich !mit der ursprünglichen Bedeutung
tun

@digEmAll die Kommentare des OP sind immer noch etwas unklar, aber es scheint, dass Null nicht unterstützt werden muss.
Giuseppe

Na
ja

7

APL (Dyalog Unicode) , 22 Byte

Anonymes Infix Lambda. Nimmt InputFormatals linkes Argument und OutputFormatals rechtes Argument und fordert zur Eingabe Numbervon stdin auf. Nimmt an ⎕IO( I ndex O rigin) zu sein 0, was auf vielen Systemen Standard ist.

{⍵[(≢⍵)⊥⍣¯1⊢(≢⍺)⊥⍺⍳⎕]}

Probieren Sie es online!

{... } "dfn"; ist linkes Argument, ist rechtes Argument
(Mnemonik: linkes und rechtes Ende des griechischen Alphabets)

⍵[] Indizieren das Ausgabeformat wie folgt:

   Eingabeaufforderung

  ⍺⍳ɩ Indexe dieser Zeichen im Eingabeformat

  ()⊥ Bewerten als in der folgenden Basis:

   ≢⍺ die Länge des Eingabeformats

   ergibt das (trennt sich ¯1von (≢⍺))

  ()⊥⍣¯1 Konvertiere zu folgender Basis:

  ≢⍺ die Länge des Ausgabeformats


7

Japt, 5 Bytes

Nach einer zweiwöchigen Pause können Sie wieder Golf spielen

nV sW

Versuch es


Erläuterung

           :Implicit input of U=Number, V=InputFormat & W=OutputFormat
 nV        :Convert U from base V to decimal
    sW     :Convert to base W string

7

C (gcc), 79 + 46 = 125 Bytes

char*O;l,n;g(n){n/l&&g(n/l);write(1,O+n%l,1);}

Dies muss mit dem kompiliert werden

-Df(s,i,o)=for(n=l=0;n=n*strlen(i)+index(i,s[l])-i,s[++l];);l=strlen(O=o);g(n)

Flagge. (Ja, das ist unglaublich lückenhaft, weshalb ich meine alte Antwort unten fbehalte. ) Dies definiert ein Makro , das die Antwort an STDOUT ausgibt.

Probieren Sie es online!

C (gcc) 133 131 Bytes

char*O;l;g(n){n/l&&g(n/l);write(1,O+n%l,1);}f(s,i,o,n)char*s,*i,*o;{for(n=0,l=strlen(O=o);n=n*strlen(i)+index(i,*s)-i,*++s;);g(n);}

Probieren Sie es online!

Dies definiert eine Funktion f, die die Antwort an STDOUT ausgibt.

char*O;           // declare variable to store output charset
l;                // will be set to length of O
g(n){             // helper function to print the result
  n/l&&g(n/l);    // recursively calls itself if there are more digits
  write(1,        // output to stdout...
   O+n%l,1);      // the byte at (n mod output base) in O
}
f(s,i,o,n)        // main function
char*s,*i,*o;{    // declare string inputs
for(n=0,          // initialize n to 0
l=strlen(O=o);    // assign output charset so we don't have to pass it to g
n=n*strlen(i)     // repeatedly multiply n by input base...
+index(i,*s)-i,   // ... add the index of the digit in input charset...
*++s;);           // and move to the next digit until there's none left
g(n);             // call the helper function on the resulting integer
}

Sie können 2 Bytes speichern , indem Sie putcharstatt writeund die Änderung der Decodierung Schleife leicht: Versuchen Sie es online!
ErikF

Diese indexFunktion ersparte mir ein Byte bei meiner Annäherung, wusste nichts davon;)
Felix Palmen

6

05AB1E , 5 Bytes

ÅβIÅв

Probieren Sie es online!

Dies gilt nicht arbeitet in der alten Version von 05AB1E. Es funktioniert nur mit der neuen Version, dem Elixir Rewrite.

Wie es funktioniert

ÅβIÅв - Volles Programm.
Åβ - Konvertiert von einer benutzerdefinierten Basis in eine Dezimalzahl.
  I - Den dritten Eingang drücken.
   Åв - Konvertiert von einer Dezimalzahl in eine benutzerdefinierte Basis. 

Sie geben an, dass es nur in 05AB1E v2 funktioniert (nicht sicher, ob dies die richtige Versionsnummer ist ..), aber Sie haben trotzdem einen TIO-Link angegeben. Ist die Elixir-Version bereits auf TIO ?! : S Oder funktioniert es für die meisten Testfälle, aber es gibt einige Randfälle, in denen es nur in der neuen Version funktioniert?
Kevin Cruijssen

2
05AB1E v2 ist jetzt bei TIO verfügbar. 05AB1E (Legacy) (in der Titelleiste suchen) ist der Name des alten 05AB1E und 05AB1E ist der Name des neuen. Ich weiß, dass Sie das bereits im Chatroom gesehen haben, aber ich werde es hier als Referenz für andere Benutzer belassen.
Mr. Xcoder


4

Kohle , 5 Bytes

⍘⍘SSS

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

  S     Input the "number"
   S    Input the input format
 ⍘      Convert to number using that format
    S   Input the output format
⍘       Convert to string using that format
        Implicitly print

Die BaseStringFunktion konvertiert abhängig vom Typ des ersten Parameters automatisch zwischen Zahl und Zeichenfolge.


3

Python 2 , 132 129 122 121 Bytes

lambda n,a,b:g(sum(len(a)**i*a.find(j)for i,j in enumerate(n[::-1])),b)
g=lambda n,c:c[n:n+1]or g(n/len(c),c)+c[n%len(c)]

Probieren Sie es online!

Eine anonyme Funktion (danke, Erik the Outgolfer !), Die die ursprüngliche Zahl in eine Ganzzahl zur Basis 10 umwandelt, dann die Ganzzahl und die neue Basiszeichenfolge an die Funktion g () übergibt, die rekursiv in die neue Basis umwandelt. Übergibt nun die Länge des OutputFormat als Parameter an g ().

Aktualisierte g () für einen niedrigeren bytecount. (Danke, Dennis !)

Ersetzte index () durch find (). (Danke, Mr. Xcoder !)

Ungolfed Erklärung:

def f(n, a, b):
    # reverse the string to that the least significant place is leftmost
    # Ex: 985724 -> 427589
    n = n[::-1]
    # get the value of each place, which is its index in the InputFormat, times the base to the power of the place
    # Ex: 427589, 9876543210 -> 5*10^0, 7*10^1, 2*10^2, 4*10^3, 1*10^4, 0*10^5 -> [5,70,200,4000,10000,0]
    n = [a.find(j)*len(a)**i for i,j in enumerate(n)]
    # add all of the values together to bet the value in base 10
    # Ex: (5 + 70 + 200 + 4000 + 10000 + 0) = 14275
    n = sum(n)

    # call the convert to base function
    return g(n, b)

def g(n, c):
    # string slice, which will return an empty string if n:n+1 is not in range
    # an empty string is falsey
    if c[n:n+1]:
        return c[n:n+1]
    else:
        # get current least significant digit
        rem = c[n%len(c)]
        # get the rest of the integer
        div = n/len(c)

        # get the converted string for the rest of the integer, append the calculated least significant digit
        return g(div,c)+rem

1
Sie brauchen nicht f=, anonyme Funktionen sind standardmäßig erlaubt.
Erik der Outgolfer

@Erik the Outgolfer Ist das erlaubt, wenn die anonyme Funktion eine andere Funktion aufruft, oder?
Triggernometrie

Ja, solange Sie die anderen Elemente in Ihr bytecount aufnehmen, dürfen Sie Variablen definieren und Module importieren.
Erik der Outgolfer

1
Die Helferfunktion kann werden g=lambda n,c:c[n:n+1]or g(n/len(c),c)+c[n%len(c)].
Dennis

1
Und der Haupt kann man werden lambda n,a,b:g(sum(len(a)**i*a.find(j)for i,j in enumerate(n[::-1])),b,len(b)).
Mr. Xcoder

2

Jelly , 11 Bytes

iⱮ’ḅL{ṃ⁵ṙ1¤

Probieren Sie es online!

Argumentreihenfolge: InputFormat, Number, OutputFormat. Stellen Sie sicher, dass Sie die Argumente mit korrekter Flucht angeben!


Ich bin mir nicht sicher, ob ich die Reihenfolge der Parameter ausdrücklich angegeben habe ...
Martin Barker

@MartinBarker Die Parameter sind hier in der Reihenfolge 2, 1, 3 aufgeführt. Ich sehe keine Anforderung für eine bestimmte Bestellung in der Herausforderung, und das wäre entmutigend.
Erik der Outgolfer

3
@MartinBarker Pro Tipp: Seien Sie flexibel mit solchen Dingen. Ich finde die Reihenfolge der Eingaben bei der Lösung einer Aufgabe völlig irrelevant, daher schlage ich vor, dass Sie eine willkürlich gewählte Reihenfolge der Parameter
zulassen

Ich wollte es sowieso bleiben lassen, nur um es jetzt zu testen.
Martin Barker

2

Pyth, 21 Bytes

s@LeQjimx@Q1dhQl@Q1le

Testsuite

Erläuterung:
s@LeQjimx@Q1dhQl@Q1le  | Code
s@LeQjimx@Q1dhQl@Q1leQ |  with implicit variables
       m               | Map the function
        x   d          |   index of d in
         @Q1           |    the second string in the input
             hQ        |  over the first string in the input
      i                | Convert the resulting list to int from base
               l@Q1    |  length of the second string in the input
     j                 | Convert the int into a list in base
                   leQ |  length of the last string in the input
 @LeQ                  | Turn each number in the list into the character from the numbers index in the last string in the input
s                      | Concatenate the strings in to one string
                       | Implicit print


2

Perl 6 , 100 97 Bytes

{$^c.comb[(":"~$^b.chars~[$^a.comb>>.&{index $b,$_}].perl).EVAL.polymod($c.chars xx*)].join.flip}

Probieren Sie es online!

Anonymer Codeblock, der 3 Zeichenfolgen in der Reihenfolge, Eingabe, Eingabeformat und Ausgabeformat verwendet und anschließend eine Zeichenfolge zurückgibt

Erläuterung:

{  # Anonymous code block
  $^c.comb[  # Split the output format into characters
           (":"~$^b.chars~[$^a.comb>>.&{index $b,$_}].perl) # The radix syntax in a string e.g ":3[1,2,3]"
           .EVAL  # Eval'ed to produce the base 10 version
           .polymod($c.chars xx*)  # Converted to a list in the output base (reversed)
          ] # Convert the list into indexes of the output format
           .join  # Join the characters to a string
           .flip  # And unreversed
}

2

VBA, 182 Bytes

Eine deklarierte Subroutine, die Eingaben nin der Sprache entgegennimmt yund diese in die Sprache projiziert z.

Sub f(n,y,z)
l=Len(n)
For i=-l To-1
v=v+(InStr(1,y,Mid(n,-i,1))-1)*Len(y)^(l+i)
Next
l=Len(z)
While v
v=v-1
d=v Mod l+1
v=v\l
If d<0Then v=v+1:d=d-l
o=Mid(z,d+1,1)&o
Wend
n=o
End Sub

2

JavaScript (ES6), 90 86 Bytes

Übernimmt die Eingabe als (input_format)(output_format)(number).

s=>d=>g=([c,...n],k=0)=>c?g(n,k*s.length+s.search(c)):k?g(n,k/(l=d.length)|0)+d[k%l]:n

Probieren Sie es online!


Dies ist leider nicht gültig, da Sie das Eingabeformat der Zeichenfolge in ein Array ändern, das nicht über eine CLI-Eingabe erfolgen kann. und muss programmiert werden, muss der String in das Array aufgeteilt werden, damit der erste Parameter gültig ist.
Martin Barker

@MartinBarker Which rule are you referring to? Updated to take 3 strings anyway.
Arnauld

All 3 of the input parameters says "string" as C++ a string can be directly read in and used as an array with javascript it can't be.
Martin Barker

1

C (gcc), 130 129 bytes

v;c(r,i,s,t)char*r,*i,*t;{for(r[1]=v=0;*i;v=v*strlen(s)+index(s,*i++)-s);for(s=strlen(t),i=1;*r=t[v%s],v/=s;memmove(r+1,r,++i));}

Try it online!

-1 byte using index instead of strchr.

This is a simple iterative approach, reusing some variables (and thereby abusing sizeof(int) == sizeof(char *) on TIO) to save bytes.

Input:

  • i input number
  • s source base characters
  • t target base characters

Output:

  • r result number (pointer to a buffer)

Explanation:

v;                                        // value of number
c(r,i,s,t)char*r,*i,*t;{
    for(r[1]=v=0;                         // initialize value and second
                                          // character of output to 0
        *i;                               // loop while not at the end of
                                          // input string
         v=v*strlen(s)+index(s,*i++)-s);  // multiply value with source base
                                          // and add the value of the current
                                          // digit (position in the base string)
    for(s=strlen(t),i=1;                  // initialize s to the length of the
                                          // target base string, length of
                                          // result to 1
        *r=t[v%s],v/=s;                   // add character for current digit
                                          // (value modulo target base) and
                                          // divide value by target base until
                                          // 0 is reached
        memmove(r+1,r,++i));              // move result string one place to
                                          // the right
}

Suggest bcopy(r,r+1,++i) instead of memmove(r+1,r,++i)
ceilingcat

1

Python 2, 97 95 bytes

Thanks to Chas Brown for -2 bytes.

n,s,t=input()
k=0;w='';x=len(t)
for d in n:k=len(s)*k+s.find(d)
while k:w=t[k%x]+w;k/=x
print w

Try it online!


1

Java 10, 131 bytes

A lambda taking the parameters in order as strings and returning a string.

(i,f,o)->{int n=0,b=o.length();var r="";for(var c:i.split(r))n=n*f.length()+f.indexOf(c);for(;n>0;n/=b)r=o.charAt(n%b)+r;return r;}

Try It Online

Ungolfed

(i, f, o) -> {
    int n = 0, b = o.length();
    var r = "";
    for (var c : i.split(r))
        n = n * f.length() + f.indexOf(c);
    for (; n > 0; n /= b)
        r = o.charAt(n % b) + r;
    return r;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.