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
|
open Int64
let debug = ref false
let sol = ref zero
let rec visit = function
[] -> assert false
| [(ck,ak)] ->
sol := add !sol one;
let sk = string_of_int ak in
let skp = sk^"+" in
for i = 1 to (ck-1) do
print_string skp;
done; print_endline sk
| (ck,ak)::q ->
let sk = string_of_int ak in
let skp = sk^"+" in
for i = 1 to ck do
print_string skp;
done; visit q
let rec main_loop n l =
if !debug then visit (List.rev l);
match l with
| [] -> assert false
| [(_,1)] -> ()
| (ck,1)::(dk, 2)::q ->
let q' = if dk=1 then q else (dk-1,2)::q in
main_loop n ((ck+2,1)::q')
| (ck,1)::(dk, ak)::q ->
let x = ak-1 in
let q' = if dk=1 then q else (dk-1,ak)::q in
let quot = (ck+1)/x in
let r = (ck+1)-x*quot in
main_loop n
(if r = 0 then
(quot+1,x)::q'
else
(1,r)::(quot+1,x)::q')
| (dk,2)::q ->
let q' = if dk=1 then q else (dk-1,2)::q in
main_loop n ((2,1)::q')
| (dk,ak)::q ->
let q' = if dk=1 then q else (dk-1,ak)::q in
main_loop n ((1,1)::(1,ak-1)::q')
let main n =
if n < 1 then raise (Invalid_argument "n should be positive");
main_loop n [(1,n)]
let usage =
Printf.sprintf
"%s <n> <t>\n Generates all partitions of n\n"
(Sys.argv.(0))
let n = ref 0
let _ =
Arg.parse [("-debug", Arg.Set debug, "prints each partition");
("-n", Arg.Set_int n, "integer to partition")]
(fun s -> print_endline usage)
usage;
main !n;
if !debug then Printf.eprintf "Number of solutions visited : %s\n" (to_string !sol) |
Partager