procedure ProcessSolution(x,y:integer; Solution:string; SolutionReason:string);
begin
PassesSinceLastSolution := 0;
TotalCellsSolved := TotalCellsSolved + 1;
GridInfo{x}{y}.IsSolved := TRUE;
GridInfo{x}{y}.Possibilities := Solution;
GridInfo{x}{y}.Impossibilities := EliminateCharacter('123456789',Solution{1});
GridInfo{x}{y}.DisplayValue := Solution{1};
GridInfo{x}{y}.NumberOfModifications := GridInfo{x}{y}.NumberOfModifications + 1;
GridInfo{x}{y}.ModificationReasons{GridInfo{x}{y}.NumberOfModifications} := SolutionReason;
end;
procedure LoadPuzzle(PuzzleNum: string);
var
i,j,x : integer;
row : integer;
fp : textfile;
begin
assignfile(fp,'Puzzle325.txt');
(* assignfile(fp,'Test001.txt'); *)
try
reset(fp);
for j:=1 to 9 do
begin
readln(fp,OrigPuzzle{j});
end; (* for j *)
close(fp);
except
writeln('Error. Please check the text file.');
end; (* try - except *)
for j:= 1 to 9 do
begin
for i := 1 to 9 do
begin
GridInfo{i}{j}.xCoord := i;
GridInfo{i}{j}.yCoord := j;
GridInfo{i}{j}.CellNumber := ((j-1) * 9) + i;
GridInfo{i}{j}.BlockColumn := (((GridInfo{i}{j}.CellNumber - ((j-1)*9)) - 1) div 3) + 1;
GridInfo{i}{j}.BlockRow := ((GridInfo{i}{j}.CellNumber - 1) div 27) + 1;
if (GridInfo{i}{j}.BlockRow = 1) then
begin
case GridInfo{i}{j}.BlockColumn of
1 : GridInfo{i}{j}.BlockNumber := 1;
2 : GridInfo{i}{j}.BlockNumber := 2;
3 : GridInfo{i}{j}.BlockNumber := 3;
end; (* case *)
end;
if (GridInfo{i}{j}.BlockRow = 2) then
begin
case GridInfo{i}{j}.BlockColumn of
1 : GridInfo{i}{j}.BlockNumber := 4;
2 : GridInfo{i}{j}.BlockNumber := 5;
3 : GridInfo{i}{j}.BlockNumber := 6;
end; (* case *)
end;
if (GridInfo{i}{j}.BlockRow = 3) then
begin
case GridInfo{i}{j}.BlockColumn of
1 : GridInfo{i}{j}.BlockNumber := 7;
2 : GridInfo{i}{j}.BlockNumber := 8;
3 : GridInfo{i}{j}.BlockNumber := 9;
end; (* case *)
end;
if OrigPuzzle{j}{i} = '0' then
begin
GridInfo{i}{j}.displayvalue := '-';
GridInfo{i}{j}.IsSolved := FALSE;
GridInfo{i}{j}.Possibilities := '123456789';
GridInfo{i}{j}.Impossibilities := '';
GridInfo{i}{j}.NumberOfModifications := 0;
for x:=1 to MAXMODS do
GridInfo{i}{j}.ModificationReasons{x} := '';
end
else
begin
GridInfo{i}{j}.displayvalue := OrigPuzzle{j}{i};
GridInfo{i}{j}.IsSolved := TRUE;
GridInfo{i}{j}.Possibilities := OrigPuzzle{j}{i};
GridInfo{i}{j}.Impossibilities := EliminateCharacter('123456789',OrigPuzzle{j}{i});
GridInfo{i}{j}.NumberOfModifications := 1;
GridInfo{i}{j}.ModificationReasons{1} := 'Given.';
for x:=2 to MAXMODS do
GridInfo{i}{j}.ModificationReasons{x} := '';
end; (* end of the 'if 0 else something else' statement *)
end; (* for i *)
end; (* for j *)
end; (* procedure LoadPuzzle*)
procedure ExamineCell(Old_x, Old_y, Examine_x, Examine_y:integer);
var
k,ExtraSpace : integer;
begin
(* Clear the old cell's brackets *)
ExtraSpace := 0;
if Old_y>=4 then ExtraSpace := 1;
if Old_y>=7 then ExtraSpace := 2;
gotoxy(GRID_XBASE+1+((Old_x-1)*4),GRID_YBASE+2+Old_y+ExtraSpace);
write(' ');
gotoxy(GRID_XBASE+3+((Old_x-1)*4),GRID_YBASE+2+Old_y+ExtraSpace);
write(' ');
(* Draw the new cell's brackets *)
ExtraSpace := 0;
if Examine_y >=4 then ExtraSpace := 1;
if Examine_y >=7 then ExtraSpace := 2;
gotoxy(GRID_XBASE+2+((Examine_x-1)*4),GRID_YBASE+2+Examine_y+ExtraSpace);
write(GridInfo{Examine_x}{Examine_y}.displayvalue );
if (not AutoMovement) or (AutoMovement and (not GridInfo{Currentpos_x}{Currentpos_y}.IsSolved)) then
begin
gotoxy(GRID_XBASE+1+((Examine_x-1)*4),GRID_YBASE+2+Examine_y+ExtraSpace);
write('{');
gotoxy(GRID_XBASE+3+((Examine_x-1)*4),GRID_YBASE+2+Examine_y+ExtraSpace);
write('}');
(* Update the cell's displayed information *)
DisplayCurrentCoordinates;
DisplayMessage(39+GRID_XBASE,5+GRID_YBASE,' ');
DisplayMessage(39+GRID_XBASE,5+GRID_YBASE,GridInfo{Examine_x}{Examine_y}.Possibilities);
DisplayMessage(49+GRID_XBASE,5+GRID_YBASE,GridInfo{Examine_x}{Examine_y}.Impossibilities);
for k := MAXMODS downto 1 do
DisplayMessage(1+GRID_XBASE,15+k+GRID_YBASE,' ');
if (GridInfo{Examine_x}{Examine_y}.NumberOfModifications >= 1) then
begin
for k := 1 to GridInfo{Examine_x}{Examine_y}.NumberOfModifications do
begin
gotoxy(2+GRID_XBASE,15+k+GRID_YBASE);
write(' ');
DisplayMessage(6+GRID_XBASE,15+k+GRID_YBASE,GridInfo{Examine_x}{Examine_y}.ModificationReasons{k});
end;
end;
end;
end; (* Procedure ExamineCell *)
procedure Rule1; (* Is the cell the only blank one in the current column? *)
var
j : integer;
CheckThisColumn : integer;
NumberSolvedInColumn : integer;
StringBeingReduced : string;
ImpossibleCharacters : string;
OnlyRemainingCharacter : char;
begin
NumberSolvedInColumn := 0;
StringBeingReduced := '123456789';
CheckThisColumn := Currentpos_x;
for j := 1 to 9 do
begin
if GridInfo{CheckThisColumn}{j}.IsSolved = TRUE then
begin
NumberSolvedInColumn := NumberSolvedInColumn + 1;
StringBeingReduced := EliminateCharacter(StringBeingReduced,GridInfo{CheckThisColumn}{j}.DisplayValue);
(* Eliminate from the Possibilities any Solution which was found elswhere in the column. *)
GridInfo{Currentpos_x}{Currentpos_y}.Possibilities
:= EliminateCharacter(GridInfo{Currentpos_x}{Currentpos_y}.Possibilities,
GridInfo{CheckThisColumn}{j}.DisplayValue);
end;
end; (* for j *)
if NumberSolvedInColumn = 8 then (* ... then the cell we're checking is the only blank one in the column *)
ProcessSolution(Currentpos_x,Currentpos_y,StringBeingReduced,'Last blank cell in the column. (Rule 1)');
if GridInfo{Currentpos_x}{Currentpos_y}.IsSolved = FALSE then
begin
if length(GridInfo{Currentpos_x}{Currentpos_y}.Possibilities) = 1 then
ProcessSolution(Currentpos_x,Currentpos_y,GridInfo{Currentpos_x}{Currentpos_y}.Possibilities,
'Column, row and block solutions leave just one possibility. (Rule 4.1)');
end;
end; (* Procedure Rule1 *)
procedure Rule2; (* Is the cell the only blank one in the current row? *)
var
i : integer;
CheckThisRow : integer;
NumberSolvedInRow : integer;
StringBeingReduced : string;
ImpossibleCharacters : string;
OnlyRemainingCharacter : char;
begin
NumberSolvedInRow := 0;
StringBeingReduced := '123456789';
CheckThisRow:= Currentpos_y;
for i := 1 to 9 do
begin
if GridInfo{i}{CheckThisRow}.IsSolved = TRUE then
begin
NumberSolvedInRow := NumberSolvedInRow + 1;
StringBeingReduced := EliminateCharacter(StringBeingReduced,GridInfo{i}{CheckThisRow}.DisplayValue);
(* Eliminate from the Possibilities this Solution which was found elswhere in the row. *)
GridInfo{Currentpos_x}{Currentpos_y}.Possibilities
:= EliminateCharacter(GridInfo{Currentpos_x}{Currentpos_y}.Possibilities,
GridInfo{i}{CheckThisRow}.DisplayValue);
end;
end; (* for i *)
if NumberSolvedInRow = 8 then (* ... then the cell we're checking is the only blank one in the row *)
ProcessSolution(Currentpos_x,Currentpos_y,StringBeingReduced,'Last blank cell in the row. (Rule 2)');
if GridInfo{Currentpos_x}{Currentpos_y}.IsSolved = FALSE then
begin
if length(GridInfo{Currentpos_x}{Currentpos_y}.Possibilities) = 1 then
ProcessSolution(Currentpos_x,Currentpos_y,GridInfo{Currentpos_x}{Currentpos_y}.Possibilities,
'Column, row and block solutions leave just one possibility. (Rule 4.2)');
end;
end; (* Procedure Rule2 *)

Gold is $1,581/oz today. When it hits $2,000, it will be up 26.5%. Let's see how long that takes. - De 3/11/2013 - ANSWER: 7 Years, 5 Months
- - - - -
View Replies (1)
»
» You can also:
- - - - -
The above is a reply to the following message:
Re: Lazarus (Pascal) - Code part 1 of 4
By: Decomposed
in
POPE IV
Mon, 20 Nov 17 10:38 PM
|
Msg. 38936 of
47202
|
Note: In addition to breaking up the code into several pieces, I also had to replace all square brackets with curly brackets. If you try to compile the code, piece it back together, then change all '{' and '}' characters to '[' and ']', respectively.
program SudokuSolver3;
(* (c) 2017 by Decomposed. All rights reserved. *)
(* Requires a text file that looks like this, where zero represents a blank spot in the initial puzzle. *)
(* Search this source code for 'Puzzle325.txt and set it match whatever the text file is named.' *)
(*
021009000
000071802
050200010
040095200
500000006
003160080
010004060
804320000
000700420
*)
{$mode objfpc}{$H+}
uses
crt,
sysutils,
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
const
GRID_XBASE = 2; (* X_BASE and Y_BASE allow us to push the grid over and down *)
GRID_YBASE = 0; (* if we ever want to which we probably won't. *)
MAXMODS = 7;
type
cell_characteristics = record
CellNumber : integer;
DisplayValue : char;
Possibilities : string;
Impossibilities : string;
xCoord : integer;
yCoord : integer;
BlockNumber : integer;
BlockRow, BlockColumn : integer;
IsSolved : boolean;
NumberOfModifications : integer;
ModificationReasons : array{1..MAXMODS} of string;
end;
var
OrigPuzzle : array{1..9} of string;
GridInfo : array{1..9, 1..9} of cell_characteristics;
ch : char;
i,j : integer;
Currentpos_x,Currentpos_y : integer;
cursorxpos, cursorypos: integer;
AutoMovement : BOOLEAN;
TotalCellsSolved : integer;
PassesSinceLastSolution : integer;
Unsolveable : BOOLEAN;
{$R *.res}
procedure drawline_h(xcoord:integer; ycoord:integer; linelength:integer; thischar:char);
(* Draw a horizontal line made up of 'thischar') *)
var
i : integer;
begin
if thischar = '0' then
thischar := '*';
gotoxy(xcoord,ycoord);
for i:=1 to linelength do
write(thischar);
end; (* procedure drawline_h *)
procedure drawline_v(xcoord:integer;
ycoord:integer;
linelength:integer;
thischar:char);
(* Draw a vertical line made up of 'thischar') *)
var
i : integer;
begin
if thischar = '0' then
thischar := '*';
for i:=1 to linelength do
begin
gotoxy(xcoord,ycoord);
write(thischar);
ycoord:=ycoord+1;
end;
end; (* procedure drawline_v); *)
procedure DisplayCurrentCoordinates;
begin
gotoxy(3,24);
write('Cell Info');
gotoxy(3,25);
write(' ');
gotoxy(3,25);
write('#', GridInfo{Currentpos_x}{Currentpos_y}.CellNumber,
' (',Currentpos_x,',',Currentpos_y,')');
gotoxy(62,24);
write('Block Info');
gotoxy(58,25);
write(' ');
gotoxy(58,25);
(* A \"Tower\" is three blocks, vertically.
A \"Swath\" is three blocks, horizontally. I had to call 'em something!
*)
write('#',GridInfo{Currentpos_x}{Currentpos_y}.BlockNumber,
' Tower: ',GridInfo{Currentpos_x}{Currentpos_y}.BlockColumn,
' Swath: ',GridInfo{Currentpos_x}{Currentpos_y}.BlockRow);
end;
procedure DisplayMessage(xpos, ypos : integer; str1: string);
begin
gotoxy(xpos,ypos);
write(str1);
end;
function EliminateCharacter(str1:string; char1:char) : string;
var
strlen : integer;
x : integer;
result1 : string;
begin
result1 := '';
strlen := length(str1);
for x:=1 to strlen do
begin
if str1{x} char1 then
result1 := result1 + str1{x};
end;
EliminateCharacter := result1;
end;
function EliminateCharacters(str1,str2: string) : string;
(* Returns str1 less any of the characters present in str2, regardless of their order *)
var
tmpstr : string;
y, int2: integer;
begin
int2 := length(str2);
for y := 1 to int2 do
begin
str1 := EliminateCharacter(str1, str2{y});
end;
end;
|
|
|
|
|