Write a base X to base Y function

6

1

Create a function 'baseXtoY' which:

converts an integer or string n, which is a base x number (hexadecimal, binary, etc) into a base y number, reliably, including numbers like 10e50 or higher, using the least bytes possible, and using the following constraints:

  • Provide built-in support for bases up to 64 using the following sequence: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ=/
  • Provide support for bases higher than 64 by allowing a different sequence to be used in the input
  • Provide support for multi-byte sequences eg ('aa','bb','cc'...) in cases rally high value bases are needed (could also support unicode instead)
  • You cannot have a base less than 2. Show an error
  • You cannot use any built-in functions that convert base to base for you
  • You need not worry about floating point

parameters should be:

  • n - any number, as a string
  • x - the base of n, integer
  • y - the base of the return value
  • s1 - the sequence the given number's base uses
  • s2 - the sequence the desired base uses
  • b - the bytesize of the digits in s1
  • return value should be a string

example inputs: using '88888' base 10 to 2: baseXtoY('88888',10,2) >>> '10101101100111000'

base 2 to 5: baseXtoY('10101101100111000',2,5) >>> '10321023'

base 5 to 32: baseXtoY('10321023',5,32) >>> '2mpo'

base 32 to 10, using a new sequence, s=the above 64bit sequence, a=the alphabet: baseXtoY('2mpo',32,10,s,a) >>> 'hhhhh'

