Created
January 16, 2018 10:40
-
-
Save mollyporph/4da47df5a93feb2a31eb33496e0cf4ec to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Main() | |
{ | |
var rng = RNGCryptoServiceProvider.Create(); | |
var servers = new int[] { 1, 2, 3, 4, 5}; | |
//generate 10 codes | |
var codes = Enumerable.Range(1, 10).Select(x => { | |
var server = servers.Random(); | |
var bytes = new Byte[3]; | |
rng.GetBytes(bytes); | |
var code = $"{server}{bytes.ToBase52().Replace("=", "")}"; | |
return code; | |
}); | |
codes.ForEach(Console.WriteLine); | |
Console.WriteLine($"All are unique: {codes.Count() == codes.Distinct().Count()}"); | |
//Generates the following | |
/* | |
3KCFM | |
2lMlV | |
3BbZL | |
3MMcB | |
2sBMB | |
4klyoA | |
3ByOp | |
2RHRzB | |
1cMnw | |
2yWrc | |
All are unique: True | |
*/ | |
} | |
public static class Extensions | |
{ | |
static Random r = new Random(); | |
public static int Random(this int[] arr) => arr[r.Next(0, arr.Length - 1)]; | |
public static void ForEach(this IEnumerable<string> strArr, Action<string> act) | |
{ | |
foreach(var str in strArr) | |
{ | |
act(str); | |
} | |
} | |
private static string Base52CodingSpace = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
public static string ToBase52(this string str) => Encoding.UTF8.GetBytes(str).ToBase52(); | |
public static string ToBase52(this byte[] byteArray) | |
{ | |
var sb = new StringBuilder(); | |
var stream = new BitStream(byteArray); | |
byte[] read = new byte[1]; | |
while (true) | |
{ | |
unchecked | |
{ | |
read[0] = 0; | |
int length = stream.Read(read, 0, 6); | |
if (length == 0) | |
break; | |
if (length == 6) | |
{ | |
if ((int)(read[0] >> 3) == 0x1f) //first 5 11111 | |
{ | |
sb.Append(Base52CodingSpace[51]); | |
stream.Seek(-1, SeekOrigin.Current); | |
} | |
else if ((int)(read[0] >> 3) == 0x1e) //first 5 11110 | |
{ | |
sb.Append(Base52CodingSpace[50]); | |
stream.Seek(-1, SeekOrigin.Current); | |
} | |
else | |
{ | |
sb.Append(Base52CodingSpace[(int)(read[0] >> 2)% 52]); | |
} | |
} | |
else | |
{ | |
sb.Append(Base52CodingSpace[(int)(read[0] >> (int)(8 - length)) % 52]); | |
break; | |
} | |
} | |
} | |
return sb.ToString(); | |
} | |
} | |
// Define other methods and classes here | |
public class BitStream : Stream | |
{ | |
private byte[] Source { get; set; } | |
public BitStream(int capacity) | |
{ | |
this.Source = new byte[capacity]; | |
} | |
public BitStream(byte[] source) | |
{ | |
this.Source = source; | |
} | |
public override bool CanRead | |
{ | |
get { return true; } | |
} | |
public override bool CanSeek | |
{ | |
get { return true; } | |
} | |
public override bool CanWrite | |
{ | |
get { return true; } | |
} | |
public override void Flush() | |
{ | |
throw new NotImplementedException(); | |
} | |
public override long Length | |
{ | |
get { return Source.Length * 8; } | |
} | |
public override long Position { get; set; } | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
long tempPos = this.Position; | |
tempPos += offset; | |
int readPosCount = 0, readPosMod = 0; | |
long posCount = tempPos >> 3; | |
int posMod = (int)(tempPos - ((tempPos >> 3) << 3)); | |
while (tempPos < this.Position + offset + count && tempPos < this.Length) | |
{ | |
if ((((int)this.Source[posCount]) & (0x1 << (7 - posMod))) != 0) | |
{ | |
buffer[readPosCount] = (byte)((int)(buffer[readPosCount]) | (0x1 << (7 - readPosMod))); | |
} | |
else | |
{ | |
buffer[readPosCount] = (byte)((int)(buffer[readPosCount]) & (0xffffffff - (0x1 << (7 - readPosMod)))); | |
} | |
tempPos++; | |
if (posMod == 7) | |
{ | |
posMod = 0; | |
posCount++; | |
} | |
else | |
{ | |
posMod++; | |
} | |
if (readPosMod == 7) | |
{ | |
readPosMod = 0; | |
readPosCount++; | |
} | |
else | |
{ | |
readPosMod++; | |
} | |
} | |
int bits = (int)(tempPos - this.Position - offset); | |
this.Position = tempPos; | |
return bits; | |
} | |
public override long Seek(long offset, SeekOrigin origin) | |
{ | |
switch (origin) | |
{ | |
case (SeekOrigin.Begin): | |
{ | |
this.Position = offset; | |
break; | |
} | |
case (SeekOrigin.Current): | |
{ | |
this.Position += offset; | |
break; | |
} | |
case (SeekOrigin.End): | |
{ | |
this.Position = this.Length + offset; | |
break; | |
} | |
} | |
return this.Position; | |
} | |
public override void SetLength(long value) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override void Write(byte[] buffer, int offset, int count) | |
{ | |
long tempPos = this.Position; | |
int readPosCount = offset >> 3, readPosMod = offset - ((offset >> 3) << 3); | |
long posCount = tempPos >> 3; | |
int posMod = (int)(tempPos - ((tempPos >> 3) << 3)); | |
while (tempPos < this.Position + count && tempPos < this.Length) | |
{ | |
if ((((int)buffer[readPosCount]) & (0x1 << (7 - readPosMod))) != 0) | |
{ | |
this.Source[posCount] = (byte)((int)(this.Source[posCount]) | (0x1 << (7 - posMod))); | |
} | |
else | |
{ | |
this.Source[posCount] = (byte)((int)(this.Source[posCount]) & (0xffffffff - (0x1 << (7 - posMod)))); | |
} | |
tempPos++; | |
if (posMod == 7) | |
{ | |
posMod = 0; | |
posCount++; | |
} | |
else | |
{ | |
posMod++; | |
} | |
if (readPosMod == 7) | |
{ | |
readPosMod = 0; | |
readPosCount++; | |
} | |
else | |
{ | |
readPosMod++; | |
} | |
} | |
this.Position = tempPos; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment