Sudoku Programmers Forum Index

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in          Games  Calendar

Log in to check your private messagesLog in to check your private messages   

Fishy Cycles
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Solving sudoku
View previous topic :: View next topic  
Author Message
gaby

Joined: 02 Jul 2005
Posts: 120
:

Items
PostPosted: Sat Aug 06, 2005 2:10 am    Post subject: Still getting problems Reply with quote

Hi,

I've got a good implementation of Fishy Cycles in place now, but it's generating an interesting recommendation, that is ultimately incorrect. The caveats I have programmed for it, and features are:

- Edges cannot be reused as edges again in any given cycle
- One cell from each vertex forms the edge, and these cells cannot be used more than once in any given cycle
- Vertices are computed acceptably
- Edges are computed acceptably, with multiple edges arising from vertices
- Graphs seem to work, except for my example.

Here's the starting point:

Code:

1358 18  36 4    7    9    6   2  18
178  178 4  126  1268 18   3   9  5
9    2   6  135  18   1358 148 47 1478
57   3   1  257  248  578  45  6  9
258  48  25 9    3    6    145 47 147
567  467 9  157  14   157  2   8  3
23   5   23 8    9    4    7   1  6
4    18  8  1367 16   137  9   5  2
16   9   7  16   5    2    48  3  48


The problem comes in the 6's, where it's the only number that creates any chains of reasonable length. Here are the edges, vertices and mappings of edges to individual cells:

Code:
Vertices for 6
r1 => [4,2][5,2]
r5 => [1,6][2,6]
r8 => [1,9][4,9]
c0 => [1,6][1,9]
c1 => [2,6][2,8]
c4 => [5,2][5,8]
b1 => [4,2][5,2]
b3 => [1,6][2,6]
b6 => [2,8][1,9]
Edges for 6
[r1,r8] <-> ec3
[r1,b1] <-> ec3,ec4
[r5,r8] <-> ec0
[r5,b3] <-> ec0,ec1
[r5,b6] <-> ec0,ec1
[r8,r1] <-> ec3
[r8,r5] <-> ec0
[r8,c0] <-> eb6
[r8,c1] <-> eb6
[r8,c4] <-> eb7
[r8,b1] <-> ec3
[r8,b3] <-> ec0
[r8,b6] <-> ec0
[c0,r8] <-> eb6
[c0,c1] <-> er5,eb3,eb6
[c0,b6] <-> er8
[c1,r8] <-> eb6
[c1,c0] <-> er5,eb3,eb6
[c1,c4] <-> er7
[c1,b6] <-> er7
[c4,r8] <-> eb7
[c4,c1] <-> er7
[c4,b6] <-> er7
[b1,r1] <-> ec3,ec4
[b1,r8] <-> ec3
[b3,r5] <-> ec0,ec1
[b3,r8] <-> ec0
[b3,b6] <-> ec0,ec1
[b6,r5] <-> ec0,ec1
[b6,r8] <-> ec0
[b6,c0] <-> er8
[b6,c1] <-> er7
[b6,c4] <-> er7
[b6,b3] <-> ec0,ec1
Mappings for 6
r1-r8-c3 = {[3,1][3,8]}
r1-b1-c3 = {[3,1][3,1]}
r1-b1-c4 = {[4,1][4,1]}
r5-r8-c0 = {[0,5][0,8]}
r5-b3-c0 = {[0,5][0,5]}
r5-b3-c1 = {[1,5][1,5]}
r5-b6-c0 = {[0,5][0,8]}
r5-b6-c1 = {[1,5][1,7]}
r8-r1-c3 = {[3,8][3,1]}
r8-r5-c0 = {[0,8][0,5]}
r8-c0-b6 = {[0,8][0,8]}
r8-c1-b6 = {[0,8][1,7]}
r8-c4-b7 = {[3,8][4,7]}
r8-b1-c3 = {[3,8][3,1]}
r8-b3-c0 = {[0,8][0,5]}
r8-b6-c0 = {[0,8][0,8]}
c0-r8-b6 = {[0,8][0,8]}
c0-c1-r5 = {[0,5][1,5]}
c0-c1-b3 = {[0,5][1,5]}
c0-c1-b6 = {[0,8][1,7]}
c0-b6-r8 = {[0,8][0,8]}
c1-r8-b6 = {[1,7][0,8]}
c1-c0-r5 = {[1,5][0,5]}
c1-c0-b3 = {[1,5][0,5]}
c1-c0-b6 = {[1,7][0,8]}
c1-c4-r7 = {[1,7][4,7]}
c1-b6-r7 = {[1,7][1,7]}
c4-r8-b7 = {[4,7][3,8]}
c4-c1-r7 = {[4,7][1,7]}
c4-b6-r7 = {[4,7][1,7]}
b1-r1-c3 = {[3,1][3,1]}
b1-r1-c4 = {[4,1][4,1]}
b1-r8-c3 = {[3,1][3,8]}
b3-r5-c0 = {[0,5][0,5]}
b3-r5-c1 = {[1,5][1,5]}
b3-r8-c0 = {[0,5][0,8]}
b3-b6-c0 = {[0,5][0,8]}
b3-b6-c1 = {[1,5][1,7]}
b6-r5-c0 = {[0,8][0,5]}
b6-r5-c1 = {[1,7][1,5]}
b6-r8-c0 = {[0,8][0,8]}
b6-c0-r8 = {[0,8][0,8]}
b6-c1-r7 = {[1,7][1,7]}
b6-c4-r7 = {[1,7][4,7]}
b6-b3-c0 = {[0,8][0,5]}
b6-b3-c1 = {[1,7][1,5]}


The problem comes with this cycle:

Code:

