# Advent of Code 2022: Day 4

A TypeScript solution for the Advent of Code 2022, Day 4 puzzle: it looks like set intersection, but actually it's much easier than that.

Today’s puzzle asks us to check if two ranges of numbers overlap or not. We have to check for complete overlaps and partial overlaps.

Even though the puzzle makes it sound like you want to use the set intersection techniques from yesterday, it’s actually much simpler than that. We just need a couple of functions to check the high and low points of the ranges with basic inequality operators (e.g. `<=` and `>=`) to find the answer.

The puzzle input data looks something like this.

```2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
```

First we split the puzzle data into `Pairs` of `Range` structures that have `hi` and `lo` values. Curiously, data parsing seems to be the most challenging part of today’s puzzle.

```interface Range { lo: number; hi: number; }
interface Pair { left: Range; right: Range; }

const pairs: Pair[] = puzzleInput
.split('\n')
.map(line => line
.split(',')
.map(member => member.split('-').map(x => parseInt(x)))
.map(([lo, hi]) => ({ lo, hi } as Range))
)
.map(([left, right]) => ({ left, right } as Pair));
```

Define a function `within` that checks if a number is within a `Range`.

```const within = (x: number, range: Range) =>
range.lo <= x && x <= range.hi;
```

Define a function `isRedundant` that checks a `Pair` of ranges to see if one of them is redundant (i.e. one entirely contains the other). To check, we see if both of the low/high values of range `left` are within range `right`, or vice versa.

```const isRedundant = ({ left, right }: Pair) =>
(within(left.lo, right) && within(left.hi, right))
|| (within(right.lo, left) && within(right.hi, left));
```

Define a function `isOverlap` that checks if a `Pair`’s ranges overlap at all. To check, we see if either of the low/high values of range `left` are within range `right`, or vice versa.

```const isOverlap = ({ left, right }: Pair) =>
(within(left.lo, right) || within(left.hi, right))
|| (within(right.lo, left) || within(right.hi, left));
```

For part 1, `filter` the pairs to where ranges are redundant, then interrogate `length` to get a count.

```const part1 = pairs.filter(isRedundant).length;
```

Part 2 is the very similar to part 1, except we `filter` for overlapping pairs instead.

```const part2 = pairs.filter(isOverlap).length;
```

## Final Solution

```interface Range { lo: number; hi: number; }
interface Pair { left: Range; right: Range; }

const pairs: Pair[] = puzzleInput
.split('\n')
.map(line => line
.split(',')
.map(member => member.split('-').map(x => parseInt(x)))
.map(([lo, hi]) => ({ lo, hi } as Range))
)
.map(([left, right]) => ({ left, right } as Pair));

const within = (x: number, range: Range) =>
range.lo <= x && x <= range.hi;

const isRedundant = ({ left, right }: Pair) =>
(within(left.lo, right) && within(left.hi, right))
|| (within(right.lo, left) && within(right.hi, left));

const isOverlap = ({ left, right }: Pair) =>
(within(left.lo, right) || within(left.hi, right))
|| (within(right.lo, left) || within(right.hi, left));

const part1 = pairs.filter(isRedundant).length;

const part2 = pairs.filter(isOverlap).length;

console.log("Part 1:", part1);
console.log("Part 2:", part2);
```
```Part 1: 560
Part 2: 839
```