Added char serialization
Added trie (prefix tree)
pull/1/head
a.bozhenov 5 years ago
parent 07283b1d73
commit 2d3cf518fa

@ -0,0 +1,93 @@
using Xunit;
using ZeroLevel.Services.Semantic;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel.UnitTests
{
public class TrieTests
{
[Fact]
public void MainTest()
{
// Arrange
var tree = new Trie();
// Act
tree.Append("коллекция");
tree.Append("коллектор");
tree.Append("колл-центр");
tree.Append("коллектив");
tree.Append("коллегия");
tree.Append("метро");
tree.Append("метрополитен");
tree.Append("метрополит");
// Assert
Assert.True(tree.Key("коллекция") == 1);
Assert.True(tree.Key("коллектор") == 2);
Assert.True(tree.Key("колл-центр") == 3);
Assert.True(tree.Key("коллектив") == 4);
Assert.True(tree.Key("коллегия") == 5);
Assert.True(tree.Key("метро") == 6);
Assert.True(tree.Key("метрополитен") == 7);
Assert.True(tree.Key("метрополит") == 8);
Assert.True(tree.Key("колл") == null);
Assert.True(tree.Key("центр") == null);
Assert.True(tree.Contains("коллекция"));
Assert.True(tree.Contains("коллектор"));
Assert.True(tree.Contains("колл-центр"));
Assert.True(tree.Contains("коллектив"));
Assert.True(tree.Contains("коллегия"));
Assert.True(tree.Contains("метро"));
Assert.True(tree.Contains("метрополитен"));
Assert.True(tree.Contains("метрополит"));
Assert.False(tree.Contains("колл"));
Assert.False(tree.Contains("коллег"));
}
[Fact]
public void SerializationTest()
{
// Arrange
var tree_original = new Trie();
// Act
tree_original.Append("коллекция");
tree_original.Append("коллектор");
tree_original.Append("колл-центр");
tree_original.Append("коллектив");
tree_original.Append("коллегия");
tree_original.Append("метро");
tree_original.Append("метрополитен");
tree_original.Append("метрополит");
var data = MessageSerializer.Serialize(tree_original);
var tree = MessageSerializer.Deserialize<Trie>(data);
// Assert
Assert.True(tree.Key("коллекция") == 1);
Assert.True(tree.Key("коллектор") == 2);
Assert.True(tree.Key("колл-центр") == 3);
Assert.True(tree.Key("коллектив") == 4);
Assert.True(tree.Key("коллегия") == 5);
Assert.True(tree.Key("метро") == 6);
Assert.True(tree.Key("метрополитен") == 7);
Assert.True(tree.Key("метрополит") == 8);
Assert.True(tree.Key("колл") == null);
Assert.True(tree.Key("центр") == null);
Assert.True(tree.Contains("коллекция"));
Assert.True(tree.Contains("коллектор"));
Assert.True(tree.Contains("колл-центр"));
Assert.True(tree.Contains("коллектив"));
Assert.True(tree.Contains("коллегия"));
Assert.True(tree.Contains("метро"));
Assert.True(tree.Contains("метрополитен"));
Assert.True(tree.Contains("метрополит"));
Assert.False(tree.Contains("колл"));
Assert.False(tree.Contains("коллег"));
}
}
}

@ -0,0 +1,189 @@
using System.Collections.Generic;
using ZeroLevel.Services.Serialization;
namespace ZeroLevel.Services.Semantic
{
public class Trie
: IBinarySerializable
{
private class TrieNode
: IBinarySerializable
{
public char Key;
public uint? Value;
public List<TrieNode> Children;
public void Deserialize(IBinaryReader reader)
{
this.Key = reader.ReadChar();
if (reader.ReadBoolean())
{
this.Value = reader.ReadUInt32();
}
else
{
this.Value = null;
}
this.Children = reader.ReadCollection<TrieNode>();
}
public void Serialize(IBinaryWriter writer)
{
writer.WriteChar(this.Key);
if (this.Value.HasValue)
{
writer.WriteBoolean(true);
writer.WriteUInt32(this.Value.Value);
}
else
{
writer.WriteBoolean(false);
}
if (this.Children == null)
{
writer.WriteInt32(0);
}
else
{
writer.WriteCollection<TrieNode>(this.Children);
}
}
internal void Append(string word, ref uint word_index, int index)
{
if (word.Length == index + 1)
{
if (!this.Value.HasValue)
{
this.Value = ++word_index;
}
}
else
{
if (this.Children == null)
{
this.Children = new List<TrieNode>();
}
bool found = false;
for (int i = 0; i < Children.Count; i++)
{
if (Children[i].Key == word[index])
{
Children[i].Append(word, ref word_index, index + 1);
found = true;
}
}
if (!found)
{
var tn = new TrieNode { Key = word[index] };
Children.Add(tn);
tn.Append(word, ref word_index, index + 1);
}
}
}
internal uint? GetKey(string word, int index)
{
if (word.Length == index + 1)
{
return this.Value;
}
else
{
if (this.Children == null)
{
this.Children = new List<TrieNode>();
}
for (int i = 0; i < Children.Count; i++)
{
if (Children[i].Key == word[index])
{
return Children[i].GetKey(word, index + 1);
}
}
}
return null;
}
}
private List<TrieNode> _roots;
private uint _word_index = 0;
public Trie()
{
_roots = new List<TrieNode>();
}
public void Append(string word)
{
if (word.Length == 0) return;
bool found = false;
for (int i = 0; i < _roots.Count; i++)
{
if (_roots[i].Key == word[0])
{
_roots[i].Append(word, ref _word_index, 1);
found = true;
}
}
if (!found)
{
var tn = new TrieNode { Key = word[0] };
_roots.Add(tn);
tn.Append(word, ref _word_index, 1);
}
}
public uint? Key(string word)
{
if (word?.Length == 0) return null;
for (int i = 0; i < _roots.Count; i++)
{
if (_roots[i].Key == word[0])
{
if (word.Length == 1)
{
return _roots[i].Value;
}
else
{
return _roots[i].GetKey(word, 1);
}
}
}
return null;
}
public bool Contains(string word)
{
if (word?.Length == 0) return false;
for (int i = 0; i < _roots.Count; i++)
{
if (_roots[i].Key == word[0])
{
if (word.Length == 1)
{
return _roots[i].Value.HasValue;
}
else
{
return _roots[i].GetKey(word, 1).HasValue;
}
}
}
return false;
}
public void Serialize(IBinaryWriter writer)
{
writer.WriteUInt32(this._word_index);
writer.WriteCollection<TrieNode>(this._roots);
}
public void Deserialize(IBinaryReader reader)
{
this._word_index = reader.ReadUInt32();
this._roots = reader.ReadCollection<TrieNode>();
}
}
}

