Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spliterator part 1 (by Narek Karapetian) #63

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 75 additions & 11 deletions src/main/java/spliterators/part1/exercise/RectangleSpliterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,106 @@
import java.util.Spliterators;
import java.util.function.IntConsumer;

import static java.lang.Math.abs;

public class RectangleSpliterator extends Spliterators.AbstractIntSpliterator {

private final int innerLength;
private final int[][] array;
private final int startOuterInclusive;
private final int endOuterExclusive;
private final int startInnerInclusive;
private int startOuterInclusive;
private int endOuterExclusive;
private int startInnerInclusive;
private int endInnerExclusive;

public RectangleSpliterator(int[][] array) {
this(array, 0, array.length, 0);
this(array,
0,
array.length,
0,
array.length == 0 ? 0 : array[0].length);
}

private RectangleSpliterator(int[][] array, int startOuterInclusive, int endOuterExclusive, int startInnerInclusive) {
super(Long.MAX_VALUE, Spliterator.IMMUTABLE | Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL);
private RectangleSpliterator(int[][] array, int startOuterInclusive, int endOuterExclusive, int startInnerInclusive, int endInnerExclusive) {
super(Long.MAX_VALUE,
Spliterator.IMMUTABLE | Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.NONNULL);

innerLength = array.length == 0 ? 0 : array[0].length;
this.array = array;
this.startOuterInclusive = startOuterInclusive;
this.endOuterExclusive = endOuterExclusive;
this.startInnerInclusive = startInnerInclusive;
this.endInnerExclusive = endInnerExclusive;
}


@Override
public OfInt trySplit() {
// TODO
throw new UnsupportedOperationException();
int elements = abs((int) estimateSize());
if (elements < 2) {
return null;
}

int half = elements / 2;
int midPoint = (startInnerInclusive + half) % innerLength;
int newRows = (startInnerInclusive + half) / innerLength;
int newOuterStart = startOuterInclusive + newRows;

RectangleSpliterator res =
new RectangleSpliterator(array, newOuterStart, endOuterExclusive, midPoint, endInnerExclusive);

endInnerExclusive = midPoint;
endOuterExclusive = midPoint == 0 ? newOuterStart : newOuterStart + 1;

return res;
}

@Override
public void forEachRemaining(IntConsumer action) {
for (int i = startOuterInclusive; i < endOuterExclusive; i++) {
if (i == startOuterInclusive && i == endOuterExclusive - 1) {
for (int j = startInnerInclusive; j < (endInnerExclusive == 0 ? innerLength : endInnerExclusive); j++) {
action.accept(array[i][j]);
}
} else if (i == endOuterExclusive - 1) {
for (int j = 0; j < endInnerExclusive; j++) {
action.accept(array[i][j]);
}
} else if (i == startOuterInclusive) {
for (int j = startInnerInclusive; j < innerLength; j++) {
action.accept(array[i][j]);
}
} else {
for (int j = 0; j < innerLength; j++) {
action.accept(array[i][j]);
}
}
}
}

@Override
public long estimateSize() {
return ((long) endOuterExclusive - startOuterInclusive)*innerLength - startInnerInclusive;
return ((long) endOuterExclusive - startOuterInclusive) * innerLength
- startInnerInclusive - (innerLength - endInnerExclusive);
}

@Override
public boolean tryAdvance(IntConsumer action) {
// TODO
throw new UnsupportedOperationException();
if (startOuterInclusive >= endOuterExclusive) {
return false;
}

final int value = array[startOuterInclusive][startInnerInclusive];
action.accept(value);
startInnerInclusive += 1;

if (((endOuterExclusive - startOuterInclusive) > 1 && startInnerInclusive >= innerLength) ||
((endOuterExclusive - startOuterInclusive) == 1 && startInnerInclusive >= (endInnerExclusive == 0 ? innerLength : endInnerExclusive))
) {
startOuterInclusive += 1;
startInnerInclusive = 0;
}

return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
@State(Scope.Thread)
public class RectangleSpliteratorExercise {

@Param({"100"})
@Param({"13000"})
public int outerLength;

@Param({"100"})
@Param({"13000"})
public int innerLength;

public int[][] array;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Benchmark (innerLength) (outerLength) Mode Cnt Score Error Units
RectangleSpliteratorExercise.baiseline_par 13000 13000 avgt 10 46.978 ± 2.854 ms/op
RectangleSpliteratorExercise.baiseline_seq 13000 13000 avgt 10 77.890 ± 2.696 ms/op
RectangleSpliteratorExercise.rectangle_par 13000 13000 avgt 10 48.243 ± 1.727 ms/op
RectangleSpliteratorExercise.rectangle_seq 13000 13000 avgt 10 80.318 ± 3.265 ms/op
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package spliterators.part1.exercise;

import org.junit.Test;

import java.util.Spliterator;
import java.util.function.IntConsumer;

import static org.junit.Assert.*;


public class RectangleSpliteratorTest {
@Test
public void trySplit() throws Exception {

final int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
};

RectangleSpliterator sp = new RectangleSpliterator(arr);

Spliterator.OfInt ofInt1 = sp.trySplit();
Spliterator.OfInt ofInt2 = ofInt1.trySplit();
Spliterator.OfInt ofInt3 = ofInt2.trySplit();

boolean b1 = ofInt3.tryAdvance((IntConsumer) value -> assertEquals(15, value));
boolean b2 = ofInt3.tryAdvance((IntConsumer) value -> assertEquals(16, value));
boolean b3 = ofInt3.tryAdvance((IntConsumer) value -> System.out.println("This message you'll never see!"));
assertTrue(b1);
assertTrue(b2);
assertFalse(b3);

boolean b4 = ofInt2.tryAdvance((IntConsumer) value -> assertEquals(13, value));
boolean b5 = ofInt2.tryAdvance((IntConsumer) value -> assertEquals(14, value));
boolean b6 = ofInt2.tryAdvance((IntConsumer) value -> System.out.println("This message you'll never see!"));
assertTrue(b4);
assertTrue(b5);
assertFalse(b6);
}


@Test
public void trySplit2() throws Exception {
final int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
{17, 18, 19, 20}
};

RectangleSpliterator sp = new RectangleSpliterator(arr);

Spliterator.OfInt ofInt1 = sp.trySplit();
Spliterator.OfInt ofInt2 = ofInt1.trySplit();
Spliterator.OfInt ofInt3 = ofInt1.trySplit();

boolean b1 = ofInt1.tryAdvance((IntConsumer) value -> assertEquals(11, value));
boolean b2 = ofInt1.tryAdvance((IntConsumer) value -> assertEquals(12, value));
boolean b3 = ofInt1.tryAdvance((IntConsumer) value -> System.out.println("This message you'll never see!"));
assertTrue(b1);
assertTrue(b2);
assertFalse(b3);

boolean b4 = ofInt3.tryAdvance((IntConsumer) value -> assertEquals(13, value));
boolean b5 = ofInt3.tryAdvance((IntConsumer) value -> assertEquals(14, value));
boolean b6 = ofInt3.tryAdvance((IntConsumer) value -> assertEquals(15, value));
boolean b7 = ofInt3.tryAdvance((IntConsumer) value -> System.out.println("This message you'll never see!"));
assertTrue(b4);
assertTrue(b5);
assertTrue(b6);
assertFalse(b7);
}

@Test
public void forEachRemaining() {
final int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
{17, 18, 19, 20}
};

RectangleSpliterator sp = new RectangleSpliterator(arr);

Spliterator.OfInt ofInt1 = sp.trySplit();
Spliterator.OfInt ofInt2 = ofInt1.trySplit();
Spliterator.OfInt ofInt3 = ofInt1.trySplit();

System.out.println("ofInt1");
ofInt1.forEachRemaining((IntConsumer) System.out::println);
System.out.println("ofInt2");
ofInt2.forEachRemaining((IntConsumer) System.out::println);
System.out.println("ofInt3");
ofInt3.forEachRemaining((IntConsumer) System.out::println);
}

}