forked from steger/pr3-sose2026
Merge remote-tracking branch 'upstream/main'
commit
6d96eb957d
|
|
@ -0,0 +1,10 @@
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y build-essential curl libffi-dev libffi8ubuntu1 libgmp-dev libgmp10 libncurses-dev
|
||||||
|
RUN curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
|
||||||
|
ENV PATH="$PATH:/root/.ghcup/bin"
|
||||||
|
RUN ghcup install hls
|
||||||
|
RUN apt-get update && apt-get install -y git zlib1g-dev
|
||||||
|
RUN cabal update && cabal install ghci-dap haskell-debug-adapter
|
||||||
|
RUN cabal update && cabal install --lib HUnit
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "Haskell Dev Container",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": { "extensions": [
|
||||||
|
"haskell.haskell",
|
||||||
|
"phoityne.phoityne-vscode"
|
||||||
|
]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
|
||||||
|
{
|
||||||
|
// Automatically created by phoityne-vscode extension.
|
||||||
|
|
||||||
|
"version": "2.0.0",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always",
|
||||||
|
"panel": "new"
|
||||||
|
},
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
// F7
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": false
|
||||||
|
},
|
||||||
|
"label": "haskell build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "cabal configure && cabal build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// F6
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"label": "haskell clean & build",
|
||||||
|
"command": "cabal clean && cabal configure && cabal build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// F8
|
||||||
|
"group": {
|
||||||
|
"kind": "test",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"type": "shell",
|
||||||
|
"label": "haskell test",
|
||||||
|
"command": "cabal test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// F6
|
||||||
|
"isBackground": true,
|
||||||
|
"type": "shell",
|
||||||
|
"label": "haskell watch",
|
||||||
|
"command": "stack build --test --no-run-tests --file-watch"
|
||||||
|
}
|
||||||
|
|
||||||
|
,
|
||||||
|
{
|
||||||
|
// Build a single Haskell file
|
||||||
|
"type": "shell",
|
||||||
|
"label": "haskell build single file",
|
||||||
|
"command": "ghc",
|
||||||
|
"args": [ "${file}" ],
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Build
|
||||||
|
|
||||||
|
`ghc hello-world.hs`
|
||||||
|
|
||||||
|
# Run
|
||||||
|
|
||||||
|
`runghc hello-world.hs`
|
||||||
|
|
||||||
|
# Run interactively
|
||||||
|
```
|
||||||
|
ghci
|
||||||
|
ghci> :load hello-world.hs
|
||||||
|
ghci> main
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn "Hello, World!"
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
# Haskell - Expressions
|
||||||
|
|
||||||
|
The following illustrates some haskell basics. It can be reproduced using `ghci`.
|
||||||
|
|
||||||
|
## Types, Literals, and Constants along with Arithmetic and Boolean Operations
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`2` | `Num a => a` | `2` |
|
||||||
|
`2.03` | `Fractional a => a` | `2.03` |
|
||||||
|
`'c'` | `Char` | `'c'`
|
||||||
|
`"hallo"` | `String` | `"hallo"` |
|
||||||
|
`True` | `Bool` | `True` |
|
||||||
|
`x=5` | `Num a => a` | `5` | Constant named `x`
|
||||||
|
`2 + 3` | `Num a => a` | `5` | Similar `-,*,^`
|
||||||
|
`2 / 3` | `Fractional a => a` | `0.6666666666666666` |
|
||||||
|
`1 > 2` | `Bool` | `False` | Similar `<, <=, >=, ==, /=`
|
||||||
|
`True && False` | `Bool` | `False` | Similar `\|\|,not`
|
||||||
|
`((2+3)*5 > 1) \|\| not (1 > 2)` | `Bool` | `True` | Right part is not evaluated due to lazy evaluation
|
||||||
|
|
||||||
|
## Unary Functions
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`sqrt(4)` | `Floating a => a` | `2.0` |
|
||||||
|
`sqrt 4` | `Floating a => a` | `2.0` | Similar `abs,negate,signum,recip`
|
||||||
|
`sqrt` | `Floating a => a -> a` | |
|
||||||
|
`sqrt 3^2 + 4^2` | `Floating a => a` | `19.0` |
|
||||||
|
`sqrt (3^2 + 4^2)` | `Floating a => a` | `5.0` |
|
||||||
|
`negate(sqrt (3^2 + 4^2))` | `Floating a => a` | `-5.0` |
|
||||||
|
`negate $ sqrt (3^2 + 4^2)` | `Floating a => a`| `-5.0` | Function **application** operator `$`
|
||||||
|
`(negate . sqrt) (3^2 + 4^2)`| `Floating a => a`| `-5.0` | Function **composition** operator `.` Reads `negate` **after** `negate . sqrt` |
|
||||||
|
`(negate . length) "hallo"` | `Int` | `-5` |
|
||||||
|
`negatedRoot = negate . sqrt` | `Floating c => c -> c` | | Constant named `negatedRoot`
|
||||||
|
|
||||||
|
## Binary Functions
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`div 8 4` | `Integral a => a` | `2` | Similar `mod,gcd,lcm,not`
|
||||||
|
``8 `div` 4`` | `Integral a => a` | `2` | **Infix** notation using backticks
|
||||||
|
`8 + 4` | `Num a => a` | `12` | `-,*,^,<, <=, >=, ==, /=`
|
||||||
|
`(+) 8 4` | `Num a => a` | `12` | **Prefix** notation using parenthesis
|
||||||
|
`div` | `Integral a => a -> a -> a` | | **Currying** represents multi-argument functions as a chain of single-argument functions |
|
||||||
|
`div 8` | `Integral a => a -> a` | | binds the **first** argument; Similar `(8/),(8*),(8+),(8-)` |
|
||||||
|
`div8bySomething = div 8` | `Integral a => a -> a` | |
|
||||||
|
`div8bySomething 4` | `Integral a => a` | `2` |
|
||||||
|
`uncurry div` | `Integral c => (c, c) -> c` | | accepts a single tuple argument
|
||||||
|
`uncurry div (8,4)` | `Integral c => c` | `2` |
|
||||||
|
`uncurry` | `(a -> b -> c) -> (a, b) -> c`| |
|
||||||
|
`` (`div` 4) `` | `Integral a => a -> a` | | **Sectioning** binds the **second** argument of infix functions; Similar `(/8),(*8),(+8),(-8)` |
|
||||||
|
``divSomethingBy4 = (`div` 4)`` | `Integral a => a -> a` | |
|
||||||
|
`divSomethingBy4 8` | `Integral a => a` | `2` |
|
||||||
|
`const` | `a -> b -> a` | |
|
||||||
|
`const 8` | `Num a => b -> a` | | function that ignores the input and always returns 8
|
||||||
|
`const 8 4` | `Num a => a` | `8` |
|
||||||
|
|
||||||
|
## Tuples
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`(1, 2)` | `(Num a, Num b) => (a, b)` | `(1, 2)` |
|
||||||
|
`(1, "hello", True)` | `(Num a => (a, String, Bool)` | `(1, "hello", True)` |
|
||||||
|
`fst (1, 2)` | `Num a => a` | `1` |
|
||||||
|
`snd (1, 2)` | `Num b => b` | `2` |
|
||||||
|
`(,) 1 2` | `Num a => a -> a -> (a, a)` | `(1, 2)` |
|
||||||
|
|
||||||
|
## Strings
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`"hello" ++ " world"` | `String` | `"hello world"` | String concatenation
|
||||||
|
`length "hello"` | `Int` | `5` | Length of the string
|
||||||
|
`null ""` | `Bool` | `True` | Checks if the string is empty
|
||||||
|
|
||||||
|
## Control Structures
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`if 10/2==5 then "five" else "something else"` | `String` | `"five"` |
|
||||||
|
`case 1 of { 1 -> "small"; 2 -> "medium"; _ -> "large"}` | `String` | `"small"` | patterns are overlapping
|
||||||
|
`(let x = 5*2 in (x * 2,x /2))` | `(Fractional b, Num a) => (a, b)` | `(20,5.0)` |
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
Expression | Type (:t) | Value | Comment
|
||||||
|
--- | --- | --- | --------
|
||||||
|
`[]` | `[a]` | `[]` |
|
||||||
|
`1:7:4:[]` | `Num a => [a]` | `[1,7,4]` | actual construction of a list
|
||||||
|
`[1,7,4]` | `Num a => [a]` | `[1,7,4]` |
|
||||||
|
`8 : [1,7,4]` | `Num a => [a]` | `[8,1,7,4]` | **cons** operator, short for construct
|
||||||
|
`[1,7,4]` | `[Num a] => [a]` | `[1,7,4]` |
|
||||||
|
`(++)` | `[a] -> [a] -> [a]` | |
|
||||||
|
`[1,7,4] ++ [8]` | `Num a => [a]` | `[1,7,4,8]` |
|
||||||
|
`[1,7,4] !! 2` | `Num a => [a]` | `4` |
|
||||||
|
`(!!)` | `[a] -> Int -> a` | |
|
||||||
|
`head [1,7,4]` | `Num a => a` | `1` | Similar `last`
|
||||||
|
`tail [1,7,4]` | `[Num a] => [a]` | `[7,4]` | Similar `init`
|
||||||
|
`length [1,7,4]` | `Int` | `3` |
|
||||||
|
`null []` | `Bool` | `True` |
|
||||||
|
`reverse [1,7,4]` | `[Num a] => [a]` | `[4,7,1]` | Similar `Data.List.sort`
|
||||||
|
`take 2 [1,7,4]` | `[Num a]=>[a]` | `[1,7]` | Similar `drop`
|
||||||
|
`take` | `Int -> [a] -> [a]` | |
|
||||||
|
`sum [1,7,4]` | `Num a=>a` | `12` | Similar `product,maximum,minimum,length`
|
||||||
|
`foldl (-) 0 [1,7,4]` | `Num a => a` | `-12` | `(((0-1)-7)-4)`
|
||||||
|
`foldl` | `Foldable t => (b -> a -> b) -> b -> t a -> b` | |
|
||||||
|
`foldr (-) 0 [1,7,4]` | `Num a => a` | `-2` | `(1-(7-(4-0)))`
|
||||||
|
`elem 7 [1,7,4]` | `Bool` | `True` |
|
||||||
|
`all even [1,7,4]` | `Bool` | `False` | Similar `any`
|
||||||
|
`filter even [1,7,4]` | `[Integral a] => [a]` | `[1,7,4]` | Similar `odd,(>1),(/=3)`
|
||||||
|
`(length . filter (>1) ) [1,7,4]` | `Int` | `2` |
|
||||||
|
`Data.List.partition (>1) [1,7,4]` | `(Ord a, Num a) => ([a], [a])` | `([7,4],[1])`
|
||||||
|
`zip [1,7,4] ["one","seven","four","eight"]` | `Num a => [(a, String)]` | `[(1,"one"),(7,"seven"),(4,"four")]` | truncating to the shorter list
|
||||||
|
`Data.List.sortOn fst $ zip [1,7,4] ["one", "seven", "four"]` | `(Ord b, Num b) => [(b, String)]` | `[(1,"one"),(4,"four"),(7,"seven")]`
|
||||||
|
`Data.List.sort ["one","seven","four","eight"]` | `[String]` | `["eight","four","one","seven"]`
|
||||||
|
`reverse $ Data.List.sort ["one","seven","four","eight"]` | `[String]` | `["seven","one","four","eight"]`
|
||||||
|
`Data.List.sortBy compare ["one","seven","four","eight"]` | `[String]` | `["eight","four","one","seven"]`
|
||||||
|
`Data.List.sortBy (flip compare) ["one","seven","four","eight"]` | `[String]` | `["seven","one","four","eight"]`
|
||||||
|
`Data.List.sortBy (curry( (uncurry compare) . (uncurry(Control.Arrow.***) (length,length)))) ["one","seven","four","eight","ten"]` | `[String]` | `["one","ten","four","seven","eight"]` |
|
||||||
|
`Data.List.sortBy (Data.Ord.comparing length) ["one","seven","four","eight","ten"]` | `[String]` | `["one","ten","four","seven","eight"]`
|
||||||
|
`map (+1) [1,7,4]` | `Num a => [a]` | `[2,8,5]` |
|
||||||
|
`map length ["one", "seven", "four"]` | `[Int]` | `[3,5,4]` |
|
||||||
|
`map (negate . abs) [1,-7,4]` | `Num a => [a]` | `[-1,-7,-4]` |
|
||||||
|
`map even [1,7,4]` | `[Bool]` | `[False,False,True]` |
|
||||||
|
`[1..5]` | `(Num a, Enum a) => [a]` | `[1,2,3,4,5]` |
|
||||||
|
`[1,3..9]` | `(Num a, Enum a) => [a]` | `[1,3,5,7,9]` |
|
||||||
|
`[1..]` | `(Num a, Enum a) => [a]` | `[1,2,3,4,5,...]` | infinite sequence
|
||||||
|
`take 4 [10..]` | `(Num a, Enum a) => [a]` | `[1,2,3,4]` | laziness in action
|
||||||
|
`[x*2 \| x <- [1..5]]` | `[Num a] => [a]` | `[2, 4, 6, 8, 10]` | List comprehension
|
||||||
|
``[x*2 \| x <- [1..5], x `mod` 3 == 0]`` | `[Num a] => [a]` | `[6]` |
|
||||||
|
`[ (a,b,c) \| c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]` | `(Num c, Eq c, Enum c) => [(c, c, c)]` | `[(3,4,5),(6,8,10)]`
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Assignment
|
||||||
|
|
||||||
|
You are provided with:
|
||||||
|
|
||||||
|
1. A vector of names
|
||||||
|
2. A vector of ages
|
||||||
|
|
||||||
|
Your task is to compute a list containing the UPPERCASE names of the two oldest persons whose names ends with an "a". The result shall be sorted by alphabet.
|
||||||
|
|
||||||
|
Complete the corresponding unit test in the file `02-list-operations/list-operations.hs`.
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||||
|
|
||||||
|
{-# HLINT ignore "Avoid reverse" #-}
|
||||||
|
{-# HLINT ignore "Use void" #-}
|
||||||
|
|
||||||
|
import Data.Char (toUpper)
|
||||||
|
import Data.List (sort, sortOn)
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
names = ["Oliver", "Emma", "Liam", "Ava", "Noah", "Sophia", "James", "Mia", "Elijah", "Isabella"]
|
||||||
|
|
||||||
|
ages = [25, 30, 22, 29, 35, 28, 40, 26, 33, 31]
|
||||||
|
|
||||||
|
-- we are looking for the UPPERCASE names of the two oldest persons whose names ends with an a sorted alphabetically"
|
||||||
|
|
||||||
|
extractedNames = []
|
||||||
|
|
||||||
|
test1 = Test.HUnit.TestCase (assertEqual "ExtractedNames" ["EMMA", "ISABELLA"] extractedNames)
|
||||||
|
|
||||||
|
tests = TestList [test1]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = runTestTT test1 >> return ()
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
-- single parameter
|
||||||
|
|
||||||
|
-- two parameters
|
||||||
|
|
||||||
|
-- ============= pattern matching =================
|
||||||
|
|
||||||
|
-- ============= guards =================
|
||||||
|
|
||||||
|
-- ============= recursive algorithms =================
|
||||||
|
|
||||||
|
-- ============= recursive list algorithms =================
|
||||||
|
|
||||||
|
-- ============= merge sort =================
|
||||||
|
|
||||||
|
-- =========== Filter all numbers that can be divided by 10 ===========
|
||||||
|
|
||||||
|
-- ========================== standard deviation using lambdas =====================
|
||||||
|
-- The standard deviation is a measure of the amount of variation or dispersion of a set of values.
|
||||||
|
-- It is defined as the square root of the average of the squared differences from the mean.
|
||||||
|
--
|
||||||
|
-- Formula:
|
||||||
|
-- σ = sqrt( (1/N) * Σ (xi - μ)^2 )
|
||||||
|
-- where:
|
||||||
|
-- - σ is the standard deviation,
|
||||||
|
-- - N is the number of values,
|
||||||
|
-- - xi represents each value,
|
||||||
|
-- - μ is the mean of the values.
|
||||||
|
|
||||||
|
stddev seq = 0
|
||||||
|
|
||||||
|
-- ======================= order list of strings by length =================
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Assignment - Tower of Hanoi {.alert}
|
||||||
|
|
||||||
|
The Tower of Hanoi is a classic mathematical puzzle that involves three rods and a number of disks of different sizes.
|
||||||
|
The puzzle starts with all the disks stacked in ascending order of size on one rod (the source rod), with the smallest disk on top.
|
||||||
|
The objective is to move the entire stack to another rod (the destination rod), following these rules:
|
||||||
|
|
||||||
|
1. Only one disk can be moved at a time.
|
||||||
|
2. Each move consists of taking the top disk from one rod and placing it on another rod.
|
||||||
|
3. No disk may be placed on top of a smaller disk.
|
||||||
|
|
||||||
|
**Your task:**
|
||||||
|
|
||||||
|
Implement a function that solves the Tower of Hanoi problem for `n` disks. The rods are represented as Chars (e.g. 'a','b','c'). The result shall be a list of moving instructions. Add your implementation to the file `04-hanoi/hanoi.hs` that already contains a test and a helper function that creates the move instruction for a single move.
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||||
|
|
||||||
|
{-# HLINT ignore "Use void" #-}
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
-- some helper function that describes a single move
|
||||||
|
move :: Int -> Char -> Char -> String
|
||||||
|
move n src dst = "move disk " ++ show n ++ " from " ++ [src] ++ " to " ++ [dst]
|
||||||
|
|
||||||
|
-- transfers a number of disks (the Int) from a source (the first Char) rod to a destination (the second Char) rod via a temp (the third char) rod
|
||||||
|
-- returns a list of required operations
|
||||||
|
hanoi :: (Int,Char,Char,Char) -> [String]
|
||||||
|
|
||||||
|
--TODO: implement here
|
||||||
|
|
||||||
|
-- Source, Destination, Temp
|
||||||
|
hanoiTests :: [((Int, Char, Char, Char), [String])]
|
||||||
|
hanoiTests =
|
||||||
|
[ ( (1, 'a', 'c', 'b'),
|
||||||
|
[ "move disk 1 from a to c"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
( (1, 'b', 'a', 'c'),
|
||||||
|
[ "move disk 1 from b to a"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
( (2, 'a', 'c', 'b'),
|
||||||
|
[ "move disk 1 from a to b",
|
||||||
|
"move disk 2 from a to c",
|
||||||
|
"move disk 1 from b to c"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
( (3, 'a', 'c', 'b'),
|
||||||
|
[ "move disk 1 from a to c",
|
||||||
|
"move disk 2 from a to b",
|
||||||
|
"move disk 1 from c to b",
|
||||||
|
"move disk 3 from a to c",
|
||||||
|
"move disk 1 from b to a",
|
||||||
|
"move disk 2 from b to c",
|
||||||
|
"move disk 1 from a to c"
|
||||||
|
]
|
||||||
|
),
|
||||||
|
( (4, 'a', 'c', 'b'),
|
||||||
|
[ "move disk 1 from a to b",
|
||||||
|
"move disk 2 from a to c",
|
||||||
|
"move disk 1 from b to c",
|
||||||
|
"move disk 3 from a to b",
|
||||||
|
"move disk 1 from c to a",
|
||||||
|
"move disk 2 from c to b",
|
||||||
|
"move disk 1 from a to b",
|
||||||
|
"move disk 4 from a to c",
|
||||||
|
"move disk 1 from b to c",
|
||||||
|
"move disk 2 from b to a",
|
||||||
|
"move disk 1 from c to a",
|
||||||
|
"move disk 3 from b to c",
|
||||||
|
"move disk 1 from a to b",
|
||||||
|
"move disk 2 from a to c",
|
||||||
|
"move disk 1 from b to c"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
hanoiTestCases :: [Test]
|
||||||
|
hanoiTestCases = map (\(input, expected) -> TestCase (assertEqual ("hanoi " ++ show input) expected (hanoi input))) hanoiTests
|
||||||
|
|
||||||
|
tests :: Test
|
||||||
|
tests = TestList hanoiTestCases
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = runTestTT tests >> return ()
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- data Entity =
|
||||||
|
|
||||||
|
-- data Shape =
|
||||||
|
|
||||||
|
-- area :: Shape a -> a
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Complex Numbers
|
||||||
|
|
||||||
|
## Assignment
|
||||||
|
Define a new type `Complex` that allows arithmetic calculations in an intuitive fashion. See below for the rules that shall be implemented. Incrementally make sure that all unit tests in `06-complex/complex.hs` are passed.
|
||||||
|
|
||||||
|
## Complex Numbers
|
||||||
|
|
||||||
|
Complex numbers are numbers of the form: $z = a + bi$
|
||||||
|
|
||||||
|
- **`a`**: The real part of the complex number.
|
||||||
|
- **`b`**: The imaginary part of the complex number.
|
||||||
|
- **`i`**: The imaginary unit, where $i^2 = -1$.
|
||||||
|
|
||||||
|
Complex numbers are used in mathematics, physics, and engineering to extend the real number system and solve equations that have no real solutions, such as $x^2 + 1 = 0$.
|
||||||
|
|
||||||
|
Complex numbers are often represented in both rectangular form $a + bi$ and polar/exponential form $r e^{i\theta}$.
|
||||||
|
|
||||||
|
|
||||||
|
## Rules for Computing with Complex Numbers
|
||||||
|
|
||||||
|
### 1. **Addition and Subtraction**
|
||||||
|
- Add or subtract the real and imaginary parts separately.
|
||||||
|
- Rule:
|
||||||
|
$(a + bi) + (c + di) = (a + c) + (b + d)i$
|
||||||
|
$(a + bi) - (c + di) = (a - c) + (b - d)i$
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
1. $(2 + 3i) + (4 + 5i) = 6 + 8i$
|
||||||
|
2. $(0 + 3i) + (2 + 0i) = 2 + 3i$
|
||||||
|
3. $(7 + 2i) - (3 + 6i) = 4 - 4i$
|
||||||
|
4. $(5 + 4i) - (1 + 2i) = 4 + 2i$
|
||||||
|
|
||||||
|
### 2. **Multiplication**
|
||||||
|
- Use the distributive property and the rule $i^2 = -1$.
|
||||||
|
- Rule:
|
||||||
|
$(a + bi)(c + di) = (ac - bd) + (ad + bc)i$
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
1. $(1 + 2i)(3 + 4i) = -5 + 10i$
|
||||||
|
2. $(2 + 3i)(1 - i) = 5 + i$
|
||||||
|
3. $(4 + i)(2 - 3i) = 11 - 10i$
|
||||||
|
4. $(3 + 2i)(3 + 2i) = 5 + 12i$
|
||||||
|
|
||||||
|
### 3. **Division**
|
||||||
|
- Multiply numerator and denominator by the conjugate of the denominator.
|
||||||
|
- Rule:
|
||||||
|
$\frac{a + bi}{c + di} = \frac{(a + bi)(c - di)}{(c + di)(c - di)}$
|
||||||
|
Simplifies to:
|
||||||
|
$\frac{(ac + bd) + (bc - ad)i}{c^2 + d^2}$
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
1. $\frac{1 + i}{1 - i} = 0 + 1i$
|
||||||
|
2. $\frac{3 + 2i}{4 + 3i} = \frac{18 + i}{25} = 0.72 - 0.04i$
|
||||||
|
3. $\frac{2 + i}{1 + i} = \frac{3 - i}{2} = 1.5 - 0.5i$
|
||||||
|
|
||||||
|
### 4. **Complex Conjugate**
|
||||||
|
- The conjugate of $a + bi$ is $a - bi$, used for simplifications and magnitude calculation.
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
1. Conjugate of $3 + 4i$ is $3 - 4i$.
|
||||||
|
2. Conjugate of $5 - i$ is $5 + i$.
|
||||||
|
3. Conjugate of $-2 + 3i$ is $-2 - 3i$.
|
||||||
|
|
||||||
|
### 5. **Magnitude (Modulus)**
|
||||||
|
- The magnitude is the distance from the origin in the complex plane.
|
||||||
|
- Rule: $|a + bi| = \sqrt{a^2 + b^2}$
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
1. $|3 + 4i| = \sqrt{3^2 + 4^2} = 5$
|
||||||
|
2. $|1 - i| = \sqrt{1^2 + (-1)^2} = \sqrt{2}$
|
||||||
|
3. $|0 + 5i| = \sqrt{0^2 + 5^2} = 5$
|
||||||
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||||
|
|
||||||
|
{-# HLINT ignore "Use void" #-}
|
||||||
|
import Test.HUnit
|
||||||
|
|
||||||
|
data Complex a = TODO
|
||||||
|
|
||||||
|
instance (Show a, Num a, Eq a) => Show (Complex a) where
|
||||||
|
-- show :: (Show a, Num a, Eq a) => Complex a -> String
|
||||||
|
-- TODO
|
||||||
|
|
||||||
|
instance (Num a, Floating a) => Num (Complex a) where
|
||||||
|
-- (+) :: (Num a, Floating a) => Complex a -> Complex a -> Complex a
|
||||||
|
-- (*) :: (Num a, Floating a) => Complex a -> Complex a -> Complex a
|
||||||
|
-- TODO
|
||||||
|
-- abs (Complex re im) = TODO
|
||||||
|
-- signum (Complex re im) = TODO
|
||||||
|
-- fromInteger n = TODO
|
||||||
|
-- negate :: (Num a, Floating a) => Complex a -> Complex a
|
||||||
|
-- negate (Complex re im) = Complex (negate re) (negate im)
|
||||||
|
|
||||||
|
instance (Fractional a, Floating a) => Fractional (Complex a) where
|
||||||
|
-- fromRational r = TODO
|
||||||
|
-- recip (Complex re im) = TODO
|
||||||
|
|
||||||
|
-- (Complex re1 im1) / (Complex re2 im2) = TODO
|
||||||
|
|
||||||
|
-- conj :: Num a => Complex a -> Complex a
|
||||||
|
-- TODO
|
||||||
|
|
||||||
|
tests :: Test
|
||||||
|
tests =
|
||||||
|
TestList
|
||||||
|
[ Test.HUnit.TestCase (assertEqual "Show 1+2i" "1+2i" (show $ Complex 1 2)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Show 1" "1" (show $ Complex 1 0)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Show i" "i" (show i)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Show 5i" "5i" (show $ Complex 0 5)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Show 0" "0" (show $ Complex 0 0)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Compare Equal" True (Complex 2 3 == Complex 2 3)),
|
||||||
|
Test.HUnit.TestCase (assertEqual "Compare Real Not Equal" False (Complex 1 3 == Complex 2 3)),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
(assertEqual "Compare Imag Not Equal" False (Complex 2 4 == Complex 2 3)),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
(assertEqual "Compare Not Equal" False (Complex 2 3 /= Complex 2 3)),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Addition 1"
|
||||||
|
(Complex 6.0 8.0)
|
||||||
|
(Complex 2.0 3.0 + Complex 4.0 5.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Addition 2"
|
||||||
|
(Complex 2.0 3.0)
|
||||||
|
(Complex 0.0 3.0 + Complex 2.0 0.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Subtraction 1"
|
||||||
|
(Complex 4.0 (-4.0))
|
||||||
|
(Complex 7.0 2.0 - Complex 3.0 6.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Subtraction 2"
|
||||||
|
(Complex 4.0 2.0)
|
||||||
|
(Complex 5.0 4.0 - Complex 1.0 2.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Negation"
|
||||||
|
(Complex (-7.0) (-2.0))
|
||||||
|
(negate (Complex 7.0 2.0))
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Multiplication 1"
|
||||||
|
(Complex (-5.0) 10.0)
|
||||||
|
(Complex 1.0 2.0 * Complex 3.0 4.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Multiplication 2"
|
||||||
|
(Complex 5.0 1.0)
|
||||||
|
(Complex 2.0 3.0 * Complex 1.0 (-1.0))
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Multiplication 3"
|
||||||
|
(Complex 11.0 (-10.0))
|
||||||
|
(Complex 4.0 1.0 * Complex 2.0 (-3.0))
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Multiplication 4"
|
||||||
|
(Complex 5.0 12.0)
|
||||||
|
(Complex 3.0 2.0 * Complex 3.0 2.0)
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Magnitude 1"
|
||||||
|
(Complex 5.0 0.0)
|
||||||
|
(abs (Complex 3.0 4.0))
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Magnitude 2"
|
||||||
|
(Complex (sqrt 2.0) 0.0)
|
||||||
|
(abs (Complex 1.0 (-1.0)))
|
||||||
|
),
|
||||||
|
Test.HUnit.TestCase
|
||||||
|
( assertEqual
|
||||||
|
"Magnitude 3"
|
||||||
|
(Complex 5.0 0.0)
|
||||||
|
(abs (Complex 0.0 5.0))
|
||||||
|
),
|
||||||
|
TestCase (assertEqual "Conjugate of 3+4i" (Complex 3 (-4)) (conj (Complex 3 4))),
|
||||||
|
TestCase (assertEqual "Conjugate of 5-i" (Complex 5 1) (conj (Complex 5 (-1)))),
|
||||||
|
TestCase (assertEqual "Conjugate of -2+3i" (Complex (-2) (-3)) (conj (Complex (-2) 3)))
|
||||||
|
]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = runTestTT tests >> return ()
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
import System.IO
|
||||||
|
import Text.Read (readMaybe)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Assignment - Statistics
|
||||||
|
|
||||||
|
The file `08-statistics/data.csv` contains random data of students. It consists of the following columns:
|
||||||
|
|
||||||
|
- first name
|
||||||
|
- last name
|
||||||
|
- study subject
|
||||||
|
|
||||||
|
The rest of the columns -- and that number may vary -- contain points for different tasks. The first row is a header.
|
||||||
|
|
||||||
|
Your task is to Write a program that reads a filename from standard input. The corresponding csv-file shall be parsed and then the following statistics shall be computed and printed to standard output:
|
||||||
|
|
||||||
|
- the best student, i.e. the student with the most accumulated points (name and points shall be printed)
|
||||||
|
- the average points of all rows for each subject (subject and average points shall be printed in ascending order)
|
||||||
|
|
||||||
|
Implement your solution in the file `08-statistics/statistics.hs` and upload the file to moodle.
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
First Name,Last Name,Subject,Task1,Task2,Task3,Task4,Task5
|
||||||
|
Alice,Johnson,IB,87,45,68,92,33
|
||||||
|
Bob,Smith,CSB,56,79,42,88,12
|
||||||
|
Charlie,Williams,IMB,73,94,35,64,89
|
||||||
|
David,Brown,UIB,41,59,77,29,83
|
||||||
|
Emma,Jones,IB,99,21,48,75,56
|
||||||
|
Frank,Garcia,CSB,32,81,94,55,23
|
||||||
|
Grace,Miller,IMB,74,53,61,95,39
|
||||||
|
Henry,Davis,UIB,90,40,28,76,65
|
||||||
|
Isabella,Rodriguez,IB,57,86,72,49,100
|
||||||
|
Jack,Martinez,CSB,64,31,59,97,14
|
||||||
|
Liam,Hernandez,IMB,85,67,50,78,41
|
||||||
|
Mia,Lopez,UIB,44,92,33,56,81
|
||||||
|
Noah,Gonzalez,IB,68,39,74,82,47
|
||||||
|
Olivia,Wilson,CSB,95,20,62,53,34
|
||||||
|
Paul,Anderson,IMB,29,88,49,31,77
|
||||||
|
Sophia,Thomas,UIB,81,56,93,42,69
|
||||||
|
Ethan,Moore,IB,47,77,65,59,92
|
||||||
|
Zoe,Taylor,CSB,38,95,40,70,58
|
||||||
|
Lucas,Harris,IMB,99,45,83,62,37
|
||||||
|
Ava,Clark,UIB,53,66,91,85,29
|
||||||
|
Benjamin,Walker,IB,71,58,80,34,61
|
||||||
|
Chloe,Hall,CSB,76,23,67,47,94
|
||||||
|
Daniel,Allen,IMB,39,82,55,90,73
|
||||||
|
Ella,Young,UIB,86,32,99,60,25
|
||||||
|
James,King,IB,42,75,48,93,57
|
||||||
|
Madison,Wright,CSB,63,54,72,51,88
|
||||||
|
Nathan,Scott,IMB,91,37,79,68,45
|
||||||
|
Emma,Green,UIB,50,89,31,77,61
|
||||||
|
Jacob,Baker,IB,74,69,58,46,97
|
||||||
|
Emily,Adams,CSB,88,41,66,79,30
|
||||||
|
Samuel,Nelson,IMB,33,85,92,40,50
|
||||||
|
Sophia,Carter,UIB,69,47,71,58,94
|
||||||
|
Alexander,Mitchell,IB,57,98,36,61,82
|
||||||
|
Victoria,Perez,CSB,92,28,64,73,49
|
||||||
|
William,Roberts,IMB,45,76,89,55,31
|
||||||
|
Ella,Turner,UIB,78,59,41,96,68
|
||||||
|
Daniel,Phillips,IB,60,32,85,71,43
|
||||||
|
Natalie,Campbell,CSB,55,74,99,28,79
|
||||||
|
Mason,Parker,IMB,93,50,39,82,66
|
||||||
|
Hannah,Evans,UIB,48,69,57,95,22
|
||||||
|
Christopher,Edwards,IB,90,88,34,53,72
|
||||||
|
Lucy,Collins,CSB,31,46,81,77,56
|
||||||
|
Gabriel,Stewart,IMB,65,79,62,90,44
|
||||||
|
Avery,Morris,UIB,80,23,47,36,97
|
||||||
|
Ryan,Ross,IB,58,71,83,45,74
|
||||||
|
Sophie,Reed,CSB,99,33,60,81,51
|
||||||
|
Isaac,Adams,IMB,42,92,30,57,85
|
||||||
|
Leah,Bennett,UIB,76,64,55,89,39
|
||||||
|
Tyler,Barnes,IB,67,40,78,95,20
|
||||||
|
Scarlett,Morgan,CSB,34,84,91,47,53
|
||||||
|
John,White,IMB,89,25,72,69,98
|
||||||
|
Eleanor,James,UIB,54,58,49,87,62
|
||||||
|
Caleb,Wood,IB,31,100,37,46,81
|
||||||
|
Amelia,Hill,CSB,73,45,79,66,50
|
||||||
|
Julian,Scott,IMB,97,34,89,22,76
|
||||||
|
Charlotte,Bryant,UIB,63,92,41,88,32
|
||||||
|
Isaiah,Mitchell,IB,81,68,52,39,74
|
||||||
|
Lily,Foster,CSB,56,97,44,85,29
|
||||||
|
Elijah,Howard,IMB,70,61,36,90,99
|
||||||
|
Peyton,Washington,UIB,49,82,67,31,75
|
||||||
|
Xavier,Cook,IB,88,55,93,42,64
|
||||||
|
Nora,Bailey,CSB,37,72,57,96,47
|
||||||
|
Owen,Rivera,IMB,59,30,80,77,91
|
||||||
|
Harper,Cooper,UIB,50,99,33,28,65
|
||||||
|
Eli,Fisher,IB,78,40,85,92,53
|
||||||
|
Mila,Harrison,CSB,62,47,71,89,31
|
||||||
|
Adam,Romero,IMB,34,66,98,42,75
|
||||||
|
Stella,Patel,UIB,96,39,54,87,68
|
||||||
|
Carson,Cox,IB,42,55,79,100,27
|
||||||
|
Luna,Sanders,CSB,88,74,46,29,83
|
||||||
|
Connor,Henderson,IMB,97,32,53,60,98
|
||||||
|
Brooklyn,Bishop,UIB,45,90,61,72,31
|
||||||
|
Andrew,Griffin,IB,58,42,87,65,49
|
||||||
|
Natalia,Russell,CSB,70,23,74,56,92
|
||||||
|
Jason,Myers,IMB,81,67,35,48,79
|
||||||
|
Alexa,Hayes,UIB,37,98,55,93,42
|
||||||
|
Christian,Long,IB,64,71,82,45,57
|
||||||
|
Zoey,Gibson,CSB,90,54,38,100,73
|
||||||
|
Brayden,Graham,IMB,39,89,66,53,31
|
||||||
|
Maya,Sullivan,UIB,85,77,62,94,25
|
||||||
|
Jaxon,Ford,IB,48,35,100,71,83
|
||||||
|
Claire,Wallace,CSB,59,46,88,38,76
|
||||||
|
Dominic,Cole,IMB,78,92,44,67,50
|
||||||
|
Eva,Jenkins,UIB,100,29,53,79,61
|
||||||
|
Riley,Perkins,IB,55,97,31,84,30
|
||||||
|
Leo,Brooks,CSB,72,40,91,45,99
|
||||||
|
Hailey,Reynolds,IMB,31,58,77,90,28
|
||||||
|
Aaron,Fox,UIB,83,72,61,35,48
|
||||||
|
Kennedy,Stevens,IB,41,66,85,92,53
|
||||||
|
Sebastian,Webb,CSB,99,33,60,81,51
|
||||||
|
Melanie,Ward,IMB,76,64,55,89,39
|
||||||
|
Adrian,Bishop,UIB,67,40,78,95,20
|
||||||
|
Jasmine,Cook,IB,34,84,91,47,53
|
||||||
|
Miles,Barnes,CSB,89,25,72,69,98
|
||||||
|
Savannah,Wood,IMB,54,58,49,87,62
|
||||||
|
Hudson,Hill,UIB,31,100,37,46,81
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import Data.List (nub, sortOn)
|
||||||
|
import System.IO
|
||||||
|
|
||||||
|
-- separator -> Input -> Separated Input
|
||||||
|
-- split :: Char -> String -> [String]
|
||||||
|
|
||||||
|
-- data Entry =
|
||||||
|
|
||||||
|
-- averages :: [Entry] -> [(String, Float)]
|
||||||
|
|
||||||
|
-- content -> Entries
|
||||||
|
-- parse :: String -> [Entry]
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
putStrLn "Enter a filename: "
|
||||||
|
putStrLn "..."
|
||||||
Loading…
Reference in New Issue