From 3a1b108a11bd598ed765dfb37dbf521f84becce9 Mon Sep 17 00:00:00 2001 From: Gabriel Clark Date: Sun, 24 Sep 2017 15:47:57 -0400 Subject: [PATCH 1/9] HW1 initial commit --- HW1.fsx | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 HW1.fsx diff --git a/HW1.fsx b/HW1.fsx new file mode 100644 index 0000000..f29d857 --- /dev/null +++ b/HW1.fsx @@ -0,0 +1,61 @@ +(* +Jose Gabriel Perez +ex 1: could save gcd on reduce to avoid double calc on big nums +Also, finding common denom instead to reduce computing could be better for large numbers +*) + +let rec gcd = function +| (a,0) -> a +| (a,b) -> gcd (b, a % b) + +let reduce = function +| (a, b) -> (a/gcd(a,b), b/gcd(a,b)) + +let (.+) (a,b) (c,d) = reduce (a*d + b*c, b*d) +let (.*) (a,b) (c,d) = reduce (a*c, b*d) + +//ex2 +let revlists l = List.map List.rev l + +//ex3 Really banking on l1 and l2 having equal length +let interleave (l1, l2) = + let rec interHelp (r, l1, l2) = + match l1 with + | [] -> r + | x::xs -> interHelp (r @ (x::List.head l2::[]) , xs, List.tail l2) + interHelp([], l1, l2) + +//ex4 +let gencut(n, l1) = + let rec helpcut (n, a, b) = + if List.isEmpty b then (n, a, b) + elif List.length a < n then helpcut (n, a @ (List.head b :: []), List.tail b) + else (n, a, b) + let (_, f1, f2) = helpcut (n, [], l1) + (f1, f2) + +let cut l1 = gencut((List.length l1)/2, l1) + +//ex5 +let shuffle l = interleave (cut l) + +//ex6 +let countshuffles n = + let countaux(deck, target) = + let rec help (count, deck, target) = + if (deck = target) then (count, deck, target) + else help (count+1, shuffle deck, target) + let (r, _, _) = help (0, deck, target) + r + countaux(shuffle [1..n],[1..n]) + 1 + +//samples +interleave ([1;2;3],[4;5;6]);; +cut [1;2;3;4;5;6];; +shuffle [1;2;3;4];; +countshuffles 8;; + + +shuffle [1; 2; 3; 4; 5; 6; 7; 8];; +shuffle [1; 5; 2; 6; 3; 7; 4; 8];; +shuffle [1; 3; 5; 7; 2; 4; 6; 8];; \ No newline at end of file From 5d5f054171b81752c78b8fa652be5a8a81cbd3ab Mon Sep 17 00:00:00 2001 From: R4il Date: Mon, 25 Sep 2017 19:38:25 -0400 Subject: [PATCH 2/9] It was bad. --- HW1.fsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/HW1.fsx b/HW1.fsx index f29d857..61c8887 100644 --- a/HW1.fsx +++ b/HW1.fsx @@ -41,12 +41,9 @@ let shuffle l = interleave (cut l) //ex6 let countshuffles n = - let countaux(deck, target) = - let rec help (count, deck, target) = - if (deck = target) then (count, deck, target) - else help (count+1, shuffle deck, target) - let (r, _, _) = help (0, deck, target) - r + let rec countaux(deck, target) = + if deck = target then 0 + else 1 + countaux(shuffle deck, target) countaux(shuffle [1..n],[1..n]) + 1 //samples @@ -54,7 +51,7 @@ interleave ([1;2;3],[4;5;6]);; cut [1;2;3;4;5;6];; shuffle [1;2;3;4];; countshuffles 8;; - +countshuffles 52;; shuffle [1; 2; 3; 4; 5; 6; 7; 8];; shuffle [1; 5; 2; 6; 3; 7; 4; 8];; From ce7a7f7d1e5e374fdafcc80a370202a1b08c5583 Mon Sep 17 00:00:00 2001 From: Jpere Date: Tue, 26 Sep 2017 11:16:06 -0400 Subject: [PATCH 3/9] Interleave was awful too. Looking at making gencut better. --- HW1.fsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/HW1.fsx b/HW1.fsx index 61c8887..5c1f778 100644 --- a/HW1.fsx +++ b/HW1.fsx @@ -4,6 +4,7 @@ ex 1: could save gcd on reduce to avoid double calc on big nums Also, finding common denom instead to reduce computing could be better for large numbers *) +//ex1 let rec gcd = function | (a,0) -> a | (a,b) -> gcd (b, a % b) @@ -17,13 +18,11 @@ let (.*) (a,b) (c,d) = reduce (a*c, b*d) //ex2 let revlists l = List.map List.rev l -//ex3 Really banking on l1 and l2 having equal length -let interleave (l1, l2) = - let rec interHelp (r, l1, l2) = - match l1 with - | [] -> r - | x::xs -> interHelp (r @ (x::List.head l2::[]) , xs, List.tail l2) - interHelp([], l1, l2) +//ex3 Really banking on l1 and l2 having equal length, otherwise it will just do it up to the smaller size +let rec interleave = function +| ([], l) -> [] +| (l, []) -> [] +| (x::xs, y::ys) -> x:: y :: interleave(xs, ys) //ex4 let gencut(n, l1) = @@ -55,4 +54,4 @@ countshuffles 52;; shuffle [1; 2; 3; 4; 5; 6; 7; 8];; shuffle [1; 5; 2; 6; 3; 7; 4; 8];; -shuffle [1; 3; 5; 7; 2; 4; 6; 8];; \ No newline at end of file +shuffle [1; 3; 5; 7; 2; 4; 6; 8];; From f7a120320e4e60c0a3d6e3ec9b428e3617eb4c18 Mon Sep 17 00:00:00 2001 From: Jpere Date: Wed, 11 Oct 2017 09:22:48 -0400 Subject: [PATCH 4/9] Create HW2.fsx --- HW2.fsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 HW2.fsx diff --git a/HW2.fsx b/HW2.fsx new file mode 100644 index 0000000..c3ad380 --- /dev/null +++ b/HW2.fsx @@ -0,0 +1,17 @@ + +/// 4. Correctness of sort recursive function with respect to the Checklist for Programming with Recursion +(* +Step One: It is okay, because empty and single item lists are automatically sorted +Step Two: wrong, because even assuming that sort (x2::xs) returns the correct answer, + there is no guarantee that x1 is the minimun since it was only compared to x2 and + is not checked again. For a counter example sort [3;2;1];; will return [2;1;3;]. + All that this sort function really guarantees is that the largest element goes to the + end of the list. + (Note: Much like insertion sort, if it gets called n-1 times the list would be sorted) +Step Three: Each recursive call gets an input that is smaller than the original input +*) +let rec sort = function + | [] -> [] + | [x] -> [x] + | x1::x2::xs -> if x1 <= x2 then x1 :: sort (x2::xs) + else x2 :: sort (x1::xs) From ba9bd426d8c6f05debc6c6e3cd2bcdc459703b0f Mon Sep 17 00:00:00 2001 From: Jpere Date: Wed, 11 Oct 2017 09:24:47 -0400 Subject: [PATCH 5/9] Update HW2.fsx --- HW2.fsx | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/HW2.fsx b/HW2.fsx index c3ad380..dd2af4a 100644 --- a/HW2.fsx +++ b/HW2.fsx @@ -1,5 +1,24 @@ + (* Homework 2 +*) + +/// 1. Returns a list of pairs that represents the cartesian product +let rec cartesian(xs, ys) = + match xs, ys with + | (xs, []) -> [] + | ([], ys) -> [] + | (x::xs, ys) -> (List.map(fun y -> x,y) ys) @ (cartesian (xs,ys));; + +/// 2. Powerset set returns the set of all subsets of set +let rec powerset = function + | [] -> [[]] + | x::xs -> List.collect (fun subset -> [subset; x::subset]) (powerset xs) + +/// 3. Transpose an m-by-n matrix +let rec transpose = function + | (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M) + | _ -> [] -/// 4. Correctness of sort recursive function with respect to the Checklist for Programming with Recursion +//// 4. Correctness of sort recursive function with respect to the Checklist for Programming with Recursion (* Step One: It is okay, because empty and single item lists are automatically sorted Step Two: wrong, because even assuming that sort (x2::xs) returns the correct answer, @@ -15,3 +34,40 @@ let rec sort = function | [x] -> [x] | x1::x2::xs -> if x1 <= x2 then x1 :: sort (x2::xs) else x2 :: sort (x1::xs) + +/// 5. Analyze mergesort with respect to the Checking for Programming with Recursion (merge and split work correctly) +(* +Step One: It is okay, because empty lists are automatically sorted +Step Two: Non base case did not previously exist. Added as | [x] -> [x] in order to correct this +Step Three: Each recursive call gets an input that is smaller than the original input +Clue something is wrong: The mergesort function is missing a case, which causes mergesort to be seen by +the compiler as 'a list -> 'b list instead of 'a list -> 'a list +*) +let rec merge = function + | ([], ys) -> ys + | (xs, []) -> xs + | (x::xs, y::ys) -> if x < y then x :: merge (xs, y::ys) + else y :: merge (x::xs, ys) + +let rec split = function + | [] -> ([], []) + | [a] -> ([a], []) + | a::b::cs -> let (M,N) = split cs + (a::M, b::N) + +let rec mergesort = function + | [] -> [] + | [x] -> [x] //Bug corrected + | L -> let (M, N) = split L + merge (mergesort M, mergesort N) + +/// 6. Define F# function curry f that converts an uncurried function to a curried function, and +(* an F# uncurry f that does the opposite conversion *) +let curry f a b = f (a, b) +let uncurry f (a,b) = f a b + +(* +val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c +val uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c +*) + From 6a5e018765104f969d095bdd8054cd9799223258 Mon Sep 17 00:00:00 2001 From: Jpere Date: Wed, 11 Oct 2017 09:28:29 -0400 Subject: [PATCH 6/9] Fixing minor stuff --- HW2.fsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/HW2.fsx b/HW2.fsx index dd2af4a..6b0f5e8 100644 --- a/HW2.fsx +++ b/HW2.fsx @@ -1,4 +1,5 @@ - (* Homework 2 +(* Homework 2 + *) /// 1. Returns a list of pairs that represents the cartesian product @@ -40,6 +41,7 @@ let rec sort = function Step One: It is okay, because empty lists are automatically sorted Step Two: Non base case did not previously exist. Added as | [x] -> [x] in order to correct this Step Three: Each recursive call gets an input that is smaller than the original input + Clue something is wrong: The mergesort function is missing a case, which causes mergesort to be seen by the compiler as 'a list -> 'b list instead of 'a list -> 'a list *) @@ -70,4 +72,3 @@ let uncurry f (a,b) = f a b val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c val uncurry : ('a -> 'b -> 'c) -> 'a * 'b -> 'c *) - From 54aef80f55e122d59c279e22a1edfe02034efa4c Mon Sep 17 00:00:00 2001 From: Jpere Date: Wed, 11 Oct 2017 09:46:17 -0400 Subject: [PATCH 7/9] Update HW2.fsx --- HW2.fsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/HW2.fsx b/HW2.fsx index 6b0f5e8..bbb5bbe 100644 --- a/HW2.fsx +++ b/HW2.fsx @@ -22,12 +22,11 @@ let rec transpose = function //// 4. Correctness of sort recursive function with respect to the Checklist for Programming with Recursion (* Step One: It is okay, because empty and single item lists are automatically sorted -Step Two: wrong, because even assuming that sort (x2::xs) returns the correct answer, - there is no guarantee that x1 is the minimun since it was only compared to x2 and - is not checked again. For a counter example sort [3;2;1];; will return [2;1;3;]. - All that this sort function really guarantees is that the largest element goes to the - end of the list. - (Note: Much like insertion sort, if it gets called n-1 times the list would be sorted) +Step Two: wrong, because even assuming that sort (x2::xs) returns the correct answer, there is no guarantee + that x1 is the minimun since it was only compared to x2 and is not checked again. + For a counter example sort [3;2;1];; will return [2;1;3;]. + All that this sort function really guarantees is that the largest element goes to the end of the list. + (Note: works like the insertion step of insertion sort, if it gets called n-1 times the list would be sorted) Step Three: Each recursive call gets an input that is smaller than the original input *) let rec sort = function @@ -39,7 +38,8 @@ let rec sort = function /// 5. Analyze mergesort with respect to the Checking for Programming with Recursion (merge and split work correctly) (* Step One: It is okay, because empty lists are automatically sorted -Step Two: Non base case did not previously exist. Added as | [x] -> [x] in order to correct this +Step Two: If mergesort of M and N return the correct answer, then since split and merge are correct the non-base case + is correct too. There is a missing base case that leads to a bug, but step 2 is still satisfied. Step Three: Each recursive call gets an input that is smaller than the original input Clue something is wrong: The mergesort function is missing a case, which causes mergesort to be seen by From 705c42d053ace4224483d4bbcdd09459663f6ecd Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 29 Oct 2017 12:39:41 -0400 Subject: [PATCH 8/9] Added part of HW 3 --- HW3.fsx | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 HW3.fsx diff --git a/HW3.fsx b/HW3.fsx new file mode 100644 index 0000000..fc8b870 --- /dev/null +++ b/HW3.fsx @@ -0,0 +1,60 @@ +// 1 +let rec inner xs ys = + match (xs, ys) with + | ([x],[y]) -> x*y + | (x::xs, y::ys) -> x*y + inner xs ys + | (_, _)-> failwith "inner defined for equal sized lists only" + + + +// 2 using transpose from last HW +let rec transpose = function + | (_::_)::_ as M -> List.map List.head M :: transpose (List.map List.tail M) + | _ -> [] + +// Posible to improve this by transposing beforehand +let rec multiply = function +|([], _) -> [] +|(x::xs, ys) -> List.map (inner x) (transpose ys) :: multiply (xs, ys) + +// 3 +let flatten1 xs = List.fold (@) [] xs +let flatten2 xs = List.foldBack (@) xs [] +let makelistlist n = List.map (fun x -> [x]) [1..n] +#time +(*In practice flatten1 behaves as O(n^2) and flatten2 is (O(n))*) + +// 4 + +// 5 + +// 6 +type Exp = Num of int + | Neg of Exp + | Sum of Exp * Exp + | Diff of Exp * Exp + | Prod of Exp * Exp + | Quot of Exp * Exp + +let rec evaluate = function +| Num n -> Some n +| Neg e -> match evaluate e with + | None -> None + | Some n -> Some (-1 * n) +|Sum (e1, e2) -> match (evaluate e1, evaluate e2) with + |(None, _) -> None + |(_, None) -> None + |(Some n1, Some n2) -> Some (n1 + n2) +|Diff (e1, e2) -> match (evaluate e1, evaluate e2) with + |(None, _) -> None + |(_, None) -> None + |(Some n1, Some n2) -> Some (n1 - n2) +|Prod (e1, e2) -> match (evaluate e1, evaluate e2) with + |(None, _) -> None + |(_, None) -> None + |(Some n1, Some n2) -> Some (n1 * n2) +|Quot (e1, e2) -> match (evaluate e1, evaluate e2) with + |(None, _) -> None + |(_, None) -> None + |(_, Some 0) -> None + |(Some n1, Some n2) -> Some (n1 - n2) From 0b1edfb80822c4b6fa5344e232b8fcbd365eeacc Mon Sep 17 00:00:00 2001 From: Edward Terry Date: Mon, 6 Nov 2017 13:14:42 -0500 Subject: [PATCH 9/9] Added problems 4 and 5 to file HW3.fsx --- HW3.fsx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/HW3.fsx b/HW3.fsx index fc8b870..18f62ec 100644 --- a/HW3.fsx +++ b/HW3.fsx @@ -25,8 +25,29 @@ let makelistlist n = List.map (fun x -> [x]) [1..n] (*In practice flatten1 behaves as O(n^2) and flatten2 is (O(n))*) // 4 +(* + twice successor 0 would be 2 = 2^1 + twice twice successor 0 would be 4 = 2^2 + twice twice twice successor 0 would be 16 = 2^4 + And so on.. + + The current value becomes equals to 2 to the power of the previous value + + The function will be defined recursively, as follows: + f(n) = + if n = 0 then 1 + else 2 ^ (f(n-1)) + + We can write this function as: + let rec f = function + | 0 -> 1.0 + | n -> 2.0 ** (f (n-1));; +*) // 5 +type 'a stream = Cons of 'a * (unit -> 'a stream);; + +let rec map f (Cons(x, xsf)) = Cons (f x, fun() -> map f (xsf()));; // 6 type Exp = Num of int