#load "nums.cma";; open Big_int;; let rec factorial n = if eq_big_int n unit_big_int then unit_big_int else mult_big_int n (factorial (pred_big_int n));; let int_list_of_string s = let len = String.length s in let rec chars_of_string s n = if n == 0 then [int_of_char s.[0] - int_of_char '0'] else (chars_of_string s (n - 1)) @ [(int_of_char s.[n]) - int_of_char '0'] in chars_of_string s (len - 1);; Printf.printf "%d\n" (List.fold_left (+) 0 (int_list_of_string (string_of_big_int (factorial (big_int_of_int 100)))));;
jeudi 25 mars 2010
Project Euler #20
mardi 23 mars 2010
Project Euler #6
#load "nums.cma" open Big_int;; let rec sum_of_squares n = if eq_big_int n unit_big_int then unit_big_int else add_big_int (square_big_int n) (sum_of_squares (pred_big_int n));; let square_of_sum n = let rec sum n = if eq_big_int n unit_big_int then unit_big_int else add_big_int n (sum (pred_big_int n)) in square_big_int (sum n);; let s1 = sum_of_squares (big_int_of_int 100);; let s2 = square_of_sum (big_int_of_int 100);; let result = sub_big_int s2 s1;; Printf.printf "%s\n" (string_of_big_int result);;
Сначала написал с использованием встроенных int, перепутал местами суммы при вычитании, получил отрицательный результат, подумал, что проблема с переполнением int, переписал при помощи Big_int, после чего и обнаружил, что перепутал суммы местами.
lundi 22 mars 2010
Project Euler #4
(* Checks if int is palindrome *) let is_palindrome n = let str = string_of_int n in let len = String.length str in let rec check_char s n = if n == len - 1 then (String.get s n == String.get s 0) else (String.get s n == String.get s (len - 1 - n)) && (check_char s (n + 1)) in check_char str 0;; (* check if n is a product of two 3-digit numbers *) let is_product n = let rec check_numbers i j n = let rest = n mod i in let modulo = n / i in let mod_length = String.length (string_of_int modulo) in if i = j then false else if (rest == 0) && (mod_length == 3) then begin Printf.printf "%d %d\n" i modulo; true end else check_numbers (i+1) j n in check_numbers 100 999 n;; (* looks for palindromes which a products of two 3-digit numbers*) let rec check_range n m = if n == m then -1 else if (is_palindrome n) && (is_product n) then n else check_range (n-1) m;; Printf.printf "%d\n" (check_range 998001 10000)Изначально пытался просто переделать двойной цикл с проверкой в рекурсию, в итоге оказалось проще перебрать числа в одной рекурсии.
lundi 1 mars 2010
Project Euler #3
#load "nums.cma" open Big_int;; let num = big_int_of_string "600851475143";; let solution n = let rec factorize m p = if ge_big_int p m then Printf.printf "%s\n" (string_of_big_int m) else if eq_big_int (mod_big_int m p) zero_big_int then factorize (div_big_int m p) (big_int_of_int 2) else factorize m (succ_big_int p) in factorize n (big_int_of_int 2);; solution num;;
Решение вида "а давайте-ка найдем все простые числа до sqrt(N), а потом найдем максимальное, которое разделит N без остатка", что прокатило для C++, в Ocaml оказалось неосуществимо в разумные сроки ;)
Project Euler #2
#load "nums.cma";; open Big_int;; let rec fib a b = function | 0 -> a | 1 -> b | n when n > 1 -> fib b (add_big_int a b) (n - 1) | _ -> raise (Invalid_argument "");; let rec fib_range n = let fn = fib zero_big_int unit_big_int n in if lt_big_int fn (big_int_of_string "4000000") then if eq_big_int (mod_big_int fn (big_int_of_int 2)) zero_big_int then fn :: (fib_range (n + 1)) else zero_big_int :: fib_range (n + 1) else [];; Printf.printf "%s\n" (string_of_big_int (List.fold_left (add_big_int) zero_big_int (fib_range 0)));;
Генерация списка по причинам детского восторга от fold, в принципе можно было сразу суммировать.
Project Euler #1
let rec range n m = if n > m then [] else n :: range (n + 1) m;; Printf.printf "%d\n" (List.fold_left (+) 0 (List.map (fun n -> if n mod 3 == 0 or n mod 5 == 0 then n else 0) (range 1 999)))
Inscription à :
Articles (Atom)