aboutsummaryrefslogtreecommitdiffstats
path: root/day7/index.ts
blob: f6a126e3495523b99169c3e9bfc62f8a464c79fe (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
import { of } from "rxjs";
import { concatAll, map, reduce, toArray } from 'rxjs/operators';
import { ExerciseModuleFunc } from "../types";

interface RuleChild {
  type: string;
  num: number;
}

interface Rule {
  type: string;
  children: RuleChild[];
}

interface TreeNode {
  type: string;
  children: TreeNode[];
}

const union = <T extends unknown>(...sets: Set<T>[]): Set<T> => {
  let result = new Set<T>();
  for (const set of sets) {
    result = new Set([...Array.from(result), ...Array.from(set)]);
  }
  return result;
}

const rowToRule = (row: string): Rule => {
  const [lhs, rhs] = row.split("bags contain").map(part => part.trim());

  if (rhs.startsWith("no")) {
    return {
      type: lhs,
      children: []
    }
  }

  const childBags = rhs.split(", ");
  const children = childBags.map(str => {
    const match = str.match(/(\d)\ (\w+\ \w+).*?/);

    const num = Number(match[1]);
    const type = match[2];

    return {
      type,
      num
    }
  });

  return {
    type: lhs,
    children
  }
};

const constructNode = (rules: Rule[], type: string): TreeNode => {
  const children = rules
    .filter(rule => rule.children.some(child => child.type === type))
    .reduce((acc: TreeNode, rule) => {
      const newChild = constructNode(rules, rule.type);
      acc.children.push(newChild);
      return acc;
    }, { type, children: [] });

  return children;
}

const buildTree = (rules: Rule[], rootType: string) => {
  return constructNode(rules, rootType);
}

const uniqueNonRootNodes = (tree: TreeNode): Set<string> => {
  let set = new Set<string>();

  for (let child of tree.children) {
    set.add(child.type);

    const childUniques = uniqueNonRootNodes(child);
    set = union(set, childUniques);
  }

  return set;
}

const day7: ExerciseModuleFunc = async (input: string) => {
  const rows = input.split("\n");

  const prom1 = of(rows).pipe(
    concatAll(),
    map(rowToRule),
    toArray(),
    map(rules => buildTree(rules, "shiny gold")),
    map(tree => uniqueNonRootNodes(tree)),
    map(set => set.size)
  ).toPromise();

  // const prom2 = of(rows).pipe(
  // ).toPromise();

  return Promise.all([prom1]);
}

export default day7;