diff --git a/07/main.go b/07/main.go new file mode 100644 index 0000000..84c6aee --- /dev/null +++ b/07/main.go @@ -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) +} diff --git a/07/main.rs b/07/main.rs new file mode 100644 index 0000000..05ed050 --- /dev/null +++ b/07/main.rs @@ -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, + folders: HashMap>, +} + +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

(filename: P) -> io::Result>> +where + P: AsRef, +{ + // 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::().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() {} diff --git a/run.sh b/run.sh index bc15aa9..1464388 100755 --- a/run.sh +++ b/run.sh @@ -3,6 +3,10 @@ if [ "${1}" != "" ]; then padded=$(printf "%02g" ${1}) 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 fi