1
0
Fork 0
mirror of https://github.com/mfocko/blog.git synced 2025-05-11 05:42:57 +02:00

chore: transfer all KBs to single one

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2022-11-05 15:24:54 +01:00
parent d207e870d4
commit 7427475022
Signed by: mfocko
GPG key ID: 7C47D46246790496
159 changed files with 28847 additions and 0 deletions

5
pb071/00-intro-pb071.md Normal file
View file

@ -0,0 +1,5 @@
---
id: pb071-intro
title: Introduction
slug: /intro
---

49
pb071/bonuses/03.md Normal file
View file

@ -0,0 +1,49 @@
---
id: seminar-03
title: 3rd seminar
description: |
Select sort implementation on arrays.
---
This assignment has two versions. For the light version you can get 0.5 K₡. For
the _full fat_ one 1 K₡. **You can choose only one of them**.
To both of them you are given some basic tests. You can also have a look at the
code used by the tests and use it to your advantage.
Details can be found in the doxygen comments included in the source files.
## Light version (`main_light.c`)
[Source](pathname:///files/pb071/bonuses/03/main_light.c)
For the light version you have 3 functions to finish:
1. `swap` - that swaps two ints passed by pointers.
2. `maximum` - that returns index of the biggest `int` in the array.
3. `select_sort` - that sorts passed array using Select Sort.
## Full fat version (`main.c`)
[Source](pathname:///files/pb071/bonuses/03/main.c)
For the full fat version you have 4 functions to implement:
1. `swap` - that swaps two variables passed by pointers.
2. `maximum` - that returns index of the biggest element in the array using the
comparator.
3. `select_sort` - that sorts passed array using Select Sort.
4. `int_comparator` - that is used for generic sort and maximum
To 2nd and 3rd function you are given a pseudocode that you can use to implement
it.
## Submitting
Ideally submit the assignment through the merge request. Step-by-step tutorial is
present [here](../mr). For setting assignee my xlogin is `xfocko`.
In case you do not want to experiment on GitLab, send me the source code via email,
but please prefix subject with: `[PB071/14][seminar-03]`
Deadline for the submission of the bonus is **March 27th 24:00**.

165
pb071/bonuses/04.md Normal file
View file

@ -0,0 +1,165 @@
---
id: seminar-04
title: 4th seminar
description: |
Robot in a maze.
---
For this bonus you can get 1.5 K₡ and another 0.5 K₡ for the bonus part of it.
[Source](pathname://files/pb071/bonuses/04/)
## Introduction
In this task you are given a 2D map for a robot. The map contains multiple markers:
- `^v<>` - which denote the directions the robot will be facing when he steps into
the cell or starts on it.
- `K` - denotes the key.
- `T` - denotes the treasure.
In case robot lands at the beginning on unknown field, e.g. `.` in the tests, he
faces the direction that is given through the parameter.
Your task is to write the `walk` function that returns end result of the walk.
Walk can end in multiple ways:
- `FOUND_TREASURE` - when you find the treasure
- `FOUND_KEY` - when you find the key
- `OUT_OF_BOUNDS` - when the robot falls off the map
- `INFINITE_LOOP` - in case you will implement the bonus
- `NONE` - which is used right now as a default return in the skeleton, has no meaning
later on
## Hard requirement
There is only one hard requirement that tests cannot check.
**You are not allowed to use any indexing related to map or your current position**
**in your implementation.**
Reason for this requirement is for you to get used to working with pointers. And
for the implementation of this task it is much easier to use just the pointers.
## Example of run
For a better understanding of your task, I will describe a simple walk with corresponding
function call.
```c
const char *map = (
">.v"
".K<"
"..."
);
walk(map, &map[6], '^', 3, 3);
```
For this call, you should return `FOUND_KEY`. Let us walk through the walk ;)
1. Robot is placed at the bottom left corner, there is no direction specified, so
he follows the direction given by parameter (upwards, denoted as `N`(orth),
so that we can differentiate markers on the map with the robot when using printing
function).
```
>.v
.K<
N..
```
2. Moves up:
```
>.v
NK<
...
```
3. Moves up (now covers `>`), changes direction to right:
```
E.v
.K<
...
```
4. Moves to right:
```
>Ev
.K<
...
```
5. Moves to right, faces south:
```
>.S
.K<
...
```
6. Moves down, faces west:
```
>.v
.KW
...
```
7. Moves left, founds key, returns `FOUND_KEY`:
```
>.v
.W<
...
```
## Bonus part
For the bonus part you are supposed to return `INFINITE_LOOP` in case the robot
is stuck in the infinite loop. There are three tests for it. If you pass only the
easy and medium one, you can get 0.25 K₡ for doing your best and trying it out. :)
## Easter eggs
- Statistics
| Language | Files | Lines | Blanks | Comments | Code | Complexity |
| ---------------- | ----: | ----: | -----: | -------: | ---: | ---------: |
| _C_ | 4 | 458 | 34 | 58 | 366 | 33 |
| `test_maze.c` | | 225 | 9 | 0 | 216 | 4 |
| `sol.maze.c` | | 141 | 15 | 28 | 98 | 24 |
| `maze.c` | | 84 | 8 | 30 | 46 | 5 |
| `main.c` | | 8 | 2 | 0 | 6 | 0 |
| _C Header_ | 1 | 33 | 3 | 19 | 11 | 0 |
| `maze.h` | | 33 | 3 | 19 | 11 | 0 |
| _CMake_ | 1 | 25 | 4 | 6 | 15 | 2 |
| `CMakeLists.txt` | | 25 | 4 | 6 | 15 | 2 |
| **Total** | 6 | 516 | 41 | 83 | 392 | 35 |
- Majority of the line count in solution is caused by the formatting :)
- Included headers can be interpreted as hints, same goes for the unimplemented
`static` functions which you can use, but **are not required**.
- Given `CMakeLists.txt` will generate 2 binaries, `test_maze` and `maze`.
- `test_maze` runs the tests you are given.
- `maze` runs the `main.c`, where you can debug, print mazes and whatever else
you want.
- I keep only one copy of `cut.h` in my repository, so you need to download it from
[here](https://gitlab.fi.muni.cz/pb071/cut/-/jobs/159010/artifacts/file/1header/cut.h) and place it into the directory where you have your source code.
- I would recommend cloning this repository and copying the `maze` directory to
your own repository, since there are multiple files and it may be easier for you.
In case you have any questions, feel free to reach out to me.
## Submitting
Ideally submit the assignment through the merge request. Step-by-step tutorial is
present [here](../mr). For setting assignee my xlogin is `xfocko`.
In case you do not want to experiment on GitLab, send me the source code via email,
but please prefix subject with: `[PB071/14][seminar-04]`
Deadline for the submission of the bonus is **April 5th 24:00**.

169
pb071/bonuses/05-06.md Normal file
View file

@ -0,0 +1,169 @@
---
id: seminar-05-06
title: 5th and 6th seminar
description: |
200IQ encryption.
---
For this bonus you can get at maximum 2.5 K₡.
[Source](pathname:///files/pb071/bonuses/05-06/)
## Introduction
In this bonus you will implement few functions that will be used together for
implementing a very special cipher.
### Task no. 1: Reverse (0.5 K₡)
Write a function `char* reverse(const char* text)` that returns copy of the input
string in reversed order (also uppercase).
In case you are given `NULL`, return `NULL`.
Example (more in tests):
```c
char* reversed = reverse("Hello world!");
printf("%s\n", reversed);
// "!DLROW OLLEH"
if (reversed != NULL) {
free(reversed);
}
```
### Task no. 2: Vigenère (0.5 K₡)
Vigenère cipher is similar to the Caesar cipher, but you also have a key that is
used for encrypting (or decrypting).
Your task is to write two functions:
- `char* vigenere_encrypt(const char* key, const char* text)` for encrypting
- `char* vigenere_decrypt(const char* key, const char* text)` for decrypting
In both of those you should return uppercase characters.
Meaning of the parameters you are given:
- `key` - String that represents key that is used for \*crypting. It consists of
one word and can have only characters of the alphabet. Does not matter if they
are uppercase or lowercase.
- `text` - String that is to be \*crypted.
Function returns address of the encrypted (or decrypted) string. Or `NULL` in case
error occurs.
Example:
```c
char *encrypted = vigenere_encrypt("CoMPuTeR", "Hello world!");
printf("%s\n", encrypted);
// "JSXAI PSINR!"
if (encrypted != NULL) {
free(encrypted)
}
```
#### Bonus part (0.5 K₡)
If you can utilize helper function that would do both encrypting and decrypting,
you can gain 0.5 K₡.
Usage of `true`/`false` to decide path in code is prohibited. It leads to merging
of both functions into one. Point of this part is to discover a way to do this
generically in such way that there are no separate paths for one or the other. One
function with no branching for both of them, parametrization is your friend :)
### Task no. 3: Bit madness (0.5 K₡)
This is a state of the art crypto. Please do not share :)
For encrypting:
1. Split the character that is to be encrypted in halves (4 and 4 bits each).
2. Bits in 1st half are to be split into pairs. Swap bits in those pairs.
3. Then use the 4 bits that you created in the 2nd step for `XOR` with the other
4 bits.
This simple and ingenious principle will be illustrated on the following example.
String we want to encrypt is `Hello world!`. We need to encrypt each letter separately,
so we will demonstrate on letter `H`:
1. Letter `H` is represented in ASCII as `72`.
`72` represented in binary is: `01001000`. So first 4 bits are: `0100` and last
4 bits are `1000`.
2. First half of bits (`0100`) consists of 2 pairs (`01` and `00`) which we swap
(`01 ~> 10` and `00 ~> 00`). That way we get `1000`.
3. That half is used for xor with the other 4 bits:
```
1000 // second half
XOR 1000 // first half after 2nd step
--------
0000
```
4. Now we combine both halves (first one is `1000`, which we got from the 2nd step
and second one is `0000`, which we got from the 3rd step) and get `10000000`,
which is encrypted character `H` using this method.
In case of decryption, reverse those steps.
Your task is to implement functions:
- `unsigned char* bit_encrypt(const char* text)`
- `char* bit_decrypt(const unsigned char* text)`
Example:
```c
unsigned char* encrypted = bit_encrypt("Hello world!");
for (int i = 0; i < 12;i++) {
printf("%x ", encrypted[i]);
//80 9c 95 95 96 11 bc 96 b9 95 9d 10
}
if (encrypted != NULL) {
free(encrypted);
}
```
### Task no. 4: All combined to BMP (0.5 K₡)
Authors of the BMP cipher are non-disclosed :)
Create pair of functions:
- `unsigned char* bmp_encrypt(const char* key, const char* text)`
- `char* bmp_decrypt(const char* key, const unsigned char* text)`
BMP cipher consists of following steps for encrypting:
1. Reverse the input string
2. Use Vigenere on the string you got from step #1
3. Use bit madness on the string you got from step #2
For decrypting, reverse the steps.
## Submitting
In case you have any questions, feel free to reach out to me.
---
Ideally submit the assignment through the merge request. Step-by-step tutorial is
present [here](../mr). For setting assignee my xlogin is `xfocko`.
In case you do not want to experiment on GitLab, send me the source code via email,
but please prefix subject with: `[PB071/14][seminar-05-06]`
Deadline for the submission of the bonus is **April 21th 24:00**.

