views:

69

answers:

1

My question is like the one here.

I'm working on a char list list and I need to check that 1-9 are used once in every list, but also once in every position in the list.

My code looks like this:

infix member
fun x member []         = false
  | x member (y::ys)    = x = y orelse x member ys;

fun rscheck xs =
                let
                  val ys = [#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"]
                in
                  ys member xs
                end;

but this only checks if 1-9 are members of the lists, not if they're on the same position in different lists.

I had the idea to use this function:

fun poslist xs n = map (fn x => List.nth (x , n)) xs;

(the function poslist is supposed to return whatever is in position n of the list xs, so I can isolate the individual lists in the char list list), but since poslist returns a char list rscheck can't work with it as it needs a char list list.

1) Can I improve poslist?

2) How do I fix rscheck?

Edit

infix member
fun x member []         = false
  | x member (y::ys)    = x = y orelse x member ys;

fun samelist (x::xs) ys = x member ys andalso samelist xs ys
  | samelist [] _       = true;

fun takelist xs n = map (fn x => List.nth (x , n)) xs;

fun reverse xs     = List.tabulate (9 , fn x => takelist xs x);

fun rscheck xs     =
                    let
                      val s = [#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"]
                    in
                      List.all (fn x => samelist s x) xs
                    end andalso rscheck (reverse xs);
+1  A: 

Your rscheck method just checks whether one of the rows is equal to [#"1",#"2",#"3",#"4",#"5",#"6",#"7",#"8",#"9"]. What it should do is check that all the rows contain the numbers in any order. Once you fix that you can solve the rest of the problem as follows:

The easiest way to check whether a matrix is a valid sudoku solution is to use your rscheck function on it, then transpose it (i.e. switch its rows and columns) and then use your rscheck on the transposed matrix. If it returns true both times, it's a valid sudoku solution.

To transpose the matrix you can either translate this OCaml code to SML, or simply use your poslist function for all indices from 0 to 8.

sepp2k
Since I don't know OCaml translating it might be a little hard. I can use poslist but since it returns a char list and rscheck works with a char list list I'm not entirely sure how to work this
GeorgeWChubby
@George: Right, it returns a `char list`. So if you call it with the indices from 0 to 8, you'll get 9 `char list`s. If you put those in a list, you'll have a `char list list`.
sepp2k
How do I do this? I thought using @ would work, but this just makes a single char list. Do you have any idea how to make a char list list?
GeorgeWChubby
@George: `@` concatenates. To create a list of lists, just do `[list1, list2,...]` or `list1 :: list_of_lists`.
sepp2k
Of course. Brain fart from me. I'm trying to make a function that'll do this for me, like call poslist where n would be 8 and then it'll count down from n to 0 and return a char list list. Is this possible? (I could of course do it manually, but that's not a very smart solution).
GeorgeWChubby
@George: I just noticed that your rscheck function doesn't do what it's supposed to. It just checks whether one of the rows is `1,2,3,4,5,6,7,8,9` (in that order), but it should check whether all rows contain the numbers `1,2,3,4,5,6,7,8,9` in any order.
sepp2k
Hmmm... If I exchange ys member xs with List.exists (fn x => x = s) xs it'll work right?
GeorgeWChubby
@George: No, that's the same thing.
sepp2k
@George: You should use [your listn function](http://stackoverflow.com/questions/3946390/help-sml-troubled/3946845#3946845) with `List.all`. That will work.
sepp2k
Alright, I have no idea how to do that. Help?
GeorgeWChubby
@George: `List.all (fn row => listn ys row) xs`. Or using partial application: `List.all (listn ys) xs`.
sepp2k
So something like this: fun test xs ys = List.all (fn row => listn ys row) xs; ? I can get it to do something if I have xs as the char list list and ys as the char list of 1-9. Problem is that it doesn't do it correctly. Also, I need it to be a char list list -> bool and this is ''a list list - ''a list - bool
GeorgeWChubby
@George: No, like your original `rscheck` function, but with the line `ys member xs` replaced with `List.all (fn row => listn ys row) xs`.
sepp2k
Working :) Now I just need to figure out the position part.
GeorgeWChubby
@George: Take a look at [List.tabulate](http://www.standardml.org/Basis/list.html#SIG:LIST.tabulate:VAL). If you use that with your `poslist` function and 9, you'll get a function that transposes the matrix.
sepp2k
The link you gave me says: tabulate (n, f) - returns a list of length n equal to [f(0), f(1), ..., f(n-1)], created from left to right.In my mind this translates to something like this: fun test xs = List.tabulate (9 , fn x => poslist xs) - but it returns this: val 'a test = fn : 'a list list -> (int -> 'a list) list and what I really want is a char list list so I can check it in rscheck.
GeorgeWChubby
@George: Almost there. `fn x => poslist xs` is wrong because you're creating a function that takes an argument `x` and then ignores it. Either do `fn x => postlist xs x` or just `poslist xs` without `fn`.
sepp2k
Success! Now how do I combine the two functions, letting rscheck check both the original char list list and the one run through my transpose function?
GeorgeWChubby
@George: `rscheck xs andalso rscheck (transpose xs)`
sepp2k
Thanks. I've run into a problem when running it. When it's supposed to return true it just stops doing stuff. Doesn't return anything at all.
GeorgeWChubby
@George: Can you please edit the code you have now into your question? I just ran the code that I thought you have and it works fine.
sepp2k
@sepp Done. The function only stops when it needs to return true, if it's false it's fine.
GeorgeWChubby
@rscheck: You need to split `rscheck` into two functions. I.e. one function that checks whether all rows contain all numbers from 1 to 9 and one function that does `check_the_rows xs andalso check_the_rows (transpose xs)`. The way you did it, it will transpose the matrix and call itself ad infinitum in the case where it should return true (because the recursive call will again cause the matrix to be transposed).
sepp2k
I can see it, now that you write it out. Thanks for your help man.
GeorgeWChubby