base 5 to 10, input base uses more than 1 byte per digit: baseXtoY('bbaaddccbbaaccdd',5,10,('aa','bb','cc','dd','ee'),'0123456789',2)) > '88888'`

you do not have to inlude the character length of the testing or input code, just the function(s).

edit: I've given up trying to shorten my Python code lower than the answers, so I'll just show what I have. 585 characters python 2.7

r=range
def b1(n,x,s):
 if n==0:return s[0]
 if x<=1:raise
 l=[];p=n;i=0
 while 1:
  y=x**i;l.append(y)
  if y>p:break
  else:i+=1
 l.reverse();f=[]
 for p in l:h=int(n//p);f.append(h);n-=h*p
 while f[0]==0:f.pop(0)
 q=''
 for p in r(len(f)):q+=s[f[p]]
 return q
def b2(n,x,s,b):
 n=list(str(n));l=[]
 while n:
  a=''
  for p in r(b):a+=n.pop(0)
  l.append(a)
 m=0;q=0
 while l:c=s.index(l.pop());q+=c*(x**m);m+=1
 return q
s=''.join(map(chr,r(48,58)+r(97,123)+r(65,91)))+'=/'
def baseXtoY(n,x=10,y=2,s1=s,s2=s,b=1):return n if x==y else b2(n,x,s1,b)if y==10 else b1(b2(n,x,s1,b),y,s2)

test cases:

32 10 5 >>> 112

112 5 2 >>> 100000

100000 2 10 >>> 32

88888 10 5 0123456789 ('aa', 'bb', 'cc', 'dd', 'ee') 1 >>> bbaaddccbbaaccdd

bbaaddccbbaaccdd 5 10 ('aa', 'bb', 'cc', 'dd', 'ee') 0123456789 2 >>> 88888

Blazer

Posted 2011-12-29T04:08:27.780

Reputation: 1 902

Question was closed 2016-01-12T15:42:33.463

@Mego: This should not be a dupe. Also, regardless of quality, this question was here first (making the newer one a dupe of this one). Personally, I think these questions are dissimilar enough to be left alone.

– Zach Gates – 2016-01-12T15:23:23.673

@ZachGates There is no clear consensus on that post. This much more recent answer of mine has very strong support for closing old challenges as dupes of new ones.

– Martin Ender – 2016-01-12T15:42:05.397

The defaulting makes no sense, and restricts several languages. – Pubby – 2011-12-29T06:05:09.043

Can you elaborate more on what is meant by multi-byte sequences (aa, bb, ..)? – captncraig – 2011-12-29T06:12:46.830

@Pubby: perhaps it could be optional? – Blazer – 2011-12-29T07:13:14.437

@CMP: incase it was impossible for the desired output to be represented by single-byte digits – Blazer – 2011-12-29T07:16:04.043

Also allowing string and int as first argument rules out several languages. May we change this to string-only? – Howard – 2011-12-29T09:04:38.863

@howard: acceptable. you could also write more than one function if you did desire both int and string compatability, but since this is for shortest code, that's not really needed – Blazer – 2011-12-29T09:52:11.330

I don't understand the "more than one byte" bit. We're in the 21st century: ignoring Unicode and equating bytes with characters is prehistoric. – Peter Taylor – 2011-12-29T21:44:40.900

Can we assume that the bases will always be integers? For example, does the program have to be able to handle conversion from base 6 to base 3.14? – Peter Olson – 2011-12-30T07:34:47.357

The second last test case has to be '...aaaccdd' instead of '...aaddcc'. – user unknown – 2011-12-30T18:08:18.640

updated the challenge, multi-byte is no longer needed, bases should be integers – Blazer – 2011-12-31T02:07:37.717

2Please do not change the task after some people already have answered your question. It is fine to clarify some points or define some corner cases but not such a fundamental change as you did. E.g. the removal of multi-byte would mean a complete rewrite of my code since many things were done with this feature in mind (and I think this is also true for user unknown). – Howard – 2011-12-31T08:09:27.130

This is also true for user unknown, yes. If you have a new quizzle in mind, open a new one, and prepare it in the chat or in the sandbox- http://meta.codegolf.stackexchange.com/q/423/373 -meta-thread, to handle questions beforehand. Thank you. Clarify the meaning of questions, but don't change them. So long -1 from me.

– user unknown – 2011-12-31T12:39:43.213

ack.. I'm new to this. Ineed to be more acquainted with the rules. sorry guys. I'll re-update the qustion to fit the answers already given – Blazer – 2011-12-31T21:19:51.043

So I revoke my downvote and turn it into an upvote. – user unknown – 2012-01-01T22:59:58.417

I've added my own attempt.. I'm never going to beat 128 characters :P. I think it's been long enough to choose the winner – Blazer – 2012-01-02T01:56:39.917

Answers

3

GolfScript, 139 130 128 characters

~]{.,5<{[10,""*26,{[97+]}%""*.{32-}%"=/"+++]+}*}2*.,6<{1+}*~:B;.""?!{1/}*:T;.""?!{B/}*:S;:Y;:X;B/0\{S?\X*+}%;""\{.Y%T=@+\Y/.}do;

Most of the characters come from reading and converting parameters and adding the optional ones. The actual conversion is only few chars.

The example inputs are processed as expected:

'88888' 10 2                      # 10101101100111000
'10101101100111000' 2 5           # 10321023
'10321023' 5 32                   # 2mpo
'2mpo' 32 10                      # 88888
'88888' 10 5 '0123456789' ['aa' 'bb' 'cc' 'dd' 'ee'] 1
                                  # bbaaddccbbaaccdd
'bbaaddccbbaaccdd' 5 10 ['aa' 'bb' 'cc' 'dd' 'ee'] '0123456789' 2
                                  # 88888

Edit 1: some minor improvements, esp. coding the digits sequence.

Edit 2: this was an easy one: 0= can be replaced by ! two times in the conversion of the base parameters.

Howard

Posted 2011-12-29T04:08:27.780

Reputation: 23 109

That's one of the longer GolfScript programs... :P – Jwosty – 2014-06-14T21:38:41.223

1

scala: 399 365 chars:

type S=String
type I=Int
def t(l:List[I],b:I):I=l match{
case x::y=>(x%b)+b*t(y,b)
case Nil=>0}
def f(d:I,b:I):List[I]=if(d==0)List()else f(d/b,b):::List(d%b)
val c=(('0'to'9')++('a'to'z')++('A'to'Z')++Seq('=','/')).map(""+_)
def baseXtoY(a:S,g:I,r:I,i:Seq[S]=c,o:Seq[S]=c,w:I=1):S={
f(t(a.sliding(w,w).toList.map(i.indexOf(_)).reverse,g),r).map(o(_)).mkString("")}

testing code:

baseXtoY ("88888", 10, 2) //"10101101100111000"
baseXtoY ("10101101100111000", 2, 5) // "10321023"
baseXtoY ("10321023", 5, 32) // "2mpo"
baseXtoY ("2mpo", 32, 10) // "88888"
baseXtoY ("88888", 10, 5,"0123456789".map ("" + _).toSeq, "aabbccddee".sliding (2, 2).toSeq, 1) // "bbaaddccbbaaccdd"
baseXtoY ("bbaaddccbbaaccdd", 5, 10, "aabbccddee".sliding (2,2).toSeq, "0123456789".map ("" + _).toSeq, 2) // "88888"

result:

scala> baseXtoY ("88888", 10, 2) //"10101101100111000"
res218: S = 10101101100111000

scala> baseXtoY ("10101101100111000", 2, 5) // "10321023"
res219: S = 10321023

scala> baseXtoY ("10321023", 5, 32) // "2mpo"
res220: S = 2mpo

scala> baseXtoY ("2mpo", 32, 10) // "88888"
res221: S = 88888

scala> baseXtoY ("88888", 10, 5,"0123456789".map ("" + _).toSeq, "aabbccddee".sliding (2, 2).toSeq, 1) // "bbaaddccbbaaccdd"
res222: S = bbaaddccbbaaccdd

scala> baseXtoY ("bbaaddccbbaaccdd", 5, 10, "aabbccddee".sliding (2,2).toSeq, "0123456789".map ("" + _).toSeq, 2) // "88888"
res223: S = 88888

and ungolfed:

def todez (li: List[Int], base: Int): Int = li match {
  case x :: xs => (x % base) + base * todez (xs, base) 
  case Nil => 0}
def fromdez (dez: Int, base: Int): List[Int] =
  if (dez == 0) List () else fromdez (dez /base, base) ::: List (dez % base)
def fromTo (li: List[Int], in: Int, out: Int) = fromdez (todez (li.reverse, in), out) 

val coding=(('0'to'9')++('a'to'z')++('A'to'Z')++Seq('=','/')).map(""+ _)

def baseXtoY (in: String, f: Int, t: Int, inCoding: Seq[String] = coding, outCoding: Seq[String] = coding, width: Int=1): String = {
  val is = in.sliding (width, width).toList
  val li = is.map (inCoding.indexOf (_))
  val tmp = fromTo (li, f, t)
  tmp.map(outCoding(_)).mkString ("")
}

user unknown

Posted 2011-12-29T04:08:27.780

Reputation: 4 210

0

Scheme type conversions take care of this. The numerical tower too:

(define (f n b) (number->string n b))

Floating points, exceptions... Everything is taken care of. Just put a number and a base and it gets converted to whichever base.

Samuel Duclos

Posted 2011-12-29T04:08:27.780

Reputation: 136

1This line will only convert a string representation of a base [2, 16] number to a number type. Isn't it a bit far from spec? – Joanis – 2012-01-06T18:00:03.460

I don't see 6 parameters. – user unknown – 2012-01-06T19:05:31.077