mizuneko
7/8/2018 - 12:55 PM

[33進数変換] 誤読しやすいILOを除くA〜Zと数字で採番

[33進数変換] 誤読しやすいILOを除くA〜Zと数字で採番

using System;
using System.Collections.Generic;

namespace AutoNumber
{
    public class AutoNumber
    {
        private static readonly int DecLength = (int)'Z' - (int)'A' + 1 - 3 + 10; // ILOを除くA〜Zと0〜9の33
        private static readonly int OffsetNum0 = (int)'0'; // 48
        private static readonly int OffsetNum1= (int)'A' - 10; // 55

        #region 33進数から10進数
        public static int ToDecimal(string source)
        {
            return ConvertString(0, new Queue<char>(source.ToCharArray()));
        }

        private static int ConvertString(int ret, Queue<char> chars)
        {
            if (chars.Count == 0)
            {
                return ret;
            }
            else
            {
                char c = chars.Dequeue();
                return ConvertString(CalcDecimal(c, chars.Count) + ret, chars);
            }
        }

        private static int CalcDecimal(char c, int times)
        {
            int offsetNum = 0;
            switch (c)
            {
                case char s when s < 'A':
                    offsetNum = OffsetNum0;
                    break;
                case char s when s < 'I':
                    offsetNum = OffsetNum1;
                    break;
                case char s when s < 'L':
                    offsetNum = OffsetNum1 + 1;
                    break;
                case char s when s < 'O':
                    offsetNum = OffsetNum1 + 2;
                    break;
                case char s when s <= 'Z':
                    offsetNum = OffsetNum1 + 3;
                    break;
                default:
                    offsetNum = OffsetNum0;
                    break;
            }
            return (int)Math.Pow(DecLength, times) * ((int)c - offsetNum);
        }
        #endregion

        #region 10進数から33進数
        public static string To33Decimal(int source)
        {
            return ConvertNumber(string.Empty, source);
        }

        public static string GetNext(string source)
        {
            return To33Decimal(ToDecimal(source) + 1);
        }

        private static string ToChar(int n)
        {
            int offsetNum = 0;
            switch (n)
            {
                case int m when m < 10:
                    offsetNum = OffsetNum0;
                    break;
                case int m when m < 18:
                    offsetNum = OffsetNum1;
                    break;
                case int m when m < 20:
                    offsetNum = OffsetNum1 + 1;
                    break;
                case int m when m < 22:
                    offsetNum = OffsetNum1 + 2;
                    break;
                case int m when m < 33:
                    offsetNum = OffsetNum1 + 3;
                    break;
                default:
                    offsetNum = OffsetNum0 - DecLength;
                    break;
            }
            return ((char)(n + offsetNum)).ToString();
        }

        private static string ConvertNumber(string ret, int n)
        {
            if (n == 0)
            {
                return string.IsNullOrEmpty(ret) ? "0" : ret;
            }
            else
            {
                int quo = n / DecLength;
                int rem = n % DecLength;
                if (rem == 0)
                {
                    rem = DecLength;
                }
                return ConvertNumber(ToChar(rem) + ret, quo);
            }
        }
        #endregion
    }
}