Skip to content

Commit 7fa8ace

Browse files
committed
Whoops, now I'm properly factoring in clues in the solver.
1 parent 79d46cb commit 7fa8ace

File tree

6 files changed

+88
-20
lines changed

6 files changed

+88
-20
lines changed

FinModelUtility/Fin/Fin.Picross/src/PicrossCluesGenerator.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ private static IPicrossClue[] GetClues_(ref int index,
5454
++length;
5555
} else if (length > 0) {
5656
clues.AddLast(
57-
new PicrossClue(index++, isForColumn, columnOrRowIndex, (byte) (i - length), length));
57+
new PicrossClue(index++,
58+
isForColumn,
59+
columnOrRowIndex,
60+
(byte) (i - length),
61+
length));
5862
length = 0;
5963
}
6064

@@ -63,7 +67,11 @@ private static IPicrossClue[] GetClues_(ref int index,
6367

6468
if (clues.Count == 0 || length != 0) {
6569
clues.AddLast(
66-
new PicrossClue(index++, isForColumn, columnOrRowIndex, (byte) (i - length), length));
70+
new PicrossClue(index++,
71+
isForColumn,
72+
columnOrRowIndex,
73+
length == 0 ? (byte) 0 : (byte) (i - length),
74+
length));
6775
}
6876

6977
return clues.ToArray();

FinModelUtility/Fin/Fin.Picross/src/PicrossSolver.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using fin.data.indexable;
33
using fin.math;
44
using fin.picross.moves;
5+
using fin.util.asserts;
56

67
namespace fin.picross.solver;
78

@@ -59,6 +60,10 @@ var clueStatesByClue
5960
moveSet.Add(new PicrossCellMove(moveType, moveSource, x, y));
6061
break;
6162
}
63+
case PicrossClueMove picrossClueMove: {
64+
moveSet.Add(picrossClueMove);
65+
break;
66+
}
6267
}
6368
}
6469
}
@@ -75,6 +80,10 @@ var clueStatesByClue
7580
moveSet.Add(new PicrossCellMove(moveType, moveSource, x, y));
7681
break;
7782
}
83+
case PicrossClueMove picrossClueMove: {
84+
moveSet.Add(picrossClueMove);
85+
break;
86+
}
7887
}
7988
}
8089
}
@@ -85,6 +94,23 @@ var clueStatesByClue
8594
}
8695

8796
boardState.ApplyMoves(moveSet);
97+
foreach (var move in moveSet) {
98+
if (move is PicrossClueMove clueMove) {
99+
var clueState = clueStatesByClue[clueMove.Clue];
100+
101+
// Verifies clue is at the correct location.
102+
Asserts.Equal(clueState.Clue.CorrectStartIndex,
103+
clueMove.StartIndex,
104+
$"Incorrect clue move of source {clueMove.MoveSource}; marked as starting at {clueMove.StartIndex} but should actually be {clueState.Clue.CorrectStartIndex}");
105+
106+
// Verifies we didn't already mark this clue as solved.
107+
Asserts.False(clueState.Solved,
108+
$"Got duplicate clue solution of source {clueMove.MoveSource}");
109+
110+
clueState.StartIndex = clueMove.StartIndex;
111+
}
112+
}
113+
88114
moveSets.Add(moveSet);
89115
}
90116

@@ -355,11 +381,12 @@ var targetI
355381
}
356382
}
357383

358-
if (isFirstClue && clueUnknownCount == 0) {
384+
if (isFirstClue && clueUnknownCount == 0 && !clueState.Solved) {
385+
var clueStartI = forward ? i : i + increment * (clueLength - 1);
359386
yield return new PicrossClueMove(
360387
PicrossClueMoveSource.FIRST_CLUE,
361388
clueState.Clue,
362-
Math.Min(i, i + increment * clueLength));
389+
clueStartI);
363390
}
364391

365392
totalUnknownCount += clueUnknownCount;

FinModelUtility/Fin/Fin.Picross/src/solver/AlreadySolvedPicrossSolverMethod.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,7 @@ var actualCount
2020
}
2121

2222
if (alreadySolved) {
23-
if (clueStates is [{ Length: 0 }]) {
24-
yield return new PicrossClueMove(
25-
PicrossClueMoveSource.ALL_CLUES_SOLVED,
26-
clueStates[0].Clue,
27-
0
28-
);
29-
} else {
23+
if (clueStates is not [{ Length: 0 }]) {
3024
var cellI = 0;
3125
foreach (var clueState in clueStates) {
3226
while (cellStates[cellI].Status != PicrossCellStatus.KNOWN_FILLED) {

FinModelUtility/Fin/Fin.Picross/src/solver/GapsBetweenNeighboringCluesSolverMethod.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ public IEnumerable<IPicrossMove1d> TryToFindMoves(
99
var cellStates = lineState.CellStates;
1010
var length = cellStates.Count;
1111

12-
var biggestLength = clues.Max(c => c.Length);
12+
if (clues.All(c => c.Solved)) {
13+
yield break;
14+
}
15+
16+
var biggestLength = clues.Where(c => !c.Solved).Max(c => c.Length);
1317

1418
var cell0 = cellStates[0].Status;
1519
var cell1 = cellStates[1].Status;

FinModelUtility/Fin/Fin.Picross/src/solver/MatchingBiggestOrUniqueLengthSolverMethod.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ public IEnumerable<IPicrossMove1d> TryToFindMoves(
1010
var cellStates = lineState.CellStates;
1111
var length = cellStates.Count;
1212

13-
var biggestUnusedLength = clueStates.Where(c => !c.Solved).Max(c => c.Length);
13+
if (clueStates.All(c => c.Solved)) {
14+
yield break;
15+
}
16+
17+
var biggestUnusedLength
18+
= clueStates.Where(c => !c.Solved).Max(c => c.Length);
1419

1520
int startIndex = -1;
1621
var inClue = false;
@@ -67,6 +72,10 @@ private static IEnumerable<IPicrossMove1d> CheckIfMatchingClue_(
6772
int clueLength,
6873
bool knownEmptyBefore,
6974
bool knownEmptyAfter) {
75+
if (clueStates.Any(c => c.StartIndex == startI)) {
76+
yield break;
77+
}
78+
7079
var firstClueWithExactLength
7180
= clueStates.Where(c => !c.Solved)
7281
.FirstOrDefaultAndCount(c => c.Length == clueLength,
@@ -79,6 +88,11 @@ var firstClueWithExactLength
7988

8089
if (matchingClueCount == 1 &&
8190
(isBiggest || (knownEmptyBefore && knownEmptyAfter))) {
91+
if (clueStates is [{ Length: 2 }, { Length: 2 }, { Length: 1 }] &&
92+
startI == 2) {
93+
;
94+
}
95+
8296
yield return new PicrossClueMove(
8397
PicrossClueMoveSource.ONLY_MATCHING_CLUE,
8498
firstClueWithExactLength.Clue,

FinModelUtility/Fin/Fin.Picross/src/solver/PicrossBoardState.cs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ public enum PicrossCompletionState {
2121
[GenerateReadOnly]
2222
public partial interface IPicrossCellState {
2323
PicrossCellStatus Status { get; set; }
24+
PicrossCellMoveSource MoveSource { get; set; }
25+
IPicrossClue? Clue { get; set; }
2426
}
2527

2628
public class PicrossCellState : IPicrossCellState {
2729
public PicrossCellStatus Status { get; set; }
2830
public PicrossCellMoveSource MoveSource { get; set; }
31+
public IPicrossClue? Clue { get; set; }
2932
}
3033

3134
public class PicrossBoardState : IReadOnlyGrid<IReadOnlyPicrossCellState> {
@@ -57,23 +60,41 @@ public void ApplyMoves(IReadOnlySet<IPicrossMove> moveSet) {
5760

5861
var cellState = this.cellStates_[y * width + x];
5962

60-
// Verifies the board didn't already have a move at this location.
61-
Asserts.Equal(PicrossCellStatus.UNKNOWN,
62-
cellState.Status,
63-
$"Got a duplicate move of source {moveSource}");
64-
6563
// Verifies moves are correct against the existing board.
6664
var expected = moveType == PicrossCellMoveType.MARK_FILLED;
6765
Asserts.Equal(expected,
6866
this.definition_[x, y],
6967
$"Incorrect move of source {moveSource}.");
7068

69+
// Verifies the board didn't already have a move at this location.
70+
Asserts.Equal(PicrossCellStatus.UNKNOWN,
71+
cellState.Status,
72+
$"Got a duplicate move of source {moveSource}");
73+
7174
// Applies the move to the cell.
7275
cellState.Status = moveType switch {
73-
PicrossCellMoveType.MARK_EMPTY => PicrossCellStatus.KNOWN_EMPTY,
76+
PicrossCellMoveType.MARK_EMPTY => PicrossCellStatus.KNOWN_EMPTY,
7477
PicrossCellMoveType.MARK_FILLED => PicrossCellStatus.KNOWN_FILLED,
75-
_ => throw new ArgumentOutOfRangeException()
78+
_ => throw new ArgumentOutOfRangeException()
7679
};
80+
cellState.MoveSource = moveSource;
81+
82+
break;
83+
}
84+
case PicrossClueMove picrossClueMove: {
85+
var (_, clue, startI) = picrossClueMove;
86+
for (var i = startI; i < startI + clue.Length; ++i) {
87+
int x, y;
88+
if (clue.IsForColumn) {
89+
x = clue.ColumnOrRowIndex;
90+
y = i;
91+
} else {
92+
x = i;
93+
y = clue.ColumnOrRowIndex;
94+
}
95+
96+
this.cellStates_[y * width + x].Clue = clue;
97+
}
7798

7899
break;
79100
}

0 commit comments

Comments
 (0)