sudoku - sudoku_test.go

package sudoku

import "testing"

/*func TestMakeBox(t *testing.T) {
	ts9 := make([]Constraint, 0, 27)
	ts9 = append(ts9, MakeBox(9, 9, 9, 1)...)
	ts9 = append(ts9, MakeBox(9, 9, 1, 9)...)
	ts9 = append(ts9, MakeBox(9, 9, 3, 3)...)
	if len(ts9) != 27 {
		t.Errorf("expecing length of 27, got %d", len(ts9))
	} else {
		for i, s := range ts9 {
			if len(s) != 9 {
				t.Errorf("section %d, expecing length of 9, got %d", i, len(s))
				continue
			}
			for j, u := range s {
				if u != s9[i][j] {
					t.Errorf("section %d, entry %d, expecing %d, got %d", i, j, s9[i][j], u)
				}
			}
		}
	}
	ts4 := make([]Constraint, 0, 12)
	ts4 = append(ts4, MakeBox(4, 4, 4, 1)...)
	ts4 = append(ts4, MakeBox(4, 4, 1, 4)...)
	ts4 = append(ts4, MakeBox(4, 4, 2, 2)...)
	if len(ts4) != 12 {
		t.Errorf("expecing length of 16, got %d", len(ts4))
	} else {
		for i, s := range ts4 {
			if len(s) != 4 {
				t.Errorf("section %d, expecing length of 4, got %d", i, len(s))
				continue
			}
			for j, u := range s {
				if u != s4[i][j] {
					t.Errorf("section %d, entry %d, expecing %d, got %d", i, j, s4[i][j], u)
				}
			}
		}
	}
}*/

func Test4(t *testing.T) {
	t.Parallel()
	tests := []struct {
		start, solution []int
		solveable       bool
	}{
		{
			[]int{
				2, 0, 0, 1,
				0, 4, 3, 0,
				0, 2, 1, 0,
				3, 0, 0, 4,
			},
			[]int{
				2, 3, 4, 1,
				1, 4, 3, 2,
				4, 2, 1, 3,
				3, 1, 2, 4,
			},
			true,
		},
		{
			[]int{
				4, 0, 1, 0,
				1, 0, 2, 0,
				0, 4, 0, 1,
				0, 1, 0, 2,
			},
			[]int{
				4, 2, 1, 3,
				1, 3, 2, 4,
				2, 4, 3, 1,
				3, 1, 4, 2,
			},
			true,
		},
	}
	for i, test := range tests {
		solved := Solve4(test.start)
		if test.solveable {
			if solved {
				for j, num := range test.start {
					if num != test.solution[j] {
						t.Errorf("solution found does not match solution given for test %d", i)
						break
					}
				}
			} else {
				t.Errorf("didn't find solution in puzzle %d when solution expected", i+1)
			}
		} else {
			if solved {
				t.Errorf("found solution in puzzle %d when no solution expected", i+1)
			}
		}
	}
}