160
pb071/bonuses/08.md Normal file
View file

@ -0,0 +1,160 @@
---
id: seminar-08
title: 8th seminar
description: |
Manipulating with files only char-by-char and a magic tree.
---
# 8th seminar bonus assignment
[Source](pathname:///files/pb071/bonuses/08/)
## Introduction
In this bonus you can implement two tasks, one of them has a bonus part with generic
solution.
One is focused on counting ananas or in case of generic version any substring in
the file, but with a restriction on the function you use.
Other one has a more algorithmic spirit.
For this bonus you can get at maximum 2.5 K₡.
## Warning
**DO NOT COMMIT test data** to your own git repository, since the tests include
files that exceed 10MB by themselves. Even if they are on separate branch, they
take up the space.
## Testing
For testing you are provided with python script (requires `click` to be installed:
`pip3 install --user click`) and `Makefile` that provides following targets:
- `check-counting` - runs the `counting` tests
- `check-counting-bonus` - runs the `counting` tests with bonus implemented
- `check` - runs both `counting` and `counting-bonus` tests
- `clean` - removes output files from the test runs
## Task no. 1: Counting (0.75 K₡)
Your first task is to make smallish program that counts occurences of specific
(or given) word from file and writes the number to other file.
Usage of the program is:
```
Usage: ./counting <input-file> <output-file> [string-to-be-counted]
```
Arguments that are passed to the program represent:
- `<input-file>` - path to the file where we count the words
- `<output-file>` - path to the file where we output the count
- (optional argument) `[string-to-be-counted]` - in case you implement bonus,
otherwise we default to word `ananas` ;)
In skeleton you are given 3 empty, but documented, functions to implement.
1. `count_anything` - function accepts input file and substring to be counted in
the file, returns the count.
2. `count_ananas` - same as `count_anything`, but specialized for ananases, the
default implementation from the skeleton expects you to implement `count_anything`
and therefore it just calls the other function.
3. `write_number` - function that writes the number to the file, why would you
need the function is explained later :)
### Requirements
For manipulation with the files you are only allowed to use `fopen`, `fclose`,
`fgetc` and `fputc`. Functions like `fprintf` (except for `stderr` or logging) and
`fscanf` are **forbidden**.
In case you struggle and want to use one of those functions, the solution will be
penalized by 50% of points.
### Bonus part (0.75 K₡)
Bonus part of this assignment is to implement `count_anything` rather than `count_ananas`.
> Smaller hint: This task does not need dynamic allocation :) You just need one
> good helper function and the right idea ;)
## Task no. 2: Weird trees (1 K₡)
In this task we are crossing our paths with _algorithms and data structures_.
Your task is to write a program that constructs tree from the file that is given
as an argument and pretty-prints it.
Input file consists of lines, that include `key` and `rank` in form `key;rank`
or `nil`. Why would we have `nil` in a file? The file represents pre-order iteration
through the tree. Leaves never have rank different than 0, so you can safely assume
2 non-existing `nil`s in the input after you read such node ;)
<table><tr>
<td>
Example input file
```
8;4
5;3
3;2
2;1
1;0
nil
4;0
7;1
6;0
nil
11;2
10;1
9;0
nil
12;0
```
</td>
<td>
Tree it represents
![tree](/files/pb071/bonuses/08/tree.png)
</td>
</tr></table>
In this task you are only provided with different trees in the `test-trees` directory.
Implementation and format of the pretty-print is totally up to you. :)
Example of mine for the tree above:
```
8 (rank = 4)
+-- 5 (rank = 3)
| +-- 3 (rank = 2)
| | +-- 2 (rank = 1)
| | | +-- 1 (rank = 0)
| | +-- 4 (rank = 0)
| +-- 7 (rank = 1)
| +-- 6 (rank = 0)
+-- 11 (rank = 2)
+-- 10 (rank = 1)
| +-- 9 (rank = 0)
+-- 12 (rank = 0)
```
> Can you find out what are those trees? :)
## Submitting
In case you have any questions, feel free to reach out to me.
---
Ideally submit the assignment through the merge request. Step-by-step tutorial is
present [here](../mr). For setting assignee my xlogin is `xfocko`.
In case you do not want to experiment on GitLab, send me the source code via email,
but please prefix subject with: `[PB071/14][seminar-08]`
Deadline for the submission of the bonus is **May 4th 24:00**.

