Skip to content

Commit

Permalink
Implement day3, challenge 2
Browse files Browse the repository at this point in the history
  • Loading branch information
tjheslin1 committed Dec 3, 2021
1 parent f9d0d07 commit eb4c726
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 26 deletions.
134 changes: 109 additions & 25 deletions 2021/day3/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
pub fn diagnostics_report(readings: &[&str]) -> (isize, isize) {
let reading_length = if readings.is_empty() {
0
} else {
readings.get(0).unwrap().len()
};

let column_bits: Vec<String> =
(0..reading_length).fold(vec![String::new(); reading_length], |mut acc, index| {
readings.iter().for_each(|line| {
acc.get_mut(index)
.unwrap()
.push(line.chars().nth(index).unwrap());
});

acc
});

let most_common =
column_bits
column_bits(readings)
.iter()
.fold((String::from("0"), String::from("0")), |acc, column| {
let count_zeroes = column.chars().filter(|char| *char == '0').count();

if count_zeroes >= (column.len() / 2) {
if most_common_bit(column, '0') == '0' {
(acc.0 + "0", acc.1 + "1")
} else {
(acc.0 + "1", acc.1 + "0")
Expand All @@ -31,17 +12,99 @@ pub fn diagnostics_report(readings: &[&str]) -> (isize, isize) {

match most_common {
(b_gamma, b_epsilon) => {
let gamma = isize::from_str_radix(&b_gamma, 2)
.expect(&format!("Expected a binary input but got: {}", b_gamma)[..]);
let gamma = binary_to_decimal(&b_gamma);

let epsilon = isize::from_str_radix(&b_epsilon, 2)
.expect(&format!("Expected a binary input but got: {}", b_epsilon)[..]);
let epsilon = binary_to_decimal(&b_epsilon);

(gamma, epsilon)
}
}
}

pub fn life_support_rating(readings: &[&str]) -> (isize, isize) {
let oxygen_rating = find_by_bit_criteria(readings, true, '1');
let co2_rating = find_by_bit_criteria(readings, false, '0');

(oxygen_rating, co2_rating)
}

fn binary_to_decimal(binary: &str) -> isize {
isize::from_str_radix(binary, 2)
.expect(&format!("Expected a binary input but got: {}", binary)[..])
}

fn find_by_bit_criteria(readings: &[&str], most_common: bool, on_match: char) -> isize {
let readings_length = readings_length(readings);

let reduced_readings = (0..readings_length).fold(readings.to_owned(), |acc, index| {
let bit_to_match = find_common_bit(
most_common,
column_bits(&acc[..]).get(index).unwrap(),
on_match,
);

if acc.len() > 1 {
acc.iter()
.filter(|line| line.chars().nth(index).unwrap() == bit_to_match)
.map(|x| *x)
.collect::<Vec<&str>>()
} else {
acc
}
});

match reduced_readings[..] {
[binary] => binary_to_decimal(binary),
_ => 0,
}
}

fn readings_length(readings: &[&str]) -> usize {
if readings.is_empty() {
0
} else {
readings.get(0).unwrap().len()
}
}

fn most_common_bit(column: &str, on_match: char) -> char {
find_common_bit(true, column, on_match)
}

fn find_common_bit(most_common: bool, column: &str, on_match: char) -> char {
let count_zeroes = column.chars().filter(|char| *char == '0').count();

if count_zeroes == (column.len() / 2) {
on_match
} else if count_zeroes > (column.len() / 2) {
if most_common {
'0'
} else {
'1'
}
} else {
if most_common {
'1'
} else {
'0'
}
}
}

fn column_bits(readings: &[&str]) -> Vec<String> {
let readings_length = readings_length(readings);

(0..readings_length).fold(vec![String::new(); readings_length], |mut acc, index| {
readings.iter().for_each(|line| {
acc.get_mut(index)
.unwrap()
.push(line.chars().nth(index).unwrap());
});

acc
})
}

#[cfg(test)]
mod tests {

Expand All @@ -67,4 +130,25 @@ mod tests {

assert_eq!(actual_report, (22, 9))
}

#[test]
fn empty_life_support_rating() {
let readings = vec![];

let actual_ratings = life_support_rating(&readings);

assert_eq!(actual_ratings, (0, 0))
}

#[test]
fn sample_life_support_rating() {
let readings = vec![
"00100", "11110", "10110", "10111", "10101", "01111", "00111", "11100", "10000",
"11001", "00010", "01010",
];

let actual_ratings = life_support_rating(&readings);

assert_eq!(actual_ratings, (23, 10))
}
}
4 changes: 3 additions & 1 deletion 2021/day3/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ fn main() {
.collect();

let (gamma, epsilon) = diagnostics::diagnostics_report(&readings);

println!("gamma = {}, epsilon = {}", gamma, epsilon);

let (oxygen, co2) = diagnostics::life_support_rating(&readings);
println!("oxygen = {}, co2 = {}", oxygen, co2);
}

0 comments on commit eb4c726

Please sign in to comment.