Monday, October 7, 2013

Problem 49 - OCaml

So, functional languages are great and all, but this problem wasn't the most fun to do in a functional language / OCaml was a bit more annoying to work with than other functional languages (or maybe I just had less patience for it than others / needed to do something more complex my first time using it). But anyway, I got a pretty reasonable program written that solves Problem 49 in about .06 seconds, so not much to complain about. Here is the program, in all of its glory...Looking back, I think 90% of my annoyance with OCaml is the need to write List.map, etc for all the list operations that are so common in functional languages. But anyway, I digress.
open Printf

let dlist y =
let rec digilist x l =
    if x < 10 then x :: l 
    else (digilist (x / 10) ((x mod 10) :: l)) in
    digilist y [];;

let cdigs y =
let rec concatdigits l x =
    if l = [] then x 
    else concatdigits (List.tl l) (x * 10 + (List.hd l)) in
    concatdigits y 0;;

let isPrime x = 
let rec checkPrime y n = 
    if n * n > y then true 
    else if y mod n = 0 then false else checkPrime y (n +1) in
    checkPrime x 2;;

let rec rem x l = if l = [] then [] else if (List.hd l) = x then (List.tl l) 
                     else (List.hd l) :: (rem x (List.tl l));;

let rec permuts elems =
    if (List.tl elems) = [] then [[List.hd elems]] else 
    List.concat (List.map (fun (x) -> (List.map (fun (l) -> x :: l) 
                (permuts (rem x elems)))) elems);;
    
let rec validArith n perms =
    let rec helper n2 dif rest = 
        if rest = [] then []
        else if (List.hd rest) - n2 = dif then n :: n2 :: [List.hd rest]
        else helper n2 dif (List.tl rest) in
    if (List.length perms) = 1 then []
    else let help = helper (List.hd perms) ((List.hd perms) - n) (List.tl perms) in
        if List.length help = 3 then help
        else validArith n (List.tl perms);; 
    
let rec compress = function
    | a :: (b :: _ as t) -> if a = b then compress t else a :: compress t
    | smaller -> smaller;;

let rec findans n =
    if n = 10000 then [] else
    if isPrime n then
    let pperms = (List.filter (fun (z) -> z >= n) (compress (List.sort (fun x y -> x - y) 
        (List.filter isPrime (List.map cdigs (permuts (dlist n))))))) in
        if (List.length pperms) >= 3  && (n != 1487) && 
            (List.length (validArith (List.hd pperms) (List.tl pperms)) = 3)
            
        then validArith (List.hd pperms) (List.tl pperms)
        else findans (n + 1)
    else findans (n + 1);; 

List.iter (printf "%d") (findans 1100);
print_string "\n"

No comments:

Post a Comment