Skip to content

Commit

Permalink
IsInterleaved
Browse files Browse the repository at this point in the history
  • Loading branch information
ZacharyPatten committed Oct 24, 2020
1 parent 4b69741 commit 4b53538
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 0 deletions.
21 changes: 21 additions & 0 deletions Examples/BasicsAndExtensions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,27 @@ void ShuffleDataSet()
}
#endregion

#region IsInterleaved
{
Console.WriteLine(" Is Interleaved ----------------------");
Console.WriteLine();

string abc = "abc";
string xyz = "xyz";
string axbycz = "axbycz";
Console.WriteLine($@" IsInterleavedRecursive(""{abc}"", ""{xyz}"", ""{axbycz}""): {IsInterleavedRecursive(abc, xyz, axbycz)}");
Console.WriteLine($@" IsInterleavedIterative(""{abc}"", ""{xyz}"", ""{axbycz}""): {IsInterleavedIterative(abc, xyz, axbycz)}");

string a = "a";
string b = "b";
string c = "c";
Console.WriteLine($@" IsInterleavedRecursive(""{a}"", ""{b}"", ""{c}""): {IsInterleavedRecursive(a, b, c)}");
Console.WriteLine($@" IsInterleavedIterative(""{a}"", ""{b}"", ""{c}""): {IsInterleavedIterative(a, b, c)}");

Console.WriteLine();
}
#endregion

#region Hamming Distance
{
Console.WriteLine(" HammingDistance----------------");
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,10 @@ Force<decimal>.TryParse(".1234 Kilograms * Meters / Seconds / Seconds",
// Note: supports System.Span<T> and any (non ref struct) int-indexed type
IsPalindrome<...>(...);
// Note: supports System.ReadOnlySpan<T>
IsInterleavedRecursive<...>(...);
IsInterleavedIterative<...>(...);
// Note: supports System.Span<T> and any (non ref struct) int-indexed type
SortShuffle<T>(...);
SortBubble<T>(...);
Expand Down
153 changes: 153 additions & 0 deletions Sources/Towel/Statics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5822,6 +5822,159 @@ public static bool IsPalindrome<T, Equate>(ReadOnlySpan<T> span, Equate equate =

#endregion

#region IsInterleaved

#region XML

#pragma warning disable CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name
#pragma warning disable CS1572 // XML comment has a param tag, but there is no parameter by that name
#pragma warning disable CS1734 // XML comment has a paramref tag, but there is no parameter by that name

/// <typeparam name="T">The element type of the sequences.</typeparam>
/// <param name="a">The first sequence to determine if <paramref name="c"/> is interleaved of.</param>
/// <param name="b">The second sequence to determine if <paramref name="c"/> is interleaved of.</param>
/// <param name="c">The sequence to determine if it is interleaved from <paramref name="a"/> and <paramref name="b"/>.</param>
/// <param name="equate">The function for equating <typeparamref name="T"/> values.</param>
/// <returns>True if <paramref name="c"/> is interleaved of <paramref name="a"/> and <paramref name="b"/> or False if not.</returns>
/// <example>
/// <code>
/// IsInterleaved("abc", "xyz", "axbycz") // True
/// IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved)
/// IsInterleaved("abc", "xyz", "012345") // False
/// </code>
/// </example>
internal static void IsInterleaved_XML() => throw new DocumentationMethodException();

/// <summary>
/// <para>
/// Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
/// meaning that <paramref name="c"/> it contains all elements of <paramref name="a"/> and <paramref name="b"/>
/// while retaining the order of the respective elements. Uses a recursive algorithm.
/// </para>
/// <para>Runtime: O(2^(Min(<paramref name="a"/>.Length + <paramref name="b"/>.Length, <paramref name="c"/>.Length))), Ω(1)</para>
/// <para>Memory: O(1)</para>
/// </summary>
/// <inheritdoc cref="IsInterleaved_XML"/>
internal static void IsInterleavedRecursive_XML() => throw new DocumentationMethodException();

/// <summary>
/// Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
/// meaning that <paramref name="c"/> it contains all elements of <paramref name="a"/> and <paramref name="b"/>
/// while retaining the order of the respective elements. Uses a interative algorithm.
/// <para>Runtime: O(Min(<paramref name="a"/>.Length * <paramref name="b"/>.Length))), Ω(1)</para>
/// <para>Memory: O(<paramref name="a"/>.Length * <paramref name="b"/>.Length)</para>
/// </summary>
/// <inheritdoc cref="IsInterleaved_XML"/>
internal static void IsInterleavedIterative_XML() => throw new DocumentationMethodException();

#pragma warning restore CS1734 // XML comment has a paramref tag, but there is no parameter by that name
#pragma warning restore CS1572 // XML comment has a param tag, but there is no parameter by that name
#pragma warning restore CS1711 // XML comment has a typeparam tag, but there is no type parameter by that name

#endregion

/// <inheritdoc cref="IsInterleavedRecursive_XML"/>
public static bool IsInterleavedRecursive<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Func<T, T, bool> equate = default) =>
IsInterleavedRecursive<T, FuncRuntime<T, T, bool>>(a, b, c, equate ?? Equate);

/// <inheritdoc cref="IsInterleavedRecursive_XML"/>
public static bool IsInterleavedRecursive(ReadOnlySpan<char> a, ReadOnlySpan<char> b, ReadOnlySpan<char> c) =>
IsInterleavedRecursive<char, CharEquate>(a, b, c);

/// <inheritdoc cref="IsInterleavedRecursive_XML"/>
public static bool IsInterleavedRecursive<T, Equate>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Equate equate = default)
where Equate : IFunc<T, T, bool>
{
if (a.Length + b.Length != c.Length)
{
return false;
}

bool Implementation(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c) =>
a.IsEmpty && b.IsEmpty && c.IsEmpty ||
(
!c.IsEmpty &&
(
(!a.IsEmpty && equate.Do(a[0], c[0]) && Implementation(a[1..], b, c[1..])) ||
(!b.IsEmpty && equate.Do(b[0], c[0]) && Implementation(a, b[1..], c[1..]))
)
);

return Implementation(a, b, c);
}

/// <inheritdoc cref="IsInterleavedIterative_XML"/>
public static bool IsInterleavedIterative<T>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Func<T, T, bool> equate = default) =>
IsInterleavedIterative<T, FuncRuntime<T, T, bool>>(a, b, c, equate ?? Equate);

/// <inheritdoc cref="IsInterleavedRecursive_XML"/>
public static bool IsInterleavedIterative(ReadOnlySpan<char> a, ReadOnlySpan<char> b, ReadOnlySpan<char> c) =>
IsInterleavedIterative<char, CharEquate>(a, b, c);

/// <inheritdoc cref="IsInterleavedIterative_XML"/>
public static bool IsInterleavedIterative<T, Equate>(ReadOnlySpan<T> a, ReadOnlySpan<T> b, ReadOnlySpan<T> c, Equate equate = default)
where Equate : IFunc<T, T, bool>
{
if (a.Length + b.Length != c.Length)
{
return false;
}
bool[,] d = new bool[a.Length + 1, b.Length + 1];
for (int i = 0; i <= a.Length; ++i)
{
for (int j = 0; j <= b.Length; ++j)
{
d[i, j] =
(i == 0 && j == 0) ||
(
i == 0 ? (equate.Do(b[j - 1], c[j - 1]) && d[i, j - 1]) :
j == 0 ? (equate.Do(a[i - 1], c[i - 1]) && d[i - 1, j]) :
equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1]) ? d[i - 1, j] :
!equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) ? d[i, j - 1] :
equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]) && (d[i - 1, j] || d[i, j - 1])
);

#region expanded version

//if (i == 0 && j == 0)
//{
// d[i, j] = true;
//}
//else if (i == 0)
//{
// if (equate.Do(b[j - 1], c[j - 1]))
// {
// d[i, j] = d[i, j - 1];
// }
//}
//else if (j == 0)
//{
// if (equate.Do(a[i - 1], c[i - 1]))
// {
// d[i, j] = d[i - 1, j];
// }
//}
//else if (equate.Do(a[i - 1], c[i + j - 1]) && !equate.Do(b[j - 1], c[i + j - 1]))
//{
// d[i, j] = d[i - 1, j];
//}
//else if (!equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]))
//{
// d[i, j] = d[i, j - 1];
//}
//else if (equate.Do(a[i - 1], c[i + j - 1]) && equate.Do(b[j - 1], c[i + j - 1]))
//{
// d[i, j] = d[i - 1, j] || d[i, j - 1];
//}

#endregion
}
}
return d[a.Length, b.Length];
}

#endregion

#region Structs

/// <summary>Default int compare.</summary>
Expand Down
55 changes: 55 additions & 0 deletions Sources/Towel/Towel.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31725,6 +31725,61 @@
<param name="equate">The element equate function.</param>
<returns>True if the sequence is a palindrome; False if not.</returns>
</member>
<member name="M:Towel.Statics.IsInterleaved_XML">
<typeparam name="T">The element type of the sequences.</typeparam>
<param name="a">The first sequence to determine if <paramref name="c"/> is interleaved of.</param>
<param name="b">The second sequence to determine if <paramref name="c"/> is interleaved of.</param>
<param name="c">The sequence to determine if it is interleaved from <paramref name="a"/> and <paramref name="b"/>.</param>
<param name="equate">The function for equating <typeparamref name="T"/> values.</param>
<returns>True if <paramref name="c"/> is interleaved of <paramref name="a"/> and <paramref name="b"/> or False if not.</returns>
<example>
<code>
IsInterleaved("abc", "xyz", "axbycz") // True
IsInterleaved("abc", "xyz", "cbazyx") // False (order not preserved)
IsInterleaved("abc", "xyz", "012345") // False
</code>
</example>
</member>
<member name="M:Towel.Statics.IsInterleavedRecursive_XML">
<summary>
<para>
Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
meaning that <paramref name="c"/> it contains all elements of <paramref name="a"/> and <paramref name="b"/>
while retaining the order of the respective elements. Uses a recursive algorithm.
</para>
<para>Runtime: O(2^(Min(<paramref name="a"/>.Length + <paramref name="b"/>.Length, <paramref name="c"/>.Length))), Ω(1)</para>
<para>Memory: O(1)</para>
</summary>
<inheritdoc cref="M:Towel.Statics.IsInterleaved_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedIterative_XML">
<summary>
Determines if <paramref name="c"/> is interleved of <paramref name="a"/> and <paramref name="b"/>,
meaning that <paramref name="c"/> it contains all elements of <paramref name="a"/> and <paramref name="b"/>
while retaining the order of the respective elements. Uses a interative algorithm.
<para>Runtime: O(Min(<paramref name="a"/>.Length * <paramref name="b"/>.Length))), Ω(1)</para>
<para>Memory: O(<paramref name="a"/>.Length * <paramref name="b"/>.Length)</para>
</summary>
<inheritdoc cref="M:Towel.Statics.IsInterleaved_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedRecursive``1(System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.Func{``0,``0,System.Boolean})">
<inheritdoc cref="M:Towel.Statics.IsInterleavedRecursive_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedRecursive(System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Char})">
<inheritdoc cref="M:Towel.Statics.IsInterleavedRecursive_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedRecursive``2(System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},``1)">
<inheritdoc cref="M:Towel.Statics.IsInterleavedRecursive_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedIterative``1(System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.Func{``0,``0,System.Boolean})">
<inheritdoc cref="M:Towel.Statics.IsInterleavedIterative_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedIterative(System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Char},System.ReadOnlySpan{System.Char})">
<inheritdoc cref="M:Towel.Statics.IsInterleavedRecursive_XML"/>
</member>
<member name="M:Towel.Statics.IsInterleavedIterative``2(System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},System.ReadOnlySpan{``0},``1)">
<inheritdoc cref="M:Towel.Statics.IsInterleavedIterative_XML"/>
</member>
<member name="T:Towel.Statics.IntCompare">
<summary>Default int compare.</summary>
</member>
Expand Down
57 changes: 57 additions & 0 deletions Tools/Towel_Testing/Statics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1988,5 +1988,62 @@ [TestMethod] public void IsPalindrome_NonSpan_Testing()
}