Vertices for 6: b6,c0,c1,b6
Edges for 6 : r8,r5,r7
Cells for 6 : {[0,8][0,8][0,5][1,5][1,7][1,7}

6 <- 4-9 (fishy cycle 6: b6<r8>c0<r5>c1<r7>b6)
6 <- 4-8 (fishy cycle 6: b6<r8>c0<r5>c1<r7>b6)
6 <- 5-8 (fishy cycle 6: b6<r8>c0<r5>c1<r7>b6)


Doing those removals results in an invalid board, with r8c5 having no possible candidates when r9c4 becomes a 1. What am I missing out here? Are any of my vertices/edges invalid? What's the upcock here?

Gaby
_________________
Free daily sudoku - Online puzzle database
http://vanhegan.net/sudoku/
Back to top
View user's profile Send private message Visit poster's website
MadOverlord

Joined: 01 Jun 2005
Posts: 80
:
Location: Wilmington, NC, USA

Items
PostPosted: Sat Aug 06, 2005 3:05 am    Post subject: Reply with quote

Well, first of all, your starting matrix has a typo in it:

Code:

1358 18  36 4    7    9    6   2  18
178  178 4  126  1268 18   3   9  5
9    2   6  135  18   1358 148 47 1478
57   3   1  257  248  578  45  6  9
258  48  25 9    3    6    145 47 147
567  467 9  157  14   157  2   8  3
23   5   23 8    9    4    7   1  6
4    18  8  1367 16   137  9   5  2
16   9   7  16   5    2    48  3  48


If R3C3=6 then R1C3 cannot be 36. It should be 35. Similarly, R8C2 is 16, not 18.

Starting from the corrected base position, there are a number of simple moves that can be done without Fishing.

Deduction pass 1; 40 squares solved; 41 remaining.

* 2 squares in row 1 form a simple locked pair. R1C2 and R1C9 share possibilities <18>. Thus, these possibilities can be removed from the rest of the row.

R1C1 - removing <18> from <1358> leaving <35>.

Deduction pass 2; 40 squares solved; 41 remaining.

* 2 squares in row 8 form a simple locked pair. R8C2 and R8C5 share possibilities <16>. Thus, these possibilities can be removed from the rest of the row.

R8C4 - removing <16> from <1367> leaving <37>.
R8C6 - removing <1> from <137> leaving <37>.

Deduction pass 3; 40 squares solved; 41 remaining.

* 2 squares in block 2 form a simple locked pair. R2C6 and R3C5 share possibilities <18>. Thus, these possibilities can be removed from the rest of the block.

R2C4 - removing <1> from <126> leaving <26>.
R2C5 - removing <18> from <1268> leaving <26>.
R3C4 - removing <1> from <135> leaving <35>.
R3C6 - removing <18> from <1358> leaving <35>.

Deduction pass 4; 40 squares solved; 41 remaining.

* Intersection of row 5 with block 4. The values <28> can only appear in squares R5C1, R5C2 and R5C3 of row 5. Thus, the non-intersecting squares of block 4 cannot contain these values.

R4C1 - removing <28> from <2578> leaving <57>.

Deduction pass 5; 40 squares solved; 41 remaining.

* Intersection of block 6 with row 5. The values <17> can only appear in squares R5C7, R5C8 and R5C9 of block 6. Thus, the non-intersecting squares of row 5 cannot contain these values.

R5C1 - removing <7> from <2578> leaving <258>.
R5C2 - removing <7> from <478> leaving <48>.

Deduction pass 6; 40 squares solved; 41 remaining.

This gets us to:

Code:

+-----------------------+-----------------------+-----------------------+
|       .       .       |       .       .       |       .       .       |
| 3 5   . 1 8   . 3 5   | #   # . ##### . ##### | ##### . ##### . 1 8   |
|       .       .       | #   # .     # . #   # | #     .     # .       |
|       .       .       | ##### .     # . ##### | ##### . ##### .       |
|       .       .       |     # .     # .     # | #   # . #     .       |
|       .       .       |     # .     # .     # | ##### . ##### .       |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| 1 7 8 . 1 7 8 . #   # | 2 6   . 2 6   . 1 8   | ##### . ##### . ##### |
|       .       . #   # |       .       .       |     # . #   # . #     |
|       .       . ##### |       .       .       |  #### . ##### . ##### |
|       .       .     # |       .       .       |     # .     # .     # |
|       .       .     # |       .       .       | ##### .     # . ##### |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| ##### . ##### . ##### | 3 5   . 1 8   . 3 5   | 1 4 8 . 4 7   . 1 4 7 |
| #   # .     # . #     |       .       .       |       .       . 8     |
| ##### . ##### . ##### |       .       .       |       .       .       |
|     # . #     . #   # |       .       .       |       .       .       |
|     # . ##### . ##### |       .       .       |       .       .       |
+-----------------------+-----------------------+-----------------------+
|       .       .       |       .       .       |       .       .       |
| 5 7   . ##### .   #   | 2 5 7 . 2 4 8 . 5 7 8 | 4 5   . ##### . ##### |
|       .     # .   #   |       .       .       |       . #     . #   # |
|       .  #### .   #   |       .       .       |       . ##### . ##### |
|       .     # .   #   |       .       .       |       . #   # .     # |
|       . ##### .   #   |       .       .       |       . ##### .     # |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| 2 5 8 . 4 8   . 2 5   | ##### . ##### . ##### | 1 4 5 . 4 7   . 1 4 7 |
|       .       .       | #   # .     # . #     |       .       .       |
|       .       .       | ##### .  #### . ##### |       .       .       |
|       .       .       |     # .     # . #   # |       .       .       |
|       .       .       |     # . ##### . ##### |       .       .       |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| 5 6 7 . 4 6 7 . ##### | 1 5 7 . 1 4   . 1 5 7 | ##### . ##### . ##### |
|       .       . #   # |       .       .       |     # . #   # .     # |
|       .       . ##### |       .       .       | ##### . ##### .  #### |
|       .       .     # |       .       .       | #     . #   # .     # |
|       .       .     # |       .       .       | ##### . ##### . ##### |
+-----------------------+-----------------------+-----------------------+
|       .       .       |       .       .       |       .       .       |
| 2 3   . ##### . 2 3   | ##### . ##### . #   # | ##### .   #   . ##### |
|       . #     .       | #   # . #   # . #   # |     # .   #   . #     |
|       . ##### .       | ##### . ##### . ##### |     # .   #   . ##### |
|       .     # .       | #   # .     # .     # |     # .   #   . #   # |
|       . ##### .       | ##### .     # .     # |     # .   #   . ##### |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| #   # . 1 6   . ##### | 3 7   . 1 6   . 3 7   | ##### . ##### . ##### |
| #   # .       . #   # |       .       .       | #   # . #     .     # |
| ##### .       . ##### |       .       .       | ##### . ##### . ##### |
|     # .       . #   # |       .       .       |     # .     # . #     |
|     # .       . ##### |       .       .       |     # . ##### . ##### |
|.......................|.......................|.......................|
|       .       .       |       .       .       |       .       .       |
| 1 6   . ##### . ##### | 1 6   . ##### . ##### | 4 8   . ##### . 4 8   |
|       . #   # .     # |       . #     .     # |       .     # .       |
|       . ##### .     # |       . ##### . ##### |       .  #### .       |
|       .     # .     # |       .     # . #     |       .     # .       |
|       .     # .     # |       . ##### . ##### |       . ##### .       |
+-----------------------+-----------------------+-----------------------+


And then you can find the fishy cycle, which breaks the puzzle:

* There is a "Fishy Cycle" in the puzzle, as follows:

{R8} -- R8C2 -- (B7) -- R9C1 -- {C1}
{C1} -- R2C1 -- (R2) -- R2C6 -- {C6}
{C6} -- R6C6 -- (R6) -- R6C4 -- {C4}
{C4} -- R9C4 -- (B8) -- R8C5 -- {R8}

Each of the "vertex groups" (shown in {braces}) has only 2 squares that can contain a <1>. Such squares are called "conjugate pairs".

These squares are the "link squares", and the possibility they share is the "link number".

Vertex groups are linked together by "edge groups" (shown in (parentheses)). An edge group shares link squares with the two vertexes that it links.

A Fishy Cycle is a loop around the puzzle, such that each vertex in the loop is visited only once, each link square is used only once, and each edge is used only once. Also, the vertexes of a fishy cycle cannot appear as edges in the cycle.

In a fishy cycle, it is impossible for the link number to appear in any of the edge groups except in the link squares. So we can remove it if it appears in any of the other squares in the group!

Beautiful female Sudoku maniacs should be aware that if you kiss a geeky mathematician, they are pathetically grateful, and will tell you lots of stuff like this.

R2C2 - removing <1> from <178> leaving <78>.
R6C5 - removing <1> from <14> leaving <4>.


Deduction pass 2; 41 squares solved; 40 remaining.

* R4C7 is the only square in row 4 that can be a <4>. It is thus pinned to that value.

From this deduction, the following moves are immediately forced:

R9C7 must be <8>.
R5C8 must be <7>.
R5C9 must be <1>.
R3C8 must be <4>.
R5C7 must be <5>.
R1C9 must be <8>.
R9C9 must be <4>.
R3C7 must be <1>.
R1C2 must be <1>.
R3C9 must be <7>.
R3C5 must be <8>.
R5C3 must be <2>.
R8C2 must be <6>.
R4C5 must be <2>.
R2C6 must be <1>.
R2C5 must be <6>.
R5C1 must be <8>.
R7C3 must be <3>.
R7C1 must be <2>.
R1C3 must be <5>.
R8C5 must be <1>.
R6C2 must be <7>.
R9C1 must be <1>.
R9C4 must be <6>.
R2C4 must be <2>.
R1C1 must be <3>.
R5C2 must be <4>.
R2C1 must be <7>.
R6C6 must be <5>.
R2C2 must be <8>.
R4C1 must be <5>.
R6C1 must be <6>.
R6C4 must be <1>.
R3C6 must be <3>.
R4C4 must be <7>.
R3C4 must be <5>.
R8C6 must be <7>.
R4C6 must be <8>.
R8C4 must be <3>.

Deduction pass 3; 81 squares solved; 0 remaining.

Solution found!
Back to top
View user's profile Send private message Visit poster's website AIM Address
gaby

Joined: 02 Jul 2005
Posts: 120
:

Items
PostPosted: Sat Aug 06, 2005 9:48 pm    Post subject: Reply with quote

Sorry about the typos, I should have checked it a little more thoroughly before putting the code up... Smile Also, I had disabled some forms of analysis so that I would have something for the fishy cycles to look for. When I enable number chains (what I call disjoint subsets) it finds the number chain 1,8 in row 1, and does as you suggest.

Having run some serious debug and optimisation on my code, I've found the problem. I found that edges were being generated when two vertices shared a cell in exactly the same location, where in effect this should not be an edge. Adding in this constraint greatly reduced the number of edges in the graph, and also prevented the problem I described in my last post.

On top of that, I created a function to narrow down the set of edges when a new vertex is added to the graph, just to make sure I'm only dealing with the minimal set of edges that I need to:

$edges = _fishy_edge_remove( $new_edge, $new_vertex, $edges )

You go along $new_edge to get to $new_vertex. $edges contains a list of vertex-to-vertex edges (va-vb)=(e1,e2...en). If $new_vertex == vb, then we remove the edge from the list. If any of the edges (e1,e2...en) == $new_vertex, then those edges are discarded as well. This ensures that we never revisit an edge, nor do we use a vertex as an edge later on in the cycle. We then recursively generate the list of possible cycles from the new list of edges.

Either way, this seems to have fixed the problem. My PHP code is not the most efficient, but ensuring that the path that a cycle takes never visits the same square twice, even for individual edges, has made it run nice and fast, solving the puzzle very quickly indeed Smile
_________________
Free daily sudoku - Online puzzle database
http://vanhegan.net/sudoku/
Back to top
View user's profile Send private message Visit poster's website
Lummox JR

Joined: 07 Sep 2005
Posts: 202
:

Items
PostPosted: Tue Sep 13, 2005 12:13 am    Post subject: Reply with quote

I think I must be misunderstanding part of this algorithm. I have a board where fishy cycles is telling me to eliminate a choice I know is actually part of the solution; eliminating it results in an unsolvable board. Here's what I get with the digit 2:
Code:
.*.|*..|...
..*|*.*|...
...|...|.2.
-----------
.**|...|...
...|...|2..
...|*.*|...
-----------
...|...|..2
...|.2.|...
2..|...|...

Where I think I'm going wrong is that the conjugate in b1 can also be used in r1, c2, and c3, and I'm not sure that's legal (nor of how to resolve it). Hence why I didn't label these with aA, bB, and so on. By my own interpretation I get potential conjugates in b1, c2, c3, c6, r1, r4, and r6. That leads me to these conclusions:

b1 -> c6 via r2
b1 -> r4 via c2,c3
c2 -> c3 via b1,r4
c3 -> c6 via r2
c3 -> r1 via b1
c6 -> r1 via b2
r1 -> r4 via c2
r1 -> r6 via c4

This gives me a graph like so:
Code:
      c2,c3
   b1=======r4
    |       |
  r2|       |c2
    |   b2  |    c4
   c6-------r1-------r6
    \       |
     \    b1|
    r2\     |  b1,r4
       \----c3=======c2


Excluding the 2-house cycles, there's a 3-cycle suggesting I should eliminate (4,2), and another 4-cycle saying the same thing. (They don't combine to a 5-cycle because of the common r2 edge.) Problem is, (4,2) is a 2 in the solution and this should not be eliminated.

