Advertisement
cryptochaos

Untitled

Jul 24th, 2015
628
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Awk 11.80 KB | None | 0 0
  1. #!/usr/bin/awk -f
  2. #
  3. # GLOBAL VARIABLES:
  4. #   grid        - Game grid
  5. #   row     - Horizontal slice through the grid
  6. #   col     - Vertical slice through the grid
  7. #   sector      - solved numbers per sector
  8. #   setorMap    - map of sector for each cell
  9. #   solutions   - grid of all possible solutions per unsolved cell
  10. #   solutionsCnt    - count of possible solutions for each unsolved number per sector
  11. #
  12.  
  13. BEGIN {
  14.     for (i=1; i <= 9; i++ ) {
  15.         for (j=1; j <= 9; j++ ) {
  16.             grid[i,j]=0
  17.             sectorMap[i,j]=toSector(i,j)
  18.         }
  19.     }
  20.  
  21.  
  22.     "tput smso" | getline SMSO
  23.     "tput bold" | getline BOLD
  24.     "tput rmso" | getline RMSO
  25.     "tput clear"    | getline CLEAR
  26.     "tput cup 0 0"  | getline HOME
  27.     "tput cup 20 0" | getline LINE20
  28.  
  29.     PROMPT = ">>"
  30.     printf "%s ", PROMPT
  31. }
  32.  
  33. $1 == "help" {
  34.     print "help, load, loadFile, step, dumpsolutions, dumpSector, dumpSectorMap, dump"
  35. }
  36.  
  37. $1 == "list" {
  38.     LIST="ls puzzle.*"
  39.     while ( LIST | getline listing >0 ) {
  40.         print listing
  41.     }
  42.     close(LIST)
  43. }
  44.  
  45. ####################################################################
  46. #
  47. #   load puzzle from a file
  48. #
  49. ####################################################################
  50. $1 == "loadFile" {
  51.     fileName = $2
  52.     print "loading " fileName
  53.  
  54.     clearSector()
  55.     delete grid
  56.     delete row
  57.     delete col
  58.  
  59.     r=0;
  60.     while ( (getline < fileName) > 0 ) {
  61.         r++
  62.         for (c=1; c<=NF; c++)
  63.         {
  64.             if ( $c != ".")
  65.                 load(r, c, $c)
  66.         }
  67.     }
  68.  
  69.     close(fileName)
  70. }
  71.  
  72. ####################################################################
  73. #
  74. #   load puzzle from command line
  75. #
  76. ####################################################################
  77. $1 == "load" {
  78.     fileName=""
  79.     for (i=2; i<=NF; i++)
  80.     {
  81.         split($i,fields,",")
  82.         load(fields[1], fields[2], fields[3])
  83.     }
  84. }
  85.  
  86. ####################################################################
  87. #
  88. #   step through automated solution of the puzzle
  89. #
  90. ####################################################################
  91. $1 == "step" {
  92.     if (solveStep()==0)
  93.         print "no solution"
  94.    
  95. }
  96.  
  97. ####################################################################
  98. #
  99. #   automatically solve the entire puzzle
  100. #
  101. ####################################################################
  102. $1 == "solve" {
  103.    
  104.     printf "%s", CLEAR
  105.  
  106.     do {
  107.         if ( $2 != "" ) {
  108.             system("sleep " $2)
  109.         }
  110.         printf "%s", HOME
  111.  
  112.     } while (solveStep() != 0 )
  113.  
  114.     dump()
  115.     print "Solution Stopped"
  116. }
  117.  
  118. ####################################################################
  119. #
  120. #   validate the currently solved puzzle against a solution
  121. #   in a file
  122. #
  123. ####################################################################
  124. $1 == "check" {
  125.  
  126.     fileName=$2
  127.     print "checking solution against " fileName
  128.  
  129.     r=0
  130.  
  131.     while ( (getline < fileName) > 0 ) {
  132.         r++
  133.  
  134.         for (c=1; c<=NF; c++)
  135.         {
  136.             # print "grid["r","c"]("grid[r,c]")=" $c  ## DEBUG
  137.             if (grid[r,c] != $c) {
  138.                 dump(r,c)
  139.                 print "Error @ cell " r","c
  140.                 close(fileName)
  141.                 next
  142.             }
  143.         }
  144.     }
  145.  
  146.     print "Congradulations, your solution is correct!"
  147.  
  148.     close(fileName)
  149. }
  150.  
  151. ####################################################################
  152. #
  153. #   save the current puzzle in a file
  154. #
  155. ####################################################################
  156. $1 == "save"        {
  157.     for (r=1; r<=9; r++) {
  158.         for (c=1; c<=9; c++) {
  159.             v = grid[r,c]
  160.             if ( v <=0 )
  161.                 v="."
  162.             printf "%s ", v  > $2
  163.         }
  164.         print "" > $2
  165.     }
  166.     close($2)
  167. }
  168.  
  169. $1 == "dumpSolution"    { dumpSolutions() }     # dump the list of solutions to output
  170. $1 == "dumpSectorMap"   { dumpSectorMap() }     # dump the sector map to output
  171. $1 == "dumpSector"  { dumpSectors() }       # dump all solved numbers per sector to output
  172. $1 == "dump"        { C=$3; dump($2, $3) }      # dump the puzzle grid to output
  173. $1 == "quit"        { exit 0 }          # exit the game
  174.             { printf "%s ", PROMPT }
  175.  
  176. ####################################################################
  177. #
  178. #   load a value into a (r)ow and (c)olumn of the puzzle grid
  179. #
  180. ####################################################################
  181. function load( r, c, value) {
  182.     grid[r,c]=value
  183.     solutions[r,c]="C"
  184.     row[r,value]=1
  185.     col[c,value]=1
  186.     addToSector(sectorMap[r, c],value)
  187. }
  188.  
  189. ####################################################################
  190. #
  191. #   attempt to find the first solvable cell in the grid.
  192. #   print the grid with the solved cell highlighted.
  193. #
  194. ####################################################################
  195. function solveStep() {
  196.     plotSolutions()
  197.  
  198.     for ( r=1; r<=9; r++ ) {
  199.         for ( c=1; c<=9; c++ ) {
  200.             for ( i=1; i <= 9; i++ ) {
  201.                 if(solutions[r,c] != "C" && solutions[r,c] ~ i && solutions[r,c] !~ /,/) {
  202.                     load(r,c,i)
  203.                     dump(r,c)
  204.                     print "                                   "
  205.                     return 1
  206.                 }
  207.        
  208.                 if ( solutions[r,c]!="C" && solutions[r,c] ~ i && solutionsCnt[sectorMap[r,c],i]==1)
  209.                 {
  210.                     load(r,c,i)
  211.                     dump(r,c)
  212.                     print "                                   "
  213.                     return 1
  214.                 }
  215.             }
  216.         }
  217.     }
  218.    
  219.         if ( !gridSolved() ) {
  220.         plotSolutions()
  221.         plotTwins()
  222.         for ( r=1; r<=9; r++ ) {
  223.             for ( c=1; c<=9; c++ ) {
  224.                 for ( i=1; i <= 9; i++ ) {
  225.                     if(solutions[r,c] != "C" && solutions[r,c] ~ i && solutions[r,c] !~ /,/) {
  226.                         load(r,c,i)
  227.                         dump(r,c)
  228.                         print "Solved using twins..."
  229.                         return 1
  230.                     }
  231.            
  232.                     if ( solutions[r,c]!="C" && solutions[r,c] ~ i && solutionsCnt[sectorMap[r,c],i]==1)
  233.                     {
  234.                         load(r,c,i)
  235.                         dump(r,c)
  236.                         print "Solved using twins..."
  237.                         return 1
  238.                     }
  239.                 }
  240.             }
  241.         }
  242.     }
  243.  
  244.     return 0
  245. }
  246.  
  247. ####################################################################
  248. #
  249. #   plot all possible solutions for all unsolved cells
  250. #
  251. ####################################################################
  252. function plotSolutions() {
  253.     delete solutions
  254.     delete solutionsCnt
  255.  
  256.     ############################################################
  257.     #
  258.     #   Mark solved cells in the solution space
  259.     #
  260.     ############################################################
  261.     for ( r=1; r<=9; r++ ) {
  262.         for (c=1; c<=9; c++) {
  263.             if ( grid[r,c] != 0 ) {
  264.                 solutions[r,c]="C"
  265.             }
  266.         }
  267.     }
  268.  
  269.  
  270.     ############################################################
  271.     #
  272.     #   plot all possible solutions for the current
  273.     #   puzzle grid
  274.     #
  275.     ############################################################
  276.     for (i=1; i<=9; i++ ) {
  277.         for ( r=1; r<=9; r++ ) {
  278.             for ( c=1; c<=9; c++ ) {
  279.                 if ( solutions[r,c] != "C" ) {
  280.                     if ( row[r,i] != 1 && col[c,i] != 1 && sector[sectorMap[r,c]] !~ i) {
  281.                         if ( solutions[r,c] == 0 )
  282.                             solutions[r,c]=i
  283.                         else
  284.                             solutions[r,c]=solutions[r,c]","i
  285.  
  286.                         solutionsCnt[sectorMap[r,c],i]= solutionsCnt[sectorMap[r,c],i]+1
  287.                     }
  288.                 }
  289.             }
  290.         }
  291.     }
  292. }
  293.  
  294. function plotTwins() {
  295.     ############################################################
  296.     #
  297.     #   look for "twins" in the solutions space
  298.     #
  299.     ############################################################
  300.  
  301.     for ( r=1; r<=9; r++) {
  302.         for ( c=1; c<=9; c++ ) {
  303.             if (split(solutions[r,c],a,",") == 2 ) {
  304.                 if (matchTwinCol(r,c,a)) {
  305.                     extractTwinValuesFromCol(c,a)
  306.                 }
  307.  
  308.                 if (matchTwinRow(r,c,a)) {
  309.                     extractTwinValuesFromRow(r,a)
  310.                 }
  311.             }
  312.         }
  313.     }
  314. }
  315.  
  316. function matchTwinCol(R,C,A){
  317.     twinCount=0
  318.     ############################################################
  319.     #
  320.     #   look for "twins" across column in the solutions space
  321.     #
  322.     ############################################################
  323.     for ( ; C<=9; C++ ) {
  324.         if (split(solutions[R,C],b,",") == 2 ) {
  325.             if( isTwin(A,b) ) {
  326.                 twinCount++
  327.             }
  328.         }
  329.     }
  330.  
  331.     if ( twinCount == 1 )
  332.         return 1
  333.     else
  334.         return 0 #  false
  335. }
  336.  
  337. function matchTwinRow(R,C,A){
  338.     twinCount=0
  339.    
  340.     ############################################################
  341.     #
  342.     #   look for "twins" across Row in the solutions space
  343.     #
  344.     ############################################################
  345.     for ( ; R<=9; R++ ) {
  346.         if (split(solutions[R,C],b,",") == 2 ) {
  347.             if( isTwin(A,b) ) {
  348.                 twinCount++
  349.             }
  350.         }
  351.     }
  352.  
  353.     if ( twinCount == 1 )
  354.         return 1
  355.     else
  356.         return 0 #  false
  357. }
  358.  
  359. function extractTwinValuesFromCol(C, A) {
  360.     for ( R=1; R<=9; R++ ) {
  361.         if ( solutions[R,C] != "C" ) {
  362.             split(solutions[R,C],B,",")
  363.  
  364.             if ( length(B) > 1 && !isTwin(A,B)) {
  365.                 solutions[R,C]=""
  366.  
  367.                 for ( i=1; i<= length(B); i++ ) {
  368.                     if ( B[i] != A[1] && B[i] != A[2] ) {
  369.                         if ( solutions[R,C]=="" ) {
  370.                             solutions[R,C]=B[i]
  371.                         }else{
  372.                             solutions[R,C]=solutions[R,C]","B[i]
  373.                         }
  374.                     }
  375.                 }
  376.             }
  377.         }
  378.     }
  379. }
  380.  
  381. function extractTwinValuesFromRow(R, A) {
  382.     for ( C=1; C<=9; C++ ) {
  383.         if ( solutions[R,C] != "C" ) {
  384.             split(solutions[R,C],B,",")
  385.  
  386.             if ( length(B) > 1 && !isTwin(A,B)) {
  387.                 solutions[R,C]=""
  388.  
  389.                 for ( i=1; i<= length(B); i++ ) {
  390.                     if ( B[i] != A[1] && B[i] != A[2] ) {
  391.                         if ( solutions[R,C]=="" ) {
  392.                             solutions[R,C]=B[i]
  393.                         }else{
  394.                             solutions[R,C]=solutions[R,C]","B[i]
  395.                         }
  396.                     }
  397.                 }
  398.             }
  399.         }
  400.     }
  401. }
  402.  
  403. function isTwin(A, B) {
  404.     if (  length(A) == 2 && length(B) == 2 && A[1] == B[1] && A[2] == B[2] ) {
  405.         return 1
  406.     }
  407.  
  408.     return 0
  409. }
  410.  
  411. function gridSolved() {
  412.     for ( r=1 ; r<=9; r++ ) {
  413.         for ( c=1; c<=9; c++ ) {
  414.             if ( solutions[r,c]!="C" )
  415.                 return 0
  416.         }
  417.     }
  418.     return 1
  419. }
  420.  
  421. ####################################################################
  422. #
  423. #   dump the list of all currently plotted solutions for
  424. #   unsolved cells
  425. #
  426. ####################################################################
  427. function dumpSolutions() {
  428.     for ( r=1; r<=9; r++ ) {
  429.         for ( c=1; c<=9; c++ ) {
  430.             printf "solutions[%d,%d]=%s\n", r, c, solutions[r,c]
  431.         }
  432.     }
  433. }
  434.  
  435. ####################################################################
  436. #
  437. #   dump all solved numbers per sector
  438. #
  439. ####################################################################
  440. function dumpSectors() {
  441.     print "SECTORS {"
  442.     for ( i=1; i <=9; i++ ) {
  443.         printf "    Sector[%d]: %s\n", i, sector[i]
  444.     }
  445.     print "}"
  446. }
  447.  
  448. ####################################################################
  449. #
  450. #   map a cell to a sector
  451. #
  452. ####################################################################
  453. function toSector(r, c) {
  454.     if ( r <= 3 && c <=3 ) {
  455.         return 1
  456.     } else if ( r <= 3 && c <=6 ) {
  457.         return 2
  458.     } else if ( r <= 3 && c <=9 ) {
  459.         return 3
  460.     } else if ( r <= 6 && c <=3 ) {
  461.         return 4
  462.     } else if ( r <= 6 && c <=6 ) {
  463.         return 5
  464.     } else if ( r <= 6 && c <=9 ) {
  465.         return 6
  466.     } else if ( r <= 9 && c <=3 ) {
  467.         return 7
  468.     } else if ( r <= 9 && c <=6 ) {
  469.         return 8
  470.     } else if ( r <= 9 && c <=9 ) {
  471.         return 9
  472.     }
  473. }
  474.  
  475. ####################################################################
  476. #
  477. #   dump the puzzle grid to output, highlight the cell
  478. #   designated by the (r)ow and (c)olumn arguments
  479. #
  480. ####################################################################
  481. function dump(r, c) {
  482.     print fileName
  483.     printf "===================\n"
  484.     for (i=1; i<=9; i++ ) {
  485.         printf "|"
  486.         for ( j=1; j<=9; j++) {
  487.  
  488.             if( i==r && j==c) {
  489.                 SM=SMSO
  490.                 RM=RMSO
  491.             }else{
  492.                 SM=""
  493.                 RM=""
  494.             }
  495.  
  496.             if (grid[i,j]!=0) {
  497.                 printf "%s%d%s",SM,grid[i,j],RM
  498.             }else{
  499.                 printf " "
  500.             }
  501.  
  502.             if ( j%3 == 0 ) {
  503.                 printf "|"
  504.             }else{
  505.                 printf ":"
  506.             }
  507.         }
  508.         if ( i%3 == 0 ) {
  509.             printf "\n|=====|=====|=====|\n"
  510.         }else{
  511.             printf "\n|-----|-----|-----|\n"
  512.         }
  513.     }
  514. }
  515.  
  516. ####################################################################
  517. #
  518. #   dump the pregenerated sector map to output
  519. #
  520. ####################################################################
  521. function dumpSectorMap() {
  522.     printf "SECTOR MAP {\n  ===================\n   "
  523.     for (i=1; i<=9; i++ ) {
  524.         printf "|"
  525.         for ( j=1; j<=9; j++) {
  526.  
  527.             printf "%d", sectorMap[i,j]
  528.  
  529.             if ( j%3 == 0 ) {
  530.                 printf "|"
  531.             }else{
  532.                 printf ":"
  533.             }
  534.         }
  535.         if ( i%3 == 0 ) {
  536.             printf "\n  |=====|=====|=====|\n   "
  537.         }else{
  538.             printf "\n  |-----|-----|-----|\n   "
  539.         }
  540.     }
  541.     printf "\n}\n"
  542. }
  543.  
  544. ####################################################################
  545. #
  546. #   clear sector solutions
  547. #
  548. ####################################################################
  549. function clearSector() {
  550.     delete sector
  551.     delete sectorCnt
  552. }
  553.  
  554. ####################################################################
  555. #
  556. #   add a solution (v)alue to a (s)ector
  557. #
  558. ####################################################################
  559. function addToSector(s,v) {
  560.     if ( sector[s]==0 ) {
  561.         sector[s]=v
  562.     } else{
  563.         sector[s]=sector[s]","v
  564.     }
  565.     sectorCnt[s,v]=sectorCnt[s,v]+1
  566. }
  567.  
  568. ####################################################################
  569. #
  570. #   Program Exit
  571. #
  572. ####################################################################
  573. END { print ">> GOODBYE!" }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement