01020304050607080910111213141516171819202122232425

Advent of Code

2015/19

Medicine for Rudolph

in C#

by encse

Rudolph the Red-Nosed Reindeer is sick! His nose isn't shining very brightly, and he needs medicine.

Red-Nosed Reindeer biology isn't similar to regular reindeer biology; Rudolph is going to need custom-made medicine. Unfortunately, Red-Nosed Reindeer chemistry isn't similar to regular reindeer chemistry, either.

Read the full puzzle.

using System;
using System.Collections.Generic;
using System.Linq;

namespace AdventOfCode.Y2015.Day19;

[ProblemName("Medicine for Rudolph")]
class Solution : Solver {

    public object PartOne(string input) {
        var (rules, m) = Parse(input);
        return ReplaceAll(rules, m).ToHashSet().Count;
    }

    public object PartTwo(string input) {
        var (rules, m) = Parse(input);
        Random r = new Random();
        var st = m;
        var depth = 0;
        var i = 0;
        while (st != "e") {
            i++;
            var replacements = Replacements(rules, st, false).ToArray();
            if (replacements.Length == 0) {
                st = m;
                depth = 0;
                continue;
            }
            var replacement = replacements[r.Next(replacements.Length)];
            st = Replace(st, replacement.from, replacement.to, replacement.length);
            depth++;
        }
        return depth;
    }

    IEnumerable<string> ReplaceAll((string from, string to)[] rules, string m) {
        foreach (var (from, length, to) in Replacements(rules, m, true)) {
            yield return Replace(m, from, to, length);
        }
    }

    string Replace(string m, int from, string to, int length) => m.Substring(0, from) + to + m.Substring(from + length);

    IEnumerable<(int from, int length, string to)> Replacements((string from, string to)[] rules, string m, bool forward) {
        var ich = 0;
        while (ich < m.Length) {
            foreach (var (a, b) in rules) {
                var (from, to) = forward ? (a, b) : (b, a);
                if (ich + from.Length <= m.Length) {
                    var i = 0;
                    while (i < from.Length) {
                        if (m[ich + i] != from[i]) {
                            break;
                        }
                        i++;
                    }
                    if (i == from.Length) {
                        yield return (ich, from.Length, to);
                    }
                }
            }
            ich++;
        }
    }

    ((string from, string to)[] rules, string m) Parse(string input) {
        var rules =
            (from line in input.Split('\n').TakeWhile(line => line.Contains("=>"))
             let parts = line.Split(" => ")
             select (parts[0], parts[1]))
            .ToArray();
        var m = input.Split('\n').Last();
        return (rules, 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