Skip to content

Commit

Permalink
improve preformance and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
samabcde committed Jun 16, 2024
1 parent 74c6d9c commit 0aa0c84
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 28 deletions.
7 changes: 7 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public int getIntersectScore(BlockPuzzle blockPuzzle) {
}
intersectScore = 0;
for (int i = 0; i < blockPuzzle.getPositionCount(); i++) {
if (!this.intersection.isPositionIdIntersectBitSet.get(i)) {
if (!this.intersection.getIsPositionIdIntersectBitSet().get(i)) {
continue;
}
BlockPosition blockPosition = blockPuzzle.getBlockPositionById(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class BlockPuzzle {
private Block[] blocksById;
private final Map<Shape, List<Block>> shapeToBlocksMap;
private final BlockPosition[] blockPositionsById;
private final List<Block> blocks = new ArrayList<>();
private final List<Block> blocks;

public int getBlockIdByBlockPositionId(int blockPositionId) {
return this.blockPositionsById[blockPositionId].getBlock().id;
Expand Down Expand Up @@ -47,6 +47,7 @@ public int getSize() {
public BlockPuzzle(Dimension dimension, String[] blockValues) {
this.puzzleDimension = dimension;
int blockId = 0;
blocks = new ArrayList<>(blockValues.length);
for (String blockValue : blockValues) {
blocks.add(new Block(blockValue, blockId));
blockId++;
Expand Down Expand Up @@ -118,9 +119,9 @@ private void intersectBlockPositions() {
}

private List<BlockPosition> generateBlockPositions(Block block) {
List<BlockPosition> blockPositions = new ArrayList<>();
block.positionIdFrom = positionCount;
int noOfPosition = (getPuzzleWidth() - block.getWidth() + 1) * (getPuzzleHeight() - block.getHeight() + 1);
List<BlockPosition> blockPositions = new ArrayList<>(noOfPosition);
block.positionIdTo = block.positionIdFrom + noOfPosition - 1;
for (int i = 0; i < getPuzzleWidth() - block.getWidth() + 1; i++) {
for (int j = 0; j < getPuzzleHeight() - block.getHeight() + 1; j++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import java.util.List;

public class Intersection {
final BitSet isPositionIdIntersectBitSet;
final List<Integer> intersectPositionIds = new ArrayList<>();
private final BitSet isPositionIdIntersectBitSet;
private final List<Integer> intersectPositionIds = new ArrayList<>();
private int intersectCount;

Intersection(int positionCount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public Solution solve() {
resetAddedPosition(block);
}
if (iterateCount % 200000 == 0) {
logger.info("iterate" + iterateCount);
logger.info("iterate{}", iterateCount);
solution.print();
}
}
Expand All @@ -117,12 +117,10 @@ public Solution solve() {
}

private boolean isCurrentBoardSolvable(Block block) {
List<Block> remainingBlocks = getRemainingBlocks();
BlockPossiblePosition cloneBlockPossiblePosition = this.blockPossiblePosition;
BoardFillState cloneBoardFillState = this.boardFillState.copy();
if (!this.blockPossiblePosition.hasPossiblePosition(block, boardFillState)) {
return false;
}
List<Block> remainingBlocks = getRemainingBlocks();
if (this.boardFillState.countPointCanOnlyFillByWeight1Block() > remainingBlocks.stream().filter(b -> b.getWeight() == 1).count()) {
return false;
}
Expand All @@ -134,7 +132,8 @@ private boolean isCurrentBoardSolvable(Block block) {
return false;
}
}
List<PossiblePositions> remainingBlockPossiblePositions = getRemainingBlocksPossiblePositions(cloneBoardFillState, remainingBlocks, cloneBlockPossiblePosition);
BoardFillState cloneBoardFillState = this.boardFillState.copy();
List<PossiblePositions> remainingBlockPossiblePositions = getRemainingBlocksPossiblePositions(cloneBoardFillState, remainingBlocks, this.blockPossiblePosition);
return isRemainingBlockPositionsSolvable(cloneBoardFillState, remainingBlockPossiblePositions);
}

Expand Down
11 changes: 5 additions & 6 deletions src/main/java/com/samabcde/puzzlesolver/solve/Solution.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,9 @@ public Solution(BlockPuzzle blockPuzzle) {

private char[] getDisplay(int count) {
if (count > display.length()) {
throw new RuntimeException("Not enough display, count:%d, available:%d".formatted(count, display.length()));
throw new IllegalArgumentException("Not enough display, count:%d, available:%d".formatted(count, display.length()));
}
char[] c = new char[count];
for (int i = 0; i < count; i++) {
c[i] = display.charAt(i);
}
return c;
return display.toCharArray();
}

void print() {
Expand Down Expand Up @@ -67,6 +63,9 @@ void print() {
}

public BlockPosition poll() {
if (positionSolutions.isEmpty()) {
throw new NoSuchElementException();
}
BlockPosition blockPosition = positionSolutions.poll();
addedBlocks.set(blockPosition.getBlock().id, false);
return blockPosition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class BlockPossiblePosition {
private final int[] possiblePositionCountOfBlocks;
private final int[] intersectionCountOfBlockPositions;
private final int[] addedPositionOfBlocks;
// TODO add BlockCommonIntersection

public BlockPossiblePosition(BlockPuzzle blockPuzzle) {
this.intersectionCountOfBlockPositions = new int[blockPuzzle.getPositionCount()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,7 @@ public List<Integer> getCanFillBlockIds() {
}

public boolean canFillByOnlyOneBlock() {
boolean hasOneBlock = false;
for (int i = 0; i < canFillPositionCountOfBlocks.length; i++) {
if (canFillPositionCountOfBlocks[i] > 0) {
if (hasOneBlock) {
return false;
}
hasOneBlock = true;
}
}
return hasOneBlock;
return this.canFillBlockCount == 1;
}

public boolean canNotFillByAnyBlock() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ public void testSolve12() {
"1,111111,01", "01,11,11,11,01", "111111,1,1,1,1", "1111,11111,01", "1111,1111,101",
"111,011,111,11,11,0111", "011,111,1,11111,111,011", "111,001,001,111", "01,1111,111111",
"01,111,01,01,111,001,001,111,1"

});
// iterate Count: 110452847
// bbii222333333
Expand Down Expand Up @@ -269,7 +268,6 @@ public void testSolve12() {
}

@Test
// @Disabled
public void testSolve12a() {
BlockPuzzle blockPuzzle = new BlockPuzzle(
new Dimension(13, 13), new String[]{"1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1,1", "11", "11", "1", "1", "1",
Expand Down
75 changes: 75 additions & 0 deletions src/test/java/com/samabcde/puzzlesolver/solve/SolutionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.samabcde.puzzlesolver.solve;

import com.samabcde.puzzlesolver.component.Block;
import com.samabcde.puzzlesolver.component.BlockPosition;
import com.samabcde.puzzlesolver.component.BlockPuzzle;
import com.samabcde.puzzlesolver.component.Dimension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.util.NoSuchElementException;

import static org.junit.jupiter.api.Assertions.*;

class SolutionTest {
@Nested
public class Given_EmptySolution {
BlockPuzzle blockPuzzle = new BlockPuzzle(new Dimension(1, 1), new String[]{"1"});
Solution solution = new Solution(blockPuzzle);

@Test
public void itSizeIs0() {
assertEquals(0, solution.size());
}

@Test
public void itIsEmpty() {
assertTrue(solution.isEmpty());
}

@Test
public void itDoesNotContainsBlock() {
blockPuzzle.getBlocks().forEach(block ->
assertFalse(solution.containsBlock(block)));
}

@Test
public void pollThrowException() {
assertThrows(NoSuchElementException.class, () -> solution.poll());
}
}

@Nested
public class AddOnePosition {
BlockPuzzle blockPuzzle = new BlockPuzzle(new Dimension(1, 1), new String[]{"1"});
Solution solution = new Solution(blockPuzzle);
Block block = blockPuzzle.getBlocks().getFirst();
BlockPosition blockPosition = block.getBlockPositions().getFirst();

@BeforeEach
public void setup() {
solution.push(blockPuzzle.getBlocks().getFirst().getBlockPositions().getFirst());
}

@Test
public void itSizeIs1() {
assertEquals(1, solution.size());
}

@Test
public void itIsNotEmpty() {
assertFalse(solution.isEmpty());
}

@Test
public void itContainsBlock() {
assertTrue(solution.containsBlock(block));
}

@Test
public void pollReturnPushedPosition() {
assertEquals(blockPosition, solution.poll());
}
}
}

0 comments on commit 0aa0c84

Please sign in to comment.