Advertisement
Guest User

Untitled

a guest
Jun 15th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
OCaml 13.07 KB | None | 0 0
  1. let u0 = 42
  2.  
  3. let nmax = 10000
  4.  
  5. let u = Array.make nmax u0
  6.  
  7. let m = 2147483647
  8.  
  9. let remplit_u =
  10.     for i = 1 to nmax-1 do
  11.         u.(i) <- (16807 * u.(i-1) + 17) mod m
  12.     done
  13.  
  14. let affiche_question qn pprint resultats =
  15.     Printf.printf "Q%d) " qn;
  16.     List.iter (fun r -> pprint r; print_string " ")
  17.         resultats;
  18.     print_newline ()
  19.  
  20. let _ =
  21.     affiche_question 1 print_int
  22.     [ u.(5) mod 101; u.(100) mod 101; u.(997) mod 101 ]
  23.  
  24.  
  25. let v = Array.make_matrix 62 1001 0
  26.  
  27. let remplit_v =
  28.     let p = ref 1 in
  29.     for k = 0 to 61 do
  30.         for n = 0 to 1000 do
  31.             v.(k).(n) <- u.(n) mod !p + !p
  32.         done;
  33.         p := !p * 2
  34.     done
  35.  
  36. let q2 k = v.(k).(97*k mod 997) mod 101
  37.  
  38. let _ =
  39.     affiche_question 2 print_int
  40.     [ q2 5; q2 30; q2 61 ]
  41.  
  42. (* soit p = max { d tels que x(d) <= x }
  43.  * on a x(p+1) = x(p)^2 > x >= x(p)
  44.  *
  45.  * soit alors d = max { k tels que x(p) * k <= x }
  46.  * on a d < x(p) et x(p)d <= x < x(p)d + x(p)
  47.  * donc 0 <= x - x(p)d < x(p)
  48.  *
  49.  * Pour l'unicité, si n = g + x(p) d =
  50.  * g' + x(p')d'
  51.  * un argument de comparaison donne rapidement p=p'
  52.  * puis le reste suit l'argument classique sur la
  53.  * division euclidienne *)
  54.  
  55. type ternaire = Zero | Un
  56.     | Noeud of ternaire * ternaire * ternaire
  57.  
  58. let rec pair t = match t with
  59.     Zero -> true
  60.     | Un -> false
  61.     | Noeud(g,_,_) -> pair g
  62.  
  63. let rec sign t =
  64.     match t with
  65.     Zero -> 0
  66.     | Un -> u.(10) mod 97
  67.     | Noeud(g,p,d) when pair p ->
  68.         (sign g + u.(30)* sign d) mod 97
  69.     | Noeud(g,p,d) ->
  70.         (sign g + u.(20)* sign d) mod 97
  71.  
  72. (* deborde tres tres vite *)
  73. let rec evalue_x p = if p = 0 then 2 else let x = evalue_x (p-1) in x * x
  74. let rec evalue t = match t with
  75.     | Zero -> 0
  76.     | Un -> 1
  77.     | Noeud(g,p,d) -> evalue g + evalue_x (evalue p) * evalue d
  78.  
  79. let rec ternarize n =
  80.     if n = 0 then Zero
  81.     else if n = 1 then Un
  82.     else begin
  83.         let p = ref 0 in
  84.         let x = ref 2 in
  85.         while !p < 5 && !x * !x <= n do
  86.             (* on espere que ca passe avant que
  87.              * ca ne depasse ... *)
  88.             incr p;
  89.             x := !x * !x
  90.         done;
  91.         Noeud(ternarize (n mod !x), ternarize !p, ternarize (n / !x))
  92.     end
  93.  
  94. let string_of_ternaire t =
  95.     let rec aux t n =
  96.         let sn = String.make n ' ' in
  97.         match t with
  98.         Zero -> sn ^ "0"
  99.         | Un -> sn ^ "1"
  100.         | Noeud (g,p,d) ->
  101.                 sn ^ "<\n" ^ aux g (n+1)
  102.                 ^ "\n" ^ aux p (n+1)
  103.                 ^ "\n" ^ aux d (n+1)
  104.                 ^ "\n" ^ sn ^ ">"
  105.     in aux t 0
  106.  
  107. let _ =
  108.     affiche_question 3 print_int
  109.         [ sign (ternarize v.(1).(10));
  110.           sign (ternarize v.(2).(20));
  111.           sign (ternarize v.(32).(30));
  112.           sign (ternarize v.(61).(40)) ]
  113.  
  114.  
  115. let rec h n = match n with
  116.     | 0 -> Un
  117.     | _ -> let t = h (n-1) in
  118.         Noeud(t,t,t)
  119.  
  120. let q4 k = sign (h v.(k).(7*k))
  121.  
  122. (* tous les h sont impairs *)
  123. (* on peut donc calculer sign o h d'un coup *)
  124. let rec q4h n =
  125.     match n with
  126.     | 0 -> u.(10) mod 97
  127.     | _ -> let s = q4h (n-1) in
  128.         (s + u.(20) * s) mod 97
  129.  
  130. let q4rapide k = q4h v.(k).(7*k)
  131.  
  132. let _ =
  133.     affiche_question 4 print_int
  134.         [q4 0; q4 2; q4rapide 4; q4rapide 8]
  135.  
  136. let gen = Array.make_matrix 62 997 Zero
  137.  
  138. (* premiere approche pour obtenir la question 5 *)
  139. let remplit_gen =
  140.     for k = 0 to 48 do
  141.         for n = 0 to 996 do
  142.             gen.(k).(n) <-
  143.                 if k = 0
  144.                 then begin if u.(n) mod 7 = 0
  145.                     then Zero else Un end
  146.                 else
  147.                     let kp = max 0 (k-1-(u.(n) mod 2)) in
  148.                     let g = gen.(kp).( (n+1) mod 997 ) in
  149.                     let p = v.(kp).(n) in
  150.                     let d = gen.(kp).( (n+2) mod 997 ) in
  151.                     if d = Zero
  152.                     then g
  153.                     else Noeud(g, ternarize p, d)
  154.         done
  155.     done
  156.                      
  157.  
  158. let q5 k n = sign gen.(k).(n)
  159.  
  160. let _ =
  161.     affiche_question 5 print_int
  162.         [ q5 6 35; q5 8 45; q5 10 55; q5 12 65; q5 14 75 ]
  163.  
  164. (* decrementation naive *)
  165. let rec dec t = match t with
  166.     Zero -> failwith "decrementation de 0"
  167.     | Un -> Zero
  168.     | Noeud(Zero,p,Un) -> xprime p
  169.     | Noeud(Zero,p,d) -> Noeud(xprime p, p, dec d)
  170.     | Noeud(g,p,d) -> Noeud(dec g,p,d)
  171. and xprime p = match p with
  172.     | Zero -> Un
  173.     | _ -> let q = dec p in
  174.           let xpq = xprime q in
  175.           Noeud(xpq, q, xpq)
  176.  
  177. let q6 k = sign (dec (gen.(k).((19*k) mod 997)))
  178.  
  179. let _ =
  180.     affiche_question 6 print_int
  181.         [ q6 6; q6 16; q6 26 ]
  182.  
  183. (* pour incrementer il faut tester l'egalite à un x(p)-1 connaissant p *)
  184. (* or xprime p defini precedemment calcule exactement x(p)-1 *)
  185. (* je pense qu'on peut faire mieux avec une reconnaissance des arbres de la
  186.  * forme x(p)-1 qui ont une forte symétrie, mais ça passe avec un test naif *)
  187. let rec inc t = match t with
  188.     | Zero -> Un
  189.     | Un -> Noeud(Zero,Zero,Un)
  190.     | Noeud(g,p,d) -> let xpp = xprime p in
  191.         if g = xpp && d = xpp
  192.         then Noeud(Zero,inc p,Un)
  193.         else if g = xpp
  194.             then Noeud(Zero,p,inc d)
  195.             else Noeud(inc g,p,d)
  196.  
  197. let q7 k = sign (inc (gen.(k).((17*k) mod 997)))
  198.  
  199. let _ =
  200.     affiche_question 7 print_int
  201.         [ q7 6; q7 7; q7 16 ]
  202.  
  203. let rec compare t1 t2 = match t1, t2 with
  204.     (* cas de base *)
  205.     | Zero, Zero -> 0
  206.     | Zero, _ -> -1
  207.     | _, Zero -> 1
  208.     | Un, Un -> 0
  209.     | Un, _ -> -1
  210.     | _, Un -> 1
  211.     (* cas general *)
  212.     | Noeud(g1,p1,d1), Noeud(g2,p2,d2) ->
  213.             let cp = compare p1 p2 in
  214.             if cp = 0
  215.             then let cd = compare d1 d2 in
  216.                 if cd = 0
  217.                 then compare g1 g2
  218.                 else cd
  219.             else cp
  220.  
  221. let q8 k = compare gen.(k).((29*k) mod 997) gen.(k).((31*k) mod 997)
  222.  
  223. let _ =
  224.     affiche_question 8 print_int
  225.         [ q8 6; q8 8; q8 16 ]
  226.  
  227. let rec add t1 t2 = match t1, t2 with
  228.     | Zero, _ -> t2
  229.     | _, Zero -> t1
  230.     | Un, _ -> inc t2
  231.     | _, Un -> inc t1
  232.     | Noeud(g1,p1,d1), Noeud(g2,p2,d2) ->
  233.             match compare p1 p2 with
  234.             | 1 -> normalize (Noeud(add t1 g2, p2, d2))
  235.             | -1 -> normalize (Noeud(add t2 g1, p1, d1))
  236.             | _ -> normalize (Noeud(add g1 g2, p1, add d1 d2))
  237. and normalize t = match t with
  238.     | Noeud(Noeud(g1,p1,d1), p, d) ->  begin
  239.             match compare p1 p with
  240.             | -1 -> normalize_right t
  241.             | 0 -> normalize_right (Noeud(g1,p,add d1 d))
  242.             | _ -> normalize (Noeud(normalize(Noeud(g1,p,d)),p1,d1))
  243.     end
  244.     | _ -> t
  245. and normalize_right t = match t with
  246.     | Noeud(g,p,Noeud(g1,p1,d1)) -> begin
  247.             match compare p p1 with
  248.             | 0 -> Noeud(Noeud(g,p,g1),inc p,d1)
  249.             | -1 -> normalize (Noeud(normalize_right(Noeud(g,p,g1)),
  250.                                     p1,normalize_right(Noeud(Zero,p,d1))))
  251.             | _ -> t
  252.     end
  253.     | _ -> t
  254.  
  255. let q9 k = sign (add gen.(k).((41*k) mod 997) gen.(k).((43*k) mod 997))
  256.  
  257. let _ =
  258.     affiche_question 9 print_int
  259.         [ q9 6; q9 12; q9 16 ]
  260.  
  261. let rec mul t1 t2 = match t1 with
  262.     | Zero -> Zero
  263.     | Un -> t2
  264.     | Noeud(g,p,d) -> normalize(Noeud(mul g t2, p, mul d t2))
  265.  
  266. (* probleme *)
  267. let q10 k = sign (mul gen.(k).((43*k) mod 997) gen.(k).((41*k) mod 997))
  268.  
  269. let _ =
  270.     affiche_question 10 print_int
  271.         [ q10 5; q10 8; q10 10 ]
  272.  
  273. let rec taille t = match t with
  274.     | Zero | Un -> 0 | Noeud(g,p,d) -> 1 + taille g + taille p + taille d
  275.  
  276. let rec concat_u l1 l2 = match l2 with
  277.     | [] -> l1
  278.     | t::q when List.mem t l1 -> concat_u l1 q
  279.     | t::q -> t :: concat_u l1 q
  280.  
  281. let rec parties t = match t with
  282.     | Zero | Un -> []
  283.     | Noeud(g,p,d) ->
  284.         let pg = parties g in
  285.         let pp = parties p in
  286.         let pd = parties d in
  287.         t :: (concat_u (concat_u pg pp) pd)
  288.  
  289. let nparties t = List.length (parties t)
  290.  
  291. let q11 k = let x = gen.(k).((23*k) mod 997) in
  292.     (nparties x, taille x)
  293.  
  294. let _ =
  295.     affiche_question 11 (fun (a,b) ->
  296.             Printf.printf "(%d,%d)" a b)
  297.         [ q11 8; q11 16; q11 24(* ; q11 32 *) ] (* dernier cas un peu lent *)
  298.  
  299. (* il faut faire du partage de sous-arbres *)
  300.  
  301. type ternaire_compact = Zero | Un | Noeud of int * int * int
  302.  
  303. let max_taille = 1000000
  304. let taille = ref 0
  305. let stockage = Array.make max_taille Zero
  306. let lookup = Hashtbl.create u0
  307.  
  308. let ajoute t =
  309.     if not (Hashtbl.mem lookup t)
  310.     then begin
  311.         let n = !taille in
  312.         stockage.(n) <- t;
  313.         incr taille;
  314.         Hashtbl.add lookup t n
  315.     end
  316.  
  317. let adresse t = Hashtbl.find lookup t
  318.  
  319. (* pour faire du copier coller facilement *)
  320. let noeud (a,b,c) =  Noeud(adresse a, adresse b, adresse c)
  321. let unpack n = match n with
  322.     | Noeud(a,b,c) -> (stockage.(a), stockage.(b), stockage.(c))
  323.     | _ -> failwith "invalide"
  324.  
  325. let ternarize_hash = Hashtbl.create 42
  326. let rec ternarize n =
  327.     try
  328.         Hashtbl.find ternarize_hash n
  329.     with Not_found -> let t =
  330.         if n = 0 then Zero
  331.         else if n = 1 then Un
  332.         else begin
  333.             let p = ref 0 in
  334.             let x = ref 2 in
  335.             while !x * !x <= n && !x * !x != 0 do
  336.                 (* on espere que ca passe avant que
  337.                  * ca ne depasse ... *)
  338.                 incr p;
  339.                 x := !x * !x
  340.             done;
  341.             let d = ref 1 in
  342.             let y = ref !x in
  343.             while !x + !y <= n do
  344.                 incr d;
  345.                 y := !y + !x
  346.             done;
  347.             noeud (ternarize (n mod !x),
  348.                 ternarize !p,
  349.                 ternarize (n / !x))
  350.         end
  351.     in Hashtbl.add ternarize_hash n t; ajoute t; t
  352.  
  353. let gen = Array.make_matrix 62 997 Zero
  354.  
  355. (* premiere approche pour obtenir la question 5 *)
  356. let remplit_gen =
  357.     for k = 0 to 10 do
  358.         for n = 0 to 996 do
  359.             let t =
  360.                 if k = 0
  361.                 then begin if u.(n) mod 7 = 0
  362.                     then Zero else Un end
  363.                 else
  364.                     let kp = max 0 (k-1-(u.(n) mod 2)) in
  365.                     let g = gen.(kp).( (n+1) mod 997 ) in
  366.                     let p = v.(kp).(n) in
  367.                     let d = gen.(kp).( (n+2) mod 997 ) in
  368.                     if d = Zero
  369.                     then g
  370.                     else noeud(g, ternarize p, d)
  371.             in
  372.             ajoute t;
  373.             gen.(k).(n) <- t
  374.         done
  375.     done
  376.  
  377. let tabule f =
  378.     let f_table = Array.make max_taille None in
  379.     let rec f_tabulee t =
  380.         let a = adresse t in
  381.  
  382.         (if f_table.(a) = None
  383.         then let v = f f_tabulee t in
  384.             f_table.(a) <- Some v);
  385.  
  386.         match f_table.(a) with
  387.         | Some v -> v
  388.         | None -> failwith "impossible"
  389.     in f_tabulee
  390.  
  391. let pop =
  392.     let aux rpop n =
  393.         match n with
  394.         | Zero -> 0
  395.         | Un -> 1
  396.         | _ -> let g,p,d = unpack n in
  397.             rpop g + rpop d
  398.     in tabule aux
  399.  
  400. let q12 k = let x = gen.(k).((37*k) mod 997) in
  401.     pop x mod 97
  402.  
  403. let _ =
  404.     affiche_question 12 print_int
  405.         [ q12 48; q12 55 ]
  406.  
  407. let rec dec t = let dt = match t with
  408.     Zero -> failwith "decrementation de 0"
  409.     | Un -> Zero
  410.     | _ -> begin match unpack t with
  411.         | Zero,p,Un -> xprime p
  412.         | Zero,p,d -> noeud(xprime p, p, dec d)
  413.         | g,p,d -> noeud(dec g, p, d)
  414.     end in ajoute dt; dt
  415. and xprime p = let v = match p with
  416.     | Zero -> Un
  417.     | _ -> let q = dec p in
  418.           let xpq = xprime q in
  419.           noeud(xpq, q, xpq)
  420.     in ajoute v; v
  421.  
  422. let pair =
  423.     let aux rpair t =
  424.         match t with
  425.         Zero -> true
  426.         | Un -> false
  427.         | Noeud(g,_,_) -> rpair stockage.(g)
  428.     in tabule aux
  429.  
  430. let sign =
  431.     let aux rsign t = match t with
  432.     | Zero -> 0
  433.     | Un -> u.(10) mod 97
  434.     | _ -> begin match unpack t with
  435.         | g,p,d when pair p ->
  436.             (rsign g + u.(30) * rsign d) mod 97
  437.         | g,p,d -> (rsign g + u.(20) * rsign d) mod 97
  438.         end
  439.     in tabule aux
  440.  
  441. let q13 k = let x = gen.(k).((19*k) mod 997) in
  442.     sign (dec (gen.(k).((19*k) mod 997)))
  443.  
  444.     (*
  445. let _ =
  446.     affiche_question 13 print_int
  447.         [ q13 48; q13 55 ]
  448. *)
  449. let rec evalue_x p = if p = 0 then 2 else let x = evalue_x (p-1) in x * x
  450. let rec evalue t = match t with
  451.     | Zero -> 0
  452.     | Un -> 1
  453.     | _ -> let g,p,d = unpack t in evalue g + evalue_x (evalue p) * evalue d
  454.  
  455. let rec complement n p = (* renvoie (-n) tq n + (-n) mod x(p) = 0 *)
  456.     let v = match n with
  457.     | Zero -> Zero
  458.     | Un -> dec (noeud(Zero,p,Un))
  459.     | _ -> let g,p1,d = unpack n in
  460.         let dp = dec p in
  461.         if p1 = p
  462.         then complement g p
  463.         else if p1 = dp
  464.             then noeud(complement g dp, dp, complement d dp)
  465.             else noeud(complement n dp, dp, xprime dp)
  466.     in Printf.printf "-(%d) =  %d [ %d ]\n" (evalue n) (evalue v) (evalue p); v
  467.  
  468. let _ =
  469.     let p = 3 in
  470.     let tp = ternarize p in
  471.     for i = 3 to 3 do
  472.         let ti = ternarize i in
  473.         Printf.printf "-(%d) = %d [x(%d)]\n"
  474.             i (evalue (complement ti tp)) p
  475.     done
  476.  
  477. let _ =
  478.     Printf.printf "nombre d'arbres %d\n" !taille
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement