day 7. gave up on fighting the borrow checker after three hours and wrote the go version in 45 minutes.
This commit is contained in:
parent
10eca9d419
commit
82a1ecab7d
158
07/main.go
Normal file
158
07/main.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
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
|
||||||
|
parent *Folder
|
||||||
|
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,
|
||||||
|
parent: stack[len(stack)-1],
|
||||||
|
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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// compute root size
|
||||||
|
for _, size := range root.files {
|
||||||
|
root.size += size
|
||||||
|
}
|
||||||
|
for _, f := range root.folders {
|
||||||
|
root.size += f.size
|
||||||
|
}
|
||||||
|
fmt.Println(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func partTwo() {
|
||||||
|
scanner := makeScanner(false)
|
||||||
|
|
||||||
|
root := Folder{
|
||||||
|
name: "/",
|
||||||
|
files: map[string]int{},
|
||||||
|
folders: map[string]*Folder{},
|
||||||
|
}
|
||||||
|
spaceToFree := 30000000 - (70000000 - 49192532)
|
||||||
|
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,
|
||||||
|
parent: stack[len(stack)-1],
|
||||||
|
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(toDelete)
|
||||||
|
}
|
99
07/main.rs
Normal file
99
07/main.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#![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, Clone)]
|
||||||
|
struct ElfFile {
|
||||||
|
name: String,
|
||||||
|
size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Folder<'a> {
|
||||||
|
name: String,
|
||||||
|
files: HashMap<String, ElfFile>,
|
||||||
|
folders: HashMap<String, &'a Folder<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ElfFile_FromStr(s: &str) -> ElfFile {
|
||||||
|
let mut f = s.split(" ");
|
||||||
|
return ElfFile {
|
||||||
|
size: f.next().unwrap().parse::<u32>().unwrap(),
|
||||||
|
name: f.next().unwrap().to_string(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn newFolder(s: &str) -> Folder {
|
||||||
|
return Folder {
|
||||||
|
name: s.to_string(),
|
||||||
|
files: HashMap::new(),
|
||||||
|
folders: HashMap::new(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_one() {
|
||||||
|
if let Ok(lines) = read_lines("./inputs/input") {
|
||||||
|
let mut tree = Folder {
|
||||||
|
name: "/".to_string(),
|
||||||
|
files: HashMap::new(),
|
||||||
|
folders: HashMap::new(),
|
||||||
|
};
|
||||||
|
let mut stack: Vec<&mut Folder> = vec![&mut tree];
|
||||||
|
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
|
||||||
|
"$ cd .." => {
|
||||||
|
// stack.pop();
|
||||||
|
}
|
||||||
|
s if s.starts_with("$ cd ") => {
|
||||||
|
println!("push {}\n", s.split(" ").nth(2).unwrap())
|
||||||
|
}
|
||||||
|
s if s.starts_with("dir ") => {
|
||||||
|
let f = stack.pop().unwrap();
|
||||||
|
let ef = newFolder(s.split(" ").nth(1).unwrap());
|
||||||
|
f.folders.insert(ef.name.clone(), &ef);
|
||||||
|
stack.push(f);
|
||||||
|
}
|
||||||
|
s => {
|
||||||
|
// otherwise it must be a file
|
||||||
|
let f = stack.pop().unwrap();
|
||||||
|
let ef = ElfFile_FromStr(s);
|
||||||
|
f.files.insert(ef.name.clone(), ef);
|
||||||
|
stack.push(f);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{:?}", tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_two() {}
|
6
run.sh
6
run.sh
@ -3,6 +3,10 @@
|
|||||||
if [ "${1}" != "" ]; then
|
if [ "${1}" != "" ]; then
|
||||||
padded=$(printf "%02g" ${1})
|
padded=$(printf "%02g" ${1})
|
||||||
cd ${padded}
|
cd ${padded}
|
||||||
rustc main.rs && ./main && rm main
|
if [ "${2}" == "go" ]; then
|
||||||
|
go run main.go
|
||||||
|
else
|
||||||
|
rustc main.rs && ./main && rm main
|
||||||
|
fi
|
||||||
cd - > /dev/null
|
cd - > /dev/null
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user