Skip to content

Commit 7d27aa9

Browse files
committed
hide solutions
1 parent 8010553 commit 7d27aa9

19 files changed

+423
-358
lines changed
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script setup>
2+
import { onMounted } from 'vue'
3+
import { useRoute } from 'vitepress'
4+
5+
const FIRST_LAB = new Date('2025-02-18T11:00:00+01:00').getTime();
6+
7+
const route = useRoute()
8+
9+
onMounted(() => { handlePageChange() })
10+
11+
function hide_details(reveal_date) {
12+
const detailsElements = document.querySelectorAll('details[hideme]');
13+
for (const details of detailsElements) {
14+
const summary = details.querySelector('summary');
15+
const summaryContent = summary ? summary.outerHTML : '';
16+
details.innerHTML = `${summaryContent} Solutions will be revealed at ${reveal_date}.`;
17+
}
18+
}
19+
function handlePageChange() {
20+
const now = new Date(Date.now()).getTime();
21+
const page_week_no = parseInt(route.path.match(/\d+/)[0]) - 1;
22+
const millis_in_day = 24 * 60 * 60 * 1000;
23+
const reveal_at = FIRST_LAB + (3 + 7 * page_week_no) * millis_in_day;
24+
const days_left = Math.floor((reveal_at - now) / millis_in_day);
25+
const should_reveal = days_left <= 0;
26+
27+
if (!should_reveal) {
28+
hide_details(new Date(reveal_at).toLocaleDateString());
29+
}
30+
}
31+
</script>
32+
33+
<template>
34+
</template>

.vitepress/config.mts

