01020304050607080910111213141516171819202122232425

Advent of Code

2023/13

Point of Incidence

in C#

by encse

Those who need a refresh can read the problem here.

A mirror is hidden somewhere in a rectangular board (our input). Some of the rocks in the picture are just reflections. The problem doesn't specify if the mirror is put horizontal or vertical, but we know that it's across the board from one end to the other and it is not necessarly in the middle.

Pretty much following the description, I created a function that tries all possible placements and computes how many errors (smudges - using the problem's terminology) were if the mirror was placed right there. Then just selected the one that had zero errors.

The second half of the problem asked for the very same thing but this time there was one smudge in the reflected image.

namespace AdventOfCode.Y2023.Day13;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Map = System.Collections.Generic.Dictionary<System.Numerics.Complex, char>;

[ProblemName("Point of Incidence")]
class Solution : Solver {

    Complex Right = 1;
    Complex Down = Complex.ImaginaryOne;
    Complex Ortho(Complex dir) => dir == Right ? Down : Right;

    public object PartOne(string input) => Solve(input, 0);
    public object PartTwo(string input) => Solve(input, 1);

    double Solve(string input, int allowedSmudges) => (
        from block in input.Split("\n\n")
        let map = ParseMap(block)
        select GetScore(map, allowedSmudges)
    ).Sum();

    // place a mirror along the edges of the map, find the one with the allowed smudges 
    double GetScore(Map map, int allowedSmudges) => (
        from dir in new Complex[] { Right, Down }
        from mirror in Positions(map, dir, dir)
        where FindSmudges(map, mirror, dir) == allowedSmudges
        select mirror.Real + 100 * mirror.Imaginary
    ).First();

    // cast a ray from each postion along the mirror and count the smudges
    int FindSmudges(Map map, Complex mirror, Complex rayDir) => (
        from ray0 in Positions(map, mirror, Ortho(rayDir))
        let rayA = Positions(map, ray0, rayDir)
        let rayB = Positions(map, ray0 - rayDir, -rayDir)
        select Enumerable.Zip(rayA, rayB).Count(p => map[p.First] != map[p.Second])
    ).Sum();

    // allowed positions of the map from 'start' going in 'dir'
    IEnumerable<Complex> Positions(Map map, Complex start, Complex dir) {
        for (var pos = start; map.ContainsKey(pos); pos += dir) {
            yield return pos; 
        }
    }

    Map ParseMap(string input) {
        var rows = input.Split("\n");
        return (
            from irow in Enumerable.Range(0, rows.Length)
            from icol in Enumerable.Range(0, rows[0].Length)
            let pos = new Complex(icol, irow)
            let cell = rows[irow][icol]
            select new KeyValuePair<Complex, char>(pos, cell)
        ).ToDictionary();
    }
}

Please ☆ my repo if you like it!

© 2025 Advent of Code is a registered trademark in the US Images provided by Bing image creator