01020304050607080910111213141516171819202122232425

Advent of Code

2017/16

Permutation Promenade

in C#

by encse

You come upon a very unusual sight; a group of programs here appear to be dancing.

There are sixteen programs in total, named a through p. They start by standing in a line: a stands in position 0, b stands in position 1, and so on until p, which stands in position 15.

Read the full puzzle.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace AdventOfCode.Y2017.Day16;

[ProblemName("Permutation Promenade")]
class Solution : Solver {

    public object PartOne(string input) {
        return ParseStep(input)("abcdefghijklmnop");
    }

    public object PartTwo(string input) {
        var step = ParseStep(input);
        var startState = "abcdefghijklmnop";

        var mod = Mod(step, startState);

        var state = startState;
        for (int i = 0; i < 1000000000 % mod; i++) {
            state = step(state);
        }
        return state;
    }

    int Mod(Func<string, string> step, string startState) {
        var state = startState;
        for (int i = 0; ; i++) {
            state = step(state);
            if (startState == state) {
                return i + 1;
            }
        }
    }

    Func<string, string> ParseStep(string input) {
        var moves = (
            from stm in input.Split(',')
            select
                ParseMove(stm, "s([0-9]+)", m => {
                    int n = int.Parse(m[0]);
                    return (order) => {
                        return order.Skip(order.Count - n).Concat(order.Take(order.Count - n)).ToList();
                    };
                }) ??
                ParseMove(stm, "x([0-9]+)/([0-9]+)", m => {
                    int idx1 = int.Parse(m[0]);
                    int idx2 = int.Parse(m[1]);
                    return (order) => {
                        (order[idx1], order[idx2]) = (order[idx2], order[idx1]);
                        return order;
                    };
                }) ??
                ParseMove(stm, "p([a-z])/([a-z])", m => {
                    var (c1, c2) = (m[0].Single(), m[1].Single());
                    return order => {
                        var (idx1, idx2) = (order.IndexOf(c1), order.IndexOf(c2));
                        order[idx1] = c2;
                        order[idx2] = c1;
                        return order;
                    };
                }) ??
                throw new Exception("Cannot parse " + stm)
        ).ToArray();

        return startOrder => {
            var order = startOrder.ToList();
            foreach (var move in moves) {
                order = move(order);
            }
            return string.Join("", order);
        };
    }

    Func<List<char>, List<char>> ParseMove(string stm, string pattern, Func<string[], Func<List<char>, List<char>>> a) {
        var match = Regex.Match(stm , pattern);
        if (match.Success) {
            return a(match.Groups.Cast<Group>().Skip(1).Select(g => g.Value).ToArray());
        } else {
            return null;
        }
    }
}

Please ☆ my repo if you like it!

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