open Format
let premiers = [1;2;4;8;16;32;64;128;256;512;1024;2048;4096;8192];;
let rec print_int_list l = match l with
	|[] -> printf "\n"
	|h::t -> begin printf "%d " h;print_int_list t end;;
let print_sum l =
	let rec aux l = match l with
		| [] -> printf "\n"
		| h::t -> begin printf " + %d" h;aux t end in
	match l with
		|[] -> printf "0\n"
		|h::t -> begin printf "%d" h;aux t end;;
let rec sum l = match l with
    | [] -> 0
    | h::t -> h + sum t;;
let rec dans a l = match l with
	| [] -> false
	| h::t -> if h=a then true else dans a t ;;
let rec retirer acc base modulo = match base with
	| [] -> acc
	| h::t -> if dans h modulo then retirer acc t modulo
  				 else retirer (h::acc) t modulo ;;
let rec somme accn accl ban lim l = match l with
	| [] -> (accn,accl,true)
  	| h::t -> if accn < lim then somme (accn+h) (h::accl) ban lim t
  	          else if dans (accn - lim) ban then somme (accn+h) (h::accl) ban lim t
				 else (accn,accl,false);;
let decomp n =
	 let imp = ref [1] in
    let rec aux impp n =
        if dans n !imp then raise Not_found else
        if dans n premiers then [n] else
        let (a,l,f) = somme 0 [] !imp n premiers in
        print_int_list (n::a::0::l);
        match a - n with
            |0 -> l
            |d (*when d < n*) -> begin try retirer [] l (aux impp d) with
            						| Not_found when f -> raise Not_found
                              | Not_found -> begin imp:=(d::(!imp)); aux (d::impp) n end end
            (*|d -> raise Not_found*) in
    aux [1] n;;
for i = 0 to sum premiers do
	try begin let d = decomp i in printf "%d = " i; print_sum d end with
		| Not_found -> printf "%d : Pas de decomposition\n" i done;;
(*
let max = ref 0 in
let imax = ref 0 in
for i = 0 to sum premiers do
	let c = ref 0 in
	try let a=sum (decomp c i) in printf "Oui :%d : %d\n" i !c with
		| Not_found -> printf "Non :%d : %d\n" i !c;
	if !c > !max then begin max := !c; imax := i end done;
printf "%d : %d" !imax !max;; *)