#endregion

#region IsInterleaved

[TestMethod] public void IsInterleavedRecursive_Testing()
{
Assert.IsTrue(IsInterleavedRecursive("a", "z", "az"));
Assert.IsTrue(IsInterleavedRecursive("ab", "yz", "aybz"));
Assert.IsTrue(IsInterleavedRecursive("abc", "xyz", "axbycz"));
Assert.IsTrue(IsInterleavedRecursive("abcd", "wxyz", "awbxcydz"));

Assert.IsTrue(IsInterleavedRecursive("a", "z", "za"));
Assert.IsTrue(IsInterleavedRecursive("ab", "yz", "yazb"));
Assert.IsTrue(IsInterleavedRecursive("abc", "xyz", "xaybzc"));
Assert.IsTrue(IsInterleavedRecursive("abcd", "wxyz", "waxbyczd"));

Assert.IsTrue(IsInterleavedRecursive("aa", "zz", "aazz"));
Assert.IsTrue(IsInterleavedRecursive("aa", "zz", "azaz"));
Assert.IsTrue(IsInterleavedRecursive("aa", "zz", "zaza"));
Assert.IsTrue(IsInterleavedRecursive("aa", "zz", "zzaa"));

Assert.IsTrue(IsInterleavedRecursive("", "", ""));

Assert.IsFalse(IsInterleavedRecursive("a", "", ""));
Assert.IsFalse(IsInterleavedRecursive("", "a", ""));
Assert.IsFalse(IsInterleavedRecursive("", "", "a"));
Assert.IsFalse(IsInterleavedRecursive("a", "a", ""));
Assert.IsFalse(IsInterleavedRecursive("a", "a", "aaa"));
}

[TestMethod] public void IsInterleavedIterative_Testing()
{
Assert.IsTrue(IsInterleavedIterative("a", "z", "az"));
Assert.IsTrue(IsInterleavedIterative("ab", "yz", "aybz"));
Assert.IsTrue(IsInterleavedIterative("abc", "xyz", "axbycz"));
Assert.IsTrue(IsInterleavedRecursive("abcd", "wxyz", "awbxcydz"));

Assert.IsTrue(IsInterleavedIterative("a", "z", "za"));
Assert.IsTrue(IsInterleavedIterative("ab", "yz", "yazb"));
Assert.IsTrue(IsInterleavedIterative("abc", "xyz", "xaybzc"));
Assert.IsTrue(IsInterleavedIterative("abcd", "wxyz", "waxbyczd"));

Assert.IsTrue(IsInterleavedIterative("aa", "zz", "aazz"));
Assert.IsTrue(IsInterleavedIterative("aa", "zz", "azaz"));
Assert.IsTrue(IsInterleavedIterative("aa", "zz", "zaza"));
Assert.IsTrue(IsInterleavedIterative("aa", "zz", "zzaa"));

Assert.IsTrue(IsInterleavedIterative("", "", ""));

Assert.IsFalse(IsInterleavedIterative("a", "", ""));
Assert.IsFalse(IsInterleavedIterative("", "a", ""));
Assert.IsFalse(IsInterleavedIterative("", "", "a"));
Assert.IsFalse(IsInterleavedIterative("a", "a", ""));
Assert.IsFalse(IsInterleavedIterative("a", "a", "aaa"));
}

#endregion

}
}

0 comments on commit 4b53538

Please sign in to comment.