Day 1: Secret Entrance
Table of Contents
Part 1
We are given line seperated operations that happen on a 100 pin circular dial. The dial starts at 50 and we are to output, how many times the dial stops at 0!
We first, as expected, just take in the input and initialise variables to store current dial position and total number of times the dial has stopped at 0.
use std::fs::read_to_string;fn main() { let contents = read_to_string("./input.txt").unwrap(); let mut curr: i32 = 50; let mut tot = 0;
<<logic_loop>>
println!("Password: {tot}");}We go through each line of input, and parse it. Our input is in the form -“L50” where the first character is the direction in which the dial is to be rotated and the rest is the amplitude.
for line in contents.lines() { let words: Vec<char> = line.chars().collect(); let dir = words[0]; let amp: String = words[1..].iter().collect(); let amp: i32 = amp.parse().unwrap();
<<rotate_dial>>}Now that we have both the dir and the amp, we can modify the dial position.
if dir == 'L' { curr -= amp;} else { curr += amp;}
<<loopback>>The value of curr could have gone above 99 or below 0, which we need to rectify.
if curr < 0 { curr = 100 + curr;}
curr = curr % 100;
<<count_zeros>>Now that we have the current position of the dial, we only need to check if it currently points at 0, and increment tot, if it does.
if curr == 0 { tot += 1;}We have the final program-
use std::fs::read_to_string;fn main() { let contents = read_to_string("./input.txt").unwrap(); let mut curr: i32 = 50; let mut tot = 0;
for line in contents.lines() { let words: Vec<char> = line.chars().collect(); let dir = words[0]; let amp: String = words[1..].iter().collect(); let amp: i32 = amp.parse().unwrap();
if dir == 'L' { curr -= amp; } else { curr += amp; }
if curr < 0 { curr = 100 + curr; }
curr = curr % 100;
if curr == 0 { tot += 1; } }
println!("Password: {tot}");}Part 2
Another complication has been added to our little problem! Now we not only need to say how many times the dial stopped at 0, but also how many times it crossed it!
We add two new variables that are going to help us! prev and cross. We are going to keep tot and its related logic and add onto it!
// In setuplet mut prev: i32 = 50;let mut cross = 0;If the amplitude is >100, that means atleast one full rotation, therefore, atleast oe crossing of 0! We can figure out the number of crossing here using division. We also bring the value of amp to the range [0, 99].
cross += amp / 100;let amp = amp % 100;An easy way to detect a crossing is to check if the difference in curr and prev is opposite to what we expected.
For example, let’s say dial position is at 5 and we get input L10, as the dir is L, the dial position should decrease, that is, curr < prev, but as the amp was 10, the new dial position becomes 95. Now, curr (95) > prev (5).
Detecting for this, and similarly curr < prev for R, we can check if there was a crossing on this move!
One thing we need to keep in mind is to ignore those where either curr or prev were 0, as they would have been already counted by tot!
if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { cross += 1;}
prev = curr;Our final program-
use std::fs::read_to_string;
fn main() { let contents = read_to_string("./input.txt").unwrap();
let mut curr: i32 = 50; let mut prev: i32 = 50; let mut tot = 0; let mut cross = 0;
for line in contents.lines() { let words: Vec<char> = line.chars().collect(); let dir = words[0]; let amp: String = words[1..].iter().collect(); let amp: i32 = amp.parse().unwrap();
cross += amp / 100; let amp = amp % 100;
if dir == 'L' { curr -= amp; } else { curr += amp; }
if curr < 0 { curr = 100 + curr; } curr = curr % 100;
if curr == 0 { tot += 1; } if ((dir == 'L' && prev < curr) || (dir == 'R' && prev > curr)) && curr != 0 && prev != 0 { cross += 1; }
prev = curr; } println!("Password: {}", cross + tot);}