If I include the rule that the same house can't be passed through more than once in a cycle, the 4-cycle can lose c2 along the double-edge and still have c3 to make a complete cycle: r1->c2->r4->c3->b1->r2->c6->b2->r1. The 3-cycle remains valid.

The only thing I can figure, since others have been able to use this algorithm effectively, is that by allowing cells to be part of two pairs like b1, r1, c2, c3, or by NOT counting b4 and b5, I'm screwing something up. Then again, I don't see counting b4 and b5 as helping much.
Code:
      c2,c3
   b1=======r4/b4
    |       |
  r2|       |c2
    |   b2  |    c4
   c6-------r1-------r6/b5
    \       |
     \    b1|
    r2\     |  b1,r4
       \----c3=======c2
Back to top
View user's profile Send private message
MadOverlord

Joined: 01 Jun 2005
Posts: 80
:
Location: Wilmington, NC, USA

Items
PostPosted: Tue Sep 13, 2005 1:28 am    Post subject: Reply with quote

Lummox JR wrote:
I think I must be misunderstanding part of this algorithm. I have a board where fishy cycles is telling me to eliminate a choice I know is actually part of the solution; eliminating it results in an unsolvable board.


Post the full puzzle; without that, it's impossible for anyone to figure out what's going wrong.

You might also download the Sudoku Susser and run the puzzle through it, it can show you fishy cycles. Single step through the deduction until you hit the fishy cycle, undo 1 step, and Hilight -> Fishy Cycles to see it.

http://www.madoverlord.com/projects/sudoku.t for download links.
Back to top
View user's profile Send private message Visit poster's website AIM Address
Lummox JR

Joined: 07 Sep 2005
Posts: 202
:

Items
PostPosted: Tue Sep 13, 2005 1:55 am    Post subject: Reply with quote

This is the original puzzle:
Code:
. . 8|. . 7|. . .
3 . .|. . .|. . .
. . 5|9 . .|8 2 .
-----------------
. . .|8 . .|5 . .
. . 6|. 9 .|2 . .
. 9 7|. 4 .|. 6 .
-----------------
. . .|. . .|. . .
. 6 .|. 2 .|1 3 .
2 . 9|7 1 .|6 . .


And this is how far I was able to take it. Fishy links gave me the 7 at (8,5), which is confirmed in the solution.
Code:
9 . 8|. . 7|4 . 3
3 . .|. . .|. . 6
6 . 5|9 3 .|8 2 .
-----------------
. . .|8 7 6|5 . .
. . 6|. 9 .|2 7 .
. 9 7|. 4 .|3 6 .
-----------------
. . .|. . .|. . 2
. 6 4|5 2 .|1 3 .
2 . 9|7 1 .|6 . 5


This is what the candidates show:
Code:
9    12   8   |126  56   7   |4    15   3
3    47   12  |124  58   1248|79   159  6
6    47   5   |9    3    14  |8    2    17
-------------------------------------------
14   23   23  |8    7    6   |5    19   149
1458 158  6   |13   9    135 |2    7    148
158  9    7   |12   4    125 |3    6    18
-------------------------------------------
1578 1358 13  |346  68   3489|79   48   2
78   6    4   |5    2    89  |1    3    79
2    38   9   |7    1    348 |6    48   5


Using both fishy links and coloring I believe I can eliminate the 3 at 2,7, but then again I'm not entirely sure I'm applying these techniques correctly. My poor understanding of the technique was leading me to eliminate the 2 at 4,2, but that's not right.
Back to top
View user's profile Send private message
gaby

Joined: 02 Jul 2005
Posts: 120
:

Items
PostPosted: Tue Sep 13, 2005 9:19 am    Post subject: Reply with quote

I can see that you're using b1 as a vertex, and as two edges in that graph. My understanding was that b1 can only appear once in the entire graph, either as an edge or a vertex, not both, and not more than once. If you constrain it this way, what does your solver suggest?
_________________
Free daily sudoku - Online puzzle database
http://vanhegan.net/sudoku/
Back to top
View user's profile Send private message Visit poster's website
MadOverlord

Joined: 01 Jun 2005
Posts: 80
:
Location: Wilmington, NC, USA

Items
PostPosted: Tue Sep 13, 2005 1:10 pm    Post subject: Reply with quote

Lummox JR wrote:
Code:
9 . 8|. . 7|4 . 3
3 . .|. . .|. . 6
6 . 5|9 3 .|8 2 .
-----------------
. . .|8 7 6|5 . .
. . 6|. 9 .|2 7 .
. 9 7|. 4 .|3 6 .
-----------------
. . .|. . .|. . 2
. 6 4|5 2 .|1 3 .
2 . 9|7 1 .|6 . 5



There is a Fishy Cycle in the puzzle at this point, but it is not needed to solve the puzzle. Some more basic techniques plus some forcing chains do the trick.

Code:

* There is a "Fishy Cycle" in the puzzle with link number <7>.

   {R2} -- R2C2 -- (C2) -- R3C2 -- {R3}
   {R3} -- R3C9 -- (C9) -- R8C9 -- {B9}
   {B9} -- R7C7 -- (C7) -- R2C7 -- {R2}

<7> cannot be a possibility for square R7C2.


Quote:

I can see that you're using b1 as a vertex, and as two edges in that graph. My understanding was that b1 can only appear once in the entire graph, either as an edge or a vertex...


Yes, IIRC this is correct.
Back to top
View user's profile Send private message Visit poster's website AIM Address
Lummox JR

Joined: 07 Sep 2005
Posts: 202
:

Items
PostPosted: Tue Sep 13, 2005 9:51 pm    Post subject: Reply with quote

Well, even constraining a house to only appear as a vertex or edge, the 3-cycle r1->c3->c6->r1 (edges are b1, r2, b2) would still seem to be valid. And indeed, the r1->c3 link with b1 as an edge could be sacrificed in favor of the 4-cycle.

I have no idea why this works out the way it does, and there must be some sort of exclusion I'm not seeing since others can get this algorithm to work. The only thing I'm seeing is that c3 and c6 link up in r2 even via the b1->r1->b2 connection, so that the same cells appear more than twice. This seems to be related to the rule that the same house can't be visited more than once, but it seems to me then that that exclusion is actually misstated. The correct rule then should not be that the house may not appear twice in the cycle, but rather that each vertex must not be part of more than 2 houses in the cycle. Counting repeated houses twice, this supercedes the other rule. In Doug's post on the exclusion it looks like this may have been the intent, but wasn't stated in that way. To formalize it:

