« POPE IV Home | Email msg. | Reply to msg. | Post new | Board info. Previous | Home | Next

Re: Lazarus (Pascal) - Code part 2 of 5 

By: Decomposed in POPE IV | Recommend this post (1)
Mon, 20 Nov 17 10:49 PM | 65 view(s)
Boardmark this board | POPES NEW and Improved Real Board
Msg. 38937 of 47202
(This msg. is a reply to 38936 by Decomposed)

Jump:
Jump to board:
Jump to msg. #



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 *)

 




Avatar

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;

 


« POPE IV Home | Email msg. | Reply to msg. | Post new | Board info. Previous | Home | Next