vendredi 15 octobre 2010
Euler #47
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from libeuler import is_prime | |
def prime_factors(n, P): | |
r = [] | |
t = n | |
while True: | |
if t == 1: | |
break | |
for p in P: | |
if t % p == 0: | |
r += [p] | |
t /= p | |
break | |
return r | |
if __name__ == '__main__': | |
n = 10 | |
primes = filter(lambda x: is_prime(x), range(1000000)) | |
while True: | |
l1 = len(set(prime_factors(n, primes))) | |
l2 = len(set(prime_factors(n+1, primes))) | |
l3 = len(set(prime_factors(n+2, primes))) | |
l4 = len(set(prime_factors(n+3, primes))) | |
if l1 == 4 and l2 == 4 and l3 == 4 and l4 == 4: | |
print n | |
break | |
print "%d -> %d %d %d %d" % (n, l1, l2, l3, l4) | |
n += 1 |
Euler #46
#!/usr/bin/env python from libeuler import is_prime, primes from math import sqrt if __name__ == '__main__': P = primes(100000) n = 1 while True: found = False for p in P[1:]: a2 = n - 0.5*(p - 1) if a2 < 0: break if sqrt(a2) == float(int(sqrt(a2))): print "%d -> %d + 2*%d^2" % (2*n + 1, p, sqrt(a2)) found = True n += 1 break if not found and not (2*n+1) in P: print 2*n + 1 break
Euler #44
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#load "euler.cma";; | |
open Euler;; | |
let pentagonal n = n * (3*n - 1) / 2;; | |
let pentagonal_index n = int_of_float ((1. +. sqrt(1. +. 24. *. float_of_int(n))) /. 6.);; | |
let is_pentagonal d = (mod_float ((sqrt(24. *. float_of_int(d) +. 1.) +. 1.) /. 6.) 1.) = 0.;; | |
let get_pentagonals n = List.rev_map (pentagonal) (range n);; | |
let low_pentagonals n = | |
let idx = pentagonal_index n in | |
get_pentagonals (idx-1);; | |
let rec search_pentagonal l = match l with | |
[] -> raise Not_found | |
| h :: t -> | |
let low = low_pentagonals h in | |
let sums = List.filter (fun x -> is_pentagonal (h + x)) low in | |
let good = List.filter (fun x -> is_pentagonal (h - x)) sums in | |
if List.length good > 0 then | |
(h, good) | |
else | |
search_pentagonal t;; | |
let _ = | |
let r = search_pentagonal (get_pentagonals 3000) in | |
let num = fst(r) in | |
let list = snd(r) in | |
List.rev_map (fun x -> Printf.printf "%d\n" x) (List.rev_map (fun x -> num - x) list) |
Euler #43
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from libeuler import str_permutations | |
if __name__ == '__main__': | |
nums = str_permutations('0123456789') | |
r = [] | |
for n in nums: | |
n1 = int(n[1:4]) | |
n2 = int(n[2:5]) | |
n3 = int(n[3:6]) | |
n4 = int(n[4:7]) | |
n5 = int(n[5:8]) | |
n6 = int(n[6:9]) | |
n7 = int(n[7:10]) | |
if n1 % 2 == 0 and \ | |
n2 % 3 == 0 and \ | |
n3 % 5 == 0 and \ | |
n4 % 7 == 0 and \ | |
n5 % 11 == 0 and \ | |
n6 % 13 == 0 and \ | |
n7 % 17 == 0: | |
print n | |
r += [int(n)] | |
print sum(r) |
Euler #42
#!/usr/bin/env python def word_value(w): return sum(map(lambda x: ord(x) - ord('A') + 1, w)) def triangle_numbers(l): res = [] n = 1 t = 1 while t < l: t = n*(n+1)/2 res += [t] n += 1 return res if __name__ == '__main__': f = open('words.txt', 'r') words = f.read() f.close() words = map(word_value, map(lambda x: x[1:-1], words.split(','))) triangles = triangle_numbers(max(words)) n = 0 for w in words: if w in triangles: n += 1 print n
Euler #41
#!/usr/bin/env python from libeuler import is_prime, pandigital if __name__ == '__main__': res = [] for i in xrange(1, 10): res += filter(lambda x: is_prime(x), pandigital(i)) print max(res)
Euler #40
#!/usr/bin/env python def create_fraction(): f = '' cnt = 1 while len(f) < 1000000: f += str(cnt) cnt += 1 return f if __name__ == '__main__': fraction = create_fraction() d1 = int(fraction[0]) d10 = int(fraction[9]) d100 = int(fraction[99]) d1000 = int(fraction[999]) d10000 = int(fraction[9999]) d100000 = int(fraction[99999]) d1000000 = int(fraction[999999]) print d1 * d10 * d100 * d1000 * d10000 * d100000 * d1000000
Well, obviously we can use arrays and powers of 10
Euler #39
#!/usr/bin/env python from math import sqrt def n_triangles(p): res = [] for a in xrange(1, p): for b in xrange(a, p): c = sqrt(a*a + b*b) if a + b + c == p: res += [(a, b, c)] return res for p in xrange(3, 1000): t = n_triangles(p) if len(t) > 0: print p, len(t), t
Euler #38
#!/usr/bin/env python from libeuler import is_pandigital def concatenated_product(n, l): return reduce(lambda x, y: str(x) + str(y), map(lambda x: x*n, l), '') if __name__ == '__main__': r = [] n = 1 m = 9 while True: p = concatenated_product(n, range(1, m+1)) print "%d -> %s" % (n, p), range(1, m+1) if len(p) > 9: m -= 1 if m < 2: break continue if is_pandigital(int(p)): r += [int(p)] n += 1 print max(r)
Euler #36
#!/usr/bin/env python def is_palyndrome(s): return (s == reduce(lambda x,y: x+y, reversed(s), '')) def right_number(n): c1 = is_palyndrome(str(n)) c2 = is_palyndrome(bin(n)[2:]) if c1 and c2: return n else: return 0 if __name__ == '__main__': print reduce(lambda x, y: x+y, map(right_number, range(1000000)), 0)
vendredi 28 mai 2010
Generating badges for upcoming seminar ;)
#!/usr/bin/env python import sys from csv import reader from mako.template import Template def help(script_name): print "Usage: %s <csv-file> <badge-template>" % script_name def write_page(template, num, person): f = open('badges%05d.svg' % num, 'w') f.write(template.render(**person)) f.close() def process_file(csv_file, template_file): rows = reader(open(csv_file, "rb")) template = Template(filename=template_file) person_cnt = 0 pages_cnt = 1 person = dict() for row in rows: person['name%d' % person_cnt] = row[0].strip() person['surname%d' % person_cnt] = row[1].strip() person['organization%d' % person_cnt] = row[2].strip() person_cnt += 1 if person_cnt == 4: write_page(template, pages_cnt, person) person_cnt = 0 pages_cnt += 1 if person_cnt != 0: write_page(template, pages_cnt, person) if __name__ == '__main__': if len(sys.argv) < 3: help() else: process_file(sys.argv[1], sys.argv[2])
mardi 25 mai 2010
FOP & Jython
#!/usr/bin/env jython import sys from java.io import File, FileOutputStream, BufferedOutputStream # JAXP from javax.xml.transform import Transformer, TransformerFactory, Source, Result from javax.xml.transform.stream import StreamSource from javax.xml.transform.sax import SAXResult # FOP from org.apache.fop.apps import FOUserAgent, Fop, FopFactory, MimeConstants xmlfile = File("projectteam.xml") xsltfile = File("projectteam2fo.xsl") pdffile = File("out.pdf") fopFactory = FopFactory.newInstance() foUserAgent = fopFactory.newFOUserAgent() out = FileOutputStream(pdffile) out = BufferedOutputStream(out) fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out) factory = TransformerFactory.newInstance() transformer = factory.newTransformer(StreamSource(xsltfile)) transformer.setParameter("versionParam", "2.0"); src = StreamSource(xmlfile) res = SAXResult(fop.getDefaultHandler()) transformer.transform(src, res) out.close()Quite funny, but there's the bug in Jython ClassLoader so we have to place all FOP jars in CLASSPATH instead of sys.path.append(...) way.
lundi 3 mai 2010
Project Euler #35
let is_prime n = if n < 0 then false else let lim = int_of_float (sqrt (float_of_int n)) in let rec check_mod i l = if i > l then true else if n mod i = 0 then false else true && (check_mod (succ i) l) in check_mod 2 lim;; let primes n = let rec inner_primes i = if i > n then [] else if is_prime i then [i] @ inner_primes (succ i) else inner_primes (succ i) in inner_primes 2;; let circulations n = let rec circulate str = let str_len = String.length str in if str_len = 1 then [int_of_string n] else let variant = (String.sub str 1 (str_len - 1)) ^ (String.sub str 0 1) in if variant = n then [(int_of_string variant)] else [(int_of_string variant)] @ (circulate variant) in circulate n;; (* let is_circular n primes = let number_string = string_of_int n in let variants = circulations number_string in List.fold_left
(&&)
true
(List.map
(fun x -> List.exists (fun y -> (x = y)) primes)
variants);; *) let is_circular n = let number_string = string_of_int n in let variants = circulations number_string in List.fold_left (&&) true (List.map (is_prime) variants);; let primes_till_1e6 = primes 1000000;; let test_primes = primes_till_1e6;; Printf.printf "%d\n" (List.fold_left (+) 0 (List.map (fun x -> if (is_circular x) then 1 else 0 ) test_primes));;Strange thing: List.exists is quite slow, so when I switched from using List.exists (commented out) to just plain is_prime in is_circular it became possible to get result in a minute. Or maybe I just can't use List.exists properly.
samedi 1 mai 2010
Project Euler #27
#load "nums.cma" open Big_int;; type triple = { a: big_int; b: big_int; len: big_int };; let is_prime n = if lt_big_int n zero_big_int then false else let lim = sqrt_big_int n in let rec check_mod i l = if gt_big_int i l then true else if eq_big_int (mod_big_int n i) zero_big_int then false else true && (check_mod (succ_big_int i) l) in check_mod (big_int_of_int 2) lim;; let primes n = let rec inner_primes i = if gt_big_int i n then [] else if is_prime i then [i] @ inner_primes (succ_big_int i) else inner_primes (succ_big_int i) in inner_primes (big_int_of_int 2);; let make_form a b = fun n -> add_big_int (mult_big_int n n) (add_big_int (mult_big_int a n) b);; let sequence_length f = let rec advance_sequence n = if not (is_prime (f n)) then zero_big_int else add_big_int unit_big_int (advance_sequence (succ_big_int n)) in advance_sequence (big_int_of_int 0);; let triple_max a b = if gt_big_int a.len b.len then a else b;; let find_longest_sequence i1 i2 n = let rec make_lengths_list i = if gt_big_int i i2 then [] else [{ a=i; b=n; len=sequence_length (make_form i n); }] @ (make_lengths_list (succ_big_int i)) in List.fold_left (triple_max) { a=zero_big_int; b=zero_big_int; len=zero_big_int; } (make_lengths_list i1);; let bs = primes (big_int_of_int 1000);; let a1 = big_int_of_string "-999";; let a2 = big_int_of_string "999";; let max_ab = List.fold_left (triple_max) { a=zero_big_int; b=zero_big_int; len=zero_big_int; } (List.map (find_longest_sequence a1 a2) bs);; Printf.printf "%s\n" (string_of_big_int (mult_big_int max_ab.a max_ab.b));;
jeudi 29 avril 2010
Project Euler #29
#load "nums.cma";; open Big_int;; let rec generate_combinations a1 a2 b1 b2 = let rec generate_single_number a b lim = if gt_big_int b lim then [] else [power_big_int_positive_big_int a b] @ generate_single_number a (succ_big_int b) lim in if gt_big_int a1 a2 then [] else (generate_single_number a1 b1 b2) @ (generate_combinations (succ_big_int a1) a2 b1 b2);; let rec uniq lst = match lst with [] -> [] | hd :: tl when List.exists (fun x -> eq_big_int x hd) tl -> uniq tl | hd :: tl -> [hd] @ uniq tl;; let a1 = big_int_of_int 2;; let a2 = big_int_of_int 100;; let b1 = big_int_of_int 2;; let b2 = big_int_of_int 100;; Printf.printf "%d\n" (List.length (uniq (generate_combinations a1 a2 b1 b2)));;Quick to come up but not so fast uniq function.
mercredi 28 avril 2010
Project Euler #28
let make_spiral n = if n mod 2 = 0 then raise (Invalid_argument "Size should be odd"); let res = Array.make_matrix n n 0 in let last_value = n * n in let current_value = ref 1 in let i = ref (n / 2) in let j = ref (n / 2) in let shift = ref 1 in let delta = ref 1 in res.(!i).(!j) <- !current_value; while !current_value < last_value do for k = 1 to !shift do if !current_value < last_value then begin j := !j + !delta; current_value := !current_value + 1; res.(!i).(!j) <- !current_value; end; done; for k = 1 to !shift do if !current_value < last_value then begin i := !i + !delta; current_value := !current_value + 1; res.(!i).(!j) <- !current_value; end; done; delta := - !delta; shift := !shift + 1; done; res;; let sum_diagonals arr = let size = Array.length arr in let sum = ref 0 in for i = 0 to size - 1 do sum := !sum + arr.(i).(i) + arr.(i).(size - 1 - i) done; !sum - 1;; Printf.printf "%d\n" (sum_diagonals (make_spiral 1001));;Very bad OCaml ;)
lundi 26 avril 2010
Project Euler #23
(* generates array with values [1..n] *) let rec range_array n = if n == 1 then [| n |] else Array.append (range_array (n - 1)) [| n |];; (* calculates sum of proper divisors of given number *) let sum_of_proper_divisors n = let limit = n / 2 in let rec sum_divisors k l = if k > l then 0 else if n mod k = 0 then k + sum_divisors (k + 1) l else sum_divisors (k + 1) l in if n = 1 then 1 else sum_divisors 1 limit;; (* checks whether given number is abundant*) let is_abundant n = n < sum_of_proper_divisors n;; (* generates array of abundant number less than given number *) let find_abundant_numbers n = let rec gen_numbers k = if k = n then [||] else if is_abundant k then Array.append [| k |] (gen_numbers (k + 1)) else gen_numbers (k + 1) in gen_numbers 12;; let binary_search (data:'a array) elem = let rec iter a b = if a = b then -1 else let median = a + (b - a)/2 in match data.(median) with | value when value = elem -> median | value when value < elem -> iter (median + 1) b | _ -> iter a median in iter 0 (Array.length data);; let make_possible_sums a = let len = (Array.length a) - 1 in let res = Array.make_matrix (len + 1) (len + 1) 0 in for i = 0 to len do for j = i to len do res.(i).(j) <- a.(i) + a.(j) done done; res;; (* sets all elements of a found in s to 0 *) let refine_array a s = let to_delete = Array.make (Array.length a) false in let l1 = Array.length s in let l2 = Array.length s.(0) in for i = 0 to l1 - 1 do for j = 0 to l2 - 1 do let idx = binary_search a s.(i).(j) in if idx != -1 then to_delete.(idx) <- true done done; for i = 0 to (Array.length to_delete) - 1 do if to_delete.(i) then a.(i) <- 0 done;; let all_numbers = range_array 28123;; let abundant_numbers_sums = make_possible_sums (find_abundant_numbers 28123);; refine_array all_numbers abundant_numbers_sums;; Printf.printf "%d\n" (Array.fold_left (+) 0 all_numbers);;Straightforward and very slow but correct solution ;)
vendredi 23 avril 2010
Project Euler #21
let proper_divisors_sum n = let limit = n / 2 in let rec proper_divisors_list n k = if k > limit then [] else if n mod k = 0 then [k] @ (proper_divisors_list n (k + 1)) else proper_divisors_list n (k + 1) in List.fold_left (+) 0 (proper_divisors_list n 1);; let amicable_numbers_sum n = let rec amicable_numbers k = if k > n then [] else let b = proper_divisors_sum k in let a = proper_divisors_sum b in if (a != b) && (a = k) then [k] @ (amicable_numbers (k + 1)) else amicable_numbers (k + 1) in List.fold_left (+) 0 (amicable_numbers 2);; Printf.printf "%d\n" (amicable_numbers_sum 10000);;Quite straightforward and surely using lists ;) Actually we can sum without intermediate lists.
dimanche 18 avril 2010
Project Euler #24
(* swaps elements of indexes i and j in array a*) let swap a i j = let t = a.(i) in a.(i) <- a.(j); a.(j) <- t;; (* reverses part of array a from index i to the end of array*) let reverse a i = let l = (Array.length a) - 1 in for k = 0 to (l - i)/2 do swap a (i + k) (l - k) done;; (* generates next permutation of array *) let make_next_permutation a = let j = ref 0 in let l = ref 0 in for i = 0 to (Array.length a) - 2 do if a.(i) < a.(i+1) then j.contents <- i done; for i = 0 to (Array.length a) - 1 do if a.(!j) < a.(i) then l.contents <- i done; swap a !j !l; reverse a (!j+1);; let make_permutations a = let t = ref 1 in while !t < 1000000 do make_next_permutation a; t := (!t + 1); done;; let t = [| 0; 1; 2; 3; 4; 5; 6; 7; 8; 9 |];; make_permutations t;; Array.iter (Printf.printf "%d") t;; Printf.printf "\n";;
http://en.wikipedia.org/wiki/Permutation#Systematic_generation_of_all_permutations
Весьма императивное решение, с использованием ссылок.
lundi 12 avril 2010
Project Euler #22
#load "str.cma";; let char_value c = (int_of_char c) - (int_of_char 'A') + 1;; let word_value s = let word_length = String.length s in let rec sum_letters s n = if n == 0 then char_value s.[0] else (char_value s.[n]) + (sum_letters s (n-1)) in sum_letters s (word_length - 1);; let line_stream_of_channel channel = Stream.from (fun _ -> try Some (input_line channel) with End_of_file -> None);; let lines datafile = let xs = ref [] in Stream.iter (fun x -> xs := x :: !xs) (line_stream_of_channel (open_in datafile)); List.rev !xs;; let content = List.sort (String.compare) (List.map (fun x -> let l = String.length x in String.sub x 1 (l - 2)) (List.concat (List.map (Str.split (Str.regexp_string ",")) (lines (Sys.argv.(1))))));; let rec sum l n = match l with h :: t -> ((word_value h) * n) + (sum t (n+1)) | [] -> 0;; Printf.printf "%d\n" (sum content 1)
Project Euler #18 and #67
#load "str.cma";; #load "nums.cma";; let array_of_string delim s = Array.of_list (List.map (int_of_string) (Str.split (Str.regexp_string delim) s));; let line_stream_of_channel channel = Stream.from (fun _ -> try Some (input_line channel) with End_of_file -> None);; let lines datafile = let xs = ref [] in Stream.iter (fun x -> xs := x :: !xs) (line_stream_of_channel (open_in datafile)); List.rev !xs;; let content = Array.of_list (List.map (array_of_string " ") (lines (Sys.argv.(1))));; (* r1 - long array, r2 - short array *) let max_row r1 r2 = let lr2 = Array.length r2 in let sum = Array.make lr2 0 in for i = 0 to lr2 - 1 do sum.(i) <- max (r1.(i) + r2.(i)) (r1.(i+1) + r2.(i)) done; sum;; let calc_sum tr = let tl = Array.length tr in for n = tl - 1 downto 1 do tr.(n-1) <- (max_row tr.(n) tr.(n-1)) done; tr.(0).(0);; Printf.printf "%s\n" (string_of_int (calc_sum content))
jeudi 25 mars 2010
Project Euler #20
#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)))));;
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)Изначально пытался просто переделать двойной цикл с проверкой в рекурсию, в итоге оказалось проще перебрать числа в одной рекурсии.
Inscription à :
Articles (Atom)