Compare commits
19 Commits
894ddd8ca7
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f00d2805fd | |||
| b705b68051 | |||
| 205ecb4acc | |||
| a97522988a | |||
| 30cb6c5cd6 | |||
| 2e1d7e2f84 | |||
| 2ba25a192c | |||
| 54c81ba1ca | |||
| ae55b29ff4 | |||
| 0cb9b68971 | |||
| 5426357cd7 | |||
| 5809d442da | |||
| 7aa2025dff | |||
| 82a1ecab7d | |||
| 10eca9d419 | |||
| b0f72b2230 | |||
| c875ec5826 | |||
| c3a6c3d117 | |||
| fc2099c14c |
14
03/main.rs
14
03/main.rs
@@ -43,11 +43,7 @@ fn part_one() {
|
||||
}
|
||||
for item in pocket_two.chars() {
|
||||
if knapsack.contains_key(&item) {
|
||||
if item as u32 > 96 {
|
||||
priorities += item as u32 - 96
|
||||
} else {
|
||||
priorities += item as u32 - 38
|
||||
}
|
||||
priorities += (item as u32 - 38) % 58;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -78,12 +74,8 @@ fn part_two() {
|
||||
HashSet::from_iter(one.intersection(three));
|
||||
let mut result = intermediate_one.intersection(&intermediate_two);
|
||||
if let Some(item) = result.next() {
|
||||
// double pointers!
|
||||
if **item as u32 > 96 {
|
||||
priorities += **item as u32 - 96
|
||||
} else {
|
||||
priorities += **item as u32 - 38
|
||||
}
|
||||
// double pointer!
|
||||
priorities += (**item as u32 - 38) % 58;
|
||||
}
|
||||
}
|
||||
group.clear();
|
||||
|
||||
75
04/main.rs
Normal file
75
04/main.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
#![allow(dead_code)]
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut overlaps = 0;
|
||||
for line in lines {
|
||||
if let Ok(ranges) = line {
|
||||
let v: Vec<Vec<i8>> = ranges
|
||||
.split(",")
|
||||
.map(|r| r.split("-").map(|i| i.parse::<i8>().unwrap()).collect())
|
||||
.collect();
|
||||
// 00 ... 01
|
||||
// 10 ... 11
|
||||
if (v[0][0] <= v[1][0] && v[0][1] >= v[1][1])
|
||||
|| (v[1][0] <= v[0][0] && v[1][1] >= v[0][1])
|
||||
{
|
||||
overlaps += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", overlaps);
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut overlaps = 0;
|
||||
for line in lines {
|
||||
if let Ok(ranges) = line {
|
||||
let v: Vec<Vec<i8>> = ranges
|
||||
.split(",")
|
||||
.map(|r| r.split("-").map(|i| i.parse::<i8>().unwrap()).collect())
|
||||
.collect();
|
||||
// 00 ... 01
|
||||
// 10 ... 11
|
||||
// uuuuuugh
|
||||
if (v[0][0] <= v[1][0] && v[0][1] >= v[1][1])
|
||||
|| (v[1][0] <= v[0][0] && v[1][1] >= v[0][1])
|
||||
|| (v[0][0] <= v[1][1] && v[0][0] >= v[1][0])
|
||||
|| (v[0][1] >= v[1][0] && v[0][1] <= v[1][1])
|
||||
{
|
||||
overlaps += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", overlaps);
|
||||
}
|
||||
}
|
||||
115
05/main.rs
Normal file
115
05/main.rs
Normal file
@@ -0,0 +1,115 @@
|
||||
#![allow(dead_code)]
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut stacks = vec![VecDeque::<char>::new(); 9];
|
||||
let mut lines_parsed = 0;
|
||||
for line in lines {
|
||||
lines_parsed += 1;
|
||||
// build our stacks...
|
||||
if lines_parsed < 9 {
|
||||
if let Ok(stack) = line {
|
||||
for (i, s) in stack.chars().enumerate() {
|
||||
if (i % 4) == 1 && s != ' ' {
|
||||
// we load in from the head, so the end of the vec is the "top" of the stack
|
||||
stacks[(i / 4)].push_front(s)
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if lines_parsed < 11 {
|
||||
continue; // skip the break
|
||||
}
|
||||
// ok, so now we need to move the crates around
|
||||
if let Ok(instruction) = line {
|
||||
let steps = instruction.split(" ").collect::<Vec<&str>>();
|
||||
let (mut count, from, to) = (
|
||||
steps[1].parse::<usize>().unwrap(),
|
||||
steps[3].parse::<usize>().unwrap(),
|
||||
steps[5].parse::<usize>().unwrap(),
|
||||
);
|
||||
while count > 0 {
|
||||
let c = stacks[from - 1].pop_back().unwrap();
|
||||
stacks[to - 1].push_back(c);
|
||||
count -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut result = "".to_string();
|
||||
for mut s in stacks {
|
||||
result.push(s.pop_back().unwrap());
|
||||
}
|
||||
println!("{}", result);
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut stacks = vec![VecDeque::<char>::new(); 9];
|
||||
let mut lines_parsed = 0;
|
||||
for line in lines {
|
||||
lines_parsed += 1;
|
||||
// build our stacks...
|
||||
if lines_parsed < 9 {
|
||||
if let Ok(stack) = line {
|
||||
for (i, s) in stack.chars().enumerate() {
|
||||
if (i % 4) == 1 && s != ' ' {
|
||||
// we load in from the head, so the end of the vec is the "top" of the stack
|
||||
stacks[(i / 4)].push_front(s)
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if lines_parsed < 11 {
|
||||
continue; // skip the break
|
||||
}
|
||||
// ok, so now we need to move the crates around
|
||||
if let Ok(instruction) = line {
|
||||
let steps = instruction.split(" ").collect::<Vec<&str>>();
|
||||
let (count, from, to) = (
|
||||
steps[1].parse::<usize>().unwrap(),
|
||||
steps[3].parse::<usize>().unwrap(),
|
||||
steps[5].parse::<usize>().unwrap(),
|
||||
);
|
||||
let s = stacks[from - 1].len();
|
||||
let mut c = stacks[from - 1].split_off(s - count);
|
||||
stacks[to - 1].append(&mut c);
|
||||
}
|
||||
}
|
||||
let mut result = "".to_string();
|
||||
for mut s in stacks {
|
||||
result.push(s.pop_back().unwrap());
|
||||
}
|
||||
println!("{}", result);
|
||||
}
|
||||
}
|
||||
85
06/main.rs
Normal file
85
06/main.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
#![allow(dead_code)]
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(mut lines) = read_lines("./inputs/input") {
|
||||
if let Some(Ok(signal)) = lines.next() {
|
||||
let mut buf = VecDeque::<char>::new();
|
||||
for (i, c) in signal.chars().enumerate() {
|
||||
if buf.len() < 3 {
|
||||
// start of stream
|
||||
buf.push_back(c);
|
||||
continue;
|
||||
} else if buf.contains(&c)
|
||||
|| buf[0] == buf[1]
|
||||
|| buf[1] == buf[2]
|
||||
|| buf[2] == buf[0]
|
||||
{
|
||||
// repeated character
|
||||
buf.pop_front();
|
||||
buf.push_back(c);
|
||||
} else {
|
||||
// found it; offset to the next character
|
||||
println!("{}", i + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
if let Ok(mut lines) = read_lines("./inputs/input") {
|
||||
if let Some(Ok(signal)) = lines.next() {
|
||||
let mut buf = VecDeque::<char>::new();
|
||||
for (i, c) in signal.chars().enumerate() {
|
||||
if buf.len() < 13 {
|
||||
// start of stream
|
||||
buf.push_back(c);
|
||||
continue;
|
||||
} else if buf.contains(&c)
|
||||
|| (1..buf.len()).any(|i| {
|
||||
buf.range(i..)
|
||||
.collect::<VecDeque<&char>>()
|
||||
.contains(&&buf[i - 1]) // neat trick
|
||||
})
|
||||
{
|
||||
// repeated character
|
||||
buf.pop_front();
|
||||
buf.push_back(c);
|
||||
} else {
|
||||
// found it; offset to the next character
|
||||
println!("{}", i + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
07/main.go
Normal file
162
07/main.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type Folder struct {
|
||||
name string
|
||||
files map[string]int
|
||||
folders map[string]*Folder
|
||||
size int
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
root := Folder{
|
||||
name: "/",
|
||||
files: map[string]int{},
|
||||
folders: map[string]*Folder{},
|
||||
}
|
||||
sum := 0
|
||||
stack := []*Folder{&root}
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case line == "$ cd /": // don't care
|
||||
continue
|
||||
case line == "$ ls": // definitely don't care
|
||||
continue
|
||||
case line == "$ cd ..":
|
||||
// since we're done in that child, compute it's size.
|
||||
curr := stack[len(stack)-1]
|
||||
for _, size := range curr.files {
|
||||
curr.size += size
|
||||
}
|
||||
for _, f := range curr.folders {
|
||||
curr.size += f.size
|
||||
}
|
||||
if curr.size <= 100000 {
|
||||
sum += curr.size
|
||||
}
|
||||
// pop off stack
|
||||
stack = stack[0 : len(stack)-1]
|
||||
case strings.HasPrefix(line, "$ cd "): // descend into folder
|
||||
stack = append(stack, stack[len(stack)-1].folders[strings.Split(line, " ")[2]])
|
||||
case strings.HasPrefix(line, "dir "): // add directory to current folder
|
||||
name := strings.Split(line, " ")[1]
|
||||
stack[len(stack)-1].folders[name] = &Folder{
|
||||
name: name,
|
||||
files: map[string]int{},
|
||||
folders: map[string]*Folder{},
|
||||
}
|
||||
default: // add file to current folder
|
||||
stack[len(stack)-1].files[strings.Split(line, " ")[1]] = mustAtoi(strings.Split(line, " ")[0])
|
||||
}
|
||||
}
|
||||
// finish computing directory sizes
|
||||
for len(stack) > 0 {
|
||||
curr := stack[len(stack)-1]
|
||||
for _, size := range curr.files {
|
||||
curr.size += size
|
||||
}
|
||||
for _, f := range curr.folders {
|
||||
curr.size += f.size
|
||||
}
|
||||
stack = stack[0 : len(stack)-1]
|
||||
}
|
||||
fmt.Println(sum)
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
root := Folder{
|
||||
name: "/",
|
||||
files: map[string]int{},
|
||||
folders: map[string]*Folder{},
|
||||
}
|
||||
spaceToFree := 30000000 - (70000000 - 49192532) // size of all files, precomputed
|
||||
toDelete := 70000000
|
||||
stack := []*Folder{&root}
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case line == "$ cd /": // don't care
|
||||
continue
|
||||
case line == "$ ls": // definitely don't care
|
||||
continue
|
||||
case line == "$ cd ..":
|
||||
// since we're done in that child, compute it's size.
|
||||
curr := stack[len(stack)-1]
|
||||
for _, size := range curr.files {
|
||||
curr.size += size
|
||||
}
|
||||
for _, f := range curr.folders {
|
||||
curr.size += f.size
|
||||
}
|
||||
if curr.size > spaceToFree && curr.size < toDelete {
|
||||
toDelete = curr.size
|
||||
}
|
||||
// pop off stack
|
||||
stack = stack[0 : len(stack)-1]
|
||||
case strings.HasPrefix(line, "$ cd "): // descend into folder
|
||||
stack = append(stack, stack[len(stack)-1].folders[strings.Split(line, " ")[2]])
|
||||
case strings.HasPrefix(line, "dir "): // add directory to current folder
|
||||
name := strings.Split(line, " ")[1]
|
||||
stack[len(stack)-1].folders[name] = &Folder{
|
||||
name: name,
|
||||
files: map[string]int{},
|
||||
folders: map[string]*Folder{},
|
||||
}
|
||||
default: // add file to current folder
|
||||
stack[len(stack)-1].files[strings.Split(line, " ")[1]] = mustAtoi(strings.Split(line, " ")[0])
|
||||
}
|
||||
}
|
||||
// finish computing directory sizes
|
||||
for len(stack) > 0 {
|
||||
curr := stack[len(stack)-1]
|
||||
for _, size := range curr.files {
|
||||
curr.size += size
|
||||
}
|
||||
for _, f := range curr.folders {
|
||||
curr.size += f.size
|
||||
}
|
||||
if curr.size > spaceToFree && curr.size < toDelete {
|
||||
toDelete = curr.size
|
||||
}
|
||||
stack = stack[0 : len(stack)-1]
|
||||
}
|
||||
fmt.Println(toDelete)
|
||||
}
|
||||
97
07/main.rs
Normal file
97
07/main.rs
Normal file
@@ -0,0 +1,97 @@
|
||||
#![allow(dead_code)]
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut sum = 0;
|
||||
let mut stack: Vec<u32> = vec![0];
|
||||
for line in lines {
|
||||
if let Ok(command) = line {
|
||||
match command.as_str() {
|
||||
"$ cd /" => continue, // skip start
|
||||
"$ ls" => continue, // we can assume this if we're not moving between directories
|
||||
s if s.starts_with("dir ") => continue, // we'll get there when we `cd`
|
||||
"$ cd .." => {
|
||||
let f = stack.pop().unwrap();
|
||||
if f < 100000 {
|
||||
sum += f
|
||||
}
|
||||
let last_on_stack = stack.len() - 1;
|
||||
stack[last_on_stack] += f;
|
||||
}
|
||||
s if s.starts_with("$ cd ") => {
|
||||
stack.push(0);
|
||||
}
|
||||
s => {
|
||||
// otherwise it must be a file
|
||||
let mut sp = s.split(" ");
|
||||
let last_on_stack = stack.len() - 1;
|
||||
stack[last_on_stack] += sp.next().unwrap().parse::<u32>().unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
println!("{:?}", sum);
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
let mut stack: Vec<u32> = vec![0];
|
||||
let space_to_free = 30000000 - (70000000 - 49192532); // size of all files, precomputed
|
||||
let mut to_delete = 70000000; // arbitrarily large
|
||||
for line in lines {
|
||||
if let Ok(command) = line {
|
||||
match command.as_str() {
|
||||
"$ cd /" => continue, // skip start
|
||||
"$ ls" => continue, // we can assume this if we're not moving between directories
|
||||
s if s.starts_with("dir ") => continue, // we'll get there when we `cd`
|
||||
"$ cd .." => {
|
||||
let f = stack.pop().unwrap();
|
||||
if f > space_to_free && f < to_delete {
|
||||
to_delete = f
|
||||
}
|
||||
let last_on_stack = stack.len() - 1;
|
||||
stack[last_on_stack] += f;
|
||||
}
|
||||
s if s.starts_with("$ cd ") => {
|
||||
stack.push(0);
|
||||
}
|
||||
s => {
|
||||
// otherwise it must be a file
|
||||
let mut sp = s.split(" ");
|
||||
let last_on_stack = stack.len() - 1;
|
||||
stack[last_on_stack] += sp.next().unwrap().parse::<u32>().unwrap();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
println!("{:?}", to_delete);
|
||||
}
|
||||
}
|
||||
147
08/main.rs
Normal file
147
08/main.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
#![allow(dead_code)]
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Tree(i8, bool); // height, visible from outside
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
let mut grid: Vec<Vec<Tree>> = vec![];
|
||||
let mut total = 0;
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for (i, line) in lines.enumerate() {
|
||||
if let Ok(row) = line {
|
||||
grid.push(vec![]);
|
||||
let mut max = -1;
|
||||
for c in row.chars() {
|
||||
if (c as i8) - 48 > max {
|
||||
total += 1;
|
||||
max = (c as i8) - 48;
|
||||
grid[i].push(Tree((c as i8) - 48, true));
|
||||
} else {
|
||||
grid[i].push(Tree((c as i8) - 48, false));
|
||||
}
|
||||
}
|
||||
max = -1;
|
||||
let invert = grid[i].len() - 1;
|
||||
for (j, t) in grid[i].clone().iter().rev().enumerate() {
|
||||
if t.0 > max {
|
||||
if !grid[i][invert - j].1 {
|
||||
total += 1;
|
||||
}
|
||||
max = t.0;
|
||||
grid[i][invert - j] = Tree(t.0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let invert = grid.len() - 1;
|
||||
for i in 0..grid.len() {
|
||||
let mut in_max = -1;
|
||||
let mut out_max = -1;
|
||||
for j in 0..grid.len() {
|
||||
if grid[j][i].0 > in_max {
|
||||
if !grid[j][i].1 {
|
||||
total += 1;
|
||||
}
|
||||
in_max = grid[j][i].0;
|
||||
grid[j][i] = Tree(grid[j][i].0, true);
|
||||
}
|
||||
if grid[invert - j][i].0 > out_max {
|
||||
if !grid[invert - j][i].1 {
|
||||
total += 1;
|
||||
}
|
||||
out_max = grid[invert - j][i].0;
|
||||
grid[invert - j][i] = Tree(grid[invert - j][i].0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", total);
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
let mut grid: Vec<Vec<Tree>> = vec![];
|
||||
let mut best = 0;
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for (i, line) in lines.enumerate() {
|
||||
if let Ok(row) = line {
|
||||
grid.push(vec![]);
|
||||
for c in row.chars() {
|
||||
grid[i].push(Tree((c as i8) - 48, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// alright, we'll do this the hard way
|
||||
// we can skip the edges, because they all multiply by 0 in one way or another
|
||||
for i in 1..grid.len() - 1 {
|
||||
for j in 1..grid.len() - 1 {
|
||||
let (mut score, mut acc) = (1, 0); // a base score and the counter we'll reuse
|
||||
for x in (0..j).rev() {
|
||||
// left
|
||||
acc += 1;
|
||||
if grid[i][x].0 >= grid[i][j].0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
score *= acc;
|
||||
acc = 0;
|
||||
for x in (0..i).rev() {
|
||||
// up
|
||||
acc += 1;
|
||||
if grid[x][j].0 >= grid[i][j].0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
score *= acc;
|
||||
acc = 0;
|
||||
for x in (j + 1)..grid.len() {
|
||||
// right
|
||||
acc += 1;
|
||||
if grid[i][x].0 >= grid[i][j].0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
score *= acc;
|
||||
acc = 0;
|
||||
for x in (i + 1)..grid.len() {
|
||||
// down
|
||||
acc += 1;
|
||||
if grid[x][j].0 >= grid[i][j].0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
score *= acc;
|
||||
if score > best {
|
||||
best = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", best);
|
||||
}
|
||||
179
09/main.go
Normal file
179
09/main.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func moveNextKnot(parent, child *coord) {
|
||||
if parent.y-child.y == 2 {
|
||||
child.y++
|
||||
if parent.x-child.x == 2 {
|
||||
child.x++
|
||||
} else if child.x-parent.x == 2 {
|
||||
child.x--
|
||||
} else {
|
||||
child.x = parent.x
|
||||
}
|
||||
}
|
||||
if child.y-parent.y == 2 {
|
||||
child.y--
|
||||
if parent.x-child.x == 2 {
|
||||
child.x++
|
||||
} else if child.x-parent.x == 2 {
|
||||
child.x--
|
||||
} else {
|
||||
child.x = parent.x
|
||||
}
|
||||
}
|
||||
if parent.x-child.x == 2 {
|
||||
child.x++
|
||||
if parent.y-child.y == 2 {
|
||||
child.y++
|
||||
} else if child.y-parent.y == 2 {
|
||||
child.y--
|
||||
} else {
|
||||
child.y = parent.y
|
||||
}
|
||||
}
|
||||
if child.x-parent.x == 2 {
|
||||
child.x--
|
||||
if parent.y-child.y == 2 {
|
||||
child.y++
|
||||
} else if child.y-parent.y == 2 {
|
||||
child.y--
|
||||
} else {
|
||||
child.y = parent.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func displayGrid(rope []coord) {
|
||||
for x := 0; x < 10; x++ {
|
||||
for y := 0; y < 10; y++ {
|
||||
printed := false
|
||||
for k, c := range rope {
|
||||
if c.x == x && c.y == y && !printed {
|
||||
printed = true
|
||||
if k == 0 {
|
||||
fmt.Print("H")
|
||||
} else {
|
||||
fmt.Print(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !printed {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
grid := map[coord]bool{{x: 0, y: 0}: true}
|
||||
head := coord{x: 0, y: 0}
|
||||
tail := coord{x: 0, y: 0}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
l := strings.Split(line, " ")
|
||||
direction, steps := l[0], mustAtoi(l[1])
|
||||
for i := 0; i < steps; i++ {
|
||||
switch direction {
|
||||
case "U":
|
||||
head.y++
|
||||
case "D":
|
||||
head.y--
|
||||
case "L":
|
||||
head.x--
|
||||
case "R":
|
||||
head.x++
|
||||
default:
|
||||
panic("oh no")
|
||||
}
|
||||
moveNextKnot(&head, &tail)
|
||||
grid[tail] = true
|
||||
}
|
||||
}
|
||||
fmt.Println(len(grid))
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
grid := map[coord]bool{{x: 0, y: 0}: true}
|
||||
rope := []coord{
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
{x: 0, y: 0},
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
l := strings.Split(line, " ")
|
||||
direction, steps := l[0], mustAtoi(l[1])
|
||||
for i := 0; i < steps; i++ {
|
||||
switch direction {
|
||||
case "U":
|
||||
rope[0].y++
|
||||
case "D":
|
||||
rope[0].y--
|
||||
case "L":
|
||||
rope[0].x--
|
||||
case "R":
|
||||
rope[0].x++
|
||||
default:
|
||||
panic("oh no")
|
||||
}
|
||||
for i := 0; i < 9; i++ {
|
||||
moveNextKnot(&rope[i], &rope[i+1])
|
||||
}
|
||||
grid[rope[9]] = true
|
||||
}
|
||||
}
|
||||
fmt.Println(len(grid))
|
||||
}
|
||||
193
09/main.rs
Normal file
193
09/main.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
#![allow(dead_code)]
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug, Eq, Hash, PartialEq, Copy, Clone)]
|
||||
struct Coord(i32, i32);
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
let mut grid = HashMap::<Coord, bool>::new();
|
||||
let (mut head_x, mut head_y) = (0, 0);
|
||||
let (mut tail_x, mut tail_y) = (0, 0);
|
||||
grid.insert(Coord(0, 0), true);
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for line in lines {
|
||||
if let Ok(m) = line {
|
||||
let mut i = m.split(" ");
|
||||
let dir = i.next().unwrap();
|
||||
let steps = i.next().unwrap().parse::<i32>().unwrap();
|
||||
match dir {
|
||||
"U" => {
|
||||
for _ in 0..steps {
|
||||
head_y += 1;
|
||||
(tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y);
|
||||
grid.insert(Coord(tail_x, tail_y), true);
|
||||
}
|
||||
}
|
||||
"D" => {
|
||||
for _ in 0..steps {
|
||||
head_y -= 1;
|
||||
(tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y);
|
||||
grid.insert(Coord(tail_x, tail_y), true);
|
||||
}
|
||||
}
|
||||
"L" => {
|
||||
for _ in 0..steps {
|
||||
head_x -= 1;
|
||||
(tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y);
|
||||
grid.insert(Coord(tail_x, tail_y), true);
|
||||
}
|
||||
}
|
||||
"R" => {
|
||||
for _ in 0..steps {
|
||||
head_x += 1;
|
||||
(tail_x, tail_y) = update_tail(head_x, head_y, tail_x, tail_y);
|
||||
grid.insert(Coord(tail_x, tail_y), true);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("unknown instruction {:?}", m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", grid.len());
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
let mut grid = HashMap::<Coord, bool>::new();
|
||||
let mut knots: Vec<Coord> = vec![
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
Coord(0, 0),
|
||||
];
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for line in lines {
|
||||
if let Ok(m) = line {
|
||||
let mut i = m.split(" ");
|
||||
let dir = i.next().unwrap();
|
||||
let steps = i.next().unwrap().parse::<i32>().unwrap();
|
||||
match dir {
|
||||
"U" => {
|
||||
for _ in 0..steps {
|
||||
knots[0] = Coord(knots[0].0, knots[0].1 + 1);
|
||||
for j in 0..9 {
|
||||
let (tail_x, tail_y) = update_tail(
|
||||
knots[j].0,
|
||||
knots[j].1,
|
||||
knots[j + 1].0,
|
||||
knots[j + 1].1,
|
||||
);
|
||||
knots[j + 1] = Coord(tail_x, tail_y);
|
||||
}
|
||||
grid.insert(knots[9], true);
|
||||
}
|
||||
}
|
||||
"D" => {
|
||||
for _ in 0..steps {
|
||||
knots[0] = Coord(knots[0].0, knots[0].1 - 1);
|
||||
for j in 0..9 {
|
||||
let (tail_x, tail_y) = update_tail(
|
||||
knots[j].0,
|
||||
knots[j].1,
|
||||
knots[j + 1].0,
|
||||
knots[j + 1].1,
|
||||
);
|
||||
knots[j + 1] = Coord(tail_x, tail_y);
|
||||
}
|
||||
grid.insert(knots[9], true);
|
||||
}
|
||||
}
|
||||
"L" => {
|
||||
for _ in 0..steps {
|
||||
knots[0] = Coord(knots[0].0 - 1, knots[0].1);
|
||||
for j in 0..9 {
|
||||
let (tail_x, tail_y) = update_tail(
|
||||
knots[j].0,
|
||||
knots[j].1,
|
||||
knots[j + 1].0,
|
||||
knots[j + 1].1,
|
||||
);
|
||||
knots[j + 1] = Coord(tail_x, tail_y);
|
||||
}
|
||||
grid.insert(knots[9], true);
|
||||
}
|
||||
}
|
||||
"R" => {
|
||||
for _ in 0..steps {
|
||||
knots[0] = Coord(knots[0].0 + 1, knots[0].1);
|
||||
for j in 0..9 {
|
||||
let (tail_x, tail_y) = update_tail(
|
||||
knots[j].0,
|
||||
knots[j].1,
|
||||
knots[j + 1].0,
|
||||
knots[j + 1].1,
|
||||
);
|
||||
knots[j + 1] = Coord(tail_x, tail_y);
|
||||
}
|
||||
grid.insert(knots[9], true);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("unknown instruction {:?}", m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("{}", grid.len());
|
||||
}
|
||||
|
||||
fn update_tail(head_x: i32, head_y: i32, mut tail_x: i32, mut tail_y: i32) -> (i32, i32) {
|
||||
if head_y - tail_y == 2 {
|
||||
tail_y += 1;
|
||||
tail_x = head_x;
|
||||
}
|
||||
if tail_y - head_y == 2 {
|
||||
tail_y -= 1;
|
||||
tail_x = head_x;
|
||||
}
|
||||
if head_x - tail_x == 2 {
|
||||
tail_x += 1;
|
||||
tail_y = head_y;
|
||||
}
|
||||
if tail_x - head_x == 2 {
|
||||
tail_x -= 1;
|
||||
tail_y = head_y;
|
||||
}
|
||||
return (tail_x, tail_y);
|
||||
}
|
||||
111
10/main.go
Normal file
111
10/main.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
register := 1
|
||||
cycleCount := 0
|
||||
signalStrength := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case line == "noop":
|
||||
cycleCount++
|
||||
if cycleCount%40 == 20 {
|
||||
signalStrength += (cycleCount) * register
|
||||
}
|
||||
default:
|
||||
s := strings.Split(line, " ")
|
||||
x := mustAtoi(s[1])
|
||||
cycleCount++
|
||||
if cycleCount%40 == 20 {
|
||||
signalStrength += (cycleCount) * register
|
||||
}
|
||||
cycleCount++
|
||||
if cycleCount%40 == 20 {
|
||||
signalStrength += (cycleCount) * register
|
||||
}
|
||||
register += x
|
||||
}
|
||||
}
|
||||
fmt.Println(signalStrength)
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
screen := make([]string, 241)
|
||||
|
||||
register := 1
|
||||
cycleCount := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case line == "noop":
|
||||
if register == cycleCount%40 || register-1 == cycleCount%40 || register+1 == cycleCount%40 {
|
||||
screen[cycleCount] = "#"
|
||||
} else {
|
||||
screen[cycleCount] = "."
|
||||
}
|
||||
cycleCount++
|
||||
default:
|
||||
s := strings.Split(line, " ")
|
||||
x := mustAtoi(s[1])
|
||||
if register == cycleCount%40 || register-1 == cycleCount%40 || register+1 == cycleCount%40 {
|
||||
screen[cycleCount] = "#"
|
||||
} else {
|
||||
screen[cycleCount] = "."
|
||||
}
|
||||
cycleCount++
|
||||
if register == cycleCount%40 || register-1 == cycleCount%40 || register+1 == cycleCount%40 {
|
||||
screen[cycleCount] = "#"
|
||||
} else {
|
||||
screen[cycleCount] = "."
|
||||
}
|
||||
cycleCount++
|
||||
register += x
|
||||
}
|
||||
}
|
||||
fmt.Println(screen[1:40])
|
||||
fmt.Println(screen[41:80])
|
||||
fmt.Println(screen[81:120])
|
||||
fmt.Println(screen[121:160])
|
||||
fmt.Println(screen[161:200])
|
||||
fmt.Println(screen[201:240])
|
||||
}
|
||||
38
10/main.rs
Normal file
38
10/main.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
#![allow(dead_code)]
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for line in lines {
|
||||
// do stuff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {}
|
||||
201
11/main.go
Normal file
201
11/main.go
Normal file
@@ -0,0 +1,201 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type monkey struct {
|
||||
items []int
|
||||
operation string // either "plus", "times", or "square"
|
||||
value int // ignored for "square"
|
||||
test int // "divisible by <test>"
|
||||
testpass int // monkey to throw to if test passes
|
||||
testfail int // monkey to throw to if test fails
|
||||
inspections int
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
currentMonkey := 0
|
||||
monkeys := []monkey{}
|
||||
|
||||
// parse monkeys
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case strings.HasPrefix(line, "M"):
|
||||
currentMonkey = mustAtoi(strings.Trim(line, "Monkey :"))
|
||||
monkeys = append(monkeys, monkey{items: make([]int, 0)})
|
||||
case strings.HasPrefix(line, " S"):
|
||||
_, after, _ := strings.Cut(line, ":")
|
||||
items := strings.Split(after, ",")
|
||||
for _, i := range items {
|
||||
monkeys[currentMonkey].items = append(monkeys[currentMonkey].items, mustAtoi(strings.TrimSpace(i)))
|
||||
}
|
||||
case strings.HasPrefix(line, " O"):
|
||||
if strings.Contains(line, "+") {
|
||||
monkeys[currentMonkey].operation = "plus"
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].value = mustAtoi(l[len(l)-1])
|
||||
} else if strings.Contains(line, "old * old") {
|
||||
monkeys[currentMonkey].operation = "square"
|
||||
} else if strings.Contains(line, "*") {
|
||||
monkeys[currentMonkey].operation = "times"
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].value = mustAtoi(l[len(l)-1])
|
||||
}
|
||||
case strings.HasPrefix(line, " T"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].test = mustAtoi(l[len(l)-1])
|
||||
case strings.HasPrefix(line, " If t"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].testpass = mustAtoi(l[len(l)-1])
|
||||
case strings.HasPrefix(line, " If f"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].testfail = mustAtoi(l[len(l)-1])
|
||||
}
|
||||
}
|
||||
for i := 0; i < 20; i++ {
|
||||
for m := range monkeys {
|
||||
monkeys[m].inspections += len(monkeys[m].items)
|
||||
for _, i := range monkeys[m].items {
|
||||
if monkeys[m].operation == "plus" {
|
||||
i = (i + monkeys[m].value) / 3
|
||||
}
|
||||
if monkeys[m].operation == "times" {
|
||||
i = (i * monkeys[m].value) / 3
|
||||
}
|
||||
if monkeys[m].operation == "square" {
|
||||
i = (i * i) / 3
|
||||
}
|
||||
if i%monkeys[m].test == 0 {
|
||||
monkeys[monkeys[m].testpass].items = append(monkeys[monkeys[m].testpass].items, i)
|
||||
} else {
|
||||
monkeys[monkeys[m].testfail].items = append(monkeys[monkeys[m].testfail].items, i)
|
||||
}
|
||||
}
|
||||
monkeys[m].items = []int{}
|
||||
}
|
||||
}
|
||||
one, two := 0, 0
|
||||
for _, m := range monkeys {
|
||||
if m.inspections > one && m.inspections > two {
|
||||
one, two = two, m.inspections
|
||||
} else if m.inspections > one {
|
||||
one = m.inspections
|
||||
}
|
||||
}
|
||||
fmt.Println(one * two)
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
currentMonkey := 0
|
||||
monkeys := []monkey{}
|
||||
|
||||
// parse monkeys
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
switch {
|
||||
case strings.HasPrefix(line, "M"):
|
||||
currentMonkey = mustAtoi(strings.Trim(line, "Monkey :"))
|
||||
monkeys = append(monkeys, monkey{items: make([]int, 0)})
|
||||
case strings.HasPrefix(line, " S"):
|
||||
_, after, _ := strings.Cut(line, ":")
|
||||
items := strings.Split(after, ",")
|
||||
for _, i := range items {
|
||||
monkeys[currentMonkey].items = append(
|
||||
monkeys[currentMonkey].items, mustAtoi(strings.TrimSpace(i)),
|
||||
)
|
||||
}
|
||||
case strings.HasPrefix(line, " O"):
|
||||
if strings.Contains(line, "+") {
|
||||
monkeys[currentMonkey].operation = "plus"
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].value = mustAtoi(l[len(l)-1])
|
||||
} else if strings.Contains(line, "old * old") {
|
||||
monkeys[currentMonkey].operation = "square"
|
||||
} else if strings.Contains(line, "*") {
|
||||
monkeys[currentMonkey].operation = "times"
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].value = mustAtoi(l[len(l)-1])
|
||||
}
|
||||
case strings.HasPrefix(line, " T"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].test = mustAtoi(l[len(l)-1])
|
||||
case strings.HasPrefix(line, " If t"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].testpass = mustAtoi(l[len(l)-1])
|
||||
case strings.HasPrefix(line, " If f"):
|
||||
l := strings.Split(line, " ")
|
||||
monkeys[currentMonkey].testfail = mustAtoi(l[len(l)-1])
|
||||
}
|
||||
}
|
||||
common := 1
|
||||
for i := range monkeys {
|
||||
common = common * monkeys[i].test
|
||||
}
|
||||
for j := 0; j < 10000; j++ {
|
||||
for m := range monkeys {
|
||||
monkeys[m].inspections += len(monkeys[m].items)
|
||||
for _, i := range monkeys[m].items {
|
||||
if monkeys[m].operation == "plus" {
|
||||
i = i + monkeys[m].value
|
||||
}
|
||||
if monkeys[m].operation == "times" {
|
||||
i = i * monkeys[m].value
|
||||
}
|
||||
if monkeys[m].operation == "square" {
|
||||
i = i * i
|
||||
}
|
||||
if i%monkeys[m].test == 0 {
|
||||
monkeys[monkeys[m].testpass].items = append(monkeys[monkeys[m].testpass].items, i%common)
|
||||
} else {
|
||||
monkeys[monkeys[m].testfail].items = append(monkeys[monkeys[m].testfail].items, i%common)
|
||||
}
|
||||
}
|
||||
monkeys[m].items = []int{}
|
||||
}
|
||||
}
|
||||
one, two := 0, 0
|
||||
for _, m := range monkeys {
|
||||
if m.inspections > one && m.inspections > two {
|
||||
one, two = two, m.inspections
|
||||
} else if m.inspections > one {
|
||||
one = m.inspections
|
||||
}
|
||||
}
|
||||
fmt.Println(one * two)
|
||||
}
|
||||
38
11/main.rs
Normal file
38
11/main.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
#![allow(dead_code)]
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::path::Path;
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
let now = Instant::now();
|
||||
part_one();
|
||||
let part_one_duration = now.elapsed();
|
||||
part_two();
|
||||
let part_two_duration = now.elapsed();
|
||||
println!(
|
||||
"p1: {}ms, p2: {}ms",
|
||||
part_one_duration.as_millis(),
|
||||
(part_two_duration - part_one_duration).as_millis()
|
||||
);
|
||||
}
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
// note that this discards a final newline
|
||||
let file = File::open(filename)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
if let Ok(lines) = read_lines("./inputs/input") {
|
||||
for line in lines {
|
||||
// do stuff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part_two() {}
|
||||
50
12/main.go
Normal file
50
12/main.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
for scanner.Scan() {
|
||||
// line := scanner.Text()
|
||||
}
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
for scanner.Scan() {
|
||||
// line := scanner.Text()
|
||||
}
|
||||
}
|
||||
103
13/main.go
Normal file
103
13/main.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type thing interface {
|
||||
IsNum() bool
|
||||
Num() int
|
||||
IsList() bool
|
||||
List() list
|
||||
}
|
||||
|
||||
type list struct {
|
||||
children []thing
|
||||
}
|
||||
|
||||
func (_ list) IsNum() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n list) Num() int {
|
||||
panic("oops")
|
||||
}
|
||||
|
||||
func (_ list) IsList() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (l list) List() list {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l list) Len() int {
|
||||
return len(l.children)
|
||||
}
|
||||
|
||||
type num int
|
||||
|
||||
func (_ num) IsNum() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n num) Num() int {
|
||||
return int(n)
|
||||
}
|
||||
|
||||
func (_ num) IsList() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (_ num) List() list {
|
||||
panic("oops")
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
pairCount := 0
|
||||
sum := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
left := scanner.Text()
|
||||
right := scanner.Text()
|
||||
}
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
for scanner.Scan() {
|
||||
// line := scanner.Text()
|
||||
}
|
||||
}
|
||||
223
14/main.go
Normal file
223
14/main.go
Normal file
@@ -0,0 +1,223 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func getRange(start, end int) []int {
|
||||
if start > end {
|
||||
s := make([]int, start-end+1)
|
||||
for i := range s {
|
||||
s[i] = start
|
||||
start--
|
||||
}
|
||||
return s
|
||||
}
|
||||
if end > start {
|
||||
s := make([]int, end-start+1)
|
||||
for i := range s {
|
||||
s[i] = start
|
||||
start++
|
||||
}
|
||||
return s
|
||||
}
|
||||
return []int{}
|
||||
}
|
||||
|
||||
func printCave(cave map[coord]int, xmin, xmax, depth int, floor bool) {
|
||||
for _, d := range getRange(0, depth) {
|
||||
fmt.Printf("%3d ", d)
|
||||
for _, x := range getRange(xmin, xmax) {
|
||||
if d == 0 && x == 500 {
|
||||
fmt.Print("+")
|
||||
} else if score, ok := cave[coord{x: x, y: d}]; ok {
|
||||
if score == 1 {
|
||||
fmt.Print("#")
|
||||
} else if score == 2 {
|
||||
fmt.Print("o")
|
||||
}
|
||||
} else {
|
||||
fmt.Print(".")
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
if floor {
|
||||
fmt.Printf("%3d ", depth+1)
|
||||
for range getRange(xmin, xmax) {
|
||||
fmt.Print("#")
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
// return value is false if sand reached max depth
|
||||
func addSand(cave map[coord]int, depth int, floor bool) bool {
|
||||
x := 500
|
||||
y := 0
|
||||
for {
|
||||
if y > depth {
|
||||
if floor {
|
||||
// made it to the floor, come to rest
|
||||
cave[coord{x: x, y: y}] = 2
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
if _, blocked := cave[coord{x: x, y: y + 1}]; !blocked {
|
||||
y += 1
|
||||
continue
|
||||
}
|
||||
if _, blocked := cave[coord{x: x - 1, y: y + 1}]; !blocked {
|
||||
y += 1
|
||||
x -= 1
|
||||
continue
|
||||
}
|
||||
if _, blocked := cave[coord{x: x + 1, y: y + 1}]; !blocked {
|
||||
y += 1
|
||||
x += 1
|
||||
continue
|
||||
}
|
||||
// filled the cavern, return false
|
||||
if y == 0 {
|
||||
cave[coord{x: x, y: y}] = 2
|
||||
return false
|
||||
}
|
||||
// blocked in all directions, come to rest
|
||||
cave[coord{x: x, y: y}] = 2
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
cave := map[coord]int{}
|
||||
maxx, minx, depth := 0, 1000, 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
coords := strings.Split(line, " -> ")
|
||||
prevx, prevy := 0, 0
|
||||
for _, i := range coords {
|
||||
x, y, _ := strings.Cut(i, ",")
|
||||
if prevx == 0 && prevy == 0 {
|
||||
prevx, prevy = mustAtoi(x), mustAtoi(y)
|
||||
continue
|
||||
}
|
||||
if prevx == mustAtoi(x) {
|
||||
for _, curry := range getRange(prevy, mustAtoi(y)) {
|
||||
cave[coord{x: prevx, y: curry}] = 1
|
||||
}
|
||||
prevy = mustAtoi(y)
|
||||
} else if prevy == mustAtoi(y) {
|
||||
for _, currx := range getRange(prevx, mustAtoi(x)) {
|
||||
cave[coord{x: currx, y: prevy}] = 1
|
||||
}
|
||||
prevx = mustAtoi(x)
|
||||
}
|
||||
if mustAtoi(x) > maxx {
|
||||
maxx = mustAtoi(x)
|
||||
} else if mustAtoi(x) < minx {
|
||||
minx = mustAtoi(x)
|
||||
}
|
||||
if mustAtoi(y) > depth {
|
||||
depth = mustAtoi(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
for addSand(cave, depth, false) {
|
||||
}
|
||||
printCave(cave, minx-1, maxx+1, depth+1, false)
|
||||
score := 0
|
||||
for _, c := range cave {
|
||||
if c == 2 {
|
||||
score++
|
||||
}
|
||||
}
|
||||
fmt.Println(score)
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
cave := map[coord]int{}
|
||||
maxx, minx, depth := 0, 1000, 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
coords := strings.Split(line, " -> ")
|
||||
prevx, prevy := 0, 0
|
||||
for _, i := range coords {
|
||||
x, y, _ := strings.Cut(i, ",")
|
||||
if prevx == 0 && prevy == 0 {
|
||||
prevx, prevy = mustAtoi(x), mustAtoi(y)
|
||||
continue
|
||||
}
|
||||
if prevx == mustAtoi(x) {
|
||||
for _, curry := range getRange(prevy, mustAtoi(y)) {
|
||||
cave[coord{x: prevx, y: curry}] = 1
|
||||
}
|
||||
prevy = mustAtoi(y)
|
||||
} else if prevy == mustAtoi(y) {
|
||||
for _, currx := range getRange(prevx, mustAtoi(x)) {
|
||||
cave[coord{x: currx, y: prevy}] = 1
|
||||
}
|
||||
prevx = mustAtoi(x)
|
||||
}
|
||||
if mustAtoi(x) > maxx {
|
||||
maxx = mustAtoi(x)
|
||||
} else if mustAtoi(x) < minx {
|
||||
minx = mustAtoi(x)
|
||||
}
|
||||
if mustAtoi(y) > depth {
|
||||
depth = mustAtoi(y)
|
||||
}
|
||||
}
|
||||
}
|
||||
for addSand(cave, depth, true) {
|
||||
}
|
||||
printCave(cave, minx-1, maxx+1, depth+1, true)
|
||||
score := 0
|
||||
for _, c := range cave {
|
||||
if c == 2 {
|
||||
score++
|
||||
}
|
||||
}
|
||||
fmt.Println(score)
|
||||
}
|
||||
161
15/main.go
Normal file
161
15/main.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
type coord struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func abs(i, j int) int {
|
||||
if i < j {
|
||||
return j - i
|
||||
}
|
||||
return i - j
|
||||
}
|
||||
|
||||
func getCoords(x, y string, _ bool) coord {
|
||||
return coord{x: mustAtoi(x), y: mustAtoi(y)}
|
||||
}
|
||||
|
||||
func distance(sensor, beacon coord) int {
|
||||
return abs(sensor.x, beacon.x) + abs(sensor.y, beacon.y)
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
test := false
|
||||
scanner := makeScanner(test)
|
||||
row := 2000000
|
||||
if test {
|
||||
row = 10
|
||||
}
|
||||
cave := map[coord]int{} // 0 for unknown space, 1 for sensor, 2 for beacon, 3 for known empty
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
s, b, _ := strings.Cut(line, ": ")
|
||||
sensor := getCoords(strings.Cut(strings.Trim(s, "Sensor at x="), ", y="))
|
||||
beacon := getCoords(strings.Cut(strings.Trim(b, "closest beacon is at x="), ", y="))
|
||||
dist := distance(sensor, beacon)
|
||||
cave[sensor] = 1
|
||||
cave[beacon] = 2
|
||||
rel := distance(sensor, coord{x: sensor.x, y: row})
|
||||
if rel <= dist {
|
||||
c := dist - rel
|
||||
for i := sensor.x - c; i <= sensor.x+c; i++ {
|
||||
if _, ok := cave[coord{x: i, y: row}]; !ok {
|
||||
cave[coord{x: i, y: row}] = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sum := 0
|
||||
for _, i := range cave {
|
||||
if i == 3 {
|
||||
sum++
|
||||
}
|
||||
}
|
||||
fmt.Println(sum)
|
||||
}
|
||||
|
||||
func sensorHalo(sensor coord, distance int) []coord {
|
||||
halo := []coord{}
|
||||
corners := []coord{
|
||||
{x: sensor.x, y: sensor.y + distance + 1},
|
||||
{x: sensor.x + distance + 1, y: sensor.y},
|
||||
{x: sensor.x, y: sensor.y - distance - 1},
|
||||
{x: sensor.x - distance - 1, y: sensor.y},
|
||||
}
|
||||
y := corners[0].y
|
||||
for i := corners[0].x; i < corners[1].x; i++ {
|
||||
halo = append(halo, coord{i, y})
|
||||
y--
|
||||
}
|
||||
for i := corners[1].x; i > corners[2].x; i-- {
|
||||
halo = append(halo, coord{i, y})
|
||||
y--
|
||||
}
|
||||
for i := corners[2].x; i > corners[3].x; i-- {
|
||||
halo = append(halo, coord{i, y})
|
||||
y++
|
||||
}
|
||||
for i := corners[3].x; i > corners[0].x; i++ {
|
||||
halo = append(halo, coord{i, y})
|
||||
y++
|
||||
}
|
||||
halo = append(halo, corners[3])
|
||||
return halo
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
test := false
|
||||
scanner := makeScanner(test)
|
||||
max := 4000000
|
||||
if test {
|
||||
max = 20
|
||||
}
|
||||
cave := map[coord]int{} // sensor: distance to beacon
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
s, b, _ := strings.Cut(line, ": ")
|
||||
sensor := getCoords(strings.Cut(strings.Trim(s, "Sensor at x="), ", y="))
|
||||
beacon := getCoords(strings.Cut(strings.Trim(b, "closest beacon is at x="), ", y="))
|
||||
dist := distance(sensor, beacon)
|
||||
cave[sensor] = dist
|
||||
}
|
||||
// since there's only one of these holes in the search space,
|
||||
// it must be just outside the maximum distance from a sensor
|
||||
// it'll take far too long to search the entire cavern, after all
|
||||
possibleCoords := []coord{}
|
||||
for sensor, dist := range cave {
|
||||
possibleCoords = append(possibleCoords, sensorHalo(sensor, dist)...)
|
||||
}
|
||||
for _, poss := range possibleCoords {
|
||||
if poss.x < 0 || poss.y < 0 || poss.x > max || poss.y > max {
|
||||
continue
|
||||
}
|
||||
hit := false
|
||||
for sensor, dist := range cave {
|
||||
if distance(sensor, poss) < dist {
|
||||
hit = true
|
||||
}
|
||||
}
|
||||
if !hit {
|
||||
fmt.Println(poss.x*4000000 + poss.y)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
77
25/main.go
Normal file
77
25/main.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
fmt.Printf("p1: %s\n", duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
func parseSNAFU(str string) int {
|
||||
num := 0
|
||||
place := 1
|
||||
for i := len(str) - 1; i >= 0; i-- {
|
||||
switch str[i] {
|
||||
case '2':
|
||||
num += place * 2
|
||||
case '1':
|
||||
num += place
|
||||
case '0':
|
||||
// noop
|
||||
case '-':
|
||||
num -= place
|
||||
case '=':
|
||||
num -= place * 2
|
||||
default:
|
||||
panic("oh no")
|
||||
}
|
||||
place *= 5
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
func toSNAFU(normal int) string {
|
||||
num := ""
|
||||
digits := []string{"0", "1", "2", "=", "-"}
|
||||
for {
|
||||
num = digits[normal%5] + num
|
||||
if normal == 0 {
|
||||
return num
|
||||
}
|
||||
normal = (normal + 2) / 5
|
||||
}
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
sum := 0
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
sum += parseSNAFU(line)
|
||||
}
|
||||
fmt.Println(toSNAFU(sum)[1:])
|
||||
}
|
||||
50
main.go.tmpl
Normal file
50
main.go.tmpl
Normal file
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func mustAtoi(line string) int {
|
||||
i, _ := strconv.Atoi(line)
|
||||
return i
|
||||
}
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
partOne()
|
||||
duration := time.Since(start)
|
||||
partTwo()
|
||||
duration2 := time.Since(start)
|
||||
fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration)
|
||||
}
|
||||
|
||||
func makeScanner(test bool) *bufio.Scanner {
|
||||
var f *os.File
|
||||
if test {
|
||||
f, _ = os.Open("inputs/testinput")
|
||||
} else {
|
||||
f, _ = os.Open("inputs/input")
|
||||
}
|
||||
reader := bufio.NewReader(f)
|
||||
return bufio.NewScanner(reader)
|
||||
}
|
||||
|
||||
func partOne() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
for scanner.Scan() {
|
||||
// line := scanner.Text()
|
||||
}
|
||||
}
|
||||
|
||||
func partTwo() {
|
||||
scanner := makeScanner(false)
|
||||
|
||||
for scanner.Scan() {
|
||||
// line := scanner.Text()
|
||||
}
|
||||
}
|
||||
7
new.sh
7
new.sh
@@ -11,8 +11,11 @@ if [ "${1}" != "" ]; then
|
||||
-A "https://git.yetaga.in/alazyreader/AdventOfCode2022/" \
|
||||
-H "Cookie: session=`cat .cookie`" https://adventofcode.com/${__year}/day/${1##0}/input > "${padded}/inputs/input"
|
||||
fi
|
||||
if [ ! -f "${padded}/main.rs" ]; then
|
||||
cp -n main.rs.tmpl ${padded}/main.rs
|
||||
# if [ ! -f "${padded}/main.rs" ]; then
|
||||
# cp -n main.rs.tmpl ${padded}/main.rs
|
||||
# fi
|
||||
if [ ! -f "${padded}/main.go" ]; then
|
||||
cp -n main.go.tmpl ${padded}/main.go
|
||||
fi
|
||||
echo "https://adventofcode.com/2022/day/${1}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user