-
Notifications
You must be signed in to change notification settings - Fork 6
/
baseconv.go
73 lines (61 loc) · 1.63 KB
/
baseconv.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package main
import "errors"
import "math"
var (
// Charset is all the alphabets that can be used
Charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// ErrInvalidBase is thrown when the base is <= 0
ErrInvalidBase = errors.New("Invalid base")
)
// Reverse a string
// https://stackoverflow.com/a/10030772/5163807
func Reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
// BaseConvertor represents the data structure required for base conversion
type BaseConvertor struct {
base uint
alphabet []rune
alphabetMap map[rune]uint
}
// NewBaseConvertor instantiates a new BaseConvertor object
func NewBaseConvertor(base uint) (*BaseConvertor, error) {
if base == 0 {
return nil, ErrInvalidBase
}
runes := []rune(Charset[0:base])
runeMap := make(map[rune]uint)
var i uint
for i = 0; i < base; i++ {
runeMap[runes[i]] = i
}
return &BaseConvertor{
base: base,
alphabet: runes,
alphabetMap: runeMap,
}, nil
}
// Encode an unsigned integer to another base
func (e *BaseConvertor) Encode(number uint) string {
remainders := make([]rune, 0)
n := number
for n > 0 {
r := rune(Charset[n%e.base])
remainders = append(remainders, r)
n = n / e.base
}
return Reverse(string(remainders))
}
// Decode string in given base to unsigned integer
func (e *BaseConvertor) Decode(code string) uint {
var value float64
value = 0
for pos, val := range Reverse(code) {
value = value + float64(e.alphabetMap[val])*math.Pow(float64(e.base), float64(pos))
}
return uint(value)
}