Sudoku Madness
I just read your Sudoku message on the J Forum. By a strange coincidence, one of my students chose Sudoku for his J assignment. He was having a lot of trouble, so I wrote the script below to give him a start. He didnt get all that far with writing some player support but Ill be working with him after I come back from overseas.
Because Im leaving early Friday for a week of meetings in the US I havent got time to do much more than send you the code. For it is that Ive commented it fairly fully for the students sake, but against it is that I left the assignments global to make it easy for him to test it.
Perhaps its interest is that Ive generalised it way beyond the 3×3×3, which is, I think, a bit of a straight jacket. Also, you should be able to jazz up the code because Im not an expert by any means, and the code is just one evenings work.
NB.
NB. General Sudoku Arrays
NB.
NB. Generate an array of numbers, for example, shape 2 3 4 5
NB. which is thought of as a 2x3 array of 4x5 rectangles,
NB. or a 2x4 by 3x5 array of numbers, where
NB. (a) no number is repeated within
NB. 0. any 4x5 subarray,
NB. 1. any 2x4 subarray, and
NB. 2. any 3x5 subarray,
NB. (b) the numbers are whole
NB. from 1 to the maximum of 4x5, 2x4, and 3x5.
NB.
NB. Final Functions : Dsply Fnl (try "Dsply Fnl 2 2 3 3" or "Dsply Fnl 3")
NB. Some Utility Functions
Dsply =: <"2 NB. Dsply y : boxes the 4x5 subarrays
PnDy =: ,"2@(0 1&|:)@:(,"2)@(0 2&|:)
NB. PnDy y : converts to 8x10 array
InDy =: Dsply@(]$({.~ -@(*/)))~ >@(1&{)
NB. x InDy y : constructs & displays intermediate array
Vldt =: 2&>.@(4&$)@,@:>.
NB. Forces 4 integers greater than 1
Mxmm =: >./@(*/)@:((2 3$2 0 1 3 2 3)&{)
NB. Calculates the maximum of 4x5, 2x4, and 3x5
NB. Functions to set up running list of boxes
NB.
NB. 0. The next index (starts as <: of 2x3x4x5)
NB. 1. The overall array as a list (starts as an empty list)
NB. 2. 2x3 table of lists of numbers used so far for each 4x5 subarray
NB. 3. 3x5 ditto for each 2x4 subarray
NB. 4. 2x4 ditto for each 3x5 subarray
SSAry =: ($&a:)@:{ NB. sets up the subarray of empty boxes
Strt =: <:@(*/) ; (i.0)"_ ; 0 1&SSAry ; 1 3&SSAry ; <@(0 2&SSAry)
NB. Functions to calculate the next number
NB.
NB. Require shape as left argument, running array as right
Ndx =: #: >@{. NB. 4 element index to next number
UsdFS =: <@(2&{.)@Ndx >@{ >@(2&{)@]
NB. x UsdFS y : gets 4x5 used so far
UsdSS =: <@(1 3&{)@Ndx >@{ >@(3&{)@]
NB. x UsdSS y : gets 2x4 used so far
UsdTS =: <@(0 2&{)@Ndx >@{ >@(4&{)@]
NB. x UsdTS y : gets 3x5 used so far
UsdS =: UsdFS ~.@, UsdSS , UsdTS
NB. x UsdTS y : gets all numbers used so far
NxtNr =: >:@i.@Mxmm@[ (0:`({~?@#)@.(*@#))@:-. UsdS
NB. x NxtNr y : selects from numbers not yet used
AdNN =: (NxtNr <@, >@(1&{)@]) 1} ]
NB. x AdNN y : puts the next number to list front
NB. Functions to put away the next number in the three boxes
NB.
NB. Further updates the running array
NwN =: {.@>@(1&{)@] NB. picks out the new number
NwFS =: (UsdFS <@, NwN)`(<@(2&{.)@Ndx)`(>@(2&{)@])}
NB. x NwFs y : updates the 4x5 subarray
NwSS =: (UsdSS <@, NwN)`(<@(1 3&{)@Ndx)`(>@(3&{)@])}
NB. x NwFs y : updates the 2x4 subarray
NwTS =: (UsdTS <@, NwN)`(<@(0 2&{)@Ndx)`(>@(4&{)@])}
NB. x NwFs y : updates the 3x5 subarray
UdtRA =: <:@>@{.@] ; 1&{@] , NwFS ; NwSS ; <@NwTS
NB. x UdtRA y : updates the running array
NB. Functions to do all, and to clean up
NB.
NB. a =. Fnl y : to get the array
NB. Dsply a : to see the boxed structure
NB. PnDy a : to see the 2D structure
Good =: -.@(0&e.)@>@(1&{)
Once =: ([ UdtRA AdNN)^:(Good@:])^:(*/@:[)
NB. (Once Strt) y : one attempt at the whole
Try =: ('No'"_`InDy@.(Good@]) (Once Strt))@Vldt
NB. Try y : works for once
Cln =: Strt@[^:(-.@Good@:])
NB. (([ Cln Once) Strt) y :
Fnsh =: [([ Once Strt@[)`]@.(Good@])^:_ (Once Strt)
NB. Fnsh y : repeated attempts at the whole
Fnl =: ($ >@(1&{)@Fnsh)@Vldt
NB. Fnl y : the structure extracted
NB. Dsply Fnl y : to see the structure