func Test9(t *testing.T) {
	t.Parallel()
	tests := []struct {
		start, solution []int
		solveable       bool
	}{
		{
			[]int{
				0, 0, 0, 0, 9, 5, 0, 0, 6,
				0, 0, 0, 0, 0, 0, 4, 5, 0,
				0, 8, 0, 0, 6, 3, 0, 9, 0,
				0, 3, 0, 0, 0, 0, 0, 0, 2,
				0, 0, 7, 0, 2, 0, 6, 0, 0,
				5, 0, 0, 0, 0, 0, 0, 8, 0,
				0, 9, 0, 2, 7, 0, 0, 6, 0,
				0, 1, 4, 0, 0, 0, 0, 0, 0,
				6, 0, 0, 1, 8, 0, 0, 0, 0,
			},
			[]int{
				4, 7, 1, 8, 9, 5, 2, 3, 6,
				3, 6, 9, 7, 1, 2, 4, 5, 8,
				2, 8, 5, 4, 6, 3, 1, 9, 7,
				1, 3, 8, 6, 5, 7, 9, 4, 2,
				9, 4, 7, 3, 2, 8, 6, 1, 5,
				5, 2, 6, 9, 4, 1, 7, 8, 3,
				8, 9, 3, 2, 7, 4, 5, 6, 1,
				7, 1, 4, 5, 3, 6, 8, 2, 9,
				6, 5, 2, 1, 8, 9, 3, 7, 4,
			},
			true,
		},
		{
			[]int{
				9, 5, 0, 0, 7, 2, 0, 0, 0,
				0, 1, 0, 0, 0, 8, 0, 0, 0,
				7, 0, 8, 0, 0, 0, 5, 0, 1,
				2, 0, 6, 9, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 6, 4, 0, 7,
				8, 0, 1, 0, 0, 0, 7, 0, 4,
				0, 0, 0, 7, 0, 0, 0, 6, 0,
				0, 0, 0, 2, 1, 0, 0, 5, 3,
			},
			[]int{
				9, 5, 4, 1, 7, 2, 6, 3, 8,
				6, 1, 3, 4, 5, 8, 9, 7, 2,
				7, 2, 8, 6, 9, 3, 5, 4, 1,
				2, 7, 6, 9, 4, 1, 3, 8, 5,
				1, 4, 5, 8, 3, 7, 2, 9, 6,
				3, 8, 9, 5, 2, 6, 4, 1, 7,
				8, 9, 1, 3, 6, 5, 7, 2, 4,
				5, 3, 2, 7, 8, 4, 1, 6, 9,
				4, 6, 7, 2, 1, 9, 8, 5, 3,
			},
			true,
		},
		{
			[]int{
				0, 0, 0, 7, 0, 9, 0, 6, 0,
				2, 0, 3, 0, 0, 0, 5, 0, 0,
				0, 0, 0, 8, 0, 0, 0, 2, 0,
				0, 0, 7, 0, 4, 0, 0, 0, 3,
				0, 5, 0, 3, 0, 8, 0, 4, 0,
				3, 0, 0, 0, 7, 0, 9, 0, 0,
				0, 1, 0, 0, 0, 2, 0, 0, 0,
				0, 0, 2, 0, 0, 0, 6, 0, 8,
				0, 3, 0, 9, 0, 4, 0, 0, 0,
			},
			[]int{
				8, 4, 5, 7, 2, 9, 3, 6, 1,
				2, 7, 3, 4, 6, 1, 5, 8, 9,
				1, 6, 9, 8, 5, 3, 7, 2, 4,
				9, 2, 7, 1, 4, 6, 8, 5, 3,
				6, 5, 1, 3, 9, 8, 2, 4, 7,
				3, 8, 4, 2, 7, 5, 9, 1, 6,
				7, 1, 8, 6, 3, 2, 4, 9, 5,
				4, 9, 2, 5, 1, 7, 6, 3, 8,
				5, 3, 6, 9, 8, 4, 1, 7, 2,
			},
			true,
		},
		{
			[]int{
				0, 1, 0, 0, 3, 0, 0, 0, 0,
				7, 5, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 2, 0, 8, 6, 4, 0, 0,
				6, 0, 0, 0, 0, 1, 0, 2, 0,
				0, 0, 5, 0, 0, 0, 7, 0, 0,
				0, 9, 0, 4, 0, 0, 0, 0, 1,
				0, 0, 4, 2, 6, 0, 1, 0, 0,
				0, 0, 0, 0, 0, 0, 0, 6, 9,
				0, 0, 0, 0, 5, 0, 0, 4, 0,
			},
			[]int{
				4, 1, 8, 5, 3, 2, 9, 7, 6,
				7, 5, 6, 9, 1, 4, 8, 3, 2,
				9, 3, 2, 7, 8, 6, 4, 1, 5,
				6, 8, 7, 3, 9, 1, 5, 2, 4,
				1, 4, 5, 6, 2, 8, 7, 9, 3,
				2, 9, 3, 4, 7, 5, 6, 8, 1,
				3, 7, 4, 2, 6, 9, 1, 5, 8,
				5, 2, 1, 8, 4, 7, 3, 6, 9,
				8, 6, 9, 1, 5, 3, 2, 4, 7,
			},
			true,
		},
		{
			[]int{
				0, 6, 0, 0, 4, 7, 0, 5, 0,
				8, 0, 0, 0, 0, 5, 4, 6, 0,
				0, 0, 2, 0, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 8, 0, 4, 0,
				0, 8, 0, 0, 3, 0, 0, 2, 0,
				0, 1, 0, 2, 0, 0, 0, 0, 0,
				0, 0, 0, 0, 0, 0, 5, 0, 0,
				0, 3, 4, 5, 0, 0, 0, 0, 1,
				0, 2, 0, 6, 8, 0, 0, 3, 0,
			},
			[]int{
				3, 6, 1, 8, 4, 7, 2, 5, 9,
				8, 9, 7, 1, 2, 5, 4, 6, 3,
				5, 4, 2, 9, 6, 3, 8, 1, 7,
				2, 5, 3, 7, 9, 8, 1, 4, 6,
				7, 8, 6, 4, 3, 1, 9, 2, 5,
				4, 1, 9, 2, 5, 6, 3, 7, 8,
				6, 7, 8, 3, 1, 4, 5, 9, 2,
				9, 3, 4, 5, 7, 2, 6, 8, 1,
				1, 2, 5, 6, 8, 9, 7, 3, 4,
			},
			true,
		},
		{
			[]int{
				4, 0, 7, 0, 0, 0, 2, 8, 0,
				0, 0, 1, 0, 5, 0, 0, 0, 0,
				8, 6, 0, 0, 0, 7, 0, 0, 0,
				0, 0, 2, 0, 0, 0, 0, 0, 3,
				0, 0, 0, 5, 8, 1, 0, 0, 0,
				1, 0, 0, 0, 0, 0, 9, 0, 0,
				0, 0, 0, 6, 0, 0, 0, 4, 7,
				0, 0, 0, 0, 7, 0, 5, 0, 0,
				0, 7, 6, 0, 0, 0, 1, 0, 2,
			},
			[]int{
				4, 9, 7, 3, 1, 6, 2, 8, 5,
				3, 2, 1, 4, 5, 8, 6, 7, 9,
				8, 6, 5, 2, 9, 7, 4, 3, 1,
				7, 5, 2, 9, 6, 4, 8, 1, 3,
				6, 3, 9, 5, 8, 1, 7, 2, 4,
				1, 8, 4, 7, 3, 2, 9, 5, 6,
				9, 1, 8, 6, 2, 5, 3, 4, 7,
				2, 4, 3, 1, 7, 9, 5, 6, 8,
				5, 7, 6, 8, 4, 3, 1, 9, 2,
			},
			true,
		},
		{
			[]int{
				0, 0, 0, 0, 0, 0, 0, 9, 0,
				0, 3, 0, 5, 0, 9, 8, 0, 0,
				0, 9, 2, 0, 0, 1, 0, 6, 0,
				9, 0, 0, 4, 0, 0, 0, 0, 5,
				0, 0, 0, 1, 0, 5, 0, 0, 0,
				4, 0, 0, 0, 0, 8, 0, 0, 1,
				0, 2, 0, 8, 0, 0, 3, 1, 0,
				0, 0, 1, 6, 0, 3, 0, 4, 0,
				0, 7, 0, 0, 0, 0, 0, 0, 0,
			},
			[]int{
				5, 4, 8, 2, 6, 7, 1, 9, 3,
				1, 3, 6, 5, 4, 9, 8, 7, 2,
				7, 9, 2, 3, 8, 1, 5, 6, 4,
				9, 1, 3, 4, 2, 6, 7, 8, 5,
				2, 8, 7, 1, 9, 5, 4, 3, 6,
				4, 6, 5, 7, 3, 8, 9, 2, 1,
				6, 2, 9, 8, 5, 4, 3, 1, 7,
				8, 5, 1, 6, 7, 3, 2, 4, 9,
				3, 7, 4, 9, 1, 2, 6, 5, 8,
			},
			true,
		},
		{
			[]int{
				0, 0, 0, 3, 1, 0, 0, 0, 0,
				0, 7, 3, 0, 0, 0, 0, 0, 0,
				4, 0, 0, 9, 0, 0, 3, 0, 0,
				0, 0, 4, 0, 2, 3, 0, 0, 5,
				0, 0, 9, 0, 4, 0, 1, 0, 0,
				3, 0, 0, 8, 6, 0, 7, 0, 0,
				0, 0, 5, 0, 0, 4, 0, 0, 6,
				0, 0, 0, 0, 0, 0, 2, 9, 0,
				0, 0, 0, 0, 3, 1, 0, 0, 0,
			},
			[]int{
				5, 6, 2, 3, 1, 8, 4, 7, 9,
				9, 7, 3, 4, 5, 2, 6, 8, 1,
				4, 1, 8, 9, 7, 6, 3, 5, 2,
				7, 8, 4, 1, 2, 3, 9, 6, 5,
				6, 2, 9, 5, 4, 7, 1, 3, 8,
				3, 5, 1, 8, 6, 9, 7, 2, 4,
				2, 3, 5, 7, 9, 4, 8, 1, 6,
				1, 4, 7, 6, 8, 5, 2, 9, 3,
				8, 9, 6, 2, 3, 1, 5, 4, 7,
			},
			true,
		},
	}
	for i, test := range tests {
		solved := Solve9(test.start)
		if test.solveable {
			if solved {
				for j, num := range test.start {
					if num != test.solution[j] {
						t.Errorf("solution found does not match solution given for test %d", i)
						break
					}
				}
			} else {
				t.Errorf("didn't find solution in puzzle %d when solution expected", i+1)
			}
		} else {
			if solved {
				t.Errorf("found solution in puzzle %d when no solution expected", i+1)
			}
		}
	}
}

func TestCustom(t *testing.T) {
	t.Parallel()
	/*
		http://www.websudoku.com/variation/?day=0
		5 overlapping 9x9 sudoku puzzles (41 regions)
		 1,  2,  3,    ,  4,  5,  6
		 7,  8,  9,    , 10, 11, 12
		 13, 14, 15, 37, 16, 17, 18,
		         38, 39, 40
		 19, 20, 21, 41, 22, 23, 24
		 25, 26, 27,   , 28, 29, 30
		 31, 32, 33,   , 34, 35, 36

		4, 6, 7, 0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 9, 0, 0, 7, 3,
		5, 0, 0, 0, 7, 3, 2, 0, 0,          0, 0, 0, 0, 3, 0, 6, 0, 1,
		0, 3, 0, 5, 0, 0, 0, 6, 0,          0, 3, 0, 8, 0, 0, 0, 0, 4,
		0, 0, 0, 7, 0, 5, 8, 0, 0,          0, 6, 4, 0, 0, 3, 2, 0, 0,
		9, 8, 0, 0, 0, 0, 0, 0, 0,          0, 0, 0, 5, 0, 0, 0, 6, 0,
		0, 0, 1, 0, 8, 0, 0, 3, 0,          3, 0, 8, 0, 0, 7, 0, 9, 0,
		0, 0, 0, 9, 0, 7, 6, 5, 4,|0, 0, 0,|1, 0, 3, 0, 0, 2, 0, 5, 0,
		0, 0, 5, 4, 0, 0, 0, 0, 0,|0, 0, 3,|9, 0, 5, 3, 0, 0, 1, 0, 0,
		0, 0, 0, 0, 0, 6, 3, 2, 0,|5, 0, 0,|0, 0, 6, 0, 0, 0, 0, 0, 0,
		                 \0, 9, 0, 0, 3, 0, 5, 0, 0,\
		                 \0, 0, 0, 7, 0, 5, 0, 0, 0,\
		                 \0, 0, 7, 0, 2, 0, 0, 8, 0,\
		0, 0, 0, 0, 0, 0, 9, 0, 0,|0, 0, 7,|0, 6, 1, 3, 0, 0, 0, 0, 0,
		0, 0, 9, 0, 0, 5, 1, 0, 8,|3, 0, 0,|0, 0, 0, 0, 0, 6, 1, 0, 0,
		0, 3, 0, 1, 0, 0, 4, 0, 5,|0, 0, 0,|7, 3, 8, 1, 0, 5, 0, 0, 0,
		0, 1, 0, 5, 0, 0, 2, 0, 9,          0, 9, 0, 0, 3, 0, 5, 0, 0,
		0, 5, 0, 0, 0, 3, 0, 0, 0,          0, 0, 0, 0, 0, 0, 0, 9, 7,
		0, 0, 4, 2, 0, 0, 7, 5, 0,          0, 0, 2, 5, 0, 1, 0, 0, 0,
		4, 0, 0, 0, 0, 7, 0, 2, 0,          0, 2, 0, 0, 0, 7, 0, 8, 0,
		1, 0, 5, 0, 2, 0, 0, 0, 0,          0, 0, 7, 9, 8, 0, 0, 0, 3,
		8, 7, 0, 0, 4, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0, 7, 1, 2,
	*/
	data := []int{
		4, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 7, 3, //0 - 17
		5, 0, 0, 0, 7, 3, 2, 0, 0, 0, 0, 0, 0, 3, 0, 6, 0, 1, //18 - 35
		0, 3, 0, 5, 0, 0, 0, 6, 0, 0, 3, 0, 8, 0, 0, 0, 0, 4, //36 - 53
		0, 0, 0, 7, 0, 5, 8, 0, 0, 0, 6, 4, 0, 0, 3, 2, 0, 0, //54 - 71
		9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, //72 - 89
		0, 0, 1, 0, 8, 0, 0, 3, 0, 3, 0, 8, 0, 0, 7, 0, 9, 0, //90 - 107
		0, 0, 0, 9, 0, 7, 6, 5, 4, 1, 0, 3, 0, 0, 2, 0, 5, 0, //108 - 116, 117 - 125
		0, 0, 5, 4, 0, 0, 0, 0, 0, 9, 0, 5, 3, 0, 0, 1, 0, 0, //126 - 134, 135 - 143
		0, 0, 0, 0, 0, 6, 3, 2, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, //144 - 152, 153 - 161

		0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 6, 1, 3, 0, 0, 0, 0, 0, //162 - 170, 171 - 179
		0, 0, 9, 0, 0, 5, 1, 0, 8, 0, 0, 0, 0, 0, 6, 1, 0, 0, //180 - 188, 189 - 197
		0, 3, 0, 1, 0, 0, 4, 0, 5, 7, 3, 8, 1, 0, 5, 0, 0, 0, //198 - 206, 207 - 215
		0, 1, 0, 5, 0, 0, 2, 0, 9, 0, 9, 0, 0, 3, 0, 5, 0, 0, //216 - 233
		0, 5, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, //234 - 251
		0, 0, 4, 2, 0, 0, 7, 5, 0, 0, 0, 2, 5, 0, 1, 0, 0, 0, //252 - 269
		4, 0, 0, 0, 0, 7, 0, 2, 0, 0, 2, 0, 0, 0, 7, 0, 8, 0, //270 - 287
		1, 0, 5, 0, 2, 0, 0, 0, 0, 0, 0, 7, 9, 8, 0, 0, 0, 3, //288 - 305
		8, 7, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 2, //306 - 323

		0, 0, 0, //324, 325, 326
		0, 0, 3, //327, 328, 329
		5, 0, 0, //330, 331, 332
		0, 9, 0, 0, 3, 0, 5, 0, 0, //333 - 341
		0, 0, 0, 7, 0, 5, 0, 0, 0, //342 - 350
		0, 0, 7, 0, 2, 0, 0, 8, 0, //351 - 359
		0, 0, 7, //360, 361, 362
		3, 0, 0, //363, 364, 365
		0, 0, 0, //366, 367, 368
	}

	solution := []int{
		4, 6, 7, 1, 2, 8, 5, 9, 3, 4, 8, 1, 2, 9, 6, 5, 7, 3,
		5, 1, 9, 6, 7, 3, 2, 4, 8, 2, 5, 9, 7, 3, 4, 6, 8, 1,
		2, 3, 8, 5, 4, 9, 1, 6, 7, 6, 3, 7, 8, 1, 5, 9, 2, 4,
		3, 4, 6, 7, 9, 5, 8, 1, 2, 5, 6, 4, 9, 8, 3, 2, 1, 7,
		9, 8, 2, 3, 6, 1, 4, 7, 5, 7, 9, 2, 5, 4, 1, 3, 6, 8,
		7, 5, 1, 2, 8, 4, 9, 3, 6, 3, 1, 8, 6, 2, 7, 4, 9, 5,
		8, 2, 3, 9, 1, 7, 6, 5, 4, 1, 7, 3, 4, 6, 2, 8, 5, 9,
		6, 9, 5, 4, 3, 2, 7, 8, 1, 9, 2, 5, 3, 7, 8, 1, 4, 6,
		1, 7, 4, 8, 5, 6, 3, 2, 9, 8, 4, 6, 1, 5, 9, 7, 3, 2,

		5, 4, 1, 7, 6, 8, 9, 3, 2, 4, 6, 1, 3, 2, 9, 8, 7, 5,
		6, 2, 9, 4, 3, 5, 1, 7, 8, 2, 5, 9, 8, 7, 6, 1, 3, 4,
		7, 3, 8, 1, 9, 2, 4, 6, 5, 7, 3, 8, 1, 4, 5, 2, 6, 9,
		3, 1, 6, 5, 7, 4, 2, 8, 9, 8, 9, 6, 7, 3, 4, 5, 2, 1,
		2, 5, 7, 9, 8, 3, 6, 1, 4, 1, 4, 5, 2, 6, 8, 3, 9, 7,
		9, 8, 4, 2, 1, 6, 7, 5, 3, 3, 7, 2, 5, 9, 1, 6, 4, 8,
		4, 9, 3, 6, 5, 7, 8, 2, 1, 5, 2, 3, 4, 1, 7, 9, 8, 6,
		1, 6, 5, 8, 2, 9, 3, 4, 7, 6, 1, 7, 9, 8, 2, 4, 5, 3,
		8, 7, 2, 3, 4, 1, 5, 9, 6, 9, 8, 4, 6, 5, 3, 7, 1, 2,

		2, 8, 9,
		6, 4, 3,
		5, 7, 1,
		2, 9, 6, 4, 3, 8, 5, 1, 7,
		8, 4, 3, 7, 1, 5, 6, 9, 2,
		5, 1, 7, 9, 2, 6, 3, 8, 4,
		8, 5, 7,
		3, 6, 4,
		1, 9, 2,
	}

	sections := make([]Constraint, 0, 131)
	sections = append(sections, MakeBox(18, 18, 9, 1)...)
	sections = append(sections, MakeBox(18, 18, 1, 9)...)
	sections = append(sections, MakeBox(18, 18, 3, 3)...)

	sections = append(sections,
		Unique{114, 115, 116, 324, 325, 326, 117, 118, 119},
		Unique{132, 133, 134, 327, 328, 329, 135, 136, 137},
		Unique{150, 151, 152, 330, 331, 332, 153, 154, 155},
		Unique{333, 334, 335, 336, 337, 338, 339, 340, 341},
		Unique{342, 343, 344, 345, 346, 347, 348, 349, 350},
		Unique{351, 352, 353, 354, 355, 356, 357, 358, 359},
		Unique{168, 169, 170, 360, 361, 362, 171, 172, 173},
		Unique{186, 187, 188, 363, 364, 365, 189, 190, 191},
		Unique{204, 205, 206, 366, 367, 368, 207, 208, 209},

		Unique{114, 132, 150, 333, 342, 351, 168, 186, 204},
		Unique{115, 133, 151, 334, 343, 352, 169, 187, 205},
		Unique{116, 134, 152, 335, 344, 353, 170, 188, 206},
		Unique{324, 327, 330, 336, 345, 354, 360, 363, 366},
		Unique{325, 328, 331, 337, 346, 355, 361, 364, 367},
		Unique{326, 329, 332, 338, 347, 356, 362, 365, 368},
		Unique{117, 135, 153, 339, 348, 357, 171, 189, 207},
		Unique{118, 136, 154, 340, 349, 358, 172, 190, 208},
		Unique{119, 137, 155, 341, 350, 359, 173, 191, 209},

		Unique{324, 325, 326, 327, 328, 329, 330, 331, 332},
		Unique{333, 334, 335, 342, 343, 344, 351, 352, 353},
		Unique{336, 337, 338, 345, 346, 347, 354, 355, 356},
		Unique{339, 340, 341, 348, 349, 350, 357, 358, 359},
		Unique{360, 361, 362, 363, 364, 365, 366, 367, 368},
	)

	if Solve(data, 9, sections) {
		for i, n := range data {
			if solution[i] != n {
				t.Errorf("solution found does not match solution given")
				break
			}
		}
	} else {
		t.Errorf("didn't find solution when solution expected")
	}
}

func TestHard(t *testing.T) {
	puzzle := []int{
		8, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 3, 6, 0, 0, 0, 0, 0,
		0, 7, 0, 0, 9, 0, 2, 0, 0,
		0, 5, 0, 0, 0, 7, 0, 0, 0,
		0, 0, 0, 0, 4, 5, 7, 0, 0,
		0, 0, 0, 1, 0, 0, 0, 3, 0,
		0, 0, 1, 0, 0, 0, 0, 6, 8,
		0, 0, 8, 5, 0, 0, 0, 1, 0,
		0, 9, 0, 0, 0, 0, 4, 0, 0,
	}
	solution := []int{
		8, 1, 2, 7, 5, 3, 6, 4, 9,
		9, 4, 3, 6, 8, 2, 1, 7, 5,
		6, 7, 5, 4, 9, 1, 2, 8, 3,
		1, 5, 4, 2, 3, 7, 8, 9, 6,
		3, 6, 9, 8, 4, 5, 7, 2, 1,
		2, 8, 7, 1, 6, 9, 5, 3, 4,
		5, 2, 1, 9, 7, 4, 3, 6, 8,
		4, 3, 8, 5, 2, 6, 9, 1, 7,
		7, 9, 6, 3, 1, 8, 4, 5, 2,
	}
	if !Solve9(puzzle) {
		t.Errorf("unable to solve puzzle")
	} else {
		for n, d := range puzzle {
			if solution[n] != d {
				t.Errorf("solution found does not match solution given")
				break
			}
		}
	}
}