@ -8,6 +8,8 @@ namespace ZeroLevel.Services.Serialization
{ {
bool ReadBoolean(); bool ReadBoolean();
char ReadChar();
byte ReadByte(); byte ReadByte();
byte[] ReadBytes(); byte[] ReadBytes();

@ -10,6 +10,8 @@ namespace ZeroLevel.Services.Serialization
{ {
void WriteBoolean(bool val); void WriteBoolean(bool val);
void WriteChar(char val);
void WriteByte(byte val); void WriteByte(byte val);
void WriteBytes(byte[] val); void WriteBytes(byte[] val);

@ -55,6 +55,14 @@ namespace ZeroLevel.Services.Serialization
return (byte)_stream.ReadByte(); return (byte)_stream.ReadByte();
} }
public char ReadChar()
{
if (CheckOutOfRange(_stream, 1))
throw new OutOfMemoryException("Array index out of bounds");
var buffer = ReadBuffer(2);
return BitConverter.ToChar(buffer, 0);
}
/// <summary> /// <summary>
/// Reading bytes /// Reading bytes
/// </summary> /// </summary>

@ -45,6 +45,14 @@ namespace ZeroLevel.Services.Serialization
_stream.WriteByte(val); _stream.WriteByte(val);
} }
/// <summary>
/// Write char (2 bytes)
/// </summary>
public void WriteChar(char val)
{
_stream.Write(BitConverter.GetBytes(val), 0, 2);
}
/// <summary> /// <summary>
/// Write array bytes /// Write array bytes
/// </summary> /// </summary>

@ -5,16 +5,17 @@
<Description>Infrastructure layer library</Description> <Description>Infrastructure layer library</Description>
<Authors>ogoun</Authors> <Authors>ogoun</Authors>
<Company>ogoun</Company> <Company>ogoun</Company>
<AssemblyVersion>3.0.0.5</AssemblyVersion> <AssemblyVersion>3.0.0.6</AssemblyVersion>
<PackageReleaseNotes>Fixes</PackageReleaseNotes> <PackageReleaseNotes>Added char serialization
Added prefix tree (Trie)</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/ogoun/Zero/wiki</PackageProjectUrl> <PackageProjectUrl>https://github.com/ogoun/Zero/wiki</PackageProjectUrl>
<Copyright>Copyright Ogoun 2019</Copyright> <Copyright>Copyright Ogoun 2019</Copyright>
<PackageLicenseUrl>https://opensource.org/licenses/MIT</PackageLicenseUrl> <PackageLicenseUrl>https://opensource.org/licenses/MIT</PackageLicenseUrl>
<PackageIconUrl>https://raw.githubusercontent.com/ogoun/Zero/master/zero.png</PackageIconUrl> <PackageIconUrl>https://raw.githubusercontent.com/ogoun/Zero/master/zero.png</PackageIconUrl>
<RepositoryUrl>https://github.com/ogoun/Zero</RepositoryUrl> <RepositoryUrl>https://github.com/ogoun/Zero</RepositoryUrl>
<RepositoryType>GitHub</RepositoryType> <RepositoryType>GitHub</RepositoryType>
<Version>3.0.5</Version> <Version>3.0.6</Version>
<FileVersion>3.0.0.5</FileVersion> <FileVersion>3.0.0.6</FileVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

Loading…
Cancel
Save

Powered by TurnKey Linux.