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