Skip to content

Commit 56035d0

Browse files
committed
more z curve
1 parent 3b1b158 commit 56035d0

File tree

2 files changed

+81
-17
lines changed

2 files changed

+81
-17
lines changed

Eocron.Algorithms.Tests/SpaceCurveTests.cs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,52 @@ namespace Eocron.Algorithms.Tests
88
public class SpaceCurveTests
99
{
1010
[Test]
11-
public void ZCurve_Check_Base3()
11+
public void ZCurve_Check_Single_Base3()
1212
{
13-
var input = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
14-
var actual = ZCurve.Interleave(input, 3);
13+
var input = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
14+
var actual = ZCurve.InterleaveSingle(input, 3);
1515
actual.Should().Equal(new[] {1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12});
1616
}
1717

1818
[Test]
19-
public void ZCurve_Check_Base2()
19+
public void ZCurve_Check_Single_Base2()
2020
{
21-
var input = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
22-
var actual = ZCurve.Interleave(input, 2);
21+
var input = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
22+
var actual = ZCurve.InterleaveSingle(input, 2);
2323
actual.Should().Equal(new[] {1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 6, 12});
2424
}
2525

2626
[Test]
27-
public void ZCurve_Check_Multiple()
27+
public void ZCurve_Check_Multiple_SameSize()
2828
{
29-
var input1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
30-
var input2 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
31-
var actual = ZCurve.Interleave(input1, input2);
29+
var input1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
30+
var input2 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
31+
var actual = ZCurve.InterleaveMultiple(input1, input2);
3232
actual.Should().Equal(new[] {1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12});
3333
}
34+
35+
36+
37+
[Test]
38+
public void ZCurve_Check_Multiple_DifferentSize()
39+
{
40+
var input1 = new[] { 1, 2, 3, 4, 5 };
41+
var input2 = new[] { 6 };
42+
var input3 = new[] { 7 };
43+
var actual = ZCurve.InterleaveMultiple(input1, input2, input3);
44+
actual.Should().Equal(new[] {1, 2, 3, 4, 5, 6, 7});
45+
}
46+
47+
[Test]
48+
public void ZCurve_Check_Multiple_DifferentSize_Gcd()
49+
{
50+
var input1 = new[] { 1, 2, 3, 4 };
51+
var input2 = new[] { 6, 7 };
52+
var input3 = new[] { 8, 9 };
53+
var actual = ZCurve.InterleaveMultiple(input1, input2, input3);
54+
actual.Should().Equal(new[] {1, 2, 6, 8, 3, 4, 7, 9});
55+
actual = ZCurve.InterleaveMultiple(input3, input2, input1);
56+
actual.Should().Equal(new[] {8, 6, 1, 2, 9, 7, 3, 4});
57+
}
3458
}
3559
}

Eocron.Algorithms/SpaceCurves/ZCurve.cs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
namespace Eocron.Algorithms.SpaceCurves
66
{
7+
78
public static class ZCurve
89
{
9-
public static T[] Interleave<T>(IReadOnlyCollection<T> items, int m)
10+
public static T[] InterleaveSingle<T>(IReadOnlyCollection<T> items, int m)
1011
{
11-
return Interleave<T>(items, items.Count, m);
12+
return InterleaveSingle(items, items.Count, m);
1213
}
1314

1415

15-
public static T[] Interleave<T>(IEnumerable<T> items, int size, int m)
16+
public static T[] InterleaveSingle<T>(IEnumerable<T> items, int size, int m)
1617
{
1718
if (size % m != 0)
1819
{
@@ -29,24 +30,63 @@ public static T[] Interleave<T>(IEnumerable<T> items, int size, int m)
2930
return output;
3031
}
3132

32-
public static T[] Interleave<T>(params IReadOnlyCollection<T>[] itemSequences)
33+
public static T[] InterleaveMultiple<T>(params IReadOnlyCollection<T>[] itemSequences)
3334
{
3435
var itemSize = itemSequences[0].Count;
3536
if (itemSequences.Any(x=> x.Count != itemSize))
3637
{
37-
throw new ArgumentOutOfRangeException(nameof(itemSequences), "Sequences should have same size");
38+
return InterleaveMultipleDifferentSize(itemSequences);
3839
}
3940

4041
var m = itemSequences.Length;
4142

42-
return Interleave(itemSequences.SelectMany(x => x), itemSize * m, m);
43+
return InterleaveSingle(itemSequences.SelectMany(x => x), itemSize * m, m);
4344
}
4445

45-
public static int GetInterleavedIndex(int idx, int n, int m)
46+
private static T[] InterleaveMultipleDifferentSize<T>(params IReadOnlyCollection<T>[] itemSequences)
47+
{
48+
var (steps, size) = GetChunkSizeAndFinalSize(itemSequences);
49+
var chunked = itemSequences.Select((x,i)=> x.Chunk(steps[i]));
50+
var m = itemSequences.Length;
51+
var interleaved = InterleaveSingle(chunked.SelectMany(x => x), size, m);
52+
return interleaved.SelectMany(x => x).ToArray();
53+
}
54+
55+
private static (int[], int) GetChunkSizeAndFinalSize<T>(IEnumerable<IReadOnlyCollection<T>> itemSequences)
56+
{
57+
var steps = itemSequences.Select(x => x.Count).ToArray();
58+
var gcd = GreatestCommonDivisor(steps);
59+
for (var i = 0; i < steps.Length; i++)
60+
{
61+
steps[i] /= gcd;
62+
}
63+
64+
return (steps, gcd * steps.Length);
65+
}
66+
67+
private static int GetInterleavedIndex(int idx, int n, int m)
4668
{
4769
var i = idx / n;
4870
var j = idx % n;
4971
return j * m + i;
5072
}
73+
74+
private static int GreatestCommonDivisor(IEnumerable<int> items)
75+
{
76+
return items.Aggregate(GreatestCommonDivisor);
77+
}
78+
79+
private static int GreatestCommonDivisor(int a, int b)
80+
{
81+
while (a != 0 && b != 0)
82+
{
83+
if (a > b)
84+
a %= b;
85+
else
86+
b %= a;
87+
}
88+
89+
return a | b;
90+
}
5191
}
5292
}

0 commit comments

Comments
 (0)