Sunday, July 5, 2009

COBOL Sudoku and the Computer Geek's Rosetta Stone

So here's the story.

Every now and then I get a stuck on a Sudoku puzzle, so I wrote a computer program to solve Sudoku puzzles, which lets me know if I had the thing right as far as I had gotten. I wrote it in Java, since I had taken a course in it and had the Java development environment set up.

Some time had elapsed after writing it before I needed to use it again. Lo and behold, the Java environment had updated itself so often and so cleverly that I was unable to guess what the path settings should be. Another triumph of portability!

Too damn aggravating, computers are supposed to be easy to use you know, so I went to a REAL computer (an IBM mainframe) and wrote it in REXX, which supports recursion. To a point. A point somewhere about halfway through a Sudoku puzzle. In the telltale mark of true "it's not 1978 anymore" chickensh*t, the limit of the recursion stack is a little under 256.

Old computer geeks will recognize this instantly as a limit set as an afterthought in a program where the only (usually politically) acceptable modifiable control block had one spare byte. This was probably done in 1978 and the person who decided to do it was probably promoted for it. Noone has changed it since and it must be one jam-packed rat's nest of a control block, because try to find a way to bump up the REXX control stack on line. I dare you.

Everybody is all "Moore's Law" but the tale of how "modern" systems are tied to efficiencies and restraints of the ancient (i.e. my) era would have your knotted and combined locks doing the "quills upon the fretful porpentine" bit in no time.

So I went back to the mother tongue, COBOL. I had always wanted to write a recursive routine in COBOL, but never had the real motivation like one of those sadistically hard Sudokus they put in the Friday paper. It works like a top. Purists will feint because it uses (maybe 8) GO TO's, but such people will also pretend "C" had real thoughts behind its syntax other than tiny CPUs and saving typing on a DEC writer.

I google'd it and discovered that Bill Price had also written a COBOL program to do this. Bill was interested in emulating algorithms a person would go through so his program is a lot more complex than mine. I just had a Sudoku grid that was pissing me off.

So until I get the password set for my ISP webspace that I never use, anyone interested in a Rosetta Stone version of the Sudoku program in COBOL, Java, and (unusable unless you can up that limit) REXX can request one in the reply.

1 comment:

AlbertEShort said...

Here's the REXX

/*************/

thegrid. = ''
thegrid.itctr = 0
theinits. = ''


'execio * diskr sudogrid 0 (stem IARRAY. '

do j = 1 to 9
do k = 1 to 9
parse var iarray.j tok iarray.j
thegrid.j.k = tok
if tok ¬= 0 then theinits.j.k = 'Y'
end
end

call spit_grid

if next_cell(1,0) then say 'grid not solvable '
else do
say ' grid solved after ' thegrid.itctr ' iterations '
call spit_grid
end

exit


spit_grid: procedure expose thegrid.

do j = 1 to 9
orec = ''
do k = 1 to 9
orec = orec thegrid.j.k
end
say orec
end
return


next_cell: procedure expose thegrid. theinits.
arg coord_x , coord_y .

thegrid.itctr = thegrid.itctr + 1
if thegrid.itctr // 4000 = 0 then call spit_grid

if coord_x = 9 & coord_y = 9 then return(1)

if coord_y = 9 then do
coord_x = coord_x + 1
coord_y = 1
end
else coord_y = coord_y + 1

if theinits.coord_x.coord_y = 'Y' then ,
return(next_cell(coord_x,coord_y))

do j = 1 to 9
thegrid.coord_x.coord_y = j
if evaluate_cell(coord_x , coord_y) then do
if next_cell(coord_x,coord_y) then return(1)
end
end

thegrid.coord_x.coord_y = 0
return(0)


evaluate_cell: procedure expose thegrid.
arg coord_x , coord_y .

tval = thegrid.coord_x.coord_y
do xx = 1 to 9
if xx = coord_x then iterate
if tval = thegrid.xx.coord_y then return(0)
end
do yy = 1 to 9
if yy = coord_y then iterate
if tval = thegrid.coord_x.yy then return(0)
end

gridx = ((coord_x - 1) % 3) * 3 + 1
gridy = ((coord_y - 1) % 3) * 3 + 1
do xx = gridx to (gridx + 2)
do yy = gridy to (gridy + 2)
if xx = coord_x & yy = coord_y then iterate
if tval = thegrid.xx.yy then return(0)
end
end
return(1)