Tuesday, July 21, 2020

Mind Expanding with a Cup of Java [Personal Growth Matters]

For me, COVID-19 Lockdown hasn't been a big change, since retirement means I have lots of free time anyway. I am very fortunate to live in a retirement village villa. I am sitting at the dining room table looking out over the golf course across our back fence - a large water trap with lots of bird life, the rushes, the fairway and the trees - ah, the serenity - too bad about the hacker golfers.

I regularly work on a book of puzzles, cross-words (straight and cryptic), 'code breakers', and of course Sudoku. Now I've never really been a Sudoku fan, preferring word puzzles. But the logic of solving a Sudoku puzzle intrigued me. My Computer Science post-graduate thesis back in the 70's involved programming a deduction 'engine' processing predicate calculus statements, so the method of solving Soduko was right up my alley.

I first learnt to program computers back in 1966, and have learned (and  forgotten) dozens of computer languages since. The later half of my career moved beyond mundane programming, into analysis, systems architecture, specification, quality assurance and management. But the mental stimulus of solving a problem in code, has never left me.

So as a personal growth project, I decided to teach myself a modern computer language, Java, and the problem I chose to was solving Sudoku puzzles.
A very hard puzzle.

Now the simplest program solution is to recursively try the digits 1..9 combinatorially in every empty cell. But I wanted to tackle the intelligent solution of how humans go about solving such puzzles.

<WARNING "descriptions of complex programming logic - skip if desired">
From the digits that exist in each row/column/sub-matrix, build lists of candidate digits that could appear in the empty cells of each row/column/sub-matrix. Then examine every empty cells' three lists of candidate digits that intersect at that cell and perform a logical AND of the three lists to get the candidate digits that satisfy all three row/column/sub-matrix constraints. If you are left with a single candidate in any of the row/column/sub-matrix, then that digit is the solution for that cell. After all empty cells have been processed, if there are still some cells that have not had a solution digit inserted, loop back and compute new lists of candidates.

I have found that puzzles of complexity up to 4 stars are soluble by the above method. A handful of ***** complexity puzzles still require a brute force method to solve the remaining empty cells after the above has finished. By using the lists of candidate digits at each empty cell, typically 2 or 3 digits, instead of trying all 1..9 digits, the size of the combination is much reduced. A classic 'block' that I have noticed that puzzle creators use, is to have a row/column/sub-matrix element with just 2 empty cells with the same 2 candidate digits, so there are only 2 combinations to test, 'x,y' and 'y,x'.
</WARNING>
Solution of above very hard puzzle.

By parameterizing the size of the puzzle, a simple 4x4 puzzle was used in initial debugging. A logical extension of the problem, would be to have a 25x25 puzzle that uses the 25 letters "A..Y" instead of the digits 1..9. Perhaps I could call it Nozeku! With a puzzle board that size, I suspect it would be too difficult to create problems by hand. Perhaps I will have to write a program to generate problems of Nozeku.

Another option I considered, is to use a phone camera to capture a picture of a puzzle and perform optical character recognition to input the puzzle into the program. At the press of a button, in a fraction of a second, the solution is displayed. But that program extension lacks intellectual stimulus for me.

So after that exercise, I feel my brain has 'grown' by a percentage point or two. Mind you, I have only just scratched the surface of the Object Oriented power of Java. I might have to look for another problem to solve.

Is programming sexy? Some programmers have reported experiencing algorisms! (that euphoric, Eureka, aha moment when you finally see an elegant solution to a difficult problem you have been mulling over for days or weeks). Do writers have such experiences when a beautiful plot inspiration blasts through a writer's block?

But in the mean time, I might go back to my landscape painting to relax for a while.

Addendum

Having programmed my 'obvious' strategy, I searched the internet literature for Sudoku solution strategies. Andrew Stuart's 'https://www.sudokuwiki.org/sudoku.htm' is probably the most comprehensive, listing 38 strategies. My program implements the first two basic strategies, 'Naked singles' and 'Hidden singles'.

Personal Growth Matters

3 comments:

  1. Wow Sir Thomas - you have totally impressed me - I think programming is very sexy - well I was a programmer for many years lol
    Well done you I am sure you have helped your brain cells multiply. I found this post thoroughly interesting
    May x

    ReplyDelete
    Replies
    1. Thanks May.
      I think as sexy as it got for youngsters back in the day, was a very early BASIC that PEEK and POKE commands.
      But just for you to stir up some old algorismic juices, here is a snippet:-
      // Create bit-masks for each empty cell, 1 bit for every candidate digit.
      int [][] possibleDigits = new int [n][n];
      int [][] possibleDigitsCount = new int [n][n];
      emptyCellCount = 0;
      for (int r = 0; r < n; r++){
      for (int c = 0; c < n; c++){
      if (board[r][c] == 0) { // Process empty cell at r,c
      emptyCellCount++;
      int mr, mc;
      mr = r / sqrtN; mc = c / sqrtN;
      // Complement DigitsMasks to get Mask of valid PossibleDigits
      // Use bitwise AND (&) to find PossibleDigits valid in all 3 'dimensions'
      possibleDigits[r][c] = 0x1FF &
      ~submatDigitsMask[mr][mc] &
      ~rowDigitsMask[r] &
      ~colDigitsMask[c];
      // Count the number of valid Possible digits in cell [r][c]
      possibleDigitsCount[r][c] = 0;
      for (int msk = 0; msk < n; msk++) {
      if ((possibleDigits[r][c] & digitsMask[msk]) != 0) {
      possibleDigitsCount[r][c]++; // # candidates for cell
      rowCandidatesCount[r][msk]++; // # occurrences of digit in row
      colCandidatesCount[c][msk]++; // # occurrences of digit in col
      submatCandidatesCount[mr][mc][msk]++;// # occurrences of digit in submatrix
      }
      }
      }
      }
      }

      Delete
  2. Goodness a few memories jogged there with things like - }
    I did learn basic although not early basic - iu sed programming languages that i suppose were a little more like english - Cobol and RPG - although I did learn a bit of "C" too

    ReplyDelete