Compare commits

...

7 Commits

@ -0,0 +1,36 @@
use aoc::input;
fn main() {
let mut v = input::read_chars();
// Part 1
for _ in 0..40 {
v = step(&v);
}
println!("Length after 40 steps: {}", v.len());
// Part 2
for _ in 0..10 {
v = step(&v);
}
println!("Length after 50 steps: {}", v.len());
}
fn step(s: &str) -> String {
let mut count = 1;
let mut pc = ' ';
let mut result = String::new();
for c in s.chars() {
if c == pc {
count += 1;
} else if pc != ' ' {
result.push_str(&count.to_string());
result.push(pc);
count = 1;
}
pc = c;
}
result.push_str(&count.to_string());
result.push(pc);
result
}

@ -0,0 +1,75 @@
use aoc::input;
fn main() {
let mut pass = input::read_chars();
// Part 1
get_next_pass(&mut pass);
println!("Next pass: {}", pass);
// Part 2
get_next_pass(&mut pass);
println!("Next pass: {}", pass);
}
fn get_next_pass(pass: &mut String) {
loop {
unsafe { inc(pass.as_bytes_mut()) }
let pb = pass.as_bytes();
if has_seq(pb) && !has_banned_chars(pb) && has_pairs(&pass) {
break;
}
}
}
fn has_seq(pass: &[u8]) -> bool {
for i in 0..(pass.len() - 2) {
if pass[i] == pass[i + 1] - 1 && pass[i + 1] == pass[i + 2] - 1 {
return true;
}
}
false
}
fn has_banned_chars(pass: &[u8]) -> bool {
for b in b"iol".iter() {
if pass.contains(b) {
return true;
}
}
false
}
fn has_pairs(pass: &str) -> bool {
let mut num_pairs = 0;
let mut pc = ' ';
let mut skip_next = false;
for c in pass.chars() {
if skip_next {
skip_next = false;
pc = c;
continue
}
if c == pc {
num_pairs += 1;
skip_next = true;
}
pc = c;
}
num_pairs >= 2
}
fn inc(pass: &mut [u8]) {
let mut i = pass.len() - 1;
loop {
let lc = pass[i];
if lc < b'z' {
let offset = if lc == b'i' || lc == b'o' || lc == b'l' { 2 } else { 1 };
pass[i] = pass[i] + offset;
break;
} else {
pass[i] = b'a';
i -= 1;
}
}
}

@ -0,0 +1,59 @@
use aoc::input;
fn main() {
let lines = input::read_lines();
// Part 1
let mut goods = 0;
let bad_pairs = vec!("ab", "cd", "pq", "xy");
for line in &lines {
let mut has_bad_pair = false;
for p in &bad_pairs {
if line.contains(p) { has_bad_pair = true; break }
}
if has_bad_pair { continue }
let mut num_vowels = 0;
let mut cc = ' ';
let mut has_doubled = false;
for c in line.chars() {
if "aeiou".contains(c) { num_vowels += 1 }
if c == cc { has_doubled = true }
cc = c;
}
if num_vowels < 3 { continue }
if !has_doubled { continue }
goods += 1;
}
println!("Good strings: {}", goods);
// Part 2
goods = 0;
for line in &lines {
let mut cond1 = false;
let chars: Vec<char> = line.chars().collect();
for i in 0..(chars.len() - 2) {
let c1 = chars[i];
let c2 = chars[i + 1];
for j in (i + 2)..(chars.len() - 1) {
if chars[j] == c1 && chars[j + 1] == c2 {
cond1 = true;
break
}
}
if cond1 { break }
}
if !cond1 { continue }
let mut cond2 = false;
let mut cm2 = ' ';
let mut cm1 = ' ';
for c in line.chars() {
if c == cm2 { cond2 = true }
cm2 = cm1;
cm1 = c;
}
if !cond2 { continue }
goods += 1;
}
println!("Best strings: {}", goods);
}