162
pb071/bonuses/10.md Normal file
View file

@ -0,0 +1,162 @@
---
id: seminar-10
title: 10th seminar
description: |
Finding bugs in a hangman.
---
[Source](pathname:///files/pb071/bonuses/10/)
## Introduction
For this bonus you are given almost finished project - The Hangman Game. Your
task is to try the game, in case you find any bugs point them out and cover as
much of the game as possible with tests.
For this bonus you can get at maximum 2 K₡.
| Item | Bonus |
| ---------------------------------------------- | ----- |
| Fixing bugs from failing tests | 0.25 |
| `word_guessed` | 0.50 |
| Hidden bug | 0.50 |
| Extending tests, undetectable bugs or evil bug | 0.37 |
| Refactor | 0.38 |
## Project
Project consists of 2 source files - `hangman.c` and `main.c`.
`main.c` is quite short and concise, there is nothing for you to do.
`hangman.c` contains implementation of the game. In case you feel lost, consult
the documentation in `hangman.h` that represents an interface that can be used
for implementing the game.
Apart from those sources this project is a bit more complicated. _Game loop_ is
realised via single encapsulated function that complicates the testing. Because
of that, there are 2 kinds of tests:
- _Unit tests_ - that are present in `test_hangman.c` and can be run via:
```
$ make check-unit
```
They cover majorly functions that can be tested easily via testing framework.
- _Functional tests_ - same as in `seminar-08` and are focused on testing the
program as whole. Basic smoke test is already included in `usage` test case.
They can be run via:
```
$ make check-functional
```
When testing `hangman` function (the game loop), it is suggested to create
functional tests.
When submitting the files for review, please leave out functional tests that
were given as a part of the assignment, so that it is easier to navigate, I
will drag the common files myself. :)
> Whole test suite can be run via:
>
> ```
> $ make check
> ```
### Summary of the gameplay
1. Secret word gets chosen from the file that's path is given as an argument.
2. You get 8 guesses.
3. Invalid characters don't count.
4. Already guessed characters don't count, even if not included in the secret.
5. You can guess the whole word at once
- If you get it right, you won, game ends.
- If you don't get it right, you get to see the secret, game ends.
6. In case of end of input, game finishes via force.
7. In case of invalid input, no guesses are subtracted, game carries on.
8. Letters and words are not case sensitive.
## Suggested workflow
As we have talked about on the seminar, I suggest you to follow
_Test-Driven Development_
in this case.
![TDD workflow](/files/pb071/bonuses/10/tdd_lifecycle.png)
In our current scenario we are already in the stage of refactoring and fixing the
bugs. Therefore try to follow this succession of steps:
1. Try to reproduce the bug.
2. Create a test that proves the presence of the bug.
3. Fix the bug.
In case you are submitting the bonus via GitLab, it is helpful to commit tests
before commiting the fixes, so that it is apparent that the bug is manifested.
Example of `git log` (notice that the first line represents latest commit):
```
feat: Implement fizz_buzzer
test: Add tests for fizz_buzzer
fix: Fix NULL-check in print_name
test: Add test for NULL in print_name
```
## Tasks
As to your tasks, there are multiple things wrong in this project.
1. There are 2 "bugs" that cannot be detected via tests, i.e. they are not bugs
that affect functionality of the game.
2. There is one evil bug in `get_word`. It is not required to be fixed ;) Assign
it the lowest priority.
3. There are some tests failing. Please try to figure it out, so you have green
tests for the rest :)
4. We have gotten a bug report for `word_guessed`, all we got is
> doesn't work when there are too many `a`s
Please try to replicate the bug and create a tests, so we don't get any
regression later on.
5. One hidden bug :) Closely non-specified, we cannot reproduce it and we were
drunk while playing the game, so we don't remember a thing. :/
6. Try to cover as much code via the tests as possible. We are not going to look
at the metrics, but DRY is violated a lot, so as a last task try to remove as
much of the duplicit code as possible.
Tests should help you a lot in case there are some regressions.
---
In case you wonder why there are always 3 same words in the file with words, it
is because of the `get_word` bug. It is not a bug that can be easily fixed, so
it is a not requirement at all and you can still get all points for the bonus ;)
## Dictionary
- [Functional tests](https://en.wikipedia.org/wiki/Functional_testing)
- [Smoke test](https://en.wikipedia.org/wiki/Smoke_testing_%28software%29)
- [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
## Submitting
In case you have any questions, feel free to reach out to me.
---
Ideally submit the assignment through the merge request. Step-by-step tutorial
is present [here](../mr). For setting assignee my xlogin is `xfocko`.
In case you do not want to experiment on GitLab, send me the source code via
email, but please prefix subject with: `[PB071/14][seminar-10]`
Deadline for the submission of the bonus is **May 17 24:00**.

View file

@ -0,0 +1,6 @@
label: Bonuses
position: 1
link:
type: generated-index
description: |
Bonus assignments for Kontr Coins.

136
pb071/mr.md Normal file
View file

@ -0,0 +1,136 @@
---
title: Submitting merge requests
---
# Submitting merge requests for review
This tutorial aims to show you how to follow basic git workflow and submit changes
through _Merge Requests_ for review.
The rudimentary idea behind aims for changes to be present on a separate branch
that is supposedly _merged_ into the default branch. Till then changes can be reviewed
on _Merge Request_ and additional changes may be made based on the reviews. Once
the changes satisfy requirements, the merge request is merged.
## Tutorial
> Use this tutorial only for bonus assignments **made by your tutors** or in case
> you need to make up for the absence.
### Step #1 - Starting from the clean repository
In your repository (either locally or on aisa) type `git status` and check if your
repository is clean and you are present on the main branch (`master`, `main` or
`trunk`). If you do not know what your default branch is, it is probably `master`
and you should not be on any other branch.
Output of the command should look like this:
```
aisa$ git status
On branch master # Or main or trunk.
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
```
> In case you are on different branch or there are uncommitted changes,
> **do not continue!!!** Clean your repository (commit the changes or discard
> them), before you continue.
### Step #2 - Create new branch
In your repository write command:
```
aisa$ git checkout -b BRANCH
Switched to a new branch 'BRANCH'
```
Instead of `BRANCH` use some reasonable name for the branch. For example if you
are working on the seminar from 3rd week, name the branch `seminar-03`.
### Step #3 - Do the assignment
Download the skeleton for the seminar assignment, extract and program. For example
if you are working on 3rd seminar, you can do so by:
```
aisa$ wget https://www.fi.muni.cz/pb071/seminars/seminar-03/pb071-seminar-03.zip
aisa$ unzip pb071-seminar-03.zip
# Now you should have directory 'seminar-03'.
aisa$ rm pb071-seminar-03.zip
aisa$ cd seminar-03
# You can work on the assignment.
```
### Step #4 - Commit and upload the changes to GitLab
The same way you _add_ and _commit_ files for the homework assignments, you do for
the seminar.
Now you can upload the changes to GitLab. `git push` is not enough, since repository
on GitLab does not know your new branch. You can solve this by adding arguments:
```
aisa$ git push origin BRANCH
...
remote: To create a merge request for BRANCH, visit:
remote: https://gitlab.fi.muni.cz/login/pb071/merge_requests/new?merge_request%5Bsource_branch%5D=BRANCH
...
```
In the output you should have a link for creating a merge request. If you see this
link, open it and skip next step.
### Step #5 - Creating a merge request manually
1. Open your repository on GitLab.
2. On the left panel click on _Merge Requests_.
3. Click on _New Merge Request_.
4. In _Source branch_ select `login/pb071` and `BRANCH`, which you created.
5. In _Target branch_ select `login/pb071` and your default branch you have seen
in the output of the first command. (most likely `master`)
6. Click on _Compare branches and continue_.
### Step #6 - Set assignees
On the page that is opened, please check at the top that you are creating merge
request **from** your new branch **to** your default branch (one of `master`, `main`
or `trunk`).
Then in the field _Assignees_ set your tutors based on the seminar group. You can
use login for a quick look up.
In the end click on _Submit merge request_.
### Step #7 - Return to default branch
Homework assignments can be submitted only from branches specified in the rules
for the course. Because of that, before you do anything else, you should switch
back to your default branch.
First of all, same as in step #1, check that your repository is clean with `git status`.
For the sake of safety, do not continue without clean repository. Then with command
`git checkout BRANCH` switch to your default branch `BRANCH`.
If you do not know which branch is your default, try `git branch` that outputs all branches in your repository. Default branch is typically `master`, but can
be `main` or `trunk`.
```
aisa$ git status
# Check if repository is clean
# If you know, what is your default branch, you can skip next command.
aisa$ git branch
# Find the default branch in the list; should be one of the `master`, `main` or
# `trunk` and you should not have more than one of those.
# In case the list clears the terminal and you cannot see shell prompt, you can
# press `q` to quit the pager.
aisa$ git checkout master
```
---
Adapted from: https://www.fi.muni.cz/~xlacko1/pb071/mr.html