/*
* This file is part of sudognu.
*
* Copyright (C) 2007-2009 Jens Baaran, Germany.
******************************************************************************/
#ifndef _SUDOKU_H
#define _SUDOKU_H
#include <stdio.h>
#ifndef __MINGW_H
#include <pthread.h>
#define PTHREAD_MUTEX_TYPE pthread_mutex_t
#define HAS_PTHREADS
#else
#define PTHREAD_MUTEX_TYPE int
#define PTHREAD_MUTEX_INITIALIZER 0
#undef HAS_PTHREADS
#endif
#define SIZE 3
#define SIZE2 (SIZE*SIZE)
#define NUM_NEIGHBOURS (SIZE2 + 2*(SIZE2-SIZE) - 1)
#define DEBUG 0
#define VERSION "1.10"
#define MAX_STRLEN 1024
// number of elimination strategies, must correspond to number of elim_types, see below
#define NUM_ET 19
typedef enum {
et_wg, // 0 wrong guess
et_hs, // 1 hidden single
et_s, // 2 single
et_hd, // 3 hidden double
et_d, // 4 double
et_b, // 5 block-line interaction
et_l, // 6 line-block interaction
et_ht, // 7 hidden triple
et_t, // 8 triple
et_hq, // 9 hidden quadruple
et_q, // 10 quadruple
et_xy, // 11 xy-wing
et_xyz, // 12 xyz-wing
et_xw, // 13 x-wing
et_2c, // 14 2-color
et_sf, // 15 swordfish
et_jf, // 16 jellyfish
et_fc, // 17 forcing chain
et_g // 18 guess
} elim_type;
typedef enum {
stat_undef,
stat_free,
stat_given,
stat_ggiven,
stat_hsingle,
stat_single,
stat_guess,
stat_fchain,
stat_2color,
stat_colortmp
} status;
typedef enum {
symm_none, // no symmetry
symm_h, // horizontal symmetry axis
symm_v, // vertical symmetry axis
symm_p, // point symmetry
symm_hv, // 2 symmetry axes, horiz. and vert.
symm_a // axisymmetry, unspecified
} t_symmetry;
typedef struct {
int value;
int cand[SIZE2];
int ncand;
status stat;
} t_field;
typedef struct {
t_field grid[SIZE2][SIZE2];
int size;
float rating;
} t_sudoku;
/* block_line.c: deal with block-line interaction
******************************************************************************/
int block_line(t_sudoku *sudoku, int doElim, int verbosity);
int line_block(t_sudoku *sudoku, int doElim, int verbosity);
/* cand.c: deal with candidates
******************************************************************************/
void update_num_candidates(t_sudoku *sudoku);
void remove_candidates(t_sudoku *sudoku, int row, int col);
void get_candidates(t_sudoku *sudoku);
int get_random_cand(t_field cell);
/* canoni.c
******************************************************************************/
int canoni(t_sudoku sudoku, t_sudoku *canon);
void beautify_symmetric_sudoku(t_sudoku *sudoku);
void print_grid(FILE *f, int **grid, int rows, int brows, int cols, int bcols);
int next_tuple(int *t0, int *t1, int size);
void init_permuts(int *t0, int **t1, int size, int tupSize, int *itup, int ntup);
void get_block_row(int **srcgrid, int **destgrid, int rows, int brows, int cols, int bcols, int minh);
void exchange_block_col(int **srcgrid, int **destgrid, int rows, int brows, int cols, int bcols, int *bcMap);
void exchange_block_row(int **srcgrid, int **destgrid, int rows, int brows, int cols, int bcols, int *brMap);
void exchange_row_in_b(int **srcgrid, int **destgrid, int rows, int rowbs, int cols, int colbs, int blk, int *rMap);
void exchange_col_in_b(int **srcgrid, int **destgrid, int rows, int rowbs, int cols, int colbs, int blk, int *cMap);
void exchange_value(int **srcgrid, int **destgrid, int rows, int cols, int *valMap);
void renumber_min(int **grid0, int **grid1, int rows, int cols, int vals);
void copy_grid(int **gridsrc, int **griddest, int rows, int cols);
void reset_grid(int **grid, int rows, int cols);
int compare_grids(int **grid0, int **grid1, int rows, int cols);
int rate_grid_b(int **grid, int rows, int cols);
/* color.c
******************************************************************************/
int two_color(t_sudoku *sudoku, int doElim, int verbosity);
/* create_sudoku.c
******************************************************************************/
int execute_thread_create(void *arg[]);
int create_sudoku(t_sudoku *sudoku, int verbosity);
int create_unsymm(t_sudoku *sudoku);
int create_psymm(t_sudoku *sudoku);
int create_asymm(t_sudoku *sudoku);
void remove_gratuituous_givens(t_sudoku *sudoku);
void remove_gratuituous_givens_symm(t_sudoku *sudoku);
/* fish.c: deal with x-wing, swordfish, jellyfish
******************************************************************************/
int fish(t_sudoku *sudoku, int fish, int doElim, int verbosity);
void find_fish(t_sudoku *sudoku, int fish, int ifish, int *r, int *c, int cc, int doElim, int verbosity, int *nfish);
int fish_rc(t_sudoku *sudoku, int fish, int cc, int *r, int *c, const char ent[12], int doElim, int verbosity);
/* forcing_chain.c
******************************************************************************/
int forcing_chain(t_sudoku *sudoku, int verbosity, int *fcl);
void diff_grid(t_field grid0[SIZE2][SIZE2],t_field grid1[SIZE2][SIZE2], t_field egrid[SIZE2][SIZE2], int size);
void grid_to_zero(t_field grid[SIZE2][SIZE2], int size);
//void merge_grid(t_field grid0[SIZE2][SIZE2],t_field grid1[SIZE2][SIZE2], t_field egrid[SIZE2][SIZE2], int size);
void intersect_grid_no_cands(t_field grid0[SIZE2][SIZE2],t_field grid1[SIZE2][SIZE2], t_field egrid[SIZE2][SIZE2], int size);
void intersect_grid_with_cands(t_field grid0[SIZE2][SIZE2],t_field grid1[SIZE2][SIZE2], t_field egrid[SIZE2][SIZE2], int size);
/* getopt.c: parse options
******************************************************************************/
int getoptions(int argc, char *argv[]);
void print_version(FILE *f);
void print_usage(FILE *f);
void print_help(FILE *f);
void print_contact(FILE *f);
/* grid.c: deal with complete grid
******************************************************************************/
void copy_sudoku(t_sudoku sudokuSrc ,t_sudoku *sudoku_Dest);
void reset_sudoku(t_sudoku *sudoku);
void transpose_sudoku(t_sudoku *sudoku);
void insert_val(t_sudoku *s, int r, int c, int cc, status stat);
//void exchange_block_rc(t_sudoku *sudoku, char ent, int brcMap[SIZE]);
//void exchange_rc(t_sudoku *sudoku, char ent, int rcMap[SIZE2]);
//void exchange_value(t_sudoku *sudoku, int valMap[SIZE2]);
void get_neighbours(int row, int col, int nb[SIZE2 + 2*(SIZE2-SIZE) - 1][2]);
int get_common_neighbours(int rc1[2], int rc2[2], int nb[SIZE2 + 2*(SIZE2-SIZE) - 1][2]);
int get_common_neighbours3(int rc1[2], int rc2[2], int rc3[2], int nb[SIZE2 + 2*(SIZE2-SIZE) - 1][2]);
int read_sudoku_from_file(FILE *f, t_sudoku *sudoku);
int check_sudoku(t_sudoku sudoku);
int get_num_cell_with_stat1(t_sudoku sudoku, status stat);
t_symmetry check_sudoku_symmetry(t_sudoku sudoku, int *r, int *c);
int read_sudoku_from_vector(int *a, t_sudoku *sudoku);
int read_sudoku_from_string(char *a, t_sudoku *sudoku);
int read_sudoku_and_candidates_from_file(FILE *f, t_sudoku *sudoku);
void set_stat_and_ncand_from_values_and_cands(t_sudoku *sudoku);
int get_basic_rating(t_sudoku sudoku, int elim[NUM_ET]);
int get_random_cell(t_sudoku sudoku, status stat);
//int get_random_cell2(t_sudoku sudoku, status stat);
//int get_random_cell3(t_field grid[SIZE2][SIZE2], int size, status stat);
/* hidden_tuple.c: deal with hidden tupels
******************************************************************************/
int hidden_single(t_sudoku *sudoku, int doElim, int verbosity);
int hsinglecc(t_sudoku *s, int cc);
int hidden_tuple(t_sudoku *sudoku, int tuple, int doElim, int verbosity);
void find_hidden_tuple(t_sudoku *sudoku, int tuple, int itup, int c, int *cc, int colVals[SIZE2], int rowVals[SIZE2], int blkVals[SIZE2], int doElim, int verbosity, int *ntup);
void hidden_tuple_crb(t_sudoku *sudoku, int tuple, int *cc, int c, char ent, int doElim, int verbosity, int *ntup);
/* pdf_sheet.c
******************************************************************************/
void sudokus_to_pdf(char fn[512], t_sudoku *sudokus, int numSudokus);
int grid_to_pdf(t_field grid[SIZE2][SIZE2], int size, char *title, FILE *f, char* font, int x0, int y0, int sqsize, float linewidth);
/* print.c
******************************************************************************/
int fprint_sudoku(FILE *file, t_sudoku sudoku);
int print_sudoku_as_grid(t_sudoku sudoku);
int fprint_sudoku_as_grid(FILE *out, t_sudoku sudoku);
int print_candidates_as_grid(t_sudoku sudoku);
void print_sudoku_and_candidates_as_html(char fn[512], t_sudoku sudoku);
void sudoku_and_candidates_to_string(t_sudoku sudoku, char gstr[SIZE2*SIZE2 + SIZE2*SIZE2*SIZE2 + 1]);
void fprint_explain(char *estr, t_sudoku sudoku, int verbosity);
/* print_svg.c
******************************************************************************/
void sudokus_to_svg(char fn[512], t_sudoku sudokus[4]);
void grid_to_svg(FILE *f, t_field grid[SIZE2][SIZE2], int size, float x0, float y0, float squareSize, float thickLineWidth, float thinLineWidth, int sudokuFontSz, int numberFontSz, char *sudTitle);
void get_sudoku_title(int isud, int rating, char *title);
/* print_ps.c
******************************************************************************/
void sudokus_to_ps(char *filename, t_sudoku *sudokus, int num_sudokus);
/* pthread.c
******************************************************************************/
void my_pthread_mutex_lock(PTHREAD_MUTEX_TYPE *m);
void my_pthread_mutex_unlock(PTHREAD_MUTEX_TYPE *m);
int solve_sudoku_and_check_uniqueness_pthread(FILE * in, int verbosity);
int create_sudoku_pthread(int verbosity);
/* solve.c: solve sudoku
******************************************************************************/
int execute_thread_solve(void *arg[]);
int solve_sudoku_and_check_uniqueness(FILE *in, int verbosity);
int solve_sudoku(t_sudoku *sudoku, int elim[NUM_ET], int depth, int verbosity, int doRate);
int check_uniqueness1(t_sudoku sudoku,t_sudoku ssudoku);
int solve_sudoku_rec(t_sudoku *sudoku, t_sudoku *dsudoku, int elim[NUM_ET], int r, int c, int cc, int depth, int verbosity, int doRate);
int eliminate(t_sudoku *sudoku, int elim[NUM_ET], int depth, int verbosity, int doRate);
int apply_solution_technique1(t_sudoku *sudoku, int elim[NUM_ET], int depth, int verbosity, FILE *out);
void find_cell_and_cand_for_guess(t_field grid[SIZE2][SIZE2], int size, int *r, int *c, int *cc);
/* tuple.c: deal with tupels
******************************************************************************/
int single(t_sudoku *sudoku, int doElim, int verbosity);
int tuple(t_sudoku *sudoku, int tuple, int doElim, int verbosity);
void find_tuple(t_sudoku *sudoku, int tuple, int itup, int c, int *cc, int colVals[SIZE2], int rowVals[SIZE2], int blkVals[SIZE2], int doElim, int verbosity, int *ntup);
void tuple_crb(t_sudoku *sudoku, int tuple, int *cc, int c, char ent, int doElim, int verbosity, int *ntup);
/* wing.c: xy-wing
******************************************************************************/
int xy_wing(t_sudoku *sudoku, int doElim, int verbosity);
int xyz_wing(t_sudoku *sudoku, int doElim, int verbosity);
#endif