Skip to content

Commit

Permalink
exams 7-10
Browse files Browse the repository at this point in the history
  • Loading branch information
nmheim committed Feb 20, 2024
1 parent 5d50000 commit c453556
Show file tree
Hide file tree
Showing 23 changed files with 1,565 additions and 9 deletions.
8 changes: 4 additions & 4 deletions .vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ export default defineConfig({
{ text: '4. N²-Knights', link: '/exams/n2-knights/' },
{ text: '5. Filetree', link: '/exams/filetree/' },
{ text: '6. Text Justification', link: '/exams/justify/' },
// { text: '7. Photographing Skyscrapers', link: '/exams/filetree' },
// { text: '8. Non-deterministic Finite Automata', link: '/exams/filetree' },
// { text: '9. Least Common Anchestor', link: '/exams/filetree' },
// { text: '10. Building Trees', link: '/exams/filetree' },
{ text: '7. Photographing Skyscrapers', link: '/exams/photo-skyscraper/' },
{ text: '8. Non-deterministic Finite Automata', link: '/exams/finite-automata/' },
{ text: '9. Least Common Anchestor', link: '/exams/least-common-ancestor/' },
{ text: '10. Building Trees', link: '/exams/building-trees/' },
// { text: '11. Square Code', link: '/exams/filetree' },
// { text: '12. Rock, Paper, Scissors', link: '/exams/filetree' },
// { text: '13. Sierpinski Carpet', link: '/exams/filetree' },
Expand Down
253 changes: 253 additions & 0 deletions exams/building-trees/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
---
outline: deep
title: "Exam Task: Building Trees"
subtitle: "From: Exam 2 - 2023"
---

# Building Trees


In this task, you will build a tree from an intial tree and a sequence of edges. Your task is to
iterate through the edge sequence from left to right and expand successively the initial tree. Each
edge is a pair $(s,t)$. To expand the tree by the edge $(s,t)$, you must traverse through the tree
and locate the node $s$. Next, you add $t$ among its children. If $s$ does not occur in the tree,
the edge is ignored.

For example, suppose that the initial tree is just a single node (a leaf) $1$ and the edge sequence
equals $(1,2),(1,3),(5,7),(2,4),(4,5),(3,6)$. By expanding the initial tree by the edges, we obtain
the following sequence of trees:

<img src="/img/building-trees-sequence.svg" style="width: 95%; margin: auto;">

Note that the third edge $(5,7)$ was ignored because there is no node $5$ in the currently
constructed tree. So the currently constructed tree remains unchanged.

## Racket

In \textbf{Racket}, implement a function `(build-tree init edges)` that takes an initial
tree `init` and a list of edges `edges`, and returns the tree created by expanding
the initial tree by the edges.

To represent trees in Racket, use the following structures:
```scheme
(struct node (val kids) #:transparent)
(struct leaf (val) #:transparent)
```
Thus the leaves (nodes without children) are represented as, for instance, `(leaf 6)`.
The nodes with children are represented as, for instance, `(node 1 (list (leaf 2) (leaf 3)))`.

To implement the function `build-tree`, implement first a function `(add-edge edge tree)`
expanding a given tree `tree` by a single edge `edge`. For example,
```scheme
> (add-edge '(2 4) (node 1 (list (leaf 2) (leaf 3))))
(node 1 (list (node 2 (list (leaf 4))) (leaf 3)))
```

When you add a new leaf to a list of children, prepend it at the front. For example,
```scheme
> (add-edge '(1 3) (node 1 (list (leaf 2))))
(node 1 (list (leaf 3) (leaf 2)))
```

To make the output of the function `build-tree` unique, sort the children of every node
in the resulting tree based on their values. You may assume, that the node values are numbers.
For example,
```scheme
(node 1 (list (node 2 (list (leaf 4))) (leaf 3))) ; correct
(node 1 (list (leaf 3) (node 2 (list (leaf 4))))) ; not correct
```

Your file should be called `task3.rkt` and should export the `add-edge` and
`build-tree` functions and the structures `node` and `leaf`.
```scheme
#lang racket
(provide add-edge
build-tree
(struct-out node)
(struct-out leaf))
(struct node (val kids) #:transparent)
(struct leaf (val) #:transparent)
(define (add-edge edge tree)
; Implement me!
)
(define (build-tree init edges)
; Implement me!
)
```

### Example

```scheme
> (build-tree (leaf 1) '((1 2) (1 3) (5 7) (2 4) (4 5) (3 6)))
(node 1 (list (node 2 (list (node 4 (list (leaf 5)))))
(node 3 (list (leaf 6)))))
```

### Hints

To sort the children, use the function `(sort lst less-than?)` sorting a list `lst`
comparing its elements by a function `less-than?`. For example,
```scheme
> (sort '((1 3) (2 2) (3 1)) (lambda (p q) (< (cadr p) (cadr q))))
'((3 1) (2 2) (1 3))
```

::: details Solution
```scheme
#lang racket
(provide add-edge build-tree)
(struct node (val kids) #:transparent)
(struct leaf (val) #:transparent)
(define (value t)
(match t
[(leaf x) x]
[(node x kids) x]))
(define (sortnodes ns)
(sort ns (lambda (p q) (< (value p) (value q)))))
(define (add-edge edge tree)
(define s (car edge))
(define t (cadr edge))
(match tree
[(leaf x)
(if (= x s)
(node x (list (leaf t)))
(leaf x))]
[(node x kids)
(if (= x s)
(node x (sortnodes (cons (leaf t) kids)))
(node x (map (curry add-edge edge) kids)))]
))
(define (build-tree init edges) (foldl add-edge init edges))
; (define (build-tree init edges))
; (add-edge '(2 4) (node 1 (list (le))))
(add-edge '(2 4) (leaf 2))
(add-edge '(2 4) (node 1 (list (leaf 2) (leaf 3))))
(build-tree (leaf 1) '((1 2) (1 3) (2 4) (4 5) (3 6)))
(node 1 (list (node 2 (list (node 4 (list (leaf 5))))) (node 3 (list (leaf 6)))))
```
:::

## Haskell

In Haskell, implement a function
`buildTree :: Ord a => Tree a -> [Edge a] -> Tree a` that takes an initial
tree and a list of edges, and returns the tree created by expanding
the initial tree by the edges.

To represent trees and edges, use the following data types:
```haskell
data Tree a = Leaf { val :: a }
| Node { val :: a,
kids :: [Tree a] } deriving (Eq,Show)

type Edge a = (a,a)
```
Thus the leaves (nodes without children) are represented as, for instance, `Leaf {val = 6}`.
The nodes with children are represented as, for instance,
```haskell
Node {val = 1, kids = [Leaf {val = 2,Leaf {val = 3}]}
```

To implement the function `buildTree`, implement first a function
```haskell
addEdge :: Eq a => Tree a -> Edge a -> Tree a
```
expanding a given tree by a single edge. For example,
```haskell
> addEdge (Node {val = 1, kids = [Leaf {val = 2}, Leaf {val = 3}]}) (2,4)
Node {val = 1, kids = [Node {val = 2, kids = [Leaf {val = 4}]},
Leaf {val = 3}]}
```

When you add a new leaf to a list of children, prepend it at the front. For example,
```haskell
> addEdge (Node {val = 1, kids = [Leaf {val = 2}]}) (1,3)
Node {val = 1, kids = [Leaf {val = 3}, Leaf {val = 2}]}
```

To make the output of the function `buildTree` unique, sort the children of every node
in the resulting tree based on their values. You may assume, that the node values belongs to
the typeclass `Ord`. For example,

```haskell
Node {val = 1, kids = [Node {val = 2, kids = [Leaf {val = 4}]},
Leaf {val = 3}]} -- correct
Node {val = 1, kids = [Leaf {val = 3},
Node {val = 2, kids = [Leaf {val = 4}]}]} -- not correct
```

Your file should be called `Task4.hs` and should export the `buildTree`,
`addEdge` functions and the type `Tree`.

```haskell
module Task4 (addEdge, buildTree, Tree(..)) where
import Data.List

data Tree a = Leaf { val :: a }
| Node { val :: a,
kids :: [Tree a] } deriving (Eq,Show)

type Edge a = (a,a)

addEdge :: Eq a => Tree a -> Edge a -> Tree a
-- implement me!

buildTree :: Ord a => Tree a -> [Edge a] -> Tree a
-- implement me!
```

### Example

```haskell
> buildTree (Leaf {val=1}) [(1,2),(1,3),(5,7),(2,4),(4,5),(3,6)]
Node {val = 1, kids = [Node {val = 2, kids = [Node {val = 4,
kids = [Leaf {val = 5}]}]},
Node {val = 3, kids = [Leaf {val = 6}]}]}
```

### Hints

To sort the children, use the function `sortOn :: Ord b => (a -> b) -> [a] -> [a]`
from the library `Data.List` sorting a list by converting them into a values of
a type inside `Ord`. For example,
```haskell
> sortOn snd [(1,3),(2,2),(3,1)]
[(3,1),(2,2),(1,3)]
```

::: details Solution
```haskell
import Data.List

data Tree a = Leaf { val :: a }
| Node { val :: a,
kids :: [Tree a] } deriving Show
type Edge a = (a,a)

tr = Node {val = 1, kids = [Leaf {val = 2},Leaf {val = 3}]}

addEdge (Leaf x) (s,t) | x == s = Node x [Leaf t]
| otherwise = Leaf x
addEdge (Node x kids) (s,t)
| x == s = Node x (sortOn val ((Leaf t):kids))
| otherwise = Node x [addEdge n (s,t) | n <- kids]


buildTree tree edges = foldl addEdge tree edges
```
:::
17 changes: 17 additions & 0 deletions exams/building-trees/task.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Data.List

data Tree a = Leaf { val :: a }
| Node { val :: a,
kids :: [Tree a] } deriving Show
type Edge a = (a,a)

tr = Node {val = 1, kids = [Leaf {val = 2},Leaf {val = 3}]}

addEdge (Leaf x) (s,t) | x == s = Node x [Leaf t]
| otherwise = Leaf x
addEdge (Node x kids) (s,t)
| x == s = Node x (sortOn val ((Leaf t):kids))
| otherwise = Node x [addEdge n (s,t) | n <- kids]


buildTree tree edges = foldl addEdge tree edges
41 changes: 41 additions & 0 deletions exams/building-trees/task.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#lang racket

(provide add-edge build-tree)

(struct node (val kids) #:transparent)
(struct leaf (val) #:transparent)

(define (value t)
(match t
[(leaf x) x]
[(node x kids) x]))

(define (sortnodes ns)
(sort ns (lambda (p q) (< (value p) (value q)))))


(define (add-edge edge tree)
(define s (car edge))
(define t (cadr edge))
(match tree
[(leaf x)
(if (= x s)
(node x (list (leaf t)))
(leaf x))]
[(node x kids)
(if (= x s)
(node x (sortnodes (cons (leaf t) kids)))
(node x (map (curry add-edge edge) kids)))]
))


(define (build-tree init edges) (foldl add-edge init edges))

; (define (build-tree init edges))
; (add-edge '(2 4) (node 1 (list (le))))
(add-edge '(2 4) (leaf 2))
(add-edge '(2 4) (node 1 (list (leaf 2) (leaf 3))))


(build-tree (leaf 1) '((1 2) (1 3) (2 4) (4 5) (3 6)))
(node 1 (list (node 2 (list (node 4 (list (leaf 5))))) (node 3 (list (leaf 6)))))
47 changes: 47 additions & 0 deletions exams/building-trees/trees.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
\documentclass[border=0pt]{standalone}
\usepackage{graphicx}
\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage{bm}
\usepackage{pgf}
\usepackage{tikz}
\usetikzlibrary{arrows,automata,positioning}

\definecolor{myGray}{rgb}{0.85,0.85,0.85}

\begin{document}

\begin{tikzpicture}
\node (1) {$1$};

\node[right=of 1] (12) {$1$}
child {node {$2$}};

\node[right=1.5cm of 12] (123) {$1$}
child {node {$2$}}
child {node {$3$}};

\node[right=2cm of 123] (123') {$1$}
child {node {$2$}}
child {node {$3$}};

\node[right=2cm of 123'] (1234) {$1$}
child {node {$2$}
child {node {$4$}}}
child {node {$3$}};

\node[right=2cm of 1234] (12345) {$1$}
child {node {$2$}
child {node {$4$}
child {node {$5$}}}}
child {node {$3$}};

\node[right=2cm of 12345] {$1$}
child {node {$2$}
child {node {$4$}
child {node {$5$}}}}
child {node {$3$}
child {node {$6$}}};

\end{tikzpicture}
\end{document}
8 changes: 4 additions & 4 deletions exams/filetree/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ subtitle: "In Racket and Haskell"
A filetree can be used to efficiently search/replace in large filesystems.
You can think of it as a tree with a variable size of nodes

```{.tight-code}
```
.
├── scripts
│   ├── emptydir
Expand Down Expand Up @@ -138,9 +138,9 @@ For splitting a string into a list of strings you can make use of the function `

## Haskell

For the Haskell implementation you are provided with a module [`FTree.hs`](../../code/FTree.hs)
which contains a `FTree` type including a `Data.Map` from keys to values. We quote the definition
here:
For the Haskell implementation you are provided with a module
[`FTree.hs`](https://github.com/aicenter/FUP/blob/main/code/FTree.hs) which contains a `FTree` type
including a `Data.Map` from keys to values. We quote the definition here:
```haskell
import Data.Map (Map)
import qualified Data.Map as Map
Expand Down
Loading

0 comments on commit c453556

Please sign in to comment.