# 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 { return s.split("\n").into_iter().filter_map(|f| f.parse::().ok()).collect::>(); } ``` 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 { 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) -> BTreeMap { 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::>(); ``` 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