From e6dbf081942dd844e5d71c3180eb36035a5e8093 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Sun, 23 Feb 2025 17:09:57 +0300 Subject: [PATCH 1/9] add solutions --- .../Continuation/Continuation.fsproj | 16 +++++++++++++ .../Continuation/Continuation/EvenNumbers.fs | 8 +++++++ Tasks/Continuation/Continuation/ParseTree.fs | 24 +++++++++++++++++++ Tasks/Continuation/Continuation/Primes.fs | 10 ++++++++ Tasks/Continuation/Continuation/Tree.fs | 16 +++++++++++++ Tasks/Continuation/Continuation/TreeMap.fs | 8 +++++++ 6 files changed, 82 insertions(+) create mode 100644 Tasks/Continuation/Continuation/Continuation.fsproj create mode 100644 Tasks/Continuation/Continuation/EvenNumbers.fs create mode 100644 Tasks/Continuation/Continuation/ParseTree.fs create mode 100644 Tasks/Continuation/Continuation/Primes.fs create mode 100644 Tasks/Continuation/Continuation/Tree.fs create mode 100644 Tasks/Continuation/Continuation/TreeMap.fs diff --git a/Tasks/Continuation/Continuation/Continuation.fsproj b/Tasks/Continuation/Continuation/Continuation.fsproj new file mode 100644 index 0000000..790526b --- /dev/null +++ b/Tasks/Continuation/Continuation/Continuation.fsproj @@ -0,0 +1,16 @@ + + + + net9.0 + true + + + + + + + + + + + diff --git a/Tasks/Continuation/Continuation/EvenNumbers.fs b/Tasks/Continuation/Continuation/EvenNumbers.fs new file mode 100644 index 0000000..3f73368 --- /dev/null +++ b/Tasks/Continuation/Continuation/EvenNumbers.fs @@ -0,0 +1,8 @@ +namespace Continuation + +module EvenNumbers = + let countEvenNumbers1 () = Seq.map (fun x -> (x + 1) % 2) >> Seq.sum + + let countEvenNumbers2 () = Seq.filter (fun x -> x % 2 = 0) >> Seq.length + + let countEvenNumbers3 () = Seq.fold (fun acc x -> acc + (x + 1) % 2) 0 diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs new file mode 100644 index 0000000..65d5f3b --- /dev/null +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -0,0 +1,24 @@ +namespace Continuation + +module ParseTree = + type Node = + | Sum + | Difference + | Product + | Ratio + | Const of int + + let operation node = + match node with + | Sum -> ( + ) + | Difference -> ( - ) + | Product -> ( * ) + | Ratio -> ( / ) + | Const x -> fun _ _ -> x + + let rec evaluate tree = + match tree with + | Tree.Empty -> 0 + | Tree.Node (x, left, right) + -> let op = operation x + op (evaluate left) (evaluate right) diff --git a/Tasks/Continuation/Continuation/Primes.fs b/Tasks/Continuation/Continuation/Primes.fs new file mode 100644 index 0000000..7d3833d --- /dev/null +++ b/Tasks/Continuation/Continuation/Primes.fs @@ -0,0 +1,10 @@ +namespace Continuation + +module Primes = + let isPrime n = + { 2 .. int (sqrt (float n)) } |> Seq.exists (fun x -> n % x = 0) + + let primes () = + ( + ) 2 + |> Seq.initInfinite + |> Seq.filter isPrime diff --git a/Tasks/Continuation/Continuation/Tree.fs b/Tasks/Continuation/Continuation/Tree.fs new file mode 100644 index 0000000..769cdcb --- /dev/null +++ b/Tasks/Continuation/Continuation/Tree.fs @@ -0,0 +1,16 @@ +namespace Continuation + +module Tree = + type Tree<'a> = + | Empty + | Node of 'a * Tree<'a> * Tree<'a> + + type ContinuationStep<'a> = + | Done + | Step of 'a * (unit -> ContinuationStep<'a>) + + let rec linearize tree cont = + match tree with + | Empty -> cont () + | Node (curr, left, right) + -> Step (curr, (fun () -> linearize left (fun () -> linearize right cont))) diff --git a/Tasks/Continuation/Continuation/TreeMap.fs b/Tasks/Continuation/Continuation/TreeMap.fs new file mode 100644 index 0000000..22f9ae1 --- /dev/null +++ b/Tasks/Continuation/Continuation/TreeMap.fs @@ -0,0 +1,8 @@ +namespace Continuation + +module TreeMap = + let rec map mapping tree = + match tree with + | Tree.Empty -> Tree.Empty + | Tree.Node (x, left, right) + -> Tree.Node (mapping x, map mapping left, map mapping right) From d2b1b3656f4e34ecc705622ba93974b96c41aba7 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Tue, 25 Feb 2025 22:45:25 +0300 Subject: [PATCH 2/9] refactor --- .../Continuation/Continuation.fsproj | 1 - .../Continuation/Continuation/EvenNumbers.fs | 12 ++++--- Tasks/Continuation/Continuation/ParseTree.fs | 33 +++++++++---------- Tasks/Continuation/Continuation/Primes.fs | 17 +++++----- Tasks/Continuation/Continuation/Tree.fs | 16 --------- Tasks/Continuation/Continuation/TreeMap.fs | 17 ++++++---- 6 files changed, 42 insertions(+), 54 deletions(-) delete mode 100644 Tasks/Continuation/Continuation/Tree.fs diff --git a/Tasks/Continuation/Continuation/Continuation.fsproj b/Tasks/Continuation/Continuation/Continuation.fsproj index 790526b..1c4985e 100644 --- a/Tasks/Continuation/Continuation/Continuation.fsproj +++ b/Tasks/Continuation/Continuation/Continuation.fsproj @@ -6,7 +6,6 @@ - diff --git a/Tasks/Continuation/Continuation/EvenNumbers.fs b/Tasks/Continuation/Continuation/EvenNumbers.fs index 3f73368..cf41487 100644 --- a/Tasks/Continuation/Continuation/EvenNumbers.fs +++ b/Tasks/Continuation/Continuation/EvenNumbers.fs @@ -1,8 +1,10 @@ -namespace Continuation +module EvenNumbers -module EvenNumbers = - let countEvenNumbers1 () = Seq.map (fun x -> (x + 1) % 2) >> Seq.sum +let countEvenNumbers1: list -> int = + Seq.map (fun x -> (x + 1) % 2) >> Seq.sum - let countEvenNumbers2 () = Seq.filter (fun x -> x % 2 = 0) >> Seq.length +let countEvenNumbers2: list -> int = + Seq.filter (fun x -> x % 2 = 0) >> Seq.length - let countEvenNumbers3 () = Seq.fold (fun acc x -> acc + (x + 1) % 2) 0 +let countEvenNumbers3: list -> int = + Seq.fold (fun acc x -> acc + (x + 1) % 2) 0 diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs index 65d5f3b..d0e6a4a 100644 --- a/Tasks/Continuation/Continuation/ParseTree.fs +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -1,24 +1,23 @@ -namespace Continuation +module ParseTree -module ParseTree = - type Node = +type Expression = + | Const of int + | Operator of Operation * Expression * Expression +and Operation = | Sum | Difference | Product | Ratio - | Const of int - let operation node = - match node with - | Sum -> ( + ) - | Difference -> ( - ) - | Product -> ( * ) - | Ratio -> ( / ) - | Const x -> fun _ _ -> x +let operation op = + match op with + | Sum -> ( + ) + | Difference -> ( - ) + | Product -> ( * ) + | Ratio -> ( / ) - let rec evaluate tree = - match tree with - | Tree.Empty -> 0 - | Tree.Node (x, left, right) - -> let op = operation x - op (evaluate left) (evaluate right) +let rec evaluate expr = + match expr with + | Const x -> x + | Operator (op, left, right) -> + operation op (evaluate left) (evaluate right) diff --git a/Tasks/Continuation/Continuation/Primes.fs b/Tasks/Continuation/Continuation/Primes.fs index 7d3833d..1de36a6 100644 --- a/Tasks/Continuation/Continuation/Primes.fs +++ b/Tasks/Continuation/Continuation/Primes.fs @@ -1,10 +1,11 @@ -namespace Continuation +module Primes -module Primes = - let isPrime n = - { 2 .. int (sqrt (float n)) } |> Seq.exists (fun x -> n % x = 0) +let isPrime n = + { 2 .. int (sqrt (float n)) } + |> Seq.exists (fun x -> n % x = 0) + |> not - let primes () = - ( + ) 2 - |> Seq.initInfinite - |> Seq.filter isPrime +let primes () = + ( + ) 2 + |> Seq.initInfinite + |> Seq.filter isPrime diff --git a/Tasks/Continuation/Continuation/Tree.fs b/Tasks/Continuation/Continuation/Tree.fs deleted file mode 100644 index 769cdcb..0000000 --- a/Tasks/Continuation/Continuation/Tree.fs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Continuation - -module Tree = - type Tree<'a> = - | Empty - | Node of 'a * Tree<'a> * Tree<'a> - - type ContinuationStep<'a> = - | Done - | Step of 'a * (unit -> ContinuationStep<'a>) - - let rec linearize tree cont = - match tree with - | Empty -> cont () - | Node (curr, left, right) - -> Step (curr, (fun () -> linearize left (fun () -> linearize right cont))) diff --git a/Tasks/Continuation/Continuation/TreeMap.fs b/Tasks/Continuation/Continuation/TreeMap.fs index 22f9ae1..167b719 100644 --- a/Tasks/Continuation/Continuation/TreeMap.fs +++ b/Tasks/Continuation/Continuation/TreeMap.fs @@ -1,8 +1,11 @@ -namespace Continuation +module TreeMap -module TreeMap = - let rec map mapping tree = - match tree with - | Tree.Empty -> Tree.Empty - | Tree.Node (x, left, right) - -> Tree.Node (mapping x, map mapping left, map mapping right) +type Tree<'a> = + | Empty + | Node of 'a * Tree<'a> * Tree<'a> + +let rec map mapping tree = + match tree with + | Empty -> Empty + | Node (value, left, right) -> + Node (mapping value, map mapping left, map mapping right) From 437c0eb627ec39469cea1ab18ee2c2a1f295ebd8 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Wed, 26 Feb 2025 00:08:31 +0300 Subject: [PATCH 3/9] add tests for even numbers functions --- .../Continuation.Tests.fsproj | 24 ++++++++++++++++ .../Continuation.Tests/EvenNumbersTests.fs | 28 +++++++++++++++++++ .../Continuation.Tests/Program.fs | 4 +++ Tasks/Continuation/Continuation.sln | 28 +++++++++++++++++++ .../Continuation/Continuation/EvenNumbers.fs | 14 ++++++---- 5 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj create mode 100644 Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs create mode 100644 Tasks/Continuation/Continuation.Tests/Program.fs create mode 100644 Tasks/Continuation/Continuation.sln diff --git a/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj b/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj new file mode 100644 index 0000000..5f0d997 --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj @@ -0,0 +1,24 @@ + + + net9.0 + latest + false + false + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs b/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs new file mode 100644 index 0000000..56ee98e --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs @@ -0,0 +1,28 @@ +module EvenNumbersTests + +open NUnit.Framework +open FsUnit +open FsCheck +open FsCheck.NUnit + +open EvenNumbers + +[] +let TestEvenNumbers_Map () = + countEvenNumbers_Map [] |> should equal 0 + countEvenNumbers_Map [1; 5; -3; 5; 77; 9] |> should equal 0 + countEvenNumbers_Map [4; 6; 8; 8] |> should equal 4 + countEvenNumbers_Map [0; 0; 1; 2; 3] |> should equal 3 + countEvenNumbers_Map [56592; -321321; 898934; 90901; -137] |> should equal 2 + countEvenNumbers_Map [2147483647] |> should equal 0 + +[] +let areEquivalent_MapAndFilter (list: list) = + countEvenNumbers_Map list = countEvenNumbers_Filter list + +[] +let areEquivalent_FilterAndFold (list: list) = + countEvenNumbers_Filter list = countEvenNumbers_Fold list + +Check.QuickThrowOnFailure areEquivalent_MapAndFilter +Check.QuickThrowOnFailure areEquivalent_FilterAndFold diff --git a/Tasks/Continuation/Continuation.Tests/Program.fs b/Tasks/Continuation/Continuation.Tests/Program.fs new file mode 100644 index 0000000..96b133f --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/Program.fs @@ -0,0 +1,4 @@ +module Program + +[] +let main _ = 0 diff --git a/Tasks/Continuation/Continuation.sln b/Tasks/Continuation/Continuation.sln new file mode 100644 index 0000000..9e704d1 --- /dev/null +++ b/Tasks/Continuation/Continuation.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Continuation", "Continuation\Continuation.fsproj", "{F1533830-EECE-4FFF-AA1F-640C75003521}" +EndProject +Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Continuation.Tests", "Continuation.Tests\Continuation.Tests.fsproj", "{06E91877-A8A4-4068-A038-566B457A95E2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F1533830-EECE-4FFF-AA1F-640C75003521}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1533830-EECE-4FFF-AA1F-640C75003521}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1533830-EECE-4FFF-AA1F-640C75003521}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1533830-EECE-4FFF-AA1F-640C75003521}.Release|Any CPU.Build.0 = Release|Any CPU + {06E91877-A8A4-4068-A038-566B457A95E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06E91877-A8A4-4068-A038-566B457A95E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06E91877-A8A4-4068-A038-566B457A95E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06E91877-A8A4-4068-A038-566B457A95E2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/Tasks/Continuation/Continuation/EvenNumbers.fs b/Tasks/Continuation/Continuation/EvenNumbers.fs index cf41487..977e0f9 100644 --- a/Tasks/Continuation/Continuation/EvenNumbers.fs +++ b/Tasks/Continuation/Continuation/EvenNumbers.fs @@ -1,10 +1,14 @@ module EvenNumbers -let countEvenNumbers1: list -> int = - Seq.map (fun x -> (x + 1) % 2) >> Seq.sum +let ( %% ) x y = + let rem = x % y + if rem >= 0 then rem else rem + y -let countEvenNumbers2: list -> int = +let countEvenNumbers_Map: list -> int = + Seq.map (fun x -> (x + 1) %% 2) >> Seq.sum + +let countEvenNumbers_Filter: list -> int = Seq.filter (fun x -> x % 2 = 0) >> Seq.length -let countEvenNumbers3: list -> int = - Seq.fold (fun acc x -> acc + (x + 1) % 2) 0 +let countEvenNumbers_Fold: list -> int = + Seq.fold (fun acc x -> acc + (x + 1) %% 2) 0 From 5feba7b0f0d79180ee6c87356c6a4d3473504482 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Wed, 26 Feb 2025 19:15:19 +0300 Subject: [PATCH 4/9] add tests --- .../Continuation.Tests.fsproj | 3 ++ .../Continuation.Tests/EvenNumbersTests.fs | 2 +- .../Continuation.Tests/ParseTreeTests.fs | 31 +++++++++++++++++++ .../Continuation.Tests/PrimesTests.fs | 28 +++++++++++++++++ .../Continuation.Tests/TreeMapTests.fs | 26 ++++++++++++++++ Tasks/Continuation/Continuation/Primes.fs | 8 +++-- 6 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs create mode 100644 Tasks/Continuation/Continuation.Tests/PrimesTests.fs create mode 100644 Tasks/Continuation/Continuation.Tests/TreeMapTests.fs diff --git a/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj b/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj index 5f0d997..310607d 100644 --- a/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj +++ b/Tasks/Continuation/Continuation.Tests/Continuation.Tests.fsproj @@ -6,7 +6,10 @@ false + + + diff --git a/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs b/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs index 56ee98e..9852775 100644 --- a/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs +++ b/Tasks/Continuation/Continuation.Tests/EvenNumbersTests.fs @@ -8,7 +8,7 @@ open FsCheck.NUnit open EvenNumbers [] -let TestEvenNumbers_Map () = +let testEvenNumbers_Map () = countEvenNumbers_Map [] |> should equal 0 countEvenNumbers_Map [1; 5; -3; 5; 77; 9] |> should equal 0 countEvenNumbers_Map [4; 6; 8; 8] |> should equal 4 diff --git a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs new file mode 100644 index 0000000..3f85a1a --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs @@ -0,0 +1,31 @@ +module ParseTreeTests + +open NUnit.Framework +open FsUnit +open System + +open ParseTree + +[] +let testEvaluate () = + let ``1 + 1`` = Operator (Sum, Const 1, Const 1) + let ``25 - 100`` = Operator (Difference, Const 25, Const 100) + let ``8 * 5`` = Operator (Product, Const 8, Const 5) + let ``8 * 5 + 25 - 100`` = Operator (Sum, ``8 * 5``, ``25 - 100``) + let ``14 / (1 + 1)`` = Operator (Ratio, Const 14, ``1 + 1``) + let ``14 / (1 + 1) - 9`` = Operator (Difference, ``14 / (1 + 1)``, Const 9) + let ``3 * (14 / (1 + 1) - 9)`` = Operator (Product, Const 3, ``14 / (1 + 1) - 9``) + let ``321 * 0`` = Operator (Product, Const 321, Const 0) + let ``0 / 0`` = Operator (Ratio, Const 0, Const 0) + let ``(1 + 1) / (321 * 0)`` = Operator (Ratio, ``1 + 1``, ``321 * 0``) + + evaluate ``1 + 1`` |> should equal 2 + evaluate ``25 - 100`` |> should equal -75 + evaluate ``8 * 5`` |> should equal 40 + evaluate ``8 * 5 + 25 - 100`` |> should equal -35 + evaluate ``14 / (1 + 1)`` |> should equal 7 + evaluate ``14 / (1 + 1) - 9`` |> should equal -2 + evaluate ``3 * (14 / (1 + 1) - 9)`` |> should equal -6 + evaluate ``321 * 0`` |> should equal 0 + (fun () -> evaluate ``0 / 0`` |> ignore) |> should throw typeof + (fun () -> evaluate ``(1 + 1) / (321 * 0)`` |> ignore) |> should throw typeof diff --git a/Tasks/Continuation/Continuation.Tests/PrimesTests.fs b/Tasks/Continuation/Continuation.Tests/PrimesTests.fs new file mode 100644 index 0000000..50d2697 --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/PrimesTests.fs @@ -0,0 +1,28 @@ +module PrimesTests + +open NUnit.Framework +open FsUnit + +open Primes + +[] +let testIsPrime () = + isPrime 0 |> should be False + isPrime 1 |> should be False + isPrime 2 |> should be True + isPrime 3 |> should be True + isPrime 73 |> should be True + isPrime 32132 |> should be False + isPrime -9091 |> should be False + isPrime 115249 |> should be True + +[] +let testPrimes () = + let primes = primes () + primes |> Seq.take 10 |> should equal (seq { 2; 3; 5; 7; 11; 13; 17; 19; 23; 29 }) + primes |> Seq.item 41 |> should equal 181 + primes |> Seq.item 978 |> should equal 7717 + let primes = Seq.take 100000 primes + primes |> should be ascending + primes |> should be unique + primes |> Seq.filter isPrime |> should equal primes diff --git a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs new file mode 100644 index 0000000..0b0c2b8 --- /dev/null +++ b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs @@ -0,0 +1,26 @@ +module TreeMapTests + +open NUnit.Framework +open FsUnit + +open TreeMap + +[] +let testTreeMap () = + let strTree = + Node ("abc", + Node ("", Empty, Node ("21321", Empty, Empty)), + Node ("ololo332", Empty, Empty)) + let lenTree = + Node (3, + Node (0, Empty, Node (5, Empty, Empty)), + Node (8, Empty, Empty)) + let intTree = + Node (1, Empty, Node (2, Empty, Node (3, Empty, Node (4, Empty, Empty)))) + let squaresTree = + Node (1, Empty, Node (4, Empty, Node (9, Empty, Node (16, Empty, Empty)))) + + map (fun x -> x * 5) Empty |> should equal Tree.Empty + map sqrt (Node (9.0, Empty, Empty)) |> should equal (Node (3.0, Empty, Empty)) + map String.length strTree |> should equal lenTree + map (fun x -> x * x) intTree |> should equal squaresTree diff --git a/Tasks/Continuation/Continuation/Primes.fs b/Tasks/Continuation/Continuation/Primes.fs index 1de36a6..b5145ae 100644 --- a/Tasks/Continuation/Continuation/Primes.fs +++ b/Tasks/Continuation/Continuation/Primes.fs @@ -1,9 +1,11 @@ module Primes let isPrime n = - { 2 .. int (sqrt (float n)) } - |> Seq.exists (fun x -> n % x = 0) - |> not + if n >= 2 then + { 2 .. int (sqrt (float n)) } + |> Seq.exists (fun x -> n % x = 0) + |> not + else false let primes () = ( + ) 2 From 42902b26c231cf305cddae00b28ccbdc688411fb Mon Sep 17 00:00:00 2001 From: bygu4 Date: Tue, 15 Apr 2025 23:35:23 +0300 Subject: [PATCH 5/9] use cps with trees, update tests --- .../Continuation.Tests/ParseTreeTests.fs | 9 +++++++++ .../Continuation.Tests/TreeMapTests.fs | 17 ++++++++++++++++- Tasks/Continuation/Continuation/ParseTree.fs | 15 +++++++++++---- Tasks/Continuation/Continuation/TreeMap.fs | 15 +++++++++++---- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs index 3f85a1a..bd94065 100644 --- a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs +++ b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs @@ -19,6 +19,7 @@ let testEvaluate () = let ``0 / 0`` = Operator (Ratio, Const 0, Const 0) let ``(1 + 1) / (321 * 0)`` = Operator (Ratio, ``1 + 1``, ``321 * 0``) + evaluate (Const 0) |> should equal 0 evaluate ``1 + 1`` |> should equal 2 evaluate ``25 - 100`` |> should equal -75 evaluate ``8 * 5`` |> should equal 40 @@ -29,3 +30,11 @@ let testEvaluate () = evaluate ``321 * 0`` |> should equal 0 (fun () -> evaluate ``0 / 0`` |> ignore) |> should throw typeof (fun () -> evaluate ``(1 + 1) / (321 * 0)`` |> ignore) |> should throw typeof + +[] +let testEvaluateWithLargeExpression () = + let treeDepth = 10000 + { 1 .. treeDepth } + |> Seq.fold (fun node _ -> Operator (Sum, node, Const 1)) (Const 1) + |> evaluate + |> should equal (treeDepth + 1) diff --git a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs index 0b0c2b8..266cff4 100644 --- a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs +++ b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs @@ -20,7 +20,22 @@ let testTreeMap () = let squaresTree = Node (1, Empty, Node (4, Empty, Node (9, Empty, Node (16, Empty, Empty)))) - map (fun x -> x * 5) Empty |> should equal Tree.Empty + map (( * ) 5) Empty |> should equal Tree.Empty + map (( = ) 0) (Node (0, Empty, Empty)) |> should equal (Node (true, Empty, Empty)) map sqrt (Node (9.0, Empty, Empty)) |> should equal (Node (3.0, Empty, Empty)) map String.length strTree |> should equal lenTree map (fun x -> x * x) intTree |> should equal squaresTree + +[] +let testMapWithLargeTree () = + let treeDepth = 10000 + let sourceTree = + { 1 .. treeDepth } + |> Seq.fold (fun node _ -> Node (1, node, Empty)) Empty + let resultTree = + { 1 .. treeDepth } + |> Seq.fold (fun node _ -> Node (8, node, Empty)) Empty + + sourceTree + |> map (( + ) 7) + |> should equal resultTree diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs index d0e6a4a..0fa65ea 100644 --- a/Tasks/Continuation/Continuation/ParseTree.fs +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -17,7 +17,14 @@ let operation op = | Ratio -> ( / ) let rec evaluate expr = - match expr with - | Const x -> x - | Operator (op, left, right) -> - operation op (evaluate left) (evaluate right) + let rec evaluateInternal expr cont = + match expr with + | Const x -> cont x + | Operator (op, left, right) -> + evaluateInternal left (fun leftValue -> + evaluateInternal right (fun rightValue -> + operation op leftValue rightValue |> cont + ) + ) + + evaluateInternal expr id diff --git a/Tasks/Continuation/Continuation/TreeMap.fs b/Tasks/Continuation/Continuation/TreeMap.fs index 167b719..bb18c86 100644 --- a/Tasks/Continuation/Continuation/TreeMap.fs +++ b/Tasks/Continuation/Continuation/TreeMap.fs @@ -5,7 +5,14 @@ type Tree<'a> = | Node of 'a * Tree<'a> * Tree<'a> let rec map mapping tree = - match tree with - | Empty -> Empty - | Node (value, left, right) -> - Node (mapping value, map mapping left, map mapping right) + let rec mapInternal tree mapping cont = + match tree with + | Empty -> cont Empty + | Node (value, left, right) -> + mapInternal left mapping (fun mappedLeft -> + mapInternal right mapping (fun mappedRight -> + Node (mapping value, mappedLeft, mappedRight) |> cont + ) + ) + + mapInternal tree mapping id From 888e3e36104d2ca5c89e3d185fe31934f534a445 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Wed, 16 Apr 2025 00:18:32 +0300 Subject: [PATCH 6/9] fix tests --- Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs | 2 +- Tasks/Continuation/Continuation.Tests/TreeMapTests.fs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs index bd94065..88048ac 100644 --- a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs +++ b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs @@ -33,7 +33,7 @@ let testEvaluate () = [] let testEvaluateWithLargeExpression () = - let treeDepth = 10000 + let treeDepth = 1000 { 1 .. treeDepth } |> Seq.fold (fun node _ -> Operator (Sum, node, Const 1)) (Const 1) |> evaluate diff --git a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs index 266cff4..37bd800 100644 --- a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs +++ b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs @@ -28,7 +28,7 @@ let testTreeMap () = [] let testMapWithLargeTree () = - let treeDepth = 10000 + let treeDepth = 1000 let sourceTree = { 1 .. treeDepth } |> Seq.fold (fun node _ -> Node (1, node, Empty)) Empty From 81170d6452f4a73ec4717885a1686db36a6d6527 Mon Sep 17 00:00:00 2001 From: bygu4 Date: Thu, 1 May 2025 01:27:06 +0300 Subject: [PATCH 7/9] minor changes --- Tasks/Continuation/Continuation/ParseTree.fs | 11 ++++++----- Tasks/Continuation/Continuation/TreeMap.fs | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs index 0fa65ea..09b7180 100644 --- a/Tasks/Continuation/Continuation/ParseTree.fs +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -16,15 +16,16 @@ let operation op = | Product -> ( * ) | Ratio -> ( / ) -let rec evaluate expr = - let rec evaluateInternal expr cont = +let evaluate expr = + + let rec evaluate expr cont = match expr with | Const x -> cont x | Operator (op, left, right) -> - evaluateInternal left (fun leftValue -> - evaluateInternal right (fun rightValue -> + evaluate left (fun leftValue -> + evaluate right (fun rightValue -> operation op leftValue rightValue |> cont ) ) - evaluateInternal expr id + in evaluate expr id diff --git a/Tasks/Continuation/Continuation/TreeMap.fs b/Tasks/Continuation/Continuation/TreeMap.fs index bb18c86..a70df97 100644 --- a/Tasks/Continuation/Continuation/TreeMap.fs +++ b/Tasks/Continuation/Continuation/TreeMap.fs @@ -4,15 +4,16 @@ type Tree<'a> = | Empty | Node of 'a * Tree<'a> * Tree<'a> -let rec map mapping tree = - let rec mapInternal tree mapping cont = +let map mapping tree = + + let rec map mapping tree cont = match tree with | Empty -> cont Empty | Node (value, left, right) -> - mapInternal left mapping (fun mappedLeft -> - mapInternal right mapping (fun mappedRight -> + map mapping left (fun mappedLeft -> + map mapping right (fun mappedRight -> Node (mapping value, mappedLeft, mappedRight) |> cont ) ) - mapInternal tree mapping id + in map mapping tree id From 2c4418245adc8aad7663669b82cf36bb6cd5400e Mon Sep 17 00:00:00 2001 From: bygu4 Date: Thu, 1 May 2025 18:01:12 +0300 Subject: [PATCH 8/9] enable tail call optimization in props, update tests --- .../Continuation.Tests/ParseTreeTests.fs | 2 +- .../Continuation.Tests/TreeMapTests.fs | 5 +-- .../Continuation/Continuation.fsproj | 1 + Tasks/Continuation/Continuation/ParseTree.fs | 21 ++++++------ Tasks/Continuation/Continuation/TreeMap.fs | 34 +++++++++++++------ 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs index 88048ac..f302dd3 100644 --- a/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs +++ b/Tasks/Continuation/Continuation.Tests/ParseTreeTests.fs @@ -33,7 +33,7 @@ let testEvaluate () = [] let testEvaluateWithLargeExpression () = - let treeDepth = 1000 + let treeDepth = 1000000 { 1 .. treeDepth } |> Seq.fold (fun node _ -> Operator (Sum, node, Const 1)) (Const 1) |> evaluate diff --git a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs index 37bd800..72bf060 100644 --- a/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs +++ b/Tasks/Continuation/Continuation.Tests/TreeMapTests.fs @@ -28,7 +28,7 @@ let testTreeMap () = [] let testMapWithLargeTree () = - let treeDepth = 1000 + let treeDepth = 1000000 let sourceTree = { 1 .. treeDepth } |> Seq.fold (fun node _ -> Node (1, node, Empty)) Empty @@ -38,4 +38,5 @@ let testMapWithLargeTree () = sourceTree |> map (( + ) 7) - |> should equal resultTree + |> areEqual resultTree + |> should be True diff --git a/Tasks/Continuation/Continuation/Continuation.fsproj b/Tasks/Continuation/Continuation/Continuation.fsproj index 1c4985e..1078db1 100644 --- a/Tasks/Continuation/Continuation/Continuation.fsproj +++ b/Tasks/Continuation/Continuation/Continuation.fsproj @@ -3,6 +3,7 @@ net9.0 true + true diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs index 09b7180..016b088 100644 --- a/Tasks/Continuation/Continuation/ParseTree.fs +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -16,16 +16,15 @@ let operation op = | Product -> ( * ) | Ratio -> ( / ) -let evaluate expr = - - let rec evaluate expr cont = - match expr with - | Const x -> cont x - | Operator (op, left, right) -> - evaluate left (fun leftValue -> - evaluate right (fun rightValue -> - operation op leftValue rightValue |> cont - ) +[] +let rec evaluateCPS expr cont = + match expr with + | Const x -> cont x + | Operator (op, left, right) -> + evaluateCPS left (fun leftValue -> + evaluateCPS right (fun rightValue -> + operation op leftValue rightValue |> cont ) + ) - in evaluate expr id +let evaluate expr = evaluateCPS expr id diff --git a/Tasks/Continuation/Continuation/TreeMap.fs b/Tasks/Continuation/Continuation/TreeMap.fs index a70df97..d2c1e23 100644 --- a/Tasks/Continuation/Continuation/TreeMap.fs +++ b/Tasks/Continuation/Continuation/TreeMap.fs @@ -4,16 +4,30 @@ type Tree<'a> = | Empty | Node of 'a * Tree<'a> * Tree<'a> -let map mapping tree = +[] +let rec private mapCPS mapping tree cont = + match tree with + | Empty -> cont Empty + | Node (value, left, right) -> + mapCPS mapping left (fun mappedLeft -> + mapCPS mapping right (fun mappedRight -> + Node (mapping value, mappedLeft, mappedRight) |> cont + ) + ) + +let map mapping tree = mapCPS mapping tree id - let rec map mapping tree cont = - match tree with - | Empty -> cont Empty - | Node (value, left, right) -> - map mapping left (fun mappedLeft -> - map mapping right (fun mappedRight -> - Node (mapping value, mappedLeft, mappedRight) |> cont - ) +[] +let rec private areEqualCPS tree1 tree2 cont = + match tree1, tree2 with + | Empty, Empty -> cont true + | Empty, Node _ | Node _, Empty -> cont false + | Node (val1, _, _), Node (val2, _, _) when val1 <> val2 -> cont false + | Node (_, left1, right1), Node (_, left2, right2) -> + areEqualCPS left1 left2 (fun leftAreEqual -> + areEqualCPS right1 right2 (fun rightAreEqual -> + leftAreEqual && rightAreEqual |> cont ) + ) - in map mapping tree id +let areEqual tree1 tree2 = areEqualCPS tree1 tree2 id From 90dc39cbb7bbfc5afcf924da051865e2bcf724dd Mon Sep 17 00:00:00 2001 From: bygu4 Date: Sun, 8 Jun 2025 16:28:58 +0300 Subject: [PATCH 9/9] correct Expression type definition --- Tasks/Continuation/Continuation/ParseTree.fs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Tasks/Continuation/Continuation/ParseTree.fs b/Tasks/Continuation/Continuation/ParseTree.fs index 016b088..035330d 100644 --- a/Tasks/Continuation/Continuation/ParseTree.fs +++ b/Tasks/Continuation/Continuation/ParseTree.fs @@ -1,14 +1,15 @@ module ParseTree -type Expression = - | Const of int - | Operator of Operation * Expression * Expression -and Operation = +type Operation = | Sum | Difference | Product | Ratio +type Expression = + | Const of int + | Operator of Operation * Expression * Expression + let operation op = match op with | Sum -> ( + )