For every simple closed cycle in a fishy cycle graph, each cell must be part of exactly one vertex and one edge.

This makes sense and, if correct, eliminates my confusion. It also implies directly that the same house cannot be used twice.

Interestingly I was looking back on the talk calling this a superset of swordfish, and I don't think that's entirely accurate. My own understanding of swordfish is that it's an extension of the X-wing technique to 3+ columns or rows, which means that it's basically a positional form of one of the subset rules (which is how my solver approaches it). While X-Wing can be considered a simple fishy cycle, not all potential swordfish can. Leastwise, a traditional swordfish with only 2 choices per row/column could be called a fishy cycle, but with more choices it has to be considered under the subset rule.
Back to top
View user's profile Send private message
Lummox JR

Joined: 07 Sep 2005
Posts: 202
:

Items
PostPosted: Wed Sep 14, 2005 11:57 pm    Post subject: Reply with quote

Brief addendum: I'm not so sure the repeat-house rule is even necessary. Doug posted this example, which by my new reckoning directly violates the above rule:
Code:
abc
---
A..
.B.
..C

The reason this can't form a 3-cycle isn't that the cycle would have to pass repeatedly through r1; it's that the endpoints don't line up in a cyclical way, which was what was screwing up my own attempt to create cycles and why I was so confused. You can't connect c1->c2->c3->c1 without "backing up"; if you go from A to a to b to B to C to c, there's no path from there back to A, and hence no cycle.

Of course, an interesting observation is that there are 3 valid 2-cycles in that example, each of which eliminates one of the pairs. So this situation can never happen in a soluble sudoku board.

By not enforcing the repeat-house rule, but simply looking at how the endpoints meet, you must only be careful when eliminating an edge not to invalidate any cell which is part of the chain.
Back to top
View user's profile Send private message
eclark

Joined: 28 Dec 2005
Posts: 70
:

Items
PostPosted: Wed Dec 28, 2005 1:32 am    Post subject: Reply with quote

Sorry to bump an old thread but I am having trouble implementing fishy cycles. I am trying like a lot of people to make a solver that uses human methods to solve complex puzzles. Right now I am solving about 58% of all randomly generated sudoku's and 24 of the top 95.

I have tried to put the example code into java but for some reason I am never finding connecting links.


here is the code invloved:
Points are just holder classes that hold row and column
Vertexes have two points their type

0 = row
1 = column
2 = square

