fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6.  
  7. public class Program
  8. {
  9. public static void Main()
  10. {
  11. AnyBaseConverter converter10 = new("0123456789");
  12. AnyBaseConverter converter62 = new("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
  13.  
  14. string year = "9999";
  15. string month = "12";
  16. string day = "31";
  17. string hours = "23";
  18. string minutes = "59";
  19. string seconds = "59";
  20. string milliseconds = "999";
  21.  
  22. string dt0 = $"{year}{month}{day}{hours}{minutes}{seconds}{milliseconds}"; // yyyyMMddHHmmssfff
  23. string sn = "99999999999999999"; // 17 digits of serial number
  24. string sum = "99999"; // 5 digits of transaction sum
  25. string s0 = dt0 + sn + sum;
  26. Console.WriteLine($"initial: {s0.Length} {s0}");
  27.  
  28. string dayOfYear = "365"; // december 31
  29. string timeInSeconds = "86399"; // 23:59:59
  30.  
  31. string dt1 = $"{year}{dayOfYear}{timeInSeconds}{milliseconds}";
  32. string s1 = dt1 + sn + sum;
  33. Console.WriteLine($"base10: {s1.Length} {s1}");
  34.  
  35. byte[] sBytes = converter10.Decode(s1);
  36. string sBytesStr = new StringBuilder()
  37. .AppendJoin(", ", sBytes.Select(b => b.ToString()))
  38. .ToString();
  39. Console.WriteLine($"base256: {sBytes.Length} [{sBytesStr}]");
  40.  
  41. string s2 = converter62.Encode(sBytes);
  42. Console.WriteLine($"base62: {s2.Length} {s2}");
  43. }
  44. }
  45.  
  46.  
  47. public class AnyBaseConverter
  48. {
  49. // Adapted code of Base62 encoding from:
  50. // https://github .com/ghost1face/base62/blob/master/Base62/Base62Converter.cs
  51.  
  52. public AnyBaseConverter(string characterSet)
  53. {
  54. if (characterSet == "")
  55. throw new ArgumentException("Character set cannot be empty", characterSet);
  56. if (characterSet.Length > 256)
  57. throw new ArgumentException("Character set length must not exceed 256 characters", characterSet);
  58. this.Base = characterSet.Length;
  59. this.CharacterSet = characterSet;
  60. this.CharacterIds = characterSet.Select((c, i) => (c, i)).ToDictionary(ci => ci.c, ci => ci.i);
  61. if (this.CharacterIds.Count != this.CharacterSet.Length)
  62. throw new ArgumentException("Characters in character set must not repeat", "characterSet");
  63. }
  64.  
  65. public int Base { get; }
  66. public string CharacterSet { get; }
  67. private readonly Dictionary<char, int> CharacterIds;
  68.  
  69. public string Encode(byte[] bytes)
  70. {
  71. byte[] converted = this.ConvertBase(bytes, 256, this.Base);
  72. StringBuilder builder = new StringBuilder(converted.Length);
  73. foreach (byte c in converted.AsSpan())
  74. builder.Append(this.CharacterSet[c]);
  75. return builder.ToString();
  76. }
  77.  
  78. public byte[] Decode(string value)
  79. {
  80. byte[] arr = new byte[value.Length];
  81. for (int i = 0; i < arr.Length; i++)
  82. {
  83. int characterId = this.CharacterIds.GetValueOrDefault(value[i], -1);
  84. if (characterId == -1) throw new ArgumentException("Character must be in specified set, found: " + value);
  85. arr[i] = (byte)characterId;
  86. }
  87. byte[] converted = ConvertBase(arr, this.Base, 256);
  88. return converted;
  89. }
  90.  
  91. private byte[] ConvertBase(byte[] source, int sourceBase, int targetBase)
  92. {
  93. int count;
  94. List<byte> result = new();
  95. List<byte> quotient = new();
  96. while ((count = source.Length) > 0)
  97. {
  98. quotient.Clear();
  99. int remainder = 0;
  100.  
  101. for (var i = 0; i < count; i++)
  102. {
  103. int accumulator = source[i] + remainder * sourceBase;
  104. byte digit = (byte)((accumulator - (accumulator % targetBase)) / targetBase);
  105. remainder = accumulator % targetBase;
  106. if (quotient.Count > 0 || digit != 0)
  107. quotient.Add(digit);
  108. }
  109.  
  110. result.Add((byte)remainder);
  111. source = quotient.ToArray();
  112. }
  113.  
  114. byte[] output = new byte[result.Count];
  115. for (var (i, j) = (0, result.Count - 1); j >= 0; i++, j--)
  116. output[i] = result[j];
  117.  
  118. return output;
  119. }
  120. }
Success #stdin #stdout 0.06s 26456KB
stdin
Standard input is empty
stdout
initial: 39 999912312359599999999999999999999999999
base10: 37 9999365863999999999999999999999999999
base256: 16 [7, 133, 206, 204, 233, 237, 90, 213, 156, 154, 224, 34, 63, 255, 255, 255]
base62: 21 EC5zRr0FV71hggqe73b0J