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() {}
|
Loading…
Reference in New Issue
Block a user