Edges have three vertexes and two points.
Code:
   @SuppressWarnings("unused")
    private boolean fishy() {
        boolean changed = false;
        makeCount();
        for (int value = 0; value < SIZE; value++) {
            changed = changed || fishyValue(value);
        }
        return false;
    }

    public Point[] pointsPosCol(int value, int col) {
        Point temp[] = new Point[2];
        int found = 0;
        for (int row = 0; row < SIZE; row++) {
            if (board[row][col].contains(value)) {
                temp[found] = new Point(row, col);
                found++;

            }
        }

        return temp;
    }

    public Point[] pointsPosRow(int value, int row) {
        Point temp[] = new Point[2];
        int found = 0;
        for (int col = 0; col < SIZE; col++) {
            if (board[row][col].contains(value)) {
                temp[found] = new Point(row, col);
                found++;

            }
        }

        return temp;
    }

    public Point[] pointsPosSquare(int value, int square_row, int square_col) {
        Point temp[] = new Point[2];
        int found = 0;
        for (int row = (3 * square_row); row < (square_row * 3) + 3; row++) {
            for (int col = (3 * square_col); col < (square_col * 3) + 3; col++) {
                if ((board[row][col].contains(value)) && (board[row][col].getAnswer() == 0)) {
                    temp[found] = new Point(row, col);
                    found++;

                }
            }
        }

        return temp;
    }

    private boolean fishyValue(int value) {
        for (int row = 0; row < 9; row++) {

            if (count_row[row][value] == 2) {
                Vertex temp = new Vertex();
                temp.setType(0);
                temp.setRow(row);
                Point temp_points[] = pointsPosRow(value + 1, row);

                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        for (int col = 0; col < 9; col++) {

            if (count_col[col][value] == 2) {
                Vertex temp = new Vertex();
                temp.setType(1);
                temp.setCol(col);

                Point temp_points[] = pointsPosCol(value + 1, col);
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        for (int i = 0; i < 9; i++) {
            if (count_square[i][value] == 2) {
                Vertex temp = new Vertex();

                temp.setType(2);

                temp.setRow(i / 3);
                temp.setCol(i % 3);

                Point temp_points[] = pointsPosSquare(value + 1, (i / 3), (i % 3));
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        if (vertexes.size() >= 2) {

            // We have more then enough to make a whole cycle so check to see
            // what the vertexes and edges are

            // We are going to check through everyone twice
            for (int j = 0; j < vertexes.size(); j++) {
                for (int k = 0; k < vertexes.size(); k++) {
                    // check to make sure that we are not comparing
                    // a vertex to itself
                    if (j != k) {

                        Vertex one = vertexes.get(j);
                        Vertex two = vertexes.get(k);

                        /*
                         * This is a lot of repeated code but its fast I HOPE
                         */

                        check_fishy_row(one, two);
                        check_fishy_col(one, two);
                        check_fishy_square(one, two);

                    }
                }
            }
            // Here we need to see if the edges and vertexes we found make
            // anything that we can use
            if (edges.size() >= 2) {
                // there is at least enough to make a full cycle
                for (int i = 0; i < edges.size(); i++) {
                    ArrayList<Edge> a = new ArrayList<Edge>();
                    a.add(edges.get(i));
                    find_cycle(a, value);
                }
            }

        }

        return false;
    }

    @SuppressWarnings("unchecked")
    private boolean find_cycle(ArrayList<Edge> pEdges, int value) {

        ArrayList<Edge> cur_edges = (ArrayList<Edge>) pEdges.clone();
        ArrayList<Point> used_points = new ArrayList<Point>();
        ArrayList<Vertex> used_groups = new ArrayList<Vertex>();

        Vertex fVertex = cur_edges.get(0).getFrom();
        Vertex lVertex = cur_edges.get(cur_edges.size() - 1).getTo();

        for (int i = 0; i < cur_edges.size(); i++) {
            /*
             *
             */
            used_groups.add(cur_edges.get(i).getFrom());
            used_groups.add(cur_edges.get(i).getVia());
            /*
             *
             *
             *
             */
            used_points.add(cur_edges.get(i).getStart());
            used_points.add(cur_edges.get(i).getEnd());
        }

        used_groups.add(cur_edges.get(cur_edges.size() - 1).getTo());

        // Now go through every edge and see if there is something that attaches
        // on the
        // end of the current chain.
        for (int i = 0; i < edges.size(); i++) {
            Edge e = edges.get(i);

            if (e.getFrom().equals(lVertex)) {
                /*
                 * Make sure this next edge has not been used before and make
                 * sure that this point has not been used.
                 */
                //System.out.println("Found Something to add onto");
                if (!used_points.contains(e.getStart()) && !used_points.contains(e.getEnd())) {
                    //System.out.println("Found Something to add onto");
                    if (!used_groups.contains(e.getFrom())) {
                        if (!used_groups.contains(e.getTo())) {
                            cur_edges.add(e);
                            System.out.println("Calling find_cycle with cur_edges size => " + cur_edges.size());
                            boolean changed = find_cycle(cur_edges, value);
                            if (changed ) {
                                return changed;
                            }
                        } else {
                            if (e.getTo().equals(fVertex)) {
                                if (cur_edges.size() >1) {
                                    System.out.println("I Found A fishy CYCLE");
                                    return true;
                                }
                            }
                        }
                    }
                } else {
                    System.out.println("NOPE");
                }
            }
        }

        return false;
    }

    private boolean inSameSquare(Point p1, Point p2) {
        return ((p1.getRow() / 3) == (p2.getRow() / 3) && (p1.getCol() / 3) == (p2.getCol() / 3));
    }

    private void check_fishy_square(Vertex one, Vertex two) {
        if ((inSameSquare(one.getP1(), two.getP1())) && !one.getP1().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / 3);
            temp_vertex.setCol(one.getP1().getCol() / 3);

            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP1(), two.getP2())) && !one.getP1().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / 3);
            temp_vertex.setCol(one.getP1().getCol() / 3);

            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((inSameSquare(one.getP2(), two.getP1())) && !one.getP2().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP2().getRow() / 3);
            temp_vertex.setCol(one.getP2().getCol() / 3);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP2(), two.getP2())) && !one.getP2().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP2().getRow() / 3);
            temp_vertex.setCol(one.getP2().getCol() / 3);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

    }

    private void check_fishy_row(Vertex one, Vertex two) {
        if ((one.getP1().getRow() == two.getP1().getRow()) && (one.getP1().getCol() != two.getP1().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() == two.getP2().getRow()) && (one.getP1().getCol() != two.getP2().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);
            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() == two.getP1().getRow()) && (one.getP2().getCol() != two.getP1().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() == two.getP2().getRow()) && (one.getP2().getCol() != two.getP2().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }

    private void check_fishy_col(Vertex one, Vertex two) {
        if ((one.getP1().getRow() != two.getP1().getRow()) && (one.getP1().getCol() == two.getP1().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() != two.getP2().getRow()) && (one.getP1().getCol() == two.getP2().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() != two.getP1().getRow()) && (one.getP2().getCol() == two.getP1().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() != two.getP2().getRow()) && (one.getP2().getCol() == two.getP2().getCol())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setStart(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }



Yes its a lot of repeated code but I was hoping it would be faster than checking every group everytime around.


Currently when run it seems like every edge fails at this line:
if (!used_points.contains(e.getStart()) && !used_points.contains(e.getEnd())) {

From what I can see this should all be right.

I forgot to say its java 5.0


What have I done wrong?
Back to top
View user's profile Send private message
eclark

Joined: 28 Dec 2005
Posts: 70
:

Items
PostPosted: Wed Dec 28, 2005 6:56 am    Post subject: Reply with quote

Well an update, I have gotten father. I was not setting the points correctly in edges the second one was never set as you can see. And I was supposed to test if the via and to were used not the from and to. The from will always be used... blah.


Anyway now I have another problem.... maybe someone will help me see what I am doing wrong. Thanks

Here is my current code:

Code:

    private boolean fishyValue(int value) {
        for (int row = 0; row < 9; row++) {
            edges = new ArrayList<Edge>();
            vertexes = new ArrayList<Vertex>();
            if (count_row[row][value] == 2) {
                Vertex temp = new Vertex();
                temp.setType(0);
                temp.setRow(row);
                Point temp_points[] = pointsPosRow(value + 1, row);
                // System.out.println("[Fishy] Found a row " + row + " for value
                // " + (value+1));

                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);

                vertexes.add(temp);
            }
        }

        for (int col = 0; col < 9; col++) {

            if (count_col[col][value] == 2) {
                Vertex temp = new Vertex();
                temp.setType(1);
                temp.setCol(col);

                // System.out.println("[Fishy] Found a Col " + col + " for value
                // " + (value+1));
                Point temp_points[] = pointsPosCol(value + 1, col);
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        for (int i = 0; i < 9; i++) {
            if (count_square[i][value] == 2) {

                Vertex temp = new Vertex();

                temp.setType(2);

                temp.setRow(i / 3);
                temp.setCol(i % 3);

                // System.out.println("[Fishy] Found a square " +
                // (i/3)+"x"+(i%3) + " for value " + (value+1) );
                Point temp_points[] = pointsPosSquare(value + 1, (i / 3), (i % 3));
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        if (vertexes.size() >= 2) {

            // We have more then enough to make a whole cycle so check to see
            // what the vertexes and edges are

            // We are going to check through everyone twice
            for (int j = 0; j < vertexes.size(); j++) {
                for (int k = 0; k < vertexes.size(); k++) {
                    // check to make sure that we are not comparing
                    // a vertex to itself
                    if (j != k) {

                        Vertex one = vertexes.get(j);
                        Vertex two = vertexes.get(k);

                        /*
                         * This is a lot of repeated code but its fast I HOPE
                         */

                        check_fishy_row(one, two);
                        check_fishy_col(one, two);
                        check_fishy_square(one, two);

                    }
                }
            }
            // Here we need to see if the edges and vertexes we found make
            // anything that we can use
            if (edges.size() >= 2) {
                // there is at least enough to make a full cycle
                for (int i = 0; i < edges.size(); i++) {
                    ArrayList<Edge> a = new ArrayList<Edge>();
                    a.add(edges.get(i));

                    find_cycle(a, value);
                }
            }

        }

        return false;
    }

    @SuppressWarnings("unchecked")
    private boolean find_cycle(ArrayList<Edge> pEdges, int value) {

        ArrayList<Edge> cur_edges = (ArrayList<Edge>) pEdges.clone();
        ArrayList<Point> used_points = new ArrayList<Point>();
        ArrayList<Vertex> used_groups = new ArrayList<Vertex>();

        Vertex fVertex = cur_edges.get(0).getFrom();
        Vertex lVertex = cur_edges.get(cur_edges.size() - 1).getTo();

        // System.out.println("First Vertex = " + fVertex);
        // System.out.println("Last Vertex = " + lVertex);
        for (int i = 0; i < cur_edges.size(); i++) {
            /*
             *
             */

            used_groups.add(cur_edges.get(i).getFrom());
            used_groups.add(cur_edges.get(i).getVia());
            /*
             *
             *
             *
             */
            // System.out.println("[Fishy]Adding Point: "
            // +cur_edges.get(i).getStart() + "to used points vector");
            used_points.add(cur_edges.get(i).getStart());
            // System.out.println("[Fishy]Adding Point: "
            // +cur_edges.get(i).getEnd() + "to used points vector");
            used_points.add(cur_edges.get(i).getEnd());
        }

        used_groups.add(cur_edges.get(cur_edges.size() - 1).getTo());

        // Now go through every edge and see if there is something that attaches
        // on the
        // end of the current chain.
        // System.out.println("For Value = " + value + "Edges has " +
        // edges.size());
        for (int i = 0; i < edges.size(); i++) {
            Edge e = edges.get(i);

            // System.out.println("I = " +i);

            // System.out.println("Last Vertex" + lVertex);
            if (cur_edges.get(cur_edges.size() - 1).getTo().equals(e.getFrom())) {
                /*
                 * Make sure this next edge has not been used before and make
                 * sure that this point has not been used.
                 */
                if (!used_points.contains(e.getStart()) && !used_points.contains(e.getEnd())) {
                    // System.out.println("Found Something to add onto");
                    if (!used_groups.contains(e.getVia())) {
                        if (!used_groups.contains(e.getTo())) {
                            cur_edges.add(e);

                            boolean changed = find_cycle(cur_edges, value);
                            if (changed) {
                                return changed;
                            }
                        } else {
                            if (fVertex.equals(e.getTo())) {
                                if (cur_edges.size() > 1) {
                                    boolean changed = false;
                                    // This is a the closing edge
                                    cur_edges.add(e);

                                    System.out.println("START FISHY FOUND FOR VALUE =" + (value + 1));
                                    Printer.printPos(board);
                                    for (int x = 0; x < cur_edges.size(); x++) {
                                        System.out.println("\t Currently Removing: " + cur_edges.get(x));

                                        changed = changed || removeFromGroup(cur_edges.get(x).getVia(), value);
                                    }

                                    if (changed) {
                                        Printer.printPos(board);
                                        System.out.println("END FISHY CHANGE == TRUE");
                                    } else {
                                        System.out.println("END FISHY CHANGED == FALSE");
                                    }
                                    return changed;
                                }
                            }
                        }
                    }
                }
            }
        }

        return false;
    }

    private boolean removeFromGroup(Vertex via, int value) {

        boolean changed = false;
        if (via.getType() == 0) {
            for (int i = 0; i < SIZE; i++) {
                if ((i != via.getP1().getCol()) && (i != via.getP2().getCol())) {
                    if (board[via.getRow()][i].contains(value + 1)) {
                        changed = true;
                        board[via.getRow()][i].remove(value + 1);
                        System.out.println("\t\t Removed Value @ " + via.getRow() + "x"+i);
                    }
                }
            }
            return changed;
        } else if (via.getType() == 1) {
            for (int i = 0; i < SIZE; i++) {
                if ((i != via.getP1().getRow()) && (i != via.getP2().getRow())) {
                    if (board[i][via.getCol()].contains(value + 1)) {
                        changed = true;
                        board[i][via.getCol()].remove(value + 1);
                        System.out.println("\t\t Removed Value @ " + i + "x"+via.getCol());
                    }
                }
            }
            return changed;
        }
        for (int row = (3 * via.getRow()); row < (3 * via.getRow()) + 3; row++) {
            for (int col = (3 * via.getCol()); col < (3 * via.getCol()) + 3; col++) {
                if ((via.getP1().getRow() != row) || (via.getP1().getCol() != col)) {
                    if ((via.getP2().getRow() != row) || (via.getP2().getCol() != col)) {
                        if (board[row][col].contains(value + 1)) {
                            board[row][col].remove(value + 1);
                            changed = true;
                            System.out.println("\t\t Removed Value @ " + row + "x"+col);
                        }
                    }
                }
            }
           
        }
        return changed;
    }

    private boolean inSameSquare(Point p1, Point p2) {
        return ((p1.getRow() / 3) == (p2.getRow() / 3) && (p1.getCol() / 3) == (p2.getCol() / 3));
    }

    private void check_fishy_square(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }
        if ((inSameSquare(one.getP1(), two.getP1())) && !one.getP1().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / 3);
            temp_vertex.setCol(one.getP1().getCol() / 3);

            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            // System.out.println("[Fishy] Found a Square " + one.getP1() +" is
            // in the same box as " + two.getP1());
            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP1(), two.getP2())) && !one.getP1().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / 3);
            temp_vertex.setCol(one.getP1().getCol() / 3);

            // System.out.println("[Fishy] Found a Square " + one.getP1() +" is
            // in the same box as " + two.getP2());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((inSameSquare(one.getP2(), two.getP1())) && !one.getP2().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            // System.out.println("[Fishy] Found a Square " + one.getP2() +" is
            // in the same box as " + two.getP1());
            temp_vertex.setRow(one.getP2().getRow() / 3);
            temp_vertex.setCol(one.getP2().getCol() / 3);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP2(), two.getP2())) && !one.getP2().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);
            // System.out.println("[Fishy] Found a Square " + one.getP2() +" is
            // in the same box as " + two.getP2());
            temp_vertex.setRow(one.getP2().getRow() / 3);
            temp_vertex.setCol(one.getP2().getCol() / 3);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

    }

    private void check_fishy_row(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }
        if ((one.getP1().getRow() == two.getP1().getRow()) && (one.getP1().getCol() != two.getP1().getCol())) {

            // System.out.println("[Fishy] "+one.getP1() + "is in the same row
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() == two.getP2().getRow()) && (one.getP1().getCol() != two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same row
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);
            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() == two.getP1().getRow()) && (one.getP2().getCol() != two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same row
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() == two.getP2().getRow()) && (one.getP2().getCol() != two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same row
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }

    private void check_fishy_col(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }
        if ((one.getP1().getRow() != two.getP1().getRow()) && (one.getP1().getCol() == two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same col
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() != two.getP2().getRow()) && (one.getP1().getCol() == two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same col
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() != two.getP1().getRow()) && (one.getP2().getCol() == two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same col
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() != two.getP2().getRow()) && (one.getP2().getCol() == two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same col
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }

Its doing pertty well and removing lots of the stuff but not quite enough to solve the whole puzzle. Even though if I turn on my x-wing only code it solves quite happily.

Here is the puzzle and the resulting output:
Code:
Puzzle #0
. . 1 | 8 . 3 | 6 . .
5 . . | 2 . . | . . .
. . . | 7 9 . | . . .
------+-------+-------
9 7 3 | 1 2 8 | 5 . .
2 8 5 | 9 6 4 | 3 1 7
. . 4 | 5 3 7 | 2 9 8
------+-------+-------
. . . | . 1 5 | . . .
. . . | . . 9 | . . 3
. . 6 | 3 . 2 | 4 . .

START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     369   789    | 2     4     16     | 1789  378   19   
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  2349  2789   | 46    1     5      | 789   2678  269   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x0 [8x1 6x2]} => Col: 2 [1x2 6x2]
       Removed Value @ 6x1
    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Row: 1 [1x2 1x6]} => Col: 6 [1x6 6x6]
    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Square: 2x2 [6x6 8x8]} => Row: 8 [8x1 8x8]
