2021 Day 3 done in Rust
I'm not especially proud of the code : it's messy, took a long time and could probably be vastly improved. I could have used the intersperse iterator method but it's currently in nightly only. Maybe another way of parsing the string would have prevented the need ?
This commit is contained in:
parent
57bf7b2194
commit
8d63db3d64
4 changed files with 1100 additions and 0 deletions
1000
2021/Day 3/input.txt
Normal file
1000
2021/Day 3/input.txt
Normal file
File diff suppressed because it is too large
Load diff
5
2021/Day 3/rust_solution/Cargo.lock
generated
Normal file
5
2021/Day 3/rust_solution/Cargo.lock
generated
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "rust_solution"
|
||||||
|
version = "0.1.0"
|
9
2021/Day 3/rust_solution/Cargo.toml
Normal file
9
2021/Day 3/rust_solution/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "rust_solution"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Teo-CD <teo.couprie_diaz@telecom-sudparis.eu>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
86
2021/Day 3/rust_solution/src/main.rs
Normal file
86
2021/Day 3/rust_solution/src/main.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
/// Count number of ones in each bit position. If the count is less than half of the total number
|
||||||
|
/// of entries, then 0 is more common.
|
||||||
|
fn find_most_common_bits(input: &String) -> Vec<i16> {
|
||||||
|
let width = input.lines().nth(0).unwrap().len();
|
||||||
|
let mut bit_counts: Vec<i16> = std::vec::from_elem(0, width);
|
||||||
|
for value in input.lines() {
|
||||||
|
let mut chars = value.chars();
|
||||||
|
for index in 0..width {
|
||||||
|
bit_counts[index] += if chars.next().unwrap() == '1' { 1 } else { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bit_counts
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loop while finding the most/least common bit for the current position until we find
|
||||||
|
/// a single number in the list.
|
||||||
|
fn reduce_by_count(input: &String, most_common: bool) -> String {
|
||||||
|
let mut count = input.lines().count();
|
||||||
|
let mut bit_index = 0;
|
||||||
|
let mut filtered_input = input.clone();
|
||||||
|
while count > 1 {
|
||||||
|
let most_common_bit = if find_most_common_bits(&filtered_input)[bit_index]
|
||||||
|
>= filtered_input.lines().count() as i16 / 2
|
||||||
|
{
|
||||||
|
if most_common {
|
||||||
|
'1'
|
||||||
|
} else {
|
||||||
|
'0'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if most_common {
|
||||||
|
'0'
|
||||||
|
} else {
|
||||||
|
'1'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Filter out the numbers which don't match the current most/least common bit.
|
||||||
|
filtered_input = filtered_input
|
||||||
|
.lines()
|
||||||
|
.filter(|line: &&str| line.chars().nth(bit_index).unwrap() == most_common_bit)
|
||||||
|
.map(|line| line.to_owned() + '\n'.to_string().as_str()) // Add the line separator back
|
||||||
|
.collect();
|
||||||
|
count = filtered_input.lines().count();
|
||||||
|
bit_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from(filtered_input.lines().next().unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let contents = fs::read_to_string("../input.txt").expect("Could not open file.");
|
||||||
|
let bit_counts = find_most_common_bits(&contents);
|
||||||
|
|
||||||
|
// Compute power consumption
|
||||||
|
let mut gamma: u32 = 0;
|
||||||
|
let mut epsilon: u32 = 0;
|
||||||
|
for count in bit_counts {
|
||||||
|
gamma <<= 1;
|
||||||
|
epsilon <<= 1;
|
||||||
|
gamma |= if count > contents.lines().count() as i16 / 2 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
epsilon |= if count > contents.lines().count() as i16 / 2 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Submarine power consumption : {}",
|
||||||
|
gamma as u64 * epsilon as u64
|
||||||
|
);
|
||||||
|
|
||||||
|
// Compute oxygen generator rating and CO2 scrubber rating.
|
||||||
|
// from_str_radix converts from a string of the binary representation to an integer.
|
||||||
|
let ox_gen = isize::from_str_radix(reduce_by_count(&contents, true).as_str(), 2).unwrap();
|
||||||
|
let co2_scrub = isize::from_str_radix(reduce_by_count(&contents, false).as_str(), 2).unwrap();
|
||||||
|
println!("Oxygen generator rating : {}", ox_gen);
|
||||||
|
println!("CO2 scrubber rating : {}", co2_scrub);
|
||||||
|
println!("Life support rating : {}", ox_gen * co2_scrub);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue