Skip to content

Commit

Permalink
feat: Day 3 2021, ⭐ ⭐ Rust + Deno
Browse files Browse the repository at this point in the history
  • Loading branch information
icyJoseph committed Dec 3, 2021
1 parent 22d4f08 commit fc5ac30
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
9 changes: 9 additions & 0 deletions 2021/day-3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
authors = ["Joseph Chamochumbi <[email protected]>"]
edition = "2018"
name = "day-3"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
aoc = {git = "https://github.com/icyJoseph/advent-of-code.git"}
114 changes: 114 additions & 0 deletions 2021/day-3/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use aoc;

fn to_int(bin: &str) -> u32 {
match u32::from_str_radix(bin, 2) {
Ok(n) => n,
_ => panic!("Error parsing binary to integer"),
}
}

fn string_vec<T: std::string::ToString>(vec: &Vec<T>, separator: &str) -> String {
vec.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(separator)
}

fn solve(raw: String) -> () {
let binaries = raw
.trim()
.split("\n")
.map(|row| row.chars().collect::<Vec<char>>())
.collect::<Vec<Vec<char>>>();

let binary_length = binaries[0].len();

let bin_base = (0..binaries[0].len()).collect::<Vec<usize>>();

let count_all = |index: usize, vec: &Vec<Vec<char>>| {
vec.iter().fold((0, 0), |prev, row| {
if row[index] == '1' {
(prev.0 + 1, prev.1)
} else {
(prev.0, prev.1 + 1)
}
})
};

let gamma = bin_base
.iter()
.scan(vec![], |state, current| {
let (ones, zeros) = count_all(*current, &binaries);
let next_bit = if ones > zeros { '1' } else { '0' };
state.push(next_bit);

Some(to_int(&string_vec(&state, "")))
})
.last();

let epsilon = bin_base
.iter()
.scan(vec![], |state, current| {
let (ones, zeros) = count_all(*current, &binaries);
let next_bit = if zeros > ones { '1' } else { '0' };
state.push(next_bit);

Some(to_int(&string_vec(&state, "")))
})
.last();

match (gamma, epsilon) {
(Some(g), Some(e)) => {
println!("Part one: {}", g * e);
}
_ => panic!("Gamma or epsilon are incorrect"),
}

let mut bit = 0;

let mut oxygen = binaries.clone();

loop {
if oxygen.len() == 1 {
break;
}
let (ones, zeros) = count_all(bit, &oxygen);
let gt_ones = ones >= zeros;

oxygen = oxygen
.into_iter()
.filter(|row| row[bit] == if gt_ones { '1' } else { '0' })
.collect::<Vec<Vec<char>>>();

bit = (bit + 1) % binary_length;
}

bit = 0;

let mut co2 = binaries.clone();

loop {
if co2.len() == 1 {
break;
}
let (ones, zeros) = count_all(bit, &co2);
let gt_zeros = zeros > ones;

co2 = co2
.into_iter()
.filter(|row| row[bit] == if gt_zeros { '1' } else { '0' })
.collect::<Vec<Vec<char>>>();
bit = (bit + 1) % binary_length;
}

println!(
"Part Two: {}",
to_int(&string_vec(&oxygen[0], "")) * to_int(&string_vec(&co2[0], "")),
);
}

fn main() {
let input = aoc::get_input(2021, 3);

solve(input);
}
93 changes: 93 additions & 0 deletions 2021/deno/day-3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
const input = await Deno.readTextFile("./input/day-3.in");

const rows = input.split("\n");

const binaries = rows.map((row) => row.split(""));

const len = binaries[0].length;

const gamma = Array.from({ length: len }, (_, i) => {
const ones = binaries.reduce(
(acc, bin) => (bin[i] === "1" ? acc + 1 : acc),
0
);
const zeros = binaries.reduce(
(acc, bin) => (bin[i] === "0" ? acc + 1 : acc),
0
);

return ones > zeros ? "1" : "0";
}).join("");

const epsilon = Array.from({ length: len }, (_, i) => {
const ones = binaries.reduce(
(acc, bin) => (bin[i] === "1" ? acc + 1 : acc),
0
);
const zeros = binaries.reduce(
(acc, bin) => (bin[i] === "0" ? acc + 1 : acc),
0
);

return zeros > ones ? "1" : "0";
}).join("");

/**
* Part One
*/

console.log("Part One:", parseInt(gamma, 2) * parseInt(epsilon, 2));

/**
* Part Two
*/

let bit = 0; // first bit
let oxygen = binaries.slice(0);
let co2 = binaries.slice(0);

while (1) {
if (oxygen.length === 1) {
break;
}
const ones = oxygen.reduce(
(acc, bin) => (bin[bit] === "1" ? acc + 1 : acc),
0
);
const zeros = oxygen.reduce(
(acc, bin) => (bin[bit] === "0" ? acc + 1 : acc),
0
);

if (ones >= zeros) {
oxygen = oxygen.filter((bin) => bin[bit] === "1");
} else {
oxygen = oxygen.filter((bin) => bin[bit] === "0");
}

bit = (bit + 1) % len;
}

// reset the bit
bit = 0;

while (1) {
if (co2.length === 1) {
break;
}
const ones = co2.reduce((acc, bin) => (bin[bit] === "1" ? acc + 1 : acc), 0);
const zeros = co2.reduce((acc, bin) => (bin[bit] === "0" ? acc + 1 : acc), 0);

if (zeros > ones) {
co2 = co2.filter((bin) => bin[bit] === "1");
} else {
co2 = co2.filter((bin) => bin[bit] === "0");
}

bit = (bit + 1) % len;
}

console.log(
"Part Two:",
parseInt(oxygen[0].join(""), 2) * parseInt(co2[0].join(""), 2)
);

0 comments on commit fc5ac30

Please sign in to comment.