47    249   1      | 8     5     3      | 6     247   249   
5     369   789    | 2     4     16     | 1789  378   19   
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  269   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

END FISHY CHANGE == TRUE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     369   789    | 2     4     16     | 1789  378   19   
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  269   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x2 [8x8 6x6]} => Col: 6 [1x6 6x6]
       Removed Value @ 6x8
    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Row: 1 [1x6 1x2]} => Col: 2 [1x2 6x2]
    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Square: 2x0 [6x2 8x1]} => Row: 8 [8x1 8x8]
47    249   1      | 8     5     3      | 6     247   249   
5     369   789    | 2     4     16     | 1789  378   19   
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

END FISHY CHANGE == TRUE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     369   789    | 2     4     16     | 1789  378   19   
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Square: 2x0 [6x2 8x1]} => Row: 8 [8x1 8x8]
    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x2 [8x8 6x6]} => Col: 6 [1x6 6x6]
    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Row: 1 [1x6 1x2]} => Col: 2 [1x2 6x2]
       Removed Value @ 1x1
       Removed Value @ 1x8
47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

END FISHY CHANGE == TRUE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Row: 1 [1x2 1x6]} => Col: 6 [1x6 6x6]
    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Square: 2x2 [6x6 8x8]} => Row: 8 [8x1 8x8]
    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x0 [8x1 6x2]} => Col: 2 [1x2 6x2]
END FISHY CHANGED == FALSE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Square: 2x2 [6x6 8x8]} => Row: 8 [8x1 8x8]
    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x0 [8x1 6x2]} => Col: 2 [1x2 6x2]
    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Row: 1 [1x2 1x6]} => Col: 6 [1x6 6x6]
END FISHY CHANGED == FALSE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Square: 2x2 [6x6 8x8]} => Row: 8 [8x1 8x8]
    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x0 [8x1 6x2]} => Col: 2 [1x2 6x2]
    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Row: 1 [1x2 1x6]} => Col: 6 [1x6 6x6]
END FISHY CHANGED == FALSE
START FISHY FOUND FOR VALUE =9
47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   

    Currently Removing: Col: 6 [1x6 6x6] =>  via: { Row: 1 [1x6 1x2]} => Col: 2 [1x2 6x2]
    Currently Removing: Col: 2 [1x2 6x2] =>  via: { Square: 2x0 [6x2 8x1]} => Row: 8 [8x1 8x8]
    Currently Removing: Row: 8 [8x1 8x8] =>  via: { Square: 2x2 [8x8 6x6]} => Col: 6 [1x6 6x6]
END FISHY CHANGED == FALSE
. . 1 | 8 5 3 | 6 . .
5 . . | 2 4 . | . . 1
. . . | 7 9 . | . . .
------+-------+-------
9 7 3 | 1 2 8 | 5 . .
2 8 5 | 9 6 4 | 3 1 7
. . 4 | 5 3 7 | 2 9 8
------+-------+-------
. . . | . 1 5 | . . .
. . . | . . 9 | . . 3
. . 6 | 3 . 2 | 4 . .

47    249   1      | 8     5     3      | 6     247   249   
5     36    789    | 2     4     16     | 1789  378   1     
3468  2346  28     | 7     9     16     | 18    23458 1245 
------------------------------------------------------------
9     7     3      | 1     2     8      | 5     46    46   
2     8     5      | 9     6     4      | 3     1     7     
16    16    4      | 5     3     7      | 2     9     8     
------------------------------------------------------------
3478  234   2789   | 46    1     5      | 789   2678  26   
1478  1245  278    | 46    78    9      | 178   25678 3     
178   159   6      | 3     78    2      | 4     578   159   


Stats
Nodes:         243
Removals:      256
Claimed Rows/Columns:   0
Revomals From Twins:   0
Revomals From Triplets:   0
Revomals From Quads:   0
Revomals From Xwings:   0
Dificulty:      25600
Time:         472ms

Solved:    0/1
Not Solved:   1/1
Nodes:   243
Nodes Per Second:   514.8305084745763
Average unSolved Dificulty:   25600
Posibilites Left:   115   Average Left: 115
Total Time:   472ms    Average Time      472ms
Total Claimed:   0    Average Claimed:   0
Total Twins:   0    Average Twins:      0
Total Trips:   0    Average Trips:      0
Total Quads:   0    Average Quads:      0
Total Xwings:   0    Average Xwings:      0.0
30000: 0   30500: 0   31000: 0   31500: 0   
32000: 0   32500: 0   33000: 0   33500: 0   
34000: 0   34500: 0   35000: 0   35500: 0   
36000: 0   36500: 0   37000: 0   37500: 0   
38000: 0   38500: 0   39000: 0   39500: 0   
40000: 0   40500: 0   41000: 0   41500: 0   
42000: 0   42500: 0   43000: 0   43500: 0   
44000: 0   44500: 0   45000: 0   45500: 0   
46000: 0   46500: 0   47000: 0   47500: 0   
48000: 0   48500: 0   49000: 0   49500: 0   
50000: 0   50500: 0   51000: 0   51500: 0   
52000: 0   52500: 0   53000: 0   53500: 0   
54000: 0   54500: 0   55000: 0   55500: 0   
56000: 0   56500: 0   57000: 0   57500: 0   
58000: 0   58500: 0   59000: 0   59500: 0   
60000: 0   60500: 0   61000: 0   61500: 0   
62000: 0   62500: 0   63000: 0   63500: 0   
64000: 0   64500: 0   65000: 0   65500: 0   
66000: 0   66500: 0   67000: 0   67500: 0   
68000: 0   68500: 0   69000: 0   69500: 0   
70000: 0   70500: 0   71000: 0   71500: 0   
72000: 0   72500: 0   73000: 0   73500: 0   
74000: 0   74500: 0   75000: 0   75500: 0   
76000: 0   76500: 0   77000: 0   77500: 0   
78000: 0   78500: 0   79000: 0   79500: 0   



Sorry the output is not more descriptive about parts but I haven't put in the logger yet as I need to get this stuff working first.
Back to top
View user's profile Send private message
eclark

Joined: 28 Dec 2005
Posts: 70
:

Items
PostPosted: Thu Dec 29, 2005 12:45 am    Post subject: Reply with quote

Well I am a lot farther then I was but I need some help.. Big suprise I know....
I am runing the top 1011 through my solver and I have 6 that cause errors.

Here is one.
what is wrong with this?
Code:

START FISHY FOUND FOR VALUE =7
349   49    345    | 8     1     6      | 25    245   7     
146   1468  14568  | 7     24    245    | 9     3     456   
2     46    7      | 349   49    345    | 156   1456  8     
------------------------------------------------------------
8     3     9      | 246   5     1      | 267   2467  246   
46    7     246    | 2469  3     8      | 256   24569 1     
5     1246  1246   | 2469  24679 247    | 8     2469  3     
------------------------------------------------------------
7     12469 12346  | 2346  246   234    | 12356 8     2569 
3469  5     23468  | 1     24678 2347   | 2367  267   269   
136   1268  12368  | 5     2678  9      | 4     1267  26   

         Currently Removing: Col: 5 [5x5 7x5] =>  via: { Row: 7 [7x5 7x6]} => Col: 6 [3x6 7x6]
Removing 7@7x4
Removing 7@7x7
         Currently Removing: Col: 6 [3x6 7x6] =>  via: { Row: 3 [3x6 3x7]} => Square: 1x2 [3x6 3x7]
         Currently Removing: Square: 1x2 [3x6 3x7] =>  via: { Col: 7 [3x7 8x7]} => Row: 8 [8x4 8x7]
         Currently Removing: Row: 8 [8x4 8x7] =>  via: { Col: 4 [8x4 5x4]} => Square: 1x1 [5x4 5x5]
         Currently Removing: Square: 1x1 [5x4 5x5] =>  via: { Row: 5 [5x4 5x5]} => Col: 5 [5x5 7x5]
349   49    345    | 8     1     6      | 25    245   7     
146   1468  14568  | 7     24    245    | 9     3     456   
2     46    7      | 349   49    345    | 156   1456  8     
------------------------------------------------------------
8     3     9      | 246   5     1      | 267   2467  246   
46    7     246    | 2469  3     8      | 256   24569 1     
5     1246  1246   | 2469  24679 247    | 8     2469  3     
------------------------------------------------------------
7     12469 12346  | 2346  246   234    | 12356 8     2569 
3469  5     23468  | 1     2468  2347   | 2367  26    269   
136   1268  12368  | 5     2678  9      | 4     1267  26   

END FISHY CHANGE == TRUE


after that simple removals result in
Code:

9 4 3 | 8 1 6 | 2 5 7
1 8 5 | 7 4 2 | 9 3 6
2 6 7 | 3 9 5 | 1 4 8
------+-------+-------
8 3 9 | 6 5 1 | 6 2 4
6 7 4 | 9 3 8 | 5 9 1
5 2 1 | 4 7 7 | 8 9 3
------+-------+-------
7 9 6 | 2 6 4 | 3 8 5
4 5 2 | 1 8 3 | 7 6 9
3 1 8 | 5 6 9 | 4 7 2

Which obviously can't happen but to me the cycle seems like it is valid.
Back to top
View user's profile Send private message
eclark

Joined: 28 Dec 2005
Posts: 70
:

Items
PostPosted: Thu Dec 29, 2005 3:29 am    Post subject: Reply with quote

YAY I have it done
Back to top
View user's profile Send private message
eclark

Joined: 28 Dec 2005
Posts: 70
:

Items
PostPosted: Sat Jan 07, 2006 6:45 am    Post subject: Reply with quote

Well after a lot of work here is my version of fishy cycles. If I forgot to include any functions just send me a message. Or if you have anything that betters my code.

