Sudoku/REXX: Difference between revisions

Line 2,410:
 
==REXX: Version 2==
'''Translation of''' [[Sudoku#PL/I]]
 
<lang rexx> Parse Arg g.0fid
Select
When g.0fid='?' Then Do
Say 'This program solves any (valid) SUDOKU puzzle'
Say 'Specify the name of the file containing the puzzle as argument'
Exit
End
When g.0fid='' Then
Call exit 'no input specified'
When lines(g.0fid)=0 Then
Call exit 'specified input does not exist'
Otherwise
Nop
End
instr=''
Do While lines(g.0fid)>0
instr=instr||linein(g.0fid)
End
Call lineout g.0fid
digits='123456789'
buffer=translate(instr,digits'000',digits'0.x'||xrange('00'x,'ff'x))
buffer=space(buffer,0)
If length(buffer)<>81 Then
Call exit 'invalid input from file' g.0fid
Call set_geometry
 
posbit.=copies('0',9)
z=posbit.0
d.z=0
 
Do i=1 To 9
posbit.i=overlay('1',posbit.i,i,1)
z=posbit.i
d.z=i
End
 
Do r=1 To 9
Do c=1 To 9
Parse Var buffer d +1 buffer
matrix.r.c=posbit.d
End
End
 
nn=0
Call show_matrix 'input from' g.0fid
res=solve()
If res Then Do
Call dbg 'nn='format(nn,5) 'res='res
Call show_matrix 'solution'
End
Else
Say 'impossible'
Exit
 
solve: Procedure Expose g. matrix. posbit. nn box. boxlr. boxlc.
nn=nn+1
Call dbg 'solve nn='format(nn,5)
do i = 1 to 9
do j = 1 to 9
if matrix.i.j=posbit.0 Then
Leave i
End
End
If i>9 Then Do
do i = 1 to 9
do j = 1 to 9
k = pos('1',matrix.i.j)
Call dbg 'sudoku',
Format(nn,9) Format(i,9) Format(j,9) Format(k,9)
matrix.i.j=posbit.0
result_=neg(or(any_col(i),any_row(j),any_box(i,j)))
If substr(result_,k,1)=0 Then
Return 0
matrix.i.j=posbit.k
End
End
Return 1
End
Else Do
result_=neg(or(any_col(i),any_row(j),any_box(i,j)))
Call dbg 'resulta='result_
k=0;
do Until k=0
Call dbg 'resultb='result_
k=pos('1',result_,k+1)
Call dbg 'k='Format(k,2)Format(i,2)Format(j,2)
if k>0 then Do;
matrix.i.j=posbit.k
Call dbg 'setting matrix('i','j')->'k
res=solve()
Call dbg 'A nn='format(nn,5) 'res='res
if res then
return 1
else Do;
matrix.i.j=posbit.0
Call dbg 'setting matrix('i','j')->'0
End;
end;
end;
return 0
end;
 
set_geometry:
box.=''
Do j=1 To 9 /* build the box bounds. */
rr=(((j*3)%10)+1)*3-2 /* compute row lower bound. */
cc=(((j-1)//3)+1)*3-2 /* compute col lower bound. */
boxr.j=rr
boxc.j=cc
Do r=rr To rr+2 /* build boxes with cell #s. */
Do c=cc To cc+2
box.r.c=j
End
End
End /* j */
rowlb.=10 /* row R, low box number=b. */
collb.=10 /* col R, low box number=b. */
boxlr.=10 /* box B, low row number=r. */
boxlc.=10 /* box B, low col number=c. */
 
Do r=1 To 9
Do c=1 To 9
b=box.r.c /* what box is this R,C in ? */
rowlb.r=min(rowlb.r,b) /* find min box # for row R. */
collb.c=min(collb.c,b) /* find min box # for col C. */
boxlr.b=min(boxlr.b,r) /* find min row # for box B. */
boxlc.b=min(boxlc.b,c) /* find min col # for box B. */
End
End
Return
 
any_col: Procedure Expose matrix.
Parse Arg r
res='000000000'
Do c=1 To 9
p=pos('1',matrix.r.c)
If p>0 Then
res=overlay('1',res,p,1)
End
Return res
 
any_row: Procedure Expose matrix.
Parse Arg c
res='000000000'
Do r=1 To 9
p=pos('1',matrix.r.c)
If p>0 Then
res=overlay('1',res,p,1)
End
Return res
 
any_box: Procedure Expose matrix. box. boxlr. boxlc.
Parse Arg r,c
b=box.r.c
res='000000000'
Do r=boxlr.b For 3
Do c=boxlc.b For 3
p=pos('1',matrix.r.c)
If p>0 Then
res=overlay('1',res,p,1)
End
End
Return res
 
or: Procedure
res='000000000'
Do ia=1 To 3
a=arg(ia)
Do p=1 To 9
If substr(a,p,1)=1 Then
res=overlay('1',res,p,1)
End
End
Return res
 
neg: Procedure
Parse Arg s
res=''
Do p=1 To 9
If substr(s,p,1)=1 Then
res=res'0'
Else
res=res'1'
End
Return res
 
o: Say arg(1)
Return
 
show_matrix:
Call o arg(1)
Do r=1 To 9
ol=''
Do c=1 To 9
m=matrix.r.c
ol=ol||d.m' '
If c//3=0 Then
ol=ol' '
End
Call o ol
If r//3=0 Then
Call o ' '
End
Return
 
dbg:
If debug=1 Then
Say arg(1)
Return
 
exit: Say '*ERROR*' arg(1)</lang>
{{out}}
<pre>input from d:\_sudoku\in\sdk001.in
4 6 0 0 0 1 0 0 0
0 0 2 0 9 6 0 0 0
0 3 0 0 0 0 0 6 8
 
0 0 0 0 0 0 0 3 7
0 0 0 6 0 7 0 0 0
5 1 0 0 0 0 0 0 0
 
8 4 0 0 0 0 0 5 0
0 0 0 7 1 0 9 0 0
0 0 0 3 0 0 0 2 4
 
solution
4 6 5 8 3 1 2 7 9
7 8 2 4 9 6 3 1 5
1 3 9 5 7 2 4 6 8
 
6 9 4 1 2 5 8 3 7
3 2 8 6 4 7 5 9 1
5 1 7 9 8 3 6 4 2
 
8 4 1 2 6 9 7 5 3
2 5 3 7 1 4 9 8 6
9 7 6 3 5 8 1 2 4</pre>
 
==REXX: Version 3==
Anonymous user