[Advent Of Code 2022] Day 04: Camp Cleanup [SPOILERS]

Management wasn’t paying much attention when they handed out the assignments!

Thankfully we only need to solve pairs of elves and not detect all overlaps!

Rough code (initial solve) - Clean Code

Summary
part1 = sum(
    True
    for a1, a2, b1, b2 in parsed_input
    if (a1 >= b1 and a2 <= b2) or (b1 >= a1 and b2 <= a2)
)

part2 = sum(
    True
    for a1, a2, b1, b2 in parsed_input
    if b1 <= a1 <= b2 or a1 <= b1 <= a2
)

Reviewing my Pangram exercise notes this morning for Day 03 helped out a lot. :slight_smile:

Julia Solution
module day04
    function part01() 
        count = 0
        for l in eachline("/Users/anagy/Documents/AdventOfCode2022/AdventOfCode2022-Julia/input/04/input.in")
            start1, stop1, start2, stop2 = parse.(Int, split(l, r"[,-]"))
            pair1 = range(start1, stop1)
            pair2 = range(start2, stop2)
            if (pair1 ⊆ pair2) || (pair2 ⊆ pair1)
                count += 1
            end
        end
        count
    end

    function part02()
        count = 0
        for l in eachline("/Users/anagy/Documents/AdventOfCode2022/AdventOfCode2022-Julia/input/04/input.in")
            start1, stop1, start2, stop2 = parse.(Int, split(l, r"[,-]"))
            pair1 = range(start1, stop1)
            pair2 = range(start2, stop2)
            if (!isempty(pair1 ∩ pair2))
                count += 1
            end
        end
        count  
    end
end
println("P01: $(day04.part01())")
println("P02: $(day04.part02())")

I have a feeling this was the easiest day yet this year. It was good to have a more relaxed day. Calm before the storm :smiley:

Typescript solution

Complete code: Advent-Of-Code/day04.ts at master · andrerfcsantos/Advent-Of-Code · GitHub

interface Range {
  min: number;
  max: number;
}

interface RangePair {
  first: Range;
  second: Range;
}

interface State {
  rangePairs: RangePair[];
}

export function parse(input: string): State {
  return {
    rangePairs: nonEmptyLines(input).map((l) => {
      const [r1, r2] = l.split(",");
      const [min1, max1] = r1.split("-").map((x) => parseInt(x, 10));
      const [min2, max2] = r2.split("-").map((x) => parseInt(x, 10));
      return {
        first: { min: min1, max: max1 },
        second: { min: min2, max: max2 },
      };
    }),
  };
}

function isContainedBy(r1: Range, r2: Range): boolean {
  return r1.min >= r2.min && r1.max <= r2.max;
}

function doesOverlap(r1: Range, r2: Range): boolean {
  return r1.min <= r2.max && r1.max >= r2.min;
}

export function part1(parsed: State): string {
  const containedRanges = parsed.rangePairs.filter((rangePair) => {
    const { first, second } = rangePair;
    return isContainedBy(first, second) || isContainedBy(second, first);
  });

  return containedRanges.length.toString();
}

export function part2(parsed: State): string {
  const overlappedRanges = parsed.rangePairs.filter((rangePair) => {
    const { first, second } = rangePair;
    return doesOverlap(first, second) || doesOverlap(second, first);
  });

  return overlappedRanges.length.toString();
}

I was also surprised that this was so smooth. I didn’t even leave the console to solve that one. So part 1 is a one-liner, as I forgot to make it as “pretty” as part 2.

defmodule AdventOfCode.Day04 do
  def part1(args) do
    args|> String.split() |> Enum.map(&String.split(&1, ~r{[\-\,]})) |> Enum.map(&Enum.map(&1, fn x -> String.to_integer(x) end)) |> Enum.map(fn [a,b,c,d] -> (a >= c and b <= d) or (c >= a and d <= b)  end) |> Enum.count(fn x -> x end)
  end

  def part2(args) do
    args
    |> String.split()
    |> Enum.map(&String.split(&1, ~r{[\-\,]}))
    |> Enum.map(&Enum.map(&1, fn x -> String.to_integer(x) end))
    |> Enum.map(fn [a,b,c,d] -> (a >= c and a <= d) or (b >= c and b <= d) or (c >= a and c <= b) or (d >= a and d <= b)
   end)
    |> Enum.count(fn x -> x end)

  end
end
Ruby Solution
def contains(fst, snd) = fst[0] >= snd[0] && fst[1] <= snd[1]
def overlaps(fst, snd) = fst[0] >= snd[0] && fst[0] <= snd[1] || fst[1] >= snd[0] && fst[1] <= snd[1]

pairs = File.readlines('inputs/04.txt', chomp: true).map { |line| line.split(',').map { |assignment| assignment.split('-').map(&:to_i) } }
a = pairs.count { |fst, snd| contains(fst, snd) || contains(snd, fst) }
b = pairs.count { |fst, snd| overlaps(fst, snd) || overlaps(snd, fst) }