summaryrefslogtreecommitdiffstats
path: root/day8/src/main.rs
blob: 4d18938ded05d9f2b6d8483d96fc02683f0811e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use std::env;
use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::process;

struct Node {
  n_children: usize,
  n_metadata: usize,
  children: Vec<Node>,
  metadata: Vec<u32>
}

impl Node {
  fn value(&self) -> u32 {
    if self.n_children == 0 {
      sum_metadata(&self)
    } else {
      let mut value: u32 = 0;
      for metadatum in &self.metadata {
        let i = (metadatum - 1) as usize;
        if i >= self.n_children {
          continue;
        }
        let child = &self.children[i];
        value += child.value();
      }
      value
    }
  }
}

fn build_tree(nums: &Vec<u32>, offset: usize, depth: u32) -> (Node, usize) {
  let mut i: usize = offset;
  for _k in 0..depth {
    print!("    ");
  }

  let n_children = nums[i] as usize;
  i += 1;

  let n_metadata = nums[i] as usize;
  i += 1;

  println!("n_children: {}, n_metadata: {}", n_children, n_metadata);
  let mut children: Vec<Node> = Vec::new();
  let mut metadata: Vec<u32> = Vec::new();
  for _j in 0..n_children {
    let (child, size) = build_tree(&nums, i, depth + 1);
    i += size;
    children.push(child);
  }
  for j in 0..n_metadata {
    let metadatum = nums[i];
    i += 1;
    metadata.push(metadatum);
  }

  let node = Node { n_children, n_metadata, children, metadata };
  (node, i - offset)
}

fn sum_metadata(node: &Node) -> u32 {
  let mut result: u32 = 0;
  for metadatum in &node.metadata {
    result += metadatum;
  }

  for child in &node.children {
    let sum = sum_metadata(child);
    result += sum;
  }

  result
}

fn main() {
  let args: Vec<String> = env::args().collect();
  if args.len() != 2 {
    println!("Wrong number of arguments. Provide a file name and worker count.");
    process::exit(1);
  }
  let filename = &args[1];

  println!("Using file {} as input.", filename);
  let f = match File::open(filename) {
    Ok(file) => file,
    Err(e) => {
      println!("Failed to open file {}. {:?}", filename, e);
      process::exit(1);
    }
  };
  let file = BufReader::new(&f);
  let lines: Vec<String> = file.lines()
    .map(|line| line.expect("Could not parse line."))
    .collect();

  let is_more_than_one_line = lines.len() >= 1;
  assert!(is_more_than_one_line);

  let line_chars = &lines[0];
  let strs: Vec<&str> = line_chars.split(" ").collect();
  let mut nums: Vec<u32> = Vec::new();
  for s in &strs {
    let num: u32 = s.parse().expect("Could not convert value to u32");
    nums.push(num);
  }

  let (tree, _size) = build_tree(&nums, 0, 0);
  let result_1 = sum_metadata(&tree);
  println!("1. Result: {}", result_1);

  let result_2 = tree.value();
  println!("2. Result: {}", result_2);
}