Break each day out into a module.
This commit is contained in:
parent
3ec015ab70
commit
9e63330189
|
@ -0,0 +1,98 @@
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub fn get_calibration_digits() -> u32 {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut sum = 0;
|
||||||
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
||||||
|
let nums: Vec<u32> = buffer.chars().filter_map(|c| c.to_digit(10)).collect();
|
||||||
|
sum += nums.first().unwrap() * 10 + nums.last().unwrap();
|
||||||
|
buffer = String::new();
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
const NUMBERS: [&'static str; 9] = [
|
||||||
|
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||||
|
];
|
||||||
|
|
||||||
|
enum SearchDir {
|
||||||
|
First,
|
||||||
|
Last,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_digit(line: &String, dir: SearchDir) -> u32 {
|
||||||
|
let mut first: usize = 0;
|
||||||
|
let mut index: Option<usize> = None;
|
||||||
|
for n in 1..=9 {
|
||||||
|
let f = match &dir {
|
||||||
|
SearchDir::First => line.find(&n.to_string()),
|
||||||
|
SearchDir::Last => line.rfind(&n.to_string()),
|
||||||
|
};
|
||||||
|
if f == None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let found = f.unwrap();
|
||||||
|
match index {
|
||||||
|
None => {
|
||||||
|
index = f;
|
||||||
|
first = n;
|
||||||
|
}
|
||||||
|
Some(i) => match &dir {
|
||||||
|
SearchDir::First => {
|
||||||
|
if found < i {
|
||||||
|
index = f;
|
||||||
|
first = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SearchDir::Last => {
|
||||||
|
if found > i {
|
||||||
|
index = f;
|
||||||
|
first = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (num, num_str) in NUMBERS.iter().enumerate() {
|
||||||
|
let f = match &dir {
|
||||||
|
SearchDir::First => line.find(num_str),
|
||||||
|
SearchDir::Last => line.rfind(num_str),
|
||||||
|
};
|
||||||
|
if f == None {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let found = f.unwrap();
|
||||||
|
match index {
|
||||||
|
None => {
|
||||||
|
index = f;
|
||||||
|
first = num + 1;
|
||||||
|
}
|
||||||
|
Some(i) => match &dir {
|
||||||
|
SearchDir::First => {
|
||||||
|
if found < i {
|
||||||
|
index = f;
|
||||||
|
first = num + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SearchDir::Last => {
|
||||||
|
if found > i {
|
||||||
|
index = f;
|
||||||
|
first = num + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first.try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_calibration_digits_alnum() -> u32 {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut sum = 0;
|
||||||
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
||||||
|
let val = (get_digit(&buffer, SearchDir::First) * 10) + get_digit(&buffer, SearchDir::Last);
|
||||||
|
sum += val;
|
||||||
|
buffer = String::new();
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub fn get_possible_games() -> (u32, u32) {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut power_sum = 0;
|
||||||
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
||||||
|
let mut game = buffer.split(":");
|
||||||
|
let game_num: u32 = game.next().unwrap()[5..]
|
||||||
|
.parse()
|
||||||
|
.expect("Couldn't parse game number");
|
||||||
|
|
||||||
|
let mut red = 0;
|
||||||
|
let mut green = 0;
|
||||||
|
let mut blue = 0;
|
||||||
|
let pulls = game.next().unwrap().split(";");
|
||||||
|
let mut possible = true;
|
||||||
|
for pull in pulls {
|
||||||
|
let colors = pull.split(",");
|
||||||
|
for mut color in colors {
|
||||||
|
color = color.trim();
|
||||||
|
let num: u32 = color[..color.find(" ").unwrap()]
|
||||||
|
.parse()
|
||||||
|
.expect("Coudn't parse number of marbles.");
|
||||||
|
match &color[color.find(" ").unwrap() + 1..] {
|
||||||
|
"red" => {
|
||||||
|
if num > 12 {
|
||||||
|
possible = false;
|
||||||
|
}
|
||||||
|
red = red.max(num);
|
||||||
|
}
|
||||||
|
"green" => {
|
||||||
|
if num > 13 {
|
||||||
|
possible = false;
|
||||||
|
}
|
||||||
|
green = green.max(num);
|
||||||
|
}
|
||||||
|
"blue" => {
|
||||||
|
if num > 14 {
|
||||||
|
possible = false;
|
||||||
|
}
|
||||||
|
blue = blue.max(num);
|
||||||
|
}
|
||||||
|
c => println!("Error color {}", c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if possible {
|
||||||
|
sum += game_num;
|
||||||
|
}
|
||||||
|
power_sum += red * green * blue;
|
||||||
|
buffer = String::new();
|
||||||
|
}
|
||||||
|
(sum, power_sum)
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
fn record_gear(num: u32, gear: usize, gears: &mut HashMap<usize, Vec<u32>>) {
|
||||||
|
match gears.get_mut(&gear) {
|
||||||
|
None => {
|
||||||
|
let mut vec: Vec<u32> = Vec::new();
|
||||||
|
vec.push(num);
|
||||||
|
gears.insert(gear, vec);
|
||||||
|
}
|
||||||
|
Some(v) => v.push(num),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_part_number(
|
||||||
|
r: usize,
|
||||||
|
c: usize,
|
||||||
|
s: usize,
|
||||||
|
part_table: &Vec<String>,
|
||||||
|
n: u32,
|
||||||
|
mut gears: &mut HashMap<usize, Vec<u32>>,
|
||||||
|
) -> bool {
|
||||||
|
let is_symbol = |c: char| c != '.' && !c.is_numeric();
|
||||||
|
// Check above.
|
||||||
|
if r > 0 {
|
||||||
|
let mut c_: usize = if c > 0 { c - 1 } else { c };
|
||||||
|
let row: &Vec<char> = &part_table[r - 1].chars().collect();
|
||||||
|
while c_ <= c + s && c_ < row.len() {
|
||||||
|
if is_symbol(row[c_]) {
|
||||||
|
if row[c_] == '*' {
|
||||||
|
let index = (r - 1) * row.len() + c_;
|
||||||
|
record_gear(n, index, &mut gears);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
c_ += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check Adjacent.
|
||||||
|
let adj_row: &Vec<char> = &part_table[r].chars().collect();
|
||||||
|
if c > 0 {
|
||||||
|
if is_symbol(adj_row[c - 1]) {
|
||||||
|
if adj_row[c - 1] == '*' {
|
||||||
|
let index = r * adj_row.len() + c - 1;
|
||||||
|
record_gear(n, index, &mut gears);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c + s < adj_row.len() {
|
||||||
|
if is_symbol(adj_row[c + s]) {
|
||||||
|
if adj_row[c + s] == '*' {
|
||||||
|
let index = r * adj_row.len() + c + s;
|
||||||
|
record_gear(n, index, &mut gears);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check below.
|
||||||
|
if r + 1 < part_table.len() {
|
||||||
|
let mut c_: usize = if c > 0 { c - 1 } else { c };
|
||||||
|
let row: &Vec<char> = &part_table[r + 1].chars().collect();
|
||||||
|
while c_ <= c + s && c_ < row.len() {
|
||||||
|
if is_symbol(row[c_]) {
|
||||||
|
if row[c_] == '*' {
|
||||||
|
let index = (r + 1) * row.len() + c_;
|
||||||
|
record_gear(n, index, &mut gears);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
c_ += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sum_part_numbers() -> (u32, u32) {
|
||||||
|
let mut part_table: Vec<String> = Vec::new();
|
||||||
|
let mut buffer: String = String::new();
|
||||||
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
||||||
|
part_table.push(buffer.trim_end().to_string());
|
||||||
|
buffer = String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sum = 0;
|
||||||
|
let mut gear_table = HashMap::new();
|
||||||
|
|
||||||
|
for r in 0..part_table.len() {
|
||||||
|
let mut c = 0;
|
||||||
|
let mut part_rem = &part_table[r][..];
|
||||||
|
loop {
|
||||||
|
match part_rem.find(char::is_numeric) {
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some(ind) => {
|
||||||
|
part_rem = &part_rem[ind..];
|
||||||
|
c += ind;
|
||||||
|
let is_non_num = |c: char| !c.is_numeric();
|
||||||
|
let end = match part_rem.find(is_non_num) {
|
||||||
|
None => part_rem.len(),
|
||||||
|
Some(i) => i,
|
||||||
|
};
|
||||||
|
let num: u32 = part_rem[..end].parse().expect("Couldn't parse number");
|
||||||
|
if is_part_number(r, c, end, &part_table, num, &mut gear_table) {
|
||||||
|
sum += num;
|
||||||
|
println!("{} {}", num, gear_table.len());
|
||||||
|
}
|
||||||
|
part_rem = &part_rem[end..];
|
||||||
|
c += end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut gear_sum = 0;
|
||||||
|
for (_, vec) in gear_table {
|
||||||
|
if vec.len() == 2 {
|
||||||
|
gear_sum += vec[0] * vec[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(sum, gear_sum)
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
use std::{collections::HashSet, io};
|
||||||
|
|
||||||
|
fn parse_num_list(num_str: &str) -> HashSet<u32> {
|
||||||
|
num_str
|
||||||
|
.split(' ')
|
||||||
|
.filter(|s| s.len() > 0)
|
||||||
|
.map(|s| s.parse().expect("couldn't parse"))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_card_points() -> (u32, u32) {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let mut score = 0;
|
||||||
|
|
||||||
|
let mut card_num = 1;
|
||||||
|
let mut card_counts: Vec<u32> = Vec::new();
|
||||||
|
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
||||||
|
if card_counts.len() < card_num + 1 {
|
||||||
|
card_counts.resize(card_num + 1, 0);
|
||||||
|
}
|
||||||
|
card_counts[card_num] += 1;
|
||||||
|
let colon_index = buffer.find(':').unwrap();
|
||||||
|
let bar_index = buffer.find('|').unwrap();
|
||||||
|
|
||||||
|
let winners = parse_num_list(buffer[colon_index + 1..bar_index].trim());
|
||||||
|
let mine = parse_num_list(buffer[bar_index + 1..].trim());
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
for num in mine {
|
||||||
|
if winners.contains(&num) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
score += 1 << (count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if card_counts.len() < card_num + count + 1 {
|
||||||
|
card_counts.resize(card_num + count + 1, 0);
|
||||||
|
}
|
||||||
|
for i in 1..=count {
|
||||||
|
card_counts[card_num + i] += card_counts[card_num]
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = String::new();
|
||||||
|
card_num += 1;
|
||||||
|
}
|
||||||
|
(score, card_counts.iter().sum())
|
||||||
|
}
|
348
src/main.rs
348
src/main.rs
|
@ -1,333 +1,9 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io;
|
|
||||||
|
|
||||||
fn get_calibration_digits() -> u32 {
|
mod day1;
|
||||||
let mut buffer = String::new();
|
mod day2;
|
||||||
let mut sum = 0;
|
mod day3;
|
||||||
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
mod day4;
|
||||||
let nums: Vec<u32> = buffer.chars().filter_map(|c| c.to_digit(10)).collect();
|
|
||||||
sum += nums.first().unwrap() * 10 + nums.last().unwrap();
|
|
||||||
buffer = String::new();
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
const NUMBERS: [&'static str; 9] = [
|
|
||||||
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
|
||||||
];
|
|
||||||
|
|
||||||
enum SearchDir {
|
|
||||||
First,
|
|
||||||
Last,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_digit(line: &String, dir: SearchDir) -> u32 {
|
|
||||||
let mut first: usize = 0;
|
|
||||||
let mut index: Option<usize> = None;
|
|
||||||
for n in 1..=9 {
|
|
||||||
let f = match &dir {
|
|
||||||
SearchDir::First => line.find(&n.to_string()),
|
|
||||||
SearchDir::Last => line.rfind(&n.to_string()),
|
|
||||||
};
|
|
||||||
if f == None {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let found = f.unwrap();
|
|
||||||
match index {
|
|
||||||
None => {
|
|
||||||
index = f;
|
|
||||||
first = n;
|
|
||||||
}
|
|
||||||
Some(i) => match &dir {
|
|
||||||
SearchDir::First => {
|
|
||||||
if found < i {
|
|
||||||
index = f;
|
|
||||||
first = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SearchDir::Last => {
|
|
||||||
if found > i {
|
|
||||||
index = f;
|
|
||||||
first = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (num, num_str) in NUMBERS.iter().enumerate() {
|
|
||||||
let f = match &dir {
|
|
||||||
SearchDir::First => line.find(num_str),
|
|
||||||
SearchDir::Last => line.rfind(num_str),
|
|
||||||
};
|
|
||||||
if f == None {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let found = f.unwrap();
|
|
||||||
match index {
|
|
||||||
None => {
|
|
||||||
index = f;
|
|
||||||
first = num + 1;
|
|
||||||
}
|
|
||||||
Some(i) => match &dir {
|
|
||||||
SearchDir::First => {
|
|
||||||
if found < i {
|
|
||||||
index = f;
|
|
||||||
first = num + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SearchDir::Last => {
|
|
||||||
if found > i {
|
|
||||||
index = f;
|
|
||||||
first = num + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
first.try_into().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_calibration_digits_alnum() -> u32 {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut sum = 0;
|
|
||||||
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
|
||||||
let val = (get_digit(&buffer, SearchDir::First) * 10) + get_digit(&buffer, SearchDir::Last);
|
|
||||||
sum += val;
|
|
||||||
buffer = String::new();
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_possible_games() -> (u32, u32) {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut sum = 0;
|
|
||||||
let mut power_sum = 0;
|
|
||||||
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
|
||||||
let mut game = buffer.split(":");
|
|
||||||
let game_num: u32 = game.next().unwrap()[5..]
|
|
||||||
.parse()
|
|
||||||
.expect("Couldn't parse game number");
|
|
||||||
|
|
||||||
let mut red = 0;
|
|
||||||
let mut green = 0;
|
|
||||||
let mut blue = 0;
|
|
||||||
let pulls = game.next().unwrap().split(";");
|
|
||||||
let mut possible = true;
|
|
||||||
for pull in pulls {
|
|
||||||
let colors = pull.split(",");
|
|
||||||
for mut color in colors {
|
|
||||||
color = color.trim();
|
|
||||||
let num: u32 = color[..color.find(" ").unwrap()]
|
|
||||||
.parse()
|
|
||||||
.expect("Coudn't parse number of marbles.");
|
|
||||||
match &color[color.find(" ").unwrap() + 1..] {
|
|
||||||
"red" => {
|
|
||||||
if num > 12 {
|
|
||||||
possible = false;
|
|
||||||
}
|
|
||||||
red = red.max(num);
|
|
||||||
}
|
|
||||||
"green" => {
|
|
||||||
if num > 13 {
|
|
||||||
possible = false;
|
|
||||||
}
|
|
||||||
green = green.max(num);
|
|
||||||
}
|
|
||||||
"blue" => {
|
|
||||||
if num > 14 {
|
|
||||||
possible = false;
|
|
||||||
}
|
|
||||||
blue = blue.max(num);
|
|
||||||
}
|
|
||||||
c => println!("Error color {}", c),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if possible {
|
|
||||||
sum += game_num;
|
|
||||||
}
|
|
||||||
power_sum += red * green * blue;
|
|
||||||
buffer = String::new();
|
|
||||||
}
|
|
||||||
(sum, power_sum)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_gear(num: u32, gear: usize, gears: &mut HashMap<usize, Vec<u32>>) {
|
|
||||||
println!("Gear {}", gear);
|
|
||||||
match gears.get_mut(&gear) {
|
|
||||||
None => {
|
|
||||||
let mut vec: Vec<u32> = Vec::new();
|
|
||||||
vec.push(num);
|
|
||||||
gears.insert(gear, vec);
|
|
||||||
}
|
|
||||||
Some(v) => v.push(num),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_part_number(
|
|
||||||
r: usize,
|
|
||||||
c: usize,
|
|
||||||
s: usize,
|
|
||||||
part_table: &Vec<String>,
|
|
||||||
n: u32,
|
|
||||||
mut gears: &mut HashMap<usize, Vec<u32>>,
|
|
||||||
) -> bool {
|
|
||||||
let is_symbol = |c: char| c != '.' && !c.is_numeric();
|
|
||||||
// Check above.
|
|
||||||
if r > 0 {
|
|
||||||
let mut c_: usize = if c > 0 { c - 1 } else { c };
|
|
||||||
let row: &Vec<char> = &part_table[r - 1].chars().collect();
|
|
||||||
while c_ <= c + s && c_ < row.len() {
|
|
||||||
if is_symbol(row[c_]) {
|
|
||||||
if row[c_] == '*' {
|
|
||||||
let index = (r - 1) * row.len() + c_;
|
|
||||||
record_gear(n, index, &mut gears);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
c_ += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check Adjacent.
|
|
||||||
let adj_row: &Vec<char> = &part_table[r].chars().collect();
|
|
||||||
if c > 0 {
|
|
||||||
if is_symbol(adj_row[c - 1]) {
|
|
||||||
if adj_row[c - 1] == '*' {
|
|
||||||
let index = r * adj_row.len() + c - 1;
|
|
||||||
record_gear(n, index, &mut gears);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c + s < adj_row.len() {
|
|
||||||
if is_symbol(adj_row[c + s]) {
|
|
||||||
if adj_row[c + s] == '*' {
|
|
||||||
let index = r * adj_row.len() + c + s;
|
|
||||||
record_gear(n, index, &mut gears);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check below.
|
|
||||||
if r + 1 < part_table.len() {
|
|
||||||
let mut c_: usize = if c > 0 { c - 1 } else { c };
|
|
||||||
let row: &Vec<char> = &part_table[r + 1].chars().collect();
|
|
||||||
while c_ <= c + s && c_ < row.len() {
|
|
||||||
if is_symbol(row[c_]) {
|
|
||||||
if row[c_] == '*' {
|
|
||||||
let index = (r + 1) * row.len() + c_;
|
|
||||||
record_gear(n, index, &mut gears);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
c_ += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sum_part_numbers() -> (u32, u32) {
|
|
||||||
let mut part_table: Vec<String> = Vec::new();
|
|
||||||
let mut buffer: String = String::new();
|
|
||||||
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
|
||||||
part_table.push(buffer.trim_end().to_string());
|
|
||||||
buffer = String::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut sum = 0;
|
|
||||||
let mut gear_table = HashMap::new();
|
|
||||||
|
|
||||||
for r in 0..part_table.len() {
|
|
||||||
let mut c = 0;
|
|
||||||
let mut part_rem = &part_table[r][..];
|
|
||||||
loop {
|
|
||||||
match part_rem.find(char::is_numeric) {
|
|
||||||
None => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Some(ind) => {
|
|
||||||
part_rem = &part_rem[ind..];
|
|
||||||
c += ind;
|
|
||||||
let is_non_num = |c: char| !c.is_numeric();
|
|
||||||
let end = match part_rem.find(is_non_num) {
|
|
||||||
None => part_rem.len(),
|
|
||||||
Some(i) => i,
|
|
||||||
};
|
|
||||||
let num: u32 = part_rem[..end].parse().expect("Couldn't parse number");
|
|
||||||
if is_part_number(r, c, end, &part_table, num, &mut gear_table) {
|
|
||||||
sum += num;
|
|
||||||
println!("{} {}", num, gear_table.len());
|
|
||||||
}
|
|
||||||
part_rem = &part_rem[end..];
|
|
||||||
c += end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut gear_sum = 0;
|
|
||||||
for (_, vec) in gear_table {
|
|
||||||
if vec.len() == 2 {
|
|
||||||
gear_sum += vec[0] * vec[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(sum, gear_sum)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_num_list(num_str: &str) -> HashSet<u32> {
|
|
||||||
num_str
|
|
||||||
.split(' ')
|
|
||||||
.filter(|s| s.len() > 0)
|
|
||||||
.map(|s| s.parse().expect("couldn't parse"))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_card_points() -> (u32, u32) {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let mut score = 0;
|
|
||||||
|
|
||||||
let mut card_num = 1;
|
|
||||||
let mut card_counts: Vec<u32> = Vec::new();
|
|
||||||
while io::stdin().read_line(&mut buffer).unwrap() > 0 {
|
|
||||||
if card_counts.len() < card_num + 1 {
|
|
||||||
card_counts.resize(card_num + 1, 0);
|
|
||||||
}
|
|
||||||
card_counts[card_num] += 1;
|
|
||||||
let colon_index = buffer.find(':').unwrap();
|
|
||||||
let bar_index = buffer.find('|').unwrap();
|
|
||||||
|
|
||||||
let winners = parse_num_list(buffer[colon_index + 1..bar_index].trim());
|
|
||||||
let mine = parse_num_list(buffer[bar_index + 1..].trim());
|
|
||||||
|
|
||||||
let mut count = 0;
|
|
||||||
for num in mine {
|
|
||||||
if winners.contains(&num) {
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if count > 0 {
|
|
||||||
score += 1 << (count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if card_counts.len() < card_num + count + 1 {
|
|
||||||
card_counts.resize(card_num + count + 1, 0);
|
|
||||||
}
|
|
||||||
for i in 1..=count {
|
|
||||||
card_counts[card_num + i] += card_counts[card_num]
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = String::new();
|
|
||||||
card_num += 1;
|
|
||||||
}
|
|
||||||
(score, card_counts.iter().sum())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args: Vec<String> = env::args().collect();
|
let args: Vec<String> = env::args().collect();
|
||||||
|
@ -336,14 +12,14 @@ fn main() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match args[1].as_str() {
|
match args[1].as_str() {
|
||||||
"day1a" => println!("Sum: {}", get_calibration_digits()),
|
"day1a" => println!("Sum: {}", day1::get_calibration_digits()),
|
||||||
"day1b" => println!("Sum: {}", get_calibration_digits_alnum()),
|
"day1b" => println!("Sum: {}", day1::get_calibration_digits_alnum()),
|
||||||
"day2a" => println!("Sum: {}", get_possible_games().0),
|
"day2a" => println!("Sum: {}", day2::get_possible_games().0),
|
||||||
"day2b" => println!("Sum: {}", get_possible_games().1),
|
"day2b" => println!("Sum: {}", day2::get_possible_games().1),
|
||||||
"day3a" => println!("Sum: {}", sum_part_numbers().0),
|
"day3a" => println!("Sum: {}", day3::sum_part_numbers().0),
|
||||||
"day3b" => println!("Sum: {}", sum_part_numbers().1),
|
"day3b" => println!("Sum: {}", day3::sum_part_numbers().1),
|
||||||
"day4a" => println!("Sum: {}", get_card_points().0),
|
"day4a" => println!("Sum: {}", day4::get_card_points().0),
|
||||||
"day4b" => println!("Sum: {}", get_card_points().1),
|
"day4b" => println!("Sum: {}", day4::get_card_points().1),
|
||||||
_ => println!("Unrecognized day: {}", args[1]),
|
_ => println!("Unrecognized day: {}", args[1]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue