Skip to content

Commit 4f1d070

Browse files
ocaml: valid sudoku
1 parent 4119bf9 commit 4f1d070

File tree

1 file changed

+178
-0
lines changed
  • ocaml/valid_sudoku_dec_08_2023

1 file changed

+178
-0
lines changed
+178
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
(*
2+
Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
3+
4+
Each row must contain the digits 1-9 without repetition.
5+
Each column must contain the digits 1-9 without repetition.
6+
Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.
7+
Note:
8+
9+
A Sudoku board (partially filled) could be valid but is not necessarily solvable.
10+
Only the filled cells need to be validated according to the mentioned rules.
11+
12+
Example 1:
13+
14+
Input: board =
15+
[["5","3",".",".","7",".",".",".","."]
16+
,["6",".",".","1","9","5",".",".","."]
17+
,[".","9","8",".",".",".",".","6","."]
18+
,["8",".",".",".","6",".",".",".","3"]
19+
,["4",".",".","8",".","3",".",".","1"]
20+
,["7",".",".",".","2",".",".",".","6"]
21+
,[".","6",".",".",".",".","2","8","."]
22+
,[".",".",".","4","1","9",".",".","5"]
23+
,[".",".",".",".","8",".",".","7","9"]]
24+
Output: true
25+
Example 2:
26+
27+
Input: board =
28+
[["8","3",".",".","7",".",".",".","."]
29+
,["6",".",".","1","9","5",".",".","."]
30+
,[".","9","8",".",".",".",".","6","."]
31+
,["8",".",".",".","6",".",".",".","3"]
32+
,["4",".",".","8",".","3",".",".","1"]
33+
,["7",".",".",".","2",".",".",".","6"]
34+
,[".","6",".",".",".",".","2","8","."]
35+
,[".",".",".","4","1","9",".",".","5"]
36+
,[".",".",".",".","8",".",".","7","9"]]
37+
Output: false
38+
Explanation: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
39+
40+
Constraints:
41+
42+
board.length == 9
43+
board[i].length == 9
44+
board[i][j] is a digit 1-9 or '.'.
45+
*)
46+
47+
let char_to_int (c : char) : int =
48+
match c with
49+
| '1' -> 1
50+
| '2' -> 2
51+
| '3' -> 3
52+
| '4' -> 4
53+
| '5' -> 5
54+
| '6' -> 6
55+
| '7' -> 7
56+
| '8' -> 8
57+
| '9' -> 9
58+
| _ -> assert false
59+
60+
(*
61+
time O(n)
62+
space O(1)
63+
*)
64+
let is_valid_sudoku (board : char array array) : bool =
65+
assert (Array.length board = Array.length board.(0));
66+
67+
let board_size = Array.length board in
68+
69+
let valid = ref true in
70+
71+
let row_or_column = ref 0 in
72+
73+
(* Check for duplicated numbers in 3x3 grid *)
74+
let grid_size = 3 in
75+
76+
let grid_row_starts_at = ref 0 in
77+
78+
let grid_column_starts_at = ref 0 in
79+
80+
(* time O(n) *)
81+
while !valid && !grid_row_starts_at <= 6 do
82+
while !valid && !grid_column_starts_at <= 6 do
83+
let count = Array.make 9 0 in
84+
85+
for i = 0 to 2 do
86+
for j = 0 to 2 do
87+
let value =
88+
board.(!grid_row_starts_at + i).(!grid_column_starts_at + j)
89+
in
90+
if value != '.' then (
91+
let index = char_to_int value - 1 in
92+
count.(index) <- count.(index) + 1;
93+
94+
if count.(index) > 1 then valid := false)
95+
done
96+
done;
97+
98+
grid_column_starts_at := !grid_column_starts_at + grid_size
99+
done;
100+
101+
grid_row_starts_at := !grid_row_starts_at + grid_size;
102+
grid_column_starts_at := 0
103+
done;
104+
105+
(* time O(n) *)
106+
while !valid && !row_or_column < board_size do
107+
(* Check for duplicated numbers in the current row *)
108+
let count = Array.make 9 0 in
109+
110+
for i = 0 to board_size - 1 do
111+
(* A value from 1 to 9. *)
112+
let value = board.(!row_or_column).(i) in
113+
if value != '.' then (
114+
let index = char_to_int value - 1 in
115+
count.(index) <- count.(index) + 1;
116+
if count.(index) > 1 then valid := false)
117+
done;
118+
119+
(* Check for duplicated numbers in the current column *)
120+
let count = Array.make 9 0 in
121+
122+
(* time O(n) *)
123+
for i = 0 to board_size - 1 do
124+
(* A value from 1 to 9. *)
125+
let value = board.(i).(!row_or_column) in
126+
if value != '.' then (
127+
let index = char_to_int value - 1 in
128+
count.(index) <- count.(index) + 1;
129+
if count.(index) > 1 then valid := false)
130+
done;
131+
132+
row_or_column := !row_or_column + 1
133+
done;
134+
135+
!valid
136+
137+
let () =
138+
Printf.printf "example 1: should be true %b\n"
139+
(is_valid_sudoku
140+
[|
141+
[| '5'; '3'; '.'; '.'; '7'; '.'; '.'; '.'; '.' |];
142+
[| '6'; '.'; '.'; '1'; '9'; '5'; '.'; '.'; '.' |];
143+
[| '.'; '9'; '8'; '.'; '.'; '.'; '.'; '6'; '.' |];
144+
[| '8'; '.'; '.'; '.'; '6'; '.'; '.'; '.'; '3' |];
145+
[| '4'; '.'; '.'; '8'; '.'; '3'; '.'; '.'; '1' |];
146+
[| '7'; '.'; '.'; '.'; '2'; '.'; '.'; '.'; '6' |];
147+
[| '.'; '6'; '.'; '.'; '.'; '.'; '2'; '8'; '.' |];
148+
[| '.'; '.'; '.'; '4'; '1'; '9'; '.'; '.'; '5' |];
149+
[| '.'; '.'; '.'; '.'; '8'; '.'; '.'; '7'; '9' |];
150+
|]);
151+
152+
Printf.printf "example 2: should be false %b\n"
153+
(is_valid_sudoku
154+
[|
155+
[| '8'; '3'; '.'; '.'; '7'; '.'; '.'; '.'; '.' |];
156+
[| '6'; '.'; '.'; '1'; '9'; '5'; '.'; '.'; '.' |];
157+
[| '.'; '9'; '8'; '.'; '.'; '.'; '.'; '6'; '.' |];
158+
[| '8'; '.'; '.'; '.'; '6'; '.'; '.'; '.'; '3' |];
159+
[| '4'; '.'; '.'; '8'; '.'; '3'; '.'; '.'; '1' |];
160+
[| '7'; '.'; '.'; '.'; '2'; '.'; '.'; '.'; '6' |];
161+
[| '.'; '6'; '.'; '.'; '.'; '.'; '2'; '8'; '.' |];
162+
[| '.'; '.'; '.'; '4'; '1'; '9'; '.'; '.'; '5' |];
163+
[| '.'; '.'; '.'; '.'; '8'; '.'; '.'; '7'; '9' |];
164+
|]);
165+
166+
Printf.printf "example 3: should be false %b\n"
167+
(is_valid_sudoku
168+
[|
169+
[| '5'; '3'; '.'; '.'; '7'; '.'; '.'; '.'; '.' |];
170+
[| '6'; '.'; '.'; '1'; '9'; '5'; '.'; '.'; '.' |];
171+
[| '.'; '9'; '8'; '.'; '.'; '.'; '.'; '6'; '.' |];
172+
[| '8'; '.'; '.'; '.'; '6'; '2'; '.'; '.'; '3' |];
173+
[| '4'; '.'; '.'; '.'; '.'; '3'; '.'; '.'; '1' |];
174+
[| '7'; '8'; '.'; '.'; '2'; '.'; '.'; '.'; '6' |];
175+
[| '.'; '6'; '.'; '.'; '.'; '.'; '2'; '8'; '.' |];
176+
[| '.'; '.'; '.'; '4'; '1'; '9'; '.'; '.'; '5' |];
177+
[| '.'; '.'; '.'; '.'; '8'; '.'; '.'; '7'; '9' |];
178+
|])

0 commit comments

Comments
 (0)