forked from steger/pr3-sose2026
Compare commits
No commits in common. "75a37a3b8985366c92d8a0d44cff3689f9882624" and "1b7756f3cd0e35e622726521d6f2bd354bfbf10b" have entirely different histories.
75a37a3b89
...
1b7756f3cd
|
|
@ -1,10 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Haskell Dev Container",
|
|
||||||
"build": {
|
|
||||||
"dockerfile": "Dockerfile"
|
|
||||||
},
|
|
||||||
"customizations": {
|
|
||||||
"vscode": { "extensions": [
|
|
||||||
"haskell.haskell",
|
|
||||||
"phoityne.phoityne-vscode"
|
|
||||||
]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"editor.formatOnSave": true
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# Build
|
|
||||||
|
|
||||||
`ghc hello-world.hs`
|
|
||||||
|
|
||||||
# Run
|
|
||||||
|
|
||||||
`runghc hello-world.hs`
|
|
||||||
|
|
||||||
# Run interactively
|
|
||||||
```
|
|
||||||
ghci
|
|
||||||
ghci> :load hello-world.hs
|
|
||||||
ghci> main
|
|
||||||
```
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
main :: IO ()
|
|
||||||
main = putStrLn "Hello, World!"
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
# 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)]`
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
# 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`.
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
{-# 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 ()
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
|
|
||||||
-- 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 =================
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
{-# 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 ()
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
-- data Entity =
|
|
||||||
|
|
||||||
-- data Shape =
|
|
||||||
|
|
||||||
-- area :: Shape a -> a
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
# 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$
|
|
||||||
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
{-# 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 ()
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
import System.IO
|
|
||||||
import Text.Read (readMaybe)
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
# 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.
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
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
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
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