01020304050607080910111213141516171819202122232425

Advent of Code

2020/13

Shuttle Search

in C#

by encse

Your ferry can make it safely to a nearby port, but it won't get much further. When you call to book another ship, you discover that no ships embark from that port to your vacation island. You'll need to get from the port to the nearest airport.

Fortunately, a shuttle bus service is available to bring you from the sea port to the airport! Each bus has an ID number that also indicates how often the bus leaves for the airport.

Read the full puzzle.

using System.Linq;
using System.Numerics;

namespace AdventOfCode.Y2020.Day13;

[ProblemName("Shuttle Search")]
class Solution : Solver {

    public object PartOne(string input) {
        var problem = Parse(input);
        return problem.buses.Aggregate(
            (wait: long.MaxValue, bus: long.MaxValue),
            (min, bus) => {
                var wait = bus.period - (problem.earliestDepart % bus.period); 
                return wait < min.wait ? (wait, bus.period) : min;
            },
            min => min.wait * min.bus
        );
    }

    public object PartTwo(string input) =>
        ChineseRemainderTheorem(
            Parse(input).buses
                .Select(bus => (mod: bus.period, a: bus.period - bus.delay))
                .ToArray()
        );

    (int earliestDepart, (long period, int delay)[] buses) Parse(string input) {
        var lines = input.Split("\n");
        var earliestDepart = int.Parse(lines[0]);
        var buses = lines[1].Split(",")
            .Select((part, idx) => (part, idx))
            .Where(item => item.part != "x")
            .Select(item => (period: long.Parse(item.part), delay: item.idx))
            .ToArray();
        return (earliestDepart, buses);
    }

    // https://rosettacode.org/wiki/Chinese_remainder_theorem#C.23
    long ChineseRemainderTheorem((long mod, long a)[] items) {
        var prod = items.Aggregate(1L, (acc, item) => acc * item.mod);
        var sum = items.Select((item, i) => {
            var p = prod / item.mod;
            return item.a * ModInv(p, item.mod) * p;
        }).Sum();

        return sum % prod;
    }

    long ModInv(long a, long m) => (long)BigInteger.ModPow(a, m - 2, m);
}

Please ☆ my repo if you like it!

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