01020304050607080910111213141516171819202122232425

Advent of Code

2017/10

Knot Hash

in C#

by encse

You come across some programs that are trying to implement a software emulation of a hash based on knot-tying. The hash these programs are implementing isn't very strong, but you decide to help them anyway. You make a mental note to remind the Elves later not to invent their own cryptographic functions.

This hash function simulates tying a knot in a circle of string with 256 marks on it. Based on the input to be hashed, the function repeatedly selects a span of string, brings the ends together, and gives the span a half-twist to reverse the order of the marks within it. After doing this many times, the order of the marks is used to build the resulting hash.

Read the full puzzle.

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

namespace AdventOfCode.Y2017.Day10;

[ProblemName("Knot Hash")]
class Solution : Solver {

    public object PartOne(string input) {
        var chars = input.Split(',').Select(int.Parse);
        var hash = KnotHash(chars, 1);
        return hash[0] * hash[1];
    }

    public object PartTwo(string input) {
        var suffix = new [] { 17, 31, 73, 47, 23 };
        var chars = input.ToCharArray().Select(b => (int)b).Concat(suffix);

        var hash = KnotHash(chars, 64);

        return string.Join("", 
            from blockIdx in Enumerable.Range(0, 16)
            let block = hash.Skip(16 * blockIdx).Take(16)
            select block.Aggregate(0, (acc, ch) => acc ^ ch).ToString("x2"));
    }

    int[] KnotHash(IEnumerable<int> input, int rounds) {
        var output = Enumerable.Range(0, 256).ToArray();

        var current = 0;
        var skip = 0;
        for (var round = 0; round < rounds; round++) {
            foreach (var len in input) {
                for (int i = 0; i < len / 2; i++) {
                    var from = (current + i) % output.Length;
                    var to = (current + len - 1 - i) % output.Length;
                    (output[from], output[to]) = (output[to], output[from]);
                }
                current += len + skip;
                skip++;
            }
        }
        return output;
    }
}

Please ☆ my repo if you like it!

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