Added article AoC2021-Day1
Signed-off-by: Louis Vallat <louis@louis-vallat.xyz>
This commit is contained in:
parent
0e49ead29a
commit
2bc3878090
111
src/aoc-2021-jour-1-sonar-sweep.md
Normal file
111
src/aoc-2021-jour-1-sonar-sweep.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# 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).
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user