File: queens_tail.ml

package info (click to toggle)
ocaml-doc 3.09-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 10,428 kB
  • ctags: 4,963
  • sloc: ml: 9,244; makefile: 2,413; ansic: 122; sh: 49; asm: 17
file content (103 lines) | stat: -rw-r--r-- 2,948 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*               Pierre Weis, projet Cristal, INRIA Rocquencourt       *)
(*                                                                     *)
(*  Copyright 2001 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  only by permission.                                                *)
(*                                                                     *)
(***********************************************************************)

(*                         E I G H T   Q U E E N S

 The Eight Queens Program tail recursive version.

*)

open List;;

let map f l =
 let rec loop accu = function
   | [] -> accu
   | x :: l -> loop (f x :: accu) l in
 loop [] l;;

let rec interval n m =
 if n > m then [] else n :: interval (n + 1) m;;

let rev_append l1 l2 =
  let rec loop accu = function
    | [] -> accu
    | h :: t -> loop (h :: accu) t in
  loop l2 l1;;

let filter_append p l l0 =
  let rec loop accu = function
    | [] -> accu
    | h :: t -> if p h then loop (h :: accu) t else loop accu t in
  let rev_res = loop [] l in
  rev_append rev_res l0;;

let concmap f l =
  let rec loop accu = function
  | [] -> accu
  | h :: t -> loop (f h accu) t in
  loop [] l;;

let rec safe x d  = function
  | [] -> true
  | h :: t ->
     x <> h && x <> h + d && x <> h - d && safe x (d + 1) t;;

let rec ok = function
  | [] -> true
  | h :: t -> safe h 1 t;;

let find_solutions size =
 let line = interval 1 size in
 let rec gen n size =
   if n = 0 then [[]] else
   concmap 
    (fun b -> filter_append ok (map (fun q -> q :: b) line))
    (gen (n - 1) size) in
 gen size size;;

(* 2. Printing results. *)

let print_solutions size solutions =
 let sol_num = ref 1 in
 iter
   (fun chess ->
     Printf.printf "\nSolution number %i\n" !sol_num;
     sol_num := !sol_num + 1;
     iter
       (fun line ->
         let count = ref 1 in
         while !count <= size do
           if !count = line then print_string "Q " else print_string "- ";
           count := !count + 1
         done;
         print_newline ())
       chess)
   solutions;;

let print_result size =
 let solutions = find_solutions size in
 let sol_num = List.length solutions in
 Printf.printf "The %i queens problem has %i solutions.\n" size sol_num;
 print_newline ();
 let pr = 
   print_string "Do you want to see the solutions <n/y> ? "; read_line () in
 if pr = "y" then print_solutions size solutions;;

(* 3. Main program. *)

let queens () =
 let size = 
   print_string "Chess boards's size ? "; read_int () in
 print_result size;;

if !Sys.interactive then () else queens ();;