Code:
    private boolean fishy() {
        boolean changed = false;

        makeCount();
        for (int value = 0; value < SIZE; value++) {
            int count = countPos(value + 1);
            changed = changed || fishyValue(value);
            if (count != countPos(value + 1)) {
                changed = true;
            }
        }
        return changed;
    }

   private boolean fishyValue(int value) {
        // System.out.println("[Fishy] Value = " +(value+1));
        for (int row = 0; row < SIZE; row++) {
            edges = new ArrayList<Edge>();
            vertexes = new ArrayList<Vertex>();
            if (countRow(value + 1, row) == 2) {
                Vertex temp = new Vertex();
                temp.setType(0);
                temp.setRow(row);
                Point temp_points[] = pointsPosRow(value + 1, row);
                // System.out.println("[Fishy] Found a row " + row + " for value
                // " + (value+1));

                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);

                vertexes.add(temp);
            }
        }

        for (int col = 0; col < SIZE; col++) {

            if (countCol(value + 1, col) == 2) {
                Vertex temp = new Vertex();
                temp.setType(1);
                temp.setCol(col);

                Point temp_points[] = pointsPosCol(value + 1, col);
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        for (int i = 0; i < SIZE; i++) {
            if (count_square[i][value] == 2) {

                Vertex temp = new Vertex();

                temp.setType(2);

                temp.setRow(i / HOUSE_SIZE);
                temp.setCol(i % HOUSE_SIZE);

                // System.out.println("[Fishy] Found a square " +
                // (i/3)+"x"+(i%3) + " for value " + (value+1) );
                Point temp_points[] = pointsPosSquare(value + 1, (i / HOUSE_SIZE), (i % HOUSE_SIZE));
                temp.setP1(temp_points[0]);
                temp.setP2(temp_points[1]);
                vertexes.add(temp);
            }
        }

        if (vertexes.size() >= 2) {

            // We have more then enough to make a whole cycle so check to see
            // what the vertexes and edges are

            // We are going to check through everyone twice
            for (int j = 0; j < vertexes.size(); j++) {
                for (int k = 0; k < vertexes.size(); k++) {
                    // check to make sure that we are not comparing
                    // a vertex to itself
                    if (j != k) {

                        Vertex one = vertexes.get(j);
                        Vertex two = vertexes.get(k);

                        /*
                         * This is a lot of repeated code but its fast I HOPE
                         */

                        check_fishy_row(one, two);
                        check_fishy_col(one, two);
                        check_fishy_square(one, two);

                    }
                }
            }
            // Here we need to see if the edges and vertexes we found make
            // anything that we can use
            if (edges.size() >= 2) {
                // there is at least enough to make a full cycle
                for (int i = 0; i < edges.size(); i++) {
                    ArrayList<Edge> a = new ArrayList<Edge>();
                    a.add(edges.get(i));
                    find_cycle(a, value);
                }
            }

        }

        return false;
    }
  private boolean checkVertexOverlap(Vertex one, Vertex two) {
        if (one.getP1().equals(two.getP1())) {
            if (one.getP2().equals(two.getP2())) {
                return true;
            }
        } else if (one.getP1().equals(two.getP2())) {
            if (one.getP2().equals(two.getP1())) {
                return true;
            }
        }
        return false;
    }

    private boolean containsPoint(Point check, ArrayList<Edge> list) {
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).getEnd().equals(check) || list.get(i).getStart().equals(check)) {
                return true;
            }
        }
        return false;
    }

    private boolean checkVia(ArrayList<Edge> pEdges, Edge check) {

        Vertex via = check.getVia();

        for (int i = 0; i < pEdges.size(); i++) {
            if (pEdges.get(i).getFrom().equals(via) || pEdges.get(i).getTo().equals(via)
                    || pEdges.get(i).getVia().equals(via)) {
                return false;
            }

        }
        return true;
    }

    private boolean checkTo(ArrayList<Edge> pEdges, Edge check) {
        for (int i = 0; i < pEdges.size(); i++) {
            if (pEdges.get(i).getFrom().equals(check.getTo()) || pEdges.get(i).getTo().equals(check.getTo())
                    || pEdges.get(i).getVia().equals(check.getTo())) {
                return false;
            }
        }
        return true;

    }

    private boolean find_cycle(ArrayList<Edge> pEdges, int value) {

        ArrayList<Edge> cur_edges = (ArrayList<Edge>) pEdges.clone();

        ArrayList<Vertex> used_groups = new ArrayList<Vertex>();

        Vertex fVertex = cur_edges.get(0).getFrom();
        for (int i = 0; i < cur_edges.size(); i++) {

            used_groups.add(cur_edges.get(i).getFrom());
            used_groups.add(cur_edges.get(i).getVia());

        }
        used_groups.add(cur_edges.get(cur_edges.size() - 1).getTo());

        // Now go through every edge and see if there is something that attaches
        // on the
        // end of the current chain.
        for (int i = 0; i < edges.size(); i++) {
            Edge e = edges.get(i);

            if (cur_edges.get(cur_edges.size() - 1).getTo().equals(e.getFrom())) {
                /*
                 * Make sure this next edge has not been used before and make
                 * sure that this point has not been used.
                 */

                if ((!containsPoint(e.getStart(), cur_edges) && !containsPoint(e.getEnd(), cur_edges))) {
                    // check to make sure that the linking edge hasn't been used
                    // before and that
                    // the points used aren't special cases.
                    if ((checkVia(cur_edges, e)) && !checkVertexOverlap(e.getVia(), e.getTo())
                            && !checkVertexOverlap(e.getVia(), e.getFrom())) {
                        if (checkTo(cur_edges, e)) {
                            cur_edges.add(e);

                            boolean changed = find_cycle(cur_edges, value);
                            if (changed) {
                                return changed;
                            }
                        } else {
                            if (fVertex.equals(e.getTo())) {
                                if (cur_edges.size() > 1) {
                                    boolean changed = false;
                                    // This is a the closing edge
                                    cur_edges.add(e);
                                    for (int x = 0; x < cur_edges.size(); x++) {
                                        // System.out.println(x+" : " +
                                        // cur_edges.get(x));
                                        changed = changed
                                                || removeFromGroup(cur_edges.get(x).getVia(), cur_edges, value);
                                    }
                                    return changed;
                                }
                            }
                        }
                    }

                }
            }
        }

        return false;
    }

    private boolean removeFromGroup(Vertex via, ArrayList<Edge> edges, int value) {

        boolean changed = false;
        if (via.getType() == 0) {
            for (int i = 0; i < SIZE; i++) {
                if ((i != via.getP1().getCol()) && (i != via.getP2().getCol())) {
                    if (board[via.getRow()][i].contains(value + 1) && !containsPoint(new Point(via.getRow(), i), edges)) {
                        changed = true;
                        // System.out.println("\tRemoving
                        // "+(value+1)+"@"+via.getRow()+"x"+i);
                        board[via.getRow()][i].remove(value + 1);
                        stats.incrementFishy();
                    }
                }
            }
            return changed;
        } else if (via.getType() == 1) {
            for (int i = 0; i < SIZE; i++) {
                if ((i != via.getP1().getRow()) && (i != via.getP2().getRow())
                        && !containsPoint(new Point(i, via.getCol()), edges)) {
                    if (board[i][via.getCol()].contains(value + 1)) {
                        changed = true;
                        // System.out.println("\tRemoving
                        // "+(value+1)+"@"+i+"x"+via.getCol());
                        board[i][via.getCol()].remove(value + 1);
                        stats.incrementFishy();
                    }
                }
            }
            return changed;
        }
        for (int row = (HOUSE_SIZE * via.getRow()); row < (HOUSE_SIZE * via.getRow()) + HOUSE_SIZE; row++) {
            for (int col = (HOUSE_SIZE * via.getCol()); col < (HOUSE_SIZE * via.getCol()) + HOUSE_SIZE; col++) {
                if ((via.getP1().getRow() != row) || (via.getP1().getCol() != col)) {
                    if ((via.getP2().getRow() != row) || (via.getP2().getCol() != col)) {
                        if (board[row][col].contains(value + 1) && !containsPoint(new Point(row, col), edges)) {
                            board[row][col].remove(value + 1);
                            // System.out.println("\tRemoving
                            // "+(value+1)+"@"+row+"x"+col);
                            changed = true;
                            stats.incrementFishy();
                        }
                    }
                }
            }

        }
        return changed;
    }

    private boolean inSameSquare(Point p1, Point p2) {
        return ((p1.getRow() / 3) == (p2.getRow() / 3) && (p1.getCol() / 3) == (p2.getCol() / 3));
    }

    private void check_fishy_square(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }
        if ((inSameSquare(one.getP1(), two.getP1())) && !one.getP1().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / HOUSE_SIZE);
            temp_vertex.setCol(one.getP1().getCol() / HOUSE_SIZE);

            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());
            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            // System.out.println("[Fishy] Found a Square " + one.getP1() +" is
            // in the same box as " + two.getP1());
            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP1(), two.getP2())) && !one.getP1().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            temp_vertex.setRow(one.getP1().getRow() / HOUSE_SIZE);
            temp_vertex.setCol(one.getP1().getCol() / HOUSE_SIZE);

            // System.out.println("[Fishy] Found a Square " + one.getP1() +" is
            // in the same box as " + two.getP2());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((inSameSquare(one.getP2(), two.getP1())) && !one.getP2().equals(two.getP1())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);

            // System.out.println("[Fishy] Found a Square " + one.getP2() +" is
            // in the same box as " + two.getP1());
            temp_vertex.setRow(one.getP2().getRow() / HOUSE_SIZE);
            temp_vertex.setCol(one.getP2().getCol() / HOUSE_SIZE);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((inSameSquare(one.getP2(), two.getP2())) && !one.getP2().equals(two.getP2())) {
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(2);
            // System.out.println("[Fishy] Found a Square " + one.getP2() +" is
            // in the same box as " + two.getP2());
            temp_vertex.setRow(one.getP2().getRow() / HOUSE_SIZE);
            temp_vertex.setCol(one.getP2().getCol() / HOUSE_SIZE);

            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

    }

    private void check_fishy_row(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }

        if ((one.getP1().getRow() == two.getP1().getRow()) && (one.getP1().getCol() != two.getP1().getCol())) {

            // System.out.println("[Fishy] "+one.getP1() + "is in the same row
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() == two.getP2().getRow()) && (one.getP1().getCol() != two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same row
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP1().getRow());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);
            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() == two.getP1().getRow()) && (one.getP2().getCol() != two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same row
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() == two.getP2().getRow()) && (one.getP2().getCol() != two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same row
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(0);
            temp_vertex.setRow(one.getP2().getRow());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }

    private void check_fishy_col(Vertex one, Vertex two) {
        if (one.getP1() == null || (one.getP2() == null) || two.getP1() == null || two.getP2() == null) {
            return;
        }
        if ((one.getP1().getRow() != two.getP1().getRow()) && (one.getP1().getCol() == two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same col
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP1().getRow() != two.getP2().getRow()) && (one.getP1().getCol() == two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP1() + "is in the same col
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP1().getCol());
            temp_vertex.setP1(one.getP1());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP1());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        }

        if ((one.getP2().getRow() != two.getP1().getRow()) && (one.getP2().getCol() == two.getP1().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same col
            // as " + two.getP1());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP1());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP1());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);

        } else if ((one.getP2().getRow() != two.getP2().getRow()) && (one.getP2().getCol() == two.getP2().getCol())) {
            // System.out.println("[Fishy] "+one.getP2() + "is in the same col
            // as " + two.getP2());
            Vertex temp_vertex = new Vertex();
            temp_vertex.setType(1);
            temp_vertex.setCol(one.getP2().getCol());
            temp_vertex.setP1(one.getP2());
            temp_vertex.setP2(two.getP2());

            Edge temp_edge = new Edge();
            temp_edge.setStart(one.getP2());
            temp_edge.setEnd(two.getP2());

            temp_edge.setFrom(one);
            temp_edge.setTo(two);
            temp_edge.setVia(temp_vertex);

            edges.add(temp_edge);
        }
    }
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Solving sudoku All times are GMT
Goto page Previous  1, 2, 3
Page 3 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Sudoku Programmers topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group

Igloo Theme Version 1.0 :: Created By: Andrew Charron