blog/src/aoc-2021-jour-1-sonar-sweep.md

113 lines
4.1 KiB
Markdown
Raw Normal View History

# AoC 2021 Jour 1: Sonar Sweep
À la recherche de la clef du traîneau à l'aide d'un sonar.
Le défi peut être trouvé [ici](https://adventofcode.com/2021/day/1), et le code
lié est sur [gitlab](https://gitlab.com/lovallat/advent-of-code-2021/-/tree/master/day1).
## Consigne du défi
Le premier puzzle est assez simple, et peut se résumer en "compter les variations
dans un fichier d'entrée".
## Lecture du fichier d'entrée
Pour lire le fichier, rien de plus simple. L'entrée étant une simple liste d'entiers
séparés par des retours à la ligne, il est assez facile de le transformer en
tableau d'entiers.
En code, cela se traduit par :
```rust
fn parse_input(s: &str) -> Vec<i32> {
return s.split("\n").into_iter().filter_map(|f| f.parse::<i32>().ok()).collect::<Vec<i32>>();
}
```
Maintenant que j'ai acquis un peu plus d'expérience en Rust, je le ferais d'une
manière assez différente :
- tout d'abord, `s.split("\n").into_iter()` peut être remplacé par `s.lines()`,
plus robuste et [System Agnostic](https://en.wikipedia.org/wiki/Agnostic_(data)),
les systèmes Windows utilisant une fin de ligne [différente](https://en.wikipedia.org/wiki/Newline#In_programming_languages).
- ensuite, utiliser des `u16`, soit des entiers non signés et encodés sur 16 bits.
Ici utiliser 32 bits signés pour stocker des valeurs relativement faibles (dans ce
jeu de données) et strictement positives n'est pas optimal.
## Première partie
La première partie nécessite de compter les augmentations de nombres un-à-un.
Nous avons donc un tableau (vecteur) d'entiers, alors il suffira simplement de le
parcourir, et si l'entier actuel est plus grand que le précédent, alors on retient
qu'on a vu une augmentation supplémentaire.
Le code de cette partie est le suivant :
```rust
fn get_increase_nb(e: &Vec<i32>) -> i32 {
let mut n = 0;
for i in 1..e.len() {
n += if e[i] > e[i - 1] { 1 } else { 0 };
}
return n;
}
```
On a donc un entier `n` qui va retenir le nombre d'augmentations observées,
et pour tous les entiers du tableau, de la case 1 (les tableaux en informatique
débutent à la case 0), à la case `taille` (non incluse, toujours parce que les
tableaux commencent à 0). Si le nombre actuel est plus grand que le précédent,
alors `n` augmente de 1.
## Deuxième partie
Pour cette deuxième partie, le concept est le même mais cette fois on prend les
entiers d'entrée par groupe de 3 et on compte les augmentations entre chaque
sommes d'entiers.
On transforme donc le tableau d'entiers en un second tableau correspondant aux
sommes de 3 entiers selon une fenêtre flottante.
```rust
fn get_sums(v: &Vec<i32>) -> BTreeMap<usize, i32> {
let mut sums = BTreeMap::new();
for i in 0..(v.len() - 2) {
sums.insert(i, v[i] + v[i + 1] + v[i + 2]);
}
return sums;
}
```
Ici, une [BTreeMap](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html)
est **totalement** inutile. Je ne sais pas trop pourquoi j'ai choisi ce type de
structure de données. Surtout qu'après, cette Map est convertie en simple tableau
en ignorant totalement la clef :
```rust
let map = get_sums(&vec_in).iter().map(|e| e.1.to_owned()).collect::<Vec<i32>>();
```
Ici il serait *beaucoup plus intéressant* d'utiliser un simple tableau, et à chaque
nouvelle somme on peut l'envoyer sur le dessus du tableau (de sommes) d'entiers.
Ce tableau enfin obtenu sera alors envoyé à la même méthode que pour la partie une
pour en obtenir le nombre d'augmentations.
Évidemment il serait aussi possible de simplement compter les augmentations en même
temps que l'on parcourt les tableaux, pour éviter de multiples passages.
## Conclusion
Ce puzzle était loin d'être compliqué. J'ai passé un peu de temps sur la
compréhension du système de sommes de la partie 2, ne sachant que faire dans le
cas où il n'y avait plus assez d'entiers pour faire une somme.
Après un peu de temps et d'essais, j'ai pu m'en sortir sans difficulté.
Concernant la qualité du code, je me demande bien ce que j'ai pu penser sur le
moment pour choisir de stocker les sommes dans une map à arbre binaire...
> À suivre