@ -0,0 +1,53 @@
use std::cmp;
use aoc::input;
fn main() {
let lines = input::read_lines();
let mut grid = vec![false; 1_000_000];
// Part 1
for line in &lines {
let mut parts = line.split_whitespace();
let state = if parts.next() == Some("turn") {
parts.next().and_then(|s| Some(s == "on"))
} else { // toggle
None
};
let s: Vec<usize> = parts.next().unwrap().split(",")
.map(|p| p.parse::<usize>().unwrap()).collect();
let e: Vec<usize> = parts.nth(1).unwrap().split(",")
.map(|p| p.parse::<usize>().unwrap()).collect();
for i in s[0]..=e[0] {
for j in s[1]..=e[1] {
grid[i * 1000 + j] = match state {
Some(c) => c,
None => !grid[i * 1000 + j]
}
}
}
}
println!("Lights on: {}", grid.iter().map(|s| if *s { 1 } else { 0 }).sum::<u32>());
// Part 2
let mut grid = vec![0; 1_000_000];
for line in &lines {
let mut parts = line.split_whitespace();
let change: i32 = if parts.next() == Some("turn") {
if parts.next().unwrap() == "on" { 1 } else { -1 }
} else { // toggle
2
};
let s: Vec<usize> = parts.next().unwrap().split(",")
.map(|p| p.parse::<usize>().unwrap()).collect();
let e: Vec<usize> = parts.nth(1).unwrap().split(",")
.map(|p| p.parse::<usize>().unwrap()).collect();
for i in s[0]..=e[0] {
for j in s[1]..=e[1] {
let current = grid[i * 1000 + j];
grid[i * 1000 + j] = cmp::max(current + change, 0);
}
}
}
println!("Brightness: {}", grid.iter().sum::<i32>());
}

@ -0,0 +1,67 @@
use std::collections::HashMap;
use aoc::input;
#[derive(Debug)]
enum Op {
And(String, String), // left-hand can be an int
Or(String, String),
Not(String),
Lshift(String, u16),
Rshift(String, u16),
Value(String), // either int or wire
}
fn main() {
let lines = input::read_lines();
let mut wiring: HashMap<String, Op> = HashMap::new();
for line in lines {
let mut parts = line.split(" -> ");
let op_text = parts.next().unwrap();
let target = parts.next().unwrap();
let op_parts: Vec<&str> = op_text.split_whitespace().collect();
let op = match op_parts.len() {
1 => { Op::Value(op_parts[0].to_string()) }
2 => { Op::Not(op_parts[1].to_string()) }
3 => { match op_parts[1] {
"AND" => { Op::And(op_parts[0].to_string(), op_parts[2].to_string()) }
"OR" => { Op::Or(op_parts[0].to_string(), op_parts[2].to_string()) }
"LSHIFT" => { Op::Lshift(op_parts[0].to_string(), op_parts[2].parse::<u16>().unwrap()) }
"RSHIFT" => { Op::Rshift(op_parts[0].to_string(), op_parts[2].parse::<u16>().unwrap()) }
_ => panic!()
} }
_ => panic!()
};
wiring.insert(target.to_string(), op);
}
// Part 1
let mut cache: HashMap<String, u16> = HashMap::new();
let part1 = solve(&wiring, "a", &mut cache);
println!("Wire a: {}", part1);
// Part 2
wiring.insert("b".to_string(), Op::Value(part1.to_string()));
let mut cache: HashMap<String, u16> = HashMap::new();
println!("Wire a with b overridden: {}", solve(&wiring, "a", &mut cache));
}
fn solve(wiring: &HashMap<String, Op>, name: &str, cache: &mut HashMap<String, u16>) -> u16 {
if cache.contains_key(name) {
return *cache.get(name).unwrap()
}
let value = if let Ok(value) = name.parse::<u16>() {
return value
} else {
match wiring.get(name).unwrap() {
Op::And(lh, rh) => { solve(wiring, lh, cache) & solve(wiring, rh, cache) }
Op::Or(lh, rh) => { solve(wiring, lh, cache) | solve(wiring, rh, cache) }
Op::Not(op) => { !solve(wiring, op, cache) }
Op::Lshift(lh, rh) => { solve(wiring, lh, cache) << rh }
Op::Rshift(lh, rh) => { solve(wiring, lh, cache) >> rh }
Op::Value(v) => { solve(wiring, v, cache) }
}
};
cache.insert(name.to_string(), value);
value
}

@ -0,0 +1,40 @@
use aoc::input;
fn main() {
let lines = input::read_lines();
// Part 1
let mut used_mem = 0;
let mut num_chars = 0;
for line in &lines {
let chars = line.chars().collect::<Vec<char>>();
let line_mem = chars.len();
let mut line_num_chars = line_mem - 2;
let mut index = 1;
while index < line_mem - 1 {
if chars[index] == '\\' {
if chars[index + 1] == '"' || chars[index + 1] == '\\' {
line_num_chars -= 1;
index += 1;
} else if chars[index + 1] == 'x' {
line_num_chars -= 3;
index += 3;
}
}
index += 1;
}
used_mem += line_mem;
num_chars += line_num_chars;
}
println!("{} - {} = {}", used_mem, num_chars, used_mem - num_chars);
// Part 2
let mut encoded_size = used_mem;
for line in &lines {
for c in line.chars() {
if c == '\\' || c == '"' { encoded_size += 1 }
}
encoded_size += 2; // enclosing quotes
}
println!("{} - {} = {}", encoded_size, used_mem, encoded_size - used_mem);
}

@ -0,0 +1,118 @@
use std::collections::{HashMap, HashSet};
use aoc::input;
type Dists = HashMap<String, HashMap<String, u32>>;
fn main() {
let lines = input::read_lines();
let mut places: HashSet<String> = HashSet::new();
let mut dists: Dists = HashMap::new();
for line in lines {
let parts = line.split_whitespace().collect::<Vec<&str>>();
let from = parts[0];
let to = parts[2];
let dist = parts[4].parse::<u32>().unwrap();
if !dists.contains_key(from) {
dists.insert(from.to_string(), HashMap::new());
}
if !dists.contains_key(to) {
dists.insert(to.to_string(), HashMap::new());
}
dists.get_mut(from).unwrap().insert(to.to_string(), dist);
dists.get_mut(to).unwrap().insert(from.to_string(), dist);
places.insert(from.to_string());
places.insert(to.to_string());
}
let path_len = places.len();
// Part 1
let mut min: u32 = u32::MAX;
for place in &places {
let shortest_dist =
find_shortest_path(&dists, &places, &mut vec![place.to_owned()], 0, path_len);
if shortest_dist < min {
min = shortest_dist
}
}
println!("Shortest distance: {}", min);
// Part 2
let mut max: u32 = 0;
for place in &places {
let longest_dist =
find_longest_path(&dists, &places, &mut vec![place.to_owned()], 0, path_len);
if longest_dist > max {
max = longest_dist
}
}
println!("Longest distance: {}", max);
}
fn find_shortest_path(
dists: &Dists,
places: &HashSet<String>,
cur_path: &mut Vec<String>,
cur_dist: u32,
max_places: usize,
) -> u32 {
if cur_path.len() == max_places {
return cur_dist;
}
// get next unexplored places
let dists_from_here = dists.get(cur_path.last().unwrap()).unwrap();
let mut min: u32 = u32::MAX;
for next_place in places {
if cur_path.contains(next_place) {
continue;
}
cur_path.push(next_place.to_string());
let next_place_dist = dists_from_here.get(next_place).unwrap();
let shortest_dist = find_shortest_path(
dists,
places,
cur_path,
cur_dist + next_place_dist,
max_places,
);
cur_path.pop();
if shortest_dist < min {
min = shortest_dist;
}
}
min
}
fn find_longest_path(
dists: &Dists,
places: &HashSet<String>,
cur_path: &mut Vec<String>,
cur_dist: u32,
max_places: usize,
) -> u32 {
if cur_path.len() == max_places {
return cur_dist;
}
// get next unexplored places
let dists_from_here = dists.get(cur_path.last().unwrap()).unwrap();
let mut max: u32 = 0;
for next_place in places {
if cur_path.contains(next_place) {
continue;
}
cur_path.push(next_place.to_string());
let next_place_dist = dists_from_here.get(next_place).unwrap();
let longest_dist = find_longest_path(
dists,
places,
cur_path,
cur_dist + next_place_dist,
max_places,
);
cur_path.pop();
if longest_dist > max {
max = longest_dist;
}
}
max
}

@ -1,3 +1,4 @@
#!/usr/bin/env python3
import argparse
import os
import shutil
@ -25,7 +26,6 @@ def main():
input_text = fetch(input_url)
create_files(input_text, args.day, args.year, args.lang)
webbrowser.open_new_tab(day_url)
webbrowser.open_new_tab(input_url)
def fetch(input_url):
response = requests.get(input_url, cookies={"session": SESSION_ID})

Loading…
Cancel
Save