Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0d0d6c2

Browse files
committed
Initial implementation of deferred execution support
1. Add EnumerableExtensions and ReaderExtensions classes and corresponding test cases. 2. Move BuildTable() method to new class TableBuilder.
1 parent 3e1e8c4 commit 0d0d6c2

File tree

7 files changed

+344
-40
lines changed

7 files changed

+344
-40
lines changed

‎src/AlgorithmForce.Searching.Test/AlgorithmForce.Searching.Test.csproj‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
</PropertyGroup>
1212

1313
<ItemGroup>
14-
<Compile Include="..\AlgorithmForce.Searching\Extensions.cs;..\AlgorithmForce.Searching\ListWrapper.cs;..\AlgorithmForce.Searching\StringWrapper.cs" />
14+
<Compile Include="..\AlgorithmForce.Searching\Extensions.cs;" />
15+
<Compile Include="..\AlgorithmForce.Searching\ListWrapper.cs;" />
16+
<Compile Include="..\AlgorithmForce.Searching\StringWrapper.cs;" />
17+
<Compile Include="..\AlgorithmForce.Searching\TableBuilder.cs;" />
18+
<Compile Include="..\AlgorithmForce.Searching\Deferred\EnumerableExtensions.cs;" />
19+
<Compile Include="..\AlgorithmForce.Searching\Deferred\ReaderExtensions.cs;" />
1520
</ItemGroup>
1621

1722
<ItemGroup>
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using System.IO;
2+
using System.Linq;
3+
using Xunit;
4+
using Xunit.Abstractions;
5+
6+
namespace AlgorithmForce.Searching.Test
7+
{
8+
using Deferred;
9+
10+
public class EnumerableExtensionsTest
11+
{
12+
private readonly ITestOutputHelper _output;
13+
14+
public EnumerableExtensionsTest(ITestOutputHelper output)
15+
{
16+
_output = output;
17+
}
18+
19+
[Fact]
20+
public void TestCaseEnumerableIndexOf()
21+
{
22+
var s = Enumerable.Range(0, 100);
23+
var t = new[] { 95, 96, 97, 98, 99 };
24+
25+
Assert.Equal(95, EnumerableExtensions.IndexOf(s, t, 0, null));
26+
}
27+
28+
[Fact]
29+
public void TestCaseEnumerableIndexOfNotFound()
30+
{
31+
var s = Enumerable.Range(0, 100);
32+
var t = new[] { 90, 92, 94, 96, 98 };
33+
34+
Assert.Equal(-1, EnumerableExtensions.IndexOf(s, t, 0, null));
35+
}
36+
37+
[Fact]
38+
public void TestCaseEnumerableIndexOfWithTextReader()
39+
{
40+
var s = string.Concat("Vrogros, the Underlord, is a melee strength hero ",
41+
"whose commanding presence is crucial to his team's success. ",
42+
"With his long-lasting abilities, Underlord is able to ",
43+
"control wide areas of the battlefield during teamfights.");
44+
var t = new[] { 'U', 'n', 'd', 'e', 'r', 'l', 'o', 'r', 'd' };
45+
46+
using (var reader = new StringReader(s))
47+
{
48+
Assert.Equal(s.IndexOf(string.Concat(t)), EnumerableExtensions.IndexOf(reader.AsCharEnumerable(), t, 0, null));
49+
}
50+
}
51+
52+
[Fact]
53+
public void TestCaseEnumerableIndexOfWithTextReaderNotFound()
54+
{
55+
var s = string.Concat("Vrogros, the Underlord, is a melee strength hero ",
56+
"whose commanding presence is crucial to his team's success. ",
57+
"With his long-lasting abilities, Underlord is able to ",
58+
"control wide areas of the battlefield during teamfights.");
59+
var t = new[] { 'S', 'u', 'n', ' ', 'W', 'u', 'k', 'o', 'n', 'g' };
60+
61+
using (var reader = new StringReader(s))
62+
{
63+
Assert.Equal(s.IndexOf(string.Concat(t)), EnumerableExtensions.IndexOf(reader.AsCharEnumerable(), t, 0, null));
64+
}
65+
}
66+
67+
[Fact]
68+
public void TestCaseEnumerableIndexOfWithStartIndex()
69+
{
70+
var s = Enumerable.Range(0, 100);
71+
var t = new[] { 95, 96, 97, 98, 99 };
72+
73+
Assert.Equal(95, EnumerableExtensions.IndexOf(s, t, 20, null));
74+
}
75+
76+
[Fact]
77+
public void TestCaseEnumerableIndexOfWithStartIndexNotFound()
78+
{
79+
var s = Enumerable.Range(0, 100);
80+
var t = new[] { 95, 96, 97, 98, 99 };
81+
82+
Assert.Equal(-1, EnumerableExtensions.IndexOf(s, t, 97, null));
83+
}
84+
85+
[Fact]
86+
public void TestCaseEnumerableIndexOfWithTextReaderAndStartIndex()
87+
{
88+
var s = string.Concat("Vrogros, the Underlord, is a melee strength hero ",
89+
"whose commanding presence is crucial to his team's success. ",
90+
"With his long-lasting abilities, Underlord is able to ",
91+
"control wide areas of the battlefield during teamfights.");
92+
var t = new[] { 'U', 'n', 'd', 'e', 'r', 'l', 'o', 'r', 'd' };
93+
94+
using (var reader = new StringReader(s))
95+
{
96+
Assert.Equal(s.IndexOf(string.Concat(t), 160), EnumerableExtensions.IndexOf(reader.AsCharEnumerable(), t, 160, null));
97+
}
98+
}
99+
100+
[Fact]
101+
public void SkipTest()
102+
{
103+
var s = Enumerable.Range(5, 100);
104+
105+
using (var enumerator = s.GetEnumerator())
106+
{
107+
EnumerableExtensions.Skip(enumerator, 55).MoveNext();
108+
Assert.Equal(s.Skip(55).First(), enumerator.Current);
109+
}
110+
}
111+
}
112+
}

‎src/AlgorithmForce.Searching.Test/TableBuildingTest.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public void TestCase1()
1818
{
1919
var input = "abcabx";
2020
var expected = new[] { -1, 0, 0, 0, 1, 2 };
21-
var actual = Extensions.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
21+
var actual = TableBuilder.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
2222

2323
_output.WriteLine("Expected:\t{0}", string.Join(", ", expected));
2424
_output.WriteLine("Actual:\t{0}", string.Join(", ", actual));
@@ -31,7 +31,7 @@ public void TestCase2()
3131
{
3232
var input = "abcdex";
3333
var expected = new[] { -1, 0, 0, 0, 0, 0 };
34-
var actual = Extensions.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
34+
var actual = TableBuilder.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
3535

3636
_output.WriteLine("Expected:\t{0}", string.Join(", ", expected));
3737
_output.WriteLine("Actual:\t{0}", string.Join(", ", actual));
@@ -44,7 +44,7 @@ public void TestCase3()
4444
{
4545
var input = "ababaaaba";
4646
var expected = new[] { -1, 0, 0, 1, 2, 3, 1, 1, 2 };
47-
var actual = Extensions.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
47+
var actual = TableBuilder.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
4848

4949
_output.WriteLine("Expected:\t{0}", string.Join(", ", expected));
5050
_output.WriteLine("Actual:\t{0}", string.Join(", ", actual));
@@ -57,7 +57,7 @@ public void TestCase4()
5757
{
5858
var input = "aaaaaaaab";
5959
var expected = new[] { -1, 0, 1, 2, 3, 4, 5, 6, 7 };
60-
var actual = Extensions.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
60+
var actual = TableBuilder.BuildTable(input.AsReadOnlyList(), EqualityComparer<char>.Default);
6161

6262
_output.WriteLine("Expected:\t{0}", string.Join(", ", expected));
6363
_output.WriteLine("Actual:\t{0}", string.Join(", ", actual));
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
6+
namespace AlgorithmForce.Searching.Deferred
7+
{
8+
/// <summary>
9+
/// Provides a set of extensions for searching specified collection in an <see cref="IEnumerable{T}" /> instance.
10+
/// </summary>
11+
public static class EnumerableExtensions
12+
{
13+
internal static int IndexOf<T>(this IEnumerable<T> s, IReadOnlyList<T> t, int startIndex, IEqualityComparer<T> comparer)
14+
where T : IEquatable<T>
15+
{
16+
Validate(s, t);
17+
18+
// Follow the behavior of string.IndexOf(string) method.
19+
if (t.Count == 0) return 0;
20+
if (comparer == null) comparer = EqualityComparer<T>.Default;
21+
if (t.Count == 1) return s.IndexOf(t[0], startIndex, comparer);
22+
23+
var table = TableBuilder.BuildTable(t, comparer);
24+
var i = 0;
25+
var offset = startIndex + 1;
26+
27+
using (var enumerator = s.GetEnumerator())
28+
{
29+
while (Skip(enumerator, offset) != null)
30+
{
31+
if (comparer.Equals(t[i], enumerator.Current))
32+
{
33+
if (i == t.Count - 1)
34+
return startIndex;
35+
i++;
36+
}
37+
else
38+
{
39+
if (table[i] > -1)
40+
{
41+
startIndex += i;
42+
offset = i;
43+
i = table[i];
44+
}
45+
else
46+
{
47+
startIndex++;
48+
offset = 1;
49+
i = 0;
50+
}
51+
}
52+
}
53+
}
54+
return -1;
55+
}
56+
57+
internal static int IndexOf<T>(this IEnumerable<T> s, T t, int startIndex, IEqualityComparer<T> comparer)
58+
where T : IEquatable<T>
59+
{
60+
foreach(var e in s)
61+
{
62+
if (comparer.Equals(e, t)) return startIndex;
63+
startIndex++;
64+
}
65+
return -1;
66+
}
67+
68+
internal static IEnumerator<T> Skip<T>(IEnumerator<T> enumerator, int count)
69+
{
70+
var i = 0;
71+
72+
do
73+
{
74+
if (enumerator.MoveNext())
75+
i++;
76+
else
77+
return null;
78+
}
79+
while (i < count);
80+
return enumerator;
81+
}
82+
83+
internal static void Validate<T>(IEnumerable<T> s, IReadOnlyList<T> t)
84+
{
85+
if (s == null) throw new ArgumentNullException(nameof(s));
86+
if (t == null) throw new ArgumentNullException(nameof(t));
87+
}
88+
}
89+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
5+
namespace AlgorithmForce.Searching.Deferred
6+
{
7+
public static class ReaderExtensions
8+
{
9+
public static IEnumerable<char> AsCharEnumerable(this TextReader reader)
10+
{
11+
return EnumerateChars(reader.Read);
12+
}
13+
14+
public static IEnumerable<char> AsCharEnumerable(this BinaryReader reader)
15+
{
16+
return Enumerate(reader.ReadChar);
17+
}
18+
19+
public static IEnumerable<byte> AsByteEnumerable(this BinaryReader reader)
20+
{
21+
return Enumerate(reader.ReadByte);
22+
}
23+
24+
public static IEnumerable<short> AsInt16Enumerable(this BinaryReader reader)
25+
{
26+
return Enumerate(reader.ReadInt16);
27+
}
28+
29+
public static IEnumerable<int> AsInt32Enumerable(this BinaryReader reader)
30+
{
31+
return Enumerate(reader.ReadInt32);
32+
}
33+
34+
public static IEnumerable<long> AsInt64Enumerable(this BinaryReader reader)
35+
{
36+
return Enumerate(reader.ReadInt64);
37+
}
38+
39+
public static IEnumerable<float> AsSingleEnumerable(this BinaryReader reader)
40+
{
41+
return Enumerate(reader.ReadSingle);
42+
}
43+
44+
public static IEnumerable<double> AsDoubleEnumerable(this BinaryReader reader)
45+
{
46+
return Enumerate(reader.ReadDouble);
47+
}
48+
49+
public static IEnumerable<decimal> AsDecimalEnumerable(this BinaryReader reader)
50+
{
51+
return Enumerate(reader.ReadDecimal);
52+
}
53+
54+
internal static IEnumerable<T> Enumerate<T>(Func<T> method)
55+
{
56+
var c = default(T);
57+
58+
while (true)
59+
{
60+
try
61+
{
62+
c = method();
63+
}
64+
catch (EndOfStreamException)
65+
{
66+
yield break;
67+
}
68+
yield return c;
69+
}
70+
}
71+
72+
internal static IEnumerable<char> EnumerateChars(Func<int> method)
73+
{
74+
var c = default(int);
75+
76+
while (c != -1)
77+
{
78+
try
79+
{
80+
c = method();
81+
}
82+
catch (EndOfStreamException)
83+
{
84+
yield break;
85+
}
86+
yield return (char)c;
87+
}
88+
}
89+
}
90+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /