Add James H's new puzzle, `Unequal' (otherwise known as the

Guardian's `Futoshiki').

[originally from svn r7100]
This commit is contained in:
Simon Tatham
2007-01-13 14:44:50 +00:00
parent 9993f71e4c
commit 2f8dba9257
5 changed files with 3493 additions and 0 deletions

1320
latin.c Normal file

File diff suppressed because it is too large Load Diff

114
latin.h Normal file
View File

@ -0,0 +1,114 @@
#ifndef LATIN_H
#define LATIN_H
#include "puzzles.h"
typedef unsigned char digit;
/* --- Solver structures, definitions --- */
#ifdef STANDALONE_SOLVER
int solver_show_working, solver_recurse_depth;
#endif
struct latin_solver {
int o; /* order of latin square */
unsigned char *cube; /* o^3, indexed by x, y, and digit:
TRUE in that position indicates a possibility */
digit *grid; /* o^2, indexed by x and y: for final deductions */
unsigned char *row; /* o^2: row[y*cr+n-1] TRUE if n is in row y */
unsigned char *col; /* o^2: col[x*cr+n-1] TRUE if n is in col x */
};
#define cubepos(x,y,n) (((x)*solver->o+(y))*solver->o+(n)-1)
#define cube(x,y,n) (solver->cube[cubepos(x,y,n)])
#define gridpos(x,y) ((y)*solver->o+(x))
#define grid(x,y) (solver->grid[gridpos(x,y)])
/* A solo solver using this code would need these defined. See solo.c. */
#ifndef YTRANS
#define YTRANS(y) (y)
#endif
#ifndef YUNTRANS
#define YUNTRANS(y) (y)
#endif
/* --- Solver individual strategies --- */
/* Place a value at a specific location. */
void latin_solver_place(struct latin_solver *solver, int x, int y, int n);
/* Positional elimination. */
int latin_solver_elim(struct latin_solver *solver, int start, int step
#ifdef STANDALONE_SOLVER
, char *fmt, ...
#endif
);
struct latin_solver_scratch; /* private to latin.c */
/* Set elimination */
int latin_solver_set(struct latin_solver *solver,
struct latin_solver_scratch *scratch,
int start, int step1, int step2
#ifdef STANDALONE_SOLVER
, char *fmt, ...
#endif
);
/* Forcing chains */
int latin_solver_forcing(struct latin_solver *solver,
struct latin_solver_scratch *scratch);
/* --- Solver allocation --- */
/* Fills in (and allocates members for) a latin_solver struct.
* Will allocate members of snew, but not snew itself
* (allowing 'struct latin_solver' to be the first element in a larger
* struct, for example). */
void latin_solver_alloc(struct latin_solver *solver, digit *grid, int o);
void latin_solver_free(struct latin_solver *solver);
/* Allocates scratch space (for _set and _forcing) */
struct latin_solver_scratch *
latin_solver_new_scratch(struct latin_solver *solver);
void latin_solver_free_scratch(struct latin_solver_scratch *scratch);
/* --- Solver guts --- */
/* Looped positional elimination */
int latin_solver_diff_simple(struct latin_solver *solver);
/* Looped set elimination; *extreme is set if it used
* the more difficult single-number elimination. */
int latin_solver_diff_set(struct latin_solver *solver,
struct latin_solver_scratch *scratch,
int *extreme);
typedef int (latin_solver_callback)(digit *, int, int, void*);
/* Use to provide a standard way of dealing with solvers which can recurse;
* pass in your enumeration for 'recursive diff' and your solver
* callback. Returns #solutions (0 == already solved). */
int latin_solver_recurse(struct latin_solver *solver, int recdiff,
latin_solver_callback cb, void *ctx);
/* Individual puzzles should use their enumerations for their
* own difficulty levels, ensuring they don't clash with these. */
enum { diff_impossible = 10, diff_ambiguous, diff_unfinished };
int latin_solver(digit *grid, int order, int maxdiff, void *unused);
void latin_solver_debug(unsigned char *cube, int o);
/* --- Generation and checking --- */
digit *latin_generate_quick(int o, random_state *rs);
digit *latin_generate(int o, random_state *rs);
int latin_check(digit *sq, int order); /* !0 => not a latin square */
void latin_debug(digit *sq, int order);
#endif

View File

@ -2073,6 +2073,75 @@ possible islands; low expansion factors can create lots of
tightly-packed islands.
\C{unequal} \i{Unequal}
\cfg{winhelp-topic}{games.unequal}
You have a square grid; each square may contain a digit from 1 to
the size of the grid, and some squares have greater-signs between
them. Your aim is to fully populate the grid with numbers such that:
\b Each row contains only one occurrence of each digit
\b Each column contains only one occurrence of each digit
\b All the greater-than signs are satisfied.
In 'Trivial' mode, there are no greater-than signs; the puzzle is
to solve the latin square only.
At the time of writing, this puzzle is appearing in the Guardian
weekly under the name 'Futoshiki'.
Unequal was contributed to this collection by James Harvey.
\H{unequal-controls} \i{Unequal controls}
\IM{Unequal controls} controls, for Unequal
Unequal shares much of its control system with Solo.
To play Unequal, simply click the mouse in any empty square and then
type a digit or letter on the keyboard to fill that square. If you
make a mistake, click the mouse in the incorrect square and press
Space to clear it again (or use the Undo feature).
If you \e{right}-click in a square and then type a number, that
number will be entered in the square as a \q{pencil mark}. You can
have pencil marks for multiple numbers in the same square.
The game pays no attention to pencil marks, so exactly what you use
them for is up to you: you can use them as reminders that a
particular square needs to be re-examined once you know more about a
particular number, or you can use them as lists of the possible
numbers in a given square, or anything else you feel like.
To erase a single pencil mark, right-click in the square and type
the same number again.
All pencil marks in a square are erased when you left-click and type
a number, or when you left-click and press space. Right-clicking and
pressing space will also erase pencil marks.
(All the actions described in \k{common-actions} are also available.)
\H{unequal-parameters} \I{parameters, for Unequal}Unequal parameters
These parameters are available from the \q{Custom...} option on the
\q{Type} menu.
\dt \e{Size (s*s)}
\dd Size of grid.
\dt \e{Difficulty}
\dd Controls the difficulty of the generated puzzle. At Trivial level,
there are no greater-than signs (the puzzle is to solve the latin
square only); at Tricky level, some recursion may be required (but the
solutions should always be unique).
\A{licence} \I{MIT licence}\ii{Licence}
This software is \i{copyright} 2004-2007 Simon Tatham.

23
unequal.R Normal file
View File

@ -0,0 +1,23 @@
# -*- makefile -*-
UNEQUAL = unequal latin tree234 maxflow
unequal : [X] GTK COMMON UNEQUAL
unequal : [G] WINDOWS COMMON UNEQUAL
unequalsolver : [U] unequal[STANDALONE_SOLVER] latin[STANDALONE_SOLVER] tree234 maxflow STANDALONE
unequalsolver : [C] unequal[STANDALONE_SOLVER] latin[STANDALONE_SOLVER] tree234 maxflow STANDALONE
latincheck : [U] latin[STANDALONE_LATIN_TEST] tree234 maxflow STANDALONE
latincheck : [C] latin[STANDALONE_LATIN_TEST] tree234 maxflow STANDALONE
ALL += UNEQUAL
!begin gtk
GAMES += unequal
!end
!begin >list.c
A(unequal) \
!end

1967
unequal.c Normal file

File diff suppressed because it is too large Load Diff