2022-01-18 12:17:03 +01:00
|
|
|
# AoC 2021 Jour 1: Sonar Sweep
|
|
|
|
|
|
|
|
À la recherche de la clef du traîneau à l'aide d'un sonar.
|
|
|
|
|
2022-01-18 12:20:28 +01:00
|
|
|
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).
|
2022-01-18 12:17:03 +01:00
|
|
|
|
|
|
|
## 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 étaient loin d'être compliqués. 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
|
|
|
|
|