+7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import { withMermaid } from 'vitepress-plugin-mermaid'
66
export default withMermaid(
77
// https://vitepress.dev/reference/site-config
88
defineConfig({
9+
vue: {
10+
template: {
11+
compilerOptions: {
12+
isCustomElement: (tag) => tag.startsWith('mjx-')
13+
}
14+
}
15+
},
916
title: "Functional Programming",
1017
description: "Course materials for the functional programming course at the Czech Technical University.",
1118
base: "/FUP/",

.vitepress/theme/index.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import DefaultTheme from 'vitepress/theme-without-fonts'
2+
import SolutionHider from '../components/SolutionHider.vue'
23
import './custom.css'
34

4-
export default DefaultTheme
5+
export default {
6+
...DefaultTheme,
7+
enhanceApp({ app }) {
8+
app.component('SolutionHider', SolutionHider)
9+
}
10+
}

labs/lab01.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
outline: deep
33
---
4+
<SolutionHider/>
45

56
# Lab 1: Introduction to Racket
67

@@ -110,7 +111,7 @@ Write a function `num-of-digits` that takes an integer `n` and computes the numb
110111
The number of digits can be computed by successively dividing the input number by 10. For integer division, you can use the function `quotient`.
111112
:::
112113

113-
::: details Solution
114+
::: details Solution { hideme }
114115
```racket
115116
(define (num-of-digits n [acc 1])
116117
(define q (quotient n 10))
@@ -130,7 +131,7 @@ You can obtain the representation by consecutively dividing `n` by the `radix` a
130131
:::
131132

132133

133-
::: details Solution
134+
::: details Solution { hideme }
134135
::: code-group
135136
```racket [direct]
136137
(define (num->str n [radix 10])

labs/lab02.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# Lab 02: Lists & Trees
1+
<SolutionHider/>
22

3+
# Lab 02: Lists & Trees
34

45
The main purpose of this lab is to practice elementary recursive manipulation with lists. Lists can be
56
decomposed by functions `car` and `cdr`. On the other hand, lists can be built by functions
@@ -140,7 +141,7 @@ your implementation function can return precise rational numbers like `(average-
140141
1/2`. If you want to have the usual floating-point representation, use the function
141142
`exact->inexact`, transforming the result into the imprecise floating-point representation.
142143

143-
::: details Solution
144+
::: details Solution { hideme }
144145
```racket
145146
(define (average-list lst)
146147
(define (iter l acc)
@@ -174,7 +175,7 @@ numbers and returns a list of averages of these `n`-tuples. E.g. `(n-block-avera
174175
built segment of consecutive elements. The second tracks how many elements we must read from the
175176
list to complete the `n`-tuple of consecutive elements.
176177

177-
::: details Solution
178+
::: details Solution { hideme }
178179
```racket
179180
(define (split-list n lst)
180181
(define (iter l k segment)

labs/lab03.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<SolutionHider/>
2+
13
# Lab 3: Higher-order functions
24

35
## Exercise 1
@@ -144,7 +146,7 @@ multiplied by respective coefficients. Then it suffices to sum them component by
144146
:::
145147

146148

147-
::: details Solution
149+
::: details Solution { hideme }
148150
```racket
149151
(define (scalar-mult coef vec)
150152
(map (curry * coef) vec))
@@ -186,7 +188,7 @@ To define the matrix power, use the `foldl` function applied to a list composed
186188
```
187189

188190

189-
::: details Solution
191+
::: details Solution { hideme }
190192
```racket
191193
(define (matrix-mult m1 m2)
192194
(map (linear-combination m2) m1))

labs/lab04.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
outline: deep
33
---
4+
<SolutionHider/>
45

56
# Lab 4: Higher-order functions and tree recursion
67

@@ -172,7 +173,7 @@ taking a list `lst` and returning a list of all its sublists/subsequences. E.g.
172173
Code it as a recursive function using the following facts. 1) There is only a single subsequence of the empty list, namely the empty list. 2) Subsequences of $(x_1,x_2,\ldots,x_n)$ are just subsequences of $(x_2,\ldots,x_n)$ together with subsequences starting with $x_1$ and following by a subsequence of $(x_2,\ldots,x_n)$.
173174
:::
174175

175-
::: details Solution
176+
::: details Solution { hideme }
176177
```racket
177178
(define (sub-seq lst)
178179
(if (null? lst)
@@ -225,7 +226,7 @@ path labelled by the winner and collects the beaten teams along the path to an a
225226
use nested patterns in pattern matching to find out the losers.
226227
:::
227228

228-
::: details Solution
229+
::: details Solution { hideme }
229230
```racket
230231
(define (beaten-teams tree [acc '()])
231232
(match tree

labs/lab05.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
outline: deep
33
---
4+
<SolutionHider/>
45

56
# Lab 5: Streams and graphs
67

@@ -166,7 +167,7 @@ elements:
166167
(apply + (stream->list (stream-take (exp-stream 1) 100)))
167168
```
168169

169-
::: details Solution
170+
::: details Solution { hideme }
170171
```racket
171172
(define (stream-mul s1 s2)
172173
(stream-cons (* (stream-first s1) (stream-first s2))
@@ -246,7 +247,7 @@ first.
246247
(lambda (x y) (< (length x) (length y)))))))
247248
```
248249

249-
::: details Solution
250+
::: details Solution { hideme }
250251
```racket
251252
; minimum vertex cover
252253
; -> smallest subset of nodes such that each edge has one of its nodes in it

labs/lab06.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<SolutionHider/>
2+
13
# Lab 6: Interpreter of Brainf*ck
24

35
This lab is closely related to the corresponding lecture. In that lecture, I showed how to implement

labs/lab07.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# Lab 7: Lambda calculus
1+
<SolutionHider/>
22

3+
# Lab 7: Lambda calculus
34

45
This lab focuses on lambda calculus. First, we focus on the syntax of $\lambda$-expressions. Second,
56
we focus on its semantics, i.e., the computation specified by $\lambda$-expressions whose one step

labs/lab08.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
<SolutionHider/>
2+
13
# Lab 8: Haskell basics
24

35
The aim of the lab is to practice function definitions using pattern matching and guarded equations together with the list comprehension.
@@ -103,7 +105,7 @@ a string consisting of `n` copies of `str`. E.g.
103105
copy 3 "abc" => "abcabcabc"
104106
```
105107

106-
::: details Solution
108+
::: details Solution { hideme }
107109
```haskell
108110
copy :: Int -> String -> String
109111
copy n str | n <= 0 = ""
@@ -146,7 +148,7 @@ Since the numbers are processed from right to left, reverse first the list by th
146148
to be luhnDoubled and the rest.
147149
:::
148150

149-
::: details Solution
151+
::: details Solution { hideme }
150152
```haskell
151153
luhnDouble :: Int -> Int
152154
luhnDouble n | n > 4 = 2*n - 9

labs/lab09.md

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
# Lab 9: Haskell types
1+
<SolutionHider/>
22

3+
# Lab 9: Haskell types
34

45
## Exercise 1
56
Define a type representing binary trees storing data in leaves of a general type `a`. Each
67
non-leaf node has always two children. Make your type an instance of the class `Show` so it can be
7-
displayed in an XML-like format. A leaf node containing a datum `x`
8+
displayed in an XML-like format. A leaf node containing a datum `x`
89
should be displayed as `<Leaf
910
x/>` and an inner
1011
node `<Node>...children nodes...</Node>`. E.g., the following tree
@@ -40,7 +41,7 @@ data Tree a = Leaf a | Node (Tree a) (Tree a)
4041

4142
To make `Tree a` an instance of the `Show` class. We have to constrain type `a` to be an instance
4243
of `Show`; otherwise, it would not be clear how to display the data stored in the tree. The
43-
definition of the function `show` is then straightforward.
44+
definition of the function `show` is then straightforward.
4445
::: details Solution
4546
```haskell
4647
instance (Show a) => Show (Tree a) where
@@ -85,11 +86,11 @@ For the tree from the previous exercise, we have
8586
```
8687

8788
## Exercise 3
88-
Consider again the `Tree a` data type from Exercise 1. Write a function
89+
Consider again the `Tree a` data type from Exercise 1. Write a function
8990
```haskell
9091
labelTree :: Tree a -> Tree (a, Int)
9192
```
92-
labeling the leaves of a tree by consecutive natural numbers in the infix order. So it should replace a leaf datum `x`
93+
labeling the leaves of a tree by consecutive natural numbers in the infix order. So it should replace a leaf datum `x`
9394
with the pair `(x,n)` for some natural number. So we would like to obtain something like that:
9495
```
9596
* *
@@ -102,13 +103,13 @@ with the pair `(x,n)` for some natural number. So we would like to obtain someth
102103
```
103104
104105
::: tip
105-
The idea behind this function will be helpful to your homework assignment. So try to understand it well.
106+
The idea behind this function will be helpful to your homework assignment. So try to understand it well.
106107
:::
107108
108109
To traverse through the nodes (particularly leaves) can be easily done recursively. The problem is with the counter for labels.
109110
In an imperative programming language, we could introduce a variable `counter` and initialize it by 0. Once we encounter a leaf, we label
110111
it with `counter` and modify
111-
`counter = counter + 1`. Unfortunately, we cannot do that in a purely functional language like Haskell.
112+
`counter = counter + 1`. Unfortunately, we cannot do that in a purely functional language like Haskell.
112113
113114
We need an accumulator in the signature of the labeling function holding the counter value. So we could think of a helper function
114115
```haskell
@@ -144,7 +145,7 @@ labelTree t = fst (labelHlp t 0)
144145
## Task 1
145146
Define a recursive data type `Polynomial a` representing univariate polynomials with an
146147
indeterminate $x$ whose coefficients are of a general type `a`. The definition will have two data
147-
constructors. First, `Null`
148+
constructors. First, `Null`
148149
represents the zero polynomial. Second, `Pol` whose parameters are a
149150
monomial and recursively the rest of the polynomial. Monomials should be represented as pairs of
150151
type `(a, Int)` where the first component is the coefficient and the second is the exponent. E.g.
@@ -180,14 +181,14 @@ has no `x^0`. Then define the instance of `Show` for `Polynomial a`. You need
180181
`show` function in the same way as `format`.
181182
:::
182183

183-
::: details Solution
184+
::: details Solution { hideme }
184185
```haskell
185186
type Monomial a = (a, Int)
186187
data Polynomial a = Null | Pol (Monomial a) (Polynomial a)
187188

188189
format :: (Show a, Num a, Ord a) => Monomial a -> String
189190
format (c, e) | e == 0 = display c
190-
| otherwise = display c ++ "x*^" ++ show e
191+
| otherwise = display c ++ "x*^" ++ show e
191192
where display k | k >= 0 = show k
192193
| otherwise = "(" ++ show k ++ ")"
193194

@@ -199,18 +200,18 @@ instance (Show a, Num a, Ord a) => Show (Polynomial a) where
199200
:::
200201

201202
## Task 2
202-
Write a function
203+
Write a function
203204
```haskell
204-
getDegree :: Polynomial a -> Int
205+
getDegree :: Polynomial a -> Int
205206
```
206207
returning the degree of a given polynomial. The zero polynomial has a degree $-1$ by definition. Otherwise, you have to find the highest exponent occurring in the polynomial.
207208

208-
::: details Solution
209+
::: details Solution { hideme }
209210
```haskell
210211
getDegree :: Polynomial a -> Int
211212
getDegree p = iter p (-1) where
212213
iter Null n = n
213214
iter (Pol (_, e) ms) n | e > n = iter ms e
214-
| otherwise = iter ms n
215+
| otherwise = iter ms n
215216
```
216217
:::

0 commit comments

Comments
 (0)