AusPostCode/BaseConversion.cs

71 lines
1.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
namespace AusPostCode {
public static class BaseConversion {
// honestly surprised c# doesn't do this out of the box
private static readonly char[] Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-=".ToCharArray();
// thanks to https://stackoverflow.com/a/35004409
private static readonly Dictionary<char, int> CharacterIndices =
Characters.Select((c, i) => new {Char = c, Index = i}).ToDictionary(c => c.Char, c => c.Index);
public static string ToBase(int num, int numberBase) {
if (numberBase > Characters.Length) {
throw new ArgumentOutOfRangeException(
nameof(numberBase),
$"Base must be below {Characters.Length}"
);
}
if (Math.Abs(num) == 0) {
return num.ToString();
}
var digits = new List<char>();
var negative = num < 0;
while (num > 0) {
digits.Add(Characters[num % numberBase]);
num /= numberBase;
}
digits.Reverse();
return (negative ? "-" : "") + string.Join("", digits);
}
public static int FromBase(string num, int numberBase) {
if (numberBase > Characters.Length) {
throw new ArgumentOutOfRangeException(
nameof(numberBase),
$"Base must be below {Characters.Length}"
);
}
var negative = false;
if (num.StartsWith("-")) {
// it's a negative number
negative = true;
num = num.Substring(1);
}
var x = num.ToCharArray();
var result = 0;
// thanks to https://stackoverflow.com/a/35004409 again for this 0uo
for (var i = 0; i < x.Length; i++) {
result += CharacterIndices[x[i]] * (int) Math.Pow(numberBase, x.Length - i - 1);
}
if (negative) {
result *= -1;
}
return result;
}
}
}