#!/usr/local/bin/python #Copyright (C) 2007 Rod Gerstad #v0.64 import copy import random from random import shuffle import string from math import sqrt import tkMessageBox from Tkinter import * from Dialog import Dialog import tkFileDialog import tkFont import time import operator #File_start sgp.py class SGP: """ Puzzle data for SG """ PUZZLES = [] PUZZLES_9 = [ [2, 2, 1, 2, 2, 0, 0, 0, 0, 0, 0, 16, 1, -2, 8, 9, -6, 7, -4, -3, -5, -5, -4, -7, -3, 2, -8, -6, -1, -9, -3, -9, 6, 5, 4, -1, -2, -7, 8, 8, 7, -9, 2, -5, -4, -3, -6, -1, 4, -1, 3, -7, -9, -6, -8, -5, -2, -6, -5, -2, -1, 8, -3, -7, 9, 4, 2, 3, -4, 6, -1, -5, -9, -8, -7, -9, -6, 1, -8, -7, 2, 5, -4, 3, 7, -8, 5, -4, 3, -9, 1, -2, -6] ,\ [5, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 16, -5, -3, -1, 6, 8, -4, 9, -2, 7, -4, 6, -9, 2, -1, 7, -5, -3, -8, -7, -2, -8, -5, 3, -9, -1, -6, 4, -3, 8, -6, -7, -4, -5, -2, -1, 9, 1, -4, -2, -3, -9, -6, -7, -8, 5, 9, -7, -5, -8, 2, -1, -3, 4, -6, 8, -1, 7, 9, 6, -2, -4, -5, 3, 2, -9, -3, -4, 5, -8, -6, 7, 1, -6, -5, 4, 1, -7, -3, 8, -9, -2] ,\ [3, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 16, 4, -8, -6, -2, -9, -3, -1, -7, -5, -3, 7, -1, -8, 5, 6, -2, -4, 9, -5, 2, 9, -1, -7, -4, -3, -6, -8, -1, 4, 8, -9, -6, -2, -7, -5, -3, -2, -9, -5, -3, -8, 7, 4, 1, -6, 7, -6, -3, -4, 1, -5, -8, 9, 2, 8, -3, -7, 5, -4, 9, 6, -2, 1, -9, 1, -4, -6, 2, -8, -5, 3, 7, -6, 5, -2, -7, 3, -1, -9, 8, -4] ,\ [4, 0, 1, 1, 1, 2, 0, 0, 0, 0, 0, 16, -2, 8, -5, 1, -9, -6, -4, -3, 7, -6, -1, 4, -3, -8, -7, -2, -5, 9, 9, -3, -7, -2, -5, -4, 8, 1, -6, -3, -9, -2, -5, -1, -8, -7, 6, 4, -1, 4, -8, -6, 7, 9, 3, -2, -5, 7, 5, -6, -4, -2, -3, -9, -8, 1, -5, -7, -9, -8, 6, 2, -1, 4, 3, 8, -6, -3, -9, -4, 1, -5, 7, 2, 4, -2, -1, -7, -3, 5, 6, -9, -8] ,\ [3, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 16, 7, 2, -4, 6, -9, -5, 3, 8, -1, -1, -5, 6, -7, -3, -8, -4, 2, -9, 3, -9, -8, 2, -1, 4, -6, -5, 7, -5, -8, -3, -1, -6, -9, -2, -7, -4, -6, 4, -1, -5, 7, -2, 9, 3, -8, -2, -7, 9, 8, 4, -3, 1, -6, -5, -4, -3, -2, -9, 5, -7, 8, -1, 6, -8, 1, -7, -4, -2, -6, 5, -9, -3, -9, -6, 5, 3, -8, -1, 7, 4, -2] ,\ [5, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 18, 7, -5, 8, -1, -4, -9, 6, -3, 2, -1, -2, -3, 8, 6, -7, -9, -4, 5, 4, -6, -9, -2, -3, -5, 1, -8, -7, -3, -7, -6, -5, 2, 1, 8, -9, -4, -8, -4, 2, -9, -7, -6, 5, -1, -3, -5, 9, 1, -4, -8, -3, -7, -2, 6, -6, 1, 4, 3, 5, -8, 2, -7, 9, -9, -3, -7, -6, -1, -2, 4, -5, -8, -2, 8, -5, -7, 9, -4, 3, 6, -1] ,\ [7, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 18, -9, 8, 4, -6, -5, -3, -2, 7, -1, -2, 1, 3, 4, 9, 7, -6, -8, 5, -5, 6, -7, -1, -2, -8, 3, -4, -9, -1, -4, -8, -2, -7, -6, 5, -9, 3, -3, -2, -6, -9, -8, -5, -7, -1, 4, -7, 9, 5, -3, 1, -4, 8, 2, 6, 8, -7, -9, -5, -3, 1, -4, -6, -2, -6, 5, 1, -8, -4, -2, -9, -3, 7, -4, 3, 2, -7, 6, -9, -1, -5, -8] ,\ [9, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 19, 2, 5, -9, -8, -3, -6, -1, 4, -7, 6, 4, -1, 9, 7, -5, -8, -3, -2, -7, -3, -8, -2, -4, -1, 6, -5, -9, -4, -1, -6, 7, -2, -3, -9, -8, 5, -5, 8, 7, -1, -6, 9, -3, 2, -4, -3, -9, -2, 4, -5, -8, -7, -6, 1, -8, 7, -5, -3, 9, -2, -4, 1, -6, 9, -2, 3, 6, 1, -4, 5, -7, -8, 1, -6, 4, -5, -8, -7, 2, 9, -3] ,\ [3, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0, 19, 5, -3, 8, 6, 4, -9, -2, -1, -7, 4, -9, -7, -1, 3, 2, 8, -6, -5, -2, 6, -1, -8, 7, -5, -4, 9, -3, -3, 8, 6, -9, -2, -1, -5, -7, -4, 7, -4, -2, -3, -5, -6, 1, -8, -9, -9, -1, -5, -7, -8, -4, -6, 3, -2, 8, -5, 3, 2, 1, 7, -9, 4, -6, -1, 2, 9, -4, -6, 3, 7, -5, -8, -6, -7, -4, 5, -9, -8, -3, 2, -1] ,\ [8, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 19, -1, 5, 3, -7, -6, 9, -4, -8, 2, -7, -4, 9, -8, -2, -5, 6, -3, -1, 2, 8, -6, -1, 4, -3, -5, -9, 7, 9, -3, -4, -2, -1, -7, -8, -6, -5, -6, 2, -1, -5, 3, 8, -7, -4, -9, -8, 7, 5, -4, -9, 6, -2, -1, 3, -4, -6, -2, 3, 7, -1, -9, 5, -8, -3, 9, 8, -6, 5, -2, 1, -7, -4, -5, 1, -7, 9, -8, -4, 3, -2, -6] ,\ [8, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 20, -5, 3, 4, 9, -6, 8, 7, -1, 2, -8, 6, -2, -1, 3, 7, -5, 4, -9, -7, -9, 1, -5, -4, -2, -3, -8, 6, -1, -5, -9, -3, -7, -6, -8, -2, -4, -3, -8, 6, -4, -2, -1, -9, -5, 7, -2, 4, -7, -8, -5, -9, 1, 6, -3, -9, 7, -8, -2, -1, 4, -6, 3, -5, -4, 1, 3, 6, 9, -5, -2, 7, 8, -6, 2, 5, -7, -8, -3, -4, -9, -1] ,\ [9, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 20, -8, 7, -1, 6, -4, -3, -2, -5, 9, 6, -3, -9, 5, -2, -1, 4, -7, 8, -2, -5, -4, -8, -7, 9, -6, 1, -3, -9, -1, -2, -4, -6, -8, 5, 3, -7, -4, -6, -5, -3, -9, -7, -1, -8, 2, -7, 8, -3, 2, -1, 5, 9, 6, -4, -5, -9, 7, -1, -8, 4, 3, -2, -6, 3, 2, 8, -9, 5, -6, -7, -4, -1, 1, -4, 6, 7, -3, -2, 8, -9, -5] ,\ [7, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 20, 7, 3, -9, -2, -8, 4, -6, -5, -1, 8, -1, -6, 7, -9, -5, 4, -2, -3, -2, 4, -5, -6, -1, -3, -9, -8, -7, -9, 7, -1, -4, -5, -8, -2, -3, -6, -6, -5, -8, 9, 3, -2, -7, -1, -4, -4, -2, 3, 1, 6, -7, 8, -9, 5, 1, 8, -7, 3, 2, 6, -5, 4, -9, -5, -9, -4, -8, 7, -1, 3, 6, -2, -3, 6, 2, 5, -4, -9, -1, 7, -8] ,\ [7, 0, 2, 2, 1, 1, 0, 0, 0, 0, 0, 20, 4, 9, -7, 3, 2, -6, 5, -1, -8, -5, 6, 8, 7, 9, 1, 2, -3, -4, -2, -3, -1, 5, -4, -8, -7, -6, -9, -8, 7, -3, -2, -1, -5, -9, -4, -6, 1, 2, -5, 9, -6, -4, -8, 7, 3, -9, -4, 6, -8, -7, -3, -1, -5, -2, 7, 8, -4, 1, -3, -2, 6, -9, -5, -6, -5, -9, -4, -8, -7, -3, 2, -1, -3, 1, -2, 6, 5, -9, 4, -8, -7] ,\ [4, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 20, -1, -5, -9, 3, -8, 2, -4, -6, -7, -4, -7, -8, -1, -5, -6, 9, 3, -2, 6, -2, -3, 4, -7, -9, -8, -5, -1, -5, 9, -4, 7, -1, -8, -6, -2, -3, 8, -3, -6, -2, -4, -5, -7, -1, -9, -2, -1, -7, -9, -6, 3, 5, 4, -8, 3, 4, 2, 5, -9, 7, 1, -8, -6, 7, 8, 5, -6, 2, 1, -3, 9, 4, -9, 6, 1, -8, -3, -4, -2, 7, -5] ,\ [10, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 21, 7, -5, -4, -2, 9, -3, -1, -8, -6, -9, -8, 1, -4, 5, 6, -7, -2, -3, -6, -2, -3, -7, -8, -1, -9, -4, -5, 2, -7, -8, -9, -3, -4, 5, -6, -1, -1, 9, -6, -8, 7, -5, 4, -3, 2, 3, 4, -5, 1, -6, -2, 8, 9, 7, -5, -1, -2, -6, 4, 9, -3, -7, -8, 8, -3, 9, -5, 2, -7, 6, -1, 4, -4, -6, 7, 3, 1, -8, -2, 5, -9] ,\ [8, 1, 0, 2, 2, 1, 0, 0, 0, 0, 0, 21, -4, -9, -5, -7, -1, -2, 6, 8, 3, 1, -6, 8, -4, -5, 3, 7, -9, -2, -2, -3, -7, -6, -9, -8, 4, 1, -5, -7, 8, -1, -9, -3, 6, 5, -2, -4, -5, 2, -9, -8, -4, 7, -3, -6, 1, 3, 4, -6, 5, -2, 1, -9, 7, -8, -8, -5, -4, -2, -6, 9, -1, -3, -7, 6, -1, -2, 3, -7, -5, -8, -4, 9, -9, 7, -3, 1, -8, 4, -2, 5, -6] ,\ [8, 3, 2, 0, 0, 1, 0, 0, 0, 0, 0, 21, -6, -5, -8, -1, 7, -4, -9, -3, -2, -3, -1, 2, -8, -6, 9, -4, -7, 5, -7, -4, -9, -5, -2, 3, 6, -8, -1, -1, -6, 4, 2, 5, -7, -3, 9, 8, 9, -8, -7, 6, -3, -1, -5, 2, -4, -5, -2, 3, -4, -9, -8, 7, -1, 6, -2, -9, -5, -3, -1, -6, 8, 4, -7, 4, -7, 6, 9, -8, -2, 1, 5, 3, -8, -3, 1, 7, -4, -5, 2, -6, -9] ,\ [9, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 21, 8, -9, -6, 2, -4, 7, -5, 1, 3, 1, -7, -2, -3, -5, 8, 6, 9, -4, -3, 5, -4, -9, -1, -6, -2, -8, 7, -9, -1, 7, -6, -8, -5, 4, -3, 2, 2, 6, -3, -7, -9, -4, -1, 5, -8, -5, 4, -8, -1, -2, -3, 9, -7, -6, -7, -2, 9, -4, -3, 1, -8, -6, -5, -4, 3, -5, 8, -6, 9, -7, -2, -1, 6, -8, -1, -5, 7, 2, 3, -4, -9] ,\ [6, 2, 0, 2, 0, 1, 1, 0, 0, 0, 0, 21, -6, 9, -3, -2, 1, -7, -5, 8, -4, -1, -4, 2, -8, -5, -9, -3, -6, 7, -7, 5, 8, -3, -6, -4, -2, -1, 9, -3, -7, -4, -1, -2, -6, -9, -5, -8, -2, -8, -1, -9, 4, -5, -7, -3, 6, 9, -6, -5, 7, -3, 8, -4, 2, 1, 5, -2, 6, 4, 7, -1, -8, -9, -3, -4, 1, -9, 5, -8, 3, -6, 7, -2, 8, 3, 7, -6, -9, 2, -1, 4, -5] ,\ [1, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 21, -7, -2, -3, -8, 4, 9, -1, 5, 6, -1, 9, -4, -5, -2, -6, 3, -7, -8, -8, -6, 5, 7, 1, -3, -4, 2, -9, -4, -7, 2, -1, 6, 8, -9, -3, -5, -6, -3, 8, -4, 9, 5, -7, 1, -2, -9, -5, -1, -2, -3, -7, -8, -6, 4, -3, 1, 9, -6, 5, 4, -2, -8, 7, -2, -8, -6, 9, -7, -1, -5, -4, -3, -5, -4, 7, 3, -8, 2, -6, 9, -1] ,\ [6, 3, 1, 3, 1, 0, 0, 0, 0, 0, 0, 22, 8, -9, -4, -5, -3, -1, 7, -6, 2, -5, -3, 7, -6, -2, 8, -1, 9, -4, -1, 2, -6, -9, 4, -7, -3, -8, 5, -7, -1, -8, -3, 6, -2, 4, 5, -9, 3, -6, -5, -4, 7, 9, 8, -2, -1, -9, -4, -2, -8, 1, -5, -6, 7, -3, -6, -8, 9, -1, -5, -4, -2, 3, 7, -2, 5, 1, -7, -8, -3, -9, -4, -6, 4, -7, 3, -2, 9, 6, -5, 1, -8] ,\ [6, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 22, -7, -5, -1, -4, -3, -9, -8, -2, -6, 4, -2, -6, -8, -1, 7, -9, 5, 3, -3, -9, 8, -5, 6, -2, -7, -1, -4, -8, 1, -3, 7, -9, -6, -5, 4, -2, 2, -6, -7, -1, -4, -5, -3, -8, -9, -9, 4, 5, -3, -2, 8, 1, -6, -7, -1, -7, 9, -2, 8, 4, 6, -3, -5, 6, -3, 4, -9, 5, 1, 2, 7, -8, -5, -8, -2, 6, 7, -3, 4, -9, 1] ,\ [8, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 22, -3, -9, 1, 5, -4, -8, -2, -6, -7, -2, -5, -4, -7, -9, -6, 3, -1, -8, 6, -8, 7, -2, -3, -1, -4, -5, 9, 5, -3, -8, -6, -2, 7, -9, -4, -1, -9, -1, -2, 3, 5, -4, 8, 7, -6, 4, -7, -6, -1, 8, 9, 5, -2, 3, -1, -2, 5, -9, -6, 3, -7, 8, -4, -7, -4, -3, 8, -1, 5, 6, -9, 2, -8, -6, 9, 4, 7, -2, 1, -3, -5] ,\ [9, 1, 0, 2, 2, 1, 0, 0, 0, 0, 0, 22, -3, -8, 7, 9, -4, 2, 1, -5, -6, -4, -6, -9, 1, -5, -8, -2, -7, 3, -1, -2, -5, 6, 7, -3, -8, -4, -9, -5, -9, 3, -2, -6, -7, -4, 8, -1, -7, -4, -6, -8, -3, -1, 9, -2, 5, -8, 1, 2, -4, -9, 5, 6, -3, -7, -6, 3, 4, 5, -2, 9, 7, -1, -8, 2, -5, -1, 7, -8, -6, 3, 9, -4, -9, -7, 8, 3, -1, -4, -5, 6, -2] ,\ [6, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0, 22, 5, -9, -4, 1, -2, 6, -8, -7, -3, 6, -7, -3, -9, -4, -8, -2, 1, 5, -8, -1, -2, 3, -5, -7, -6, 9, -4, -4, -6, -1, 8, -9, -3, -5, -2, -7, 3, -2, -5, -4, -7, 1, -9, 8, 6, -9, -8, 7, -2, -6, -5, 4, -3, -1, 2, -3, -6, -5, -1, -9, 7, 4, -8, 7, -4, 8, -6, 3, 2, -1, -5, -9, 1, 5, -9, 7, 8, 4, 3, -6, -2] ,\ [8, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 22, -9, -3, 8, 2, -7, -4, 1, -5, 6, -1, -6, -4, -8, -5, 9, -7, -3, 2, -7, -2, 5, -6, 3, -1, -4, -9, -8, -3, -1, 9, -7, -8, -2, 5, 6, -4, -2, -8, -6, -9, -4, -5, -3, -1, 7, 4, -5, -7, -1, -6, -3, 8, -2, 9, -5, 4, -2, 3, 9, -8, -6, -7, -1, 6, 9, -3, -4, -1, 7, -2, -8, -5, 8, 7, 1, 5, 2, -6, 9, 4, -3] ,\ [12, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 23, -5, 9, 8, -6, -2, 3, -1, -7, 4, -4, 6, -3, -5, -1, -7, -9, -2, -8, 7, 2, -1, 8, 4, -9, -6, 5, -3, -2, -3, -7, -4, -9, -8, 5, 6, -1, -8, 4, -6, -2, -5, -1, -3, -9, -7, -1, -5, 9, 3, -7, -6, -8, -4, 2, 6, 7, 4, 1, 3, -5, 2, -8, 9, 3, -8, -2, -9, 6, -4, 7, -1, -5, -9, -1, -5, -7, -8, 2, -4, 3, -6] ,\ [12, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 23, 2, 1, 3, -7, -6, -9, 4, 5, -8, -6, -4, -5, -8, 1, -3, -7, -2, -9, -8, 7, -9, -4, -2, -5, -6, -3, -1, -7, -9, -2, -3, -4, -1, -5, -8, -6, -5, -6, 4, 2, 9, 8, -3, -1, 7, -1, 3, -8, 5, -7, 6, -9, 4, 2, -9, 8, -6, 1, -5, 4, -2, 7, -3, 4, -2, 1, 6, 3, 7, -8, -9, -5, -3, 5, -7, -9, -8, -2, -1, 6, -4] ,\ [9, 1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 23, -6, -3, -5, 8, -7, -4, -1, -9, 2, -8, 1, -2, -6, -9, -5, 3, -4, 7, -4, 9, 7, -2, -3, -1, -5, 8, -6, -9, -2, 8, -5, 1, -3, -6, -7, -4, -1, -4, -6, -7, 2, -9, -8, 3, -5, 5, -7, -3, 4, 6, -8, -2, -1, -9, -7, -8, 1, -9, 5, 6, -4, -2, 3, -3, 5, -9, 1, -4, -2, -7, 6, -8, -2, 6, -4, 3, 8, 7, 9, 5, -1] ,\ [9, 2, 1, 2, 0, 0, 1, 0, 0, 0, 0, 23, -4, 8, 1, -9, -7, -5, -3, -2, -6, -9, -6, -5, -3, -8, -2, 4, -1, -7, -3, 2, -7, -1, 4, -6, -8, 5, 9, 6, -1, 3, -5, 2, -8, -7, -9, -4, 5, 7, -8, -4, -9, -1, 6, -3, -2, 2, 4, 9, -7, -6, -3, -1, 8, -5, -7, 5, 2, -8, 3, 4, -9, -6, 1, -8, -9, 6, -2, -1, 7, -5, 4, -3, -1, -3, -4, -6, 5, 9, 2, -7, -8] ,\ [9, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 23, -5, -7, -9, 4, -2, 3, 8, -6, 1, 8, -6, -3, -9, -1, -5, -2, -4, -7, -2, -4, -1, 7, 6, -8, -3, -9, -5, -9, 3, -8, -2, -7, -6, -1, -5, -4, 4, 1, -2, -3, -5, -9, -7, -8, -6, 7, 5, 6, 1, -8, 4, 9, 2, -3, -1, -8, -4, -6, 9, -7, -5, 3, 2, -6, 2, 5, -8, -3, 1, -4, 7, -9, 3, -9, 7, 5, -4, -2, -6, 1, -8] ,\ [12, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 23, -5, 9, 4, -7, -3, -6, -1, -8, 2, 2, -3, -8, -9, -5, 1, -7, -4, -6, -6, -1, 7, -8, -2, 4, -3, -9, -5, -7, -5, -9, -6, -4, 8, -2, 3, -1, -1, -8, -2, -5, 7, -3, 9, -6, 4, -4, -6, -3, 2, -1, -9, 5, 7, -8, 8, 7, 1, -3, 6, -2, -4, 5, -9, -9, -2, -5, -4, -8, 7, 6, 1, 3, -3, 4, 6, -1, 9, 5, -8, -2, -7] ,\ [6, 0, 2, 2, 0, 0, 0, 0, 1, 0, 0, 23, -4, -3, 2, -9, -1, 6, -5, 8, -7, 9, -8, -6, -4, 7, -5, 1, -2, -3, -7, 5, -1, -2, -8, 3, -4, 9, -6, -5, 2, 3, 8, -4, -7, 6, -1, -9, 1, -4, -7, -3, -6, -9, -8, -5, -2, 6, -9, -8, -1, -5, -2, -3, 7, 4, -2, -1, 9, 5, -3, 4, -7, -6, -8, 8, 6, -4, -7, -2, 1, 9, -3, 5, -3, -7, -5, 6, -9, 8, 2, -4, -1] ,\ [5, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 23, -9, 7, -6, 5, -8, 2, -3, -4, -1, -3, -8, -1, -4, 9, -7, 6, 2, -5, 2, -4, -5, -3, -6, -1, 8, -7, 9, -8, -2, -9, 7, -5, -3, -4, 1, -6, -6, -3, 4, -2, -1, -9, -5, 8, -7, -5, -1, -7, 6, 4, 8, -9, -3, -2, -7, 9, 2, -8, 3, -5, 1, -6, -4, -1, 6, -8, 9, -7, -4, -2, -5, 3, -4, 5, -3, 1, 2, 6, 7, -9, -8] ,\ [10, 2, 1, 2, 0, 0, 1, 0, 0, 0, 0, 24, 9, -4, 3, -2, -7, 1, -6, -8, -5, -8, 5, -7, -3, 4, -6, -2, -1, -9, 2, -1, -6, -8, -9, -5, -7, 4, -3, 1, -2, -8, -5, 3, -7, 4, -9, -6, -6, -9, -5, -1, -8, -4, -3, -7, 2, 7, -3, -4, -6, -2, 9, -1, 5, 8, -4, 8, 1, 9, -6, -3, -5, 2, -7, -5, 6, 9, 7, -1, -2, -8, 3, -4, 3, 7, -2, 4, -5, 8, -9, 6, -1] ,\ [13, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 24, -3, -9, 7, 6, -8, -5, -1, -2, -4, -1, 6, -8, 3, -4, -2, -7, 5, 9, 2, -4, -5, -9, -7, -1, 3, -8, -6, -7, -2, -4, 8, 5, -9, -6, 1, -3, -5, -1, -3, 2, -6, 4, -8, -9, 7, -6, -8, -9, -1, -3, -7, -5, 4, 2, 8, -5, -6, -4, 9, -3, 2, -7, -1, -9, 7, 2, 5, -1, -6, -4, 3, -8, -4, 3, 1, 7, -2, 8, 9, -6, -5] ,\ [8, 3, 2, 3, 0, 0, 0, 0, 0, 0, 0, 24, 2, 1, 8, -5, -4, 3, 6, 9, -7, 5, 4, 9, 2, -6, -7, -8, -3, -1, -6, -7, -3, 8, -1, -9, -2, 5, -4, -1, 9, -6, 4, -8, -2, -3, -7, -5, -3, -8, -5, -9, 7, -6, -4, 1, 2, -7, -2, -4, -1, -3, -5, -9, -6, 8, -8, -6, -2, -7, -9, 1, 5, -4, -3, 4, -3, -1, 6, -5, -8, -7, 2, -9, 9, 5, 7, -3, -2, -4, 1, 8, -6] ,\ [8, 5, 2, 1, 0, 0, 0, 0, 0, 0, 0, 24, 2, -4, 7, 5, 1, -3, -9, -8, -6, 8, -5, -9, -4, -7, 6, -2, -1, -3, -3, -6, -1, -2, -9, -8, -7, 4, -5, -7, 2, -6, -9, -5, 4, 1, -3, -8, -5, -1, 3, -8, -6, -7, -4, -9, -2, 9, -8, -4, 1, -3, -2, 5, -6, 7, 4, 9, -2, 6, 8, -5, 3, -7, -1, 6, -3, 5, 7, 4, -1, -8, 2, 9, -1, -7, -8, 3, -2, 9, -6, -5, -4] ,\ [8, 5, 2, 1, 0, 0, 0, 0, 0, 0, 0, 24, 7, -8, 3, 1, -6, -2, 4, -9, -5, -1, -4, -5, 8, -3, 9, -2, -6, -7, 6, -9, -2, -7, -4, -5, -8, -1, -3, 2, -1, 9, 3, -5, 4, 6, -7, -8, -5, -3, -4, -6, 7, -8, -9, -2, -1, -8, 6, -7, -9, 2, -1, 5, -3, 4, -3, -7, 8, -4, -9, -6, -1, -5, -2, -4, 2, -6, 5, 1, -3, 7, -8, 9, 9, -5, 1, 2, -8, -7, 3, 4, -6] ,\ [11, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 24, 1, -2, 4, -6, -3, 8, -9, -7, -5, -8, -5, -9, -1, 4, -7, -2, 6, 3, -7, -6, 3, 9, 2, -5, -8, -4, 1, -2, -3, 8, -4, -6, -1, 7, -5, -9, -4, -9, -6, -5, -7, 2, -3, 1, -8, 5, -7, -1, -3, -8, -9, 6, -2, 4, 9, -4, 2, 8, -5, -6, -1, -3, 7, -3, 1, -7, 2, -9, -4, -5, -8, -6, 6, -8, -5, 7, 1, 3, 4, -9, -2] ,\ [8, 1, 2, 3, 2, 0, 0, 0, 0, 0, 0, 24, -1, -2, -6, 7, -3, -4, 9, 8, 5, -4, -5, 7, -8, 9, 6, 3, -2, 1, -3, -8, -9, -1, -5, -2, -7, 6, -4, -6, -9, 8, -4, 7, -5, 2, 1, -3, -2, 4, -3, 9, -6, 1, -5, -7, -8, -7, -1, -5, -2, -8, 3, -6, 4, -9, 9, -6, -4, 3, -1, 7, -8, -5, -2, -5, -3, 2, -6, 4, -8, -1, -9, -7, 8, -7, -1, 5, 2, -9, -4, 3, -6] ,\ [3, 4, 2, 3, 0, 1, 0, 0, 0, 0, 0, 24, 3, -9, -4, -5, -7, 8, -2, 6, -1, 5, 2, -7, -1, 9, 6, -8, -3, 4, -6, -8, 1, -2, -4, -3, -9, -5, -7, -9, -4, -8, -6, -3, 7, 1, -2, -5, -1, -6, -5, -9, -8, 2, -7, -4, 3, 7, -3, -2, 4, -1, -5, -6, 9, 8, 8, -7, 6, -3, -5, -9, 4, -1, 2, -2, 1, -3, -7, 6, -4, 5, -8, 9, -4, 5, 9, -8, -2, -1, -3, 7, -6] ,\ [7, 1, 0, 2, 1, 0, 0, 0, 1, 0, 0, 24, -2, -3, 9, -7, -1, -5, 4, -6, -8, -1, -5, 4, -3, -6, 8, -2, 7, -9, -8, -7, -6, -4, -9, 2, 1, -3, 5, -6, -2, -5, -9, -8, 4, -3, -1, -7, -9, -1, -3, 2, -7, -6, 5, -8, -4, 7, -4, -8, -1, 5, -3, -9, 2, 6, -5, 6, -2, -8, 3, -9, -7, 4, 1, 4, 9, 7, 6, -2, -1, -8, 5, -3, 3, -8, 1, -5, -4, 7, 6, -9, -2] ,\ [11, 1, 1, 3, 2, 0, 0, 0, 0, 0, 0, 25, 2, -1, -5, -8, -3, 4, 6, -9, 7, 7, 9, -4, 2, -6, 5, 1, -3, -8, -3, -6, -8, -7, -9, -1, -4, -2, -5, -5, -4, -3, 1, -7, -2, -9, 8, -6, 8, -2, 6, -4, -5, 9, 3, -7, -1, -1, -7, -9, -6, -8, -3, -5, -4, 2, 4, -8, -1, 3, 2, 6, 7, 5, -9, -9, 3, -7, -5, -1, 8, -2, -6, 4, 6, -5, -2, 9, -4, -7, 8, -1, -3] ,\ [11, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0, 25, -9, -8, 1, -5, -2, 3, -7, 4, -6, 7, 2, -3, -6, -4, -9, -5, -1, 8, 5, -4, -6, -8, -7, 1, -9, -2, -3, 2, -5, 8, -3, -1, 6, -4, -7, -9, -4, 1, -9, -2, -8, -7, -3, -6, 5, -6, -3, -7, 9, -5, -4, -1, -8, 2, -8, 9, 4, 1, 6, 5, -2, 3, -7, -3, -7, 2, -4, -9, 8, 6, -5, -1, -1, -6, 5, 7, -3, 2, -8, 9, -4] ,\ [14, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 25, 2, 7, -1, -8, -9, 6, -4, -3, -5, -9, -4, 3, -5, -7, 1, 8, -6, -2, -5, -8, -6, -3, 4, -2, -1, -9, -7, -1, -9, -8, -7, 6, -3, -2, -5, 4, -6, 5, -4, -2, -1, 9, 7, -8, -3, -7, -3, 2, -4, 8, -5, 9, 1, -6, -4, 6, 7, -1, -3, 8, 5, -2, -9, 3, -1, -5, 9, 2, -7, 6, 4, -8, 8, -2, 9, 6, -5, -4, -3, -7, -1] ,\ [9, 2, 1, 4, 1, 0, 0, 0, 0, 0, 0, 25, 2, -1, 7, -4, 5, -6, -3, -9, -8, -8, -3, 5, 9, 1, 2, -6, 4, -7, -4, -9, -6, -7, -8, 3, -5, 1, -2, 6, -5, 9, -8, -3, -4, -7, -2, -1, -3, -2, -1, -6, 7, -9, -4, 8, -5, -7, -4, -8, 5, -2, 1, -9, 3, -6, 9, -7, -4, -2, -6, -8, -1, -5, -3, -5, 8, -3, -1, 9, 7, 2, -6, 4, -1, -6, 2, 3, 4, 5, 8, -7, -9] ,\ [9, 5, 2, 1, 0, 0, 0, 0, 0, 0, 0, 25, 3, -1, 5, -9, -2, -7, -8, -4, 6, 4, -2, -7, 8, -6, 5, -9, 3, -1, 8, -6, 9, -3, -4, -1, -7, -5, -2, -9, -7, -8, -1, -5, -4, 6, -2, -3, -2, -5, -4, -6, -3, -9, 1, -7, 8, -6, 3, 1, 2, 7, -8, -5, -9, -4, -1, 8, -3, -5, 9, 2, -4, -6, -7, 7, -9, 2, 4, -8, 6, 3, -1, 5, -5, -4, -6, 7, 1, -3, -2, 8, -9] ,\ [12, 0, 2, 2, 1, 1, 0, 0, 0, 0, 0, 25, -5, -3, -4, 8, -2, -9, 6, 1, -7, 7, -8, -1, 6, -5, -4, -9, -2, 3, -6, -9, 2, -3, 1, -7, -4, 5, -8, -8, 4, -7, -1, -9, 5, -2, -3, -6, -1, -5, -3, -2, -8, -6, 7, 4, -9, 9, -2, -6, -7, -4, 3, 5, -8, 1, 3, -7, -8, -4, -6, 2, -1, -9, 5, -4, -6, 9, -5, 3, 1, -8, 7, 2, -2, 1, -5, -9, 7, 8, -3, -6, -4] ,\ [9, 1, 3, 4, 0, 0, 0, 0, 0, 0, 0, 25, -2, 8, 1, -7, 3, -6, -4, -9, -5, -4, -7, -9, -1, -8, -5, -6, -2, 3, 6, -5, -3, -9, 4, -2, 1, 7, 8, 7, 6, -2, -4, 5, -3, 9, 8, -1, -3, -1, 4, -8, -7, -9, 5, -6, 2, -5, -9, 8, -2, 6, 1, -3, -4, -7, 9, -3, -7, -6, -1, -8, 2, 5, -4, -1, -4, 6, 5, -2, -7, -8, -3, -9, -8, -2, 5, 3, 9, -4, -7, -1, -6] ,\ [9, 3, 2, 2, 1, 0, 0, 0, 0, 0, 0, 25, -3, -8, 9, -7, 2, -4, -5, 6, -1, -5, 7, -4, -6, -1, 8, 3, -2, -9, 1, -2, -6, -9, -3, -5, -7, -4, -8, -2, -1, 3, -5, -8, 6, -9, 7, 4, -7, 9, -5, -1, -4, -2, -6, -8, -3, -6, 4, -8, -3, -7, -9, 2, -1, 5, -8, 6, 2, -4, 5, 3, -1, -9, -7, -9, -5, 7, -8, 6, 1, -4, 3, 2, -4, 3, 1, -2, 9, -7, 8, -5, -6] ,\ [12, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 25, -4, 7, 5, -6, -1, 2, 3, 9, -8, -6, -8, -2, -9, 3, -7, -5, -4, 1, -9, -1, -3, 5, -8, -4, -6, -2, -7, 5, -9, -6, 4, -7, -1, 2, -8, -3, -7, 3, -4, -8, -2, 6, 9, -1, -5, 8, 2, -1, -3, -9, -5, -7, 6, -4, 2, 5, 7, -1, 6, 8, -4, -3, 9, -1, 6, -9, -7, -4, -3, -8, -5, -2, -3, -4, -8, 2, 5, 9, 1, -7, -6] ,\ [13, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 25, -3, -6, -7, 1, 8, 5, 9, 2, -4, 1, -4, 5, 9, -2, -7, 8, -6, -3, -9, -2, -8, 6, -3, -4, -5, -7, -1, 7, -1, -6, -3, -5, -9, -2, -4, -8, -2, 5, -4, -8, 6, -1, -3, -9, -7, -8, 3, 9, 7, -4, 2, 1, 5, -6, 4, -8, 2, -5, -1, -6, -7, 3, 9, -5, -9, -3, -4, 7, 8, -6, 1, -2, -6, -7, 1, -2, -9, -3, 4, -8, -5] ,\ [12, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 25, -3, -4, 2, -9, 5, -8, 1, -7, 6, -6, -5, -8, -2, -7, -1, -3, -9, -4, 1, 7, 9, 3, -4, -6, 8, -2, 5, -8, -6, 4, -1, 2, -3, 9, 5, -7, -2, -1, -5, -7, -8, -9, -6, -4, -3, -7, 9, -3, 4, -6, 5, -2, -8, -1, 5, -3, -6, -8, 9, 7, 4, 1, -2, -4, 8, -1, -5, -3, -2, 7, -6, 9, -9, -2, -7, 6, -1, 4, -5, 3, -8] ,\ [8, 2, 1, 1, 0, 0, 0, 0, 1, 0, 0, 25, -3, -4, 1, -6, -5, 8, -2, 7, -9, 6, 2, -7, -9, -1, 3, -5, -8, -4, 5, 9, -8, -2, -7, -4, -1, -3, -6, -8, -3, -5, 4, 2, -1, -6, 9, -7, -7, -1, -4, 3, -6, -9, 8, -2, 5, -9, -6, -2, -5, -8, 7, -4, -1, 3, -2, 7, -3, -8, -4, -5, 9, 6, 1, -1, -5, 6, -7, -9, 2, 3, -4, 8, 4, -8, -9, 1, -3, -6, 7, 5, -2] ,\ [11, 2, 0, 3, 1, 1, 0, 0, 0, 0, 0, 26, -7, -5, 1, -4, -3, -8, -2, 9, -6, 8, 3, -9, -6, -1, -2, -7, -4, -5, -4, -2, 6, 7, -9, 5, -1, -8, -3, -1, 4, -2, -3, -5, 9, -8, 6, -7, -6, 8, -3, -1, -7, -4, -9, -5, -2, 9, -7, 5, 2, -8, -6, -3, 1, -4, -5, -1, -4, -9, -2, -7, 6, 3, 8, -2, -9, -8, 5, -6, 3, -4, 7, 1, 3, 6, 7, 8, -4, 1, -5, 2, -9] ,\ [12, 4, 1, 0, 2, 0, 0, 0, 0, 0, 0, 26, -7, 5, -4, 3, -6, -8, -1, -2, -9, 9, -8, -1, -7, -4, 2, 6, -3, 5, 2, 3, 6, -1, -5, 9, 8, 4, -7, -4, -1, -2, 8, -3, -5, -7, -9, -6, -3, -9, -5, -6, -7, -1, -2, 8, -4, -6, 7, -8, -2, -9, 4, 3, -5, -1, -1, 2, -9, -5, -8, 7, -4, 6, -3, 8, 4, 3, 9, -1, 6, -5, -7, 2, -5, -6, 7, -4, -2, -3, 9, -1, -8] ,\ [14, 1, 3, 1, 1, 0, 0, 0, 0, 0, 0, 26, -9, -5, 8, -2, -6, -7, -3, -4, -1, -7, -3, 1, 4, 9, -5, -8, -2, -6, -2, -4, 6, 8, 3, -1, -7, 9, -5, -3, -8, -5, -9, -4, 6, 1, 7, -2, -6, -2, -7, 5, -1, -8, 4, -3, 9, -1, 9, -4, -7, -2, -3, -5, -6, 8, -8, -1, -9, 6, 7, -4, 2, 5, -3, 4, -6, -3, 1, -5, 2, -9, -8, -7, 5, -7, 2, 3, -8, -9, 6, 1, -4] ,\ [8, 3, 0, 5, 1, 0, 0, 0, 0, 0, 0, 26, -3, -8, 6, -4, 9, 7, 2, -1, 5, 9, -5, -4, -1, -2, 8, 7, -3, -6, -2, -7, -1, 6, 5, -3, -9, -8, -4, -4, 1, 8, -9, -3, -6, -5, -7, -2, 7, -3, -9, -5, -4, -2, 1, -6, -8, -6, -2, 5, 8, -7, 1, 3, 4, -9, 8, -9, 3, 7, -6, -5, -4, -2, -1, -5, -6, 2, -3, 1, 4, 8, -9, -7, -1, 4, -7, -2, -8, -9, -6, 5, -3] ,\ [15, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 26, -7, -2, -5, -3, 9, 8, 1, -4, -6, -1, -9, -6, -2, -7, 4, 8, -3, 5, -8, 4, -3, -6, 5, -1, -7, -9, -2, -4, -7, 8, -1, 2, -3, -5, -6, -9, 3, -1, 2, 9, -6, -5, -4, -8, -7, 5, 6, -9, -8, -4, -7, -2, -1, 3, -2, -3, 4, -5, 1, 6, 9, 7, 8, -9, -8, -7, -4, -3, 2, 6, -5, -1, -6, -5, 1, -7, 8, -9, 3, 2, -4] ,\ [11, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 26, 1, -7, -2, 8, -9, -4, -5, -3, -6, -8, 6, 4, -3, -2, -5, 7, -9, -1, -5, 3, -9, -1, -7, -6, -8, 4, -2, -7, -8, -1, -4, -6, 9, 3, -2, -5, 4, -9, -6, 5, -3, -2, -1, 8, -7, 2, -5, -3, 7, -8, -1, -4, 6, -9, 6, 1, -8, 2, 5, 3, -9, -7, 4, -3, -2, 5, -9, -4, 7, 6, -1, -8, -9, -4, -7, 6, 1, 8, -2, 5, -3] ,\ [11, 1, 0, 2, 0, 0, 0, 0, 1, 0, 0, 26, -9, -5, -2, 8, -3, -6, -1, 7, 4, -7, -3, -8, -2, 1, -4, -9, -6, -5, -4, 6, -1, -7, -5, 9, 3, -8, -2, -2, -9, -7, -1, -6, -5, -8, -4, -3, -6, -4, 5, -3, -9, 8, -2, 1, -7, 8, -1, -3, 4, 7, 2, 6, -5, -9, -1, -8, 9, -5, 4, 3, -7, 2, -6, 3, -7, 4, 6, -2, 1, 5, 9, -8, -5, 2, -6, -9, 8, -7, 4, -3, -1] ,\ [11, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 26, 7, 4, -9, -6, -2, -1, -3, -5, -8, 5, -8, -3, -7, -9, 4, -1, 6, 2, -6, -2, -1, -8, -5, 3, -7, 9, 4, -3, -6, 5, 9, -8, 2, -4, -1, -7, -9, -7, -8, 1, -4, -6, -2, 3, -5, -4, -1, 2, -3, 7, 5, -9, 8, 6, 8, -9, -6, 2, -3, -7, -5, 4, -1, -2, 3, -4, -5, -1, -8, -6, 7, 9, -1, -5, 7, -4, 6, -9, 8, -2, -3] ,\ [11, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 26, 7, -2, 9, 1, -8, -3, -5, -4, -6, -5, -1, 4, -9, 7, -6, -8, -2, 3, -8, -6, -3, -4, 2, -5, -9, -7, -1, 4, -7, -5, -3, -9, -1, 6, 8, 2, 6, -8, -1, -2, -4, -7, 3, 9, -5, -3, -9, -2, -5, -6, -8, 4, 1, -7, -2, -3, 6, 8, -1, 4, -7, -5, -9, -9, 4, -7, -6, 5, 2, -1, -3, 8, 1, 5, -8, 7, 3, -9, -2, 6, -4] ,\ [9, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 26, -3, 7, -4, -6, 1, 5, 8, 2, -9, -5, -8, 1, -9, -4, 2, -6, 3, -7, -2, -6, -9, 8, -3, -7, 4, -5, -1, -7, -3, -6, -1, -5, -9, -2, 8, -4, 4, -9, 5, -2, -7, -8, 1, -6, -3, -8, -1, -2, -4, 6, 3, 9, -7, 5, -9, 2, -7, -3, 8, -4, -5, -1, 6, 6, -5, 8, -7, -9, 1, -3, -4, -2, -1, -4, 3, 5, -2, -6, 7, 9, -8] ,\ [9, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 26, -4, -2, -8, -3, -9, 5, -1, -7, 6, 1, -5, -9, 8, -7, 6, -2, 3, -4, -3, 6, 7, -1, -4, -2, -8, -9, -5, 5, -8, -6, 9, 1, 3, 4, 2, -7, -9, 4, 1, -5, -2, -7, -6, -8, -3, -2, 7, -3, -4, -6, -8, 5, 1, -9, -7, -1, -5, -6, 8, -9, -3, 4, -2, -8, 3, 2, -7, 5, -4, -9, 6, -1, -6, 9, -4, -2, -3, 1, 7, -5, -8] ,\ [8, 0, 0, 2, 1, 0, 0, 0, 0, 1, 0, 26, -6, 2, 1, 4, -5, 9, -3, 7, 8, 3, -8, -7, -6, -2, 1, -4, -9, -5, -9, -4, 5, -3, 7, -8, -6, -2, -1, 7, -9, -8, -2, 1, -4, -5, 6, -3, 5, -3, -4, -8, -9, 6, -2, -1, 7, -1, -6, -2, -7, -3, 5, 8, -4, 9, -8, -1, 6, 9, -4, -3, -7, 5, -2, -4, 7, -9, -5, 8, 2, -1, -3, 6, -2, -5, 3, -1, 6, -7, -9, -8, -4] ,\ [11, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 27, 1, 4, 7, -6, -2, 5, -3, 9, -8, -5, -6, 8, -3, -9, -7, -4, -1, 2, -3, -9, -2, -4, -8, 1, 5, -7, -6, -6, -7, -5, 9, 4, 3, -8, -2, -1, -9, -1, -3, -8, 7, -2, 6, -4, -5, -8, -2, 4, -5, -1, -6, 7, -3, 9, -2, 8, 1, -7, -6, -4, 9, -5, -3, 7, -3, 6, 1, -5, -9, 2, -8, -4, -4, 5, -9, -2, 3, 8, -1, 6, -7] ,\ [13, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 27, 5, 6, 8, -1, -4, -7, -9, -2, -3, -1, -9, 3, -2, -5, -6, -4, -8, -7, -4, 7, -2, -8, 9, 3, -5, 1, -6, -9, 5, -4, -3, -8, -2, -7, -6, 1, -2, -8, -7, -4, -6, 1, 3, 9, -5, 6, -3, -1, -5, 7, -9, -8, 4, -2, 7, -1, 6, 9, 3, -4, -2, -5, 8, -3, -4, 5, 6, -2, 8, 1, -7, -9, -8, 2, -9, -7, -1, 5, -6, 3, -4] ,\ [13, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 27, -2, -6, -4, -8, -9, -1, -7, -5, -3, 7, -1, 3, 6, 2, -5, -8, 4, -9, 9, -8, -5, -4, 3, 7, -6, -1, -2, 8, -2, 1, -5, -4, -9, 3, -6, -7, -4, -7, -9, -2, -6, -3, 5, -8, -1, -5, -3, -6, -7, -1, -8, 9, 2, 4, 1, 5, -8, 9, 7, 4, 2, 3, -6, -3, -9, 2, -1, 8, -6, -4, -7, -5, -6, -4, 7, 3, -5, -2, 1, 9, -8] ,\ [13, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 27, -8, -2, -3, 5, 4, -6, -9, -1, -7, 9, -4, 6, -8, 1, -7, -5, 2, -3, -7, 1, -5, -2, -9, -3, -6, -8, 4, -1, -7, -4, -6, 2, -8, 3, -5, 9, -6, -5, -8, -9, 3, -1, -7, -4, -2, -3, -9, 2, 7, -5, -4, 8, 6, -1, -2, 3, 7, -1, -6, 5, 4, -9, 8, -4, 6, 1, -3, -8, -9, 2, -7, -5, 5, 8, -9, -4, 7, 2, -1, -3, -6] ,\ [11, 2, 1, 2, 3, 0, 0, 0, 0, 0, 0, 27, -9, 2, -8, 3, -1, 4, -7, -5, -6, -4, -7, 5, 2, 9, -6, -3, -8, -1, -3, 6, -1, 8, -5, -7, -2, -9, -4, -7, -9, -3, -6, -2, -8, 4, 1, -5, -6, -1, -2, -5, -4, -3, -9, 7, -8, -8, 5, -4, -1, 7, -9, 6, 3, 2, 2, -3, 7, -4, 8, -5, -1, 6, -9, 5, 4, -6, 9, 3, 1, -8, -2, -7, -1, -8, 9, 7, -6, -2, 5, -4, -3] ,\ [9, 1, 2, 5, 1, 0, 0, 0, 0, 0, 0, 27, 6, -1, -8, 3, -9, -4, 7, -5, -2, -7, 5, -3, -1, -2, 8, -9, -4, 6, -9, -4, 2, -5, 6, -7, -3, -8, -1, -8, -6, -5, -7, -1, -2, 4, -3, -9, -3, 9, -1, -8, -4, 6, 5, -2, 7, 4, -2, -7, -9, -3, 5, -6, 1, 8, 1, -8, -4, -6, -7, 3, 2, -9, -5, -5, 3, 6, 2, -8, -9, -1, 7, 4, -2, -7, -9, 4, -5, 1, 8, -6, -3] ,\ [10, 1, 0, 3, 0, 0, 0, 0, 1, 0, 0, 27, -2, 8, 7, -3, -9, 1, 4, -6, -5, -4, -1, -5, -2, -8, -6, -9, -7, -3, 3, 9, -6, 4, 5, -7, -2, -1, -8, -6, -7, -8, -1, -2, -5, 3, -9, -4, -5, 2, -3, -9, -6, -4, 1, -8, 7, -9, 4, 1, -7, -3, -8, -5, -2, -6, 8, 5, 9, -6, -1, 3, 7, -4, 2, -1, 6, 4, -5, -7, 2, -8, -3, -9, -7, 3, -2, 8, 4, -9, 6, 5, -1] ,\ [12, 0, 1, 2, 0, 0, 0, 0, 1, 0, 0, 27, -9, -4, -1, -6, 2, -7, -5, -3, -8, -6, 5, -3, 8, 9, 4, -2, 1, -7, -2, -7, -8, -5, -3, -1, 6, -4, -9, -7, -8, 2, -1, -4, -3, -9, 5, -6, -1, -6, -4, -2, -5, -9, -7, -8, 3, 5, -3, 9, 7, -6, 8, 4, 2, -1, 4, -1, 5, 3, 7, -6, 8, 9, -2, -3, -9, -7, -4, 8, 2, -1, -6, -5, -8, 2, 6, -9, -1, 5, -3, 7, -4] ,\ [12, 2, 0, 0, 1, 0, 0, 0, 1, 0, 0, 27, -1, 4, 7, -5, -2, 6, -8, -9, -3, -3, -5, 2, 1, 8, -9, -7, -6, -4, -6, -8, -9, -7, -4, -3, -5, 1, -2, 4, -7, 3, 9, -6, -2, -1, -8, -5, -8, 1, 6, -3, -7, 5, 4, -2, -9, -9, -2, -5, -8, 1, -4, -3, 7, -6, 5, 9, -8, -6, 3, -1, -2, -4, 7, -7, -3, 4, 2, -9, 8, -6, -5, 1, 2, 6, -1, -4, -5, 7, 9, -3, -8] ,\ [8, 2, 0, 2, 1, 0, 0, 0, 1, 0, 0, 27, 6, 7, -2, -8, -4, -1, -5, -3, 9, 4, 1, 8, -3, 9, -5, -6, 2, -7, -3, -5, -9, -6, 2, 7, -8, -1, -4, -7, 6, -5, -9, 1, -8, -2, 4, -3, -8, -3, 4, -7, 5, -2, -1, -9, -6, 9, -2, -1, 4, -3, -6, -7, -5, 8, -2, -8, -3, -1, -7, -4, 9, -6, -5, 1, -4, 7, -5, 6, -9, -3, 8, 2, 5, -9, 6, -2, -8, 3, -4, 7, -1] ,\ [11, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 28, -9, -5, -8, -3, -2, 6, -7, -4, 1, -1, 6, -4, -7, 9, -8, -2, -3, 5, 7, -2, -3, -5, -1, 4, 8, -6, -9, -2, -7, 1, -9, 4, -5, 3, 8, -6, 5, -4, -6, -2, 8, -3, -1, 9, -7, -3, 8, -9, 1, -6, -7, -5, -2, 4, -4, -3, 2, 6, -7, -1, -9, 5, -8, -8, 9, -7, -4, 5, -2, -6, 1, 3, -6, -1, -5, -8, 3, 9, 4, -7, -2] ,\ [10, 2, 1, 4, 2, 0, 0, 0, 0, 0, 0, 28, -5, -8, -4, -3, -9, 7, -2, -6, 1, -6, -9, -3, -1, 8, -2, 4, 5, 7, -7, 2, -1, -5, 6, -4, -8, 3, -9, -1, 3, -2, -7, -5, 9, -6, -4, -8, -9, 7, -5, -8, -4, 6, 3, -1, -2, 8, 4, -6, -2, -1, -3, 7, 9, 5, 3, -6, -8, -9, -7, -1, 5, -2, 4, 4, 1, 7, -6, -2, -5, -9, -8, -3, -2, -5, 9, -4, 3, -8, -1, 7, -6] ,\ [15, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 28, -7, -9, 4, -8, 3, -6, -1, 5, -2, 3, -2, -6, -1, -7, 5, -4, -8, 9, -1, -5, -8, -9, -2, -4, -3, -7, 6, -2, -1, 7, 5, 4, -9, -8, -6, -3, 8, -4, -9, -3, -6, -1, -5, -2, -7, -5, -6, 3, -7, 8, -2, -9, 4, 1, -4, -7, 1, -2, 9, 8, -6, 3, 5, 9, -8, 2, -6, -5, -3, -7, 1, 4, 6, -3, -5, 4, -1, 7, -2, 9, -8] ,\ [12, 1, 0, 2, 3, 0, 1, 0, 0, 0, 0, 28, -6, 8, -7, -4, -1, -5, 9, -2, -3, -4, 1, -9, 3, 8, 2, -7, 5, 6, 2, -3, -5, -6, -7, -9, -8, -1, -4, -3, 6, -8, -9, 2, -7, -5, 4, -1, -7, -5, -4, -1, 3, -6, -2, -9, 8, -1, -9, -2, -8, -5, 4, -3, -6, 7, -5, 2, -6, 7, -4, 3, 1, -8, -9, -9, 7, -1, -5, 6, -8, -4, 3, -2, 8, -4, 3, 2, 9, -1, 6, -7, -5] ,\ [13, 0, 0, 2, 1, 0, 0, 0, 1, 0, 0, 28, 2, -1, -9, -8, -7, 3, -6, -4, -5, -5, -3, -7, -4, -2, -6, 1, 8, -9, 8, 6, 4, -9, 5, -1, -7, -2, -3, -9, -8, -2, -7, 6, -5, 4, -3, -1, -3, -4, 5, -1, -9, -8, -2, 6, 7, 1, -7, -6, -2, -3, -4, 9, -5, -8, -4, 2, -8, 3, 1, 9, 5, -7, -6, -7, -5, 1, -6, 8, 2, 3, 9, -4, -6, -9, -3, 5, -4, 7, -8, 1, -2] ,\ [11, 2, 1, 1, 0, 0, 0, 0, 1, 0, 0, 28, -8, 3, 7, 2, 4, -5, -1, -9, -6, 4, -5, -9, -1, 3, -6, -8, -2, 7, 1, 6, -2, -7, -9, -8, -4, -3, 5, -9, -7, -1, -3, -2, -4, -5, -6, -8, 6, -2, -3, -5, 8, -1, -9, -7, -4, 5, 8, -4, -6, 7, -9, 3, 1, -2, 7, -1, 6, -8, 5, -3, -2, 4, 9, 3, -4, -8, -9, 6, -2, -7, -5, -1, -2, -9, 5, 4, -1, 7, 6, -8, -3] ,\ [9, 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 28, -6, 9, -8, -7, -4, 3, -2, -5, -1, -4, -5, 7, -9, -1, 2, -6, 3, -8, -1, -3, -2, 6, -8, -5, 7, 4, -9, -5, 7, -1, -8, -2, -9, 4, -6, -3, 8, -4, -6, -3, -5, -7, -1, 9, 2, 3, -2, -9, -4, -6, 1, -8, -7, -5, 9, 8, 4, 2, -3, -6, 5, 1, 7, -7, 6, -5, -1, 9, -8, -3, -2, -4, 2, -1, -3, 5, -7, -4, 9, 8, -6] ,\ [10, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 28, -2, -4, 1, -5, 8, -3, -9, 7, 6, -7, -8, 6, 9, 1, -2, -4, 5, -3, 9, -5, -3, -7, -4, -6, -1, 8, -2, -1, -9, 2, -3, 5, -8, -6, -4, -7, -5, 3, -4, -1, -6, -7, -2, -9, 8, -6, 7, -8, 4, 2, 9, 3, 1, -5, 8, -1, -7, -2, -3, -4, 5, -6, 9, -3, -6, -5, -8, -9, -1, -7, -2, 4, 4, -2, 9, 6, -7, -5, -8, 3, -1] ,\ [9, 0, 3, 1, 1, 0, 0, 0, 1, 0, 0, 28, -3, 5, -6, 8, -1, -9, -2, -4, -7, -9, -7, -4, -5, 6, -2, 8, -1, 3, -1, -8, -2, 4, -7, 3, -9, 6, -5, -8, -2, -7, -6, -5, 1, -4, -3, -9, -4, 1, -5, -9, 3, -7, -6, -2, 8, 6, -3, 9, -2, 8, 4, -7, -5, 1, 5, -9, -1, -7, -4, -6, 3, 8, -2, 2, -6, -8, -3, 9, -5, 1, 7, -4, 7, 4, -3, -1, -2, -8, 5, 9, -6] ,\ [15, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 29, 8, -9, -6, -1, -5, -2, -7, 4, -3, 3, -5, 7, -4, 9, 8, 2, 1, -6, -1, 2, -4, 7, -6, -3, -9, -5, -8, 4, -8, -9, -2, -1, -7, -6, 3, 5, -7, 6, -5, -8, -3, -9, -4, -2, -1, -2, -3, 1, -5, 4, -6, -8, -9, 7, 5, -1, -8, -9, -7, 4, 3, -6, -2, -6, 4, 2, -3, 8, 5, -1, -7, -9, -9, -7, 3, 6, -2, 1, 5, -8, -4] ,\ [16, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 29, 6, -7, 3, -9, -5, 8, 2, 1, -4, -8, -1, 4, -3, -2, -7, -9, -5, -6, -5, 9, -2, -6, -1, -4, -3, -7, 8, -7, 6, -1, -5, 8, 9, -4, -2, -3, 4, -8, -5, -2, 3, -1, -7, 6, -9, -3, -2, -9, 7, -4, -6, 5, 8, -1, 9, 3, 7, -1, 6, 2, -8, -4, -5, 2, -4, -6, -8, -9, -5, 1, -3, -7, 1, -5, 8, -4, 7, 3, -6, -9, -2] ,\ [18, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 29, 6, -8, 9, 3, -4, -2, 1, -7, -5, -4, -7, -3, -5, -6, -1, 9, -2, -8, 5, 2, -1, -8, -9, -7, -3, 4, -6, 1, -3, -5, -9, -7, -6, 2, 8, -4, -8, 9, 2, -4, -1, -5, -7, -6, 3, 7, 4, -6, -2, -3, 8, -5, -1, -9, -2, 1, -4, -6, 5, -3, -8, -9, -7, -3, -6, -8, -7, -2, 9, 4, -5, 1, 9, -5, 7, 1, 8, -4, 6, 3, -2] ,\ [16, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 29, 7, 2, -4, -1, 9, 5, -8, -3, -6, -1, 8, -5, -7, -6, -3, -4, -9, -2, -6, -9, 3, -2, 8, -4, 5, 1, 7, -4, -6, 8, -3, -5, -1, -7, 2, 9, -3, -1, -9, -8, -7, -2, -6, -4, -5, -2, -5, -7, 6, -4, -9, 1, 8, 3, 5, -7, -1, 9, -3, -8, 2, -6, -4, -8, -3, -6, 4, 2, 7, -9, 5, -1, 9, 4, -2, -5, 1, -6, 3, -7, -8] ,\ [12, 1, 1, 2, 0, 0, 0, 0, 1, 0, 0, 29, 6, -1, -2, -7, -4, 8, -9, -3, -5, 7, 5, -9, -2, -3, -1, 4, -8, -6, -8, -4, 3, -6, 9, -5, -2, -1, 7, -5, 3, -1, -4, 2, 7, -8, -6, 9, -9, -8, 4, -1, -5, -6, -7, -2, -3, -2, -6, -7, -9, -8, 3, 1, 5, -4, 4, -9, -6, 3, 1, 2, -5, -7, 8, -1, -7, 5, -8, -6, 9, -3, -4, -2, -3, 2, 8, 5, -7, 4, 6, -9, -1] ,\ [12, 3, 1, 0, 0, 0, 0, 0, 1, 0, 0, 29, 7, -5, -4, -9, 8, -1, -3, 6, -2, -9, 8, -1, 3, -2, -6, 5, 4, -7, -2, -6, -3, 5, -4, -7, 9, 1, -8, -4, -1, 2, -7, -5, 9, -6, -8, -3, 3, -7, -8, -2, 6, -4, -1, -5, -9, -5, -9, -6, -8, -1, 3, 7, 2, -4, -6, 4, 7, 1, -3, -2, -8, 9, -5, -1, -3, -5, -4, -9, 8, 2, -7, 6, -8, 2, -9, 6, 7, 5, -4, -3, -1] ,\ [13, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 29, -7, -6, -5, -2, -1, -9, 8, 4, -3, 1, -2, -3, -4, 8, -5, 9, -7, 6, 9, -8, -4, -6, -3, 7, 2, -1, -5, -3, -5, 1, -7, -9, -4, -6, 2, -8, -2, 4, 8, -5, -6, 3, 7, -9, -1, 6, -9, 7, -8, -2, 1, -5, 3, 4, -8, -7, -6, -1, -4, 2, -3, -5, 9, -4, -3, 2, -9, 5, -6, 1, 8, -7, -5, 1, -9, -3, -7, -8, 4, -6, -2] ,\ [16, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 30, -5, 4, 7, -8, -6, -9, 2, 1, -3, -6, -8, 9, -1, 2, -3, -5, -7, -4, 1, -2, -3, -7, -4, -5, -6, 8, -9, 8, 3, -6, -4, -5, -2, -7, 9, -1, -7, -9, -1, -3, 8, -6, 4, -2, 5, -4, -5, -2, -9, -7, 1, -8, -3, -6, 2, 1, 4, -5, 9, 7, 3, -6, -8, -3, -7, 5, -6, -1, -8, -9, -4, 2, -9, 6, 8, -2, 3, 4, 1, -5, -7] ,\ [17, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 30, 4, -6, -1, 8, -7, -2, 9, -3, 5, -5, 2, -9, -6, -1, -3, -4, 8, 7, -7, -8, -3, -9, 5, -4, -1, -6, -2, -2, -5, -4, -1, 3, -7, -8, -9, 6, -9, -3, 6, -2, -8, 5, -7, -4, -1, -8, 1, 7, 4, -6, -9, 2, -5, -3, -3, 7, -2, -5, -4, 8, -6, 1, -9, 6, -9, 8, -3, 2, 1, 5, 7, -4, -1, 4, 5, -7, -9, 6, -3, -2, -8] ,\ [17, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 30, 6, -8, -4, -1, 5, 2, -7, -3, 9, -9, -5, -2, 3, 8, -7, -6, -4, -1, -7, 1, -3, 4, -9, -6, -5, -8, -2, -8, 2, -1, -6, -3, 5, -4, -9, -7, -3, 6, 9, -7, -2, -4, 1, -5, -8, -5, -4, 7, 8, -1, -9, -2, -6, 3, -2, 7, -8, -5, 6, -3, -9, -1, 4, 1, 9, -5, -2, -4, 8, 3, -7, -6, -4, 3, 6, -9, 7, -1, 8, 2, -5] ,\ [15, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 30, -8, 4, -5, -7, 1, 3, 2, -9, 6, -9, -3, -1, -2, -6, -8, -5, 4, 7, -6, -7, -2, 9, -5, -4, -1, 3, -8, -4, -5, -7, -3, -8, -2, -6, -1, 9, 1, -8, -3, -6, -4, -9, 7, -5, -2, 2, -6, 9, -1, -7, -5, -4, 8, 3, -5, 2, 4, -8, -9, 7, 3, -6, 1, -7, -9, 6, 4, -3, -1, -8, -2, 5, 3, 1, -8, 5, 2, -6, -9, -7, -4] ,\ [10, 4, 2, 2, 2, 0, 0, 0, 0, 0, 0, 30, -4, 7, 1, -8, -5, -3, 6, 2, -9, 3, -5, 8, -2, -6, -9, -1, -7, -4, -2, 6, -9, -1, 4, -7, -8, -3, -5, -7, -3, -2, 9, -8, 6, -4, -5, 1, 1, -4, -6, 3, -2, -5, -7, -9, 8, -8, -9, -5, -7, -1, 4, 3, 6, -2, -9, 8, 3, -4, -7, -2, 5, 1, -6, 5, -2, 4, -6, -3, 1, -9, -8, 7, -6, -1, 7, -5, 9, -8, -2, 4, -3] ,\ [13, 0, 1, 3, 0, 0, 0, 0, 1, 0, 0, 30, 3, -5, -7, -2, -6, 8, -1, -4, 9, -4, -6, 1, -5, -9, 3, -8, -2, -7, -2, -8, -9, 7, -4, -1, -3, 5, -6, 9, 1, 6, 8, -5, -2, 4, -7, -3, -7, -4, -5, 3, -1, 9, -2, 6, -8, 8, -3, -2, -4, -7, -6, -9, -1, 5, 6, -2, 8, -1, -3, -5, 7, -9, -4, -1, -9, 4, -6, 8, -7, -5, -3, 2, -5, 7, 3, -9, 2, -4, 6, 8, -1] ,\ [13, 3, 0, 0, 1, 0, 0, 0, 1, 0, 0, 30, -1, 2, -6, -5, 4, -9, -7, -8, -3, -7, 4, -8, -3, -1, -6, -9, -2, 5, 3, 5, -9, -2, -8, 7, -4, -6, 1, 2, -1, -7, -6, 5, 3, 8, -4, -9, -5, -8, 3, 9, -7, -4, -6, -1, -2, -9, 6, -4, -1, -2, 8, -3, -5, 7, -4, 7, -2, 8, 3, -5, -1, 9, 6, -6, -3, 1, -4, -9, 2, -5, -7, -8, 8, -9, -5, -7, 6, 1, -2, 3, -4] ,\ [15, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 30, -3, -6, -4, -8, -1, -9, 5, -2, 7, -5, -2, -1, -3, 7, -6, -4, -8, -9, 9, -7, -8, -5, -2, 4, -6, -3, 1, -6, 1, -5, -4, -8, -3, -7, 9, -2, -7, 4, -9, 1, 5, -2, 3, -6, -8, -2, -8, 3, -6, -9, 7, -1, -5, 4, 1, -9, 2, 7, -3, -5, -8, 4, -6, -8, 5, 6, 2, 4, -1, -9, -7, -3, 4, 3, -7, 9, -6, 8, -2, 1, -5] ,\ [13, 0, 0, 1, 3, 0, 0, 0, 1, 0, 0, 30, -8, -9, 2, 5, -3, -6, -4, -1, 7, -3, 5, 1, 4, -2, -7, -9, 6, 8, -7, -6, -4, -9, -1, 8, 5, -2, -3, -6, 7, 9, -3, -4, -1, 8, -5, 2, -4, -1, -8, -6, -5, -2, -3, 7, -9, -5, -2, -3, 8, -7, 9, -6, 4, -1, -1, 3, -6, -7, 8, -4, 2, -9, 5, 2, -4, -5, 1, -9, -3, -7, -8, 6, -9, 8, -7, -2, -6, 5, 1, -3, -4] ,\ [7, 2, 0, 2, 3, 0, 0, 0, 1, 0, 0, 30, -9, -2, -1, 4, -5, -6, -7, 3, 8, 7, -8, -4, -3, -2, 9, 5, -1, 6, 5, 3, 6, 7, 8, -1, -9, -2, 4, -8, 1, -7, -5, 4, -2, -3, -6, -9, -2, -6, -3, -1, -9, -7, 4, -8, -5, -4, 9, 5, -8, -6, -3, -1, 7, -2, -6, -7, 2, -9, -3, -4, -8, -5, 1, 1, -5, 9, -2, 7, -8, -6, -4, -3, 3, -4, 8, -6, -1, 5, 2, -9, -7] ,\ [15, 2, 1, 4, 1, 0, 0, 0, 0, 0, 0, 31, -2, 1, -4, 8, -9, -6, 5, -3, -7, -9, -3, -7, 5, -4, -1, -8, 2, -6, 5, -8, -6, -2, -3, 7, -1, 9, 4, -1, -2, 3, 9, -8, 4, -6, -7, -5, -6, -4, -5, -7, -2, -3, -9, -8, -1, 7, 9, -8, -6, 1, 5, -3, -4, -2, -8, -6, -1, -4, 7, -9, -2, -5, 3, -3, 7, -2, -1, 5, 8, 4, -6, -9, 4, 5, -9, 3, 6, 2, -7, 1, -8] ,\ [13, 3, 1, 4, 1, 0, 0, 0, 0, 0, 0, 31, 9, 2, -4, -7, -6, -1, -8, 3, -5, -8, 1, -6, 3, 5, -9, 4, -2, -7, -7, -5, -3, -8, -4, -2, -6, 9, -1, -6, -8, -5, -9, 3, -7, -2, -1, 4, 4, -3, -1, -2, -8, -5, 7, -6, -9, 2, -7, 9, 6, -1, -4, -5, 8, -3, 1, -6, 7, -5, 9, 8, -3, 4, -2, -3, 4, -2, -1, -7, 6, 9, 5, -8, 5, -9, -8, -4, 2, -3, 1, -7, -6] ,\ [13, 7, 1, 0, 1, 0, 0, 0, 0, 0, 0, 31, 8, -6, -2, 1, 4, -3, -5, -9, -7, -7, -1, -5, -9, -2, 8, 3, 6, -4, -3, 4, -9, -6, 5, 7, -2, -8, 1, 9, -5, -3, -2, -8, -1, -7, -4, -6, 4, 2, -7, -5, -6, -9, 8, 1, 3, 6, -8, -1, -3, -7, -4, -9, 5, -2, -2, 7, -8, 4, -9, 6, -1, 3, -5, 1, -9, -4, 7, -3, -5, 6, -2, 8, -5, -3, -6, 8, -1, -2, -4, 7, -9] ,\ [11, 2, 0, 6, 0, 0, 1, 0, 0, 0, 0, 31, 9, -6, 2, -3, 8, 1, -7, 4, 5, 7, -4, -5, 6, -2, -9, 1, -3, -8, -8, -3, -1, -7, -5, 4, 6, -9, -2, -5, 9, -3, -2, -6, 7, -8, -1, -4, -4, 8, -7, -1, 9, -5, -2, 6, -3, -2, -1, 6, -4, -3, -8, -5, -7, -9, -3, -5, 4, 8, -1, -6, -9, 2, -7, -6, 7, 8, -9, -4, -2, -3, 5, 1, -1, 2, 9, 5, -7, 3, -4, -8, -6] ,\ [8, 0, 0, 4, 1, 0, 1, 0, 1, 0, 0, 31, -4, 2, 9, 6, -1, 3, 5, -8, -7, -3, -6, -8, -2, -5, -7, -4, -1, 9, 5, -7, -1, -8, -4, -9, -2, -6, -3, 2, -5, 3, -9, -6, 4, -1, 7, 8, -9, 4, -7, 1, 3, -8, 6, -5, -2, -8, -1, 6, 5, 7, -2, -9, -3, -4, -1, 3, -2, 7, -9, 6, 8, -4, -5, -6, -9, -4, -3, -8, -5, -7, 2, 1, -7, -8, 5, 4, -2, -1, 3, -9, -6] ,\ [19, 1, 0, 2, 0, 0, 0, 1, 0, 0, 0, 32, -7, -4, 1, -9, -8, -3, -6, 2, 5, -9, -5, -8, 6, -2, -4, 3, 7, -1, 6, -3, 2, -5, -1, -7, -9, -4, -8, -4, -6, -9, -1, 3, -8, -2, -5, -7, -1, 7, -3, -2, -6, 5, -8, 9, -4, -8, 2, -5, 7, -4, 9, 1, -6, -3, -3, -9, -7, -8, 5, -6, 4, 1, 2, 5, 1, -4, -3, -9, 2, -7, 8, -6, -2, 8, -6, 4, 7, -1, -5, 3, -9] ,\ [12, 5, 1, 4, 0, 0, 0, 0, 0, 0, 0, 32, 4, 2, -9, 1, 8, 7, -6, -5, -3, -3, -7, -8, -2, -5, -6, 9, -4, -1, -5, -6, -1, 4, -9, -3, -8, -7, 2, -8, 3, -2, -5, 7, -4, -1, -9, -6, -9, -4, 5, -3, -6, 1, -7, -2, 8, -7, -1, 6, -9, -2, -8, -4, 3, -5, -2, -5, 7, 8, -1, -9, -3, 6, 4, 1, -9, 4, -6, 3, 5, 2, -8, 7, 6, -8, -3, -7, 4, -2, -5, 1, -9] ,\ [17, 1, 0, 2, 0, 0, 0, 0, 1, 0, 0, 32, 3, 6, -1, -2, 5, -8, -9, 4, 7, 5, -8, -4, -7, -9, -3, -1, -6, 2, -7, -9, -2, -6, 1, -4, 5, 8, -3, -6, -7, 9, -4, 8, -1, -3, -2, -5, -1, 2, -5, 3, -6, -9, 8, -7, -4, 8, -4, -3, -5, 7, 2, -6, -9, -1, 4, -3, -6, 8, -2, -5, -7, 1, -9, 2, -1, -8, -9, -3, 7, 4, -5, 6, -9, 5, -7, -1, -4, 6, 2, -3, -8] ,\ [17, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 32, 4, 6, 2, 8, -7, -5, -3, 9, -1, -9, 7, -5, 3, -1, -6, 8, -4, -2, -1, -8, -3, -2, -4, 9, -5, 6, -7, -5, -4, -8, -1, -9, 2, 7, -3, -6, -7, -2, -1, 6, -3, -4, -9, -5, -8, -6, 3, -9, -5, 8, -7, 1, -2, 4, 8, 5, -7, -4, -6, 3, -2, -1, 9, 3, -9, -4, 7, -2, -1, 6, 8, -5, -2, 1, -6, -9, 5, 8, -4, -7, -3] ,\ [17, 2, 2, 0, 2, 1, 0, 0, 0, 0, 0, 32, -4, -1, 6, 7, 9, 3, -5, -8, -2, 3, -8, -2, 5, -4, -1, -9, 7, -6, -5, -7, -9, 8, -2, 6, -3, 4, -1, -2, 3, 4, -6, -7, 8, -1, -5, -9, -1, -9, 7, -4, -5, -2, -6, -3, -8, 6, -5, 8, -1, -3, -9, -7, 2, -4, 7, -6, 1, 3, 8, -4, -2, -9, 5, 9, -4, -5, 2, -1, -7, -8, -6, 3, -8, -2, -3, -9, 6, -5, 4, 1, -7] ,\ [17, 0, 1, 6, 1, 0, 0, 0, 0, 0, 0, 33, -1, -5, 4, -6, -8, -7, -2, 9, -3, -2, -9, -8, 1, -3, 4, -7, -5, -6, -3, 6, -7, -5, -9, 2, 4, 1, -8, -4, 7, -1, 9, 5, -6, -3, 8, 2, -6, 2, -9, -3, 4, -8, -1, 7, -5, 5, -8, -3, -7, -2, 1, -6, 4, -9, -7, 3, 2, -8, 1, -9, -5, 6, -4, -8, -1, -5, -4, -6, -3, 9, -2, 7, -9, -4, 6, 2, 7, -5, -8, -3, -1] ,\ [22, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 33, -8, 9, -3, -2, -1, 6, -5, 4, -7, 1, -4, 2, -8, 5, -7, -9, -6, 3, -7, -5, -6, -9, -3, -4, -2, 8, -1, -2, -8, -4, 3, -7, -9, 1, -5, -6, -6, 7, -1, -4, 2, 5, 3, -9, -8, -9, -3, 5, 6, 8, -1, -7, -2, -4, -4, -1, 8, -5, -9, 3, -6, -7, 2, -3, -2, -9, -7, -6, 8, 4, 1, 5, 5, -6, 7, -1, 4, -2, -8, 3, -9] ,\ [18, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 33, -9, 7, -3, -1, 6, 8, 5, -2, -4, -6, -5, -1, -2, -4, 7, -3, -8, -9, -4, -2, 8, 5, 3, -9, -1, -7, 6, 5, -9, 2, -4, -8, -3, 6, -1, -7, -1, -8, -4, -6, -7, -2, -9, 5, 3, -3, 6, -7, -9, -5, 1, 2, 4, -8, -2, -3, -9, -7, 1, -4, -8, -6, -5, -7, 1, 6, 8, -9, 5, 4, -3, -2, -8, 4, 5, -3, 2, -6, 7, -9, -1] ,\ [16, 3, 0, 1, 0, 0, 0, 0, 1, 0, 0, 33, -4, -3, -7, 2, -5, 9, -1, 8, -6, 6, -1, -2, -4, -7, -8, 9, 5, 3, -8, -9, -5, -1, -6, -3, -7, -4, -2, -5, -4, -9, 3, 1, -2, -6, -7, -8, -3, 6, 8, 7, 4, 5, 2, -9, -1, 2, 7, -1, -9, -8, -6, -5, -3, -4, -9, 5, -4, -8, -2, 1, -3, 6, 7, 7, -2, -3, -6, -9, 4, 8, -1, -5, -1, -8, 6, -5, 3, -7, 4, 2, -9] ,\ [18, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 33, 2, -6, -5, -8, 7, -9, -4, 3, -1, -4, -3, 7, -5, 1, -2, -8, -9, -6, -9, -1, 8, -3, 4, -6, -5, -7, 2, 5, 2, 6, -9, -3, -4, 1, 8, -7, -3, 4, -1, 6, -8, 7, -2, -5, -9, 7, -8, 9, -1, -2, -5, -3, -6, -4, -8, -7, -4, 2, -6, 3, 9, -1, 5, 1, -9, -2, -7, -5, -8, -6, -4, 3, -6, 5, -3, 4, -9, 1, 7, -2, -8] ,\ [18, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 33, -1, 3, 9, -7, -8, -2, -5, -6, -4, 7, -6, -4, -1, 3, -5, 2, -8, -9, -2, -8, 5, -4, 6, -9, -1, -7, -3, -4, -9, -2, -5, -7, -8, -3, 1, 6, -6, 5, -8, -3, 9, 1, -4, 2, -7, -3, 7, 1, -2, -4, -6, -9, 5, 8, -5, 4, -3, -8, -1, 7, -6, 9, -2, -8, 2, 6, -9, 5, -3, 7, -4, 1, -9, -1, -7, 6, 2, -4, -8, 3, -5] ,\ [14, 3, 0, 1, 1, 0, 0, 0, 1, 0, 0, 33, -7, -5, -4, -6, 3, 9, 8, -2, 1, 1, -9, 2, -8, -4, 7, -5, -3, -6, -8, -6, -3, -2, 5, -1, -9, -7, -4, -3, -8, 9, -1, -6, 2, 4, -5, -7, 6, -1, 5, -4, -7, -3, -2, -8, -9, -2, 4, -7, -9, 8, -5, -1, -6, 3, 5, 3, -1, 7, 2, -4, -6, 9, -8, -9, -2, 8, -3, -1, -6, -7, 4, 5, -4, 7, 6, -5, -9, 8, -3, 1, -2] ,\ [16, 2, 1, 0, 1, 0, 0, 0, 1, 0, 0, 33, -2, 6, -9, -1, -4, 3, -8, -5, -7, -3, -8, 5, -7, 9, 2, -1, -6, -4, 4, 7, 1, -6, -5, -8, -2, -3, 9, -6, -5, -3, 8, -1, -4, -7, -9, -2, -8, -9, -4, -2, 7, -6, -3, -1, 5, -7, -1, 2, -9, -3, 5, 6, 4, 8, -9, -2, -8, 5, -6, -1, 4, 7, -3, 1, -3, -7, -4, -8, 9, -5, -2, 6, 5, 4, -6, 3, -2, 7, -9, 8, -1] ,\ [11, 1, 1, 1, 2, 1, 0, 0, 1, 0, 0, 33, -5, -1, 7, 4, 6, 9, -8, 3, -2, 8, -9, -3, -7, -1, -2, 4, 5, -6, -4, 6, 2, -8, -5, 3, -9, -1, 7, -2, -8, 9, 5, 3, -1, 6, -7, -4, -3, -5, -6, 2, -4, -7, -1, -8, -9, 1, -7, -4, -6, 9, 8, -5, -2, 3, 6, -2, -8, -1, 7, -4, -3, -9, -5, -7, -3, 5, 9, -8, -6, 2, -4, -1, -9, -4, -1, -3, -2, 5, -7, 6, -8] ,\ [19, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 34, 9, 8, -3, -7, 6, 5, -2, 4, -1, -7, -4, 2, -9, -3, 1, 6, -5, -8, -1, -6, 5, -4, -2, -8, -9, -3, 7, -8, 1, -7, -2, -9, -4, -5, 6, 3, 5, -2, -9, -6, -1, -3, -7, -8, -4, -6, -3, -4, -8, 5, 7, -1, -2, 9, 4, 5, -8, 1, 7, -2, 3, -9, -6, -3, -9, -1, -5, -8, 6, -4, 7, 2, 2, -7, -6, -3, 4, 9, -8, -1, -5] ,\ [15, 0, 0, 3, 0, 0, 1, 0, 1, 0, 0, 34, -8, 9, -4, 6, -2, 3, -1, 7, -5, -7, -3, -2, 5, -1, -8, -9, -4, -6, -5, -1, -6, -4, -7, -9, 2, -8, -3, -1, -8, 7, -2, -4, -6, -3, 5, -9, -3, 6, 5, 9, -8, 1, -4, -2, -7, -2, -4, 9, -3, -5, -7, 8, -6, 1, -6, 5, -8, 1, -3, -2, 7, -9, -4, -9, 2, 1, 7, -6, 4, -5, 3, -8, 4, -7, 3, -8, 9, 5, -6, 1, -2] ,\ [15, 2, 2, 1, 0, 0, 0, 0, 1, 0, 0, 34, -8, 9, 6, 5, -7, -3, -2, -1, -4, -7, -3, -2, -4, 9, -1, -6, -8, -5, 5, -1, -4, 8, -6, -2, -7, -9, 3, -4, -5, 9, -6, -2, -8, -3, -7, 1, 6, -2, 3, -1, -4, 7, -9, 5, -8, -1, -7, -8, -3, -5, -9, 4, -6, 2, -9, 8, -7, 2, -3, -5, -1, -4, -6, 2, -6, 5, 7, -1, 4, 8, 3, 9, 3, -4, 1, -9, 8, -6, 5, -2, -7] ,\ [18, 2, 0, 2, 0, 0, 0, 0, 1, 0, 0, 35, 7, -5, 4, -9, -1, -2, 3, -6, -8, 8, 3, -1, -7, -6, -4, -9, -5, -2, 9, -6, -2, 5, -8, -3, -7, -1, 4, -5, -2, -9, -8, 4, -1, 6, 7, -3, -4, -7, -3, -2, 5, 6, -1, -8, 9, 1, -8, 6, 3, -7, -9, 2, -4, -5, 6, 9, 7, -4, -3, 8, -5, 2, -1, -3, 4, -5, -1, -2, -7, 8, -9, 6, 2, -1, -8, -6, 9, -5, -4, -3, -7] ,\ [16, 3, 2, 0, 0, 0, 0, 0, 1, 0, 0, 35, -8, 2, 6, -4, -5, -7, -3, 9, 1, 5, -9, 4, 3, -1, 2, 8, -7, -6, -3, -1, -7, -9, -6, -8, -5, -4, -2, -7, -5, -2, 6, -9, -1, -4, -8, 3, -6, -4, 9, -5, -8, 3, 1, 2, -7, -1, -8, -3, -7, 2, 4, -6, 5, -9, -9, -6, -8, 1, -7, 5, 2, -3, -4, -4, 7, 5, -2, -3, -6, -9, -1, -8, -2, 3, 1, 8, -4, 9, -7, 6, -5] ,\ [10, 3, 1, 2, 1, 1, 0, 0, 1, 0, 0, 36, -2, -3, -1, -7, 8, 5, -9, 6, -4, -7, -5, 4, 2, -6, -9, -8, -3, 1, -8, -6, 9, -1, 4, 3, -5, 7, -2, 5, 7, -6, -3, 9, -1, 2, -4, -8, 9, -1, 2, -4, -7, -8, -3, -5, -6, -4, -8, 3, 5, -2, -6, -1, -9, 7, -6, -2, 5, 8, 3, -4, -7, -1, 9, -3, 4, -7, -9, -1, -2, -6, -8, 5, -1, -9, 8, 6, -5, -7, 4, -2, -3] ,\ [7, 5, 1, 3, 1, 0, 0, 0, 1, 0, 0, 36, -3, 5, 8, -4, -1, -6, -7, -9, -2, 6, -4, -2, -3, -9, 7, 1, -8, -5, 7, -9, -1, 8, 2, -5, -6, -3, -4, -1, -2, -5, -7, -4, -9, 3, -6, -8, -4, -6, -7, -2, -8, -3, -5, -1, 9, -9, 8, -3, -6, 5, 1, 4, 2, -7, -5, -1, 4, -9, 3, -8, -2, 7, -6, 2, 7, -9, 1, 6, -4, 8, -5, 3, -8, 3, -6, 5, 7, 2, -9, -4, -1] ,\ [5, 3, 0, 4, 1, 1, 0, 0, 0, 1, 0, 36, -5, -4, -3, -7, -1, 2, -9, -8, -6, 2, 6, -1, -3, 9, -8, 4, 5, -7, 7, 9, -8, -4, 6, -5, -2, 3, -1, 8, -7, -5, 1, -3, -9, -6, -4, 2, -9, 1, -4, -2, -5, -6, -8, -7, -3, 3, -2, 6, 8, -4, 7, -5, -1, -9, -6, 3, -9, -5, -8, -1, 7, -2, 4, -1, -8, -7, -6, 2, 4, -3, -9, -5, 4, 5, -2, -9, 7, -3, 1, 6, -8] ,\ [22, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 37, 7, -1, -4, 3, -6, -5, 2, 8, 9, -9, -3, 6, -2, 8, -1, -5, -7, 4, -8, -2, -5, -7, -9, 4, -6, -1, -3, -4, 8, 2, 9, -3, 6, 1, 5, -7, -5, -6, -3, -4, -1, -7, -9, -2, -8, -1, -7, 9, -5, -2, -8, -3, 4, 6, -6, -4, 1, -8, -5, -9, -7, 3, -2, 3, 5, 8, -6, -7, 2, -4, 9, -1, -2, 9, -7, 1, -4, -3, 8, -6, -5] ,\ [21, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 37, -1, -4, -3, -7, 6, -2, -5, -9, -8, 7, -9, -2, -5, -1, -8, 6, 3, 4, 5, -6, -8, -4, -3, -9, -7, 2, -1, -8, 1, -9, 3, -5, -6, 2, 4, -7, -3, -5, 4, -1, -2, 7, 9, -8, -6, 2, -7, 6, 9, -8, -4, -3, -1, -5, 6, -8, -1, 2, -7, 3, -4, -5, -9, -9, 3, 7, -8, -4, 5, 1, -6, -2, 4, 2, -5, -6, -9, 1, 8, -7, -3] ,\ [18, 2, 1, 1, 1, 0, 0, 0, 1, 0, 0, 37, 8, -4, -3, 6, -2, -1, -9, 7, -5, -6, 7, -2, -9, -8, -5, -3, -4, 1, -1, -9, 5, 4, -3, -7, 8, -2, -6, -3, -8, 7, -1, 9, -2, -6, -5, 4, -9, -6, -4, -5, -7, 8, 2, 1, -3, -5, -2, -1, -3, -6, 4, -7, -9, 8, 2, -5, -8, 7, 4, 3, -1, -6, 9, 7, -1, 6, 8, 5, -9, 4, -3, -2, 4, -3, -9, -2, 1, -6, -5, -8, -7] ,\ [14, 4, 1, 2, 0, 0, 0, 0, 1, 0, 0, 37, -4, -5, -6, 1, -9, -8, 3, -7, 2, -1, 7, 9, 2, -6, -3, -8, -4, -5, -2, 8, -3, -5, -4, -7, -1, -9, 6, -7, -4, -1, -9, 5, -2, -6, -8, 3, -3, -6, 2, 7, 8, -4, 5, -1, 9, -8, -9, 5, -6, -3, 1, -7, 2, -4, 9, -3, 4, -8, -1, -5, -2, -6, -7, 6, 2, -8, -3, 7, -9, 4, -5, 1, -5, -1, 7, -4, -2, 6, 9, -3, -8] ,\ [13, 1, 0, 4, 1, 1, 0, 0, 1, 0, 0, 37, 8, -1, -9, 6, 3, -2, -4, -7, 5, -5, -3, -2, -7, 4, 9, 1, -8, 6, -7, -6, 4, -1, 5, -8, -9, 2, -3, 4, -2, -8, -3, -9, -5, 7, -6, -1, -9, -7, 1, -8, -2, -6, -3, 5, -4, 6, -5, -3, -4, -7, -1, 8, -9, 2, 3, -9, -6, -2, 8, -4, -5, 1, 7, -1, -4, 5, 9, -6, -7, 2, -3, -8, -2, -8, 7, 5, -1, -3, -6, 4, -9] ,\ [9, 2, 0, 2, 1, 0, 0, 0, 2, 0, 0, 37, -5, -3, 8, 2, -1, -7, -9, -4, 6, -2, -4, -7, -6, -9, -3, 1, -5, 8, -6, 9, -1, -8, 5, -4, -2, 3, 7, 8, -1, -3, -4, -2, 5, 7, -6, -9, -9, 2, -5, 3, -7, 6, -8, -1, -4, -7, -6, -4, 9, -8, -1, -3, -2, 5, 1, -7, -9, -5, 4, 2, 6, 8, -3, -4, -8, -6, -1, 3, -9, 5, -7, -2, -3, 5, -2, 7, -6, 8, 4, -9, -1] ,\ [19, 1, 1, 2, 1, 0, 0, 0, 1, 0, 0, 38, -4, 1, -6, -9, 8, -5, 3, -7, -2, 5, -9, 7, 4, -2, -3, -6, -8, -1, -3, 8, 2, -6, 1, 7, -5, -9, 4, -2, -3, -8, 7, -6, 1, -9, -4, -5, -9, -5, -1, -8, 3, -4, -7, -2, 6, -6, -7, 4, -5, -9, 2, -1, -3, 8, -1, -6, -3, -2, 4, -9, 8, 5, -7, -8, 4, -5, -3, -7, 6, -2, -1, 9, 7, 2, -9, -1, -5, 8, 4, -6, -3] ,\ [11, 2, 1, 5, 1, 0, 0, 0, 1, 0, 0, 38, -7, -8, -6, 3, 1, -5, -9, -4, -2, -5, -9, 1, 6, -4, 2, -7, -3, 8, 4, 2, -3, -9, -7, -8, -1, -6, -5, -1, -4, 2, -7, -5, 9, -6, 8, -3, -3, 7, -5, -8, -2, -6, 4, 1, -9, 9, -6, 8, -1, -3, -4, 5, -2, -7, 6, 3, -9, 5, -8, -1, -2, -7, 4, 2, -1, -7, 4, -9, -3, -8, -5, 6, -8, 5, 4, -2, -6, 7, -3, 9, -1] ,\ [10, 5, 1, 1, 1, 1, 0, 0, 1, 0, 0, 38, -7, -2, 1, -4, 8, -9, 3, -6, -5, -6, -5, -8, 1, -3, -7, 9, -2, -4, 3, 9, 4, -6, -2, -5, -7, -1, -8, 5, -4, -6, 9, -7, -1, 8, -3, 2, -1, -3, -2, -5, 6, -8, -4, -7, -9, -8, 7, 9, -3, 4, -2, -1, 5, 6, -4, -1, 5, -2, -9, 3, -6, 8, -7, -9, -8, 3, -7, 5, -6, 2, -4, 1, -2, 6, 7, -8, -1, 4, -5, -9, -3] ,\ [19, 2, 0, 1, 1, 1, 0, 0, 1, 0, 0, 39, -6, -1, 8, -9, -4, -5, -7, 2, -3, -4, 2, -5, -3, -7, -1, -8, -9, -6, -7, -3, -9, -6, -8, 2, 1, 5, -4, -8, 6, -7, -2, 5, -3, -4, -1, 9, 5, -9, -1, 7, -6, 4, -2, -3, -8, 3, -4, 2, -8, 1, 9, -5, -6, 7, -2, -8, -6, -1, 9, 7, 3, 4, -5, 1, -7, -4, 5, -3, 6, 9, -8, 2, -9, -5, 3, -4, 2, -8, -6, -7, -1] ,\ [12, 3, 4, 2, 0, 0, 0, 0, 1, 0, 0, 39, -9, 3, 6, -1, -8, -2, -7, -4, 5, -2, 5, -4, -3, 7, -6, 1, -8, 9, -7, -8, -1, 5, -4, -9, -3, -2, -6, -3, -6, 8, -2, -5, -7, -9, -1, 4, 4, 2, -7, -9, -6, 1, 5, -3, -8, -1, -9, 5, -8, -3, -4, 6, -7, -2, -6, -4, -9, -7, 1, -8, -2, 5, -3, -5, -1, -2, 4, 9, 3, 8, -6, 7, -8, 7, 3, -6, 2, 5, -4, 9, -1] ,\ [14, 1, 1, 1, 2, 1, 0, 0, 0, 1, 0, 39, -5, -1, 8, 9, -4, -7, -2, 6, -3, 7, -3, 4, 1, 6, -2, -5, -9, 8, -9, -6, 2, -8, -5, -3, -1, -7, -4, 6, 4, -5, -3, -7, 8, -9, -2, -1, -3, -2, 9, -5, 1, -6, -4, -8, 7, -8, -7, -1, 4, -2, -9, -3, 5, -6, -2, -8, 3, -6, -9, -1, 7, -4, -5, 4, -9, 6, -7, 3, -5, 8, 1, 2, -1, 5, -7, -2, 8, -4, 6, -3, -9] ,\ [15, 1, 2, 0, 0, 0, 0, 0, 2, 0, 0, 39, -6, -5, -7, -2, -9, -8, -3, -1, 4, -9, -4, -1, -5, 6, 3, 2, 7, -8, 3, 8, -2, 7, -4, -1, -6, -5, -9, 8, -3, -9, -4, -7, -2, 1, -6, -5, 4, 7, -5, 9, -1, -6, -8, -3, 2, -1, -2, -6, -8, -3, 5, -4, 9, -7, 2, 9, -3, -6, 8, 7, -5, 4, -1, -7, -6, -8, 1, 5, -4, -9, -2, 3, 5, -1, 4, -3, 2, 9, -7, -8, -6] ,\ [8, 3, 1, 4, 3, 0, 0, 0, 1, 0, 0, 39, -6, -4, 2, 3, 8, -1, -7, 5, -9, -1, 3, -7, -9, -6, 5, 2, -4, -8, -5, -8, -9, 2, -4, -7, -3, -1, 6, -3, -7, -6, -4, -9, 8, -5, 2, -1, 9, -5, -1, 7, -2, 3, -6, 8, -4, 8, -2, -4, 5, 1, -6, 9, 7, -3, -2, -1, -8, 6, -7, 9, 4, -3, -5, -4, -9, 5, -8, -3, -2, -1, 6, -7, 7, -6, -3, -1, -5, 4, 8, -9, -2] ,\ [15, 2, 0, 4, 2, 0, 0, 0, 1, 0, 0, 40, -8, 2, 3, -1, -9, 7, -6, -5, -4, -4, -5, 7, 6, -3, -8, -2, 1, -9, 1, -9, 6, -5, 4, 2, -3, -7, 8, -3, -4, -8, -9, 1, -6, -5, -2, -7, -6, -7, -2, -4, -8, -5, 9, 3, -1, -9, -1, -5, 2, -7, 3, 4, -8, 6, -2, -8, 9, -7, -5, -4, -1, 6, 3, -7, 6, 4, -3, 2, -1, -8, -9, 5, -5, 3, -1, 8, -6, -9, 7, -4, -2] ,\ [16, 2, 1, 4, 1, 0, 0, 0, 1, 0, 0, 41, 6, -4, -9, 5, -3, 7, 8, 1, -2, 2, 1, -7, 6, -4, -8, -5, 3, -9, -5, -3, 8, -2, 1, -9, 7, -4, -6, -4, -8, -6, -3, 7, 2, 9, 5, -1, 3, -7, -5, -9, -6, -1, -2, -8, -4, -9, -2, -1, -8, -5, 4, -3, -6, -7, 1, 6, -2, -7, 8, -5, -4, -9, 3, -7, -5, -3, 4, -9, -6, -1, 2, -8, -8, 9, -4, 1, 2, -3, -6, 7, -5] ,\ [22, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 42, -8, -2, -5, -4, -9, -3, -1, 6, -7, 3, -6, 1, -5, 7, -8, -2, -9, -4, 7, 4, -9, -2, -1, -6, 8, -5, -3, 2, 7, -4, -9, 6, -5, -3, -8, -1, -1, -3, -6, -7, -8, -2, 9, -4, -5, 5, -9, -8, -1, 3, 4, 7, 2, 6, -4, -5, -7, -3, -2, 9, -6, 1, -8, 6, -1, -2, -8, 5, 7, 4, 3, -9, -9, -8, 3, 6, 4, -1, -5, 7, -2] ,\ [16, 2, 0, 1, 1, 0, 0, 0, 2, 0, 0, 42, -1, -5, -9, -6, -3, -4, -8, -2, 7, -7, 6, -3, -8, -1, 2, 4, -9, -5, -4, 2, 8, -9, 5, -7, -1, 3, -6, 3, -1, -4, -7, 2, -8, -5, -6, 9, -6, 7, -5, -3, -9, 1, 2, -4, -8, -9, -8, 2, 5, -4, 6, -3, -7, -1, 8, 3, -6, -2, -7, 5, -9, -1, -4, 5, -9, -1, 4, -6, -3, 7, -8, -2, -2, 4, -7, -1, 8, 9, 6, -5, 3] ,\ [16, 1, 2, 2, 0, 0, 0, 1, 1, 0, 0, 42, -2, -4, 9, -1, 6, -8, -5, 7, -3, 8, -7, -5, -4, -2, 3, -1, -6, -9, -3, -6, -1, 5, 7, 9, 2, -8, -4, 4, 2, -8, -7, 5, 1, -9, -3, 6, -1, 9, -6, -8, -3, -4, -7, -2, -5, -7, -5, -3, 2, -9, 6, -8, -4, -1, -5, 3, -4, 9, -8, -7, 6, -1, -2, -9, 1, -7, -6, -4, -2, 3, 5, 8, -6, 8, 2, -3, -1, 5, -4, 9, -7] ,\ [7, 1, 2, 4, 1, 1, 0, 1, 1, 0, 0, 42, 4, -5, 7, -6, -8, 3, -2, -1, -9, -2, 8, 9, -7, 1, -5, -4, -6, -3, -1, -3, -6, -4, 9, -2, 5, -8, -7, 8, -7, 3, -5, -2, -9, 1, 4, -6, -9, -4, -1, -8, -3, -6, 7, -5, 2, -5, -6, 2, -1, -4, 7, -9, -3, -8, 6, -1, -8, 9, -7, -4, 3, 2, -5, 7, -2, 4, -3, -5, 8, 6, -9, 1, -3, -9, 5, 2, -6, 1, -8, -7, -4] ,\ [23, 2, 0, 1, 1, 0, 0, 0, 0, 0, 1, 51, 9, -7, 4, -6, -8, -5, -2, 3, -1, -1, -6, -8, 2, -3, 7, -9, 4, -5, -3, -2, -5, -1, -9, 4, 6, -7, 8, -6, -4, -2, 3, -7, -1, -8, 5, 9, -5, -1, 7, -9, -2, -8, 4, -6, -3, 8, 3, -9, -4, -5, 6, -7, -1, -2, 4, -8, 6, 5, -1, -2, -3, -9, -7, -7, 9, -1, 8, -4, 3, -5, -2, -6, -2, 5, -3, -7, -6, -9, 1, -8, 4] ,\ ] PUZZLES_16 = [[10,10,1,1,0,0,1,1,0,0,0,0, 1,-2,-13,7,11,-3,-4,15,-16,9,10,6,12,-14,-8,5,\ -8,15,-14,-5,-10,13,7,-9,2,1,12,-11,-16,-3,4,-6,\ -6,-12,3,-11,-8,1,14,-16,4,-7,-15,5,-2,9,-10,-13,\ 4,-16,-9,10,5,-12,-2,6,-8,3,13,-14,11,-15,-7,1,\ 10,-5,11,-13,-3,4,12,-14,-1,2,16,-15,-6,8,-9,7,\ -3,6,-12,8,15,-11,-9,1,10,-4,-5,7,13,-2,14,-16,\ -9,-4,1,16,7,-5,-13,2,6,-14,-8,12,10,11,-3,-15,\ 14,-7,15,-2,-16,10,6,-8,-11,13,3,-9,-5,12,-1,4,\ 16,-9,4,-3,-13,15,8,-12,-7,6,2,-1,-14,5,-11,10,\ -15,-10,2,6,1,-7,-11,5,13,-12,-14,8,9,4,-16,-3,\ -7,13,-5,12,9,-14,-10,3,15,-11,-4,16,1,-6,2,-8,\ 11,-14,8,-1,-2,6,16,-4,-3,5,9,-10,-7,13,-15,12,\ 13,-3,-10,14,-6,9,15,-7,5,-8,-1,2,4,-16,-12,11,\ -12,-11,6,-15,4,-2,-3,10,-9,16,7,-13,-8,1,-5,-14,\ -5,8,-7,-9,-14,16,1,11,-12,15,6,-4,-3,-10,13,-2,\ 2,-1,-16,4,12,8,5,-13,14,-10,-11,3,15,-7,-6,9]] PUZZLES_4 = [[10,10,1,1,0,0,1,1,0,0,0,0, -1,2,-3,-4,3,-4,-1,-2,-2,-1,4,-3,-4,3,-2,1]] def set_puzzle_set(): if SGG.SYMBOL_SET_SIZE == 4: SGP.PUZZLES = SGP.PUZZLES_4 if SGG.SYMBOL_SET_SIZE == 9: SGP.PUZZLES = SGP.PUZZLES_9 if SGG.SYMBOL_SET_SIZE == 16: SGP.PUZZLES = SGP.PUZZLES_16 def fetch_selected_puzzle(puzzle_index): """ load a built-in puzzle""" puzzle_solution = [0] * SGG.CELL_COUNT puzzle_data = [0] * (SGG.CELL_COUNT + 12) puzzle_data = SGP.PUZZLES[puzzle_index] for solution_index in range(SGG.CELL_COUNT): puzzle_solution[solution_index] = puzzle_data[solution_index \ + 12] return puzzle_solution #File_end sgp.py #File_start sgg.py class SGG: """ an SGG defines all the SG CONSTANTS and globals""" ROW = 1 COLUMN = 2 BOX = 3 SET = True UNSET = False SOLVED = 1025 UNSOLVED = 1026 INCONSISTENT = 1027 STALLED = 1028 SYMBOL_SET_SIZE = 9 SYMBOL_SET_SIZE_SQRT = int(sqrt(SYMBOL_SET_SIZE)) CELL_COUNT = SYMBOL_SET_SIZE * SYMBOL_SET_SIZE R_SYMBOL_SET_SIZE = range(SYMBOL_SET_SIZE) R_CELL_COUNT = range(CELL_COUNT) I_SET_GUESS = 2 I_DIDNT_SET_GUESS = 1 I_SET_CANDIDATE = 2 I_DIDNT_SET_CANDIDATE = 1 NORMAL = 1 I_AM_CAUSE = 2 I_AM_EFFECT = 3 REDRAW_ME = 5 BUTTON_PRESS = 7 HINT_CELLS = 11 HINT_CAUSES = 13 HINT_EFFECTS = 17 HINT_CANDIDATES = HINT_CAUSES * HINT_EFFECTS I_AM_WRONG = 19 I_AM_COLOURED = 23 HINT_NOTHING = 29 HINT_GROUPS = 31 HINT_ABSOLUTELY_NOTHING = 37 MODE_PRIMES = [NORMAL,\ I_AM_CAUSE,\ I_AM_EFFECT,\ REDRAW_ME,\ BUTTON_PRESS,\ HINT_CELLS,\ HINT_CAUSES,\ HINT_EFFECTS,\ I_AM_WRONG,\ I_AM_COLOURED,\ HINT_NOTHING,\ HINT_GROUPS,\ HINT_ABSOLUTELY_NOTHING] MAX_MODES = len(MODE_PRIMES) HELP_INCONSISTENCIES = 1 HELP_WRONG_ANSWERS = 2 HELP_NONE = 3 #algorithms etc MOST_EFFECTIVE_HINT = 0 SIMPLEST_HINT = 1 CURRENT_ALGORITHM = SIMPLEST_HINT UNDO = 0 UNDO_TO_CONSISTENCY = 1 GIVE_HINT = 2 SIMPLE_FILTER_EXHAUSTIVELY = 3 SIMPLE_FILTER = 4 HIDDEN_SINGLE = 5 HIDDEN_PAIRS = 6 HIDDEN_TRIPLES = 7 LOCKED_CANDIDATE_1 = 8 LOCKED_CANDIDATE_2 = 9 NAKED_PAIRS = 10 NAKED_TRIPLES = 11 NAKED_QUADS = 12 X_WING = 13 SWORDFISH = 14 JELLYFISH = 15 ALGORITHM_GROUP = [[-1],[-1],[-1],[-1],[-1],\ [HIDDEN_SINGLE, HIDDEN_PAIRS, HIDDEN_TRIPLES], [HIDDEN_SINGLE, HIDDEN_PAIRS, HIDDEN_TRIPLES], [HIDDEN_SINGLE, HIDDEN_PAIRS, HIDDEN_TRIPLES], [LOCKED_CANDIDATE_1, LOCKED_CANDIDATE_2], [LOCKED_CANDIDATE_1, LOCKED_CANDIDATE_2], [NAKED_PAIRS, NAKED_TRIPLES, NAKED_QUADS], [NAKED_PAIRS, NAKED_TRIPLES, NAKED_QUADS], [NAKED_PAIRS, NAKED_TRIPLES, NAKED_QUADS], [X_WING, SWORDFISH, JELLYFISH], [X_WING, SWORDFISH, JELLYFISH], [X_WING, SWORDFISH, JELLYFISH]] ALGORITHM_SCORES = [0,0,0,0,0,1,2,2,2,2,3,4,7,9,12,20] ALGORITHM_USAGE = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ALGORITHM_ORDER = [0,0,0,0,0, HIDDEN_SINGLE,\ HIDDEN_PAIRS,\ HIDDEN_TRIPLES,\ LOCKED_CANDIDATE_1,\ LOCKED_CANDIDATE_2,\ NAKED_PAIRS,\ NAKED_TRIPLES,\ NAKED_QUADS,\ X_WING,\ SWORDFISH,\ JELLYFISH] ROWS_WITH_CANDIDATE = [] #the row numbers of columns with candidates COLUMNS_WITH_CANDIDATE = [] #the column numbers of rows with candidates READY_TO_GO_FISHING = False CANDIDATES_IN_ROWS = [] CANDIDATES_IN_COLUMNS = [] CANDIDATES_IN_BOXES = [] CANDIDATES_IN_ROWS = [] READY_TO_GET_NAKED = False ROW_CELLS_WITH_CANDIDATE = [] ROW_CELL_CANDIDATE_COUNTS = [] COLUMN_CELLS_WITH_CANDIDATE = [] COLUMN_CELL_CANDIDATE_COUNTS = [] BOX_CELLS_WITH_CANDIDATE = [] BOX_CELL_CANDIDATE_COUNTS = [] READY_TO_GET_HIDDEN = False help = HELP_NONE history = [] hint = [] button_status = [] ROW_INDEX = [] COLUMN_INDEX = [] BOX_INDEX = [] ROW_CELLS = [] COLUMN_CELLS = [] BOX_CELLS = [] SET_CANDIDATES = [] UNSET_CANDIDATES = [] LC_BOX_INDEXES = [] LC_COLUMN_INDEXES = [] LC_ROW_INDEXES = [] def make_indexes(): #box_indexes_1 = [0,0,0,1,1,1,2,2,2] #column_indexes = [0,3,6,0,3,6,0,3,6,1,4,7,1,4,7,1,4,7,2,5,8,2,5,8,2,5,8] SQRT = SGG.SYMBOL_SET_SIZE_SQRT for i in range(SQRT): for j in range(SQRT): SGG.LC_BOX_INDEXES.append(i) for i in range(SQRT): for j in range(SQRT): for k in range(SQRT): SGG.LC_COLUMN_INDEXES.append(i+k*SQRT) #row_indexes = [0,1,2,0,1,2,0,1,2,3,4,5,3,4,5,3,4,5,6,7,8,6,7,8,6,7,8] for i in range(SQRT): for j in range(SQRT): for k in range(SQRT): SGG.LC_ROW_INDEXES.append(i*SQRT+k) for i in range(SGG.SYMBOL_SET_SIZE): for j in range(SGG.SYMBOL_SET_SIZE): SGG.ROW_INDEX.append(i) for i in range(SGG.SYMBOL_SET_SIZE): for j in range(SGG.SYMBOL_SET_SIZE): SGG.COLUMN_INDEX.append(j) for i in range(SGG.SYMBOL_SET_SIZE): for j in range(SGG.SYMBOL_SET_SIZE): SGG.BOX_INDEX.append(SQRT*(i/SQRT) + j/SQRT) k = 0 for i in range(SGG.SYMBOL_SET_SIZE): t = [] for j in range(SGG.SYMBOL_SET_SIZE): t.append(k) k += 1 SGG.ROW_CELLS.append(t) k = 0 for i in range(SGG.SYMBOL_SET_SIZE): t = [] for j in range(SGG.SYMBOL_SET_SIZE): t.append(j*SGG.SYMBOL_SET_SIZE + i) k += 1 SGG.COLUMN_CELLS.append(t) tr = 0 td = 0 r0 = 0 for i in range(SGG.SYMBOL_SET_SIZE): r = r0 + SQRT * i if td == SQRT: r = i* SGG.SYMBOL_SET_SIZE td = 0 tr = 0 r0 += (SQRT-1) * SGG.SYMBOL_SET_SIZE #print 'td r',r t = [] k = 0 for j in range(SGG.SYMBOL_SET_SIZE): t.append(r + k) m = r + k k += 1 tr += 1 if tr == SQRT: r += SGG.SYMBOL_SET_SIZE tr = 0 k = 0 #print 'tr r',r,m #print t SGG.BOX_CELLS.append(t) td += 1 for j in range(SGG.SYMBOL_SET_SIZE): SGG.SET_CANDIDATES.append(SGG.SET) SGG.UNSET_CANDIDATES.append(SGG.UNSET) #File_end sgg.py #File_start sg.py class SGHint: """ Maintains and provides hints for SGSudoku algorithms and SGWidget""" instance = None def __init__(self): assert SGHint.instance is None, 'Trying to create a second Hint' self.score = 0 self.effects = [] self.causes = [] self.algorithm = 0 self.active = False self.mode = SGG.HINT_EFFECTS self.saved_mode = self.mode self.saved = False SGHint.instance = self def add(self,score, effects, causes, algorithm): if score > self.score: self.causes = causes self.effects = effects self.score = score self.algorithm = algorithm def list(self): print 'list hint',self.score,self.algorithm,\ self.causes,self.effects def delete(self): self.score = 0 self.effects = [] self.causes = [] def hint_on(self): self.score = 0 self.algorithm = 0 self.effects = [] self.causes = [] self.mode = SGG.HINT_CANDIDATES self.active = True def hint_off(self): self.score = 0 self.effects = [] self.causes = [] self.active = False self.mode = SGG.NORMAL def hint_is_on(self): return self.active def restore_hint_mode(self): if self.saved: self.mode = self.saved_mode self.saved = False def save_hint_mode(self): if not self.saved: self.saved_mode = self.mode self.saved = True def len_hint_effects(self): return len(self.effects) def len_hint_causes(self): return len(self.causes) def hint_effects(self): return self.effects def hint_causes(self): return self.causes def mode_ok(self, mode_in): assert (type(mode_in) is int), \ 'mode_in is out of range' for mode_index in range(SGG.MAX_MODES): if SGG.MODE_PRIMES[mode_index] == mode_in: return True print 'Scream mode' return False def mode_is_on(self, mode_in, query_mode): """ return True if mode is on """ if self.mode_ok(query_mode): if mode_in%query_mode == 0: return True else: return False print ' scream in mode_is_on' class SGHistory: """ Maintains and provides copies of SGSudokus """ def __init__(self,sg): self.history = [] self.items = 0 cp = copy.deepcopy(sg) self.history.append(cp) self.items += 1 def empty(self): self.history = [] self.items = 0 def add(self,sg): cp = copy.deepcopy(sg) self.history.append(cp) self.items += 1 def delete(self): if self.items > 0: self.history.pop() self.items -= 1 else: self = [] def get_current(self): cp = [] if self.items > 0: cp = copy.deepcopy(self.history[self.items-1]) return cp def get_previous(self): cp = [] if self.items > 1: cp = copy.deepcopy(self.history[self.items-2]) return cp def replace(self,sg): if self.items > 0: self.delete() self.add(sg) class SGSCell: """ a cell_index, candidates to try, and their count""" def __init__(self, sg, cell_index_in): self.cell_index = cell_index_in # delete deleted candidates for this cell_index self.candidates = copy.deepcopy(sg.sg_sudoku[cell_index_in].candidates) self.guess = 99 self.info = 0 for candidate in range(SGG.SYMBOL_SET_SIZE): if self.candidates[candidate] == SGG.SET: self.info += 1 self.get_next_candidate() def get_next_candidate(self): for candidate in range(SGG.SYMBOL_SET_SIZE): if self.candidates[candidate] == SGG.SET: self.candidates[candidate] = SGG.UNSET self.guess = candidate self.info -= 1 return class SGCell: """an SGCell maintains and provides data on a single sudoku cell solution is the true solution guess is the current guess candidates are the current remaining symbols """ def __init__(self, cell_index): self.solution = SGG.UNSET self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) self.cell_index = cell_index self.row = SGG.ROW_INDEX[cell_index] self.column = SGG.COLUMN_INDEX[cell_index] self.box = SGG.BOX_INDEX[cell_index] def get_solution(self): return self.solution def get_guess(self): return self.guess def get_candidates(self): return self.candidates def candidate_is_set(self,candidate): SET = SGG.SET if self.candidates[candidate] == SET: return True else: return False def guess_is_set(self): if self.status == SGG.SOLVED: return True else: return False def guess_is_a_given(self): return self.given def guess_correct(self): status = True if self.guess_is_set(): if self.guess != self.solution: status = False return status def candidates_consistent(self): status = True if not self.guess_is_set(): solution_index = self.solution - 1 if self.candidates[solution_index] != SGG.SET: status = False return status # solution values are 0-9 # candidate indexes are 0-8 # requests to delete or add a candidate must be 1-9 # requests to set a guess must be 0-8 def check_range_0_8(self,value): assert (type(value) is int) and (value >= 0) and (value < SGG.SYMBOL_SET_SIZE), \ 'index is out of range' def check_range_0_9(self,value): assert (type(value) is int) and (value >= 0) and (value <= SGG.SYMBOL_SET_SIZE), \ 'guess is out of range' def check_range_1_9(self,value): assert (type(value) is int) and (value >= 1) and (value <= SGG.SYMBOL_SET_SIZE), \ 'guess is out of range' def check_range_cell_index(self,value): assert (type(value) is int) and (value >= 0) \ and (value < SGG.CELL_COUNT), 'index is out of range' def set_candidates(self, candidates): len_candidates = len(candidates) if len_candidates == 1: # only 1 candidate hence: the solution, unknown or hidden clue solution = candidates[0] if solution > 0: self.solution = solution self.given = True self.status = SGG.SOLVED self.guess = solution self.candidates = copy.deepcopy(SGG.UNSET_CANDIDATES) elif solution == 0: # an unknown self.solution = SGG.UNSET self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) else: # a hidden clue solution = -1 * solution self.solution = solution self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) elif len_candidates > 1: # these are the remaing candidates self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.UNSET_CANDIDATES) for i in range(len_candidates): candidate = candidates[i] self.add_candidate(candidate) else: print 'SCREAM: set_candidates' def set_solution(self,solution): SHOW_SOLUTION = 999 if solution == SHOW_SOLUTION: self.status = SGG.SOLVED self.guess = self.solution self.candidates = copy.deepcopy(SGG.UNSET_CANDIDATES) elif solution > 0: # a given self.solution = solution self.given = True self.status = SGG.SOLVED self.guess = solution self.candidates = copy.deepcopy(SGG.UNSET_CANDIDATES) elif solution == 0: # an unknown self.solution = SGG.UNSET self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) else: solution = -1 * solution self.solution = solution self.given = False self.status = SGG.UNSOLVED self.guess = SGG.UNSET self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) def set_guess(self,guess): self.guess = guess + 1 # note well!!! self.status = SGG.SOLVED self.candidates = copy.deepcopy(SGG.UNSET_CANDIDATES) def unset_guess(self): self.guess = SGG.UNSET self.status = SGG.UNSOLVED self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) # solution values are 0-9 # candidate indexes are 0-8 # requests to delete or add a candidate must be 1-9 # requests to set a guess must be 0-8 def del_candidate(self,candidate_in): result_1 = SGG.I_DIDNT_SET_CANDIDATE result_2 = SGG.I_DIDNT_SET_GUESS self.check_range_1_9(candidate_in) # proceed only if cell unsolved or candidate set if self.status == SGG.UNSOLVED and \ self.candidates[candidate_in-1] == SGG.SET: self.candidates[candidate_in-1] = SGG.UNSET result_1 = SGG.I_SET_CANDIDATE #need to check if last one info = 0 for candidate in SGG.R_SYMBOL_SET_SIZE: if self.candidates[candidate] == SGG.SET: info += 1 cand = candidate assert (info >0), 'info 0' if info == 1: # got a single candidate so set guess self.set_guess(cand) result_2 = SGG.I_SET_GUESS return result_1, result_2 def add_candidate(self,candidate): self.candidates[candidate-1] = SGG.SET self.status = SGG.UNSOLVED #print 'add_candidate',candidate,self.candidates def reset_all_candidates(self): self.candidates = copy.deepcopy(SGG.SET_CANDIDATES) self.status = SGG.UNSOLVED self.guess = SGG.UNSET def get_cell_info(self): info = 0 for candidate in SGG.R_SYMBOL_SET_SIZE: if self.candidates[candidate] == SGG.SET: info += 1 return info def compare_candidates(self,other): """ compare the candidate status for a pair of cells """ result_2 = copy.deepcopy(SGG.UNSET_CANDIDATES) result_1 = False for candidate in SGG.R_SYMBOL_SET_SIZE: if self.candidates[candidate] != other.candidates[candidate]: result_2[candidate] = SGG.SET result_1 = True return result_1, result_2 def available_candidates(self): result = [] my_range = SGG.R_SYMBOL_SET_SIZE [result.append(candidate) for candidate in my_range\ if self.candidate_is_set(candidate)] return result class SGSudoku: """ an SGSudoku maintains and provides data on a set of 81 Sudoku \ cells""" ROW_INDEX = 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,\ 3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,6,6,6,6,6,\ 6,6,6,6,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8 COLUMN_INDEX = 0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,\ 2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,\ 4,5,6,7,8,0,1,2,3,4,5,6,7,8,0,1,2,3,4,5,6,7,8 BOX_INDEX = 0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2,0,0,0,1,1,1,2,2,2,3,3,3,\ 4,4,4,5,5,5,3,3,3,4,4,4,5,5,5,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,\ 8,8,8,6,6,6,7,7,7,8,8,8,6,6,6,7,7,7,8,8,8 ROW_CELLS = [[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ],\ [ 9, 10, 11, 12, 13, 14, 15, 16, 17 ],\ [ 18, 19, 20, 21, 22, 23, 24, 25, 26 ],\ [ 27, 28, 29, 30, 31, 32, 33, 34, 35 ],\ [ 36, 37, 38, 39, 40, 41, 42, 43, 44 ],\ [ 45, 46, 47, 48, 49, 50, 51, 52, 53 ],\ [ 54, 55, 56, 57, 58, 59, 60, 61, 62 ],\ [ 63, 64, 65, 66, 67, 68, 69, 70, 71 ],\ [ 72, 73, 74, 75, 76, 77, 78, 79, 80 ]] COLUMN_CELLS = [[ 0, 9, 18, 27, 36, 45, 54, 63, 72 ],\ [ 1, 10, 19, 28, 37, 46, 55, 64, 73 ],\ [ 2, 11, 20, 29, 38, 47, 56, 65, 74 ],\ [ 3, 12, 21, 30, 39, 48, 57, 66, 75 ],\ [ 4, 13, 22, 31, 40, 49, 58, 67, 76 ],\ [ 5, 14, 23, 32, 41, 50, 59, 68, 77 ],\ [ 6, 15, 24, 33, 42, 51, 60, 69, 78 ],\ [ 7, 16, 25, 34, 43, 52, 61, 70, 79 ],\ [ 8, 17, 26, 35, 44, 53, 62, 71, 80 ]] BOX_CELLS = [[ 0, 1, 2, 9, 10, 11, 18, 19, 20 ],\ [ 3, 4, 5, 12, 13, 14, 21, 22, 23 ],\ [ 6, 7, 8, 15, 16, 17, 24, 25, 26 ],\ [ 27, 28, 29, 36, 37, 38, 45, 46, 47 ],\ [ 30, 31, 32, 39, 40, 41, 48, 49, 50 ],\ [ 33, 34, 35, 42, 43, 44, 51, 52, 53 ],\ [ 54, 55, 56, 63, 64, 65, 72, 73, 74 ],\ [ 57, 58, 59, 66, 67, 68, 75, 76, 77 ],\ [ 60, 61, 62, 69, 70, 71, 78, 79, 80 ]] def __init__(self): self.sg_sudoku = [] new = [] for cell_index in SGG.R_CELL_COUNT: new.append(SGCell(cell_index)) self.sg_sudoku = new self.algorithms_not_ready() def make_indexeso(self): for i in range(SGG.SYMBOL_SET_SIZE): for j in range(SGG.SYMBOL_SET_SIZE): print i for i in range(SGG.SYMBOL_SET_SIZE): for j in range(SGG.SYMBOL_SET_SIZE): print j tt = [] k = 0 for i in range(SGG.SYMBOL_SET_SIZE): t = [] for j in range(SGG.SYMBOL_SET_SIZE): t.append(k) k += 1 tt.append(t) print tt print ' ' tt = [] SQRT = int(sqrt(SGG.SYMBOL_SET_SIZE)) tr = 0 td = 0 r0 = 0 for i in range(SGG.SYMBOL_SET_SIZE): r = r0 + SQRT * i if td == SQRT: r = i* SGG.SYMBOL_SET_SIZE td = 0 tr = 0 r0 += (SQRT-1) * SGG.SYMBOL_SET_SIZE #print 'td r',r t = [] k = 0 for j in range(SGG.SYMBOL_SET_SIZE): t.append(r + k) m = r + k k += 1 tr += 1 if tr == SQRT: r += SGG.SYMBOL_SET_SIZE tr = 0 k = 0 #print 'tr r',r,m #print t tt.append(t) td += 1 print tt def __len__(self): return len(self.sg_sudoku) def check_range(self,value): assert (type(value) is int) and (value >= 0) \ and (value <= SGG.CELL_COUNT), 'index is out of range' def print_sg_sudoku(self): for cell_index in SGG.R_CELL_COUNT: if cell_index%9 == 0: print ' ' print self.sg_sudoku[cell_index].guess, print ' ' #for cell_index in SGG.R_CELL_COUNT: # if not SGCell.guess_is_set(self.sg_sudoku[cell_index]): # print cell_index, # for candidate in range(9): # if self.sg_sudoku[cell_index].candidates[candidate] == SGG.SET: print candidate, # print ' ' def print_sg_sudoku_2(self): for cell_index in SGG.R_CELL_COUNT: if cell_index%9 == 0: print ' ' if SGCell.guess_is_set(self.sg_sudoku[cell_index]): print self.sg_sudoku[cell_index].guess, else: t = '' for candidate in range(9): if self.sg_sudoku[cell_index].candidates[candidate] == SGG.SET: t += str(candidate+1) print t, print ' ' def print_sg_sudoku_1(self): for cell_index in SGG.R_CELL_COUNT: if cell_index%9 == 0: print ' ' print self.sg_sudoku[cell_index].solution, print ' ' def get_info(self): get_cell_info = SGCell.get_cell_info info = 0 for cell_index in SGG.R_CELL_COUNT: info += get_cell_info(self.sg_sudoku[cell_index]) return info def transfer_solutions(self, sg_solved): get_guess = SGCell.get_guess guess_is_a_given = SGCell.guess_is_a_given set_solution = SGCell.set_solution unset_guess = SGCell.unset_guess for cell_index in SGG.R_CELL_COUNT: if not guess_is_a_given(self.sg_sudoku[cell_index]): guess = get_guess(sg_solved.sg_sudoku[cell_index]) self.sg_sudoku[cell_index].solution = guess self.sg_sudoku[cell_index].guess = SGG.UNSET self.sg_sudoku[cell_index].status = SGG.UNSOLVED def set_solutions(self,job): """ after solving a grid in .guesses set up solutions""" guess_is_a_given = SGCell.guess_is_a_given get_guess = SGCell.get_guess set_solution = SGCell.set_solution unset_guess = SGCell.unset_guess if job == 1: for cell_index in SGG.R_CELL_COUNT: if not guess_is_a_given(self.sg_sudoku[cell_index]): guess = get_guess(self.sg_sudoku[cell_index]) set_solution(self.sg_sudoku[cell_index],guess) # self.solution = guess unset_guess(self.sg_sudoku[cell_index]) elif job == 2: guess = 999 for cell_index in SGG.R_CELL_COUNT: set_solution(self.sg_sudoku[cell_index],guess) def check_guesses(self): result = [] for cell_index in SGG.R_CELL_COUNT: if not SGCell.guess_correct(self.sg_sudoku[cell_index]): result.append(cell_index) if not SGCell.candidates_consistent(self.sg_sudoku[cell_index]): result.append(cell_index) status = True if len(result) > 0: status = False return status, result def is_ninemer_consistent(self, shape): guess_is_set = SGCell.guess_is_set result = [] status = True # do each shape index for shape_index in SGG.R_SYMBOL_SET_SIZE: this_list = self.get_cell_list(shape_index, shape) for ninemer in range(SGG.SYMBOL_SET_SIZE-1): cell_index = this_list[ninemer] if guess_is_set(self.sg_sudoku[cell_index]): guess = self.sg_sudoku[cell_index].guess for ninemer_1 in range(ninemer+1,SGG.SYMBOL_SET_SIZE): cell_index_1 = this_list[ninemer_1] if guess_is_set(self.sg_sudoku[cell_index_1]): guess_1 = self.sg_sudoku[cell_index_1].guess if guess == guess_1: result.append(cell_index) result.append(cell_index_1) status = False return status, result def is_consistent(self): guess_is_set = SGCell.guess_is_set get_cell_info = SGCell.get_cell_info result = [] status = True s, r = self.is_ninemer_consistent(SGG.ROW) if not s: status = False result += r s, r = self.is_ninemer_consistent(SGG.COLUMN) if not s: status = False result += r s, r = self.is_ninemer_consistent(SGG.BOX) if not s: status = False result += r # unset guess and zero info? for cell_index in SGG.R_CELL_COUNT: if not guess_is_set(self.sg_sudoku[cell_index]): info = get_cell_info(self.sg_sudoku[cell_index]) if info == 0: status = False result.append(cell_index) return status, result def load_sg_sudoku(self,solutions): set_solution = SGCell.set_solution for cell_index in SGG.R_CELL_COUNT: set_solution(self.sg_sudoku[cell_index],solutions[cell_index]) def load_sg_sudoku_f(self,solutions): set_candidates = SGCell.set_candidates for cell_index in SGG.R_CELL_COUNT: set_candidates(self.sg_sudoku[cell_index],solutions[cell_index]) def zero_algorithm_usage(self): length = len(SGG.ALGORITHM_USAGE) for algorithm in range(length): SGG.ALGORITHM_USAGE[algorithm] = 0 def get_cell_list(self,my_shape_index,shape): result = [] if shape == SGG.ROW: result = SGG.ROW_CELLS[my_shape_index] elif shape == SGG.COLUMN: result = SGG.COLUMN_CELLS[my_shape_index] elif shape == SGG.BOX: result = SGG.BOX_CELLS[my_shape_index] else: assert (shape == SGG.ROW), 'shape not recognised' return result def get_set_cell_list(self): my_list = [] for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].status == SGG.SOLVED: my_list.append(cell_index) return my_list def prepare_to_go_fishing(self): # get the row numbers of columns with candidates # get the column numbers of rows with candidates if SGG.READY_TO_GO_FISHING: return candidate_is_set = SGCell.candidate_is_set shape = SGG.COLUMN local = [] for candidate in SGG.R_SYMBOL_SET_SIZE: t = [] for ninemer in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(ninemer, shape) result = [self.sg_sudoku[x].row for x in cell_list if \ candidate_is_set(self.sg_sudoku[x],candidate)] t.append(result) local.append(t) SGG.ROWS_WITH_CANDIDATE = local shape = SGG.ROW local = [] for candidate in SGG.R_SYMBOL_SET_SIZE: t = [] for ninemer in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(ninemer, shape) result = [self.sg_sudoku[x].column for x in cell_list if \ candidate_is_set(self.sg_sudoku[x],candidate)] t.append(result) local.append(t) SGG.COLUMNS_WITH_CANDIDATE = local SGG.READY_TO_GO_FISHING = True def prepare_tables(self): self.prepare_to_go_fishing() self.prepare_to_get_naked() self.prepare_to_get_hidden() def algorithms_not_ready(self): SGG.READY_TO_GO_FISHING = False SGG.READY_TO_GET_NAKED = False SGG.READY_TO_GET_HIDDEN = False def prepare_to_get_naked_1(self, shape): candidate_is_set = SGCell.candidate_is_set local = [] # do a ninemer for ninemer in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(ninemer, shape) # do cells in ninemer good_stuff = [] for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] candidate_list = [] [candidate_list.append(candidate) for candidate \ in SGG.R_SYMBOL_SET_SIZE\ if self.sg_sudoku[cell_index].candidate_is_set(candidate)] if len(candidate_list) > 0: t = cell_index, set(candidate_list) good_stuff.append(t) local.append(good_stuff) if shape == SGG.ROW: SGG.CANDIDATES_IN_ROWS = local elif shape == SGG.COLUMN: SGG.CANDIDATES_IN_COLUMNS = local elif shape == SGG.BOX: SGG.CANDIDATES_IN_BOXES = local def prepare_to_get_naked(self): if SGG.READY_TO_GET_NAKED: return self.prepare_to_get_naked_1(SGG.ROW) self.prepare_to_get_naked_1(SGG.COLUMN) self.prepare_to_get_naked_1(SGG.BOX) SGG.READY_TO_GET_NAKED = True def prepare_to_get_hidden_1(self, shape): candidate_is_set = SGCell.candidate_is_set local = [] for ninemer in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(ninemer, shape) t = [] for candidate in SGG.R_SYMBOL_SET_SIZE: result = [x for x in cell_list if \ candidate_is_set(self.sg_sudoku[x],candidate)] t.append(result) local.append(t) p_c = local local = [] for ninemer in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(ninemer, shape) counts = [0] * SGG.SYMBOL_SET_SIZE for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] for candidate in SGG.R_SYMBOL_SET_SIZE: if candidate_is_set(self.sg_sudoku[cell_index],candidate): counts[candidate] += 1 local.append(counts) p_counts = local if shape == SGG.ROW: SGG.ROW_CELL_CANDIDATE_COUNTS = p_counts SGG.ROW_CELLS_WITH_CANDIDATE = p_c elif shape == SGG.COLUMN: SGG.COLUMN_CELL_CANDIDATE_COUNTS = p_counts SGG.COLUMN_CELLS_WITH_CANDIDATE = p_c elif shape == SGG.BOX: SGG.BOX_CELL_CANDIDATE_COUNTS = p_counts SGG.BOX_CELLS_WITH_CANDIDATE = p_c def prepare_to_get_hidden(self): if SGG.READY_TO_GET_HIDDEN: return self.prepare_to_get_hidden_1(SGG.ROW) self.prepare_to_get_hidden_1(SGG.COLUMN) self.prepare_to_get_hidden_1(SGG.BOX) SGG.READY_TO_GET_HIDDEN = True def lc1_cause(self, box, index_t, candidate, shape): cause = [] candidate_is_set = SGCell.candidate_is_set if shape == SGG.ROW: for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].box == box: if self.sg_sudoku[cell_index].row == index_t: if candidate_is_set(self.sg_sudoku[cell_index],\ candidate): cause.append(cell_index) cause.append(candidate) else: for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].box == box: if self.sg_sudoku[cell_index].column == index_t: if candidate_is_set(self.sg_sudoku[cell_index],\ candidate): cause.append(cell_index) cause.append(candidate) return cause def locked_candidate_12(self, box, shape, hints): result = 0 counts = [0] * SGG.SYMBOL_SET_SIZE * SGG.SYMBOL_SET_SIZE_SQRT sum_counts = [0] * SGG.SYMBOL_SET_SIZE candidate_is_set = SGCell.candidate_is_set guess_is_set = SGCell.guess_is_set cell_list = self.get_cell_list(box, SGG.BOX) cell_index = cell_list[0] if shape == SGG.ROW: index_0 = self.sg_sudoku[cell_index].row else: index_0 = self.sg_sudoku[cell_index].column for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] if not guess_is_set(self.sg_sudoku[cell_index]): if shape == SGG.ROW: t = self.sg_sudoku[cell_index].row else: t = self.sg_sudoku[cell_index].column index_1 = SGG.SYMBOL_SET_SIZE * (t - index_0) for candidate in SGG.R_SYMBOL_SET_SIZE: if candidate_is_set(\ self.sg_sudoku[cell_index],candidate): counts[index_1 + candidate] = 1 for i in SGG.R_SYMBOL_SET_SIZE: for j in range(SGG.SYMBOL_SET_SIZE_SQRT): sum_counts[i] += counts[i+j*SGG.SYMBOL_SET_SIZE] for candidate in SGG.R_SYMBOL_SET_SIZE: if sum_counts[candidate] == 1: # candidate only occurs in 1 row/column # which of the 3 rows/columns this box? effect = [] cause = [] for row_col in range(SGG.SYMBOL_SET_SIZE_SQRT): if counts[candidate + SGG.SYMBOL_SET_SIZE*row_col] == 1: # only once in row_col # find its cell_index for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].box != box: # not causing box good = 0 index_t = index_0 + row_col if shape == SGG.ROW: if self.sg_sudoku[cell_index].row\ == index_t: good = 1 else: if self.sg_sudoku[cell_index].column\ == index_t: good = 1 if good: if candidate_is_set(\ self.sg_sudoku[cell_index],candidate): effect.append(cell_index) effect.append(candidate) cause += self.lc1_cause(box, index_t, \ candidate, shape) score = len(effect) / 2 if score: hints.add(score, effect, cause,\ SGG.LOCKED_CANDIDATE_1) result += score return result def locked_candidate_1(self, hints): result = 0 for box in SGG.R_SYMBOL_SET_SIZE: result += self.locked_candidate_12(box, SGG.ROW, hints) result += self.locked_candidate_12(box, SGG.COLUMN, hints) return result def lc2_cause(self, row_col_in, box, candidate, shape): cause = [] candidate_is_set = SGCell.candidate_is_set if shape == SGG.ROW: for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].box == box: if self.sg_sudoku[cell_index].row == row_col_in: if candidate_is_set(self.sg_sudoku[cell_index],\ candidate): cause.append(cell_index) cause.append(candidate) else: for cell_index in SGG.R_CELL_COUNT: if self.sg_sudoku[cell_index].box == box: if self.sg_sudoku[cell_index].column == row_col_in: if candidate_is_set(self.sg_sudoku[cell_index],\ candidate): cause.append(cell_index) cause.append(candidate) return cause def locked_candidate_22(self, row_col_in, shape, hints): result = 0 counts = [0] * SGG.SYMBOL_SET_SIZE * SGG.SYMBOL_SET_SIZE_SQRT sum_counts = [0] * SGG.SYMBOL_SET_SIZE candidate_is_set = SGCell.candidate_is_set guess_is_set = SGCell.guess_is_set if shape == SGG.ROW: box_indexes = SGG.LC_ROW_INDEXES else: box_indexes = SGG.LC_COLUMN_INDEXES cell_list = self.get_cell_list(row_col_in, shape) for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] if not guess_is_set(self.sg_sudoku[cell_index]): box_index = SGG.SYMBOL_SET_SIZE * SGG.LC_BOX_INDEXES[list_index] for candidate in SGG.R_SYMBOL_SET_SIZE: if candidate_is_set(\ self.sg_sudoku[cell_index],candidate): counts[box_index + candidate] = 1 for i in SGG.R_SYMBOL_SET_SIZE: for j in range(SGG.SYMBOL_SET_SIZE_SQRT): sum_counts[i] += counts[i+j*SGG.SYMBOL_SET_SIZE] for candidate in SGG.R_SYMBOL_SET_SIZE: if sum_counts[candidate] == 1: # candidate only occurs in 1 box # which of the 3 rows/columns this box? effect = [] cause = [] for row_col in range(SGG.SYMBOL_SET_SIZE_SQRT): if counts[candidate + SGG.SYMBOL_SET_SIZE*row_col] == 1: # only once in row_col # find its cell_index box = box_indexes[row_col_in * SGG.SYMBOL_SET_SIZE_SQRT + row_col] for cell_index in SGG.R_CELL_COUNT: good = 0 if shape == SGG.ROW: if self.sg_sudoku[cell_index].row\ != row_col_in: good = 1 else: if self.sg_sudoku[cell_index].column\ != row_col_in: good = 1 if good: if self.sg_sudoku[cell_index].box == box: if candidate_is_set(\ self.sg_sudoku[cell_index],candidate): effect.append(cell_index) effect.append(candidate) cause += self.lc2_cause(row_col_in, box, \ candidate, shape) score = len(effect) / 2 if score: hints.add(score, effect, cause,\ SGG.LOCKED_CANDIDATE_2) result += score return result def locked_candidate_2(self, hints): result = 0 for row_col in SGG.R_SYMBOL_SET_SIZE: result += self.locked_candidate_22(row_col, SGG.ROW, hints) result += self.locked_candidate_22(row_col, SGG.COLUMN, hints) return result def hs3(self,cell_index, result): candidate_is_set = SGCell.candidate_is_set guess_is_set = SGCell.guess_is_set if not guess_is_set(self.sg_sudoku[cell_index]): for candidate in SGG.R_SYMBOL_SET_SIZE: if candidate_is_set(self.sg_sudoku[cell_index],candidate): result[candidate] += 1 def hs4(self, cell_list, candidate, hints): """ candidate occurs once in the list of cells \ find which one and get its other candidates (which could be deleted)""" candidate_is_set = SGCell.candidate_is_set score = 0 for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] if candidate_is_set(self.sg_sudoku[cell_index], candidate): # this is the cell we want cause = [] effect = [] cause.append(cell_index) cause.append(candidate) for candidate_index in SGG.R_SYMBOL_SET_SIZE: if candidate_index != candidate and \ candidate_is_set(self.sg_sudoku[cell_index], \ candidate_index): score += 1 effect.append(cell_index) effect.append(candidate_index) if score: hints.add(score, effect, cause, \ SGG.HIDDEN_SINGLE) return score return score def hs2(self, shape, hints): score = 0 good = 0 if shape == SGG.ROW: p_counts = SGG.ROW_CELL_CANDIDATE_COUNTS elif shape == SGG.COLUMN: p_counts = SGG.COLUMN_CELL_CANDIDATE_COUNTS elif shape == SGG.BOX: p_counts = SGG.BOX_CELL_CANDIDATE_COUNTS for shape_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(shape_index, shape) counts = p_counts[shape_index] # any unique candidates? for candidate in SGG.R_SYMBOL_SET_SIZE: if counts[candidate] == 1: score = self.hs4(cell_list, candidate, hints) good = 1 return good def hidden_single(self, hints): if not SGG.READY_TO_GET_HIDDEN: self.prepare_to_get_hidden() result = 0 result += self.hs2(SGG.ROW,hints) result += self.hs2(SGG.COLUMN,hints) result += self.hs2(SGG.BOX,hints) return result def get_effects_1(self, cell_index, candidate_list): result = [] candidate_is_set = SGCell.candidate_is_set len_candidate_list = len(candidate_list) for candidate in SGG.R_SYMBOL_SET_SIZE: if candidate_is_set(self.sg_sudoku[cell_index],candidate): ok = 1 for list_index in range(len_candidate_list): if candidate == candidate_list[list_index]: ok = 0 break if ok == 1: result.append(cell_index) result.append(candidate) return result def get_cause_1(self, cell_index, candidate_list): result = [] candidate_is_set = SGCell.candidate_is_set len_candidate_list = len(candidate_list) for list_index in range(len_candidate_list): candidate = candidate_list[list_index] if candidate_is_set(self.sg_sudoku[cell_index],candidate): result.append(cell_index) result.append(candidate) return result def hp3(self,cell_list,candidate): result = [] candidate_is_set = SGCell.candidate_is_set for list_index in SGG.R_SYMBOL_SET_SIZE: cell_index = cell_list[list_index] if candidate_is_set(self.sg_sudoku[cell_index],candidate): result.append(cell_index) return result def hp2(self, shape, hints): cell_indexes_1 = [] cell_indexes_2 = [] cell_indexes_set = [] result = [] cause = [] score = 0 max_score = 0 if shape == SGG.ROW: p_counts = SGG.ROW_CELL_CANDIDATE_COUNTS p_c = SGG.ROW_CELLS_WITH_CANDIDATE elif shape == SGG.COLUMN: p_counts = SGG.COLUMN_CELL_CANDIDATE_COUNTS p_c = SGG.COLUMN_CELLS_WITH_CANDIDATE elif shape == SGG.BOX: p_counts = SGG.BOX_CELL_CANDIDATE_COUNTS p_c = SGG.BOX_CELLS_WITH_CANDIDATE for shape_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(shape_index, shape) counts = p_counts[shape_index] # any candidates occur twice? for candidate_1 in range(SGG.SYMBOL_SET_SIZE-1): if counts[candidate_1] == 2: cell_indexes_1 = p_c[shape_index][candidate_1] for candidate_2 in range(candidate_1 + 1, SGG.SYMBOL_SET_SIZE): if counts[candidate_2] == 2: cell_indexes_2 = p_c[shape_index][candidate_2] # in the same cells? cell_indexes_set_1 = set(cell_indexes_1) cell_indexes_set_2 = set(cell_indexes_2) if cell_indexes_set_1 == cell_indexes_set_2: t = candidate_1, candidate_2 result_1 = self.get_effects_1(cell_indexes_1[0], t) result_2 = self.get_effects_1(cell_indexes_1[1], t) result = result_1 + result_2 len_result = len(result) score = len_result / 2 if score > 0: cause = [] t_1 = cell_indexes_set_1.pop() t_2 = cell_indexes_set_1.pop() cause.append(t_1) cause.append(candidate_1) cause.append(t_1) cause.append(candidate_2) cause.append(t_2) cause.append(candidate_1) cause.append(t_2) cause.append(candidate_2) if score: hints.add(score, result, cause, \ SGG.HIDDEN_PAIRS) if score > max_score: max_score = score return max_score def hidden_pairs(self,hints): if not SGG.READY_TO_GET_HIDDEN: self.prepare_to_get_hidden() result = 0 result = result + self.hp2(SGG.ROW,hints) result = result + self.hp2(SGG.COLUMN,hints) result = result + self.hp2(SGG.BOX,hints) return result def ht2(self,shape,hints): cell_indexes_1 = [] cell_indexes_2 = [] cell_indexes_3 = [] cell_indexes_set = [] result = [] cause = [] score = 0 max_score = 0 if shape == SGG.ROW: p_counts = SGG.ROW_CELL_CANDIDATE_COUNTS p_c = SGG.ROW_CELLS_WITH_CANDIDATE elif shape == SGG.COLUMN: p_counts = SGG.COLUMN_CELL_CANDIDATE_COUNTS p_c = SGG.COLUMN_CELLS_WITH_CANDIDATE elif shape == SGG.BOX: p_counts = SGG.BOX_CELL_CANDIDATE_COUNTS p_c = SGG.BOX_CELLS_WITH_CANDIDATE for shape_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(shape_index, shape) counts = p_counts[shape_index] # any candidates occur twice or more? for candidate_1 in range(SGG.SYMBOL_SET_SIZE-2): if counts[candidate_1] > 1 and counts[candidate_1] < 4: cell_indexes_1 = p_c[shape_index][candidate_1] for candidate_2 in range(candidate_1 + 1,\ SGG.SYMBOL_SET_SIZE-1): if counts[candidate_2] > 1 and counts[candidate_2] < 4: cell_indexes_2 = p_c[shape_index][candidate_2] for candidate_3 in range(candidate_2 + 1,\ SGG.SYMBOL_SET_SIZE): if counts[candidate_3] > 1 and \ counts[candidate_3] < 4: cell_indexes_3 = p_c[shape_index][candidate_3] cell_indexes_set = set(cell_indexes_1) \ | set(cell_indexes_2) \ | set(cell_indexes_3) if len(cell_indexes_set) == 3: t = candidate_1, candidate_2, \ candidate_3 cell_index_1 = cell_indexes_set.pop() cell_index_2 = cell_indexes_set.pop() cell_index_3 = cell_indexes_set.pop() result_1 = self.get_effects_1(\ cell_index_1, t) result_2 = self.get_effects_1(\ cell_index_2, t) result_3 = self.get_effects_1(\ cell_index_3, t) result = result_1 + result_2 + result_3 score = len(result)/2 if score > 0: # causing cell/candidate combinations? cause = [] t = candidate_1, candidate_2, \ candidate_3 result_1 = self.get_cause_1(\ cell_index_1, t) result_2 = self.get_cause_1(\ cell_index_2, t) result_3 = self.get_cause_1(\ cell_index_3, t) cause = result_1 + result_2 + \ result_3 # check for each candidate in each cell if score > max_score: \ max_score = score hints.add(score, result, cause, \ SGG.HIDDEN_TRIPLES) return max_score def hidden_triples(self,hints): if not SGG.READY_TO_GET_HIDDEN: self.prepare_to_get_hidden() result = 0 result = result + self.ht2(SGG.ROW,hints) result = result + self.ht2(SGG.COLUMN,hints) result = result + self.ht2(SGG.BOX,hints) return result def naked_1(self, cell_list_1, cell_list_2, candidate_list): """ return effects for naked quads etc """ # cell_list_2 causing cell indexes # cell_list_1 complete cell index list # find cells in list 1 not in list 2: they are effects result = [] candidate_is_set = SGCell.candidate_is_set len_cell_list_2 = len(cell_list_2) len_candidate_list = len(candidate_list) for list_index_1 in SGG.R_SYMBOL_SET_SIZE: cell_index_1 = cell_list_1[list_index_1] good_index = 1 for list_index_2 in range(len_cell_list_2): if cell_index_1 == cell_list_2[list_index_2]: good_index = 0 break if good_index: for candidate_list_index in range(len_candidate_list): candidate = candidate_list[candidate_list_index] if candidate_is_set(\ self.sg_sudoku[cell_index_1],candidate): result.append(cell_index_1) result.append(candidate) return result def naked_2(self, cell_list, candidate_list): """find cells in list with these candidates \ return as cell_index, candidate pairs""" result = [] candidate_is_set = SGCell.candidate_is_set len_cell_list = len(cell_list) len_candidate_list = len(candidate_list) for list_index in range(len_cell_list): cell_index = cell_list[list_index] for candidate_list_index in range(len_candidate_list): candidate = candidate_list[candidate_list_index] if candidate_is_set(\ self.sg_sudoku[cell_index],candidate): result.append(cell_index) result.append(candidate) return result def naked_pairs_1(self, cell_list_in, good_stuff, hints): """ do naked_pairs for a 9mer""" result = 0 len_good_stuff = len(good_stuff) # good_stuff is tuples of cell_indexes and their candidates for list_index_1 in range(len_good_stuff-1): cell_index_1, candidates_1 = good_stuff[list_index_1] for list_index_2 in range(list_index_1+1, len_good_stuff): cell_index_2, candidates_2 = good_stuff[list_index_2] candidate_set = \ candidates_1 | \ candidates_2 # candidate_set is set of candidates from 3 cells if len(candidate_set) == 2: cell_list = [] cell_list.append(cell_index_1) cell_list.append(cell_index_2) # cell_list is list of the 3 cell indexes (causes) good_candidate_list = [] for list_index in range(2): good_candidate_list.append(candidate_set.pop()) # good_candidate_list is list of the 4 candidates effect = self.naked_1(\ cell_list_in, \ cell_list, \ good_candidate_list) len_effects = len(effect) if len_effects > 0: score = len_effects / 2 cause = self.naked_2(cell_list, \ good_candidate_list) hints.add(score, effect, cause, \ SGG.NAKED_PAIRS) result = 1 return result def naked_pairs(self,hints): if not SGG.READY_TO_GET_NAKED: self.prepare_to_get_naked() result = 0 for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.ROW) result += \ self.naked_pairs_1(cell_list, \ SGG.CANDIDATES_IN_ROWS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.COLUMN) result += \ self.naked_pairs_1(cell_list, \ SGG.CANDIDATES_IN_COLUMNS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.BOX) result += \ self.naked_pairs_1(cell_list, \ SGG.CANDIDATES_IN_BOXES[cell_index], hints) return result def naked_triples_1(self, cell_list_in, good_stuff, hints): """ do naked_triples for a 9mer""" result = 0 len_good_stuff = len(good_stuff) # good_stuff is tuples of cell_indexes and their candidates for list_index_1 in range(len_good_stuff-2): cell_index_1, candidates_1 = good_stuff[list_index_1] for list_index_2 in range(list_index_1+1, len_good_stuff-1): cell_index_2, candidates_2 = good_stuff[list_index_2] for list_index_3 in range(list_index_2+1, len_good_stuff): cell_index_3, candidates_3 = good_stuff[list_index_3] candidate_set = \ candidates_1 | \ candidates_2 | \ candidates_3 # candidate_set is set of candidates from 3 cells if len(candidate_set) == 3: cell_list = [] cell_list.append(cell_index_1) cell_list.append(cell_index_2) cell_list.append(cell_index_3) # cell_list is list of the 3 cell indexes (causes) good_candidate_list = [] for list_index in range(3): good_candidate_list.append(candidate_set.pop()) # good_candidate_list is list of the 4 candidates effect = self.naked_1(\ cell_list_in, \ cell_list, \ good_candidate_list) len_effects = len(effect) if len_effects > 0: score = len_effects / 2 cause = self.naked_2(cell_list, \ good_candidate_list) hints.add(score, effect, cause, \ SGG.NAKED_TRIPLES) result = 1 return result def naked_triples(self,hints): if not SGG.READY_TO_GET_NAKED: self.prepare_to_get_naked() result = 0 for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.ROW) result += \ self.naked_triples_1(cell_list, \ SGG.CANDIDATES_IN_ROWS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.COLUMN) result += \ self.naked_triples_1(cell_list, \ SGG.CANDIDATES_IN_COLUMNS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.BOX) result += \ self.naked_triples_1(cell_list, \ SGG.CANDIDATES_IN_BOXES[cell_index], hints) return result def naked_quads_1(self, cell_list_in, good_stuff, hints): """ do naked_quads for a 9mer""" result = 0 len_good_stuff = len(good_stuff) # good_stuff is tuples of cell_indexes and their candidates for list_index_1 in range(len_good_stuff-3): cell_index_1, candidates_1 = good_stuff[list_index_1] for list_index_2 in range(list_index_1+1, len_good_stuff-2): cell_index_2, candidates_2 = good_stuff[list_index_2] for list_index_3 in range(list_index_2+1, len_good_stuff-1): cell_index_3, candidates_3 = good_stuff[list_index_3] for list_index_4 in range(list_index_3+1, len_good_stuff): cell_index_4, candidates_4 = good_stuff[list_index_4] candidate_set = \ candidates_1 | \ candidates_2 | \ candidates_3 | \ candidates_4 # candidate_set is set of candidates from 4 cells if len(candidate_set) == 4: cell_list = [] cell_list.append(cell_index_1) cell_list.append(cell_index_2) cell_list.append(cell_index_3) cell_list.append(cell_index_4) # cell_list is list of the 4 cell indexes (causes) good_candidate_list = [] for list_index in range(4): good_candidate_list.append(candidate_set.pop()) # good_candidate_list is list of the 4 candidates effect = self.naked_1(\ cell_list_in, \ cell_list, \ good_candidate_list) len_effects = len(effect) if len_effects > 0: score = len_effects / 2 cause = self.naked_2(cell_list, \ good_candidate_list) hints.add(score, effect, cause, \ SGG.NAKED_QUADS) result = 1 return result def naked_quads(self,hints): if not SGG.READY_TO_GET_NAKED: self.prepare_to_get_naked() result = 0 for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.ROW) result += \ self.naked_quads_1(cell_list, \ SGG.CANDIDATES_IN_ROWS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.COLUMN) result += \ self.naked_quads_1(cell_list, \ SGG.CANDIDATES_IN_COLUMNS[cell_index], hints) for cell_index in SGG.R_SYMBOL_SET_SIZE: cell_list = self.get_cell_list(cell_index, SGG.BOX) result += \ self.naked_quads_1(cell_list, \ SGG.CANDIDATES_IN_BOXES[cell_index], hints) return result def indexes_with_candidate(self, cell_list, candidate, shape): """ return list of row or column indexes with candidate""" result = [] candidate_is_set = SGCell.candidate_is_set if shape == SGG.ROW: result = [self.sg_sudoku[x].column for x in cell_list if \ candidate_is_set(self.sg_sudoku[x],candidate)] else: result = [self.sg_sudoku[x].row for x in cell_list if \ candidate_is_set(self.sg_sudoku[x],candidate)] return result def row_col_to_index(self, index_1, index_2, shape): if shape == SGG.ROW: result = index_1 * SGG.SYMBOL_SET_SIZE + index_2 elif shape == SGG.COLUMN: result = index_2 * SGG.SYMBOL_SET_SIZE + index_1 return result def fish_1(self, index_list, ninemer_index, candidate, shape): """ return list of alternating cell_index, candidate pairs""" result = [] len_list = len(index_list) for list_index in range(len_list): cell_index = self.row_col_to_index(ninemer_index, \ index_list[list_index],\ shape) result.append(cell_index) result.append(candidate) return result def get_effects_2(self, cell_list, candidate_in, ninemer_list): """ return cell_index, candidate pairs from cells \ with candidate candidate but not from ninemers in ninemer_list """ result = [] candidate_is_set = SGCell.candidate_is_set len_ninemer_list = len(ninemer_list) for cell_list_index in SGG.R_SYMBOL_SET_SIZE: ok = 1 for ninemer_index in range(len_ninemer_list): if cell_list_index == ninemer_list[ninemer_index]: ok = 0 break if ok == 1: cell_index = cell_list[cell_list_index] if candidate_is_set(self.sg_sudoku[cell_index],\ candidate_in): result.append(cell_index) result.append(candidate_in) return result def xwing_1(self, shape_in, hints): score = 0 max_score = 0 shape = SGG.COLUMN data = SGG.COLUMNS_WITH_CANDIDATE if shape_in == SGG.COLUMN: shape = SGG.ROW data = SGG.ROWS_WITH_CANDIDATE for candidate in SGG.R_SYMBOL_SET_SIZE: cell_list = data[candidate] r1 = SGG.SYMBOL_SET_SIZE-1 for index_1 in range(r1): list_1 = cell_list[index_1] # list_1 is row/column indexes with candidate len_list_1 = len(list_1) if len_list_1 == 2: # candidate occurs in 2 rows/columns r2s = index_1 + 1 r2e = SGG.SYMBOL_SET_SIZE for index_2 in range(r2s,r2e): list_2 = cell_list[index_2] len_list_2 = len(list_2) if len_list_2 == 2: # make set to make counting easier!!! t_set = \ set(list_1) | \ set(list_2) len_t_set = len(t_set) cause = [] effect = [] if len_t_set == 2: # candidate in 2 row and # 2 column intersects # stick set elements in t t = [] for i in range(len_t_set): t.append(t_set.pop()) # get causes cause += self.fish_1(\ list_1, \ index_1, \ candidate, \ shape_in) cause += self.fish_1(\ list_2, \ index_2, \ candidate, \ shape_in) # get effects ninemer_list = \ index_1, \ index_2 for i in range(len_t_set): cell_list_t = \ self.get_cell_list(\ t[i], shape) effect += \ self.get_effects_2(\ cell_list_t, \ candidate, \ ninemer_list) score = len(effect) / 2 hints.add(score, effect, cause, \ SGG.X_WING) if score > max_score: max_score = score return max_score def xwing(self, hints): if not SGG.READY_TO_GO_FISHING: self.prepare_to_go_fishing() result = 0 result += self.xwing_1(SGG.ROW, hints) result += self.xwing_1(SGG.COLUMN, hints) return result def check_cause(self, cause, shape): # calling algorithm can make mistakes # check here that each causing cell has a partner counts = [0] * SGG.SYMBOL_SET_SIZE len_cause = len(cause) for list_index in range(0,len_cause,2): cell_index = cause[list_index] if shape == SGG.ROW: t = self.sg_sudoku[cell_index].column else: t = self.sg_sudoku[cell_index].row counts[t] += 1 for candidate in SGG.R_SYMBOL_SET_SIZE: if counts[candidate] == 1: return False return True def swordfish_1(self, shape_in, hints): score = 0 max_score = 0 shape = SGG.COLUMN data = SGG.COLUMNS_WITH_CANDIDATE if shape_in == SGG.COLUMN: shape = SGG.ROW data = SGG.ROWS_WITH_CANDIDATE for candidate in SGG.R_SYMBOL_SET_SIZE: cell_list = data[candidate] r1 = SGG.SYMBOL_SET_SIZE-2 for index_1 in range(r1): list_1 = cell_list[index_1] # list_1 is row/column indexes with candidate len_list_1 = len(list_1) if len_list_1 > 1: # candidate occurs in >1 rows/columns r2s = index_1 + 1 r2e = SGG.SYMBOL_SET_SIZE - 1 for index_2 in range(r2s,r2e): list_2 = cell_list[index_2] len_list_2 = len(list_2) if len_list_2 > 1: r3s = index_2 + 1 r3e = SGG.SYMBOL_SET_SIZE for index_3 in range(r3s,r3e): list_3 = cell_list[index_3] len_list_3 = len(list_3) if len_list_3 > 1: # make set to make counting easier t_set = \ set(list_1) | \ set(list_2) | \ set(list_3) len_t_set = len(t_set) cause = [] effect = [] if len_t_set == 3: # candidate in 3 row and # 3 column intersects # stick set elements in t t = [] for i in range(len_t_set): t.append(t_set.pop()) # get causes cause += self.fish_1(\ list_1, \ index_1, \ candidate, \ shape_in) cause += self.fish_1(\ list_2, \ index_2, \ candidate, \ shape_in) cause += self.fish_1(\ list_3, \ index_3, \ candidate, \ shape_in) if self.check_cause(cause, shape_in): # get effects ninemer_list = \ index_1, \ index_2,\ index_3 for i in range(len_t_set): cell_list_t = \ self.get_cell_list(\ t[i], shape) effect += \ self.get_effects_2(\ cell_list_t, \