package main
import (
"fmt"
"strings"
"math/big"
)
/*
Base‑36 encoding/decoding in Go
-----------------------------------------
Base‑36 digits: 0–9, A–Z
Encoding:
- Convert string → bytes (UTF‑8)
- Convert bytes → big integer (base‑256)
- Convert big integer → base‑36 using big.Int.Text(36)
Decoding:
- Convert base‑36 → big integer
- Convert big integer → bytes (base‑256)
- Convert bytes → original UTF‑8 string
Go's math/big package provides arbitrary‑precision integers,
making the implementation clean and efficient.
*/
const base36Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
// Encode any string into Base‑36
func EncodeToBase36(text string) string {
data := []byte(text)
// Convert bytes → big integer (base‑256)
n := big.NewInt(0)
for _, b := range data {
n.Mul(n, big.NewInt(256))
n.Add(n, big.NewInt(int64(b)))
}
// Convert big integer → Base‑36
return strings.ToUpper(n.Text(36))
}
// Decode Base‑36 back into original string
func DecodeFromBase36(encoded string) string {
encoded = strings.ToUpper(encoded)
// Convert Base‑36 → big integer
n := new(big.Int)
n.SetString(encoded, 36)
// Convert big integer → bytes (base‑256)
var bytes []byte
zero := big.NewInt(0)
twoFiveSix := big.NewInt(256)
for n.Cmp(zero) > 0 {
rem := new(big.Int)
n.DivMod(n, twoFiveSix, rem)
bytes = append(bytes, byte(rem.Int64()))
}
// Reverse to restore original byte order
for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {
bytes[i], bytes[j] = bytes[j], bytes[i]
}
return string(bytes)
}
func main() {
text := "Hello Universe!"
encoded := EncodeToBase36(text)
decoded := DecodeFromBase36(encoded)
fmt.Println("Original:", text)
fmt.Println("Base-36 encoded:", encoded)
fmt.Println("Decoded:", decoded)
}
/*
run:
Original: Hello Universe!
Base-36 encoded: LP4N024HJ1YVBVD84Y8TYQP
Decoded: Hello Universe!
*/