namespace WhiteRabbit
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
///
/// Converts strings to vectors containing chars count, based on a source string.
/// E.g. for source string "abc", string "a" is converted to [1, 0, 0], while string "bcb" is converted to [0, 2, 1].
///
internal sealed class VectorsConverter
{
public VectorsConverter(byte[] sourceString)
{
var rawNumberOfOccurrences = sourceString.GroupBy(ch => ch).ToDictionary(group => group.Key, group => group.Count());
this.IntToChar = rawNumberOfOccurrences.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Key).ToArray();
if (this.IntToChar.Length > Vector.Count)
{
throw new ArgumentException($"String should not contain more than {Vector.Count} different characters", nameof(sourceString));
}
this.CharToInt = Enumerable.Range(0, this.IntToChar.Length).ToDictionary(i => this.IntToChar[i], i => i);
}
private Dictionary CharToInt { get; }
private byte[] IntToChar { get; }
public Vector? GetVector(byte[] word)
{
if (word.Any(ch => !this.CharToInt.ContainsKey(ch)))
{
return null;
}
var arr = new byte[Vector.Count];
foreach (var ch in word)
{
arr[this.CharToInt[ch]]++;
}
return new Vector(arr);
}
public string GetString(Vector vector)
{
return new string(Enumerable.Range(0, this.IntToChar.Length).SelectMany(i => Enumerable.Repeat((char)this.IntToChar[i], vector[i])).ToArray());
}
}
}