diff --git a/2015/1/illustration.jpeg b/2015/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/1/illustration.jpeg differ diff --git a/2015/1/index.html b/2015/1/index.html new file mode 100644 index 00000000..81136bea --- /dev/null +++ b/2015/1/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/1 'Not Quite Lisp'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/1

+

Not Quite Lisp

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa was hoping for a white Christmas, but his weather machine's "snow" function is powered by stars, and he's fresh out! To save Christmas, he needs you to collect fifty stars by December 25th.

+

Collect stars by helping Santa solve puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day01;
+
+[ProblemName("Not Quite Lisp")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Levels(input).Last().level;
+
+    public object PartTwo(string input) => Levels(input).First(p => p.level == -1).idx;
+
+    IEnumerable<(int idx, int level)> Levels(string input){
+        var level = 0;
+        for (var i = 0; i < input.Length; i++) {
+            level += input[i] == '(' ? 1 : -1;
+            yield return (i+1, level);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/10/illustration.jpeg b/2015/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/10/illustration.jpeg differ diff --git a/2015/10/index.html b/2015/10/index.html new file mode 100644 index 00000000..66eb1557 --- /dev/null +++ b/2015/10/index.html @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/10 'Elves Look, Elves Say'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/10

+

Elves Look, Elves Say

+

in C#

+

+

by encse

+
+ +
+ +
+

Today, the Elves are playing a game called look-and-say. They take turns making sequences by reading aloud the previous sequence and using that reading as the next sequence. For example, 211 is read as "one two, two ones", which becomes 1221 (1 2, 2 1s).

+

Look-and-say sequences are generated iteratively, using the previous value as input for the next step. For each step, take the previous value, and replace each run of digits (like 111) with the number of digits (3) followed by the digit itself (1).

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AdventOfCode.Y2015.Day10;
+
+[ProblemName("Elves Look, Elves Say")]
+class Solution : Solver {
+
+    public object PartOne(string input) => LookAndSay(input).Skip(39).First().Length;
+    public object PartTwo(string input) => LookAndSay(input).Skip(49).First().Length;
+
+    IEnumerable LookAndSay(string input) {
+        while (true) {
+            var sb = new StringBuilder();
+            var ich = 0;
+            while (ich < input.Length) {
+                if (ich < input.Length - 2 && input[ich] == input[ich + 1] && input[ich] == input[ich + 2]) {
+                    sb.Append("3");
+                    sb.Append(input[ich]);
+                    ich += 3;
+                } else if (ich < input.Length - 1 && input[ich] == input[ich + 1]) {
+                    sb.Append("2");
+                    sb.Append(input[ich]);
+                    ich += 2;
+                } else {
+                    sb.Append("1");
+                    sb.Append(input[ich]);
+                    ich += 1;
+                }
+            }
+            input = sb.ToString();
+            yield return input;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/11/illustration.jpeg b/2015/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/11/illustration.jpeg differ diff --git a/2015/11/index.html b/2015/11/index.html new file mode 100644 index 00000000..d0e6e0d1 --- /dev/null +++ b/2015/11/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/11 'Corporate Policy'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/11

+

Corporate Policy

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa's previous password expired, and he needs help choosing a new one.

+

To help him remember his new password after the old one expires, Santa has devised a method of coming up with a password based on the previous one. Corporate policy dictates that passwords must be exactly eight lowercase letters (for security reasons), so he finds his new password by incrementing his old password string repeatedly until it is valid.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AdventOfCode.Y2015.Day11;
+
+[ProblemName("Corporate Policy")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Passwords(input).First();
+    public object PartTwo(string input) => Passwords(input).Skip(1).First();
+
+    IEnumerable Passwords(string pwd) =>
+        from word in Words(pwd) 
+        let straigth = Enumerable.Range(0, word.Length - 2).Any(i => word[i] == word[i + 1] - 1 && word[i] == word[i + 2] - 2)
+        let reserved = "iol".Any(ch => word.Contains(ch))
+        let pairs = Enumerable.Range(0, word.Length - 1).Select(i => word.Substring(i, 2)).Where(sword => sword[0] == sword[1]).Distinct()
+        where straigth && !reserved && pairs.Count() > 1
+        select word;
+    
+    IEnumerable Words(string word) {
+        while (true) {
+            var sb = new StringBuilder();
+            for (var i = word.Length - 1; i >= 0; i--) {
+                var ch = word[i] + 1;
+                if (ch > 'z') {
+                    ch = 'a';
+                    sb.Insert(0, (char)ch);
+                } else {
+                    sb.Insert(0, (char)ch);
+                    sb.Insert(0, word.Substring(0, i));
+                    i = 0;
+                }
+            }
+            word = sb.ToString();
+            yield return word;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/12/illustration.jpeg b/2015/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/12/illustration.jpeg differ diff --git a/2015/12/index.html b/2015/12/index.html new file mode 100644 index 00000000..a74ab7b2 --- /dev/null +++ b/2015/12/index.html @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/12 'JSAbacusFramework.io'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/12

+

JSAbacusFramework.io

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa's Accounting-Elves need help balancing the books after a recent order. Unfortunately, their accounting software uses a peculiar storage format. That's where you come in.

+

They have a JSON document which contains a variety of things: arrays ([1,2,3]), objects ({"a":1, "b":2}), numbers, and strings. Your first job is to simply find all of the numbers throughout the document and add them together.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Text.Json;
+
+namespace AdventOfCode.Y2015.Day12;
+
+[ProblemName("JSAbacusFramework.io")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, false);
+    public object PartTwo(string input) => Solve(input, true);
+
+    int Solve(string input, bool skipRed) {
+        int Traverse(JsonElement t) {
+            return t.ValueKind switch
+            {
+                JsonValueKind.Object when skipRed && t.EnumerateObject().Any(
+                    p => p.Value.ValueKind == JsonValueKind.String && p.Value.GetString() == "red") => 0,
+                JsonValueKind.Object => t.EnumerateObject().Select(p => Traverse(p.Value)).Sum(),
+                JsonValueKind.Array => t.EnumerateArray().Select(Traverse).Sum(),
+                JsonValueKind.Number => t.GetInt32(),
+                _ => 0
+            };
+        }
+
+        return Traverse(JsonDocument.Parse(input).RootElement);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/13/illustration.jpeg b/2015/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/13/illustration.jpeg differ diff --git a/2015/13/index.html b/2015/13/index.html new file mode 100644 index 00000000..8964e6d7 --- /dev/null +++ b/2015/13/index.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/13 'Knights of the Dinner Table'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/13

+

Knights of the Dinner Table

+

in C#

+

+

by encse

+
+ +
+ +
+

In years past, the holiday feast with your family hasn't gone so well. Not everyone gets along! This year, you resolve, will be different. You're going to find the optimal seating arrangement and avoid all those awkward conversations.

+

You start by writing up a list of everyone invited and the amount their happiness would increase or decrease if they were to find themselves sitting next to each other person. You have a circular table that will be just big enough to fit everyone comfortably, and so each person will have exactly two neighbors.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day13;
+
+[ProblemName("Knights of the Dinner Table")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Happiness(input, false).Max();
+    public object PartTwo(string input) => Happiness(input, true).Max();
+
+    IEnumerable Happiness(string input, bool includeMe) {
+        var dh = new Dictionary<(string, string), int>();
+        foreach (var line in input.Split('\n')) {
+            var m = Regex.Match(line, @"(.*) would (.*) (.*) happiness units by sitting next to (.*).");
+            var a = m.Groups[1].Value;
+            var b = m.Groups[4].Value;
+            var happiness = int.Parse(m.Groups[3].Value) * (m.Groups[2].Value == "gain" ? 1 : -1);
+            if (!dh.ContainsKey((a, b))) {
+                dh[(a, b)] = 0;
+                dh[(b, a)] = 0;
+            }
+            dh[(a, b)] += happiness;
+            dh[(b, a)] += happiness;
+        }
+
+        var people = dh.Keys.Select(k => k.Item1).Distinct().ToList();
+        if (includeMe) {
+            people.Add("me");
+        }
+        return Permutations(people.ToArray()).Select(order =>
+            order.Zip(order.Skip(1).Append(order[0]), (a, b) => dh.TryGetValue((a, b), out var v) ? v : 0).Sum()
+        );
+    }
+
+    IEnumerable Permutations(T[] rgt) {
+
+        IEnumerable PermutationsRec(int i) {
+            if (i == rgt.Length) {
+                yield return rgt.ToArray();
+            }
+
+            for (var j = i; j < rgt.Length; j++) {
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+                foreach (var perm in PermutationsRec(i + 1)) {
+                    yield return perm;
+                }
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+            }
+        }
+
+        return PermutationsRec(0);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/14/illustration.jpeg b/2015/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/14/illustration.jpeg differ diff --git a/2015/14/index.html b/2015/14/index.html new file mode 100644 index 00000000..442b140d --- /dev/null +++ b/2015/14/index.html @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/14 'Reindeer Olympics'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/14

+

Reindeer Olympics

+

in C#

+

+

by encse

+
+ +
+ +
+

This year is the Reindeer Olympics! Reindeer can fly at high speeds, but must rest occasionally to recover their energy. Santa would like to know which of his reindeer is fastest, and so he has them race.

+

Reindeer can only either be flying (always at their top speed) or resting (not moving at all), and always spend whole seconds in either state.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day14;
+
+[ProblemName("Reindeer Olympics")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Race(Parse(input)).Skip(2502).First().Max();
+    public object PartTwo(string input) => Race2(Parse(input)).Skip(2502).First().Max();
+
+    IEnumerable[] Parse(string input) => input.Split('\n').Select(Reindeer).ToArray();
+
+    IEnumerable Race(IEnumerable[] reindeers) {
+        var res = new int[reindeers.Length];
+        var enumarators = reindeers.Select(r => r.GetEnumerator()).ToArray();
+        while (true) {
+            yield return (from en in enumarators
+                          let _ = en.MoveNext()
+                          select en.Current).ToArray();
+        }
+    }
+
+    IEnumerable Race2(IEnumerable[] reindeers) {
+        var points = new int[reindeers.Length];
+        foreach (var step in Race(reindeers)) {
+            var m = step.Max();
+            for (var i = 0; i < step.Length; i++) {
+                if (step[i] == m) {
+                    points[i]++;
+                }
+            }
+            yield return points;
+        }
+    }
+    
+    IEnumerable Reindeer(string line) {
+        var m = Regex.Match(line, @"(.*) can fly (.*) km/s for (.*) seconds, but then must rest for (.*) seconds.");
+        var speed = int.Parse(m.Groups[2].Value);
+        var flightTime = int.Parse(m.Groups[3].Value);
+        var restTime = int.Parse(m.Groups[4].Value);
+        var t = 0;
+        var dist = 0;
+        var flying = true;
+        while (true) {
+            if (flying) {
+                dist += speed;
+            }
+            t++;
+            if ((flying && t == flightTime) || (!flying && t == restTime)) {
+                t = 0;
+                flying = !flying;
+            }
+            yield return dist;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/15/illustration.jpeg b/2015/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/15/illustration.jpeg differ diff --git a/2015/15/index.html b/2015/15/index.html new file mode 100644 index 00000000..6fd47086 --- /dev/null +++ b/2015/15/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/15 'Science for Hungry People'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/15

+

Science for Hungry People

+

in C#

+

+

by encse

+
+ +
+ +
+

Today, you set out on the task of perfecting your milk-dunking cookie recipe. All you have to do is find the right balance of ingredients.

+

Your recipe leaves room for exactly 100 teaspoons of ingredients. You make a list of the remaining ingredients you could use to finish the recipe (your puzzle input) and their properties per teaspoon:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day15;
+
+[ProblemName("Science for Hungry People")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, null);
+    public object PartTwo(string input) => Solve(input, 500);
+
+    long Solve(string input, int? calories) {
+        var ingredients = Parse(input);
+        var propsCount = ingredients[0].Length;
+
+        var maxValue = 0L;
+        foreach (var amounts in Partition(100, ingredients.Length)) {
+            var props = new int[propsCount];
+            for (int ingredient = 0; ingredient < ingredients.Length; ingredient++) {
+                for (int prop = 0; prop < 5; prop++) {
+                    props[prop] += ingredients[ingredient][prop] * amounts[ingredient];
+                }
+            }
+            if (!calories.HasValue || calories.Value == props.Last()) {
+                var value = props.Take(propsCount - 1).Aggregate(1L, (acc, p) => acc * Math.Max(0, p));
+                maxValue = Math.Max(maxValue, value);
+            }
+        }
+        return maxValue;
+    }
+
+    int[][] Parse(string input) =>
+        (from line in input.Split('\n')
+         let m = Regex.Match(line, @".*: capacity (.*), durability (.*), flavor (.*), texture (.*), calories (.*)")
+         let nums = m.Groups.Cast().Skip(1).Select(g => int.Parse(g.Value)).ToArray()
+         select nums).ToArray();
+
+    IEnumerable Partition(int n, int k) {
+        if (k == 1) {
+            yield return new int[] { n };
+        } else {
+            for (var i = 0; i <= n; i++) {
+                foreach (var rest in Partition(n - i, k - 1)) {
+                    yield return rest.Select(x => x).Append(i).ToArray();
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/16/illustration.jpeg b/2015/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/16/illustration.jpeg differ diff --git a/2015/16/index.html b/2015/16/index.html new file mode 100644 index 00000000..8381bdf9 --- /dev/null +++ b/2015/16/index.html @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/16 'Aunt Sue'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/16

+

Aunt Sue

+

in C#

+

+

by encse

+
+ +
+ +
+

Your Aunt Sue has given you a wonderful gift, and you'd like to send her a thank you card. However, there's a small problem: she signed it "From, Aunt Sue".

+

You have 500 Aunts named "Sue".

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day16;
+
+[ProblemName("Aunt Sue")]
+class Solution : Solver {
+
+    private Dictionary target = new Dictionary {
+        ["children"] = 3,
+        ["cats"] = 7,
+        ["samoyeds"] = 2,
+        ["pomeranians"] = 3,
+        ["akitas"] = 0,
+        ["vizslas"] = 0,
+        ["goldfish"] = 5,
+        ["trees"] = 3,
+        ["cars"] = 2,
+        ["perfumes"] = 1,
+    };
+
+    public object PartOne(string input) =>
+        Parse(input).FindIndex(p => p.Keys.All(k => p[k] == target[k])) + 1;
+
+    public object PartTwo(string input) =>
+        Parse(input).FindIndex(p => p.Keys.All(k => {
+            if (k == "cats" || k == "trees") {
+                return p[k] > target[k];
+            } else if (k == "pomeranians" || k == "goldfish") {
+                return p[k] < target[k];
+            } else {
+                return p[k] == target[k];
+            }
+        })) + 1;
+
+    List> Parse(string input) => (
+            from line in input.Split('\n')
+            let parts = Regex.Matches(line, @"(\w+): (\d+)")
+            select parts.ToDictionary(
+                part => part.Groups[1].Value,
+                part => int.Parse(part.Groups[2].Value))
+         ).ToList();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/17/illustration.jpeg b/2015/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/17/illustration.jpeg differ diff --git a/2015/17/index.html b/2015/17/index.html new file mode 100644 index 00000000..dd777d66 --- /dev/null +++ b/2015/17/index.html @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/17 'No Such Thing as Too Much'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/17

+

No Such Thing as Too Much

+

in C#

+

+

by encse

+
+ +
+ +
+

The elves bought too much eggnog again - 150 liters this time. To fit it all into your refrigerator, you'll need to move it into smaller containers. You take an inventory of the capacities of the available containers.

+

For example, suppose you have containers of size 20, 15, 10, 5, and 5 liters. If you need to store 25 liters, there are four ways to do it:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day17;
+
+[ProblemName("No Such Thing as Too Much")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Fill(Parse(input)).Count();
+    public object PartTwo(string input) {
+        var combinations = Fill(Parse(input)).ToArray();
+        var shortest = combinations.Select(combination => combination.Count()).Min();
+        return combinations.Count(combination => combination.Count() == shortest);
+    }
+
+    int[] Parse(string input) => input.Split('\n').Select(int.Parse).ToArray();
+
+    IEnumerable> Fill(int[] containers) {
+        IEnumerable> FillRecursive(int i, int amount) {
+            if (i == containers.Length) {
+                yield break;
+            } else {
+                if (amount == containers[i]) {
+                    yield return ImmutableList.Create(i);
+                }
+                if (amount >= containers[i]) {
+                    foreach (var v in FillRecursive(i + 1, amount - containers[i])) {
+                        yield return v.Add(i);
+                    }
+                }
+                foreach (var v in FillRecursive(i + 1, amount)) {
+                    yield return v;
+                }
+            }
+        }
+
+        return FillRecursive(0, 150);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/18/illustration.jpeg b/2015/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/18/illustration.jpeg differ diff --git a/2015/18/index.html b/2015/18/index.html new file mode 100644 index 00000000..ada9c011 --- /dev/null +++ b/2015/18/index.html @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/18 'Like a GIF For Your Yard'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/18

+

Like a GIF For Your Yard

+

in C#

+

+

by encse

+
+ +
+ +
+

After the million lights incident, the fire code has gotten stricter: now, at most ten thousand lights are allowed. You arrange them in a 100x100 grid.

+

Never one to let you down, Santa again mails you instructions on the ideal lighting configuration. With so few lights, he says, you'll have to resort to animation.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day18;
+
+[ProblemName("Like a GIF For Your Yard")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        Enumerable.Range(0, 100).Aggregate(Parse(input), (acc, _) => Step(acc, false)).Select(row => row.Sum()).Sum();
+
+    public object PartTwo(string input) =>
+        Enumerable.Range(0, 100).Aggregate(Parse(input), (acc, _) => Step(acc, true)).Select(row => row.Sum()).Sum();
+
+    int[][] Step(int[][] input, bool stuck) {
+        
+        var res = new List();
+        var (crow, ccol) = (input.Length, input[0].Length);
+
+        if (stuck) {
+            input[0][0] = 1;
+            input[crow - 1][0] = 1;
+            input[0][ccol - 1] = 1;
+            input[crow - 1][ccol - 1] = 1;
+        }
+        for (var irow = 0; irow < crow; irow++) {
+            var row = new List();
+            for (var icol = 0; icol < ccol; icol++) {
+                if (stuck && 
+                    ((icol == 0 && irow == 0) || (icol == ccol - 1 && irow == 0) || 
+                        (icol == 0 && irow == crow - 1) || (icol == ccol - 1 && irow == crow - 1))
+                ) {
+                    row.Add(1);
+                } else {
+                    var neighbours =
+                        (from d in new(int row, int col)[] { (-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1) }
+                         let irowT = irow + d.row
+                         let icolT = icol + d.col
+                         where irowT >= 0 && irowT < crow && icolT >= 0 && icolT < ccol && input[irowT][icolT] == 1
+                         select 1).Sum();
+                    if (input[irow][icol] == 1) {
+                        row.Add(new[] { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }[neighbours]);
+                    } else {
+                        row.Add(new[] { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }[neighbours]);
+                    }
+                }
+            }
+            res.Add(row.ToArray());
+        }
+        return res.ToArray();
+    }
+
+    int[][] Parse(string input) =>(
+            from line in input.Split('\n')
+            select 
+                (from ch in line select ch == '#' ? 1 : 0).ToArray()
+        ).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/19/illustration.jpeg b/2015/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/19/illustration.jpeg differ diff --git a/2015/19/index.html b/2015/19/index.html new file mode 100644 index 00000000..404d9a4c --- /dev/null +++ b/2015/19/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/19 'Medicine for Rudolph'' in C# by encse + + + + + + + + + + + + + + +
+
+
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 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!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/2/illustration.jpeg b/2015/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/2/illustration.jpeg differ diff --git a/2015/2/index.html b/2015/2/index.html new file mode 100644 index 00000000..83b11f0f --- /dev/null +++ b/2015/2/index.html @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/2 'I Was Told There Would Be No Math'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/2

+

I Was Told There Would Be No Math

+

in C#

+

+

by encse

+
+ +
+ +
+

The elves are running low on wrapping paper, and so they need to submit an order for more. They have a list of the dimensions (length l, width w, and height h) of each present, and only want to order exactly as much as they need.

+

Fortunately, every present is a box (a perfect right rectangular prism), which makes calculating the required wrapping paper for each gift a little easier: find the surface area of the box, which is 2*l*w + 2*w*h + 2*h*l. The elves also need a little extra paper for each present: the area of the smallest side.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day02;
+
+[ProblemName("I Was Told There Would Be No Math")]
+class Solution : Solver {
+
+    public object PartOne(string input) => (
+            from nums in Parse(input) 
+            select 2 * (nums[0] * nums[1] + nums[1] * nums[2] + nums[0] * nums[2]) + nums[0] * nums[1]
+        ).Sum();
+
+    public object PartTwo(string input) => (
+            from nums in Parse(input) 
+            select nums[0] * nums[1] * nums[2] + 2 * (nums[0] + nums[1])
+        ).Sum();
+
+    IEnumerable Parse(string input) {
+        return (from line in input.Split('\n')
+                let parts = line.Split('x')
+                let nums = parts.Select(int.Parse).OrderBy(x => x).ToArray()
+                select nums);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/20/illustration.jpeg b/2015/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/20/illustration.jpeg differ diff --git a/2015/20/index.html b/2015/20/index.html new file mode 100644 index 00000000..ee7f629f --- /dev/null +++ b/2015/20/index.html @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/20 'Infinite Elves and Infinite Houses'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/20

+

Infinite Elves and Infinite Houses

+

in C#

+

+

by encse

+
+ +
+ +
+

To keep the Elves busy, Santa has them deliver some presents by hand, door-to-door. He sends them down a street with infinite houses numbered sequentially: 1, 2, 3, 4, 5, and so on.

+

Each Elf is assigned a number, too, and delivers presents to houses based on that number:

+

Read the full puzzle.

+
+
namespace AdventOfCode.Y2015.Day20;
+
+[ProblemName("Infinite Elves and Infinite Houses")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var l = int.Parse(input);
+        return PresentsByHouse(1000000, 10, l);
+    }
+
+    public object PartTwo(string input) {
+        var l = int.Parse(input);
+        return PresentsByHouse(50, 11, l);
+    }
+
+    int PresentsByHouse(int steps, int mul, int l) {
+        var presents = new int[1000000];
+        for (var i = 1; i < presents.Length; i++) {
+            var j = i;
+            var step = 0;
+            while (j < presents.Length && step < steps) {
+                presents[j] += mul * i;
+                j += i;
+                step++;
+            }
+        }
+
+        for (var i = 0; i < presents.Length; i++) {
+            if (presents[i] >= l) {
+                return i;
+            }
+        }
+        return -1;
+
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/21/illustration.jpeg b/2015/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/21/illustration.jpeg differ diff --git a/2015/21/index.html b/2015/21/index.html new file mode 100644 index 00000000..1af8129e --- /dev/null +++ b/2015/21/index.html @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/21 'RPG Simulator 20XX'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/21

+

RPG Simulator 20XX

+

in C#

+

+

by encse

+
+ +
+ +
+

Little Henry Case got a new video game for Christmas. It's an RPG, and he's stuck on a boss. He needs to know what equipment to buy at the shop. He hands you the controller.

+

In this game, the player (you) and the enemy (the boss) take turns attacking. The player always goes first. Each attack reduces the opponent's hit points by at least 1. The first character at or below 0 hit points loses.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day21;
+
+[ProblemName("RPG Simulator 20XX")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var boss = Parse(input);
+        var minGold = int.MaxValue;
+        foreach (var c in Buy()) {
+            if (DefeatsBoss((c.damage, c.armor, 100), boss)) {
+                minGold = Math.Min(c.gold, minGold);
+            }
+        }
+        return minGold;
+    }
+
+    public object PartTwo(string input) {
+        var boss = Parse(input);
+        var maxGold = 0;
+        foreach (var c in Buy()) {
+            if (!DefeatsBoss((c.damage, c.armor, 100), boss)) {
+                maxGold = Math.Max(c.gold, maxGold);
+            }
+        }
+        return maxGold;
+    }
+
+    (int damage, int armor, int hp) Parse(string input) {
+        var lines = input.Split("\n");
+        var hp = int.Parse(lines[0].Split(": ")[1]);
+        var damage = int.Parse(lines[1].Split(": ")[1]);
+        var armor = int.Parse(lines[2].Split(": ")[1]);
+        return (damage, armor, hp);
+    }
+
+    bool DefeatsBoss((int damage, int armor, int hp) player, (int damage, int armor, int hp) boss) {
+        while (true) {
+            boss.hp -= Math.Max(player.damage - boss.armor, 1);
+            if (boss.hp <= 0) {
+                return true;
+            }
+
+            player.hp -= Math.Max(boss.damage - player.armor, 1);
+            if (player.hp <= 0) {
+                return false;
+            }
+        }
+    }
+
+    IEnumerable<(int gold, int damage, int armor)> Buy() {
+        return
+            from weapon in Buy(1, 1, new[] { (8, 4, 0), (10, 5, 0), (25, 6, 0), (40, 7, 0), (74, 8, 0) })
+            from armor in Buy(0, 1, new[] { (13, 0, 1), (31, 0, 2), (53, 0, 3), (75, 0, 4), (102, 0, 5) })
+            from ring in Buy(1, 2, new[] { (25, 1, 0), (50, 2, 0), (100, 3, 0), (20, 0, 1), (40, 0, 2), (80, 0, 3) })
+            select Sum(weapon, armor, ring);
+    }
+
+    IEnumerable<(int gold, int damage, int armor)> Buy(int min, int max, (int gold, int damage, int armor)[] items) {
+        if (min == 0) {
+            yield return (0, 0, 0);
+        }
+
+        foreach (var item in items) {
+            yield return item;
+        }
+
+        if (max == 2) {
+            for (int i = 0; i < items.Length; i++) {
+                for (int j = i + 1; j < items.Length; j++) {
+                    yield return Sum(items[i], items[j]);
+                }
+            }
+        }
+    }
+
+    (int gold, int damage, int armor) Sum(params (int gold, int damage, int armor)[] items) {
+        return (items.Select(item => item.gold).Sum(), items.Select(item => item.damage).Sum(), items.Select(item => item.armor).Sum());
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/22/illustration.jpeg b/2015/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/22/illustration.jpeg differ diff --git a/2015/22/index.html b/2015/22/index.html new file mode 100644 index 00000000..c64ea6c6 --- /dev/null +++ b/2015/22/index.html @@ -0,0 +1,467 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/22 'Wizard Simulator 20XX'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/22

+

Wizard Simulator 20XX

+

in C#

+

+

by encse

+
+ +
+ +
+

Little Henry Case decides that defeating bosses with swords and stuff is boring. Now he's playing the game with a wizard. Of course, he gets stuck on another boss and needs your help again.

+

In this version, combat still proceeds with the player and the boss taking alternating turns. The player still goes first. Now, however, you don't get any equipment; instead, you must choose one of your spells to cast. The first character at or below 0 hit points loses.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2015.Day22;
+
+[ProblemName("Wizard Simulator 20XX")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var state0 = Parse(input);
+        return BinarySearch(mana => TrySolve(state0.WithManaLimit(mana), false));
+    }
+
+    public object PartTwo(string input) {
+        var state0 = Parse(input);
+        return BinarySearch(mana => TrySolve(state0.WithManaLimit(mana), true));
+    }
+
+    int BinarySearch(Func f) {
+        var hi = 1;
+        while (!f(hi)) {
+            hi *= 2;
+        }
+        var lo = hi / 2;
+        var first = false;
+        while (hi - lo > 1) {
+            var m = (hi + lo) / 2;
+            if (!first && f(m)) {
+                hi = m;
+            } else {
+                lo = m;
+            }
+            first = false;
+        }
+        return hi;
+    }
+
+    bool TrySolve(State state, bool hard) {
+        if (hard) {
+            state = state.Damage(1);
+        }
+        state = state.ApplyEffects();
+        foreach (var stateT in state.PlayerSteps()) {
+            state = stateT.ApplyEffects();
+            state = state.BossStep();
+            if (state.bossHp <= 0 || state.playerHp > 0 && TrySolve(state, hard)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    State Parse(string input){
+        var lines = input.Split("\n");
+        return new State {
+            playerHp = 50,
+            playerMana = 500,
+            bossHp = int.Parse(lines[0].Split(": ")[1]),
+            bossDamage = int.Parse(lines[1].Split(": ")[1])
+        };
+    }
+}
+
+
+class State {
+    const int missileMana = 53;
+    const int drainMana = 73;
+    const int shieldMana = 113;
+    const int poisonMana = 173;
+    const int rechargeMana = 229;
+
+    public int shield;
+    public int poison;
+    public int recharge;
+    public int playerHp;
+    public int bossHp;
+    public int playerMana;
+    public int bossDamage;
+    public int usedMana;
+    public int playerArmor;
+    public int manaLimit;
+
+    public State Dup() {
+        return this.MemberwiseClone() as State;
+    }
+
+    public State WithManaLimit(int manaLimit) {
+        var newState = Dup();
+        newState.manaLimit = manaLimit;
+        return newState;
+    }
+
+    public State ApplyEffects() {
+        if (playerHp <= 0 || bossHp <= 0) {
+            return this;
+        }
+
+        var newState = Dup();
+        if (newState.poison > 0) {
+            newState.bossHp -= 3;
+            newState.poison--;
+        }
+
+        if (newState.recharge > 0) {
+            newState.playerMana += 101;
+            newState.recharge--;
+        }
+
+        if (newState.shield > 0) {
+            newState.shield--;
+            newState.playerArmor = 7;
+        } else {
+            newState.playerArmor = 0;
+        }
+        return newState;
+    }
+
+    public State Damage(int damage) {
+        if (playerHp <= 0 || bossHp <= 0) {
+            return this;
+        }
+
+        var step = Dup();
+        step.playerHp -= damage;
+        return step;
+    }
+
+    public State BossStep(){
+        if (playerHp <= 0 || bossHp <= 0) {
+            return this;
+        }
+
+        var step = Dup();
+        step.playerHp -= Math.Max(1, step.bossDamage - step.playerArmor);
+        return step;
+    }
+
+    public IEnumerable PlayerSteps() {
+
+        if (playerHp <= 0 || bossHp <= 0) {
+            yield return this;
+            yield break;
+        }
+   
+        if (playerMana >= missileMana && missileMana + usedMana <= manaLimit) {
+            var c = Dup();
+            c.playerMana -= missileMana;
+            c.usedMana += missileMana;
+            c.bossHp -= 4;
+            yield return c;
+        }
+
+        if (playerMana >= drainMana && drainMana + usedMana <= manaLimit) {
+            var c = Dup();
+            c.playerMana -= drainMana;
+            c.usedMana += drainMana;
+            c.bossHp -= 2;
+            c.playerHp += 2;
+            yield return c;
+        }
+
+        if (playerMana >= shieldMana && shield == 0 && shieldMana + usedMana <= manaLimit) {
+            var c = Dup();
+            c.playerMana -= shieldMana;
+            c.usedMana += shieldMana;
+            c.shield = 6;
+            yield return c;
+        }
+
+        if (playerMana >= poisonMana && poison == 0 && poisonMana + usedMana <= manaLimit) {
+            var c = Dup();
+            c.playerMana -= poisonMana;
+            c.usedMana += poisonMana;
+            c.poison = 6;
+            yield return c;
+        }
+
+        if (playerMana >= rechargeMana && recharge == 0 && rechargeMana + usedMana <= manaLimit) {
+            var c = Dup();
+            c.playerMana -= rechargeMana;
+            c.usedMana += rechargeMana;
+            c.recharge = 5;
+            yield return c;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/23/illustration.jpeg b/2015/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/23/illustration.jpeg differ diff --git a/2015/23/index.html b/2015/23/index.html new file mode 100644 index 00000000..74fccd51 --- /dev/null +++ b/2015/23/index.html @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/23 'Opening the Turing Lock'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/23

+

Opening the Turing Lock

+

in C#

+

+

by encse

+
+ +
+ +
+

Little Jane Marie just got her very first computer for Christmas from some unknown benefactor. It comes with instructions and an example program, but the computer itself seems to be malfunctioning. She's curious what the program does, and would like you to help her run it.

+

The manual explains that the computer supports two registers and six instructions (truly, it goes on to remind the reader, a state-of-the-art technology). The registers are named a and b, can hold any non-negative integer, and begin with a value of 0. The instructions are as follows:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2015.Day23;
+
+[ProblemName("Opening the Turing Lock")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 0);
+    public object PartTwo(string input) => Solve(input, 1);
+
+    long Solve(string input, long a) {
+        var regs = new Dictionary();
+        var ip = 0L;
+        long getReg(string reg) {
+            return long.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        void setReg(string reg, long value) {
+            regs[reg] = value;
+        }
+
+        setReg("a", a);
+        var prog = input.Split('\n');
+        while (ip >= 0 && ip < prog.Length) {
+            var line = prog[ip];
+            var parts = line.Replace(",", "").Split(" ");
+            switch (parts[0]) {
+                case "hlf":
+                    setReg(parts[1], getReg(parts[1]) / 2);
+                    ip++;
+                    break;
+                case "tpl":
+                    setReg(parts[1], getReg(parts[1]) * 3);
+                    ip++;
+                    break;
+                case "inc":
+                    setReg(parts[1], getReg(parts[1]) + 1);
+                    ip++;
+                    break;
+                case "jmp":
+                    ip += getReg(parts[1]);
+                    break;
+                case "jie":
+                    ip += getReg(parts[1]) % 2 == 0 ? getReg(parts[2]) : 1;
+                    break;
+                case "jio":
+                    ip += getReg(parts[1]) == 1 ? getReg(parts[2]) : 1;
+                    break;
+                default: throw new Exception("Cannot parse " + line);
+            }
+        }
+        return getReg("b");
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/24/illustration.jpeg b/2015/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/24/illustration.jpeg differ diff --git a/2015/24/index.html b/2015/24/index.html new file mode 100644 index 00000000..ac507366 --- /dev/null +++ b/2015/24/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/24 'It Hangs in the Balance'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/24

+

It Hangs in the Balance

+

in C#

+

+

by encse

+
+ +
+ +
+

It's Christmas Eve, and Santa is loading up the sleigh for this year's deliveries. However, there's one small problem: he can't get the sleigh to balance. If it isn't balanced, he can't defy physics, and nobody gets presents this year.

+

No pressure.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Immutable;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day24;
+
+[ProblemName("It Hangs in the Balance")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(Parse(input), 3);
+
+    public object PartTwo(string input) => Solve(Parse(input), 4);
+
+    int[] Parse(string input) =>
+        input.Split("\n").Select(int.Parse).ToArray();
+
+    long Solve(int[] nums, int groups) {
+        var mul = (ImmutableList l) => l.Aggregate(1L, (m, x) => m*x);
+
+        for(var i =0;i> Pick(int[] nums, int count, int i, int sum) {
+        if (sum == 0) {
+            yield return ImmutableList.Create();
+            yield break;
+        }
+
+        if (count < 0 || sum < 0 || i >= nums.Length) {
+            yield break;
+        }
+        
+        if (nums[i] <= sum) {
+            foreach (var x in Pick(nums, count-1, i + 1, sum - nums[i])) {
+                yield return x.Add(nums[i]);
+            }
+        }
+
+        foreach (var x in Pick(nums, count, i + 1, sum)) {
+            yield return x;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/25/illustration.jpeg b/2015/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/25/illustration.jpeg differ diff --git a/2015/25/index.html b/2015/25/index.html new file mode 100644 index 00000000..da772e5a --- /dev/null +++ b/2015/25/index.html @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/25 'Let It Snow'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/25

+

Let It Snow

+

in C#

+

+

by encse

+
+ +
+ +
+

Merry Christmas! Santa is booting up his weather machine; looks like you might get a white Christmas after all.

+

The weather machine beeps! On the console of the machine is a copy protection message asking you to enter a code from the instruction manual. Apparently, it refuses to run unless you give it that code. No problem; you'll just look up the code in the--

+

Read the full puzzle.

+
+
using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day25;
+
+[ProblemName("Let It Snow")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var m = 20151125L;
+        var (irow, icol) = (1, 1);
+        var (irowDst, icolDst) = Parse(input);
+        while (irow != irowDst || icol != icolDst) {
+            irow--;
+            icol++;
+            if (irow == 0) {
+                irow = icol;
+                icol = 1;
+            }
+            m = (m * 252533L) % 33554393L;
+        }
+        return m;
+    }
+
+    (int irowDst, int icolDst) Parse(string  input){
+        var m = Regex.Match(input, @"To continue, please consult the code grid in the manual.  Enter the code at row (\d+), column (\d+).");
+        return (int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/3/illustration.jpeg b/2015/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/3/illustration.jpeg differ diff --git a/2015/3/index.html b/2015/3/index.html new file mode 100644 index 00000000..cbb9050f --- /dev/null +++ b/2015/3/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/3 'Perfectly Spherical Houses in a Vacuum'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/3

+

Perfectly Spherical Houses in a Vacuum

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa is delivering presents to an infinite two-dimensional grid of houses.

+

He begins by delivering a present to the house at his starting location, and then an elf at the North Pole calls him via radio and tells him where to move next. Moves are always exactly one house to the north (^), south (v), east (>), or west (<). After each move, he delivers another present to the house at his new location.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2015.Day03;
+
+[ProblemName("Perfectly Spherical Houses in a Vacuum")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Run(input, 1);
+
+    public object PartTwo(string input) => Run(input, 2);
+
+    int Run(string input, int actors) {
+
+        var seen = new HashSet<(int, int)>();
+        var pos = new(int irow, int icol)[actors];
+        for (var i = 0; i < actors; i++) {
+            pos[i] = (0, 0);
+        }
+        seen.Add((0,0));
+        
+        var actor = 0;
+        foreach (var ch in input) {
+            switch (ch) {
+                case 'v': pos[actor].irow++; break;
+                case '<': pos[actor].icol--; break;
+                case '>': pos[actor].icol++; break;
+                case '^': pos[actor].irow--; break;
+            }
+            seen.Add(pos[actor]);
+            actor = (actor + 1) % actors;
+        }
+        return seen.Count();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/4/illustration.jpeg b/2015/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/4/illustration.jpeg differ diff --git a/2015/4/index.html b/2015/4/index.html new file mode 100644 index 00000000..881a60fb --- /dev/null +++ b/2015/4/index.html @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/4 'The Ideal Stocking Stuffer'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/4

+

The Ideal Stocking Stuffer

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa needs help mining some AdventCoins (very similar to bitcoins) to use as gifts for all the economically forward-thinking little girls and boys.

+

To do this, he needs to find MD5 hashes which, in hexadecimal, start with at least five zeroes. The input to the MD5 hash is some secret key (your puzzle input, given below) followed by a number in decimal. To mine AdventCoins, you must find Santa the lowest positive number (no leading zeroes: 1, 2, 3, ...) that produces such a hash.

+

Read the full puzzle.

+
+
using System.Collections.Concurrent;
+using System.Linq;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Y2015.Day04;
+
+[ProblemName("The Ideal Stocking Stuffer")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ParallelFind(input, "00000");
+    public object PartTwo(string input) => ParallelFind(input, "000000");
+
+    int ParallelFind(string input, string prefix) {
+        var q = new ConcurrentQueue();
+
+        Parallel.ForEach(
+            Numbers(), 
+            () => MD5.Create(), 
+            (i, state, md5) => {
+                var hashBytes = md5.ComputeHash(Encoding.ASCII.GetBytes(input + i));
+                var hash = string.Join("", hashBytes.Select(b => b.ToString("x2")));
+
+                if (hash.StartsWith(prefix)) {
+                    q.Enqueue(i);
+                    state.Stop();
+                }
+                return md5;
+             }, 
+             (_) => {}
+        );
+        return q.Min();
+    }
+
+    IEnumerable Numbers() {
+        for (int i=0; ;i++) {
+            yield return i;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/5/illustration.jpeg b/2015/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/5/illustration.jpeg differ diff --git a/2015/5/index.html b/2015/5/index.html new file mode 100644 index 00000000..61248537 --- /dev/null +++ b/2015/5/index.html @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/5 'Doesn't He Have Intern-Elves For This?'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/5

+

Doesn't He Have Intern-Elves For This?

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa needs help figuring out which strings in his text file are naughty or nice.

+

A nice string is one with all of the following properties:

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2015.Day05;
+
+[ProblemName("Doesn't He Have Intern-Elves For This?")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        input.Split('\n').Count(line => {
+            var threeVowels = line.Count(ch => "aeiou".Contains(ch)) >= 3;
+            var duplicate = Enumerable.Range(0, line.Length - 1).Any(i => line[i] == line[i + 1]);
+            var reserved = "ab,cd,pq,xy".Split(',').Any(line.Contains);
+            return threeVowels && duplicate && !reserved;
+        });
+
+    public object PartTwo(string input) =>
+        input.Split('\n').Count(line => {
+            var appearsTwice = Enumerable.Range(0, line.Length - 1).Any(i => line.IndexOf(line.Substring(i, 2), i+2) >= 0); 
+            var repeats = Enumerable.Range(0, line.Length - 2).Any(i => line[i] == line[i + 2]);
+            return appearsTwice && repeats;
+        });
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/6/illustration.jpeg b/2015/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/6/illustration.jpeg differ diff --git a/2015/6/index.html b/2015/6/index.html new file mode 100644 index 00000000..85f6ad27 --- /dev/null +++ b/2015/6/index.html @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/6 'Probably a Fire Hazard'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/6

+

Probably a Fire Hazard

+

in C#

+

+

by encse

+
+ +
+ +
+

Because your neighbors keep defeating you in the holiday house decorating contest year after year, you've decided to deploy one million lights in a 1000x1000 grid.

+

Furthermore, because you've been especially nice this year, Santa has mailed you instructions on how to display the ideal lighting configuration.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day06;
+
+[ProblemName("Probably a Fire Hazard")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Run(input, _ => 1, _ => 0, v => 1 - v);
+    public object PartTwo(string input) => Run(input, v => v + 1, v => v > 0 ? v - 1 : 0, v => v + 2);
+
+    int Run(string input, Func turnOn, Func turnOff, Func toggle) {
+        int[] apply(int[] grid, string line, string pattern, Func dg) {
+            var match = Regex.Match(line, pattern);
+            if (match.Success) {
+                var rect = match.Groups.Cast().Skip(1).Select(g => int.Parse(g.Value)).ToArray();
+                for (int irow = rect[0]; irow <= rect[2]; irow++) {
+                    for (int icol = rect[1]; icol <= rect[3]; icol++) {
+                        grid[irow * 1000 + icol] = dg(grid[irow * 1000 + icol]);
+                    }
+                }
+                return grid;
+            } else {
+                return null;
+            }
+        }
+        return input.Split('\n')
+            .Aggregate(new int[1000 * 1000], (grid, line) =>
+                apply(grid, line, @"turn on (\d+),(\d+) through (\d+),(\d+)", turnOn) ??
+                apply(grid, line, @"turn off (\d+),(\d+) through (\d+),(\d+)", turnOff) ??
+                apply(grid, line, @"toggle (\d+),(\d+) through (\d+),(\d+)", toggle) ??
+                throw new Exception(line))
+            .Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/7/illustration.jpeg b/2015/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/7/illustration.jpeg differ diff --git a/2015/7/index.html b/2015/7/index.html new file mode 100644 index 00000000..5ddb1c2f --- /dev/null +++ b/2015/7/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/7 'Some Assembly Required'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/7

+

Some Assembly Required

+

in C#

+

+

by encse

+
+ +
+ +
+

This year, Santa brought little Bobby Tables a set of wires and bitwise logic gates! Unfortunately, little Bobby is a little under the recommended age range, and he needs help assembling the circuit.

+

Each wire has an identifier (some lowercase letters) and can carry a 16-bit signal (a number from 0 to 65535). A signal is provided to each wire by a gate, another wire, or some specific value. Each wire can only get a signal from one source, but can provide its signal to multiple destinations. A gate provides no signal until all of its inputs have a signal.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day07;
+
+[ProblemName("Some Assembly Required")]
+class Solution : Solver {
+
+    class State : Dictionary { }
+    class Calc : Dictionary> { }
+
+
+    public object PartOne(string input) => Parse(input)["a"](new State());
+
+    public object PartTwo(string input) {
+        var calc = Parse(input);
+        return calc["a"](new State() { ["b"] = calc["a"](new State()) });
+    }
+
+    Calc Parse(string input) =>
+        input.Split('\n').Aggregate(new Calc(), (calc, line) =>
+            Gate(calc, line, @"(\w+) AND (\w+) -> (\w+)", pin => pin[0] & pin[1]) ??
+            Gate(calc, line, @"(\w+) OR (\w+) -> (\w+)", pin => pin[0] | pin[1]) ??
+            Gate(calc, line, @"(\w+) RSHIFT (\w+) -> (\w+)", pin => pin[0] >> pin[1]) ??
+            Gate(calc, line, @"(\w+) LSHIFT (\w+) -> (\w+)", pin => pin[0] << pin[1]) ??
+            Gate(calc, line, @"NOT (\w+) -> (\w+)", pin => ~pin[0]) ??
+            Gate(calc, line, @"(\w+) -> (\w+)", pin => pin[0]) ??
+            throw new Exception(line)
+        );
+
+    Calc Gate(Calc calc, string line, string pattern, Func op) {
+        var match = Regex.Match(line, pattern);
+        if (!match.Success) {
+            return null;
+        }
+        var parts = match.Groups.Cast().Skip(1).Select(g => g.Value).ToArray();
+        var pinOut = parts.Last();
+        var pins = parts.Take(parts.Length - 1).ToArray();
+        calc[pinOut] = (state) => {
+            if (!state.ContainsKey(pinOut)) {
+                var args = pins.Select(pin => int.TryParse(pin, out var i) ? i : calc[pin](state)).ToArray();
+                state[pinOut] = op(args);
+            }
+            return state[pinOut];
+        };
+        return calc;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/8/illustration.jpeg b/2015/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/8/illustration.jpeg differ diff --git a/2015/8/index.html b/2015/8/index.html new file mode 100644 index 00000000..cc77fbea --- /dev/null +++ b/2015/8/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/8 'Matchsticks'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/8

+

Matchsticks

+

in C#

+

+

by encse

+
+ +
+ +
+

Space on the sleigh is limited this year, and so Santa will be bringing his list as a digital copy. He needs to know how much space it will take up when stored.

+

It is common in many programming languages to provide a way to escape special characters in strings. For example, C, JavaScript, Perl, Python, and even PHP handle special characters in very similar ways.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day08;
+
+[ProblemName("Matchsticks")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        (from line in input.Split('\n')
+         let u = Regex.Unescape(line.Substring(1, line.Length - 2))
+         select line.Length - u.Length).Sum();
+
+
+    public object PartTwo(string input) =>
+        (from line in input.Split('\n')
+        let u = "\"" + line.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\""
+        select u.Length - line.Length).Sum();
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2015/9/illustration.jpeg b/2015/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2015/9/illustration.jpeg differ diff --git a/2015/9/index.html b/2015/9/index.html new file mode 100644 index 00000000..9ed7962d --- /dev/null +++ b/2015/9/index.html @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2015/9 'All in a Single Night'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2015/9

+

All in a Single Night

+

in C#

+

+

by encse

+
+ +
+ +
+

Every year, Santa manages to deliver all of his presents in a single night.

+

This year, however, he has some new locations to visit; his elves have provided him the distances between every pair of locations. He can start and end at any two (different) locations he wants, but he must visit each location exactly once. What is the shortest distance he can travel to achieve this?

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2015.Day09;
+
+[ProblemName("All in a Single Night")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Routes(input).Min();
+    public object PartTwo(string input) => Routes(input).Max();
+
+    IEnumerable Routes(string input) {
+        var distances = input.Split('\n').SelectMany(line => {
+            var m = Regex.Match(line, @"(.*) to (.*) = (.*)");
+            var (a, b) = (m.Groups[1].Value, m.Groups[2].Value);
+            var d = int.Parse(m.Groups[3].Value);
+            return new[] {
+                (k: (a, b), d),
+                (k: (b, a), d)
+            };
+        }).ToDictionary(p => p.k, p => p.d);
+
+        var cities = distances.Keys.Select(k => k.Item1).Distinct().ToArray();
+        return Permutations(cities).Select(route =>
+            route.Zip(route.Skip(1), (a, b) => distances[(a, b)]).Sum()
+        );
+    }
+
+    IEnumerable Permutations(T[] rgt) {
+        IEnumerable PermutationsRec(int i) {
+            if (i == rgt.Length) {
+                yield return rgt.ToArray();
+            }
+
+            for (var j = i; j < rgt.Length; j++) {
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+                foreach (var perm in PermutationsRec(i + 1)) {
+                    yield return perm;
+                }
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+            }
+        }
+
+        return PermutationsRec(0);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/1/illustration.jpeg b/2016/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/1/illustration.jpeg differ diff --git a/2016/1/index.html b/2016/1/index.html new file mode 100644 index 00000000..cbea6553 --- /dev/null +++ b/2016/1/index.html @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/1 'No Time for a Taxicab'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/1

+

No Time for a Taxicab

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa's sleigh uses a very high-precision clock to guide its movements, and the clock's oscillator is regulated by stars. Unfortunately, the stars have been stolen... by the Easter Bunny. To save Christmas, Santa needs you to retrieve all fifty stars by December 25th.

+

Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day01;
+
+[ProblemName("No Time for a Taxicab")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var (irow, icol) = Travel(input).Last();
+        return irow + icol;
+    }
+
+    public object PartTwo(string input) {
+        var seen = new HashSet<(int, int)>();
+        foreach (var pos in Travel(input)) {
+            if (seen.Contains(pos)) {
+                return (pos.icol + pos.irow);
+            }
+            seen.Add(pos);
+        }
+        throw new Exception();
+    }
+
+    IEnumerable<(int irow, int icol)> Travel(string input) {
+        var (irow, icol) = (0, 0);
+        var (drow, dcol) = (-1, 0);
+        yield return (irow, icol);
+
+        foreach (var stm in Regex.Split(input, ", ")) {
+            var d = int.Parse(stm.Substring(1));
+
+            (drow, dcol) = stm[0] switch {
+                'R' => (dcol, -drow),
+                'L' => (-dcol, drow),
+                _ => throw new ArgumentException()
+            };
+           
+            for (int i = 0; i < d; i++) {
+                (irow, icol) = (irow + drow, icol + dcol);
+                yield return (irow, icol);
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/10/illustration.jpeg b/2016/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/10/illustration.jpeg differ diff --git a/2016/10/index.html b/2016/10/index.html new file mode 100644 index 00000000..40f4d165 --- /dev/null +++ b/2016/10/index.html @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/10 'Balance Bots'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/10

+

Balance Bots

+

in C#

+

+

by encse

+
+ +
+ +
+

You come upon a factory in which many robots are zooming around handing small microchips to each other.

+

Upon closer examination, you notice that each bot only proceeds when it has two microchips, and once it does, it gives each one to a different bot or puts it in a marked "output" bin. Sometimes, bots take microchips from "input" bins, too.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day10;
+
+[ProblemName("Balance Bots")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        Execute(Parse(input)).Single(v => v.min == 17 && v.max == 61).id.Split(' ')[1];
+
+    public object PartTwo(string input) {
+        var m = Execute(Parse(input)).Last().machine;
+        return m["output 0"].values.Single() * m["output 1"].values.Single() * m["output 2"].values.Single();
+    }
+
+    IEnumerable<(Dictionary machine, string id, int min, int max)> Execute(Dictionary machine) {
+        var any = true;
+        while (any) {
+            any = false;
+            foreach (var node in machine.Values) {
+                if (node.values.Count == 2 && node.outHigh != null) {
+                    any = true;
+                    var (min, max) = (node.values.Min(), node.values.Max());
+                    machine[node.outLow].values.Add(min);
+                    machine[node.outHigh].values.Add(max);
+                    node.values.Clear();
+                    yield return (machine, node.id, min, max);
+                }
+            }
+        }
+    }
+
+    Dictionary Parse(string input) {
+        var res = new Dictionary();
+        void ensureNodes(params string[] ids) {
+            foreach (var id in ids) {
+                if (!res.ContainsKey(id)) {
+                    res[id] = new Node { id = id };
+                }
+            }
+        }
+        foreach (var line in input.Split('\n')) {
+            if (Match(line, @"(.+) gives low to (.+) and high to (.+)", out var m)) {
+                ensureNodes(m);
+                res[m[0]].outLow = m[1];
+                res[m[0]].outHigh = m[2];
+            } else if (Match(line, @"value (\d+) goes to (.+)", out m)) {
+                ensureNodes(m[1]);
+                res[m[1]].values.Add(int.Parse(m[0]));
+            } else {
+                throw new NotImplementedException();
+            }
+        }
+        return res;
+    }
+
+    bool Match(string stm, string pattern, out string[] m) {
+        var match = Regex.Match(stm, pattern);
+        m = null;
+        if (match.Success) {
+            m = match.Groups.Cast().Skip(1).Select(g => g.Value).ToArray();
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
+
+class Node {
+    public string id;
+    public List values = new List();
+    public string outLow;
+    public string outHigh;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/11/illustration.jpeg b/2016/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/11/illustration.jpeg differ diff --git a/2016/11/index.html b/2016/11/index.html new file mode 100644 index 00000000..b3190b20 --- /dev/null +++ b/2016/11/index.html @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/11 'Radioisotope Thermoelectric Generators'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/11

+

Radioisotope Thermoelectric Generators

+

in C#

+

+

by encse

+
+ +
+ +
+

You come upon a column of four floors that have been entirely sealed off from the rest of the building except for a small dedicated lobby. There are some radiation warnings and a big sign which reads "Radioisotope Testing Facility".

+

According to the project status board, this facility is currently being used to experiment with Radioisotope Thermoelectric Generators (RTGs, or simply "generators") that are designed to be paired with specially-constructed microchips. Basically, an RTG is a highly radioactive rock that generates electricity through heat.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day11;
+
+enum Element {
+    Thulium    = 0b1,
+    Plutonium  = 0b10,
+    Strontium  = 0b100,
+    Promethium = 0b1000,
+    Ruthenium  = 0b10000,
+    Elerium    = 0b100000,
+    Dilithium  = 0b1000000
+}
+
+[ProblemName("Radioisotope Thermoelectric Generators")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(Parse(input));
+    public object PartTwo(string input) => Solve(Parse(input)
+        .AddGenerator(0, Element.Elerium).AddChip(0, Element.Elerium)
+        .AddGenerator(0, Element.Dilithium).AddChip(0, Element.Dilithium)
+        );
+
+    int Solve(ulong state){
+        var steps = 0;
+        var seen = new HashSet();
+        var q = new Queue<(int steps, ulong state)>();
+        q.Enqueue((0, state));
+        while (q.Any()) {
+            (steps, state) = q.Dequeue();
+
+            if (state.Final()) {
+                return steps;
+            }
+
+            foreach(var nextState in state.NextStates()){
+                if(!seen.Contains(nextState)){
+                    q.Enqueue((steps + 1, nextState));
+                    seen.Add(nextState);
+                }
+            }
+        }
+        return 0;
+    }
+    ulong Parse(string input) {
+
+        var nextMask = 1;
+        var elementToMask = new Dictionary();
+        int mask(string element) {
+            if (!elementToMask.ContainsKey(element)) {
+                if (elementToMask.Count() == 5) {
+                    throw new NotImplementedException();
+                }
+                elementToMask[element] = nextMask;
+                nextMask <<= 1;
+            }
+            return elementToMask[element];
+        }
+
+        ulong state = 0;
+        var floor = 0;
+        foreach(var line in input.Split('\n')){
+            var chips = (from m in Regex.Matches(line, @"(\w+)-compatible")
+                         let element = m.Groups[1].Value
+                         select mask(element)).Sum();
+
+            var generators = (from m in Regex.Matches(line, @"(\w+) generator")
+                         let element = m.Groups[1].Value
+                         select mask(element)).Sum();
+            state = state.SetFloor((ulong)floor, (ulong)chips, (ulong)generators);
+            floor++;
+        }
+        return state;
+    }
+}
+
+static class StateExtensions {
+    const int elementCount = 7;
+    const int elevatorShift = 8 * elementCount;
+    const int generatorShift = 0;
+
+    static int[] floorShift = new int[] { 0, 2 * elementCount, 4 * elementCount, 6 * elementCount };
+   
+    const ulong elevatorMask = 0b00111111111111111111111111111111111111111111111111111111;
+    const ulong chipMask = 0b00000001111111;
+    const ulong generatorMask = 0b11111110000000;
+
+    static ulong[] floorMask = new ulong[]{
+        0b1111111111111111111111111111111111111111111100000000000000,
+        0b1111111111111111111111111111110000000000000011111111111111,
+        0b1111111111111111000000000000001111111111111111111111111111,
+        0b1100000000000000111111111111111111111111111111111111111111
+    };
+    
+    public static ulong SetFloor(this ulong state, ulong floor, ulong chips, ulong generators) =>
+         (state & floorMask[floor]) | 
+         (((chips << elementCount) | (generators << generatorShift)) << floorShift[floor]);
+
+    public static ulong GetElevator(this ulong state) => 
+        (ulong)(state >> elevatorShift);
+
+    public static ulong SetElevator(this ulong state, ulong elevator) => 
+        (state & elevatorMask) | ((ulong)elevator << elevatorShift);
+
+    public static ulong GetChips(this ulong state, ulong floor) =>
+        (ulong)(((state & ~floorMask[floor]) >> floorShift[floor]) & ~chipMask) >> elementCount;
+    
+    public static ulong GetGenerators(this ulong state, ulong floor) =>
+        (ulong)(((state & ~floorMask[floor]) >> floorShift[floor]) & ~generatorMask) >> generatorShift;
+
+    public static ulong AddChip(this ulong state, ulong floor, Element chip) =>
+        state | (((ulong)chip << elementCount) << floorShift[floor]);
+
+    public static ulong AddGenerator(this ulong state, ulong floor, Element genetator) =>
+        state | (((ulong)genetator << generatorShift) << floorShift[floor]);
+
+    public static bool Valid(this ulong state) {
+        for (int floor = 3; floor >= 0; floor--) {
+            var chips = state.GetChips((ulong)floor);
+            var generators = state.GetGenerators((ulong)floor);
+            var pairs = chips & generators;
+            var unpairedChips = chips & ~pairs;
+            if (unpairedChips != 0 && generators != 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static IEnumerable NextStates(this ulong state) {
+        var floor = state.GetElevator();
+        for (ulong i = 1; i < 0b100000000000000; i <<= 1) {
+            for (ulong j = 1; j < 0b100000000000000; j <<= 1) {
+                var iOnFloor = i << floorShift[floor];
+                var jOnFloor = j << floorShift[floor];
+                if ((state & iOnFloor) != 0 && (state & jOnFloor) != 0) {
+                    if (floor > 0) {
+                        var iOnPrevFloor = i << floorShift[floor - 1];
+                        var jOnPrevFloor = j << floorShift[floor - 1];
+                        var elevatorOnPrevFloor = (floor - 1) << elevatorShift;
+                        var stateNext = (state & ~iOnFloor & ~jOnFloor & elevatorMask) | iOnPrevFloor | jOnPrevFloor | elevatorOnPrevFloor;
+                        if (stateNext.Valid())
+                            yield return stateNext;
+                    }
+
+                    if (floor < 3) {
+                        var iOnNextFloor = i << floorShift[floor + 1];
+                        var jOnNextFloor = j << floorShift[floor + 1];
+                        var elevatorOnNextFloor = (floor + 1) << elevatorShift;
+                        var stateNext = (state & ~iOnFloor & ~jOnFloor & elevatorMask) | iOnNextFloor | jOnNextFloor | elevatorOnNextFloor;
+                        if (stateNext.Valid())
+                            yield return stateNext;
+                    }
+                }
+            }
+        }
+    }
+
+    public static bool Final(this ulong state) =>
+        (state & 0b0000000000000000111111111111111111111111111111111111111111) == 0;
+
+    public static string Tsto(this ulong state){
+        var sb = new StringBuilder();
+        for (int floor = 3; floor >= 0; floor --){
+            var e = state.GetElevator() == (ulong)floor ? "E" : " ";
+            var chips = state.GetChips((ulong)floor);
+            var generators =state.GetGenerators((ulong)floor);
+
+            sb.Append($"F{(floor + 1)} {e} |");
+            for (int i = 0; i < elementCount;i++){
+                sb.Append((generators & 1) == 1 ? " #" : " .");
+                sb.Append((chips & 1) == 1 ? " #" : " .");
+                sb.Append(" |");
+                chips >>= 1;
+                generators >>= 1;
+            }
+            sb.AppendLine();
+        }
+        return sb.ToString();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/12/illustration.jpeg b/2016/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/12/illustration.jpeg differ diff --git a/2016/12/index.html b/2016/12/index.html new file mode 100644 index 00000000..c23855b8 --- /dev/null +++ b/2016/12/index.html @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/12 'Leonardo's Monorail'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/12

+

Leonardo's Monorail

+

in C#

+

+

by encse

+
+ +
+ +
+

You finally reach the top floor of this building: a garden with a slanted glass ceiling. Looks like there are no more stars to be had.

+

While sitting on a nearby bench amidst some tiger lilies, you manage to decrypt some of the files you extracted from the servers downstairs.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day12;
+
+[ProblemName("Leonardo's Monorail")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 0);
+
+    public object PartTwo(string input) => Solve(input, 1);
+
+    int Solve(string input, int c) {
+        var regs = new Dictionary();
+        int ip = 0;
+        int getReg(string reg) {
+            return int.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        void setReg(string reg, int value) {
+            regs[reg] = value;
+        }
+
+        setReg("c", c);
+
+        var prog = input.Split('\n').ToArray();
+        while (ip >= 0 && ip < prog.Length) {
+            var line = prog[ip];
+            var stm = line.Split(' ');
+            switch (stm[0]) {
+                case "cpy":
+                    setReg(stm[2], getReg(stm[1]));
+                    ip++;
+                    break;
+                case "inc":
+                    setReg(stm[1], getReg(stm[1]) + 1);
+                    ip++;
+                    break;
+                case "dec":
+                    setReg(stm[1], getReg(stm[1]) - 1);
+                    ip++;
+                    break;
+                case "jnz":
+                    ip += getReg(stm[1]) != 0 ? getReg(stm[2]) : 1;
+                    break;
+                default: throw new Exception("Cannot parse " + line);
+            }
+        }
+        return getReg("a");
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/13/illustration.jpeg b/2016/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/13/illustration.jpeg differ diff --git a/2016/13/index.html b/2016/13/index.html new file mode 100644 index 00000000..1f702891 --- /dev/null +++ b/2016/13/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/13 'A Maze of Twisty Little Cubicles'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/13

+

A Maze of Twisty Little Cubicles

+

in C#

+

+

by encse

+
+ +
+ +
+

You arrive at the first floor of this new building to discover a much less welcoming environment than the shiny atrium of the last one. Instead, you are in a maze of twisty little cubicles, all alike.

+

Every location in this area is addressed by a pair of non-negative integers (x,y). Each such coordinate is either a wall or an open space. You can't move diagonally. The cube maze starts at 0,0 and seems to extend infinitely toward positive x and y; negative values are invalid, as they represent a location outside the building. You are in a small waiting area at 1,1.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day13;
+
+[ProblemName("A Maze of Twisty Little Cubicles")]
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        Steps(int.Parse(input))
+        .First(s => s.icol == 31 && s.irow == 39)
+        .steps;
+
+    public object PartTwo(string input) =>
+        Steps(int.Parse(input))
+        .TakeWhile(s => s.steps <= 50)
+        .Count();
+
+    IEnumerable<(int steps, int irow, int icol)> Steps(int input) {
+        var q = new Queue<(int steps, int irow, int icol)>();
+        q.Enqueue((0, 1, 1));
+        var seen = new HashSet<(int, int)>();
+        seen.Add((1, 1));
+        var n = (
+                from drow in new[] { -1, 0, 1 }
+                from dcol in new[] { -1, 0, 1 }
+                where Math.Abs(drow) + Math.Abs(dcol) == 1
+                select (drow, dcol)
+            ).ToArray();
+
+        while (q.Any()) {
+            var (steps, irow, icol) = q.Dequeue();
+
+            yield return (steps, irow, icol);
+
+            foreach (var (drow, dcol) in n) {
+                var (irowT, icolT) = (irow + drow, icol + dcol);
+                if (irowT >= 0 && icolT >= 0) {
+                    var w = icolT * icolT + 3 * icolT + 2 * icolT * irowT + irowT + irowT * irowT + input;
+                    if (Convert.ToString(w, 2).Count(ch => ch == '1') % 2 == 0) {
+                        if (!seen.Contains((irowT, icolT))) {
+                            q.Enqueue((steps + 1, irowT, icolT));
+                            seen.Add((irowT, icolT));
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/14/illustration.jpeg b/2016/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/14/illustration.jpeg differ diff --git a/2016/14/index.html b/2016/14/index.html new file mode 100644 index 00000000..78c3851c --- /dev/null +++ b/2016/14/index.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/14 'One-Time Pad'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/14

+

One-Time Pad

+

in C#

+

+

by encse

+
+ +
+ +
+

In order to communicate securely with Santa while you're on this mission, you've been using a one-time pad that you generate using a pre-agreed algorithm. Unfortunately, you've run out of keys in your one-time pad, and so you need to generate some more.

+

To generate keys, you first get a stream of random data by taking the MD5 of a pre-arranged salt (your puzzle input) and an increasing integer index (starting with 0, and represented in decimal); the resulting MD5 hash should be represented as a string of lowercase hexadecimal digits.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Y2016.Day14;
+
+[ProblemName("One-Time Pad")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(Hashes(input, 0));
+    public object PartTwo(string input) => Solve(Hashes(input, 2016));
+
+    int Solve(IEnumerable hashes) {
+        var found = 0;
+        var nextIdx = Enumerable.Range(0, 16).Select(_ => new Queue()).ToArray();
+        var res = 0;
+        var hashQueue = new Queue();
+        var idx = 0;
+        var idxEnd = 0;
+        foreach (var hashEnd in hashes) {
+
+            hashQueue.Enqueue(hashEnd);
+
+            for (int i = 0; i < hashEnd.Length - 5; i++) {
+                if (hashEnd[i] == hashEnd[i + 1] &&
+                    hashEnd[i + 1] == hashEnd[i + 2] &&
+                    hashEnd[i + 2] == hashEnd[i + 3] &&
+                    hashEnd[i + 3] == hashEnd[i + 4]
+                ) {
+                    var c = hashEnd[i] <= '9' ? hashEnd[i] - '0' : hashEnd[i] - 'a' + 10;
+                    nextIdx[c].Enqueue(idxEnd);
+                }
+            }
+            idxEnd++;
+
+            if (hashQueue.Count() == 1001) {
+                var hash = hashQueue.Dequeue();
+                for (int i = 0; i < hash.Length - 2; i++) {
+                    if (hash[i] == hash[i + 1] && hash[i + 2] == hash[i + 1]) {
+                        var iq = hash[i] <= '9' ? hash[i] - '0' : hash[i] - 'a' + 10;
+                        var q = nextIdx[iq];
+                        while (q.Any() && q.First() <= idx) {
+                            q.Dequeue();
+                        }
+                        if (q.Any() && q.First() - idx <= 1000) {
+                            found++;
+                            res = idx;
+                            if (found == 64) {
+                                return res;
+                            }
+                        }
+                        break;
+                    }
+                }
+                idx++;
+            }
+        }
+
+        throw new Exception();
+    }
+
+    public IEnumerable Hashes(string input, int rehash) {
+
+        for (var i = 0; i < int.MaxValue; i++) {
+            var q = new ConcurrentQueue<(int i, string hash)>();
+
+            Parallel.ForEach(
+                Enumerable.Range(i, 1000),
+                () => MD5.Create(),
+                (i, state, md5) => {
+                    var newInput = new byte[32];
+                    var btoh = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+                    var hash = md5.ComputeHash(Encoding.ASCII.GetBytes(input + i));
+
+                    for (var r = 0; r < rehash; r++) {
+                        for (int ib = 0; ib < 16; ib++) {
+                            newInput[2 * ib] = (byte)btoh[(hash[ib] >> 4) & 15];
+                            newInput[2 * ib + 1] = (byte)btoh[hash[ib] & 15];
+                        }
+                        hash = md5.ComputeHash(newInput);
+                    }
+
+                    q.Enqueue((i, string.Join("", hash.Select(b => b.ToString("x2")))));
+                    return md5;
+                },
+                (_) => { }
+            );
+            foreach (var item in q.OrderBy(x => x.i)) {
+                i = item.i;
+                yield return item.hash;
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/15/illustration.jpeg b/2016/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/15/illustration.jpeg differ diff --git a/2016/15/index.html b/2016/15/index.html new file mode 100644 index 00000000..e95d6f73 --- /dev/null +++ b/2016/15/index.html @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/15 'Timing is Everything'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/15

+

Timing is Everything

+

in C#

+

+

by encse

+
+ +
+ +
+

The halls open into an interior plaza containing a large kinetic sculpture. The sculpture is in a sealed enclosure and seems to involve a set of identical spherical capsules that are carried to the top and allowed to bounce through the maze of spinning pieces.

+

Part of the sculpture is even interactive! When a button is pressed, a capsule is dropped and tries to fall through slots in a set of rotating discs to finally go through a little hole at the bottom and come out of the sculpture. If any of the slots aren't aligned with the capsule as it passes, the capsule bounces off the disc and soars away. You feel compelled to get one of those capsules.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day15;
+
+[ProblemName("Timing is Everything")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Iterate(Parse(input)).First(v => v.ok).t;
+
+    public object PartTwo(string input) => Iterate(Parse(input).Concat(new []{(pos: 0, mod: 11)}).ToArray()).First(v => v.ok).t;
+
+    (int pos, int mod)[] Parse(string input) => (
+            from line in input.Split('\n')
+            let m = Regex.Match(line, @"Disc #\d has (\d+) positions; at time=0, it is at position (\d+).")
+            select (pos: int.Parse(m.Groups[2].Value), mod: int.Parse(m.Groups[1].Value))
+        ).ToArray();
+
+    IEnumerable<(int t, bool ok)> Iterate((int pos, int mod)[] discs) {
+        for (int t = 0; ; t++) {
+            var ok = Enumerable.Range(0, discs.Length)
+                .All(i => (discs[i].pos + t + i + 1) % discs[i].mod == 0);
+            yield return (t, ok);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/16/illustration.jpeg b/2016/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/16/illustration.jpeg differ diff --git a/2016/16/index.html b/2016/16/index.html new file mode 100644 index 00000000..d94233bf --- /dev/null +++ b/2016/16/index.html @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/16 'Dragon Checksum'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/16

+

Dragon Checksum

+

in C#

+

+

by encse

+
+ +
+ +
+

You're done scanning this part of the network, but you've left traces of your presence. You need to overwrite some disks with random-looking data to cover your tracks and update the local security system with a new checksum for those disks.

+

For the data to not be suspicious, it needs to have certain properties; purely random data will be detected as tampering. To generate appropriate random data, you'll need to use a modified dragon curve.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Text;
+
+namespace AdventOfCode.Y2016.Day16;
+
+[ProblemName("Dragon Checksum")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Checksum(input, 272);
+
+    public object PartTwo(string input) => Checksum(input, 35651584);
+
+    string Checksum(string st, int length) {
+
+        while (st.Length < length) {
+            var a = st;
+            var b = string.Join("", from ch in a.Reverse() select ch == '0' ? '1' : '0');
+            st = a + "0" + b;
+        }
+        st = st.Substring(0, length);
+        var sb = new StringBuilder();
+
+        while (sb.Length % 2 == 0) {
+            sb.Clear();
+            for (int i = 0; i < st.Length; i += 2) {
+                sb.Append(st[i] == st[i + 1] ? "1" : "0");
+            }
+            st = sb.ToString();
+        }
+        return st;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/17/illustration.jpeg b/2016/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/17/illustration.jpeg differ diff --git a/2016/17/index.html b/2016/17/index.html new file mode 100644 index 00000000..d9626cae --- /dev/null +++ b/2016/17/index.html @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/17 'Two Steps Forward'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/17

+

Two Steps Forward

+

in C#

+

+

by encse

+
+ +
+ +
+

You're trying to access a secure vault protected by a 4x4 grid of small rooms connected by doors. You start in the top-left room (marked S), and you can access the vault (marked V) once you reach the bottom-right room:

+
#########
+#S| | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | |  
+####### V
+
+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace AdventOfCode.Y2016.Day17;
+
+[ProblemName("Two Steps Forward")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Routes(input).First();
+
+    public object PartTwo(string input) => Routes(input).Last().Length;
+
+    IEnumerable Routes(string input) {
+
+        var q = new Queue<(string path, int irow, int icol)>();
+        q.Enqueue(("", 0, 0));
+
+        while (q.Any()) {
+            var s = q.Dequeue();
+
+            if (s.icol == 3 && s.irow == 3) {
+                yield return s.path;
+            } else {
+                var doors = DoorState(input + s.path);
+
+                if (doors.down && s.irow < 3) {
+                    q.Enqueue((s.path + "D", s.irow + 1, s.icol));
+                }
+                if (doors.up && s.irow > 0) {
+                    q.Enqueue((s.path + "U", s.irow - 1, s.icol));
+                }
+                if (doors.left && s.icol > 0) {
+                    q.Enqueue((s.path + "L", s.irow, s.icol - 1));
+                }
+                if (doors.right && s.icol < 3) {
+                    q.Enqueue((s.path + "R", s.irow, s.icol + 1));
+                }
+            }
+        }
+    }
+
+    (bool up, bool down, bool left, bool right) DoorState(string st) {
+        var md5 = MD5.Create();
+        var hash = md5.ComputeHash(Encoding.ASCII.GetBytes(st));
+        var stHash = string.Join("", hash.Select(b => b.ToString("x2")));
+        return (stHash[0] > 'a', stHash[1] > 'a', stHash[2] > 'a', stHash[3] > 'a');
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/18/illustration.jpeg b/2016/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/18/illustration.jpeg differ diff --git a/2016/18/index.html b/2016/18/index.html new file mode 100644 index 00000000..55a39e3d --- /dev/null +++ b/2016/18/index.html @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/18 'Like a Rogue'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/18

+

Like a Rogue

+

in C#

+

+

by encse

+
+ +
+ +
+

As you enter this room, you hear a loud click! Some of the tiles in the floor here seem to be pressure plates for traps, and the trap you just triggered has run out of... whatever it tried to do to you. You doubt you'll be so lucky next time.

+

Upon closer examination, the traps and safe tiles in this room seem to follow a pattern. The tiles are arranged into rows that are all the same width; you take note of the safe tiles (.) and traps (^) in the first row (your puzzle input).

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Text;
+
+namespace AdventOfCode.Y2016.Day18;
+
+[ProblemName("Like a Rogue")]
+class Solution : Solver {
+
+    public object PartOne(string input) => SafeCount(input, 40);
+
+    public object PartTwo(string input) => SafeCount(input, 400000);
+
+    int SafeCount(string input, int lines) {
+        var rowPrev = input;
+        var safeCount = rowPrev.Count(ch => ch == '.');
+        for (int i = 0; i < lines - 1; i++) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < rowPrev.Length; j++) {
+                var leftTrap = j != 0 && rowPrev[j - 1] == '^';
+                var centerTrap = rowPrev[j] == '^';
+                var rightTrap = j != rowPrev.Length - 1 && rowPrev[j + 1] == '^';
+
+                var trap =
+                    (leftTrap && centerTrap && !rightTrap) ||
+                    (!leftTrap && centerTrap && rightTrap) ||
+                    (leftTrap && !centerTrap && !rightTrap) ||
+                    (!leftTrap && !centerTrap && rightTrap)
+                    ;
+                sb.Append(trap ? '^' : '.');
+            }
+            rowPrev = sb.ToString();
+            safeCount += rowPrev.Count(ch => ch == '.');
+        }
+
+        return safeCount;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/19/illustration.jpeg b/2016/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/19/illustration.jpeg differ diff --git a/2016/19/index.html b/2016/19/index.html new file mode 100644 index 00000000..f1f536a6 --- /dev/null +++ b/2016/19/index.html @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/19 'An Elephant Named Joseph'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/19

+

An Elephant Named Joseph

+

in C#

+

+

by encse

+
+ +
+ +
+

The Elves contact you over a highly secure emergency channel. Back at the North Pole, the Elves are busy misunderstanding White Elephant parties.

+

Each Elf brings a present. They all sit in a circle, numbered starting with position 1. Then, starting with the first Elf, they take turns stealing all the presents from the Elf to their left. An Elf with no presents is removed from the circle and does not take turns.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day19;
+
+[ProblemName("An Elephant Named Joseph")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var elves = Elves(int.Parse(input));
+        return Solve(elves[0], elves[1], elves.Length, 
+            (elfVictim, count) => elfVictim.next.next);
+    }
+
+    public object PartTwo(string input) {
+        var elves = Elves(int.Parse(input));
+        return Solve(elves[0], elves[elves.Length / 2], elves.Length, 
+            (elfVictim, count) => count % 2 == 1 ? elfVictim.next : elfVictim.next.next);
+    }
+
+    int Solve(Elf elf, Elf elfVictim, int elfCount, Func nextVictim) {
+        while (elfCount > 1) {
+            elfVictim.prev.next = elfVictim.next;
+            elfVictim.next.prev = elfVictim.prev;
+            elf = elf.next;
+            elfCount--;
+            elfVictim = nextVictim(elfVictim, elfCount);
+        }
+        return elf.id;
+    }
+
+    Elf[] Elves(int count) {
+        var elves = Enumerable.Range(0, count).Select(x => new Elf { id = x + 1 }).ToArray();
+        for (var i = 0; i < count; i++) {
+            elves[i].prev = elves[(i - 1 + count) % count];
+            elves[i].next = elves[(i + 1) % count];
+        }
+        return elves;
+    }
+
+    class Elf {
+        public int id;
+        public Elf prev;
+        public Elf next;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/2/illustration.jpeg b/2016/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/2/illustration.jpeg differ diff --git a/2016/2/index.html b/2016/2/index.html new file mode 100644 index 00000000..43fee262 --- /dev/null +++ b/2016/2/index.html @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/2 'Bathroom Security'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/2

+

Bathroom Security

+

in C#

+

+

by encse

+
+ +
+ +
+

You arrive at Easter Bunny Headquarters under cover of darkness. However, you left in such a rush that you forgot to use the bathroom! Fancy office buildings like this one usually have keypad locks on their bathrooms, so you search the front desk for the code.

+

"In order to improve security," the document you find says, "bathroom codes will no longer be written down. Instead, please memorize and follow the procedure below to access the bathrooms."

+

Read the full puzzle.

+
+
using System;
+
+namespace AdventOfCode.Y2016.Day02;
+
+[ProblemName("Bathroom Security")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, "123\n456\n789");
+    public object PartTwo(string input) => Solve(input, "  1  \n 234 \n56789\n ABC \n  D  ");
+
+    string Solve(string input, string keypad) {
+        var res = "";
+        var lines = keypad.Split('\n');
+        var (crow, ccol) = (lines.Length, lines[0].Length);
+        var (irow, icol) = (crow / 2, ccol / 2);
+        foreach (var line in input.Split('\n')) {
+            foreach (var ch in line) {
+                var (drow, dcol) = ch switch {
+                    'U' => (-1, 0),
+                    'D' =>  (1, 0),
+                    'L' => (0, -1),
+                    'R' => (0, 1),
+                    _ => throw new ArgumentException()
+                };
+
+                var (irowT, icolT) = (irow + drow, icol + dcol);
+                if (irowT >= 0 && irowT < crow && icolT >= 0 && icolT < ccol && lines[irowT][icolT] != ' ') {
+                    (irow, icol) = (irowT, icolT);
+                }
+            }
+            res += lines[irow][icol];
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/20/illustration.jpeg b/2016/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/20/illustration.jpeg differ diff --git a/2016/20/index.html b/2016/20/index.html new file mode 100644 index 00000000..30f82810 --- /dev/null +++ b/2016/20/index.html @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/20 'Firewall Rules'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/20

+

Firewall Rules

+

in C#

+

+

by encse

+
+ +
+ +
+

You'd like to set up a small hidden computer here so you can use it to get back into the network later. However, the corporate firewall only allows communication with certain external IP addresses.

+

You've retrieved the list of blocked IPs from the firewall, but the list seems to be messy and poorly maintained, and it's not clear which IPs are allowed. Also, rather than being written in dot-decimal notation, they are written as plain 32-bit integers, which can have any value from 0 through 4294967295, inclusive.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day20;
+
+[ProblemName("Firewall Rules")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var k = 0L;
+        foreach (var range in Parse(input)) {
+            if (k < range.min) {
+                break;
+            } else if (range.min <= k && k <= range.max) {
+                k = range.max + 1;
+            }
+        }
+        return k;
+    }
+
+    public object PartTwo(string input) {
+        var k = 0L;
+        var sum = 0L;
+        foreach (var range in Parse(input)) {
+            if (k < range.min) {
+                sum += range.min - k;
+                k = range.max + 1;
+            } else if (range.min <= k && k <= range.max) {
+                k = range.max + 1;
+            }
+        }
+
+        var lim = 4294967296L;
+        if (lim > k) {
+            sum += lim - k;
+        }
+        return sum;
+    }
+
+    IEnumerable<(long min, long max)> Parse(string input) => (
+            from line in input.Split('\n')
+            let parts = line.Split('-')
+            let min = long.Parse(parts[0])
+            let max = long.Parse(parts[1])
+            orderby min
+            select (min, max)
+        ).AsEnumerable();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/21/illustration.jpeg b/2016/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/21/illustration.jpeg differ diff --git a/2016/21/index.html b/2016/21/index.html new file mode 100644 index 00000000..3f232493 --- /dev/null +++ b/2016/21/index.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/21 'Scrambled Letters and Hash'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/21

+

Scrambled Letters and Hash

+

in C#

+

+

by encse

+
+ +
+ +
+

The computer system you're breaking into uses a weird scrambling function to store its passwords. It shouldn't be much trouble to create your own scrambled password so you can add it to the system; you just have to implement the scrambler.

+

The scrambling function is a series of operations (the exact list is provided in your puzzle input). Starting with the password to be scrambled, apply each operation in succession to the string. The individual operations behave as follows:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day21;
+
+[ProblemName("Scrambled Letters and Hash")]
+class Solution : Solver {
+
+    public object PartOne(string input) => string.Join("", Parse(input)("abcdefgh"));
+
+    public object PartTwo(string input) {
+        var scramble = Parse(input);
+        return string.Join("", Permutations("abcdefgh".ToArray()).First(p => scramble(p).SequenceEqual("fbgdceah")));
+    }
+
+   IEnumerable Permutations(T[] rgt) {
+       
+        IEnumerable PermutationsRec(int i) {
+            if (i == rgt.Length) {
+                yield return rgt.ToArray();
+            }
+
+            for (var j = i; j < rgt.Length; j++) {
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+                foreach (var perm in PermutationsRec(i + 1)) {
+                    yield return perm;
+                }
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+            }
+        }
+
+        return PermutationsRec(0);
+    }
+    
+    Func, IEnumerable> Parse(string input) {
+        var steps = (
+            from line in input.Split('\n')
+            select
+                Match(line, @"swap position (\d+) with position (\d+)", m => {
+                    var x = int.Parse(m[0]);
+                    var y = int.Parse(m[1]);
+                    return chars => SwapPosition(chars, x, y);
+                }) ??
+                Match(line, @"swap letter (\w) with letter (\w)", m => {
+                    var chX = m[0][0];
+                    var chY = m[1][0];
+                    return (chars) => SwapLetter(chars, chX, chY);
+                }) ??
+                Match(line, @"rotate left (\d+) step", m => {
+                    var x = int.Parse(m[0]);
+                    return chars => RotateLeft(chars, x);
+                }) ??
+                Match(line, @"rotate right (\d+) step", m => {
+                    var x = int.Parse(m[0]);
+                    return chars => RotateRight(chars, x);
+                }) ??
+                Match(line, @"rotate based on position of letter (\w)", m => {
+                    var chX = m[0][0];
+                    return chars => RotateBasedOnPosition(chars, chX);
+                }) ??
+                Match(line, @"reverse positions (\d+) through (\d+)", m => {
+                    var x = int.Parse(m[0]);
+                    var y = int.Parse(m[1]);
+                    return chars => Reverse(chars, x, y);
+                }) ??
+                Match(line, @"move position (\d+) to position (\d+)", m => {
+                    var x = int.Parse(m[0]);
+                    var y = int.Parse(m[1]);
+                    return chars => MovePosition(chars, x, y);
+                }) ??
+                throw new Exception("Cannot parse " + line)
+            ).ToArray();
+
+        return chars => {
+            var charsArray = chars.ToArray();
+            foreach (var step in steps) {
+                step(charsArray);
+            }
+            return charsArray;
+        };
+    }
+
+    Action Match(string stm, string pattern, Func> a) {
+        var match = Regex.Match(stm, pattern);
+        if (match.Success) {
+            return a(match.Groups.Cast().Skip(1).Select(g => g.Value).ToArray());
+        } else {
+            return null;
+        }
+    }
+
+    void SwapPosition(char[] chars, int x, int y) {
+        (chars[x], chars[y]) = (chars[y], chars[x]);
+    }
+
+    void SwapLetter(char[] chars, char chX, char chY) {
+        for (var i = 0; i < chars.Length; i++) {
+            chars[i] = chars[i] == chX ? chY : chars[i] == chY ? chX : chars[i];
+        }
+    }
+
+    void RotateBasedOnPosition(char[] chars, char chX) {
+        var i = Array.IndexOf(chars, chX);
+        RotateRight(chars, i >= 4 ? i + 2 : i + 1);
+    }
+
+    void RotateLeft(char[] chars, int t) {
+        t %= chars.Length;
+        Reverse(chars, 0, t - 1);
+        Reverse(chars, t, chars.Length - 1);
+        Reverse(chars, 0, chars.Length - 1);
+    }
+
+    void RotateRight(char[] chars, int t) {
+        t %= chars.Length;
+        Reverse(chars, 0, chars.Length - 1);
+        Reverse(chars, 0, t - 1);
+        Reverse(chars, t, chars.Length - 1);
+    }
+
+    void Reverse(char[] chars, int x, int y) {
+        while (x < y) {
+            (chars[x], chars[y]) = (chars[y], chars[x]);
+            x++;
+            y--;
+        }
+    }
+
+    void MovePosition(char[] chars, int x, int y) {
+        var d = x < y ? 1 : -1;
+
+        var ch = chars[x];
+        for (int i = x + d; i != y + d; i += d) {
+            chars[i - d] = chars[i];
+        }
+        chars[y] = ch;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/22/illustration.jpeg b/2016/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/22/illustration.jpeg differ diff --git a/2016/22/index.html b/2016/22/index.html new file mode 100644 index 00000000..b5b2e560 --- /dev/null +++ b/2016/22/index.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/22 'Grid Computing'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/22

+

Grid Computing

+

in C#

+

+

by encse

+
+ +
+ +
+

You gain access to a massive storage cluster arranged in a grid; each storage node is only connected to the four nodes directly adjacent to it (three if the node is on an edge, two if it's in a corner).

+

You can directly access data only on node /dev/grid/node-x0-y0, but you can perform some limited actions on the other nodes:

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day22;
+
+[ProblemName("Grid Computing")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var nodes = Parse(input);
+        var r = 0;
+        foreach (var nodeA in nodes) {
+            if (nodeA.used > 0) {
+                foreach (var nodeB in nodes) {
+                    if ((nodeA.irow != nodeB.irow || nodeA.icol != nodeB.icol) && nodeB.avail > nodeA.used) {
+                        r++;
+                    }
+                }
+            }
+        }
+        return r;
+    }
+
+    public object PartTwo(string input) {
+        var nodes = Parse(input);
+        var grid = new Grid(nodes);
+        
+        while(grid.irowEmpty != 0){
+            if (!grid.Wall(grid.irowEmpty - 1, grid.icolEmpty)) {
+                grid.Move(-1, 0);
+            } else {
+                grid.Move(0, -1);
+            }
+        }
+        while (grid.icolEmpty != grid.ccol -1) {
+            grid.Move(0, 1);
+        }
+        while(!nodes[0,0].goal) {
+            grid.Move(1, 0);
+            grid.Move(0, -1);
+            grid.Move(0, -1);
+            grid.Move(-1, 0);
+            grid.Move(0, 1);
+        }
+        return grid.moves;
+    }
+
+    Node[,] Parse(string input) {
+        var nodes = (
+            from line in input.Split('\n').Skip(2)
+            let parts = Regex.Matches(line, @"(\d+)").Select(m => int.Parse(m.Groups[1].Value)).ToArray()
+            select new Node { irow = parts[1], icol = parts[0], size = parts[2], used = parts[3] }
+        ).ToArray();
+
+        var (crow, ccol) = (nodes.Select(x => x.irow).Max() + 1, nodes.Select(x => x.icol).Max() + 1);
+        var res = new Node[crow, ccol];
+        foreach (var file in nodes) {
+            res[file.irow, file.icol] = file;
+        }
+        res[0, ccol - 1].goal = true;
+        return res;
+    }
+
+    class Grid {
+        public int irowEmpty;
+        public int icolEmpty;
+        public Node[,] nodes;
+        public int moves;
+
+        public Grid(Node[,] nodes){
+            this.nodes = nodes;
+            foreach(var node in nodes){
+                if(node.used == 0){
+                    irowEmpty = node.irow;
+                    icolEmpty = node.icol;
+                    break;
+                }
+            }
+        }
+
+        public int crow { get { return nodes.GetLength(0); } }
+        public int ccol { get { return nodes.GetLength(1); } }
+
+        public void Tsto() {
+            var sb = new StringBuilder();
+            sb.AppendLine();
+            for (var irowT = 0; irowT < crow; irowT++) {
+                for (var icolT = 0; icolT < ccol; icolT++) {
+                    if (nodes[irowT, icolT].goal) {
+                        sb.Append("G");
+                    } else if (irowT == 0 && icolT == 0) {
+                        sb.Append("x");
+                    } else if (nodes[irowT, icolT].used == 0) {
+                        sb.Append("E");
+                    } else if (Wall(irowT, icolT)) {
+                        sb.Append("#");
+                    } else {
+                        sb.Append(".");
+                    }
+                }
+                sb.AppendLine();
+            }
+            Console.WriteLine(sb.ToString());
+        }
+
+        public bool Wall(int irow, int icol) =>
+            nodes[irow, icol].used > nodes[irowEmpty, icolEmpty].size;
+
+        public void Move(int drow, int dcol) {
+            if (Math.Abs(drow) + Math.Abs(dcol) != 1) throw new Exception();
+
+            var irowT = irowEmpty + drow;
+            var icolT = icolEmpty + dcol;
+
+            if (irowT < 0 || irowT >= crow) throw new Exception();
+            if (icolT < 0 || icolT >= ccol) throw new Exception();
+            if (nodes[irowT, icolT].used > nodes[irowEmpty, icolEmpty].avail) throw new Exception();
+
+            nodes[irowEmpty, icolEmpty].used = nodes[irowT, icolT].used;
+            nodes[irowEmpty, icolEmpty].goal = nodes[irowT, icolT].goal;
+
+            (irowEmpty, icolEmpty) = (irowT, icolT);
+            nodes[irowEmpty, icolEmpty].used = 0;
+            nodes[irowEmpty, icolEmpty].goal = false;
+
+            moves++;
+        }
+    }
+
+    class Node {
+        public bool goal = false;
+        public int irow; 
+        public int icol; 
+        public int size; 
+        public int used;
+        public int avail { get { return size - used; } }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/23/illustration.jpeg b/2016/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/23/illustration.jpeg differ diff --git a/2016/23/index.html b/2016/23/index.html new file mode 100644 index 00000000..4a6bc1f1 --- /dev/null +++ b/2016/23/index.html @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/23 'Safe Cracking'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/23

+

Safe Cracking

+

in C#

+

+

by encse

+
+ +
+ +
+

This is one of the top floors of the nicest tower in EBHQ. The Easter Bunny's private office is here, complete with a safe hidden behind a painting, and who wouldn't hide a star in a safe behind a painting?

+

The safe has a digital screen and keypad for code entry. A sticky note attached to the safe has a password hint on it: "eggs". The painting is of a large rabbit coloring some eggs. You see 7.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day23;
+
+[ProblemName("Safe Cracking")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 7);
+    public object PartTwo(string input) => Solve(input, 12);
+    
+    int Solve(string input, int a) {
+        var prg = Parse(Patch(input));
+        var regs = new Dictionary();
+        var ip = 0;
+        int getReg(string reg) {
+            return int.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        void setReg(string reg, int value) {
+            if (!int.TryParse(reg, out var _)) {
+                regs[reg] = value;
+            }
+        }
+
+        setReg("a", a);
+
+        while(ip < prg.Length){
+            var stm = prg[ip];
+            switch (stm[0]) {
+                case "cpy":
+                    setReg(stm[2], getReg(stm[1]));
+                    ip++;
+                    break;
+                case "inc":
+                    setReg(stm[1], getReg(stm[1]) + 1);
+                    ip++;
+                    break;
+                case "mul":
+                    setReg(stm[2], getReg(stm[1]) * getReg(stm[2]));
+                    ip++;
+                    break;
+                case "dec":
+                    setReg(stm[1], getReg(stm[1]) - 1);
+                    ip++;
+                    break;
+                case "jnz":
+                    ip += getReg(stm[1]) != 0 ? getReg(stm[2]) : 1;
+                    break;
+                case "tgl":
+                    var ipDst = ip + getReg(stm[1]);
+                    if (ipDst >= 0 && ipDst < prg.Length) {
+                        var stmDst = prg[ipDst];
+                        stmDst[0] = stmDst[0] switch {
+                            "cpy" => "jnz",
+                            "inc" => "dec",
+                            "dec" => "inc",
+                            "jnz" => "cpy",
+                            "tgl" => "inc",
+                            _ => stmDst[0]
+                        };
+                    }
+                    ip++;
+                    break;
+                default: 
+                    throw new Exception("Cannot parse " + string.Join(" ", stm));
+            }
+        }
+        return getReg("a");
+    }
+
+    string Patch(string input) {
+        var lines = input.Split('\n');
+        lines[5] = "cpy c a";
+        lines[6] = "mul d a";
+        lines[7] = "cpy 0 d";
+        lines[8] = "cpy 0 c";
+        return string.Join("\n", lines);
+    }
+    
+    string[][] Parse(string input) =>
+        input.Split('\n').Select(line => line.Split(' ')).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/24/illustration.jpeg b/2016/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/24/illustration.jpeg differ diff --git a/2016/24/index.html b/2016/24/index.html new file mode 100644 index 00000000..90307ec6 --- /dev/null +++ b/2016/24/index.html @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/24 'Air Duct Spelunking'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/24

+

Air Duct Spelunking

+

in C#

+

+

by encse

+
+ +
+ +
+

You've finally met your match; the doors that provide access to the roof are locked tight, and all of the controls and related electronics are inaccessible. You simply can't reach them.

+

The robot that cleans the air ducts, however, can.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day24;
+
+[ProblemName("Air Duct Spelunking")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Routes(input, false).Min();
+
+    public object PartTwo(string input) => Routes(input, true).Min();
+
+    IEnumerable Routes(string input, bool loop) {
+        var map = new Map(input);
+
+        foreach (var perm in Permutations(Enumerable.Range(1, map.poi.Length - 1).ToArray())) {
+
+            perm.Insert(0, 0);
+            if (loop) {
+                perm.Add(0);
+            }
+            var l = 0;
+            for (int i = 0; i < perm.Count - 1; i++) {
+                l += map.ShortestPathLength(map.poi[perm[i]], map.poi[perm[i + 1]]);
+            }
+            yield return l;
+        }
+    }
+
+    IEnumerable> Permutations(T[] rgt) {
+       
+        IEnumerable> PermutationsRec(int i) {
+            if (i == rgt.Length) {
+                yield return rgt.ToList();
+            }
+
+            for (var j = i; j < rgt.Length; j++) {
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+                foreach (var perm in PermutationsRec(i + 1)) {
+                    yield return perm;
+                }
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+            }
+        }
+
+        return PermutationsRec(0);
+    }
+
+    class Map {
+
+        string[] map;
+        public int crow;
+        public int ccol;
+        public (int irow, int icol)[] poi;
+        private Dictionary<(int, int, int, int), int> cache = new Dictionary<(int, int, int, int), int>();
+
+        public Map(string input) {
+            this.map = input.Split('\n');
+            this.crow = map.Length;
+            this.ccol = map[0].Length;
+
+            poi = new(int irow, int icol)[10];
+            var poiCount = 0;
+            for (var irow = 0; irow < crow; irow++) {
+                for (var icol = 0; icol < ccol; icol++) {
+                    if (int.TryParse($"{map[irow][icol]}", out var i)) {
+                        poi[i] = (irow, icol);
+                        poiCount++;
+                    }
+                }
+            }
+            poi = poi.Take(poiCount).ToArray();
+        }
+
+        public int ShortestPathLength((int irow, int icol) from, (int irow, int icol) to) {
+            var key = (from.irow, from.icol, to.irow, to.icol);
+            if (!cache.ContainsKey(key)) {
+                var q = new Queue<(int steps, int irow, int icol)>();
+                q.Enqueue((0, from.irow, from.icol));
+                var seen = new HashSet<(int, int)>();
+                seen.Add(from);
+                while (q.Any()) {
+                    var p = q.Dequeue();
+                    if (p.irow == to.irow && p.icol == to.icol) {
+                        cache[key] = p.steps;
+                        break;
+                    }
+                    foreach (var (drow, dcol) in new[] { (-1, 0), (1, 0), (0, 1), (0, -1) }) {
+                        var (irowT, icolT) = (p.irow + drow, p.icol + dcol);
+                        if (irowT >= 0 && irowT < crow &&
+                            icolT >= 0 && icolT < ccol &&
+                            map[irowT][icolT] != '#' &&
+                            !seen.Contains((irowT, icolT))
+                        ) {
+                            q.Enqueue((p.steps + 1, irowT, icolT));
+                            seen.Add((irowT, icolT));
+                        }
+                    }
+                }
+            }
+
+            return cache[key];
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/25/illustration.jpeg b/2016/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/25/illustration.jpeg differ diff --git a/2016/25/index.html b/2016/25/index.html new file mode 100644 index 00000000..caf13641 --- /dev/null +++ b/2016/25/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/25 'Clock Signal'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/25

+

Clock Signal

+

in C#

+

+

by encse

+
+ +
+ +
+

You open the door and find yourself on the roof. The city sprawls away from you for miles and miles.

+

There's not much time now - it's already Christmas, but you're nowhere near the North Pole, much too far to deliver these stars to the sleigh in time.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day25;
+
+[ProblemName("Clock Signal")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        for (int a = 0; ; a++) {
+            var length = 0;
+            var expectedBit = 0;
+            foreach (var actualBit in Run(input, a).Take(100)) {
+                if (actualBit == expectedBit) {
+                    expectedBit = 1 - expectedBit;
+                    length++;
+                } else {
+                    break;
+                }
+            }
+            if (length == 100) {
+                return a;
+            }
+        }
+    }
+    
+    IEnumerable Run(string input, int a) {
+        var prg = Parse(input);
+        var regs = new Dictionary();
+        var ip = 0;
+        int getReg(string reg) {
+            return int.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        void setReg(string reg, int value) {
+            if (!int.TryParse(reg, out var _)) {
+                regs[reg] = value;
+            }
+        }
+
+        setReg("a", a);
+
+        while (ip < prg.Length) {
+            var stm = prg[ip];
+            switch (stm[0]) {
+                case "cpy":
+                    setReg(stm[2], getReg(stm[1]));
+                    ip++;
+                    break;
+                case "inc":
+                    setReg(stm[1], getReg(stm[1]) + 1);
+                    ip++;
+                    break;
+                case "out":
+                    yield return getReg(stm[1]);
+                    ip++;
+                    break;
+                case "dec":
+                    setReg(stm[1], getReg(stm[1]) - 1);
+                    ip++;
+                    break;
+                case "jnz":
+                    ip += getReg(stm[1]) != 0 ? getReg(stm[2]) : 1;
+                    break;
+                default:
+                    throw new Exception("Cannot parse " + string.Join(" ", stm));
+            }
+        }
+    }
+    
+    string[][] Parse(string input) =>
+        input.Split('\n').Select(line => line.Split(' ')).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/3/illustration.jpeg b/2016/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/3/illustration.jpeg differ diff --git a/2016/3/index.html b/2016/3/index.html new file mode 100644 index 00000000..0beb7fef --- /dev/null +++ b/2016/3/index.html @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/3 'Squares With Three Sides'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/3

+

Squares With Three Sides

+

in C#

+

+

by encse

+
+ +
+ +
+

Now that you can think clearly, you move deeper into the labyrinth of hallways and office furniture that makes up this part of Easter Bunny HQ. This must be a graphic design department; the walls are covered in specifications for triangles.

+

Or are they?

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day03;
+
+[ProblemName("Squares With Three Sides")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ValidTriangles(Parse(input));
+
+    public object PartTwo(string input) {
+        var tripplets = new List>();
+
+        foreach (var lineT in Transpose(Parse(input))) {
+            IEnumerable line = lineT;
+            while (line.Any()) {
+                tripplets.Add(line.Take(3));
+                line = line.Skip(3);
+            }
+        }
+
+        return ValidTriangles(tripplets);
+    }
+
+    int[][] Parse(string input) => (
+            from line in input.Split('\n')
+            select Regex.Matches(line, @"\d+").Select(m => int.Parse(m.Value)).ToArray()
+        ).ToArray();
+
+    int ValidTriangles(IEnumerable> tripplets) =>
+       tripplets.Count(tripplet => {
+           var nums = tripplet.OrderBy(x => x).ToArray();
+           return nums[0] + nums[1] > nums[2];
+       });
+
+    int[][] Transpose(int[][] src) {
+        var crowDst = src[0].Length;
+        var ccolDst = src.Length;
+        int[][] dst = new int[crowDst][];
+        for (int irowDst = 0; irowDst < crowDst; irowDst++) {
+            dst[irowDst] = new int[ccolDst];
+            for (int icolDst = 0; icolDst < ccolDst; icolDst++) {
+                dst[irowDst][icolDst] = src[icolDst][irowDst];
+            }
+        }
+        return dst;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/4/illustration.jpeg b/2016/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/4/illustration.jpeg differ diff --git a/2016/4/index.html b/2016/4/index.html new file mode 100644 index 00000000..1c0f0852 --- /dev/null +++ b/2016/4/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/4 'Security Through Obscurity'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/4

+

Security Through Obscurity

+

in C#

+

+

by encse

+
+ +
+ +
+

Finally, you come across an information kiosk with a list of rooms. Of course, the list is encrypted and full of decoy data, but the instructions to decode the list are barely hidden nearby. Better remove the decoy data first.

+

Each room consists of an encrypted name (lowercase letters separated by dashes) followed by a dash, a sector ID, and a checksum in square brackets.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day04;
+
+[ProblemName("Security Through Obscurity")]
+class Solution : Solver {
+
+    public object PartOne(string input) => (
+        from i in Parse(input)
+        let name = i.name.Replace("-", "")
+        let computedChecksum = string.Join("", (from ch in name group ch by ch into g orderby -g.Count(), g.Key select g.Key).Take(5))
+        where computedChecksum == i.checksum
+        select i.sectorid
+    ).Sum();
+
+    public object PartTwo(string input) => (
+        from i in Parse(input)
+        let name = string.Join("", from ch in i.name select ch == '-' ? ' ' : (char)('a' + (ch - 'a' + i.sectorid) % 26))
+        where name.Contains("northpole")
+        select i.sectorid
+    ).Single();
+
+    IEnumerable<(string name, int sectorid, string checksum)> Parse(string input){
+        var rx = new Regex(@"([^\d]+)\-(\d+)\[(.*)\]");
+        
+        return from line in input.Split('\n')
+            let m = rx.Match(line)
+            select (m.Groups[1].Value, int.Parse(m.Groups[2].Value), m.Groups[3].Value);
+         
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/5/illustration.jpeg b/2016/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/5/illustration.jpeg differ diff --git a/2016/5/index.html b/2016/5/index.html new file mode 100644 index 00000000..69c00e02 --- /dev/null +++ b/2016/5/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/5 'How About a Nice Game of Chess?'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/5

+

How About a Nice Game of Chess?

+

in C#

+

+

by encse

+
+ +
+ +
+

You are faced with a security door designed by Easter Bunny engineers that seem to have acquired most of their security knowledge by watching hacking movies.

+

The eight-character password for the door is generated one character at a time by finding the MD5 hash of some Door ID (your puzzle input) and an increasing integer index (starting with 0).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Y2016.Day05;
+
+[ProblemName("How About a Nice Game of Chess?")]
+class Solution : Solver
+{
+
+    public object PartOne(string input)
+    {
+       return string.Join("", Hashes(input).Select(hash => hash[5]).Take(8));
+    }
+
+    public object PartTwo(string input)
+    {
+        var res = new char[8];
+        var found = 0;
+        foreach (var hash in Hashes(input))
+        {
+            var idx = hash[5] - '0';
+            if (0 <= idx && idx < 8 && res[idx] == 0)
+            {
+                res[idx] = hash[6];
+                found++;
+                if (found == 8) { 
+                    break; 
+                }
+            }
+           
+        }
+        return string.Join("", res);
+    }
+
+    public IEnumerable Hashes(string input)
+    {
+
+        for (var i = 0; i < int.MaxValue; i++)
+        {
+            var q = new ConcurrentQueue<(int i, string hash)>();
+
+            Parallel.ForEach(
+                NumbersFrom(i),
+                () => MD5.Create(),
+                (i, state, md5) =>
+                {
+                    var hash = md5.ComputeHash(Encoding.ASCII.GetBytes(input + i));
+                    var hashString = string.Join("", hash.Select(x => x.ToString("x2")));
+
+                    if (hashString.StartsWith("00000"))
+                    {
+                        q.Enqueue((i, hashString));
+                        state.Stop();
+                    }
+                    return md5;
+                },
+                (_) => { }
+            );
+            var item = q.OrderBy(x => x.i).First();
+            i = item.i;
+            yield return item.hash;
+        }
+    }
+
+    IEnumerable NumbersFrom(int i)
+    {
+        for (;;) yield return i++;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/6/illustration.jpeg b/2016/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/6/illustration.jpeg differ diff --git a/2016/6/index.html b/2016/6/index.html new file mode 100644 index 00000000..8c670b17 --- /dev/null +++ b/2016/6/index.html @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/6 'Signals and Noise'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/6

+

Signals and Noise

+

in C#

+

+

by encse

+
+ +
+ +
+

Something is jamming your communications with Santa. Fortunately, your signal is only partially jammed, and protocol in situations like this is to switch to a simple repetition code to get the message through.

+

In this model, the same message is sent repeatedly. You've recorded the repeating message signal (your puzzle input), but the data seems quite corrupted - almost too badly to recover. Almost.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2016.Day06;
+
+[ProblemName("Signals and Noise")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Decode(input).mostFrequent;
+    public object PartTwo(string input) => Decode(input).leastFrequent;
+
+    (string mostFrequent, string leastFrequent) Decode(string input) {
+        var lines = input.Split('\n');
+        string mostFrequent = "";
+        string leastFrequent = "";
+        for (int i = 0; i < lines[0].Length; i++) {
+            var items = (from line in lines group line by line[i] into g orderby g.Count() select g.Key);
+            mostFrequent += items.Last();
+            leastFrequent += items.First();
+        }
+        return (mostFrequent: mostFrequent, leastFrequent: leastFrequent);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/7/illustration.jpeg b/2016/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/7/illustration.jpeg differ diff --git a/2016/7/index.html b/2016/7/index.html new file mode 100644 index 00000000..ebf1babe --- /dev/null +++ b/2016/7/index.html @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/7 'Internet Protocol Version 7'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/7

+

Internet Protocol Version 7

+

in C#

+

+

by encse

+
+ +
+ +
+

While snooping around the local network of EBHQ, you compile a list of IP addresses (they're IPv7, of course; IPv6 is much too limited). You'd like to figure out which IPs support TLS (transport-layer snooping).

+

An IP supports TLS if it has an Autonomous Bridge Bypass Annotation, or ABBA. An ABBA is any four-character sequence which consists of a pair of two different characters followed by the reverse of that pair, such as xyyx or abba. However, the IP also must not have an ABBA within any hypernet sequences, which are contained by square brackets.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2016.Day07;
+
+[ProblemName("Internet Protocol Version 7")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        input.Split('\n').Count(TLS);
+
+    public object PartTwo(string input) =>
+        input.Split('\n').Count(SSL);
+
+
+    bool TLS(string st) =>
+        Classify(st).Any(c => !c.f && Abba(c.st).Any()) &&
+        Classify(st).All(c => !c.f || !Abba(c.st).Any());
+
+    bool SSL(string st) => (
+        from c1 in Classify(st)
+        from c2 in Classify(st)
+        where !c1.f && c2.f
+        from aba in Aba(c1.st)
+        let bab = $"{aba[1]}{aba[0]}{aba[1]}"
+        where c2.st.Contains(bab)
+        select true
+    ).Any();
+
+    IEnumerable<(string st, bool f)> Classify(string st) {
+        var part = "";
+        for (var i = 0; i < st.Length; i++) {
+            var ch = st[i];
+            if (ch == '[') {
+                yield return (part, false);
+                part = "";
+            } else if (ch == ']') {
+                yield return (part, true);
+                part = "";
+            } else {
+                part += ch;
+            }
+        }
+        if (part != "")
+            yield return (part, false);
+    }
+
+    IEnumerable Abba(string st) {
+        for (var i = 0; i < st.Length - 3; i++) {
+            if(st[i + 2] == st[i + 1] && st[i] == st[i + 3] && st[i] != st[i + 2])
+                yield return st.Substring(i, 4);
+        }
+    }
+    
+    IEnumerable Aba(string st) {
+        for (var i = 0; i < st.Length -2; i++) {
+            if(st[i] == st[i + 2] && st[i] != st[i + 1])
+                yield return st.Substring(i, 3);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/8/illustration.jpeg b/2016/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/8/illustration.jpeg differ diff --git a/2016/8/index.html b/2016/8/index.html new file mode 100644 index 00000000..0e045bfb --- /dev/null +++ b/2016/8/index.html @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/8 'Two-Factor Authentication'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/8

+

Two-Factor Authentication

+

in C#

+

+

by encse

+
+ +
+ +
+

You come across a door implementing what you can only assume is an implementation of two-factor authentication after a long game of requirements telephone.

+

To get past the door, you first swipe a keycard (no problem; there was one on a nearby desk). Then, it displays a code on a little screen, and you type that code on a keypad. Then, presumably, the door unlocks.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day08;
+
+[ProblemName("Two-Factor Authentication")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var mtx = Execute(input);
+        return (
+            from irow in Enumerable.Range(0, mtx.GetLength(0))
+            from icol in Enumerable.Range(0, mtx.GetLength(1))
+            where mtx[irow, icol]
+            select 1
+        ).Count();
+    }
+
+    public object PartTwo(string input) {
+        var mtx = Execute(input);
+        var res = "";
+        foreach (var irow in Enumerable.Range(0, mtx.GetLength(0))) {
+            foreach (var icol in Enumerable.Range(0, mtx.GetLength(1))) {
+                res += mtx[irow, icol] ? "#" : " ";
+            }
+            res += "\n";
+        }
+        return res.Ocr();
+    }
+
+    bool[,] Execute(string input) {
+        var (crow, ccol) = (6, 50);
+        var mtx = new bool[crow, ccol];
+        foreach (var line in input.Split('\n')) {
+            if (Match(line, @"rect (\d+)x(\d+)", out var m)) {
+                var (ccolT, crowT) = (int.Parse(m[0]), int.Parse(m[1]));
+                for (var irow = 0; irow < crowT; irow++) {
+                    for (var icol = 0; icol < ccolT; icol++) {
+                        mtx[irow, icol] = true;
+                    }
+                }
+            } else if (Match(line, @"rotate row y=(\d+) by (\d+)", out m)) {
+                var (irow, d) = (int.Parse(m[0]), int.Parse(m[1]));
+                for (int i = 0; i < d; i++) {
+                    var t = mtx[irow, ccol - 1];
+                    for (var icol = ccol - 1; icol >= 1; icol--) {
+                        mtx[irow, icol] = mtx[irow, icol - 1];
+                    }
+                    mtx[irow, 0] = t;
+                }
+            } else if (Match(line, @"rotate column x=(\d+) by (\d+)", out m)) {
+                var (icol, d) = (int.Parse(m[0]), int.Parse(m[1]));
+                for (int i = 0; i < d; i++) {
+                    var t = mtx[crow - 1, icol];
+                    for (var irow = crow - 1; irow >= 1; irow--) {
+                        mtx[irow, icol] = mtx[irow - 1, icol];
+                    }
+                    mtx[0, icol] = t;
+                }
+            }
+        }
+        return mtx;
+    }
+
+    bool Match(string stm, string pattern, out string[] m) {
+        var match = Regex.Match(stm, pattern);
+        m = null;
+        if (match.Success) {
+            m = match.Groups.Cast().Skip(1).Select(g => g.Value).ToArray();
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2016/9/illustration.jpeg b/2016/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2016/9/illustration.jpeg differ diff --git a/2016/9/index.html b/2016/9/index.html new file mode 100644 index 00000000..03558eb1 --- /dev/null +++ b/2016/9/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2016/9 'Explosives in Cyberspace'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2016/9

+

Explosives in Cyberspace

+

in C#

+

+

by encse

+
+ +
+ +
+

Wandering around a secure area, you come across a datalink port to a new part of the network. After briefly scanning it for interesting files, you find one file in particular that catches your attention. It's compressed with an experimental format, but fortunately, the documentation for the format is nearby.

+

The format compresses a sequence of characters. Whitespace is ignored. To indicate that some sequence should be repeated, a marker is added to the file, like (10x2). To decompress this marker, take the subsequent 10 characters and repeat them 2 times. Then, continue reading the file after the repeated data. The marker itself is not included in the decompressed output.

+

Read the full puzzle.

+
+
using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2016.Day09;
+
+[ProblemName("Explosives in Cyberspace")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Expand(input, 0, input.Length, false);
+    }
+
+    public object PartTwo(string input) {
+        return Expand(input, 0, input.Length, true);
+    }
+
+    long Expand(string input, int i, int lim, bool recursive) {
+        var res = 0L;
+        while (i < lim) {
+            if (input[i] == '(') {
+                var j = input.IndexOf(')', i + 1);
+                var m = Regex.Match(input.Substring(i + 1, j - i - 1), @"(\d+)x(\d+)");
+                var length = int.Parse(m.Groups[1].Value);
+                var mul = int.Parse(m.Groups[2].Value);
+                res += recursive ? Expand(input, j + 1, j + length + 1, recursive) * mul : length * mul;
+                i = j + length + 1;
+            } else {
+                res++;
+                i++;
+            }
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/1/illustration.jpeg b/2017/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/1/illustration.jpeg differ diff --git a/2017/1/index.html b/2017/1/index.html new file mode 100644 index 00000000..3c34b71b --- /dev/null +++ b/2017/1/index.html @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/1 'Inverse Captcha'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/1

+

Inverse Captcha

+

in C#

+

+

by encse

+
+ +
+ +
+

The night before Christmas, one of Santa's Elves calls you in a panic. "The printer's broken! We can't print the Naughty or Nice List!" By the time you make it to sub-basement 17, there are only a few minutes until midnight. "We have a big problem," she says; "there must be almost fifty bugs in this system, but nothing else can print The List. Stand in this square, quick! There's no time to explain; if you can convince them to pay you in stars, you'll be able to--" She pulls a lever and the world goes blurry.

+

When your eyes can focus again, everything seems a lot more pixelated than before. She must have sent you inside the computer! You check the system clock: 25 milliseconds until midnight. With that much time, you should be able to collect all fifty stars by December 25th.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2017.Day01;
+
+[ProblemName("Inverse Captcha")]
+class Solution : Solver {
+
+    public object PartOne(string input) => InverseCaptcha(input, 1);
+
+    public object PartTwo(string input) => InverseCaptcha(input, input.Length / 2);
+
+    int InverseCaptcha(string input, int skip) {
+        return (
+            from i in Enumerable.Range(0, input.Length)
+            where input[i] == input[(i + skip) % input.Length]
+            select int.Parse(input[i].ToString())
+        ).Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/10/illustration.jpeg b/2017/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/10/illustration.jpeg differ diff --git a/2017/10/index.html b/2017/10/index.html new file mode 100644 index 00000000..a8e435ab --- /dev/null +++ b/2017/10/index.html @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/10 'Knot Hash'' in C# by encse + + + + + + + + + + + + + + +
+
+
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 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!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/11/illustration.jpeg b/2017/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/11/illustration.jpeg differ diff --git a/2017/11/index.html b/2017/11/index.html new file mode 100644 index 00000000..98bcafbd --- /dev/null +++ b/2017/11/index.html @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/11 'Hex Ed'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/11

+

Hex Ed

+

in C#

+

+

by encse

+
+ +
+ +
+

Crossing the bridge, you've barely reached the other side of the stream when a program comes up to you, clearly in distress. "It's my child process," she says, "he's gotten lost in an infinite grid!"

+

Fortunately for her, you have plenty of experience with infinite grids.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day11;
+
+[ProblemName("Hex Ed")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Distances(input).Last();
+
+    public object PartTwo(string input) => Distances(input).Max();
+
+    IEnumerable Distances(string input) => 
+        from w in Wander(input) select (Math.Abs(w.x) + Math.Abs(w.y) + Math.Abs(w.z))/2;
+
+    IEnumerable<(int x, int y, int z)> Wander(string input) {
+        var (x, y, z) = (0, 0, 0);
+        foreach (var dir in input.Split(',')) {
+            switch (dir) {
+                case "n":  (x, y, z) = (x + 0, y + 1, z - 1); break;
+                case "ne": (x, y, z) = (x + 1, y + 0, z - 1); break;
+                case "se": (x, y, z) = (x + 1, y - 1, z + 0); break;
+                case "s":  (x, y, z) = (x + 0, y - 1, z + 1); break;
+                case "sw": (x, y, z) = (x - 1, y + 0, z + 1); break;
+                case "nw": (x, y, z) = (x - 1, y + 1, z + 0); break;
+                default: throw new ArgumentException(dir);
+            }
+            yield return (x, y, z);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/12/illustration.jpeg b/2017/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/12/illustration.jpeg differ diff --git a/2017/12/index.html b/2017/12/index.html new file mode 100644 index 00000000..a940504c --- /dev/null +++ b/2017/12/index.html @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/12 'Digital Plumber'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/12

+

Digital Plumber

+

in C#

+

+

by encse

+
+ +
+ +
+

Walking along the memory banks of the stream, you find a small village that is experiencing a little confusion: some programs can't communicate with each other.

+

Programs in this village communicate using a fixed system of pipes. Messages are passed between programs using these pipes, but most programs aren't connected to each other directly. Instead, programs pass messages between each other until the message reaches the intended recipient.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day12;
+
+class Node {
+    public string Id;
+    public List Neighbours;
+}
+
+[ProblemName("Digital Plumber")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetPartitions(input).Single(x => x.Contains("0")).Count();
+    public object PartTwo(string input) => GetPartitions(input).Count();
+
+    IEnumerable> GetPartitions(string input) {
+        var nodes = Parse(input);
+        var parent = new Dictionary();
+
+        string getRoot(string id) {
+            var root = id;
+            while (parent.ContainsKey(root)) {
+                root = parent[root];
+            }
+            return root;
+        }
+
+        foreach (var nodeA in nodes) {
+            var rootA = getRoot(nodeA.Id);
+            foreach (var nodeB in nodeA.Neighbours) {
+                var rootB = getRoot(nodeB);
+                if (rootB != rootA) {
+                    parent[rootB] = rootA;
+                }
+            }
+        }
+
+        return
+            from node in nodes
+            let root = getRoot(node.Id)
+            group node.Id by root into partitions
+            select new HashSet(partitions.ToArray());
+        
+    }
+
+    List Parse(string input) {
+        return (
+            from line in input.Split('\n')
+            let parts = Regex.Split(line, " <-> ")
+            select new Node() {
+                    Id = parts[0],
+                    Neighbours = new List(Regex.Split(parts[1], ", "))
+                }
+        ).ToList();
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/13/illustration.jpeg b/2017/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/13/illustration.jpeg differ diff --git a/2017/13/index.html b/2017/13/index.html new file mode 100644 index 00000000..6575f800 --- /dev/null +++ b/2017/13/index.html @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/13 'Packet Scanners'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/13

+

Packet Scanners

+

in C#

+

+

by encse

+
+ +
+ +
+

You need to cross a vast firewall. The firewall consists of several layers, each with a security scanner that moves back and forth across the layer. To succeed, you must not be detected by a scanner.

+

By studying the firewall briefly, you are able to record (in your puzzle input) the depth of each layer and the range of the scanning area for the scanner within it, written as depth: range. Each layer has a thickness of exactly 1. A layer at depth 0 begins immediately inside the firewall; a layer at depth 1 would start immediately after that.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day13;
+
+class Layers : List<(int depth, int range)> {
+    public Layers(IEnumerable<(int depth, int range)> layers) : base(layers) {
+    }
+}
+
+[ProblemName("Packet Scanners")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Severities(Parse(input), 0).Sum();
+
+    public object PartTwo(string input) {
+        var layers = Parse(input);
+        return Enumerable
+            .Range(0, int.MaxValue)
+            .First(n => !Severities(layers, n).Any());
+    }
+
+    Layers Parse(string input) =>
+        new Layers(
+            from line in input.Split('\n')
+            let parts = Regex.Split(line, ": ").Select(int.Parse).ToArray()
+            select (parts[0], parts[1])
+        );
+
+    IEnumerable Severities(Layers layers, int t) {
+        var packetPos = 0;
+        foreach (var layer in layers) {
+            t += layer.depth - packetPos;
+            packetPos = layer.depth;
+            var scannerPos = t % (2 * layer.range - 2);
+            if (scannerPos == 0) {
+                yield return layer.depth * layer.range;
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/14/illustration.jpeg b/2017/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/14/illustration.jpeg differ diff --git a/2017/14/index.html b/2017/14/index.html new file mode 100644 index 00000000..9999909e --- /dev/null +++ b/2017/14/index.html @@ -0,0 +1,381 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/14 'Disk Defragmentation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/14

+

Disk Defragmentation

+

in C#

+

+

by encse

+
+ +
+ +
+

Suddenly, a scheduled job activates the system's disk defragmenter. Were the situation different, you might sit and watch it for a while, but today, you just don't have that kind of time. It's soaking up valuable system resources that are needed elsewhere, and so the only option is to help it finish its task as soon as possible.

+

The disk in question consists of a 128x128 grid; each square of the grid is either free or used. On this disk, the state of the grid is tracked by the bits in a sequence of knot hashes.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day14;
+
+[ProblemName("Disk Defragmentation")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Extract(input).Select(row => row.Count(ch => ch == '#')).Sum();
+
+    public object PartTwo(string input) {
+        var mtx = Extract(input).Select(row => row.ToCharArray()).ToArray();
+        var regions = 0;
+        for (int irow = 0; irow < mtx.Count(); irow++) {
+            for (int icol = 0; icol < mtx[0].Count(); icol++) {
+                if (mtx[irow][icol] == '#') {
+                    regions++;
+                    Fill(mtx, (irow, icol));
+                }
+            }
+        }
+        return regions;
+    }
+
+    void Fill(char[][] mtx, (int, int) startCell) {
+        var q = new Queue<(int irow, int icol)>();
+        var ccol = mtx[0].Count();
+        var crow = mtx.Count();
+        q.Enqueue(startCell);
+
+        while (q.Any()) {
+            var (irowCurrent, icolCurrent) = q.Dequeue();
+            mtx[irowCurrent][icolCurrent] = ' ';
+
+            var neighbourCells =
+                from drow in new[] { -1, 0, 1 }
+                from dcol in new[] { -1, 0, 1 }
+                where Math.Abs(drow) + Math.Abs(dcol) == 1
+
+                let icolNeighbour = icolCurrent + dcol
+                let irowNeighbour = irowCurrent + drow
+
+                where icolNeighbour >= 0 &&
+                    icolNeighbour < ccol &&
+                    irowNeighbour >= 0 &&
+                    irowNeighbour < crow &&
+                    mtx[irowNeighbour][icolNeighbour] == '#'
+
+                select (irowNeighbour, icolNeighbour);
+
+            foreach (var neighbourCell in neighbourCells) {
+                q.Enqueue(neighbourCell);
+            }
+        }
+    }
+
+    IEnumerable Extract(string input) {
+        for (var irow = 0; irow < 128; irow++) {
+            var row = "";
+            foreach (var n in KnotHash(input + "-" + irow)) {
+                var m = n;
+                for (var bit = 0; bit < 8; bit++) {
+                    if ((m & (1 << (7 - bit))) != 0) {
+                        row += "#";
+                    } else {
+                        row += ".";
+                    }
+                }
+            }
+            yield return row;
+        }
+    }
+
+    int[] KnotHash(string input) {
+        var suffix = new[] { 17, 31, 73, 47, 23 };
+        var chars = input.ToCharArray().Select(b => (int)b).Concat(suffix);
+        var output = Enumerable.Range(0, 256).ToArray();
+
+        var current = 0;
+        var skip = 0;
+        for (var round = 0; round < 64; round++) {
+            foreach (var len in chars) {
+                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++;
+            }
+        }
+        var hash = output;
+        return (
+            from blockIdx in Enumerable.Range(0, 16)
+            let block = hash.Skip(16 * blockIdx).Take(16)
+            select block.Aggregate(0, (acc, ch) => acc ^ ch)
+        ).ToArray();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/15/illustration.jpeg b/2017/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/15/illustration.jpeg differ diff --git a/2017/15/index.html b/2017/15/index.html new file mode 100644 index 00000000..ba3e214b --- /dev/null +++ b/2017/15/index.html @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/15 'Dueling Generators'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/15

+

Dueling Generators

+

in C#

+

+

by encse

+
+ +
+ +
+

Here, you encounter a pair of dueling generators. The generators, called generator A and generator B, are trying to agree on a sequence of numbers. However, one of them is malfunctioning, and so the sequences don't always match.

+

As they do this, a judge waits for each of them to generate its next value, compares the lowest 16 bits of both values, and keeps track of the number of times those parts of the values match.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day15;
+
+[ProblemName("Dueling Generators")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        MatchCount(Combine(ParseGenerators(input)).Take(40000000));
+
+    public object PartTwo(string input) {
+        var generators = ParseGenerators(input);
+        return MatchCount(Combine((generators.a.Where(a => (a & 3) == 0), generators.b.Where(a => (a & 7) == 0))).Take(5000000));
+    }
+
+    IEnumerable<(long, long)> Combine((IEnumerable a, IEnumerable b) items) =>
+        Enumerable.Zip(items.a, items.b, (a, b) => (a, b));
+
+    int MatchCount(IEnumerable<(long a, long b)> items) =>
+        items.Count(item => (item.a & 0xffff) == (item.b & 0xffff));
+
+    (IEnumerable a, IEnumerable b) ParseGenerators(string input) {
+        var lines = input.Split('\n');
+        var startA = int.Parse(lines[0].Substring("Generator A starts with ".Length));
+        var startB = int.Parse(lines[1].Substring("Generator B starts with ".Length));
+
+        return (Generator(startA, 16807), Generator(startB, 48271));
+    }
+
+    IEnumerable Generator(int start, int mul) {
+        var mod = 2147483647;
+
+        long state = start;
+        while (true) {
+            state = (state * mul) % mod;
+            yield return state;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/16/illustration.jpeg b/2017/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/16/illustration.jpeg differ diff --git a/2017/16/index.html b/2017/16/index.html new file mode 100644 index 00000000..56e7a71b --- /dev/null +++ b/2017/16/index.html @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/16 'Permutation Promenade'' in C# by encse + + + + + + + + + + + + + + +
+
+
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 step, string startState) {
+        var state = startState;
+        for (int i = 0; ; i++) {
+            state = step(state);
+            if (startState == state) {
+                return i + 1;
+            }
+        }
+    }
+
+    Func 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> ParseMove(string stm, string pattern, Func, List>> a) {
+        var match = Regex.Match(stm , pattern);
+        if (match.Success) {
+            return a(match.Groups.Cast().Skip(1).Select(g => g.Value).ToArray());
+        } else {
+            return null;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/17/illustration.jpeg b/2017/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/17/illustration.jpeg differ diff --git a/2017/17/index.html b/2017/17/index.html new file mode 100644 index 00000000..27325547 --- /dev/null +++ b/2017/17/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/17 'Spinlock'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/17

+

Spinlock

+

in C#

+

+

by encse

+
+ +
+ +
+

Suddenly, whirling in the distance, you notice what looks like a massive, pixelated hurricane: a deadly spinlock. This spinlock isn't just consuming computing power, but memory, too; vast, digital mountains are being ripped from the ground and consumed by the vortex.

+

If you don't move quickly, fixing that printer will be the least of your problems.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+
+namespace AdventOfCode.Y2017.Day17;
+
+[ProblemName("Spinlock")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var step = int.Parse(input);
+        var nums = new List() { 0 };
+        var pos = 0;
+        for (int i = 1; i < 2018; i++) {
+            pos = (pos + step) % nums.Count + 1;
+            nums.Insert(pos, i);
+        }
+        return nums[(pos + 1) % nums.Count];
+    }
+
+    public object PartTwo(string input) {
+        var step = int.Parse(input);
+        var pos = 0;
+        var numsCount = 1;
+        var res = 0;
+        for (int i = 1; i < 50000001; i++) {
+            pos = (pos + step) % numsCount + 1;
+            if (pos == 1) {
+                res = i;
+            }
+            numsCount++;
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/18/illustration.jpeg b/2017/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/18/illustration.jpeg differ diff --git a/2017/18/index.html b/2017/18/index.html new file mode 100644 index 00000000..173cb5a2 --- /dev/null +++ b/2017/18/index.html @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/18 'Duet'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/18

+

Duet

+

in C#

+

+

by encse

+
+ +
+ +
+

You discover a tablet containing some strange assembly code labeled simply "Duet". Rather than bother the sound card with it, you decide to run the code yourself. Unfortunately, you don't see any documentation, so you're left to figure out what the instructions mean on your own.

+

It seems like the assembly is meant to operate on a set of registers that are each named with a single letter and that can each hold a single integer. You suppose each register should start with a value of 0.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day18;
+
+[ProblemName("Duet")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        new Machine1()
+            .Execute(input)
+            .First(received => received != null).Value;
+
+    public object PartTwo(string input) {
+        var p0Input = new Queue();
+        var p1Input = new Queue();
+
+        return Enumerable
+            .Zip(
+                new Machine2(0, p0Input, p1Input).Execute(input), 
+                new Machine2(1, p1Input, p0Input).Execute(input), 
+                (state0, state1) => (state0: state0, state1: state1))
+            .First(x => !x.state0.running && !x.state1.running)
+            .state1.valueSent;
+    }
+}
+
+abstract class Machine {
+    private Dictionary regs = new Dictionary();
+
+    protected bool running;
+    protected int ip = 0;
+    protected long this[string reg] {
+        get {
+            return long.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        set {
+            regs[reg] = value;
+        }
+    }
+
+    public IEnumerable Execute(string input) {
+        var prog = input.Split('\n').ToArray();
+
+        while (ip >= 0 && ip < prog.Length) {
+            running = true;
+            var line = prog[ip];
+            var parts = line.Split(' ');
+            switch (parts[0]) {
+                case "snd": snd(parts[1]); break;
+                case "rcv": rcv(parts[1]); break;
+                case "set": set(parts[1], parts[2]); break;
+                case "add": add(parts[1], parts[2]); break;
+                case "mul": mul(parts[1], parts[2]); break;
+                case "mod": mod(parts[1], parts[2]); break;
+                case "jgz": jgz(parts[1], parts[2]); break;
+                default: throw new Exception("Cannot parse " + line);
+            }
+            yield return State();
+        }
+
+        running = false;
+        yield return State();
+    }
+
+    protected abstract TState State();
+
+    protected abstract void snd(string reg);
+    
+    protected abstract void rcv(string reg);
+
+    protected void set(string reg0, string reg1) {
+        this[reg0] = this[reg1];
+        ip++;
+    }
+
+    protected void add(string reg0, string reg1) {
+        this[reg0] += this[reg1];
+        ip++;
+    }
+
+    protected void mul(string reg0, string reg1) {
+        this[reg0] *= this[reg1];
+        ip++;
+    }
+
+    protected void mod(string reg0, string reg1) {
+        this[reg0] %= this[reg1];
+        ip++;
+    }
+
+    protected void jgz(string reg0, string reg1) {
+        ip += this[reg0] > 0 ? (int)this[reg1] : 1;
+    }
+}
+
+class Machine1 : Machine {
+    private long? sent = null;
+    private long? received = null;
+
+    protected override long? State() { 
+        return received; 
+    }
+
+    protected override void snd(string reg) {
+        sent = this[reg];
+        ip++;
+    }
+
+    protected override void rcv(string reg) {
+        if (this[reg] != 0) {
+            received = sent;
+        }
+        ip++;
+    }
+
+}
+
+class Machine2 : Machine<(bool running, int valueSent)> {
+    private int valueSent = 0;
+    private Queue qIn;
+    private Queue qOut;
+
+    public Machine2(long p, Queue qIn, Queue qOut) {
+        this["p"] = p;
+        this.qIn = qIn;
+        this.qOut = qOut;
+    }
+
+    protected override (bool running, int valueSent) State() { 
+        return (running: running, valueSent: valueSent); 
+    }  
+
+    protected override void snd(string reg) {
+        qOut.Enqueue(this[reg]);
+        valueSent++;
+        ip++;
+    }
+
+    protected override void rcv(string reg) {
+        if (qIn.Any()) {
+            this[reg] = qIn.Dequeue();
+            ip++;
+        } else {
+            running = false;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/19/illustration.jpeg b/2017/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/19/illustration.jpeg differ diff --git a/2017/19/index.html b/2017/19/index.html new file mode 100644 index 00000000..5efbff27 --- /dev/null +++ b/2017/19/index.html @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/19 'A Series of Tubes'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/19

+

A Series of Tubes

+

in C#

+

+

by encse

+
+ +
+ +
+

Somehow, a network packet got lost and ended up here. It's trying to follow a routing diagram (your puzzle input), but it's confused about where to go.

+

Its starting point is just off the top of the diagram. Lines (drawn with |, -, and +) show the path it needs to take, starting by going down onto the only line connected to the top of the diagram. It needs to follow this path until it reaches the end (located somewhere within the diagram) and stop there.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2017.Day19;
+
+[ProblemName("A Series of Tubes")]
+class Solution : Solver {
+
+    public object PartOne(string input) => FollowPath(input).msg;
+
+    public object PartTwo(string input) => FollowPath(input).steps;
+
+    (string msg, int steps) FollowPath(string input){
+        var map = input.Split('\n');
+        var (ccol, crow) = (map[0].Length, map.Length);
+        var (icol, irow) = (map[0].IndexOf('|'), 0);
+        var (dcol, drow) = (0, 1);
+
+        var msg = "";
+        var steps = 0;
+
+        while (true) {
+            irow += drow;
+            icol += dcol;
+            steps++;
+
+            if (icol < 0 || icol >= ccol || irow < 0 || irow >= crow || map[irow][icol] == ' ') {
+                break;
+            }
+
+            switch (map[irow][icol]) {
+                case '+':
+                    (dcol, drow) = (
+                            from q in new[] { (drow: dcol, dcol: -drow), (drow: -dcol, dcol: drow)}
+                            let icolT = icol + q.dcol
+                            let irowT = irow + q.drow
+                            where icolT >= 0 && icolT < ccol && irowT >= 0 && irowT < crow && map[irowT][icolT] != ' '
+                            select (q.dcol, q.drow)
+                        ).Single();
+                    break;
+                case char ch when (ch >= 'A' && ch <= 'Z'):
+                    msg += ch;
+                    break;
+            }
+        }
+        return (msg, steps);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/2/illustration.jpeg b/2017/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/2/illustration.jpeg differ diff --git a/2017/2/index.html b/2017/2/index.html new file mode 100644 index 00000000..0eba1692 --- /dev/null +++ b/2017/2/index.html @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/2 'Corruption Checksum'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/2

+

Corruption Checksum

+

in C#

+

+

by encse

+
+ +
+ +
+

As you walk through the door, a glowing humanoid shape yells in your direction. "You there! Your state appears to be idle. Come help us repair the corruption in this spreadsheet - if we take another millisecond, we'll have to display an hourglass cursor!"

+

The spreadsheet consists of rows of apparently-random numbers. To make sure the recovery process is on the right track, they need you to calculate the spreadsheet's checksum. For each row, determine the difference between the largest value and the smallest value; the checksum is the sum of all of these differences.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2017.Day02;
+
+[ProblemName("Corruption Checksum")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return (
+            from line in input.Split('\n')
+            let numbers = line.Split('\t').Select(int.Parse)
+            select numbers.Max() - numbers.Min()
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+        return (
+            from line in input.Split('\n')
+            let numbers = line.Split('\t').Select(int.Parse)
+            from a in numbers
+            from b in numbers
+            where a > b && a % b == 0
+            select a / b
+        ).Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/20/illustration.jpeg b/2017/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/20/illustration.jpeg differ diff --git a/2017/20/index.html b/2017/20/index.html new file mode 100644 index 00000000..5f92ce55 --- /dev/null +++ b/2017/20/index.html @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/20 'Particle Swarm'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/20

+

Particle Swarm

+

in C#

+

+

by encse

+
+ +
+ +
+

Suddenly, the GPU contacts you, asking for help. Someone has asked it to simulate too many particles, and it won't be able to finish them all in time to render the next frame at this rate.

+

It transmits to you a buffer (your puzzle input) listing each particle in order (starting with particle 0, then particle 1, particle 2, and so on). For each particle, it provides the X, Y, and Z coordinates for the particle's position (p), velocity (v), and acceleration (a), each in the format <X,Y,Z>.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day20;
+
+[ProblemName("Particle Swarm")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var particles = Parse(input);
+        return (
+            from particle in particles
+            orderby particle.acc.Len(), particle.vel.Len(), particle.pos.Len()
+            select particle
+        ).First().i;
+    }
+
+    public object PartTwo(string input) {
+        var particles = Parse(input);
+        var collisionTimes = (
+            from p1 in particles
+            from p2 in particles
+            where p1.i != p2.i
+            from collisionTime in p1.CollisionTime(p2)
+            select collisionTime
+        ).ToArray();
+        var T = collisionTimes.Max();
+
+        var t = 0;
+        while (t <= T) {
+            var particlesByPos = (from particle in particles orderby particle.pos.x, particle.pos.y, particle.pos.z select particle).ToArray();
+            
+            var particlePrev = particlesByPos[0];
+
+            for (int i = 1; i < particlesByPos.Length; i++) {
+                var particle = particlesByPos[i];
+                if (particlePrev.pos.x == particle.pos.x && particlePrev.pos.y == particle.pos.y && particlePrev.pos.z == particle.pos.z) {
+                    particlePrev.destroyed = true;
+                    particle.destroyed = true;
+                }
+                particlePrev = particle;
+            }
+
+            if (particles.Any(p => p.destroyed)) {
+                particles = particles.Where(particle => !particle.destroyed).ToList();
+            }
+
+            foreach (var particle in particles) {
+                particle.Step();
+            }
+
+            t++;
+        }
+        return particles.Count;
+    }
+
+
+    List Parse(string input) {
+        var lines = input.Split('\n');
+        return (
+             from q in Enumerable.Zip(lines, Enumerable.Range(0, int.MaxValue), (line, i) => (i: i, line: line))
+             let nums = Regex.Matches(q.line, "-?[0-9]+").Select(m => int.Parse(m.Value)).ToArray()
+             let p = new Point(nums[0], nums[1], nums[2])
+             let v = new Point(nums[3], nums[4], nums[5])
+             let a = new Point(nums[6], nums[7], nums[8])
+             select new Particle(q.i, p, v, a))
+         .ToList();
+    }
+}
+
+class Point {
+    public int x;
+    public int y;
+    public int z;
+
+    public int Len() => Math.Abs(x) + Math.Abs(y) + Math.Abs(z);
+
+    public Point(int x, int y, int z) {
+        this.x = x;
+        this.y = y;
+        this.z = z;
+    }
+}
+
+class Particle {
+    public int i;
+    public Point pos;
+    public Point vel;
+    public Point acc;
+
+    public bool destroyed = false;
+
+    public Particle(int i, Point pos, Point vel, Point acc) {
+        this.i = i;
+        this.pos = pos;
+        this.vel = vel;
+        this.acc = acc;
+    }
+
+    public void Step() {
+        (vel.x, vel.y, vel.z) = (vel.x + acc.x, vel.y + acc.y, vel.z + acc.z);
+        (pos.x, pos.y, pos.z) = (pos.x + vel.x, pos.y + vel.y, pos.z + vel.z);
+    }
+
+    public IEnumerable CollisionTime(Particle particle) {
+        return
+            from tx in CollisionTimeOnAxis(particle.acc.x - acc.x, particle.vel.x - vel.x, particle.pos.x - pos.x)
+            from ty in CollisionTimeOnAxis(particle.acc.y - acc.y, particle.vel.y - vel.y, particle.pos.y - pos.y)
+            from tz in CollisionTimeOnAxis(particle.acc.z - acc.x, particle.vel.z - vel.z, particle.pos.z - pos.z)
+            where tx == ty && ty == tz
+            select (tx);
+    }
+
+    private IEnumerable CollisionTimeOnAxis(int da, int dv, int dp) =>
+        SolveIntEq(da / 2, dv, dp);
+
+    private IEnumerable SolveIntEq(int a, int b, int c) {
+        if (a == 0) {
+            if (b == 0) {
+                if (c == 0) {
+                    yield return 0;
+                }
+            } else {
+                yield return -c / b;
+            }
+        } else {
+            var d = b * b - 4 * a * c;
+            if (d == 0) {
+                yield return -b / (2 * a);
+            } else if (d > 0) {
+                var ds = Math.Sqrt(d);
+                if (ds * ds == d) {
+                    yield return (int)((-b + ds) / (2 * a));
+                    yield return (int)((-b - ds) / (2 * a));
+                }
+
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/21/illustration.jpeg b/2017/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/21/illustration.jpeg differ diff --git a/2017/21/index.html b/2017/21/index.html new file mode 100644 index 00000000..372e2557 --- /dev/null +++ b/2017/21/index.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/21 'Fractal Art'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/21

+

Fractal Art

+

in C#

+

+

by encse

+
+ +
+ +
+

You find a program trying to generate some art. It uses a strange process that involves repeatedly enhancing the detail of an image through a set of rules.

+

The image consists of a two-dimensional square grid of pixels that are either on (#) or off (.). The program always begins with this pattern:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day21;
+
+[ProblemName("Fractal Art")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Iterate(input, 5);
+
+    public object PartTwo(string input) => Iterate(input, 18);
+
+    int Iterate(string input, int iterations) {
+        var mtx = Mtx.FromString(".#./..#/###");
+        var ruleset = new RuleSet(input);
+        for (var i = 0; i < iterations; i++) {
+            mtx = ruleset.Apply(mtx);
+        }
+        return mtx.Count();
+    }
+}
+
+class RuleSet {
+    private Dictionary rules2;
+    private Dictionary rules3;
+
+    public RuleSet(string input) {
+        rules2 = new Dictionary();
+        rules3 = new Dictionary();
+
+        foreach (var line in input.Split('\n')) {
+            var parts = Regex.Split(line, " => ");
+            var left = parts[0];
+            var right = parts[1];
+            var rules =
+                left.Length == 5 ? rules2 :
+                left.Length == 11 ? rules3 :
+                throw new Exception();
+            foreach (var mtx in Variations(Mtx.FromString(left))) {
+                rules[mtx.CodeNumber] = Mtx.FromString(right);
+            }
+        }
+    }
+
+    public Mtx Apply(Mtx mtx) {
+        return Mtx.Join((
+            from child in mtx.Split()
+            select
+                child.Size == 2 ? rules2[child.CodeNumber] :
+                child.Size == 3 ? rules3[child.CodeNumber] :
+                null
+        ).ToArray());
+    }
+
+    IEnumerable Variations(Mtx mtx) {
+        for (int j = 0; j < 2; j++) {
+            for (int i = 0; i < 4; i++) {
+                yield return mtx;
+                mtx = mtx.Rotate();
+            }
+            mtx = mtx.Flip();
+        }
+    }
+}
+
+class Mtx {
+    private bool[] flags;
+
+    public int Size {
+        get;
+        private set;
+    }
+
+    public int CodeNumber {
+        get {
+            if (Size != 2 && Size != 3) {
+                throw new ArgumentException();
+            }
+            var i = 0;
+            for (int irow = 0; irow < Size; irow++) {
+                for (int icol = 0; icol < Size; icol++) {
+                    if (this[irow, icol]) {
+                        i |= (1 << (irow * Size + icol));
+                    }
+                }
+            }
+            return i;
+        }
+    }
+
+    public Mtx(int size) {
+        this.flags = new bool[size * size];
+        this.Size = size;
+    }
+
+    public static Mtx FromString(string st) {
+        st = st.Replace("/", "");
+        var size = (int)Math.Sqrt(st.Length);
+        var res = new Mtx(size);
+        for (int i = 0; i < st.Length; i++) {
+            res[i / size, i % size] = st[i] == '#';
+        }
+        return res;
+    }
+
+    public static Mtx Join(Mtx[] rgmtx) {
+        var mtxPerRow = (int)Math.Sqrt(rgmtx.Length);
+        var res = new Mtx(mtxPerRow * rgmtx[0].Size);
+        for (int imtx = 0; imtx < rgmtx.Length; imtx++) {
+            var mtx = rgmtx[imtx];
+            for (int irow = 0; irow < mtx.Size; irow++) {
+                for (int icol = 0; icol < mtx.Size; icol++) {
+                    var irowRes = (imtx / mtxPerRow) * mtx.Size + irow;
+                    var icolRes = (imtx % mtxPerRow) * mtx.Size + icol;
+                    res[irowRes, icolRes] = mtx[irow, icol];
+                }
+            }
+        }
+
+        return res;
+    }
+
+    public IEnumerable Split() {
+
+        var blockSize =
+            Size % 2 == 0 ? 2 :
+            Size % 3 == 0 ? 3 :
+            throw new Exception();
+
+        for (int irow = 0; irow < Size; irow += blockSize) {
+            for (int icol = 0; icol < Size; icol += blockSize) {
+                var mtx = new Mtx(blockSize);
+                for (int drow = 0; drow < blockSize; drow++) {
+                    for (int dcol = 0; dcol < blockSize; dcol++) {
+                        mtx[drow, dcol] = this[irow + drow, icol + dcol];
+                    }
+                }
+                yield return mtx;
+            }
+        }
+    }
+    
+    public Mtx Flip() {
+        var res = new Mtx(this.Size);
+        for (int irow = 0; irow < Size; irow++) {
+            for (int icol = 0; icol < Size; icol++) {
+                res[irow, Size - icol - 1] = this[irow, icol];
+            }
+        }
+        return res;
+    }
+
+    public Mtx Rotate() {
+        var res = new Mtx(this.Size);
+        for (int i = 0; i < Size; i++) {
+            for (int j = 0; j < Size; j++) {
+                res[i, j] = this[j, Size - i - 1];
+            }
+        }
+        return res;
+    }
+
+    public int Count() {
+        var count = 0;
+        for (int irow = 0; irow < Size; irow++) {
+            for (int icol = 0; icol < Size; icol++) {
+                if (this[irow, icol]) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    public override string ToString() {
+        var sb = new StringBuilder();
+        for (int irow = 0; irow < Size; irow++) {
+            for (int icol = 0; icol < Size; icol++) {
+                sb.Append(this[irow, icol] ? "#" : ".");
+            }
+            sb.AppendLine();
+        }
+        return sb.ToString();
+    }
+
+    private bool this[int irow, int icol] {
+        get {
+            return flags[(Size * irow) + icol];
+        }
+        set {
+            flags[(Size * irow) + icol] = value;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/22/illustration.jpeg b/2017/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/22/illustration.jpeg differ diff --git a/2017/22/index.html b/2017/22/index.html new file mode 100644 index 00000000..62084f9e --- /dev/null +++ b/2017/22/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/22 'Sporifica Virus'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/22

+

Sporifica Virus

+

in C#

+

+

by encse

+
+ +
+ +
+

Diagnostics indicate that the local grid computing cluster has been contaminated with the Sporifica Virus. The grid computing cluster is a seemingly-infinite two-dimensional grid of compute nodes. Each node is either clean or infected by the virus.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2017.Day22;
+
+enum State {
+    Clean,
+    Weakened,
+    Infected,
+    Flagged
+}
+
+[ProblemName("Sporifica Virus")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        Iterate(input, 10000,
+            (state, drow, dcol) =>
+                state switch {
+                    State.Clean => (State.Infected, -dcol, drow),
+                    State.Infected => (State.Clean, dcol, -drow),
+                    _ => throw new ArgumentException()
+                }
+        );
+
+    public object PartTwo(string input) =>
+        Iterate(input, 10000000,
+            (state, drow, dcol) =>
+                state switch {
+                    State.Clean => (State.Weakened, -dcol, drow),
+                    State.Weakened => (State.Infected, drow, dcol),
+                    State.Infected => (State.Flagged, dcol, -drow),
+                    State.Flagged => (State.Clean, -drow, -dcol),
+                    _ => throw new ArgumentException()
+                }
+        );
+
+
+    int Iterate(string input, int iterations, Func update) {
+        var lines = input.Split('\n');
+        var crow = lines.Length;
+        var ccol = lines[0].Length;
+        var cells = new Dictionary<(int irow, int icol), State>();
+        for (int irowT = 0; irowT < crow; irowT++) {
+            for (int icolT = 0; icolT < ccol; icolT++) {
+                if (lines[irowT][icolT] == '#') {
+                    cells.Add((irowT, icolT), State.Infected);
+                }
+            }
+        }
+        var (irow, icol) = (crow / 2, ccol / 2);
+        var (drow, dcol) = (-1, 0);
+        var infections = 0;
+        for (int i = 0; i < iterations; i++) {
+            var state = cells.TryGetValue((irow, icol), out var s) ? s : State.Clean;
+
+            (state, drow, dcol) = update(state, drow, dcol);
+
+            if (state == State.Infected) {
+                infections++;
+            }
+            if (state == State.Clean) {
+                cells.Remove((irow, icol));
+            } else {
+                cells[(irow, icol)] = state;
+            }
+            (irow, icol) = (irow + drow, icol + dcol);
+        }
+        return infections;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/23/illustration.jpeg b/2017/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/23/illustration.jpeg differ diff --git a/2017/23/index.html b/2017/23/index.html new file mode 100644 index 00000000..ef2d0521 --- /dev/null +++ b/2017/23/index.html @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/23 'Coprocessor Conflagration'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/23

+

Coprocessor Conflagration

+

in C#

+

+

by encse

+
+ +
+ +
+

You decide to head directly to the CPU and fix the printer from there. As you get close, you find an experimental coprocessor doing so much work that the local programs are afraid it will halt and catch fire. This would cause serious issues for the rest of the computer, so you head in and see what you can do.

+

The code it's running seems to be a variant of the kind you saw recently on that tablet. The general functionality seems very similar, but some of the instructions are different:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2017.Day23;
+
+[ProblemName("Coprocessor Conflagration")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var regs = new Dictionary();
+        int ip = 0;
+        int getReg(string reg) {
+            return int.TryParse(reg, out var n) ? n
+                : regs.ContainsKey(reg) ? regs[reg]
+                : 0;
+        }
+        void setReg(string reg, int value) {
+            regs[reg] = value;
+        }
+
+        var prog = input.Split('\n');
+        var mulCount = 0;
+        while (ip >= 0 && ip < prog.Length) {
+            var line = prog[ip];
+            var parts = line.Split(' ');
+            switch (parts[0]) {
+                case "set":
+                    setReg(parts[1], getReg(parts[2]));
+                    ip++;
+                    break;
+                case "sub":
+                    setReg(parts[1], getReg(parts[1]) - getReg(parts[2]));
+                    ip++;
+                    break;
+                case "mul":
+                    mulCount++;
+                    setReg(parts[1], getReg(parts[1]) * getReg(parts[2]));
+                    ip++;
+                    break;
+                case "jnz":
+                    ip += getReg(parts[1]) != 0 ? getReg(parts[2]) : 1;
+                    break;
+                default: throw new Exception("Cannot parse " + line);
+            }
+        }
+        return mulCount;
+    }
+
+    public object PartTwo(string input) {
+        var c = 0;
+        for (int b = 107900; b <= 124900; b += 17) {
+            if (!IsPrime(b)) {
+                c++;
+            }
+        }
+        return c;
+    }
+
+    bool IsPrime(int n) {
+        for (int j = 2; j * j <= n; j++) {
+            if (n % j == 0) return false;
+        }
+        return true;
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/24/illustration.jpeg b/2017/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/24/illustration.jpeg differ diff --git a/2017/24/index.html b/2017/24/index.html new file mode 100644 index 00000000..ed06bdf8 --- /dev/null +++ b/2017/24/index.html @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/24 'Electromagnetic Moat'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/24

+

Electromagnetic Moat

+

in C#

+

+

by encse

+
+ +
+ +
+

The CPU itself is a large, black building surrounded by a bottomless pit. Enormous metal tubes extend outward from the side of the building at regular intervals and descend down into the void. There's no way to cross, but you need to get inside.

+

No way, of course, other than building a bridge out of the magnetic components strewn about nearby.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day24;
+
+[ProblemName("Electromagnetic Moat")]
+class Solution : Solver {
+
+    public object PartOne(string input) => StrongestBridge(input, (a, b) => a.strength - b.strength);
+    public object PartTwo(string input) => StrongestBridge(input, (a, b) => a.CompareTo(b));
+
+    int StrongestBridge(string input, Func<(int length, int strength), (int length, int strength), int> compare) {
+
+        (int length, int strength) fold(int pinIn, HashSet components) {
+            var strongest = (0, 0);
+            foreach (var component in components.ToList()) {
+                var pinOut =
+                    pinIn == component.pinA ? component.pinB :
+                    pinIn == component.pinB ? component.pinA :
+                     -1;
+
+                if (pinOut != -1) {
+                    components.Remove(component);
+                    var curr = fold(pinOut, components);
+                    (curr.length, curr.strength) = (curr.length + 1, curr.strength + component.pinA + component.pinB);
+                    strongest = compare(curr, strongest) > 0 ? curr : strongest;
+                    components.Add(component);
+                }
+            }
+            return strongest;
+        }
+        return fold(0, Parse(input)).strength;
+    }
+
+    HashSet Parse(string input) {
+        var components = new HashSet();
+        foreach (var line in input.Split('\n')) {
+            var parts = line.Split('/');
+            components.Add(new Component { pinA = int.Parse(parts[0]), pinB = int.Parse(parts[1]) });
+        }
+        return components;
+    }
+}
+
+class Component {
+    public int pinA;
+    public int pinB;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/25/illustration.jpeg b/2017/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/25/illustration.jpeg differ diff --git a/2017/25/index.html b/2017/25/index.html new file mode 100644 index 00000000..8c8248ea --- /dev/null +++ b/2017/25/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/25 'The Halting Problem'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/25

+

The Halting Problem

+

in C#

+

+

by encse

+
+ +
+ +
+

Following the twisty passageways deeper and deeper into the CPU, you finally reach the core of the computer. Here, in the expansive central chamber, you find a grand apparatus that fills the entire room, suspended nanometers above your head.

+

You had always imagined CPUs to be noisy, chaotic places, bustling with activity. Instead, the room is quiet, motionless, and dark.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day25;
+
+[ProblemName("The Halting Problem")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var machine = Parse(input);
+        var tape = new Dictionary();
+        var pos = 0;
+        while (machine.iterations > 0) {
+            var read = tape.TryGetValue(pos, out var t) ? t : 0;
+            var (write, dir, newState) = machine.prg[(machine.state, read)];
+            machine.state = newState;
+            tape[pos] = write;
+            pos += dir;
+            machine.iterations--;
+        }
+        return tape.Select(kvp => kvp.Value).Sum();
+    }
+
+    Machine Parse(string input) {
+        var lines = input.Split('\n').Where(line => !string.IsNullOrEmpty(line)).ToArray();
+        int iline = 0;
+
+        Machine machine = new Machine();
+
+        String(@"Begin in state (\w).", out machine.state);
+        Int(@"Perform a diagnostic checksum after (\d+) steps.", out machine.iterations);
+
+        while (String(@"In state (\w):", out var state)) {
+            while (Int(@"If the current value is (\d):", out var read)) {
+                Int(@"- Write the value (\d).", out var write);
+                String(@"- Move one slot to the (left|right).", out var dir);
+                String(@" - Continue with state (\w).", out string newState);
+                machine.prg[(state, read)] = (write, dir == "left" ? -1 : 1, newState);
+            }
+        }
+
+        bool Int(string pattern, out int r) {
+            r = 0;
+            return String(pattern, out string st) && int.TryParse(st, out r);
+        }
+
+        bool String(string pattern, out string st) {
+            st = null;
+            if (iline >= lines.Length) {
+                return false;
+            }
+            var m = Regex.Match(lines[iline], pattern);
+            if (m.Success) {
+                iline++;
+                st = m.Groups[1].Value;
+            }
+            return m.Success;
+        }
+
+        return machine;
+    }
+}
+
+class Machine {
+    public string state;
+    public int iterations;
+    public Dictionary<(string state, int read), (int write, int dir, string state)> prg =
+        new Dictionary<(string, int), (int, int, string)>();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/3/illustration.jpeg b/2017/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/3/illustration.jpeg differ diff --git a/2017/3/index.html b/2017/3/index.html new file mode 100644 index 00000000..b5bc6d55 --- /dev/null +++ b/2017/3/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/3 'Spiral Memory'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/3

+

Spiral Memory

+

in C#

+

+

by encse

+
+ +
+ +
+

You come across an experimental new kind of memory stored on an infinite two-dimensional grid.

+

Each square on the grid is allocated in a spiral pattern starting at a location marked 1 and then counting up while spiraling outward. For example, the first few squares are allocated like this:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day03;
+
+[ProblemName("Spiral Memory")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var (x, y) = SpiralCoordinates().ElementAt(int.Parse(input) - 1);
+        return Math.Abs(x) + Math.Abs(y);
+    }
+
+    public object PartTwo(string input) {
+        var num = int.Parse(input);
+       return SpiralSums().First(v => v > num);
+    }
+
+    IEnumerable<(int, int)> SpiralCoordinates() {
+        var (x, y) = (0, 0);
+        var (dx, dy) = (1, 0);
+
+        for (var edgeLength = 1; ; edgeLength++) {
+            for (var run = 0; run < 2; run++) {
+                for (var step = 0; step < edgeLength; step++) {
+                    yield return (x, y);
+                    (x, y) = (x + dx, y - dy);
+                }
+                (dx, dy) = (-dy, dx);
+            }
+        }
+    }
+
+    IEnumerable SpiralSums() {
+        var mem = new Dictionary<(int, int), int>();
+        mem[(0, 0)] = 1;
+
+        foreach (var coord in SpiralCoordinates()) {
+            var sum = (from coordT in Window(coord) where mem.ContainsKey(coordT) select mem[coordT]).Sum();
+            mem[coord] = sum;
+            yield return sum;
+        }
+    }
+
+    IEnumerable<(int, int)> Window((int x, int y) coord) =>
+         from dx in new[] { -1, 0, 1 }
+         from dy in new[] { -1, 0, 1 }
+         select (coord.x + dx, coord.y + dy);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/4/illustration.jpeg b/2017/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/4/illustration.jpeg differ diff --git a/2017/4/index.html b/2017/4/index.html new file mode 100644 index 00000000..e81f5063 --- /dev/null +++ b/2017/4/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/4 'High-Entropy Passphrases'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/4

+

High-Entropy Passphrases

+

in C#

+

+

by encse

+
+ +
+ +
+

A new system policy has been put in place that requires all accounts to use a passphrase instead of simply a password. A passphrase consists of a series of words (lowercase letters) separated by spaces.

+

To ensure security, a valid passphrase must contain no duplicate words.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day04;
+
+[ProblemName("High-Entropy Passphrases")]
+class Solution : Solver {
+
+    public object PartOne(string lines) =>
+        ValidLineCount(lines, word => word);
+
+    public object PartTwo(string lines) =>
+        ValidLineCount(lines, word => string.Concat(word.OrderBy(ch => ch)));
+
+    int ValidLineCount(string lines, Func normalizer) =>
+        lines.Split('\n').Where(line => IsValidLine(line.Split(' '), normalizer)).Count();
+
+    bool IsValidLine(string[] words, Func normalizer) =>
+        words.Select(normalizer).Distinct().Count() == words.Count();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/5/illustration.jpeg b/2017/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/5/illustration.jpeg differ diff --git a/2017/5/index.html b/2017/5/index.html new file mode 100644 index 00000000..e8794173 --- /dev/null +++ b/2017/5/index.html @@ -0,0 +1,306 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/5 'A Maze of Twisty Trampolines, All Alike'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/5

+

A Maze of Twisty Trampolines, All Alike

+

in C#

+

+

by encse

+
+ +
+ +
+

An urgent interrupt arrives from the CPU: it's trapped in a maze of jump instructions, and it would like assistance from any programs with spare cycles to help find the exit.

+

The message includes a list of the offsets for each jump. Jumps are relative: -1 moves to the previous instruction, and 2 skips the next one. Start at the first instruction in the list. The goal is to follow the jumps until one leads outside the list.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day05;
+
+[ProblemName("A Maze of Twisty Trampolines, All Alike")]
+class Solution : Solver {
+    
+    public object PartOne(string input) => GetStepCount(input, x => x + 1);
+
+    public object PartTwo(string input) => GetStepCount(input, x => x < 3 ? x + 1 : x - 1);
+
+    int GetStepCount(string input, Func update) {
+        var numbers = input.Split('\n').Select(int.Parse).ToArray();
+        var i = 0;
+        var stepCount = 0;
+        while (i < numbers.Length && i >= 0) {
+            var jmp = numbers[i];
+            numbers[i] = update(numbers[i]);
+            i += jmp;
+            stepCount++;
+        }
+        return stepCount;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/6/illustration.jpeg b/2017/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/6/illustration.jpeg differ diff --git a/2017/6/index.html b/2017/6/index.html new file mode 100644 index 00000000..e1055262 --- /dev/null +++ b/2017/6/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/6 'Memory Reallocation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/6

+

Memory Reallocation

+

in C#

+

+

by encse

+
+ +
+ +
+

A debugger program here is having an issue: it is trying to repair a memory reallocation routine, but it keeps getting stuck in an infinite loop.

+

In this area, there are sixteen memory banks; each memory bank can hold any number of blocks. The goal of the reallocation routine is to balance the blocks between the memory banks.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day06;
+
+[ProblemName("Memory Reallocation")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetStepCount(Parse(input));
+
+    public object PartTwo(string input) {
+        var numbers = Parse(input);
+        GetStepCount(numbers);
+        return GetStepCount(numbers);
+    }
+
+    List Parse(string input) => input.Split('\t').Select(int.Parse).ToList();
+
+    int GetStepCount(List numbers) {
+        var stepCount = 0;
+        var seen = new HashSet();
+        while (true) {
+            var key = string.Join(";", numbers.Select(x => x.ToString()));
+            if (seen.Contains(key)) {
+                return stepCount;
+            }
+            seen.Add(key);
+            Redistribute(numbers);
+            stepCount++;
+        }
+    }
+
+    void Redistribute(List numbers) {
+        var max = numbers.Max();
+        var i = numbers.IndexOf(max);
+        numbers[i] = 0;
+        while (max > 0) {
+            i++;
+            numbers[i % numbers.Count]++;
+            max--;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/7/illustration.jpeg b/2017/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/7/illustration.jpeg differ diff --git a/2017/7/index.html b/2017/7/index.html new file mode 100644 index 00000000..a08b806b --- /dev/null +++ b/2017/7/index.html @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/7 'Recursive Circus'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/7

+

Recursive Circus

+

in C#

+

+

by encse

+
+ +
+ +
+

Wandering further through the circuits of the computer, you come upon a tower of programs that have gotten themselves into a bit of trouble. A recursive algorithm has gotten out of hand, and now they're balanced precariously in a large tower.

+

One program at the bottom supports the entire tower. It's holding a large disc, and on the disc are balanced several more sub-towers. At the bottom of these sub-towers, standing on the bottom disc, are other programs, each holding their own disc, and so on. At the very tops of these sub-sub-sub-...-towers, many programs stand simply keeping the disc below them balanced but with no disc of their own.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2017.Day07;
+
+class Node {
+    public string Id;
+    public string[] Children;
+    public int Weight;
+    public int TreeWeight = -1;
+}
+
+class Tree : Dictionary { }
+
+[ProblemName("Recursive Circus")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Root(Parse(input)).Id;
+
+    public object PartTwo(string input) {
+        var tree = Parse(input);
+        var root = Root(tree);
+        ComputeTreeWeights(root, tree);
+        var bogusChild = BogusChild(root, tree);
+        var desiredWeight = tree[root.Children.First(childId => childId != bogusChild.Id)].TreeWeight;
+        return Fix(bogusChild, desiredWeight, tree);
+    }
+
+    Tree Parse(string input) {
+        var tree = new Tree();
+        foreach (var line in input.Split('\n')) {
+            var parts = Regex.Match(line, @"(?[a-z]+) \((?[0-9]+)\)( -> (?.*))?");
+
+            tree.Add(
+                parts.Groups["id"].Value,
+                new Node {
+                    Id = parts.Groups["id"].Value,
+                    Weight = int.Parse(parts.Groups["weight"].Value),
+                    Children = string.IsNullOrEmpty(parts.Groups["children"].Value)
+                        ? new string[0]
+                        : Regex.Split(parts.Groups["children"].Value, ", "),
+                });
+        }
+        return tree;
+    }
+
+    Node Root(Tree tree) =>
+        tree.Values.First(node => !tree.Values.Any(nodeParent => nodeParent.Children.Contains(node.Id)));
+
+    int ComputeTreeWeights(Node node, Tree tree) {
+        node.TreeWeight = node.Weight + node.Children.Select(childId => ComputeTreeWeights(tree[childId], tree)).Sum();
+        return node.TreeWeight;
+    }
+
+    Node BogusChild(Node node, Tree tree) {
+        var w =
+            (from childId in node.Children
+             let child = tree[childId]
+             group child by child.TreeWeight into childrenByTreeWeight
+             orderby childrenByTreeWeight.Count()
+             select childrenByTreeWeight).ToArray();
+
+        return w.Length == 1 ? null : w[0].Single();
+    }
+
+    int Fix(Node node, int desiredWeight, Tree tree) {
+        if (node.Children.Length < 2) {
+            throw new NotImplementedException();
+        } 
+
+        var bogusChild = BogusChild(node, tree);
+
+        if (bogusChild == null) {
+            return desiredWeight - node.TreeWeight + node.Weight;
+        } else {
+            desiredWeight = desiredWeight - node.TreeWeight + bogusChild.TreeWeight;
+            return Fix(bogusChild, desiredWeight, tree);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/8/illustration.jpeg b/2017/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/8/illustration.jpeg differ diff --git a/2017/8/index.html b/2017/8/index.html new file mode 100644 index 00000000..570c60d1 --- /dev/null +++ b/2017/8/index.html @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/8 'I Heard You Like Registers'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/8

+

I Heard You Like Registers

+

in C#

+

+

by encse

+
+ +
+ +
+

You receive a signal directly from the CPU. Because of your recent assistance with jump instructions, it would like you to compute the result of a series of unusual register instructions.

+

Each instruction consists of several parts: the register to modify, whether to increase or decrease that register's value, the amount by which to increase or decrease it, and a condition. If the condition fails, skip the instruction without modifying the register. The registers all start at 0. The instructions look like this:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day08;
+
+[ProblemName("I Heard You Like Registers")]
+class Solution : Solver {
+ 
+    public object PartOne(string input) => Run(input).lastMax;
+    public object PartTwo(string input) => Run(input).runningMax;
+
+    (int runningMax, int lastMax) Run(string input) {
+        var regs = new Dictionary();
+        var runningMax = 0;
+        foreach (var line in input.Split('\n')) {
+            //hsv inc 472 if hsv >= 4637
+            var words = line.Split(' ');
+            var (regDst, op, num, regCond, cond, condNum) = (words[0], words[1], int.Parse(words[2]), words[4], words[5], int.Parse(words[6]));
+            if (!regs.ContainsKey(regDst)) {
+                regs[regDst] = 0;
+            }
+            if (!regs.ContainsKey(regCond)) {
+                regs[regCond] = 0;
+            }
+
+            var conditionHolds = cond switch {
+                ">=" => regs[regCond] >= condNum,
+                "<=" => regs[regCond] <= condNum,
+                "==" => regs[regCond] == condNum,
+                "!=" => regs[regCond] != condNum,
+                ">"  => regs[regCond] > condNum,
+                "<"  => regs[regCond] < condNum,
+                _ => throw new NotImplementedException(cond)
+            };
+            if (conditionHolds) {
+                regs[regDst] += 
+                    op == "inc" ? num :
+                    op == "dec" ? -num :
+                    throw new NotImplementedException(op);
+            }
+            runningMax = Math.Max(runningMax, regs[regDst]);
+        }
+        return (runningMax, regs.Values.Max());
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2017/9/illustration.jpeg b/2017/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2017/9/illustration.jpeg differ diff --git a/2017/9/index.html b/2017/9/index.html new file mode 100644 index 00000000..1db6eb9c --- /dev/null +++ b/2017/9/index.html @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2017/9 'Stream Processing'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2017/9

+

Stream Processing

+

in C#

+

+

by encse

+
+ +
+ +
+

A large stream blocks your path. According to the locals, it's not safe to cross the stream at the moment because it's full of garbage. You look down at the stream; rather than water, you discover that it's a stream of characters.

+

You sit for a while and record part of the stream (your puzzle input). The characters represent groups - sequences that begin with { and end with }. Within a group, there are zero or more other things, separated by commas: either another group or garbage. Since groups can contain other groups, a } only closes the most-recently-opened unclosed group - that is, they are nestable. Your puzzle input represents a single, large group which itself contains many smaller ones.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2017.Day09;
+
+[ProblemName("Stream Processing")]
+class Solution : Solver {
+
+    public object PartOne(string input) => BlockScores(input).Sum();
+    public object PartTwo(string input) => Classify(input).Where((x) => x.garbage).Count();
+
+    IEnumerable BlockScores(string input) {
+        var score = 0;
+        foreach (var ch in Classify(input).Where((x) => !x.garbage).Select(x => x.ch)) {
+            if (ch == '}') {
+                score--;
+            } else if (ch == '{') {
+                score++;
+                yield return score;
+            }
+        }
+    }
+
+    IEnumerable<(char ch, bool garbage)> Classify(string input) {
+        var skip = false;
+        var garbage = false;
+        foreach (var ch in input) {
+            if (garbage) {
+                if (skip) {
+                    skip = false;
+                } else {
+                    if (ch == '>') {
+                        garbage = false;
+                    } else if (ch == '!') {
+                        skip = true;
+                    } else {
+                        yield return (ch, garbage);
+                    }
+                }
+            } else {
+                if (ch == '<') {
+                    garbage = true;
+                } else {
+                    yield return (ch, garbage);
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/1/illustration.jpeg b/2018/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/1/illustration.jpeg differ diff --git a/2018/1/index.html b/2018/1/index.html new file mode 100644 index 00000000..c383b0c4 --- /dev/null +++ b/2018/1/index.html @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/1 'Chronal Calibration'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/1

+

Chronal Calibration

+

in C#

+

+

by encse

+
+ +
+ +
+

"We've detected some temporal anomalies," one of Santa's Elves at the Temporal Anomaly Research and Detection Instrument Station tells you. She sounded pretty worried when she called you down here. "At 500-year intervals into the past, someone has been changing Santa's history!"

+

"The good news is that the changes won't propagate to our time stream for another 25 days, and we have a device" - she attaches something to your wrist - "that will let you fix the changes with no such propagation delay. It's configured to send you 500 years further into the past every few days; that was the best we could do on such short notice."

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day01;
+
+[ProblemName("Chronal Calibration")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Frequencies(input).ElementAt(input.Split("\n").Count() - 1);
+    }
+
+    public object PartTwo(string input) {
+        var seen = new HashSet();
+        foreach (var f in Frequencies(input)) {
+            if (seen.Contains(f)) {
+                return f;
+            }
+            seen.Add(f);
+        }
+        throw new Exception();
+    }
+
+    IEnumerable Frequencies(string input) {
+        var f = 0;
+        while (true) {
+            foreach (var d in input.Split("\n").Select(int.Parse)) {
+                f += d;
+                yield return f;
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/10/illustration.jpeg b/2018/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/10/illustration.jpeg differ diff --git a/2018/10/index.html b/2018/10/index.html new file mode 100644 index 00000000..56e0007e --- /dev/null +++ b/2018/10/index.html @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/10 'The Stars Align'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/10

+

The Stars Align

+

in C#

+

+

by encse

+
+ +
+ +
+

It's no use; your navigation system simply isn't capable of providing walking directions in the arctic circle, and certainly not in 1018.

+

The Elves suggest an alternative. In times like these, North Pole rescue operations will arrange points of light in the sky to guide missing Elves back to base. Unfortunately, the message is easy to miss: the points move slowly enough that it takes hours to align them, but have so much momentum that they only stay aligned for a second. If you blink at the wrong time, it might be hours before another message appears.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day10;
+
+[ProblemName("The Stars Align")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solver(input).st.Ocr();
+
+    public object PartTwo(string input) => Solver(input).seconds;
+
+    (string st, int seconds) Solver(string input) {
+        // position=< 21992, -10766> velocity=<-2,  1>
+        var rx = new Regex(@"position=\<\s*(?-?\d+),\s*(?-?\d+)\> velocity=\<\s*(?-?\d+),\s*(?-?\d+)\>");
+        var points = (
+            from line in input.Split("\n")
+            let m = rx.Match(line)
+            select new Point {
+                x = int.Parse(m.Groups["x"].Value),
+                y = int.Parse(m.Groups["y"].Value),
+                vx = int.Parse(m.Groups["vx"].Value),
+                vy = int.Parse(m.Groups["vy"].Value)
+            }
+        ).ToArray();
+
+        var seconds = 0;
+        Func step = (bool forward) => {
+            foreach (var point in points) {
+                if (forward) {
+                    point.x += point.vx;
+                    point.y += point.vy;
+                } else {
+                    point.x -= point.vx;
+                    point.y -= point.vy;
+                }
+            }
+            seconds += forward ? 1 : -1;
+
+            var minX = points.Min(pt => pt.x);
+            var maxX = points.Max(pt => pt.x);
+            var minY = points.Min(pt => pt.y);
+            var maxY = points.Max(pt => pt.y);
+            return (minX, minY, maxX - minX + 1, maxY - minY + 1);
+        };
+
+        var area = long.MaxValue;
+        while (true) {
+
+            var rect = step(true);
+            var areaNew = (rect.width) * (rect.height);
+
+            if (areaNew > area) {
+                rect = step(false);
+                var st = "";
+                for(var irow=0;irow p.x - rect.left == icol && p.y-rect.top == irow) ? '#': ' ';
+                    }
+                    st+= "\n";
+                }
+                return (st, seconds);
+            }
+            area = areaNew;
+        }
+    }
+}
+
+class Point {
+    public int x;
+    public int y;
+    public int vx;
+    public int vy;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/11/illustration.jpeg b/2018/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/11/illustration.jpeg differ diff --git a/2018/11/index.html b/2018/11/index.html new file mode 100644 index 00000000..745cc909 --- /dev/null +++ b/2018/11/index.html @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/11 'Chronal Charge'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/11

+

Chronal Charge

+

in C#

+

+

by encse

+
+ +
+ +
+

You watch the Elves and their sleigh fade into the distance as they head toward the North Pole.

+

Actually, you're the one fading. The falling sensation returns.

+

Read the full puzzle.

+
+
namespace AdventOfCode.Y2018.Day11;
+
+[ProblemName("Chronal Charge")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var res = Solver(int.Parse(input), 3);
+        return $"{res.xMax},{res.yMax}";
+    }
+
+    public object PartTwo(string input) {
+        var res = Solver(int.Parse(input), 300);
+        return $"{res.xMax},{res.yMax},{res.dMax}";
+    }
+
+    (int xMax, int yMax, int dMax) Solver(int gridSerialNumber, int D) {
+        var gridOriginal = new int[300, 300];
+        for (var irow = 0; irow < 300; irow++) {
+            for (var icol = 0; icol < 300; icol++) {
+                var x = icol + 1;
+                var y = irow + 1;
+                //  Find the fuel cell's *rack ID*, which is its *X coordinate plus 10*.
+                var rackId = x + 10;
+                // - Begin with a power level of the *rack ID* times the *Y coordinate*.
+                var powerLevel = rackId * y;
+                // - Increase the power level by the value of the *grid serial number* (your puzzle input).
+                powerLevel += gridSerialNumber;
+                // - Set the power level to itself multiplied by the *rack ID*.
+                powerLevel *= rackId;
+                // - Keep only the *hundreds digit* of the power level (so `12*3*45` becomes `3`; numbers with no hundreds digit become `0`).
+                powerLevel = (powerLevel % 1000) / 100;
+                // - *Subtract 5* from the power level.
+                powerLevel -= 5;
+
+                gridOriginal[irow, icol] = powerLevel;
+            }
+        }
+
+        var maxTotalPower = int.MinValue;
+        var yMax = int.MinValue;
+        var xMax = int.MinValue;
+        var dMax = int.MinValue;
+
+        var grid = new int[300, 300];
+        for (var d = 1; d <= D; d++) {
+            for (var irow = 0; irow < 300 - d; irow++) {
+                for (var icol = 0; icol < 300; icol++) {
+                    grid[irow, icol] += gridOriginal[irow + d - 1, icol];
+                }
+            }
+
+            for (var irow = 0; irow < 300 - d; irow++) {
+                for (var icol = 0; icol < 300 - d; icol++) {
+                    var totalPower = 0;
+
+                    for (var i = 0; i < d; i++) {
+                        totalPower += grid[irow, icol + i];
+                    }
+
+                    if (totalPower > maxTotalPower) {
+                        maxTotalPower = totalPower;
+                        yMax = irow + 1;
+                        xMax = icol + 1;
+                        dMax = d;
+                    }
+                }
+            }
+        }
+        return (xMax, yMax, dMax);
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/12/illustration.jpeg b/2018/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/12/illustration.jpeg differ diff --git a/2018/12/index.html b/2018/12/index.html new file mode 100644 index 00000000..736a9595 --- /dev/null +++ b/2018/12/index.html @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/12 'Subterranean Sustainability'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/12

+

Subterranean Sustainability

+

in C#

+

+

by encse

+
+ +
+ +
+

The year 518 is significantly more underground than your history books implied. Either that, or you've arrived in a vast cavern network under the North Pole.

+

After exploring a little, you discover a long tunnel that contains a row of small pots as far as you can see to your left and right. A few of them contain plants - someone is trying to grow things in these geothermally-heated caves.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day12;
+
+[ProblemName("Subterranean Sustainability")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Iterate(input, 20);
+
+    public object PartTwo(string input) => Iterate(input, 50000000000);
+
+    long Iterate(string input, long iterations) {
+        var (state, rules) = Parse(input);
+
+        var dLeftPos = 0L;
+
+        while (iterations > 0) {
+            var prevState = state;
+            state = Step(state, rules);
+            iterations--;
+            dLeftPos = state.left - prevState.left;
+            if (state.pots == prevState.pots) {
+                state = new State { left = state.left + iterations * dLeftPos, pots = state.pots };
+                break;
+            }
+        }
+
+        return Enumerable.Range(0, state.pots.Length).Select(i => state.pots[i] == '#' ? i + state.left : 0).Sum();
+    }
+
+    State Step(State state, Dictionary rules) {
+        var pots = "....." + state.pots + ".....";
+        var newPots = "";
+        for (var i = 2; i < pots.Length - 2; i++) {
+            var x = pots.Substring(i - 2, 5);
+            newPots += rules.TryGetValue(x, out var ch) ? ch : ".";
+        }
+
+        var firstFlower = newPots.IndexOf("#");
+        var newLeft = firstFlower + state.left - 3;
+
+        newPots = newPots.Substring(firstFlower);
+        newPots = newPots.Substring(0, newPots.LastIndexOf("#") + 1);
+        var res = new State { left = newLeft, pots = newPots };
+
+        return res;
+    }
+
+    (State state, Dictionary rules) Parse(string input) {
+        var lines = input.Split("\n");
+        var state = new State { left = 0, pots = lines[0].Substring("initial state: ".Length) };
+        var rules = (from line in lines.Skip(2) let parts = line.Split(" => ") select new { key = parts[0], value = parts[1] }).ToDictionary(x => x.key, x => x.value);
+        return (state, rules);
+    }
+}
+
+class State {
+    public long left;
+    public string pots;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/13/illustration.jpeg b/2018/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/13/illustration.jpeg differ diff --git a/2018/13/index.html b/2018/13/index.html new file mode 100644 index 00000000..11b3b126 --- /dev/null +++ b/2018/13/index.html @@ -0,0 +1,400 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/13 'Mine Cart Madness'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/13

+

Mine Cart Madness

+

in C#

+

+

by encse

+
+ +
+ +
+

A crop of this size requires significant logistics to transport produce, soil, fertilizer, and so on. The Elves are very busy pushing things around in carts on some kind of rudimentary system of tracks they've come up with.

+

Seeing as how cart-and-track systems don't appear in recorded history for another 1000 years, the Elves seem to be making this up as they go along. They haven't even figured out how to avoid collisions yet.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day13;
+
+[ProblemName("Mine Cart Madness")]
+class Solution : Solver {
+
+   
+    public object PartOne(string input) {
+        var (mat, carts) = Parse(input);
+        while (true) {
+            var newState = Step(mat, carts);
+            if (newState.crashed.Any()) {
+                return Tsto(newState.crashed[0]);
+            }
+        }
+    }
+
+    public object PartTwo(string input) {
+        var (mat, carts) = Parse(input);
+        while (carts.Count > 1) {
+            var newState = Step(mat, carts);
+            carts = newState.carts;
+        }
+        return Tsto(carts[0]);
+    }
+
+    string Tsto(Cart cart) => $"{cart.pos.icol},{cart.pos.irow}";
+
+    (List crashed, List carts) Step(string[] mat, List carts) {
+        var crashed = new List();
+
+        foreach (var cart in carts.OrderBy((cartT) => cartT.pos)) {
+            cart.pos = (irow: cart.pos.irow + cart.drow, icol: cart.pos.icol + cart.dcol);
+            
+            foreach (var cart2 in carts.ToArray()) {
+                if (cart != cart2 && cart.pos.irow == cart2.pos.irow && cart.pos.icol == cart2.pos.icol) {
+                    crashed.Add(cart);
+                    crashed.Add(cart2);
+
+                }
+            }
+            switch (mat[cart.pos.irow][cart.pos.icol]) {
+                case '\\':
+                    if (cart.dcol == 1 || cart.dcol == -1) {
+                        cart.Rotate(Dir.Right);
+                    } else if (cart.drow == -1 || cart.drow == 1) {
+                        cart.Rotate(Dir.Left);
+                    } else {
+                        throw new Exception();
+                    }
+                    break;
+                case '/':
+                    if (cart.dcol == 1 || cart.dcol == -1) {
+                        cart.Rotate(Dir.Left);
+                    } else if (cart.drow == 1 || cart.drow == -1) {
+                        cart.Rotate(Dir.Right);
+                    }
+                    break;
+                case '+':
+                    cart.Turn();
+                    break;
+            }
+        }
+        return (crashed, carts.Where(cart => !crashed.Contains(cart)).ToList());
+    }
+
+    (string[] mat, List carts) Parse(string input){
+        var mat = input.Split("\n");
+        var crow = mat.Length;
+        var ccol = mat[0].Length;
+
+        var carts = new List();
+        for (var irow = 0; irow < crow; irow++) {
+            for (var icol = 0; icol < ccol; icol++) {
+                var ch = mat[irow][icol];
+                switch (ch) {
+                    case '^':
+                        carts.Add(new Cart { pos = (irow: irow, icol: icol), dcol = 0, drow = -1 });
+                        break;
+                    case 'v':
+                        carts.Add(new Cart { pos = (irow: irow, icol: icol), dcol = 0, drow = 1 });
+                        break;
+                    case '<':
+                        carts.Add(new Cart { pos = (irow: irow, icol: icol), dcol = -1, drow = 0 });
+                        break;
+                    case '>':
+                        carts.Add(new Cart { pos = (irow: irow, icol: icol), dcol = 1, drow = 0 });
+                        break;
+                }
+            }
+        }
+        return (mat, carts);
+    }
+}
+
+enum Dir { Left, Forward, Right }
+class Cart {
+    public (int irow, int icol) pos;
+    public int drow;
+    public int dcol;
+    private Dir nextTurn = Dir.Left;
+
+    public void Rotate(Dir dir) {
+         (drow, dcol) = dir switch {
+             Dir.Left => (-dcol, drow),
+             Dir.Right => (dcol, -drow),
+             Dir.Forward => (drow, dcol),
+             _ => throw new ArgumentException()
+         };
+    }
+
+    public void Turn() {
+        Rotate(nextTurn);
+        nextTurn = (Dir)(((int)nextTurn + 1) % 3);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/14/illustration.jpeg b/2018/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/14/illustration.jpeg differ diff --git a/2018/14/index.html b/2018/14/index.html new file mode 100644 index 00000000..d444d115 --- /dev/null +++ b/2018/14/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/14 'Chocolate Charts'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/14

+

Chocolate Charts

+

in C#

+

+

by encse

+
+ +
+ +
+

You finally have a chance to look at all of the produce moving around. Chocolate, cinnamon, mint, chili peppers, nutmeg, vanilla... the Elves must be growing these plants to make hot chocolate! As you realize this, you hear a conversation in the distance. When you go to investigate, you discover two Elves in what appears to be a makeshift underground kitchen/laboratory.

+

The Elves are trying to come up with the ultimate hot chocolate recipe; they're even maintaining a scoreboard which tracks the quality score (0-9) of each recipe.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day14;
+
+[ProblemName("Chocolate Charts")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Window(10).ElementAt(int.Parse(input)).st;
+
+    public object PartTwo(string input) => Window(input.Length).First(item => item.st == input).i;
+
+    IEnumerable<(int i, string st)> Window(int w) {
+        var st = "";
+        var i = 0;
+        foreach (var score in Scores()) {
+            i++;
+            st += score;
+            if (st.Length > w) {
+                st = st.Substring(st.Length - w);
+            }
+            if (st.Length == w) {
+                yield return (i - w, st);
+            }
+        }
+    }
+
+    IEnumerable Scores() {
+        var scores = new List();
+        Func add = (i) => { scores.Add(i); return i; };
+
+        var elf1 = 0;
+        var elf2 = 1;
+
+        yield return add(3);
+        yield return add(7);
+
+        while (true) {
+            var sum = scores[elf1] + scores[elf2];
+            if (sum >= 10) {
+                yield return add(sum / 10);
+            }
+            yield return add(sum % 10);
+
+            elf1 = (elf1 + scores[elf1] + 1) % scores.Count;
+            elf2 = (elf2 + scores[elf2] + 1) % scores.Count;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/15/illustration.jpeg b/2018/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/15/illustration.jpeg differ diff --git a/2018/15/index.html b/2018/15/index.html new file mode 100644 index 00000000..778679d9 --- /dev/null +++ b/2018/15/index.html @@ -0,0 +1,532 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/15 'Beverage Bandits'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/15

+

Beverage Bandits

+

in C#

+

+

by encse

+
+ +
+ +
+

Having perfected their hot chocolate, the Elves have a new problem: the Goblins that live in these caves will do anything to steal it. Looks like they're here for a fight.

+

You scan the area, generating a map of the walls (#), open cavern (.), and starting position of every Goblin (G) and Elf (E) (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day15;
+
+[ProblemName("Beverage Bandits")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Outcome(input, 3, 3, false).score;
+    }
+
+    public object PartTwo(string input) {
+        var elfAp = 4;
+        while (true) {
+            var outcome = Outcome(input, 3, elfAp, false);
+            if (outcome.noElfDied) {
+                return outcome.score;
+            }
+            elfAp++;
+        }
+    }
+
+    (bool noElfDied, int score) Outcome(string input, int goblinAp, int elfAp, bool tsto) {
+        var game = Parse(input, goblinAp, elfAp);
+        var elfCount = game.players.Count(player => player.elf);
+
+        if (tsto) {
+            Console.WriteLine(game.Tsto());
+        }
+
+        while (!game.Finished()) {
+            game.Step();
+            if (tsto) {
+                Console.WriteLine(game.Tsto());
+            }
+        }
+
+        return (game.players.Count(p => p.elf) == elfCount, game.rounds * game.players.Select(player => player.hp).Sum());
+    }
+
+
+    Game Parse(string input, int goblinAp, int elfAp) {
+        var players = new List();
+        var lines = input.Split("\n");
+        var mtx = new Block[lines.Length, lines[0].Length];
+
+        var game = new Game { mtx = mtx, players = players };
+
+        for (var irow = 0; irow < lines.Length; irow++) {
+            for (var icol = 0; icol < lines[0].Length; icol++) {
+                switch (lines[irow][icol]) {
+                    case '#':
+                        mtx[irow, icol] = Wall.Block;
+                        break;
+                    case '.':
+                        mtx[irow, icol] = Empty.Block;
+                        break;
+                    case var ch when ch == 'G' || ch == 'E':
+                        var player = new Player {
+                            elf = ch == 'E',
+                            ap = ch == 'E' ? elfAp : goblinAp,
+                            pos = (irow, icol),
+                            game = game
+                        };
+                        players.Add(player);
+                        mtx[irow, icol] = player;
+                        break;
+                }
+            }
+        }
+        return game;
+    }
+
+
+}
+
+class Game {
+    public Block[,] mtx;
+    public List players;
+    public int rounds;
+
+    private bool ValidPos((int irow, int icol) pos) =>
+        pos.irow >= 0 && pos.irow < this.mtx.GetLength(0) && pos.icol >= 0 && pos.icol < this.mtx.GetLength(1);
+
+    public Block GetBlock((int irow, int icol) pos) =>
+        ValidPos(pos) ? mtx[pos.irow, pos.icol] : Wall.Block;
+
+    public void Step() {
+        var finishedBeforeEndOfRound = false;
+        foreach (var player in players.OrderBy(player => player.pos).ToArray()) {
+            if (player.hp > 0) {
+                finishedBeforeEndOfRound |= Finished();
+                player.Step();
+            }
+        }
+
+        if (!finishedBeforeEndOfRound) {
+            rounds++;
+        }
+    }
+
+    public bool Finished() =>
+        players.Where(p => p.elf).All(p => p.hp == 0) ||
+        players.Where(p => !p.elf).All(p => p.hp == 0);
+
+    public string Tsto() {
+
+        var res = "";
+        res += rounds == 0 ? "Initial:\n" : $"After round {rounds}:\n";
+        for (var irow = 0; irow < mtx.GetLength(0); irow++) {
+            for (var icol = 0; icol < mtx.GetLength(1); icol++) {
+                res += GetBlock((irow, icol)) switch {
+                    Player p when p.elf => "E",
+                    Player p when !p.elf => "G",
+                    Empty _ => ".",
+                    Wall _ => "#",
+                    _ => throw new ArgumentException()
+                };
+            }
+
+            foreach (var player in players.Where(player => player.pos.irow == irow).OrderBy(player => player.pos)) {
+                var ch = player.elf ? 'E' : 'G';
+                res += $" {ch}{{{player.pos.irow}, {player.pos.icol}}}({player.hp})";
+            }
+            res += "\n";
+        }
+        res += "\n";
+        return res;
+    }
+}
+
+abstract class Block { }
+
+class Empty : Block {
+    public static readonly Empty Block = new Empty();
+    private Empty() { }
+}
+
+class Wall : Block {
+    public static readonly Wall Block = new Wall();
+    private Wall() { }
+}
+
+class Player : Block {
+    public (int irow, int icol) pos;
+    public bool elf;
+    public int ap = 3;
+    public int hp = 200;
+    public Game game;
+
+    public bool Step() {
+        if (hp <= 0) {
+            return false;
+        } else if (Attack()) {
+            return true;
+        } else if (Move()) {
+            Attack();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private bool Move() {
+        var targets = FindTargets();
+        if (!targets.Any()) {
+            return false;
+        }
+        var opponent = targets.OrderBy(a => a.target).First();
+        var nextPos = targets.Where(a => a.player == opponent.player).Select(a => a.firstStep).OrderBy(_ => _).First();
+        (game.mtx[nextPos.irow, nextPos.icol], game.mtx[pos.irow, pos.icol]) =
+            (game.mtx[pos.irow, pos.icol], game.mtx[nextPos.irow, nextPos.icol]);
+        pos = nextPos;
+        return true;
+    }
+
+    private IEnumerable<(Player player, (int irow, int icol) firstStep, (int irow, int icol) target)> FindTargets() {
+
+        var minDist = int.MaxValue;
+        foreach (var (otherPlayer, firstStep, target, dist) in BlocksNextToOpponentsByDistance()) {
+            if (dist > minDist) {
+                break;
+            } else {
+                minDist = dist;
+                yield return (otherPlayer, firstStep, target);
+            }
+        }
+    }
+
+    private IEnumerable<(Player player, (int irow, int icol) firstStep, (int irow, int icol) target, int dist)> BlocksNextToOpponentsByDistance() {
+        var seen = new HashSet<(int irow, int icol)>();
+        seen.Add(pos);
+        var q = new Queue<((int irow, int icol) pos, (int drow, int dcol) origDir, int dist)>();
+
+        foreach (var (drow, dcol) in new[] { (-1, 0), (0, -1), (0, 1), (1, 0) }) {
+            var posT = (pos.irow + drow, pos.icol + dcol);
+            q.Enqueue((posT, posT, 1));
+        }
+
+        while (q.Any()) {
+            var (pos, firstStep, dist) = q.Dequeue();
+
+            if (game.GetBlock(pos) is Empty) {
+                foreach (var (drow, dcol) in new[] { (-1, 0), (0, -1), (0, 1), (1, 0) }) {
+                    var posT = (pos.irow + drow, pos.icol + dcol);
+                    if (!seen.Contains(posT)) {
+                        seen.Add(posT);
+                        q.Enqueue((posT, firstStep, dist + 1));
+
+                        var nextBlock = game.GetBlock(posT);
+                        if (nextBlock is Player) {
+                            var player = nextBlock as Player;
+                            if (player.elf != this.elf) {
+                                yield return (player, firstStep, pos, dist);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private bool Attack() {
+        var opponents = new List();
+
+        foreach (var (drow, dcol) in new[] { (-1, 0), (0, -1), (0, 1), (1, 0) }) {
+            var posT = (this.pos.irow + drow, this.pos.icol + dcol);
+            var block = game.GetBlock(posT);
+            switch (block) {
+                case Player otherPlayer when otherPlayer.elf != this.elf:
+                    opponents.Add(otherPlayer);
+                    break;
+            }
+        }
+
+        if (!opponents.Any()) {
+            return false;
+        }
+        var minHp = opponents.Select(a => a.hp).Min();
+        var opponent = opponents.First(a => a.hp == minHp);
+        opponent.hp -= this.ap;
+        if (opponent.hp <= 0) {
+            game.players.Remove(opponent);
+            game.mtx[opponent.pos.irow, opponent.pos.icol] = Empty.Block;
+        }
+        return true;
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/16/illustration.jpeg b/2018/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/16/illustration.jpeg differ diff --git a/2018/16/index.html b/2018/16/index.html new file mode 100644 index 00000000..045664f5 --- /dev/null +++ b/2018/16/index.html @@ -0,0 +1,420 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/16 'Chronal Classification'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/16

+

Chronal Classification

+

in C#

+

+

by encse

+
+ +
+ +
+

As you see the Elves defend their hot chocolate successfully, you go back to falling through time. This is going to become a problem.

+

If you're ever going to return to your own time, you need to understand how this device on your wrist works. You have a little while before you reach your next destination, and with a bit of trial and error, you manage to pull up a programming manual on the device's tiny screen.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day16;
+
+[ProblemName("Chronal Classification")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var res = 0;
+        var (testCases, prg) = Parse(input);
+        foreach (var testCase in testCases) {
+            var match = 0;
+            for (var i = 0; i < 16; i++) {
+                testCase.stm[0] = i;
+                var regsActual = Step(testCase.regsBefore, testCase.stm);
+                if (Enumerable.Range(0, 4).All(ireg => regsActual[ireg] == testCase.regsAfter[ireg])) {
+                    match++;
+                }
+            }
+            if (match >= 3) {
+                res++;
+            }
+        }
+        return res;
+    }
+
+    public object PartTwo(string input) {
+
+        var constraints = Enumerable.Range(0, 16).ToDictionary(i => i, i => Enumerable.Range(0, 16).ToList());
+        var (testCases, prg) = Parse(input);
+        foreach (var testCase in testCases) {
+            var op = testCase.stm[0];
+            var oldMapping = constraints[op];
+            var newMapping = new List();
+            foreach (var i in oldMapping) {
+                testCase.stm[0] = i;
+                var regsActual = Step(testCase.regsBefore, testCase.stm);
+                if (Enumerable.Range(0, 4).All(ireg => regsActual[ireg] == testCase.regsAfter[ireg])) {
+                    newMapping.Add(i);
+                }
+            }
+            constraints[op] = newMapping;
+        }
+
+        var mapping = WorkOutMapping(constraints, new bool[16], new Dictionary());
+        var regs = new int[4];
+        foreach (var stm in prg) {
+            stm[0] = mapping[stm[0]];
+            regs = Step(regs, stm);
+        }
+        return regs[0];
+    }
+
+    Dictionary WorkOutMapping(Dictionary> constaints, bool[] used, Dictionary res) {
+        var op = res.Count;
+        if (op == 16) {
+            return res;
+        }
+        foreach (var i in constaints[op]) {
+            if (!used[i]) {
+                used[i] = true;
+                res[op] = i;
+                var x = WorkOutMapping(constaints, used, res);
+                if (x != null) {
+                    return x;
+                }
+                res.Remove(op);
+                used[i] = false;
+            }
+        }
+        return null;
+    }
+
+    (List testCases, List prg) Parse(string input) {
+        var lines = input.Split("\n").ToList();
+        var iline = 0;
+
+        var testCases = new List();
+        while (Ints(@"Before: \[(\d+), (\d+), (\d+), (\d+)\]", out var regsBefore)) {
+            Ints(@"(\d+) (\d+) (\d+) (\d+)", out var stm);
+            Ints(@"After:  \[(\d+), (\d+), (\d+), (\d+)\]", out var regsAfter);
+            iline++;
+            testCases.Add(new TestCase() { regsBefore = regsBefore, regsAfter = regsAfter, stm = stm });
+        }
+        iline++;
+        iline++;
+        var prg = new List();
+        while (Ints(@"(\d+) (\d+) (\d+) (\d+)", out var stm)) {
+            prg.Add(stm);
+        }
+
+        bool Ints(string pattern, out int[] r) {
+            r = null;
+            if (iline >= lines.Count) {
+                return false;
+            }
+            var m = Regex.Match(lines[iline], pattern);
+            if (m.Success) {
+                iline++;
+                r = m.Groups.Values.Skip(1).Select(x => int.Parse(x.Value)).ToArray();
+            }
+            return m.Success;
+        }
+        return (testCases, prg);
+    }
+
+    int[] Step(int[] regs, int[] stm) {
+        regs = regs.ToArray();
+        regs[stm[3]] = stm[0] switch {
+            0 => regs[stm[1]] + regs[stm[2]],
+            1 => regs[stm[1]] + stm[2],
+            2 => regs[stm[1]] * regs[stm[2]],
+            3 => regs[stm[1]] * stm[2],
+            4 => regs[stm[1]] & regs[stm[2]],
+            5 => regs[stm[1]] & stm[2],
+            6 => regs[stm[1]] | regs[stm[2]],
+            7 => regs[stm[1]] | stm[2],
+            8 => regs[stm[1]],
+            9 => stm[1],
+            10 => stm[1] > regs[stm[2]] ? 1 : 0,
+            11 => regs[stm[1]] > stm[2] ? 1 : 0,
+            12 => regs[stm[1]] > regs[stm[2]] ? 1 : 0,
+            13 => stm[1] == regs[stm[2]] ? 1 : 0,
+            14 => regs[stm[1]] == stm[2] ? 1 : 0,
+            15 => regs[stm[1]] == regs[stm[2]] ? 1 : 0,
+            _ => throw new ArgumentException()
+        };
+        return regs;
+    }
+}
+
+class TestCase {
+    public int[] regsBefore;
+    public int[] regsAfter;
+    public int[] stm;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/17/illustration.jpeg b/2018/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/17/illustration.jpeg differ diff --git a/2018/17/index.html b/2018/17/index.html new file mode 100644 index 00000000..eec55f58 --- /dev/null +++ b/2018/17/index.html @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/17 'Reservoir Research'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/17

+

Reservoir Research

+

in C#

+

+

by encse

+
+ +
+ +
+

You arrive in the year 18. If it weren't for the coat you got in 1018, you would be very cold: the North Pole base hasn't even been constructed.

+

Rather, it hasn't been constructed yet. The Elves are making a little progress, but there's not a lot of liquid water in this climate, so they're getting very dehydrated. Maybe there's more underground?

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day17;
+
+[ProblemName("Reservoir Research")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Regex.Matches(Fill(input), "[~|]").Count;
+    public object PartTwo(string input) => Regex.Matches(Fill(input), "[~]").Count;
+
+    string Fill(string input) {
+        var (width, height) = (2000, 2000);
+        var mtx = new char[width, height];
+
+        for (var y = 0; y < height; y++) {
+            for (var x = 0; x < width; x++) {
+                mtx[x, y] = '.';
+            }
+        }
+
+        foreach (var line in input.Split("\n")) {
+            var nums = Regex.Matches(line, @"\d+").Select(g => int.Parse(g.Value)).ToArray();
+            for (var i = nums[1]; i <= nums[2]; i++) {
+                if (line.StartsWith("x")) {
+                    mtx[nums[0], i] = '#';
+                } else {
+                    mtx[i, nums[0]] = '#';
+                }
+            }
+        }
+        FillRecursive(mtx, 500, 0);
+
+        var (minY, maxY) = (int.MaxValue, int.MinValue);
+        for (var y = 0; y < height; y++) {
+            for (var x = 0; x < width; x++) {
+                if (mtx[x, y] == '#') {
+                    minY = Math.Min(minY, y);
+                    maxY = Math.Max(maxY, y);
+                }
+            }
+        }
+        var sb = new StringBuilder();
+        for (var y = minY; y <= maxY; y++) {
+            for (var x = 0; x < width; x++) {
+                sb.Append(mtx[x, y]);
+            }
+            sb.AppendLine();
+        }
+        return sb.ToString();
+    }
+
+    void FillRecursive(char[,] mtx, int x, int y) {
+        var width = mtx.GetLength(0);
+        var height = mtx.GetLength(1);
+        if (mtx[x, y] != '.') {
+            return;
+        }
+        mtx[x, y] = '|';
+        if (y == height - 1) {
+            return ;
+        }
+        FillRecursive(mtx, x, y + 1);
+
+        if (mtx[x, y + 1] == '#' || mtx[x, y + 1] == '~') {
+            if (x > 0) {
+                FillRecursive(mtx, x - 1, y);
+            }
+            if (x < width - 1) {
+                FillRecursive(mtx, x + 1, y);
+            }
+        }
+
+        if (IsStill(mtx, x, y)) {
+            foreach (var dx in new[] { -1, 1 }) {
+                for (var xT = x; xT >= 0 && xT < width && mtx[xT, y] == '|'; xT += dx) {
+                    mtx[xT, y] = '~';
+                }
+            }
+        }
+    }
+
+    bool IsStill(char[,] mtx, int x, int y) {
+        var width = mtx.GetLength(0);
+        foreach (var dx in new[] { -1, 1 }) {
+            for (var xT = x; xT >= 0 && xT < width && mtx[xT, y] != '#'; xT += dx) {
+                if (mtx[xT, y] == '.' || mtx[xT, y + 1] == '|') {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/18/illustration.jpeg b/2018/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/18/illustration.jpeg differ diff --git a/2018/18/index.html b/2018/18/index.html new file mode 100644 index 00000000..5b6901b8 --- /dev/null +++ b/2018/18/index.html @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/18 'Settlers of The North Pole'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/18

+

Settlers of The North Pole

+

in C#

+

+

by encse

+
+ +
+ +
+

On the outskirts of the North Pole base construction project, many Elves are collecting lumber.

+

The lumber collection area is 50 acres by 50 acres; each acre can be either open ground (.), trees (|), or a lumberyard (#). You take a scan of the area (your puzzle input).

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day18;
+
+[ProblemName("Settlers of The North Pole")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Iterate(input, 10);
+    public object PartTwo(string input) => Iterate(input, 1000000000);
+
+    int Iterate(string input, int lim) {
+        var seen = new Dictionary();
+        var mtx = input.Split("\n");
+        
+        for (var t = 0; t < lim; t++) {
+            var hash = string.Join("", mtx);
+            if (seen.ContainsKey(hash)) {
+                var loopLength = t - seen[hash];
+                var remainingSteps = lim - t - 1;
+                var remainingLoops = remainingSteps / loopLength;
+                t += remainingLoops * loopLength;
+            } else {
+                seen[hash] = t;
+            }
+            mtx = Step(mtx);
+        }
+        var res = string.Join("", mtx);
+        return Regex.Matches(res, @"\#").Count * Regex.Matches(res, @"\|").Count;
+    }
+
+    string[] Step(string[] mtx) {
+        var res = new List();
+        var crow = mtx.Length;
+        var ccol = mtx[0].Length;
+       
+        for (var irow = 0; irow < crow; irow++) {
+            var line = "";
+            for (var icol = 0; icol < ccol; icol++) {
+                var (tree, lumberyard, empty) = (0, 0, 0);
+                foreach (var drow in new[] { -1, 0, 1 }) {
+                    foreach (var dcol in new[] { -1, 0, 1 }) {
+                        if (drow != 0 || dcol != 0) {
+                            var (icolT, irowT) = (icol + dcol, irow + drow);
+                            if (icolT >= 0 && icolT < ccol && irowT >= 0 && irowT < crow) {
+                                switch (mtx[irowT][icolT]) {
+                                    case '#': lumberyard++; break;
+                                    case '|': tree++; break;
+                                    case '.': empty++; break;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                line += mtx[irow][icol] switch {
+                    '#' when lumberyard >= 1 && tree >= 1 => '#',
+                    '|' when lumberyard >= 3 => '#',
+                    '.' when tree >= 3 => '|',
+                    '#' => '.',
+                    var c => c
+                };
+            }
+            res.Add(line);
+        }
+        return res.ToArray();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/19/illustration.jpeg b/2018/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/19/illustration.jpeg differ diff --git a/2018/19/index.html b/2018/19/index.html new file mode 100644 index 00000000..b0776ab8 --- /dev/null +++ b/2018/19/index.html @@ -0,0 +1,338 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/19 'Go With The Flow'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/19

+

Go With The Flow

+

in C#

+

+

by encse

+
+ +
+ +
+

With the Elves well on their way constructing the North Pole base, you turn your attention back to understanding the inner workings of programming the device.

+

You can't help but notice that the device's opcodes don't contain any flow control like jump instructions. The device's manual goes on to explain:

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day19;
+
+[ProblemName("Go With The Flow")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var ip = 0;
+        var ipReg = int.Parse(input.Split("\n").First().Substring("#ip ".Length));
+        var prg = input.Split("\n").Skip(1).ToArray();
+        var regs = new int[6];
+        while (ip >= 0 && ip < prg.Length) {
+            var args = prg[ip].Split(" ");
+            regs[ipReg] = ip;
+            regs = Step(regs, args[0], args.Skip(1).Select(int.Parse).ToArray());
+            ip = regs[ipReg];
+            ip++;
+        }
+        return regs[0];
+    }
+
+    public object PartTwo(string input) {
+        var t = 10551292;
+        var r0 = 0;
+        for (var x = 1; x <= t; x++) {
+            if (t % x == 0)
+                r0 += x;
+        }
+        return r0;
+    }
+
+    int[] Step(int[] regs, string op, int[] stm) {
+        regs = regs.ToArray();
+        regs[stm[2]] = op switch {
+            "addr" => regs[stm[0]] + regs[stm[1]],
+            "addi" => regs[stm[0]] + stm[1],
+            "mulr" => regs[stm[0]] * regs[stm[1]],
+            "muli" => regs[stm[0]] * stm[1],
+            "banr" => regs[stm[0]] & regs[stm[1]],
+            "bani" => regs[stm[0]] & stm[1],
+            "borr" => regs[stm[0]] | regs[stm[1]],
+            "bori" => regs[stm[0]] | stm[1],
+            "setr" => regs[stm[0]],
+            "seti" => stm[0],
+            "gtir" => stm[0] > regs[stm[1]] ? 1 : 0,
+            "gtri" => regs[stm[0]] > stm[1] ? 1 : 0,
+            "gtrr" => regs[stm[0]] > regs[stm[1]] ? 1 : 0,
+            "eqir" => stm[0] == regs[stm[1]] ? 1 : 0,
+            "eqri" => regs[stm[0]] == stm[1] ? 1 : 0,
+            "eqrr" => regs[stm[0]] == regs[stm[1]] ? 1 : 0,
+            _ => throw new ArgumentException()
+        };
+        return regs;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/2/illustration.jpeg b/2018/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/2/illustration.jpeg differ diff --git a/2018/2/index.html b/2018/2/index.html new file mode 100644 index 00000000..86fdb291 --- /dev/null +++ b/2018/2/index.html @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/2 'Inventory Management System'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/2

+

Inventory Management System

+

in C#

+

+

by encse

+
+ +
+ +
+

You stop falling through time, catch your breath, and check the screen on the device. "Destination reached. Current Year: 1518. Current Location: North Pole Utility Closet 83N10." You made it! Now, to find those anomalies.

+

Outside the utility closet, you hear footsteps and a voice. "...I'm not sure either. But now that so many people have chimneys, maybe he could sneak in that way?" Another voice responds, "Actually, we've been working on a new kind of suit that would let him fit through tight spaces like that. But, I heard that a few days ago, they lost the prototype fabric, the design plans, everything! Nobody on the team can even seem to remember important details of the project!"

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2018.Day02;
+
+[ProblemName("Inventory Management System")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var doubles = (
+            from line in input.Split("\n")
+            where CheckLine(line, 2)
+            select line
+        ).Count();
+        var tripples = (
+            from line in input.Split("\n")
+            where CheckLine(line, 3)
+            select line
+        ).Count();
+        return doubles * tripples;
+    }
+
+    bool CheckLine(string line, int n) {
+        return (from ch in line
+                group ch by ch into g
+                select g.Count()).Any(cch => cch == n);
+    }
+
+    public object PartTwo(string input) {
+        var lines = input.Split("\n");
+        return (from i in Enumerable.Range(0, lines.Length)
+                from j in Enumerable.Range(i + 1, lines.Length - i - 1)
+                let line1 = lines[i]
+                let line2 = lines[j]
+                where Diff(line1, line2) == 1
+                select Common(line1, line2)
+        ).Single();
+    }
+
+    int Diff(string line1, string line2) {
+        return line1.Zip(line2, 
+            (chA, chB) => chA == chB
+        ).Count(x => x == false);
+    }
+
+    string Common(string line1, string line2) {
+        return string.Join("", line1.Zip(line2, (chA, chB) => chA == chB ? chA.ToString() : ""));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/20/illustration.jpeg b/2018/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/20/illustration.jpeg differ diff --git a/2018/20/index.html b/2018/20/index.html new file mode 100644 index 00000000..3f59a6da --- /dev/null +++ b/2018/20/index.html @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/20 'A Regular Map'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/20

+

A Regular Map

+

in C#

+

+

by encse

+
+ +
+ +
+

While you were learning about instruction pointers, the Elves made considerable progress. When you look up, you discover that the North Pole base construction project has completely surrounded you.

+

The area you are in is made up entirely of rooms and doors. The rooms are arranged in a grid, and rooms only connect to adjacent rooms when a door is present between them.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day20;
+[ProblemName("A Regular Map")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solver(input).dMax;
+    public object PartTwo(string input) => Solver(input).distantRooms;
+
+    (int dMax, int distantRooms) Solver(string input) {
+        var grid = Doors(input)
+            .ToList()
+            .GroupBy(x => x.posFrom)
+            .ToDictionary(x=>x.Key, x=> x.Select(y => y.posTo).ToList());
+                   
+        var queue = new Queue<((int x, int y) pos, int d)>();
+        queue.Enqueue(((0, 0), 0));
+
+        var seen = new HashSet<(int x, int y)>();
+        var (dMax, distantRooms) = (int.MinValue, 0);
+
+        while (queue.Any()) {
+            var (pos, d) = queue.Dequeue();
+            if (seen.Contains(pos)) {
+                continue;
+            }
+
+            dMax = Math.Max(dMax, d);
+            if (d >= 1000) {
+                distantRooms++;
+            }
+
+            seen.Add(pos);
+            foreach (var nextPos in grid[pos]) {
+                queue.Enqueue((nextPos, d + 1));
+            }
+        }
+
+        return (dMax, distantRooms);
+    }
+
+    IEnumerable<((int x, int y) posFrom, (int x, int y) posTo)> Doors(string input) {
+        var s = new Stack<(int x, int y)>();
+        (int x, int y) pos = (0, 0);
+        foreach (var ch in input) {
+            var prev = pos;
+            switch (ch) {
+                case 'N': pos = (pos.x, pos.y - 1); break;
+                case 'S': pos = (pos.x, pos.y + 1); break;
+                case 'E': pos = (pos.x + 1, pos.y); break;
+                case 'W': pos = (pos.x - 1, pos.y); break;
+                case '(': s.Push(pos); break;
+                case '|': pos = s.Peek(); break;
+                case ')': pos = s.Pop(); break;
+            }
+
+            if ("NSEW".IndexOf(ch) >= 0) {
+                yield return (prev, pos);
+                yield return (pos, prev);
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/21/illustration.jpeg b/2018/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/21/illustration.jpeg differ diff --git a/2018/21/index.html b/2018/21/index.html new file mode 100644 index 00000000..9f731b74 --- /dev/null +++ b/2018/21/index.html @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/21 'Chronal Conversion'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/21

+

Chronal Conversion

+

in C#

+

+

by encse

+
+ +
+ +
+

You should have been watching where you were going, because as you wander the new North Pole base, you trip and fall into a very deep hole!

+

Just kidding. You're falling through time again.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day21;
+
+[ProblemName("Chronal Conversion")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Run(input).First();
+    public object PartTwo(string input) => Run(input).Last();
+
+    public IEnumerable Run(string input) {
+        var breakpoint = 28;
+        var seen = new List();
+
+        foreach (var regs in Trace(input, breakpoint)) {
+            if (seen.Contains(regs[3])) {
+                break;
+            }
+            seen.Add(regs[3]);
+            yield return regs[3];
+        }
+    }
+
+    public IEnumerable Trace(string input, int breakpoint) {
+        var lines = input.Split("\n");
+        var ipReg = int.Parse(lines.First().Split(" ")[1]);
+        var program = lines.Skip(1).Select(Compile).ToArray();
+        var regs = new long[] { 0, 0, 0, 0, 0, 0 };
+
+        while (true) {
+            if (regs[ipReg] == breakpoint) {
+                yield return regs;
+            }
+            program[regs[ipReg]](regs);
+            regs[ipReg]++;
+        }
+    }
+
+    Action Compile(string line) {
+        var parts = line.Split(" ");
+        var op = parts[0];
+        var args = parts.Skip(1).Select(long.Parse).ToArray();
+        return op switch {
+            "addr" => regs => regs[args[2]] = regs[args[0]] + regs[args[1]],
+            "addi" => regs => regs[args[2]] = regs[args[0]] + args[1],
+            "mulr" => regs => regs[args[2]] = regs[args[0]] * regs[args[1]],
+            "muli" => regs => regs[args[2]] = regs[args[0]] * args[1],
+            "banr" => regs => regs[args[2]] = regs[args[0]] & regs[args[1]],
+            "bani" => regs => regs[args[2]] = regs[args[0]] & args[1],
+            "borr" => regs => regs[args[2]] = regs[args[0]] | regs[args[1]],
+            "bori" => regs => regs[args[2]] = regs[args[0]] | args[1],
+            "setr" => regs => regs[args[2]] = regs[args[0]],
+            "seti" => regs => regs[args[2]] = args[0],
+            "gtir" => regs => regs[args[2]] = args[0] > regs[args[1]] ? 1 : 0,
+            "gtri" => regs => regs[args[2]] = regs[args[0]] > args[1] ? 1 : 0,
+            "gtrr" => regs => regs[args[2]] = regs[args[0]] > regs[args[1]] ? 1 : 0,
+            "eqir" => regs => regs[args[2]] = args[0] == regs[args[1]] ? 1 : 0,
+            "eqri" => regs => regs[args[2]] = regs[args[0]] == args[1] ? 1 : 0,
+            "eqrr" => regs => regs[args[2]] = regs[args[0]] == regs[args[1]] ? 1 : 0,
+            _ => throw new ArgumentException()
+        };
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/22/illustration.jpeg b/2018/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/22/illustration.jpeg differ diff --git a/2018/22/index.html b/2018/22/index.html new file mode 100644 index 00000000..125989af --- /dev/null +++ b/2018/22/index.html @@ -0,0 +1,436 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/22 'Mode Maze'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/22

+

Mode Maze

+

in C#

+

+

by encse

+
+ +
+ +
+

This is it, your final stop: the year -483. It's snowing and dark outside; the only light you can see is coming from a small cottage in the distance. You make your way there and knock on the door.

+

A portly man with a large, white beard answers the door and invites you inside. For someone living near the North Pole in -483, he must not get many visitors, but he doesn't act surprised to see you. Instead, he offers you some milk and cookies.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day22;
+
+[ProblemName("Mode Maze")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var (targetX, targetY, regionType) = Parse(input);
+        var riskLevel = 0;
+        for (var y = 0; y <= targetY; y++) {
+            for (var x = 0; x <= targetX; x++) {
+                riskLevel += (int)regionType(x, y);
+            }
+        }
+        return riskLevel;
+    }
+
+
+    public object PartTwo(string input) {
+        var (targetX, targetY, regionType) = Parse(input);
+        var q = new PQueue<((int x, int y) pos, Tool tool, int t)>();
+        var seen = new HashSet<((int x, int y), Tool tool)>();
+
+        IEnumerable<((int x, int y) pos, Tool tool, int dt)> Neighbours((int x, int y) pos, Tool tool) {
+            yield return regionType(pos.x, pos.y) switch {
+                RegionType.Rocky => (pos, tool == Tool.ClimbingGear ? Tool.Torch : Tool.ClimbingGear, 7),
+                RegionType.Narrow => (pos, tool == Tool.Torch ? Tool.Nothing : Tool.Torch, 7),
+                RegionType.Wet => (pos, tool == Tool.ClimbingGear ? Tool.Nothing : Tool.ClimbingGear, 7),
+                _ => throw new ArgumentException()
+            };
+
+            foreach (var dx in new[] { -1, 0, 1 }) {
+                foreach (var dy in new[] { -1, 0, 1 }) {
+                    if (Math.Abs(dx) + Math.Abs(dy) != 1) {
+                        continue;
+                    }
+
+                    var posNew = (x: pos.x + dx, y: pos.y + dy);
+                    if (posNew.x < 0 || posNew.y < 0) {
+                        continue;
+                    }
+
+                    switch (regionType(posNew.x, posNew.y)) {
+                        case RegionType.Rocky when tool == Tool.ClimbingGear || tool == Tool.Torch:
+                        case RegionType.Narrow when tool == Tool.Torch || tool == Tool.Nothing:
+                        case RegionType.Wet when tool == Tool.ClimbingGear || tool == Tool.Nothing:
+                            yield return (posNew, tool, 1);
+                            break;
+                    }
+                }
+            }
+        }
+
+        q.Enqueue(0, ((0, 0), Tool.Torch, 0));
+
+        while (q.Any()) {
+            var state = q.Dequeue();
+            var (pos, tool, t) = state;
+
+            if (pos.x == targetX && pos.y == targetY && tool == Tool.Torch) {
+                return t;
+            }
+
+            var hash = (pos, tool);
+            if (seen.Contains(hash)) {
+                continue;
+            }
+
+            seen.Add(hash);
+
+            foreach( var (newPos, newTool, dt) in Neighbours(pos, tool)) {
+                q.Enqueue(
+                    t + dt + Math.Abs(newPos.x - targetX) + Math.Abs(newPos.y - targetY), 
+                    (newPos, newTool, t + dt)
+                );
+            }
+
+        }
+
+        throw new Exception();
+    }
+
+    (int targetX, int targetY, Func regionType) Parse(string input) {
+        var lines = input.Split("\n");
+        var depth = Regex.Matches(lines[0], @"\d+").Select(x => int.Parse(x.Value)).Single();
+        var target = Regex.Matches(lines[1], @"\d+").Select(x => int.Parse(x.Value)).ToArray();
+        var (targetX, targetY) = (target[0], target[1]);
+
+        var m = 20183;
+
+        var erosionLevelCache = new Dictionary<(int, int), int>();
+        int erosionLevel(int x, int y) {
+            var key = (x, y);
+            if (!erosionLevelCache.ContainsKey(key)) {
+                if (x == targetX && y == targetY) {
+                    erosionLevelCache[key] = depth;
+                } else if (x == 0 && y == 0) {
+                    erosionLevelCache[key] = depth;
+                } else if (x == 0) {
+                    erosionLevelCache[key] = ((y * 48271) + depth) % m;
+                } else if (y == 0) {
+                    erosionLevelCache[key] = ((x * 16807) + depth) % m;
+                } else {
+                    erosionLevelCache[key] = ((erosionLevel(x, y - 1) * erosionLevel(x - 1, y)) + depth) % m;
+                }
+            }
+            return erosionLevelCache[key];
+        }
+
+        RegionType regionType(int x, int y) {
+            return (RegionType)(erosionLevel(x, y) % 3);
+        }
+
+        return (targetX, targetY, regionType);
+    }
+}
+enum RegionType {
+    Rocky = 0,
+    Wet = 1,
+    Narrow = 2
+}
+
+enum Tool {
+    Nothing,
+    Torch,
+    ClimbingGear
+}
+
+class PQueue {
+    SortedDictionary> d = new SortedDictionary>();
+    public bool Any() {
+        return d.Any();
+    }
+
+    public void Enqueue(int p, T t) {
+        if (!d.ContainsKey(p)) {
+            d[p] = new Queue();
+        }
+        d[p].Enqueue(t);
+    }
+
+    public T Dequeue() {
+        var p = d.Keys.First();
+        var items = d[p];
+        var t = items.Dequeue();
+        if (!items.Any()) {
+            d.Remove(p);
+        }
+        return t;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/23/illustration.jpeg b/2018/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/23/illustration.jpeg differ diff --git a/2018/23/index.html b/2018/23/index.html new file mode 100644 index 00000000..ed226684 --- /dev/null +++ b/2018/23/index.html @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/23 'Experimental Emergency Teleportation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/23

+

Experimental Emergency Teleportation

+

in C#

+

+

by encse

+
+ +
+ +
+

Using your torch to search the darkness of the rocky cavern, you finally locate the man's friend: a small reindeer.

+

You're not sure how it got so far in this cave. It looks sick - too sick to walk - and too heavy for you to carry all the way back. Sleighs won't be invented for another 1500 years, of course.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day23;
+
+[ProblemName("Experimental Emergency Teleportation")]
+class Solution : Solver {
+
+    int Dist((int x, int y, int z) a, (int x, int y, int z) b) => Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y) + Math.Abs(a.z - b.z);
+
+    public object PartOne(string input) {
+        var drones = Parse(input);
+        var maxRange = drones.Select(drone => drone.r).Max();
+        var maxDrone = drones.Single(drone => drone.r == maxRange);
+        return drones.Count(drone => Dist(drone.pos, maxDrone.pos) <= maxRange);
+    }
+
+    IEnumerable<(int x, int y, int z)> Corners(Drone[] drones) => (
+        from drone in drones
+        from dx in new[] { -1, 0, 1 }
+        from dy in new[] { -1, 0, 1 }
+        from dz in new[] { -1, 0, 1 }
+        where dx * dx + dy * dy + dz * dz == 1
+        select (drone.pos.x + dx * drone.r, drone.pos.y + dy * drone.r, drone.pos.z + dz * drone.r)
+    ).ToArray();
+
+    Drone[] Parse(string input) => (
+        from line in input.Split("\n")
+        let parts = Regex.Matches(line, @"-?\d+").Select(x => int.Parse(x.Value)).ToArray()
+        select new Drone((parts[0], parts[1], parts[2]), parts[3])
+    ).ToArray();
+
+    public object PartTwo(string input) {
+        var drones = Parse(input);
+        var minX = drones.Select(drone => drone.pos.x).Min();
+        var minY = drones.Select(drone => drone.pos.y).Min();
+        var minZ = drones.Select(drone => drone.pos.z).Min();
+
+        var maxX = drones.Select(drone => drone.pos.x).Max();
+        var maxY = drones.Select(drone => drone.pos.y).Max();
+        var maxZ = drones.Select(drone => drone.pos.z).Max();
+
+        return Solve(new Box((minX, minY, minZ), (maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1)), drones).pt;
+    }
+
+    (int drones, int pt) Solve(Box box, Drone[] drones) {
+
+        var q = new PQueue<(int, int), (Box box, Drone[] drones)>();
+        q.Enqueue((0, 0), (box, drones));
+
+        while (q.Any()) {
+            (box, drones) = q.Dequeue();
+
+            if (box.Size() == 1) {
+                return (drones.Count(drone => drone.Contains(box)), box.Dist());
+            } else {
+                foreach (var subBox in box.Divide()) {
+                    var intersectingDrones = drones.Where(drone => drone.Intersects(subBox)).ToArray();
+                    q.Enqueue((-intersectingDrones.Count(), subBox.Dist()), (subBox, intersectingDrones));
+                }
+            }
+        }
+        throw new Exception();
+    }
+
+}
+
+class Box {
+    public readonly (int x, int y, int z) min;
+    public readonly (int x, int y, int z) max;
+    private readonly (int sx, int sy, int sz) size;
+    public Box((int x, int y, int z) min, (int sx, int sy, int sz) size) {
+        this.min = min;
+        this.max = (min.x + size.sx - 1, min.y + size.sy - 1, min.z + size.sz - 1);
+        this.size = size;
+    }
+
+    public IEnumerable<(int x, int y, int z)> Corners() {
+        yield return (min.x, min.y, min.z);
+        yield return (max.x, min.y, min.z);
+        yield return (min.x, max.y, min.z);
+        yield return (max.x, max.y, min.z);
+
+        yield return (min.x, min.y, max.z);
+        yield return (max.x, min.y, max.z);
+        yield return (min.x, max.y, max.z);
+        yield return (max.x, max.y, max.z);
+    }
+    
+    public IEnumerable Divide() {
+        var sx = size.sx / 2;
+        var tx = size.sx - sx; 
+        var sy = size.sy / 2;
+        var ty = size.sy - sy;
+        var sz = size.sz / 2;
+        var tz = size.sz - sz;
+
+        return new[]{
+            new Box((min.x,      min.y,       min.z     ), (sx, sy, sz)),
+            new Box((min.x + sx, min.y,       min.z     ), (tx, sy, sz)),
+            new Box((min.x,      min.y + sy,  min.z     ), (sx, ty, sz)),
+            new Box((min.x + sx, min.y + sy,  min.z     ), (tx, ty, sz)),
+
+            new Box((min.x,      min.y,       min.z + sz), (sx, sy, tz)),
+            new Box((min.x + sx, min.y,       min.z + sz), (tx, sy, tz)),
+            new Box((min.x,      min.y + sy,  min.z + sz), (sx, ty, tz)),
+            new Box((min.x + sx, min.y + sy,  min.z + sz), (tx, ty, tz)),
+
+        }.Where(box => box.size.sx > 0 && box.size.sy > 0 && box.size.sz > 0);
+    }
+
+    public int Dist() {
+        return Corners().Select(pt => Math.Abs(pt.x) + Math.Abs(pt.y) + Math.Abs(pt.z)).Min();
+    }
+
+    public BigInteger Size() {
+        return (BigInteger)size.sx * (BigInteger)size.sy * (BigInteger)size.sz;
+    }
+}
+
+class Drone {
+    public readonly (int x, int y, int z) pos;
+    public readonly int r;
+    public readonly Box box;
+    public Drone((int x, int y, int z) pos, int r) {
+        this.pos = pos;
+        this.r = r;
+        box = new Box((pos.x - r, pos.y - r, pos.z - r), (2 * r + 1, 2 * r + 1, 2 * r + 1));
+    }
+
+    public bool Intersects(Box box) {
+        var dx = Math.Max(0, Math.Max(box.min.x - pos.x, pos.x - box.max.x));
+        var dy = Math.Max(0, Math.Max(box.min.y - pos.y, pos.y - box.max.y));
+        var dz = Math.Max(0, Math.Max(box.min.z - pos.z, pos.z - box.max.z));
+
+        return Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz) <= r;
+    }
+
+    public bool Contains(Box box) {
+        return box
+            .Corners()
+            .All(pt => Math.Abs(pt.x - pos.x) + Math.Abs(pt.y - pos.y) + Math.Abs(pt.z - pos.z) <= r);
+    }
+}
+
+class PQueue where K : IComparable {
+    SortedDictionary> d = new SortedDictionary>();
+    int c = 0;
+    public bool Any() {
+        return d.Any();
+    }
+
+    public void Enqueue(K p, T t) {
+        if (!d.ContainsKey(p)) {
+            d[p] = new Queue();
+        }
+        d[p].Enqueue(t);
+        c++;
+    }
+
+    public T Dequeue() {
+        c--;
+        var p = d.Keys.First();
+        var items = d[p];
+        var t = items.Dequeue();
+        if (!items.Any()) {
+            d.Remove(p);
+        }
+        return t;
+    }
+
+    public int Count() {
+        return c;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/24/illustration.jpeg b/2018/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/24/illustration.jpeg differ diff --git a/2018/24/index.html b/2018/24/index.html new file mode 100644 index 00000000..39cc959f --- /dev/null +++ b/2018/24/index.html @@ -0,0 +1,421 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/24 'Immune System Simulator 20XX'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/24

+

Immune System Simulator 20XX

+

in C#

+

+

by encse

+
+ +
+ +
+

After a weird buzzing noise, you appear back at the man's cottage. He seems relieved to see his friend, but quickly notices that the little reindeer caught some kind of cold while out exploring.

+

The portly man explains that this reindeer's immune system isn't similar to regular reindeer immune systems:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day24;
+
+[ProblemName("Immune System Simulator 20XX")]
+class Solution : Solver {
+
+    (bool immuneSystem, long units) Fight(string input, int boost) {
+        var army = Parse(input);
+        foreach (var g in army) {
+            if (g.immuneSystem) {
+                g.damage += boost;
+            }
+        }
+        var attack = true;
+        while (attack) {
+            attack = false;
+            var remainingTarget = new HashSet(army);
+            var targets = new Dictionary();
+            foreach (var g in army.OrderByDescending(g => (g.effectivePower, g.initiative))) {
+                var maxDamage = remainingTarget.Select(t => g.DamageDealtTo(t)).Max();
+                if (maxDamage > 0) {
+                    var possibleTargets = remainingTarget.Where(t => g.DamageDealtTo(t) == maxDamage);
+                    targets[g] = possibleTargets.OrderByDescending(t => (t.effectivePower, t.initiative)).First();
+                    remainingTarget.Remove(targets[g]);
+                }
+            }
+            foreach (var g in targets.Keys.OrderByDescending(g => g.initiative)) {
+                if (g.units > 0) {
+                    var target = targets[g];
+                    var damage = g.DamageDealtTo(target);
+                    if (damage > 0 && target.units > 0) {
+                        var dies = damage / target.hp;
+                        target.units = Math.Max(0, target.units - dies);
+                        if (dies > 0) {
+                            attack = true;
+                        }
+                    }
+                }
+            }
+            army = army.Where(g => g.units > 0).ToList();
+        }
+        return (army.All(x => x.immuneSystem), army.Select(x => x.units).Sum());
+    }
+
+    public object PartOne(string input) => Fight(input, 0).units;
+
+    public object PartTwo(string input) {
+        var l = 0;
+        var h = int.MaxValue / 2;
+        while (h - l > 1) {
+            var m = (h + l) / 2;
+            if (Fight(input, m).immuneSystem) {
+                h = m;
+            } else {
+                l = m;
+            }
+        }
+        return Fight(input, h).units;
+    }
+
+    List Parse(string input) {
+        var lines = input.Split("\n");
+        var immuneSystem = false;
+        var res = new List();
+        foreach (var line in lines)
+            if (line == "Immune System:") {
+                immuneSystem = true;
+            } else if (line == "Infection:") {
+                immuneSystem = false;
+            } else if (line != "") {
+                //643 units each with 9928 hit points (immune to fire; weak to slashing, bludgeoning) with an attack that does 149 fire damage at initiative 14
+                var rx = @"(\d+) units each with (\d+) hit points(.*)with an attack that does (\d+)(.*)damage at initiative (\d+)";
+                var m = Regex.Match(line, rx);
+                if (m.Success) {
+                    Group g = new Group();
+                    g.immuneSystem = immuneSystem;
+                    g.units = int.Parse(m.Groups[1].Value);
+                    g.hp = int.Parse(m.Groups[2].Value);
+                    g.damage = int.Parse(m.Groups[4].Value);
+                    g.attackType = m.Groups[5].Value.Trim();
+                    g.initiative = int.Parse(m.Groups[6].Value);
+                    var st = m.Groups[3].Value.Trim();
+                    if (st != "") {
+                        st = st.Substring(1, st.Length - 2);
+                        foreach (var part in st.Split(";")) {
+                            var k = part.Split(" to ");
+                            var set = new HashSet(k[1].Split(", "));
+                            var w = k[0].Trim();
+                            if (w == "immune") {
+                                g.immuneTo = set;
+                            } else if (w == "weak") {
+                                g.weakTo = set;
+                            } else {
+                                throw new Exception();
+                            }
+                        }
+                    }
+                    res.Add(g);
+                } else {
+                    throw new Exception();
+                }
+
+            }
+        return res;
+    }
+}
+
+class Group {
+    //4 units each with 9798 hit points (immune to bludgeoning) with an attack that does 1151 fire damage at initiative 9
+    public bool immuneSystem;
+    public long units;
+    public int hp;
+    public int damage;
+    public int initiative;
+    public string attackType;
+    public HashSet immuneTo = new HashSet();
+    public HashSet weakTo = new HashSet();
+
+    public long effectivePower {
+        get {
+            return units * damage;
+        }
+    }
+
+    public long DamageDealtTo(Group target) {
+        if (target.immuneSystem == immuneSystem) {
+            return 0;
+        } else if (target.immuneTo.Contains(attackType)) {
+            return 0;
+        } else if (target.weakTo.Contains(attackType)) {
+            return effectivePower * 2;
+        } else {
+            return effectivePower;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/25/illustration.jpeg b/2018/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/25/illustration.jpeg differ diff --git a/2018/25/index.html b/2018/25/index.html new file mode 100644 index 00000000..4be2e27a --- /dev/null +++ b/2018/25/index.html @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/25 'Four-Dimensional Adventure'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/25

+

Four-Dimensional Adventure

+

in C#

+

+

by encse

+
+ +
+ +
+

The reindeer's symptoms are getting worse, and neither you nor the white-bearded man have a solution. At least the reindeer has a warm place to rest: a small bed near where you're sitting.

+

As you reach down, the reindeer looks up at you, accidentally bumping a button on your wrist-mounted device with its nose in the process - a button labeled "help".

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day25;
+
+[ProblemName("Four-Dimensional Adventure")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var sets = new List>();
+
+        foreach (var line in input.Split("\n")) {
+            var set = new HashSet();
+            set.Add(line.Split(",").Select(int.Parse).ToArray());
+            sets.Add(set);
+        }
+
+        foreach (var set in sets.ToList()) {
+            var pt = set.Single();
+            var closeSets = new List>();
+            foreach (var setB in sets) {
+                foreach (var ptB in setB) {
+                    if (Dist(pt, ptB) <= 3) {
+                        closeSets.Add(setB);
+                    }
+                }
+            }
+            var mergedSet = new HashSet();
+            foreach (var setB in closeSets) {
+                foreach (var ptB in setB) {
+                    mergedSet.Add(ptB);
+                }
+                sets.Remove(setB);
+            }
+            sets.Add(mergedSet);
+        }
+
+        return sets.Count;
+    }
+   
+    int Dist(int[] a, int[] b) => Enumerable.Range(0, a.Length).Select(i => Math.Abs(a[i] - b[i])).Sum();
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/3/illustration.jpeg b/2018/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/3/illustration.jpeg differ diff --git a/2018/3/index.html b/2018/3/index.html new file mode 100644 index 00000000..26aeec51 --- /dev/null +++ b/2018/3/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/3 'No Matter How You Slice It'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/3

+

No Matter How You Slice It

+

in C#

+

+

by encse

+
+ +
+ +
+

The Elves managed to locate the chimney-squeeze prototype fabric for Santa's suit (thanks to someone who helpfully wrote its box IDs on the wall of the warehouse in the middle of the night). Unfortunately, anomalies are still affecting them - nobody can even agree on how to cut the fabric.

+

The whole piece of fabric they're working on is a very large square - at least 1000 inches on each side.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day03;
+
+[ProblemName("No Matter How You Slice It")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Decorate(input).overlapArea;
+
+    public object PartTwo(string input) => Decorate(input).intactId;
+
+    (int overlapArea, int intactId) Decorate(string input) {
+        // #1 @ 55,885: 22x10
+        var rx = new Regex(@"(?\d+) @ (?\d+),(?\d+): (?\d+)x(?\d+)");
+        var mtx = new int[1000, 1000];
+
+        var overlapArea = 0;
+
+        var ids = new HashSet();
+        foreach (var line in input.Split("\n")) {
+            var parts = rx.Match(line);
+            var id = int.Parse(parts.Groups["id"].Value);
+            var x = int.Parse(parts.Groups["x"].Value);
+            var y = int.Parse(parts.Groups["y"].Value);
+            var width = int.Parse(parts.Groups["width"].Value);
+            var height = int.Parse(parts.Groups["height"].Value);
+
+            ids.Add(id);
+
+            for (var i = 0; i < width; i++) {
+                for (var j = 0; j < height; j++) {
+                    if (mtx[x + i, y + j] == 0) {
+                        mtx[x + i, y + j] = id;
+                    } else if (mtx[x + i, y + j] == -1) {
+                        ids.Remove(id);
+                    } else {
+                        ids.Remove(mtx[x + i, y + j]);
+                        ids.Remove(id);
+                        overlapArea++;
+
+                        mtx[x + i, y + j] = -1;
+                    }
+                }
+            }
+        }
+
+        return (overlapArea, ids.Single());
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/4/illustration.jpeg b/2018/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/4/illustration.jpeg differ diff --git a/2018/4/index.html b/2018/4/index.html new file mode 100644 index 00000000..eeb65283 --- /dev/null +++ b/2018/4/index.html @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/4 'Repose Record'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/4

+

Repose Record

+

in C#

+

+

by encse

+
+ +
+ +
+

You've sneaked into another supply closet - this time, it's across from the prototype suit manufacturing lab. You need to sneak inside and fix the issues with the suit, but there's a guard stationed outside the lab, so this is as close as you can safely get.

+

As you search the closet for anything that might help, you discover that you're not the first person to want to sneak in. Covering the walls, someone has spent an hour starting every midnight for the past few months secretly observing this guard post! They've been writing down the ID of the one guard on duty that night - the Elves seem to have decided that one guard was enough for the overnight shift - as well as when they fall asleep or wake up while at their post (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day04;
+
+[ProblemName("Repose Record")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var foo = from day in Parse(input)
+                group day by day.guard into g
+                select new { 
+                    guard = g.Key, 
+                    totalSleeps = g.Select(day => day.totalSleep).Sum(), 
+                    sleepByMin = Enumerable.Range(0, 60).Select(minT => g.Sum(day => day.sleep[minT])).ToArray()
+                };
+        var maxSleep = foo.Max(x => x.totalSleeps);
+        var fooT = foo.Single(g => g.totalSleeps == maxSleep);
+        var maxSleepByMin = Enumerable.Range(0, 60).Max(minT => fooT.sleepByMin[minT]);
+        var min = Enumerable.Range(0, 60).Single(minT => fooT.sleepByMin[minT] == maxSleepByMin);
+        return fooT.guard * min;
+    }
+
+    public object PartTwo(string input) {
+        var foo = from day in Parse(input)
+                group day by day.guard into g
+                select new { 
+                    guard = g.Key, 
+                    totalSleeps = g.Select(day => day.totalSleep).Sum(), 
+                    sleepByMin = Enumerable.Range(0, 60).Select(minT => g.Sum(day => day.sleep[minT])).ToArray()
+                };
+
+        var maxMaxSleep = foo.Max(x => x.sleepByMin.Max());
+        var fooT = foo.Single(x => x.sleepByMin.Max() == maxMaxSleep);
+        var min = Enumerable.Range(0, 60).Single(minT => fooT.sleepByMin[minT] == maxMaxSleep);
+
+        return fooT.guard * min;
+    }
+
+    IEnumerable Parse(string input) {
+        var lines = input.Split("\n").ToList();
+        lines.Sort((x, y) => DateTime.Parse(x.Substring(1, "1518-03-25 00:01".Length)).CompareTo(DateTime.Parse(y.Substring(1, "1518-03-25 00:01".Length))));
+        var iline = 0;
+
+        while (Int(@"Guard #(\d+) begins shift", out var guard)) {
+
+            var sleep = new int[60];
+            while (Date(@"\[(.*)\] falls asleep", out var fallsAsleap)) {
+                Date(@"\[(.*)\] wakes up", out var wakesUp);
+
+                var from = fallsAsleap.Hour != 0 ? 0 : fallsAsleap.Minute;
+                var to = wakesUp.Hour != 0 ? 0 : wakesUp.Minute;
+
+                for (var min = from; min < to; min++) {
+                    sleep[min] = 1;
+                }
+            }
+
+            yield return new Day() { guard = guard, sleep = sleep };
+        }
+
+        if (iline != lines.Count) {
+            throw new Exception();
+        }
+        bool Int(string pattern, out int r) {
+            r = 0;
+            return String(pattern, out string st) && int.TryParse(st, out r);
+        }
+
+        bool Date(string pattern, out DateTime r) {
+            r = DateTime.MinValue;
+            return String(pattern, out string st) && DateTime.TryParse(st, out r);
+        }
+
+        bool String(string pattern, out string st) {
+            st = null;
+            if (iline >= lines.Count) {
+                return false;
+            }
+            var m = Regex.Match(lines[iline], pattern);
+            if (m.Success) {
+                iline++;
+                st = m.Groups[1].Value;
+            }
+            return m.Success;
+        }
+
+    }
+}
+
+class Day {
+    public int guard;
+    public int[] sleep;
+    public int totalSleep => sleep.Sum();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/5/illustration.jpeg b/2018/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/5/illustration.jpeg differ diff --git a/2018/5/index.html b/2018/5/index.html new file mode 100644 index 00000000..d86f4f9d --- /dev/null +++ b/2018/5/index.html @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/5 'Alchemical Reduction'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/5

+

Alchemical Reduction

+

in C#

+

+

by encse

+
+ +
+ +
+

You've managed to sneak in to the prototype suit manufacturing lab. The Elves are making decent progress, but are still struggling with the suit's size reduction capabilities.

+

While the very latest in 1518 alchemical technology might have solved their problem eventually, you can do better. You scan the chemical composition of the suit's material and discover that it is formed by extremely long polymers (one of which is available as your puzzle input).

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day05;
+
+[ProblemName("Alchemical Reduction")]
+class Solution : Solver {
+
+    public object PartOne(string input) => React(input);
+
+    public object PartTwo(string input) => (from ch in "abcdefghijklmnopqrstuvwxyz" select React(input, ch)).Min();
+
+    char ToLower(char ch) => ch <= 'Z' ? (char)(ch - 'A' + 'a') : ch;
+
+    int React(string input, char? skip = null) {
+        var stack = new Stack("⊥");
+        
+        foreach (var ch in input) {
+            var top = stack.Peek();
+            if (ToLower(ch) == skip) {
+                continue;
+            } else if (top != ch && ToLower(ch) == ToLower(top)) {
+                stack.Pop();
+            } else {
+                stack.Push(ch);
+            }
+        }
+        return stack.Count() - 1;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/6/illustration.jpeg b/2018/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/6/illustration.jpeg differ diff --git a/2018/6/index.html b/2018/6/index.html new file mode 100644 index 00000000..4fb268bb --- /dev/null +++ b/2018/6/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/6 'Chronal Coordinates'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/6

+

Chronal Coordinates

+

in C#

+

+

by encse

+
+ +
+ +
+

The device on your wrist beeps several times, and once again you feel like you're falling.

+

"Situation critical," the device announces. "Destination indeterminate. Chronal interference detected. Please specify new target coordinates."

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day06;
+
+[ProblemName("Chronal Coordinates")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var coords = Parse(input);
+
+        var minX = coords.Min(coord => coord.x) - 1;
+        var maxX = coords.Max(coord => coord.x) + 1;
+        var minY = coords.Min(coord => coord.y) - 1;
+        var maxY = coords.Max(coord => coord.y) + 1;
+
+        var area = new int[coords.Length];
+
+        foreach (var x in Enumerable.Range(minX, maxX - minX + 1)) {
+            foreach (var y in Enumerable.Range(minY, maxY - minX + 1)) {
+                var d = coords.Select(coord => Dist((x, y), coord)).Min();
+                var closest = Enumerable.Range(0, coords.Length).Where(i => Dist((x, y), coords[i]) == d).ToArray();
+
+                if (closest.Length != 1) {
+                    continue;
+                }
+
+                if (x == minX || x == maxX || y == minY || y == maxY) {
+                    foreach (var icoord in closest) {
+                        if (area[icoord] != -1) {
+                            area[icoord] = -1;
+                        }
+                    }
+                } else {
+                    foreach (var icoord in closest) {
+                        if (area[icoord] != -1) {
+                            area[icoord]++;
+                        }
+                    }
+                }
+            }
+        }
+        return area.Max();
+    }
+
+    public object PartTwo(string input) {
+        var coords = Parse(input);
+
+        var minX = coords.Min(coord => coord.x) - 1;
+        var maxX = coords.Max(coord => coord.x) + 1;
+        var minY = coords.Min(coord => coord.y) - 1;
+        var maxY = coords.Max(coord => coord.y) + 1;
+
+        var area = 0;
+
+        foreach (var x in Enumerable.Range(minX, maxX - minX + 1)) {
+            foreach (var y in Enumerable.Range(minY, maxY - minX + 1)) {
+                var d = coords.Select(coord => Dist((x, y), coord)).Sum();
+                if (d < 10000)
+                    area++;
+            }
+        }
+        return area;
+    }
+
+    int Dist((int x, int y) c1, (int x, int y) c2) {
+        return Math.Abs(c1.x - c2.x) + Math.Abs(c1.y - c2.y);
+    }
+
+    (int x, int y)[] Parse(string input) => (
+            from line in input.Split("\n")
+            let coords = line.Split(", ").Select(int.Parse).ToArray()
+            select (coords[0], coords[1])
+        ).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/7/illustration.jpeg b/2018/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/7/illustration.jpeg differ diff --git a/2018/7/index.html b/2018/7/index.html new file mode 100644 index 00000000..1aa8a980 --- /dev/null +++ b/2018/7/index.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/7 'The Sum of Its Parts'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/7

+

The Sum of Its Parts

+

in C#

+

+

by encse

+
+ +
+ +
+

You find yourself standing on a snow-covered coastline; apparently, you landed a little off course. The region is too hilly to see the North Pole from here, but you do spot some Elves that seem to be trying to unpack something that washed ashore. It's quite cold out, so you decide to risk creating a paradox by asking them for directions.

+

"Oh, are you the search party?" Somehow, you can understand whatever Elves from the year 1018 speak; you assume it's Ancient Nordic Elvish. Could the device on your wrist also be a translator? "Those clothes don't look very warm; take this." They hand you a heavy coat.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AdventOfCode.Y2018.Day07;
+
+[ProblemName("The Sum of Its Parts")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+
+        var sb = new StringBuilder();
+        var graph = Parse(input);
+        while (graph.Any()) {
+            char minKey = char.MaxValue;
+            foreach (var key in graph.Keys) {
+                if (graph[key].Count == 0) {
+                    if (key < minKey) {
+                        minKey = key;
+                    }
+                }
+            }
+            sb.Append(minKey);
+            graph.Remove(minKey);
+            foreach (var key in graph.Keys) {
+                graph[key].Remove(minKey);
+            }
+        }
+        return sb.ToString();
+    }
+
+    public object PartTwo(string input) {
+        var time = 0;
+        var graph = Parse(input);
+
+        var works = new int[5];
+        var items = new char[works.Length];
+
+        while (graph.Any() || works.Any(work => work > 0)) {
+            for (var i = 0; i < works.Length && graph.Any(); i++) {
+                // start working
+                if (works[i] == 0) {
+                    char minKey = char.MaxValue;
+                    foreach (var key in graph.Keys) {
+                        if (graph[key].Count == 0) {
+                            if (key < minKey) {
+                                minKey = key;
+                            }
+                        }
+                    }
+                    if (minKey != char.MaxValue) {
+                        works[i] = 60 + minKey - 'A' + 1;
+                        items[i] = minKey;
+                        graph.Remove(items[i]);
+                    }
+                }
+            }
+
+            time++;
+
+            for (var i = 0; i < works.Length; i++) {
+                if (works[i] == 0) {
+                    // wait
+                    continue;
+                } else if (works[i] == 1) {
+                    // finish
+                    works[i]--;
+                    foreach (var key in graph.Keys) {
+                        graph[key].Remove(items[i]);
+                    }
+
+                } else if (works[i] > 0) {
+                    // step
+                    works[i]--;
+                }
+            }
+        }
+
+        return time;
+    }
+
+    Dictionary> Parse(string input) {
+        var dict = (
+            from line in input.Split("\n")
+            let parts = line.Split(" ")
+            let part = parts[7][0]
+            let partDependsOn = parts[1][0]
+            group partDependsOn by part into g
+            select g
+        ).ToDictionary(g => g.Key, g => g.ToList());
+
+        foreach (var key in new List(dict.Keys)) {
+            foreach (var d in dict[key]) {
+                if (!dict.ContainsKey(d)) {
+                    dict.Add(d, new List());
+                }
+            }
+        }
+        return dict;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/8/illustration.jpeg b/2018/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/8/illustration.jpeg differ diff --git a/2018/8/index.html b/2018/8/index.html new file mode 100644 index 00000000..7bee420e --- /dev/null +++ b/2018/8/index.html @@ -0,0 +1,345 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/8 'Memory Maneuver'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/8

+

Memory Maneuver

+

in C#

+

+

by encse

+
+ +
+ +
+

The sleigh is much easier to pull than you'd expect for something its weight. Unfortunately, neither you nor the Elves know which way the North Pole is from here.

+

You check your wrist device for anything that might help. It seems to have some kind of navigation system! Activating the navigation system produces more bad news: "Failed to start navigation system. Could not read software license file."

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2018.Day08;
+
+[ProblemName("Memory Maneuver")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        Parse(input).fold(0, (cur, node) => cur + node.metadata.Sum());
+    
+
+    public object PartTwo(string input) {
+        return Parse(input).value();
+    }
+
+    Node Parse(string input) {
+        var nums = input.Split(" ").Select(int.Parse).GetEnumerator();
+        Func next = () => {
+            nums.MoveNext();
+            return nums.Current;
+        };
+
+        Func read = null;
+        read = () => {
+            var node = new Node() {
+                children = new Node[next()],
+                metadata = new int[next()]
+            };
+            for (var i = 0; i < node.children.Length; i++) {
+                node.children[i] = read();
+            }
+            for (var i = 0; i < node.metadata.Length; i++) {
+                node.metadata[i] = next();
+            }
+            return node;
+        };
+        return read();
+    }
+
+
+}
+
+class Node {
+    public Node[] children;
+    public int[] metadata;
+    public T fold(T seed, Func aggregate) {
+        return children.Aggregate(aggregate(seed, this), (cur, child) => child.fold(cur, aggregate));
+    }
+
+    public int value() {
+        if(children.Length == 0){
+            return metadata.Sum();
+        }
+
+        var res = 0;
+        foreach(var i in metadata){
+            if(i >= 1 && i <= children.Length){
+                res += children[i-1].value();
+            }
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2018/9/illustration.jpeg b/2018/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2018/9/illustration.jpeg differ diff --git a/2018/9/index.html b/2018/9/index.html new file mode 100644 index 00000000..7fc0f10e --- /dev/null +++ b/2018/9/index.html @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2018/9 'Marble Mania'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2018/9

+

Marble Mania

+

in C#

+

+

by encse

+
+ +
+ +
+

You talk to the Elves while you wait for your navigation system to initialize. To pass the time, they introduce you to their favorite marble game.

+

The Elves play this game by taking turns arranging the marbles in a circle according to very particular rules. The marbles are numbered starting with 0 and increasing by 1 until every marble has a number.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2018.Day09;
+
+[ProblemName("Marble Mania")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 1);
+
+    public object PartTwo(string input) => Solve(input, 100);
+
+    long Solve(string input, int mul) {
+
+        var match = Regex.Match(input, @"(?\d+) players; last marble is worth (?\d+) points");
+        var players = new long[int.Parse(match.Groups["players"].Value)];
+        var targetPoints = int.Parse(match.Groups["points"].Value) * mul;
+
+        var current = new Node { value = 0 };
+        current.left = current;
+        current.right = current;
+
+        var points = 1;
+        var iplayer = 1;
+        while (points <= targetPoints) {
+
+            if (points % 23 == 0) {
+                for (var i = 0; i < 7; i++) {
+                    current = current.left;
+                }
+
+                players[iplayer] += points + current.value;
+
+                var left = current.left;
+                var right = current.right;
+                right.left = left;
+                left.right = right;
+                current = right;
+
+            } else {
+                var left = current.right;
+                var right = current.right.right;
+                current = new Node { value = points, left = left, right = right };
+                left.right = current;
+                right.left = current;
+            }
+
+            points++;
+            iplayer = (iplayer + 1) % players.Length;
+        }
+
+        return players.Max();
+    }
+}
+
+class Node {
+    public int value;
+    public Node left;
+    public Node right;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/1/illustration.jpeg b/2019/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/1/illustration.jpeg differ diff --git a/2019/1/index.html b/2019/1/index.html new file mode 100644 index 00000000..27994fb8 --- /dev/null +++ b/2019/1/index.html @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/1 'The Tyranny of the Rocket Equation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/1

+

The Tyranny of the Rocket Equation

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa has become stranded at the edge of the Solar System while delivering presents to other planets! To accurately calculate his position in space, safely align his warp drive, and return to Earth in time to save Christmas, he needs you to bring him measurements from fifty stars.

+

Collect stars by solving puzzles. Two puzzles will be made available on each day in the Advent calendar; the second puzzle is unlocked when you complete the first. Each puzzle grants one star. Good luck!

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day01;
+
+[ProblemName("The Tyranny of the Rocket Equation")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, false);
+    public object PartTwo(string input) => Solve(input, true);
+
+    int Solve(string input, bool recursive) {
+        var weights = new Queue(input.Split("\n").Select(x => int.Parse(x)));
+        var res = 0;
+        while (weights.Any()) {
+            var weight = weights.Dequeue();
+            var fuel = (int)(Math.Floor(weight / 3.0) - 2);
+            if (fuel > 0) {
+                if (recursive) {
+                    weights.Enqueue(fuel);
+                }
+                res += fuel;
+            }
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/10/illustration.jpeg b/2019/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/10/illustration.jpeg differ diff --git a/2019/10/index.html b/2019/10/index.html new file mode 100644 index 00000000..9b139308 --- /dev/null +++ b/2019/10/index.html @@ -0,0 +1,371 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/10 'Monitoring Station'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/10

+

Monitoring Station

+

in C#

+

+

by encse

+
+ +
+ +
+

You fly into the asteroid belt and reach the Ceres monitoring station. The Elves here have an emergency: they're having trouble tracking all of the asteroids and can't be sure they're safe.

+

The Elves would like to build a new monitoring station in a nearby area of space; they hand you a map of all of the asteroids in that region (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using AsteroidsByDir = System.Collections.Generic.Dictionary<
+(int drow, int dcol), System.Collections.Generic.List<(int irow, int icol)>
+>;
+
+namespace AdventOfCode.Y2019.Day10;
+
+[ProblemName("Monitoring Station")]
+class Solution : Solver {
+
+    public object PartOne(string input) => SelectStationPosition(input).asteroidsByDir.Count;
+
+    public object PartTwo(string input) {
+        var asteroid = Destroy(input).ElementAt(199);
+        return (asteroid.icol * 100 + asteroid.irow);
+    }
+
+    IEnumerable<(int irow, int icol)> Destroy(string input) {
+        var (station, asteroidsByDir) = SelectStationPosition(input);
+
+        foreach (var dir in asteroidsByDir.Keys.ToArray()) {
+            asteroidsByDir[dir] = asteroidsByDir[dir]
+                .OrderBy(a => Math.Abs(a.irow - station.irow) + Math.Abs(a.icol - station.icol))
+                .ToList();
+        }
+
+        foreach (var dir in Rotate(asteroidsByDir.Keys)) {
+            if (asteroidsByDir.ContainsKey(dir)) {
+                var asteroid = asteroidsByDir[dir].First();
+                asteroidsByDir[dir].RemoveAt(0);
+
+                yield return asteroid;
+
+                if (!asteroidsByDir[dir].Any()) {
+                    asteroidsByDir.Remove(dir);
+                }
+            }
+        }
+    }
+
+    IEnumerable<(int drow, int dcol)> Rotate(IEnumerable<(int drow, int dcol)> dirs) {
+        var ordered = dirs.OrderBy(dir => -Math.Atan2(dir.dcol, dir.drow)).ToList();
+        for (var i = 0; ; i++) {
+            yield return ordered[i % ordered.Count];
+        }
+    }
+
+    ((int irow, int icol) station, AsteroidsByDir asteroidsByDir) SelectStationPosition(string input) {
+
+        var res = ((0, 0), asteroidsByDir: new AsteroidsByDir());
+        var asteroids = Asteroids(input);
+
+        foreach (var station in asteroids) {
+            var asteroidsByDir = new AsteroidsByDir();
+            foreach (var asteroid in asteroids) {
+                if (station != asteroid) {
+                    var (rowDir, colDir) = (asteroid.irow - station.irow, asteroid.icol - station.icol);
+                    var gcd = Math.Abs(Gcd(rowDir, colDir));
+                    var dir = (rowDir / gcd, colDir / gcd);
+
+                    if (!asteroidsByDir.ContainsKey(dir)) {
+                        asteroidsByDir[dir] = new List<(int irow, int icol)>();
+                    }
+                    asteroidsByDir[dir].Add(asteroid);
+                }
+            }
+            if (asteroidsByDir.Count > res.asteroidsByDir.Count) {
+                res = (station, asteroidsByDir);
+            }
+        }
+
+        return res;
+    }
+
+    List<(int irow, int icol)> Asteroids(string input) {
+        var map = input.Split("\n");
+        var (crow, ccol) = (map.Length, map[0].Length);
+
+        return (
+            from irow in Enumerable.Range(0, crow)
+            from icol in Enumerable.Range(0, ccol)
+            where map[irow][icol] == '#'
+            select (irow, icol)
+        ).ToList();
+    }
+
+   int Gcd(int a, int b) => b == 0 ? a : Gcd(b, a % b);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/11/illustration.jpeg b/2019/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/11/illustration.jpeg differ diff --git a/2019/11/index.html b/2019/11/index.html new file mode 100644 index 00000000..9eac9d4c --- /dev/null +++ b/2019/11/index.html @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/11 'Space Police'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/11

+

Space Police

+

in C#

+

+

by encse

+
+ +
+ +
+

On the way to Jupiter, you're pulled over by the Space Police.

+

"Attention, unmarked spacecraft! You are in violation of Space Law! All spacecraft must have a clearly visible registration identifier! You have 24 hours to comply or be sent to Space Jail!"

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day11;
+
+[ProblemName("Space Police")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Run(input, 0).Count;
+
+    public object PartTwo(string input) {
+        var dict = Run(input, 1);
+        var irowMin = dict.Keys.Select(pos => pos.irow).Min();
+        var icolMin = dict.Keys.Select(pos => pos.icol).Min();
+        var irowMax = dict.Keys.Select(pos => pos.irow).Max();
+        var icolMax = dict.Keys.Select(pos => pos.icol).Max();
+        var crow = irowMax - irowMin + 1;
+        var ccol = icolMax - icolMin + 1;
+        var st = "";
+        for (var irow = 0; irow < crow; irow++) {
+            for (var icol = 0; icol < ccol; icol++) {
+                st +=  " #"[dict.GetValueOrDefault((irowMin + irow, icolMin + icol), 0)];
+            }
+            st += "\n";
+        }
+
+        return st.Ocr();
+    }
+
+    Dictionary<(int irow, int icol), int> Run(string input, int startColor) {
+        var mtx = new Dictionary<(int irow, int icol), int>();
+        (int irow, int icol) pos = (0, 0);
+        (int drow, int dcol) dir = (-1, 0);
+        mtx[(0, 0)] = startColor;
+        var icm = new IntCodeMachine(input);
+        while (true) {
+            var output = icm.Run(mtx.GetValueOrDefault(pos, 0));
+            if (icm.Halted()) {
+                return mtx;
+            }
+            mtx[pos] = (int)output[0];
+            dir = output[1] switch {
+                0 => (-dir.dcol, dir.drow),
+                1 => (dir.dcol, -dir.drow),
+                _ => throw new ArgumentException()
+            };
+            pos = (pos.irow + dir.drow, pos.icol + dir.dcol);
+        }
+    }
+
+    
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/12/illustration.jpeg b/2019/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/12/illustration.jpeg differ diff --git a/2019/12/index.html b/2019/12/index.html new file mode 100644 index 00000000..350cc18d --- /dev/null +++ b/2019/12/index.html @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/12 'The N-Body Problem'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/12

+

The N-Body Problem

+

in C#

+

+

by encse

+
+ +
+ +
+

The space near Jupiter is not a very safe place; you need to be careful of a big distracting red spot, extreme radiation, and a whole lot of moons swirling around. You decide to start by tracking the four largest moons: Io, Europa, Ganymede, and Callisto.

+

After a brief scan, you calculate the position of each moon (your puzzle input). You just need to simulate their motion so you can avoid them.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2019.Day12;
+
+[ProblemName("The N-Body Problem")]
+class Solution : Solver {
+
+    public object PartOne(string input) => (
+            from planet in Simulate(input).ElementAt(999)
+            let pot = planet.pos.Select(Math.Abs).Sum()
+            let kin = planet.vel.Select(Math.Abs).Sum()
+            select pot * kin
+        ).Sum();
+
+    public object PartTwo(string input) {
+        var statesByDim = new long[3];
+        for (var dim = 0; dim < 3; dim++) {
+            var states = new HashSet<(int,int,int,int,int,int,int,int)>();
+            foreach (var planets in Simulate(input)) {
+                var state = (planets[0].pos[dim], planets[1].pos[dim], planets[2].pos[dim], planets[3].pos[dim],
+                             planets[0].vel[dim], planets[1].vel[dim], planets[2].vel[dim], planets[3].vel[dim]);
+                if (states.Contains(state)) {
+                    break;
+                }
+                states.Add(state);
+            }
+            statesByDim[dim] = states.Count;
+        }
+
+        return Lcm(statesByDim[0], Lcm(statesByDim[1], statesByDim[2]));
+    }
+
+    long Lcm(long a, long b) => a * b / Gcd(a, b);
+    long Gcd(long a, long b) => b == 0 ? a : Gcd(b, a % b);
+
+    IEnumerable<(int[] pos, int[] vel)[]> Simulate(string input) {
+        var planets = (
+            from line in input.Split("\n")
+            let m = Regex.Matches(line, @"-?\d+")
+            let pos = (from v in m select int.Parse(v.Value)).ToArray()
+            let vel = new int[3]
+            select (pos, vel)
+        ).ToArray();
+
+        while (true) {
+            foreach (var planetA in planets) {
+                foreach (var planetB in planets) {
+                    for (var dim = 0; dim < 3; dim++) {
+                        planetA.vel[dim] += Math.Sign(planetB.pos[dim] - planetA.pos[dim]);
+                    }
+                }
+            }
+
+            foreach (var planet in planets) {
+                for (var dim = 0; dim < 3; dim++) {
+                    planet.pos[dim] += planet.vel[dim];
+                }
+            }
+
+            yield return planets;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/13/illustration.jpeg b/2019/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/13/illustration.jpeg differ diff --git a/2019/13/index.html b/2019/13/index.html new file mode 100644 index 00000000..fcbc096b --- /dev/null +++ b/2019/13/index.html @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/13 'Care Package'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/13

+

Care Package

+

in C#

+

+

by encse

+
+ +
+ +
+

As you ponder the solitude of space and the ever-increasing three-hour roundtrip for messages between you and Earth, you notice that the Space Mail Indicator Light is blinking. To help keep you sane, the Elves have sent you a care package.

+

It's a new game for the ship's arcade cabinet! Unfortunately, the arcade is all the way on the other end of the ship. Surely, it won't be hard to build your own - the care package even comes with schematics.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day13;
+
+[ProblemName("Care Package")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var icm = new IntCodeMachine(input);
+        var output = icm.Run();
+        var chunks = Chunk(output, 3);
+        return chunks.Count(x => x[2] == 2);
+    }
+
+    public object PartTwo(string input) {
+        var icm = new IntCodeMachine(input);
+        icm.memory[0] = 2;
+        var score = 0;
+        var icolBall = -1;
+        var icolPaddle = -1;
+        var dir = 0;
+        while (true) {
+            var output = icm.Run(dir);
+            var chunks = Chunk(output, 3);
+            foreach (var chunk in chunks) {
+                var (icol, irow, block) = (chunk[0], chunk[1], chunk[2]);
+                if ((icol, irow) == (-1, 0)) {
+                    score = (int)block;
+                } if (block == 3) {
+                    icolPaddle = (int)icol;
+                } else if (block == 4) {
+                    icolBall = (int)icol;
+                }
+            }
+
+            if (icm.Halted()) {
+                break;
+            }
+
+            dir = 
+                icolBall < icolPaddle ? -1 :
+                icolBall > icolPaddle ? 1 :
+                0;
+           
+        }
+        return score;
+    }
+
+    public T[][] Chunk(IEnumerable source, int chunksize) {
+        var res = new List();
+        while (source.Any()) {
+            res.Add(source.Take(chunksize).ToArray());
+            source = source.Skip(chunksize);
+        }
+        return res.ToArray();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/14/illustration.jpeg b/2019/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/14/illustration.jpeg differ diff --git a/2019/14/index.html b/2019/14/index.html new file mode 100644 index 00000000..b26943e2 --- /dev/null +++ b/2019/14/index.html @@ -0,0 +1,358 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/14 'Space Stoichiometry'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/14

+

Space Stoichiometry

+

in C#

+

+

by encse

+
+ +
+ +
+

As you approach the rings of Saturn, your ship's low fuel indicator turns on. There isn't any fuel here, but the rings have plenty of raw material. Perhaps your ship's Inter-Stellar Refinery Union brand nanofactory can turn these raw materials into fuel.

+

You ask the nanofactory to produce a list of the reactions it can perform that are relevant to this process (your puzzle input). Every reaction turns some quantities of specific input chemicals into some quantity of an output chemical. Almost every chemical is produced by exactly one reaction; the only exception, ORE, is the raw material input to the entire process and is not produced by a reaction.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day14;
+
+[ProblemName("Space Stoichiometry")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Parse(input)(1);
+    public object PartTwo(string input) {
+        var oreForFuel = Parse(input);
+
+        var ore = 1000000000000L;
+
+        var fuel = 1L;
+        while (true) {
+            // newFuel <= the amount we can produce with the given ore
+            // since (double)ore / oreForFuel(fuel) >= 1, fuel becomes
+            // a better estimation in each iteration until it reaches 
+            // the maximum
+
+            var newFuel = (int)((double)ore / oreForFuel(fuel) * fuel);
+
+            if (newFuel == fuel) {
+                return newFuel;
+            }
+            fuel = newFuel;
+        }
+    }
+
+    Func Parse(string productionRules) {
+        (string chemical, long amount) ParseReagent(string st) {
+            var parts = st.Split(" ");
+            return (parts[1], long.Parse(parts[0]));
+        }
+
+        var reactions = (
+            from rule in productionRules.Split("\n")
+            let inout = rule.Split(" => ")
+            let input = inout[0].Split(", ").Select(ParseReagent).ToArray()
+            let output = ParseReagent(inout[1])
+            select (output, input)
+        ).ToDictionary(inout => inout.output.chemical, inout => inout);
+
+        return (fuel) => {
+
+            var ore = 0L;
+            var inventory = reactions.Keys.ToDictionary(chemical => chemical, _ => 0L);
+            var productionList = new Queue<(string chemical, long amount)>();
+            productionList.Enqueue(("FUEL", fuel));
+
+            while (productionList.Any()) {
+                var (chemical, amount) = productionList.Dequeue();
+                if (chemical == "ORE") {
+                    ore += amount;
+                } else {
+                    var reaction = reactions[chemical];
+
+                    var useFromInventory = Math.Min(amount, inventory[chemical]);
+                    amount -= useFromInventory;
+                    inventory[chemical] -= useFromInventory;
+
+                    if (amount > 0) {
+                        var multiplier = (long)Math.Ceiling((decimal)amount / reaction.output.amount);
+                        inventory[chemical] = Math.Max(0, multiplier * reaction.output.amount - amount);
+
+                        foreach (var reagent in reaction.input) {
+                            productionList.Enqueue((reagent.chemical, reagent.amount * multiplier));
+                        }
+                    }
+                }
+            }
+            return ore;
+        };
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/15/illustration.jpeg b/2019/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/15/illustration.jpeg differ diff --git a/2019/15/index.html b/2019/15/index.html new file mode 100644 index 00000000..73fe15ab --- /dev/null +++ b/2019/15/index.html @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/15 'Oxygen System'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/15

+

Oxygen System

+

in C#

+

+

by encse

+
+ +
+ +
+

Out here in deep space, many things can go wrong. Fortunately, many of those things have indicator lights. Unfortunately, one of those lights is lit: the oxygen system for part of the ship has failed!

+

According to the readouts, the oxygen system must have failed days ago after a rupture in oxygen tank two; that section of the ship was automatically sealed once oxygen levels went dangerously low. A single remotely-operated repair droid is your only option for fixing the oxygen system.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day15;
+
+[ProblemName("Oxygen System")]
+class Solution : Solver {
+
+    enum Tile {
+        Wall = 0,
+        Empty = 1,
+        O2 = 2,
+    }
+
+    public object PartOne(string input) {
+        var iicm = new ImmutableIntCodeMachine(input);
+        return Bfs(iicm).First(s => s.tile == Tile.O2).path.Count;
+    }
+
+    public object PartTwo(string input) {
+        var iicm = Bfs(new ImmutableIntCodeMachine(input)).First(s => s.tile == Tile.O2).iicm;
+        return Bfs(iicm).Last().path.Count;
+    }
+
+    IEnumerable<(ImmutableIntCodeMachine iicm, ImmutableList path, Tile tile)> Bfs(ImmutableIntCodeMachine startIicm) {
+
+        (int dx, int dy)[] dirs = new[] { (0, -1), (0, 1), (-1, 0), (1, 0) };
+
+        var seen = new HashSet<(int x, int y)> { (0, 0) };
+        var q = new Queue<(ImmutableIntCodeMachine iicm, ImmutableList path, int x, int y)>();
+        q.Enqueue((startIicm, ImmutableList.Empty, 0, 0));
+        while (q.Any()) {
+            var current = q.Dequeue();
+
+            for (var i = 0; i < dirs.Length; i++) {
+                var (nextX, nextY) = (current.x + dirs[i].dx, current.y + dirs[i].dy);
+
+                if (!seen.Contains((nextX, nextY))) {
+                    seen.Add((nextX, nextY));
+                    var nextPath = current.path.Add(i + 1);
+                    var (nextIicm, output) = current.iicm.Run(i + 1);
+
+                    var tile = (Tile)output.Single();
+                    if (tile != Tile.Wall) {
+                        yield return (nextIicm, nextPath, tile);
+                        q.Enqueue((nextIicm, nextPath, nextX, nextY));
+                    }
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/16/illustration.jpeg b/2019/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/16/illustration.jpeg differ diff --git a/2019/16/index.html b/2019/16/index.html new file mode 100644 index 00000000..a3680ec8 --- /dev/null +++ b/2019/16/index.html @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/16 'Flawed Frequency Transmission'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/16

+

Flawed Frequency Transmission

+

in C#

+

+

by encse

+
+ +
+ +
+

You're 3/4ths of the way through the gas giants. Not only do roundtrip signals to Earth take five hours, but the signal quality is quite bad as well. You can clean up the signal with the Flawed Frequency Transmission algorithm, or FFT.

+

As input, FFT takes a list of numbers. In the signal you received (your puzzle input), each number is a single digit: data like 15243 represents the sequence 1, 5, 2, 4, 3.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+namespace AdventOfCode.Y2019.Day16;
+
+[ProblemName("Flawed Frequency Transmission")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+
+        int[] Fft(int[] digits) {
+            IEnumerable Pattern(int digit) {
+                var repeat = digit + 1;
+                while (true) {
+                    foreach (var item in new[] { 0, 1, 0, -1 }) {
+                        for (var i = 0; i < repeat; i++) {
+                            yield return item;
+                        }
+                    }
+                }
+            }
+
+            return (
+                from i in Enumerable.Range(0, digits.Length)
+                let pattern = Pattern(i).Skip(1)
+                let dotProduct = (from p in digits.Zip(pattern) select p.First * p.Second).Sum()
+                select Math.Abs(dotProduct) % 10
+            ).ToArray();
+        }
+
+        var digits = input.Select(ch => int.Parse(ch.ToString())).ToArray();
+
+        for (var i = 0; i < 100; i++) {
+            digits = Fft(digits);
+        }
+
+        return string.Join("", digits.Take(8));
+    }
+
+    public object PartTwo(string input) {
+        /* 
+            Let's introduce the following matrix:
+                    FFT = [
+                        1,  0, -1,  0,  1,  0, -1,  0, ...
+                        0,  1,  1,  0,  0, -1, -1,  0, ...
+                        0,  0,  1,  1,  1,  0,  0,  0, ...
+                        0,  0,  0,  1,  1,  1,  1,  0, ...
+                        0,  0,  0,  0,  1,  1,  1,  1, ...
+                        0,  0,  0,  0,  0,  1,  1,  1, ...
+                        0,  0,  0,  0,  0,  0,  1,  1, ...
+                        0,  0,  0,  0,  0,  0,  0,  1, ...
+                        ...
+                    ]
+
+            A single FFT step of the data stored in vector x is just a matrix multiplication FFT . x
+            We get repeated FFT steps with multiplying with the proper power of FFT: FFT^2, FFT^3, ... FFT^100.
+
+            Looking at the FFT matrix, we notice that the bottom right corner is always an upper triangular filled with 1s:
+                    A = [
+                        1, 1, 1, 1, ...
+                        0, 1, 1, 1, ...
+                        0, 0, 1, 1, ...
+                        0, 0, 0, 1, ...
+                        ....
+                    ]
+            The problem asks for output components that correspond to multiplication with rows in this area.
+
+            Examining A's powers reveal that the the first row can be:
+                the numbers from 1-n, 
+                    A^2 = [
+                        1, 2, 3, 4, ...
+                        0, 1, 2, 3, ...
+                        0, 0, 1, 3, ...
+                        0, 0, 0, 1, ...
+                        ....
+                    ]
+                the sum of numbers from 1-n
+                    A^3 = [
+                        1, 3, 6, 10, ...
+                        0, 1, 3, 6, ...
+                        0, 0, 1, 3, ...
+                        0, 0, 0, 1, ...
+                        ....
+                    ]
+                the sum of the sum of numbers from 1-n
+                    A^4 = [
+                        1, 4, 10, 20, ...
+                        0, 1,  4, 10, ...
+                        0, 0,  1,  4, ...
+                        0, 0,  0,  1, ...
+                        ....
+                    ]
+                etc.
+            And we get the second, third... rows with shifting the previous one.
+
+            Using the properties of binomial coefficients we get that the items of the first row of A^k are
+                (A^k)_1_j = choose(j - 1 + k - 1, k - 1)
+
+                see https://math.stackexchange.com/questions/234304/sum-of-the-sum-of-the-sum-of-the-first-n-natural-numbers
+
+            and we can compute the items from left to right with
+                choose(m + 1, n) = choose(m, n) * (m + 1) / (m + 1 - n)
+            
+            specifically
+                 (A^k)_1_(j + 1) = 
+                    choose(j + k - 1, k - 1) = 
+                    choose(j - 1 + k - 1, k - 1) * (j + k - 1) / j =
+                    (A^k)_1_j * (j + k - 1) / j
+
+            let B = A^100 and so k - 1 = 99.
+                B_1_(j + 1) = B_1_j * (j + 99) / j
+            and 
+                B_i_j = B_1_(j - i + 1)
+
+            we need to compute [B]_{1..7} * xs % 10, where xs is the digits of input repeated 10000 times shifted with t
+         */
+
+        var xs = input.Select(ch => int.Parse(ch.ToString())).ToArray();
+        var res = "";
+
+        var t = int.Parse(input.Substring(0, 7));
+        var crow = 8;
+        var ccol = input.Length * 10000 - t;
+
+        var bijMods = new int[ccol + 1];
+        var bij = new BigInteger(1);
+        for (var j = 1; j <= ccol; j++) {
+            bijMods[j] = (int)(bij % 10);
+            bij = bij * (j + 99) / j;
+        }
+
+        for (var i = 1; i <= crow; i++) {
+            var s = 0;
+            for (var j = i; j <= ccol; j++) {
+                var x = xs[(t + j - 1) % input.Length];
+                s += x * bijMods[j - i + 1];
+            }
+            res += (s % 10).ToString();
+        }
+
+        return res;
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/17/illustration.jpeg b/2019/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/17/illustration.jpeg differ diff --git a/2019/17/index.html b/2019/17/index.html new file mode 100644 index 00000000..4412a84f --- /dev/null +++ b/2019/17/index.html @@ -0,0 +1,441 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/17 'Set and Forget'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/17

+

Set and Forget

+

in C#

+

+

by encse

+
+ +
+ +
+

An early warning system detects an incoming solar flare and automatically activates the ship's electromagnetic shield. Unfortunately, this has cut off the Wi-Fi for many small robots that, unaware of the impending danger, are now trapped on exterior scaffolding on the unsafe side of the shield. To rescue them, you'll have to act quickly!

+

The only tools at your disposal are some wired cameras and a small vacuum robot currently asleep at its charging station. The video quality is poor, but the vacuum robot has a needlessly bright LED that makes it easy to spot no matter where it is.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day17;
+
+[ProblemName("Set and Forget")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var mx = Screenshot(input);
+
+        var crow = mx.Length;
+        var ccol = mx[0].Length;
+        var cross = ".#.\n###\n.#.".Split("\n");
+
+        bool crossing(int irow, int icol) => (
+            from drow in new[] { -1, 0, 1 }
+            from dcol in new[] { -1, 0, 1 }
+            select cross[1 + drow][1 + dcol] == mx[irow + drow][icol + dcol]
+        ).All(x => x);
+
+        return (
+            from irow in Enumerable.Range(1, crow - 2)
+            from icol in Enumerable.Range(1, ccol - 2)
+            where crossing(irow, icol)
+            select icol * irow
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var program = GeneratePrograms(Path(input)).First();
+
+        var icm = new IntCodeMachine(input);
+        icm.memory[0] = 2;
+        return icm.Run(program).Last();
+    }
+
+    string[] Screenshot(string input) {
+        var icm = new IntCodeMachine(input);
+        var output = icm.Run();
+        return output.ToAscii().Split("\n").Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();
+    }
+
+    IEnumerable GeneratePrograms(string path) {
+
+        IEnumerable<(ImmutableList indices, ImmutableList functions)> GenerateRec(string path, ImmutableList functions) {
+            if (path.Length == 0) {
+                yield return (ImmutableList.Empty, functions);
+            }
+
+            for (var i = 0; i < functions.Count; i++) {
+                var function = functions[i];
+
+                if (path.StartsWith(function)) {
+
+                    var pathT = path.Substring(function.Length);
+                    foreach (var res in GenerateRec(pathT, functions)) {
+                        yield return (res.indices.Insert(0, i), res.functions);
+                    }
+                }
+            }
+
+            if (functions.Count < 3) {
+                for (var length = 1; length <= path.Length; length++) {
+                    var function = path[0..length].ToString();
+                    var functionsT = functions.Add(function);
+                    var idx = functions.Count;
+                    var pathT = path.Substring(function.Length);
+                    foreach (var res in GenerateRec(pathT, functionsT)) {
+                        yield return (res.indices.Insert(0, idx), res.functions);
+                    }
+                }
+            }
+        }
+
+        foreach (var (indices, functions) in GenerateRec(path, ImmutableList.Empty)) {
+
+            var compressed = functions.Select(Compress).ToArray();
+            if (indices.Count <= 20 && compressed.All(c => c.Length <= 20)) {
+
+                var main = string.Join(",", indices.Select(i => "ABC"[i]));
+                yield return $"{main}\n{compressed[0]}\n{compressed[1]}\n{compressed[2]}\nn\n";
+            }
+
+        }
+    }
+
+    string Compress(string st) {
+        var steps = new List();
+        var l = 0;
+        for (var i = 0; i < st.Length; i++) {
+            var ch = st[i];
+
+            if (l > 0 && ch != 'F') {
+                steps.Add(l.ToString());
+                l = 0;
+            }
+            if (ch == 'R' || ch == 'L') {
+                steps.Add(ch.ToString());
+            } else {
+                l++;
+            }
+        }
+        if (l > 0) {
+            steps.Add(l.ToString());
+        }
+        return string.Join(",", steps);
+    }
+
+    string Path(string input) {
+        var mx = Screenshot(input);
+        var crow = mx.Length;
+        var ccol = mx[0].Length;
+
+        var (pos, dir) = FindRobot(mx);
+        char look((int irow, int icol) pos) {
+            var (irow, icol) = pos;
+            return irow < 0 || irow >= crow || icol < 0 || icol >= ccol ? '.' : mx[irow][icol];
+        }
+
+        var path = "";
+        var finished = false;
+        while (!finished) {
+            finished = true;
+            foreach (var (nextDir, step) in new[]{
+                ((drow:  dir.drow, dcol:  dir.dcol), "F"),
+                ((drow: -dir.dcol, dcol:  dir.drow), "LF"),
+                ((drow:  dir.dcol, dcol: -dir.drow), "RF")
+            }) {
+                var nextPos = (pos.irow + nextDir.drow, pos.icol + nextDir.dcol);
+                if (look(nextPos) == '#') {
+                    path += step;
+                    pos = nextPos;
+                    dir = nextDir;
+                    finished = false;
+                    break;
+                }
+            }
+        }
+        return path;
+    }
+
+    ((int irow, int icol) pos, (int drow, int dcol) dir) FindRobot(string[] mx) => (
+        from irow in Enumerable.Range(0, mx.Length)
+        from icol in Enumerable.Range(0, mx[0].Length)
+        let ch = mx[irow][icol]
+        where "^v<>".Contains(ch)
+        let dir = mx[irow][icol] switch
+        {
+            '^' => (-1, 0),
+            'v' => (1, 0),
+            '<' => (0, -1),
+            '>' => (0, 1),
+            _ => throw new Exception()
+        }
+        select ((irow, icol), dir)
+    ).First();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/18/illustration.jpeg b/2019/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/18/illustration.jpeg differ diff --git a/2019/18/index.html b/2019/18/index.html new file mode 100644 index 00000000..22c53bd3 --- /dev/null +++ b/2019/18/index.html @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/18 'Many-Worlds Interpretation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/18

+

Many-Worlds Interpretation

+

in C#

+

+

by encse

+
+ +
+ +
+

As you approach Neptune, a planetary security system detects you and activates a giant tractor beam on Triton! You have no choice but to land.

+

A scan of the local area reveals only one interesting feature: a massive underground vault. You generate a map of the tunnels (your puzzle input). The tunnels are too narrow to move diagonally.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day18;
+
+
+class Maze {
+    string[] maze;
+    public Maze(string st) {
+        this.maze = st.Split("\n");
+    }
+    int ccol => maze[0].Length;
+    int crow => maze.Length;
+    Dictionary positionCache = new Dictionary();
+    Dictionary<(char, char), int> distanceCache = new Dictionary<(char, char), int>();
+
+    public char Look((int irow, int icol) pos) {
+        var (irow, icol) = pos;
+        if (irow < 0 || irow >= crow || icol < 0 || icol >= ccol) {
+            return '#';
+        }
+        return maze[irow][icol];
+
+    }
+
+    public (int irow, int icol) Find(char ch) {
+        if (!positionCache.ContainsKey(ch)) {
+            for (var irow = 0; irow < crow; irow++) {
+                for (var icol = 0; icol < ccol; icol++) {
+                    if (maze[irow][icol] == ch) {
+                        positionCache[ch] = (irow, icol);
+                        return positionCache[ch];
+                    }
+                }
+            }
+            throw new Exception();
+        } else {
+            return positionCache[ch];
+        }
+    }
+
+
+    public int Distance(char chA, char chB) {
+        var key = (chA, chB);
+        if (!distanceCache.ContainsKey(key)) {
+            distanceCache[key] = ComputeDistance(chA, chB);
+        }
+        return distanceCache[key];
+    }
+
+    int ComputeDistance(char chA, char chB) {
+        var pos = Find(chA);
+        if (chA == chB) {
+            return 0;
+        }
+        var q = new Queue<((int irow, int icol) pos, int dist)>();
+        int dist = 0;
+        q.Enqueue((pos, dist));
+
+        var seen = new HashSet<(int irow, int icol)>();
+        seen.Add(pos);
+        while (q.Any()) {
+            (pos, dist) = q.Dequeue();
+
+            foreach (var (drow, dcol) in new[] { (-1, 0), (1, 0), (0, -1), (0, 1) }) {
+                var posT = (pos.irow + drow, pos.icol + dcol);
+                var ch = Look(posT);
+
+                if (seen.Contains(posT) || ch == '#') {
+                    continue;
+                }
+
+                seen.Add(posT);
+                var distT = dist + 1;
+
+                if (ch == chB) {
+                    return distT;
+                } else {
+                    q.Enqueue((posT, distT));
+                }
+            }
+        }
+        throw new Exception();
+    }
+}
+
+[ProblemName("Many-Worlds Interpretation")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var maze = new Maze(input);
+
+
+        var dependencies = GenerateDependencies(maze);
+        return Solve(maze);
+    }
+
+
+    public object PartTwo(string input) {
+        var d = 0;
+        foreach (var subMaze in GenerateSubMazes(input)) {
+            var maze = new Maze(subMaze);
+
+            var dependencies = GenerateDependencies(maze);
+            d += Solve(maze);
+        }
+        return d;
+    }
+
+    IEnumerable GenerateSubMazes(string input) {
+        var mx = input.Split("\n").Select(x => x.ToCharArray()).ToArray();
+        var crow = mx.Length;
+        var ccol = mx[0].Length;
+        var hrow = crow / 2;
+        var hcol = ccol / 2;
+        var pattern = "@#@\n###\n@#@".Split();
+        foreach (var drow in new[] { -1, 0, 1 }) {
+            foreach (var dcol in new[] { -1, 0, 1 }) {
+                mx[hrow + drow][hcol + dcol] = pattern[1 + drow][1 + dcol];
+            }
+        }
+
+        foreach (var (drow, dcol) in new[] { (0, 0), (0, hcol + 1), (hrow + 1, 0), (hrow + 1, hcol + 1) }) {
+            var res = "";
+            for (var irow = 0; irow < hrow; irow++) {
+                res += string.Join("", mx[irow + drow].Skip(dcol).Take(hcol)) + "\n";
+            }
+
+            for (var ch = 'A'; ch <= 'Z'; ch++) {
+                if (!res.Contains(char.ToLower(ch))) {
+                    res = res.Replace(ch, '.');
+                }
+            }
+            res = res.Substring(0, res.Length - 1);
+            yield return res;
+        }
+    }
+
+
+    int Solve(Maze maze) {
+        var dependencies = GenerateDependencies(maze);
+        var cache = new Dictionary();
+
+        int SolveRecursive(char currentItem, ImmutableHashSet keys
+        ) {
+            if (keys.Count == 0) {
+                return 0;
+            }
+            var cacheKey = currentItem + string.Join("", keys);
+
+            if (!cache.ContainsKey(cacheKey)) {
+                var result = int.MaxValue;
+                foreach (var key in keys) {
+                    if (dependencies[key].Intersect(keys).Count == 0) {
+                        var d = maze.Distance(currentItem, key) + SolveRecursive(key, keys.Remove(key));
+                        result = Math.Min(d, result);
+                    }
+                }
+                cache[cacheKey] = result;
+            }
+            return cache[cacheKey];
+        }
+
+        return SolveRecursive('@', dependencies.Keys.ToImmutableHashSet());
+    }
+
+    Dictionary> GenerateDependencies(Maze maze) {
+        var q = new Queue<((int irow, int icol) pos, string dependsOn)>();
+        var pos = maze.Find('@');
+        var dependsOn = "";
+        q.Enqueue((pos, dependsOn));
+
+        var res = new Dictionary>();
+        var seen = new HashSet<(int irow, int icol)>();
+        seen.Add(pos);
+        while (q.Any()) {
+            (pos, dependsOn) = q.Dequeue();
+
+            foreach (var (drow, dcol) in new[] { (-1, 0), (1, 0), (0, -1), (0, 1) }) {
+                var posT = (pos.irow + drow, pos.icol + dcol);
+                var ch = maze.Look(posT);
+
+                if (seen.Contains(posT) || ch == '#') {
+                    continue;
+                }
+
+                seen.Add(posT);
+                var dependsOnT = dependsOn;
+
+                if (char.IsLower(ch)) {
+                    res[ch] = ImmutableHashSet.CreateRange(dependsOn);
+                }
+
+                if (char.IsLetter(ch)) {
+                    dependsOnT += char.ToLower(ch);
+                }
+                q.Enqueue((posT, dependsOnT));
+            }
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/19/illustration.jpeg b/2019/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/19/illustration.jpeg differ diff --git a/2019/19/index.html b/2019/19/index.html new file mode 100644 index 00000000..7440ddaf --- /dev/null +++ b/2019/19/index.html @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/19 'Tractor Beam'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/19

+

Tractor Beam

+

in C#

+

+

by encse

+
+ +
+ +
+

Unsure of the state of Santa's ship, you borrowed the tractor beam technology from Triton. Time to test it out.

+

When you're safely away from anything else, you activate the tractor beam, but nothing happens. It's hard to tell whether it's working if there's nothing to use it on. Fortunately, your ship's drone system can be configured to deploy a drone to specific coordinates and then check whether it's being pulled. There's even an Intcode program (your puzzle input) that gives you access to the drone system.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day19;
+
+[ProblemName("Tractor Beam")]
+class Solution : Solver {
+
+    Func Detector(string input) {
+        var icm = new ImmutableIntCodeMachine(input);
+        return (int x, int y) => {
+            var (_, output) = icm.Run(x, y);
+            return output[0] == 1;
+        };
+    }
+
+    public object PartOne(string input) {
+        var detector = Detector(input);
+        return (from x in Enumerable.Range(0, 50)
+                from y in Enumerable.Range(0, 50)
+                where detector(x, y)
+                select 1).Count();
+    }
+
+    public object PartTwo(string input) {
+
+        var detector = Detector(input);
+
+        var (xStart, y) = (0, 100);
+        while (true) {
+            while (!detector(xStart, y)) {
+                xStart++;
+            }
+            var x = xStart;
+            while (detector(x + 99, y)) {
+                if (detector(x, y + 99) && detector(x + 99, y + 99)) {
+                    return (x * 10000 + y);
+                }
+                x++;
+            }
+            y++;
+        }
+
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/2/illustration.jpeg b/2019/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/2/illustration.jpeg differ diff --git a/2019/2/index.html b/2019/2/index.html new file mode 100644 index 00000000..9bfeca9d --- /dev/null +++ b/2019/2/index.html @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/2 '1202 Program Alarm'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/2

+

1202 Program Alarm

+

in C#

+

+

by encse

+
+ +
+ +
+

On the way to your gravity assist around the Moon, your ship computer beeps angrily about a "1202 program alarm". On the radio, an Elf is already explaining how to handle the situation: "Don't worry, that's perfectly norma--" The ship computer bursts into flames.

+

You notify the Elves that the computer's magic smoke seems to have escaped. "That computer ran Intcode programs like the gravity assist program it was working on; surely there are enough spare parts up there to build a new Intcode computer!"

+

Read the full puzzle.

+
+
using System;
+
+namespace AdventOfCode.Y2019.Day02;
+
+[ProblemName("1202 Program Alarm")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ExecIntCode(new IntCodeMachine(input), 12, 2);
+
+    public object PartTwo(string input) {
+        var icm = new IntCodeMachine(input);
+
+        for (var sum = 0; ; sum++) {
+            for (var verb = 0; verb <= sum; verb++) {
+                var noun = sum - verb;
+                var res = ExecIntCode(icm, noun, verb);
+                if (res == 19690720) {
+                    return 100 * noun + verb;
+                }
+            }
+        }
+        throw new Exception();
+    }
+
+    long ExecIntCode(IntCodeMachine icm, int noun, int verb) {
+        icm.Reset();
+        icm.memory[1] = noun;
+        icm.memory[2] = verb;
+        icm.Run();
+        return icm.memory[0];
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/20/illustration.jpeg b/2019/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/20/illustration.jpeg differ diff --git a/2019/20/index.html b/2019/20/index.html new file mode 100644 index 00000000..c766a512 --- /dev/null +++ b/2019/20/index.html @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/20 'Donut Maze'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/20

+

Donut Maze

+

in C#

+

+

by encse

+
+ +
+ +
+

You notice a strange pattern on the surface of Pluto and land nearby to get a closer look. Upon closer inspection, you realize you've come across one of the famous space-warping mazes of the long-lost Pluto civilization!

+

Because there isn't much space on Pluto, the civilization that used to live here thrived by inventing a method for folding spacetime. Although the technology is no longer understood, mazes like this one provide a small glimpse into the daily life of an ancient Pluto citizen.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day20;
+
+record Pos2(int irow, int icol);
+record Pos3(int irow, int icol, int level);
+record PosD(int irow, int icol, int dlevel);
+
+[ProblemName("Donut Maze")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Solve(input, false);
+    }
+
+    public object PartTwo(string input) {
+        return Solve(input, true);
+    }
+
+    int Solve(string input, bool part2) {
+        var mx = input.Split("\n").Select(x => x.ToCharArray()).ToArray();
+        var (portals, start, end) = Explore(mx);
+
+        var pos = start;
+        var dist = 0;
+        var q = new Queue<(Pos3, int dist)>();
+        q.Enqueue((pos, dist));
+
+        var seen = new HashSet();
+        seen.Add(pos);
+
+        IEnumerable Neighbours(Pos3 pos) {
+            foreach (var (drow, dcol) in new[] { (0, -1), (0, 1), (-1, 0), (1, 0) }) {
+                yield return new (pos.irow + drow, pos.icol + dcol, pos.level);
+            }
+
+            if (portals.ContainsKey(new (pos.irow, pos.icol))) {
+                var (irowT, icolT, dlevel) = portals[new (pos.irow, pos.icol)];
+
+                if (!part2) {
+                    dlevel = 0;
+                }
+
+                if (pos.level + dlevel >= 0) {
+                    yield return new (irowT, icolT, pos.level + dlevel);
+                }
+            }
+        }
+
+        while (q.Any()) {
+            (pos, dist) = q.Dequeue();
+            if (pos == end) {
+                return dist;
+            }
+
+            foreach (var posT in Neighbours(pos)) {
+                if (!seen.Contains(posT)) {
+                    var distT = dist + 1;
+                    if (mx[posT.irow][posT.icol] == '.') {
+                        seen.Add(posT);
+                        q.Enqueue((posT, distT));
+                    }
+
+                }
+            }
+        }
+        throw new Exception();
+    }
+
+    (Dictionary portals, Pos3 start, Pos3 goal) Explore(char[][] mx) {
+        var portals = new Dictionary();
+        var tmp = new Dictionary();
+        var ccol = mx[0].Length;
+        var crow = mx.Length;
+        for (var irow = 0; irow < crow - 1; irow++) {
+            for (var icol = 0; icol < ccol - 1; icol++) {
+                foreach (var (drow, dcol) in new[] { (0, 1), (1, 0) }) {
+                    var st = $"{mx[irow][icol]}{mx[irow + drow][icol + dcol]}";
+                    if (st.All(char.IsLetter)) {
+                        var portal = irow - drow >= 0 && icol - dcol >= 0 && mx[irow - drow][icol - dcol] == '.' ?
+                            new Pos2(irow - drow, icol - dcol) :
+                            new Pos2(irow + 2 * drow, icol + 2 * dcol);
+
+                        if (tmp.ContainsKey(st)) {
+                            var dlevel = portal.icol == 2 || portal.icol == ccol - 3 || portal.irow == 2 || portal.irow == crow - 3 ? -1 : 1;
+                            portals[portal] = new (tmp[st].irow, tmp[st].icol, dlevel);
+                            portals[tmp[st]] = new (portal.irow, portal.icol, -dlevel);
+                        } else {
+                            tmp[st] = portal;
+                        }
+                        mx[irow][icol] = ' ';
+                        mx[irow + drow][icol + dcol] = ' ';
+                    }
+                }
+            }
+        }
+
+        return (portals, new (tmp["AA"].irow, tmp["AA"].icol, 0), new (tmp["ZZ"].irow, tmp["ZZ"].icol, 0));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/21/illustration.jpeg b/2019/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/21/illustration.jpeg differ diff --git a/2019/21/index.html b/2019/21/index.html new file mode 100644 index 00000000..890fc18d --- /dev/null +++ b/2019/21/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/21 'Springdroid Adventure'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/21

+

Springdroid Adventure

+

in C#

+

+

by encse

+
+ +
+ +
+

You lift off from Pluto and start flying in the direction of Santa.

+

While experimenting further with the tractor beam, you accidentally pull an asteroid directly into your ship! It deals significant damage to your hull and causes your ship to begin tumbling violently.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2019.Day21;
+
+[ProblemName("Springdroid Adventure")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var icm = new IntCodeMachine(input);
+        
+        // J = (¬A ∨ ¬B ∨ ¬C) ∧ D  
+        // jump if no road ahead, but we can continue from D
+        return new IntCodeMachine(input).Run(
+            "OR A T",
+            "AND B T",
+            "AND C T",
+            "NOT T J", 
+            "AND D J", 
+            "WALK"
+        ).Last();
+    }
+
+    public object PartTwo(string input) {
+
+         // J = (¬A ∨ ¬B ∨ ¬C) ∧ D ∧ (H ∨ E) 
+         // same as part 1, but also check that D is not a dead end
+        return new IntCodeMachine(input).Run(
+            "OR A T",
+            "AND B T",
+            "AND C T",
+            "NOT T J",  
+            "AND D J", 
+            "OR H T",
+            "OR E T",
+            "AND T J", 
+            "RUN"
+        ).Last();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/22/illustration.jpeg b/2019/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/22/illustration.jpeg differ diff --git a/2019/22/index.html b/2019/22/index.html new file mode 100644 index 00000000..890fd4eb --- /dev/null +++ b/2019/22/index.html @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/22 'Slam Shuffle'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/22

+

Slam Shuffle

+

in C#

+

+

by encse

+
+ +
+ +
+

There isn't much to do while you wait for the droids to repair your ship. At least you're drifting in the right direction. You decide to practice a new card shuffle you've been working on.

+

Digging through the ship's storage, you find a deck of space cards! Just like any deck of space cards, there are 10007 cards in the deck numbered 0 through 10006. The deck must be new - they're still in factory order, with 0 on the top, then 1, then 2, and so on, all the way through to 10006 on the bottom.

+

Read the full puzzle.

+
+
using System;
+using System.Numerics;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2019.Day22;
+
+[ProblemName("Slam Shuffle")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var m = 10007;
+        var iter = 1;
+        var (a, b) = Parse(input, m, iter);
+        return Mod(a * 2019 + b, m);
+    }
+
+    public object PartTwo(string input) {
+        var m = 119315717514047;
+        var iter = 101741582076661;
+        var (a, b) = Parse(input, m, iter);
+
+        return Mod(ModInv(a, m) * (2020 - b), m);
+    }
+
+    BigInteger Mod(BigInteger a, BigInteger m) => ((a % m) + m) % m;
+    BigInteger ModInv(BigInteger a, BigInteger m) => BigInteger.ModPow(a, m - 2, m);
+
+    (BigInteger a, BigInteger big) Parse(string input, long m, long n) {
+        var a = new BigInteger(1);
+        var b = new BigInteger(0);
+
+        foreach (var line in input.Split('\n')) {
+            if (line.Contains("into new stack")) {
+                a = -a;
+                b = m - b - 1;
+            } else if (line.Contains("cut")) {
+                var i = long.Parse(Regex.Match(line, @"-?\d+").Value);
+                b = m + b - i;
+            } else if (line.Contains("increment")) {
+                var i = long.Parse(Regex.Match(line, @"-?\d+").Value);
+                a *= i;
+                b *= i;
+            } else {
+                throw new Exception();
+            }
+        }
+
+        var resA = BigInteger.One;
+        var resB = BigInteger.Zero;
+
+        // resA = a^n
+        resA = BigInteger.ModPow(a, n, m);
+        // resB = b * (1 + a + a^2 + ... a^n) = b * (a^n - 1) / (a - 1);
+        resB = b * (BigInteger.ModPow(a, n, m) - 1) * ModInv(a - 1, m) % m;
+
+        return (resA, resB);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/23/illustration.jpeg b/2019/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/23/illustration.jpeg differ diff --git a/2019/23/index.html b/2019/23/index.html new file mode 100644 index 00000000..24353c55 --- /dev/null +++ b/2019/23/index.html @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/23 'Category Six'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/23

+

Category Six

+

in C#

+

+

by encse

+
+ +
+ +
+

The droids have finished repairing as much of the ship as they can. Their report indicates that this was a Category 6 disaster - not because it was that bad, but because it destroyed the stockpile of Category 6 network cables as well as most of the ship's network infrastructure.

+

You'll need to rebuild the network from scratch.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Packets = System.Collections.Generic.List<(long address, long x, long y)>;
+
+namespace AdventOfCode.Y2019.Day23;
+
+[ProblemName("Category Six")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, false);
+    public object PartTwo(string input) => Solve(input, true);
+
+    long Solve(string input, bool hasNat) {
+        var machines = (
+            from address in Enumerable.Range(0, 50)
+            select Nic(input, address)
+        ).ToList();
+
+        var natAddress = 255;
+
+        if (hasNat) {
+            machines.Add(Nat(natAddress));
+        }
+
+        var packets = new Packets();
+        while (!packets.Any(packet => packet.address == natAddress)) {
+            foreach (var machine in machines) {
+                packets = machine(packets);
+            }
+        }
+        return packets.Single(packet => packet.address == natAddress).y;
+    }
+
+    (List data, Packets packets) Receive(Packets packets, int address) {
+        var filteredPackets = new Packets();
+        var data = new List();
+        foreach (var packet in packets) {
+            if (packet.address == address) {
+                data.Add(packet.x);
+                data.Add(packet.y);
+            } else {
+                filteredPackets.Add(packet);
+            }
+        }
+        return (data, filteredPackets);
+    }
+
+    Func Nic(string program, int address) {
+        var icm = new IntCodeMachine(program);
+        var output = icm.Run(address);
+        Debug.Assert(output.Count == 0);
+
+        return (input) => {
+            var (data, packets) = Receive(input, address);
+            if (!data.Any()) {
+                data.Add(-1);
+            }
+            var output = icm.Run(data.ToArray());
+            for (var d = 0; d < output.Count; d += 3) {
+                packets.Add((output[d], output[d + 1], output[d + 2]));
+            }
+            return packets;
+        };
+    }
+
+    Func Nat(int address) {
+        long? yLastSent = null;
+        long? x = null;
+        long? y = null;
+        return (input) => {
+            var (data, packets) = Receive(input, address);
+            if (data.Any()) {
+                (x, y) = (data[^2], data[^1]);
+            }
+            if (packets.Count == 0) {
+                Debug.Assert(x.HasValue && y.HasValue);
+                packets.Add((y == yLastSent ? 255 : 0, x.Value, y.Value));
+                yLastSent = y;
+            }
+            return packets;
+        };
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/24/illustration.jpeg b/2019/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/24/illustration.jpeg differ diff --git a/2019/24/index.html b/2019/24/index.html new file mode 100644 index 00000000..1fd55e25 --- /dev/null +++ b/2019/24/index.html @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/24 'Planet of Discord'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/24

+

Planet of Discord

+

in C#

+

+

by encse

+
+ +
+ +
+

You land on Eris, your last stop before reaching Santa. As soon as you do, your sensors start picking up strange life forms moving around: Eris is infested with bugs! With an over 24-hour roundtrip for messages between you and Earth, you'll have to deal with this problem on your own.

+

Eris isn't a very large place; a scan of the entire area fits into a 5x5 grid (your puzzle input). The scan shows bugs (#) and empty spaces (.).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day24;
+
+record Position(int ilevel, int irow, int icol);
+
+[ProblemName("Planet of Discord")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        int[] levels = Parse(input);
+
+        var seen = new HashSet();
+        var biodiversity = levels[0];
+        while (!seen.Contains(biodiversity)) {
+            seen.Add(biodiversity);
+            levels = Step(levels, FlatNeighbours);
+            biodiversity = levels[levels.Length >> 1];
+        }
+        return biodiversity;
+    }
+
+    public object PartTwo(string input) {
+        int[] levels = Parse(input);
+
+        for (var i = 0; i < 200; i++) {
+            levels = Step(levels, RecursiveNeighbours);
+        }
+
+        return (
+            from level in levels 
+            from pos in Positions() 
+            where pos != (2,2) && HasBug(level, pos.irow, pos.icol) 
+            select 1
+        ).Count();
+    }
+
+    int[] Parse(string input) {
+        var biodiversity = 0;
+        var m = 1;
+        foreach (var ch in input.Replace("\n", "")) {
+            if (ch == '#') {
+                biodiversity += m;
+            }
+            m <<= 1;
+        }
+        return new[] { biodiversity };
+    }
+
+    IEnumerable<(int irow, int icol)> Positions() {
+        for (var irow = 0; irow < 5; irow++) {
+            for (var icol = 0; icol < 5; icol++) {
+                yield return (irow, icol);
+            }
+        }
+    }
+
+    bool HasBug(int biodiversity, int irow, int icol) {
+        return ((biodiversity >> (irow * 5 + icol)) & 1) == 1;
+    }
+
+    int SetBug(int biodiversity, int irow, int icol) {
+        return biodiversity | (1 << (irow * 5 + icol));
+    }
+
+    int[] Step(int[] oldLevelsT, Func> neighbours) {
+        var oldLevels = oldLevelsT.ToList();
+        oldLevels.Insert(0, 0);
+        oldLevels.Add(0);
+
+        var newLevels = new List();
+        for (var ilevel = 0; ilevel < oldLevels.Count; ilevel++) {
+
+            var newLevel = 0;
+            foreach (var (irow, icol) in Positions()) {
+                var bugCount = 0;
+                foreach (var (ilevelT, irowT, icolT) in neighbours(new Position(ilevel, irow, icol))) {
+                    if (ilevelT >= 0 && ilevelT < oldLevels.Count) {
+                        bugCount += HasBug(oldLevels[ilevelT], irowT, icolT) ? 1 : 0;
+                    }
+                }
+
+                if (!HasBug(oldLevels[ilevel], irow, icol)) {
+                    if (bugCount == 1 || bugCount == 2) {
+                        newLevel = SetBug(newLevel, irow, icol);
+                    }
+                } else {
+                    if (bugCount == 1) {
+                        newLevel = SetBug(newLevel, irow, icol);
+                    }
+                }
+            }
+            newLevels.Add(newLevel);
+        }
+
+        return newLevels.ToArray();
+    }
+
+
+    IEnumerable FlatNeighbours(Position pos) {
+        foreach (var (drow, dcol) in new[] { (0, 1), (0, -1), (-1, 0), (1, 0) }) {
+            var (irowT, icolT) = (pos.irow + drow, pos.icol + dcol);
+            if (icolT >= 0 && icolT <= 4 && irowT >= 0 && irowT <= 4) {
+                yield return new Position(pos.ilevel, irowT, icolT);
+            }
+        }
+    }
+
+    IEnumerable RecursiveNeighbours(Position pos) {
+        var (ilevel, irow, icol) = pos;
+        foreach (var (drow, dcol) in new[] { (0, 1), (0, -1), (-1, 0), (1, 0) }) {
+            var posMin = (irow: irow + drow, icol: icol + dcol);
+            var posMax = (irow: irow + drow, icol: icol + dcol);
+            var ilevelT = ilevel;
+
+            if (posMin.irow == -1) {
+                ilevelT = ilevel - 1;
+                posMin = posMax = (1, 2);
+            } else if (posMin.irow == 5) {
+                ilevelT = ilevel - 1;
+                posMin = posMax = (3, 2);
+            } else if (posMin.icol == -1) {
+                ilevelT = ilevel - 1;
+                posMin = posMax = (2, 1);
+            } else if (posMin.icol == 5) {
+                ilevelT = ilevel - 1;
+                posMin = posMax = (2, 3);
+            } else if (posMin == (2, 2)) {
+                ilevelT = ilevel + 1;
+                if (dcol == 0) {
+                    posMin = (drow == 1 ? 0 : 4, 0);
+                    posMax = (drow == 1 ? 0 : 4, 4);
+                } else if (drow == 0) {
+                    posMin = (0, dcol == 1 ? 0 : 4);
+                    posMax = (4, dcol == 1 ? 0 : 4);
+                }
+            }
+
+            for (var irowT = posMin.irow; irowT <= posMax.irow; irowT++) {
+                for (var icolT = posMin.icol; icolT <= posMax.icol; icolT++) {
+                    yield return new Position(ilevelT, irowT, icolT);
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/25/illustration.jpeg b/2019/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/25/illustration.jpeg differ diff --git a/2019/25/index.html b/2019/25/index.html new file mode 100644 index 00000000..6be2aead --- /dev/null +++ b/2019/25/index.html @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/25 'Cryostasis'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/25

+

Cryostasis

+

in C#

+

+

by encse

+
+ +
+ +
+

As you approach Santa's ship, your sensors report two important details:

+

First, that you might be too late: the internal temperature is -40 degrees.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2019.Day25;
+
+[ProblemName("Cryostasis")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var securityRoom = "== Security Checkpoint ==";
+        var icm = new IntCodeMachine(input);
+        var description = icm.Run().ToAscii();
+
+        VisitRooms(securityRoom, icm, description, args => {
+            foreach (var item in args.items) {
+                if (item != "infinite loop") {
+                    var takeCmd = "take " + item;
+                    var clone = icm.Clone();
+                    clone.Run(takeCmd);
+                    if (!clone.Halted() && Inventory(clone).Contains(item)) {
+                        icm.Run(takeCmd);
+                    }
+                }
+            }
+            return null;
+        });
+
+        var door = VisitRooms(securityRoom, icm, description, args =>
+           args.room == securityRoom ? args.doors.Single(door => door != ReverseDir(args.doorTaken)) : null);
+        
+        Random r = new Random();
+        void TakeOrDrop(string cmd, List from, List to) {
+            var i = r.Next(from.Count);
+            var item = from[i];
+            from.RemoveAt(i);
+            to.Add(item);
+            icm.Run(cmd + " " + item);
+        }
+
+        var inventory = Inventory(icm).ToList();
+        var floor = new List();
+        while (true) {
+            var output = icm.Run(door).ToAscii();
+            if (output.Contains("heavier")) {
+                TakeOrDrop("take", floor, inventory);
+            } else if (output.Contains("lighter")) {
+                TakeOrDrop("drop", inventory, floor);
+            } else {
+                return long.Parse(Regex.Match(output, @"\d+").Value);
+            }
+        }
+    }
+
+    List directions = new List() { "south", "east", "west", "north" };
+    string ReverseDir(string direction) => directions[3 - directions.IndexOf(direction)];
+
+    string VisitRooms(
+        string securityRoom,
+        IntCodeMachine icm, 
+        string description, 
+        Func<(IEnumerable items, string room, string doorTaken, IEnumerable doors), string> callback
+    ) {
+
+        var roomsSeen = new HashSet();
+        string DFS(string description, string doorTaken) {
+            var room = description.Split("\n").Single(x => x.Contains("=="));
+            var listing = GetListItems(description).ToHashSet();
+            var doors = listing.Intersect(directions);
+            var items = listing.Except(doors);
+
+            if (!roomsSeen.Contains(room)) {
+                roomsSeen.Add(room);
+
+                var res = callback((items, room, doorTaken, doors));
+                if (res != null) {
+                    return res;
+                }
+                if (room != securityRoom) {
+                    foreach (var door in doors) {
+                        res = DFS(icm.Run(door).ToAscii(), door);
+                        if (res != null) {
+                            return res;
+                        }
+                        icm.Run(ReverseDir(door));
+                    }
+                }
+            }
+            return null;
+        }
+
+        return DFS(description, null);
+    }
+
+    IEnumerable Inventory(IntCodeMachine icm) => GetListItems(icm.Run("inv").ToAscii());
+
+    IEnumerable GetListItems(string description) =>
+        from line in description.Split("\n")
+        where line.StartsWith("- ")
+        select line.Substring(2);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/3/illustration.jpeg b/2019/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/3/illustration.jpeg differ diff --git a/2019/3/index.html b/2019/3/index.html new file mode 100644 index 00000000..52a28f80 --- /dev/null +++ b/2019/3/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/3 'Crossed Wires'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/3

+

Crossed Wires

+

in C#

+

+

by encse

+
+ +
+ +
+

The gravity assist was successful, and you're well on your way to the Venus refuelling station. During the rush back on Earth, the fuel management system wasn't completely installed, so that's next on the priority list.

+

Opening the front panel reveals a jumble of wires. Specifically, two wires are connected to a central port and extend outward on a grid. You trace the path each wire takes as it leaves the central port, one wire per line of text (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day03;
+
+[ProblemName("Crossed Wires")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, (x) => Math.Abs(x.irow) + Math.Abs(x.icol));
+
+    public object PartTwo(string input) => Solve(input, (x) => x.distance1 + x.distance2);
+
+    int Solve(string input, Func<(int irow, int icol, int distance1, int distance2), int> distance) {
+        var paths = input.Split("\n");
+        var trace1 = Trace(paths[0]);
+        var trace2 = Trace(paths[1]);
+
+        var distances =
+            from pos in trace1.Keys
+            where trace2.ContainsKey(pos)
+            select distance((pos.irow, pos.icol, trace1[pos], trace2[pos]));
+        return distances.Min();
+    }
+
+    Dictionary<(int irow, int icol), int> Trace(string path) {
+        var res = new Dictionary<(int irow, int icol), int>();
+
+        var (irow, icol, distance) = (0, 0, 0);
+        foreach (var step in path.Split(",")) {
+            var (drow, dcol) = step[0] switch {
+                'U' => (-1, 0),
+                'D' => (1, 0),
+                'R' => (0, -1),
+                'L' => (0, 1),
+                _ => throw new ArgumentException()
+            };
+
+            for (var i = 0; i < int.Parse(step.Substring(1)); i++) {
+                (irow, icol, distance) = (irow + drow, icol + dcol, distance + 1);
+
+                if (!res.ContainsKey((irow, icol))) {
+                    res[(irow, icol)] = distance;
+                }
+            }
+        }
+
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/4/illustration.jpeg b/2019/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/4/illustration.jpeg differ diff --git a/2019/4/index.html b/2019/4/index.html new file mode 100644 index 00000000..2ebe514a --- /dev/null +++ b/2019/4/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/4 'Secure Container'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/4

+

Secure Container

+

in C#

+

+

by encse

+
+ +
+ +
+

You arrive at the Venus fuel depot only to discover it's protected by a password. The Elves had written the password on a sticky note, but someone threw it out.

+

However, they do remember a few key facts about the password:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2019.Day04;
+
+[ProblemName("Secure Container")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, true);
+    public object PartTwo(string input) => Solve(input, false);
+    private int Solve(string input, bool trippletsAllowed) {
+
+        var args = input.Split("-").Select(int.Parse).ToArray();
+        return (
+            from i in Enumerable.Range(args[0], args[1] - args[0] + 1)
+            where OK(i.ToString(), trippletsAllowed)
+            select i
+        ).Count();
+    }
+
+    private bool OK(string password, bool trippletsAllowed) {
+
+        if (string.Join("", password.OrderBy(ch => ch)) != password) {
+            return false;
+        }
+
+        return (
+            from sequence in Split(password)
+            where sequence.Length >= 2 && (trippletsAllowed || sequence.Length == 2)
+            select sequence
+        ).Any();
+    }
+
+    private IEnumerable Split(string st) {
+        var ich = 0;
+        while (ich < st.Length) {
+            var sequence = Regex.Match(st.Substring(ich), @$"[{st[ich]}]+").Value;
+            yield return sequence;
+            ich += sequence.Length;
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/5/illustration.jpeg b/2019/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/5/illustration.jpeg differ diff --git a/2019/5/index.html b/2019/5/index.html new file mode 100644 index 00000000..d3cfdbd8 --- /dev/null +++ b/2019/5/index.html @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/5 'Sunny with a Chance of Asteroids'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/5

+

Sunny with a Chance of Asteroids

+

in C#

+

+

by encse

+
+ +
+ +
+

You're starting to sweat as the ship makes its way toward Mercury. The Elves suggest that you get the air conditioner working by upgrading your ship computer to support the Thermal Environment Supervision Terminal.

+

The Thermal Environment Supervision Terminal (TEST) starts by running a diagnostic program (your puzzle input). The TEST diagnostic program will run on your existing Intcode computer after a few modifications:

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2019.Day05;
+
+[ProblemName("Sunny with a Chance of Asteroids")]
+class Solution : Solver {
+
+    public object PartOne(string input) => new IntCodeMachine(input).Run(1).Last();
+
+    public object PartTwo(string input) => new IntCodeMachine(input).Run(5).Last();
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/6/illustration.jpeg b/2019/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/6/illustration.jpeg differ diff --git a/2019/6/index.html b/2019/6/index.html new file mode 100644 index 00000000..e3072ce3 --- /dev/null +++ b/2019/6/index.html @@ -0,0 +1,329 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/6 'Universal Orbit Map'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/6

+

Universal Orbit Map

+

in C#

+

+

by encse

+
+ +
+ +
+

You've landed at the Universal Orbit Map facility on Mercury. Because navigation in space often involves transferring between orbits, the orbit maps here are useful for finding efficient routes between, for example, you and Santa. You download a map of the local orbits (your puzzle input).

+

Except for the universal Center of Mass (COM), every object in space is in orbit around exactly one other object. An orbit looks roughly like this:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using ChildToParent = System.Collections.Generic.Dictionary;
+
+namespace AdventOfCode.Y2019.Day06;
+
+[ProblemName("Universal Orbit Map")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var childToParent = ParseTree(input);
+        return (
+            from node in childToParent.Keys
+            select GetAncestors(childToParent, node).Count()
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var childToParent = ParseTree(input);
+        var ancestors1 = new Stack(GetAncestors(childToParent, "YOU"));
+        var ancestors2 = new Stack(GetAncestors(childToParent, "SAN"));
+        while (ancestors1.Peek() == ancestors2.Peek()) {
+            ancestors1.Pop();
+            ancestors2.Pop();
+        }
+        return ancestors1.Count + ancestors2.Count;
+    }
+
+    ChildToParent ParseTree(string input) =>
+        input
+            .Split("\n")
+            .Select(line => line.Split(")"))
+            .ToDictionary(
+                parent_child => parent_child[1],
+                parent_child => parent_child[0]
+            );
+
+    IEnumerable GetAncestors(ChildToParent childToParent, string node) {
+        for (
+            var parent = childToParent[node];
+            parent != null;
+            parent = childToParent.GetValueOrDefault(parent, null)
+        ) {
+            yield return parent;
+        }
+
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/7/illustration.jpeg b/2019/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/7/illustration.jpeg differ diff --git a/2019/7/index.html b/2019/7/index.html new file mode 100644 index 00000000..c4ebf167 --- /dev/null +++ b/2019/7/index.html @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/7 'Amplification Circuit'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/7

+

Amplification Circuit

+

in C#

+

+

by encse

+
+ +
+ +
+

Based on the navigational maps, you're going to need to send more power to your ship's thrusters to reach Santa in time. To do this, you'll need to configure a series of amplifiers already installed on the ship.

+

There are five amplifiers connected in series; each one receives an input signal and produces an output signal. They are connected such that the first amplifier's output leads to the second amplifier's input, the second amplifier's output leads to the third amplifier's input, and so on. The first amplifier's input value is 0, and the last amplifier's output leads to your ship's thrusters.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day07;
+
+[ProblemName("Amplification Circuit")]
+class Solution : Solver {
+
+    public object PartOne(string prg) => Solve(prg, false, new[] { 0, 1, 2, 3, 4 });
+    public object PartTwo(string prg) => Solve(prg, true, new[] { 5, 6, 7, 8, 9 });
+
+    long Solve(string prg, bool loop, int[] prgids) {
+        var amps = Enumerable.Range(0, 5).Select(x => new IntCodeMachine(prg)).ToArray();
+        var max = 0L;
+
+        foreach (var perm in Permutations(prgids)) {
+            max = Math.Max(max, ExecAmps(amps, perm, loop));
+        }
+        return max;
+    }
+
+    long ExecAmps(IntCodeMachine[] amps, int[] prgid, bool loop) {
+
+        for (var i = 0; i < amps.Length; i++) {
+            amps[i].Reset();
+            amps[i].input.Enqueue(prgid[i]);
+        }
+
+        var data = new[] { 0L };
+
+        while (true) {
+            for (var i = 0; i < amps.Length; i++) {
+                data = amps[i].Run(data).ToArray();
+            }
+            if (amps.All(amp => amp.Halted())) {
+                return data.Last();
+            }
+            if (!loop) {
+                data = new long[0];
+            }
+        }
+    }
+
+    IEnumerable Permutations(T[] rgt) {
+       
+        IEnumerable PermutationsRec(int i) {
+            if (i == rgt.Length) {
+                yield return rgt.ToArray();
+            }
+
+            for (var j = i; j < rgt.Length; j++) {
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+                foreach (var perm in PermutationsRec(i + 1)) {
+                    yield return perm;
+                }
+                (rgt[i], rgt[j]) = (rgt[j], rgt[i]);
+            }
+        }
+
+        return PermutationsRec(0);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/8/illustration.jpeg b/2019/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/8/illustration.jpeg differ diff --git a/2019/8/index.html b/2019/8/index.html new file mode 100644 index 00000000..538456a0 --- /dev/null +++ b/2019/8/index.html @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/8 'Space Image Format'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/8

+

Space Image Format

+

in C#

+

+

by encse

+
+ +
+ +
+

The Elves' spirits are lifted when they realize you have an opportunity to reboot one of their Mars rovers, and so they are curious if you would spend a brief sojourn on Mars. You land your ship near the rover.

+

When you reach the rover, you discover that it's already in the process of rebooting! It's just waiting for someone to enter a BIOS password. The Elf responsible for the rover takes a picture of the password (your puzzle input) and sends it to you via the Digital Sending Network.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2019.Day08;
+
+[ProblemName("Space Image Format")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var zeroMin = int.MaxValue;
+        var checksum = 0;
+        foreach (var layer in Layers(input)) {
+            var zero = layer.Count(item => item == 0);
+            var ones = layer.Count(item => item == 1);
+            var twos = layer.Count(item => item == 2);
+
+            if (zeroMin > zero) {
+                zeroMin = zero;
+                checksum = ones * twos;
+            }
+        }
+        return checksum;
+    }
+
+    public object PartTwo(string input) {
+        var img = new char[6 * 25];
+        foreach (var layer in Layers(input).Reverse()) {
+            for (var i = 0; i < img.Length; i++) {
+                img[i] = layer[i] switch {
+                    0 => ' ',
+                    1 => '#',
+                    _ => img[i]
+                };
+            }
+        }
+        return string.Join("", 
+            img.Chunk(25).Select(line => string.Join("", line)+"\n")
+        ).Ocr();
+    }
+
+    int[][] Layers(string input) =>
+        input.Select(ch => ch - '0').Chunk(6 * 25).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2019/9/illustration.jpeg b/2019/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2019/9/illustration.jpeg differ diff --git a/2019/9/index.html b/2019/9/index.html new file mode 100644 index 00000000..aaf53d03 --- /dev/null +++ b/2019/9/index.html @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2019/9 'Sensor Boost'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2019/9

+

Sensor Boost

+

in C#

+

+

by encse

+
+ +
+ +
+

You've just said goodbye to the rebooted rover and left Mars when you receive a faint distress signal coming from the asteroid belt. It must be the Ceres monitoring station!

+

In order to lock on to the signal, you'll need to boost your sensors. The Elves send up the latest BOOST program - Basic Operation Of System Test.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2019.Day09;
+
+[ProblemName("Sensor Boost")]
+class Solution : Solver {
+
+    public object PartOne(string input) => new IntCodeMachine(input).Run(1).Single();
+    public object PartTwo(string input) => new IntCodeMachine(input).Run(2).Single();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/1/illustration.jpeg b/2020/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/1/illustration.jpeg differ diff --git a/2020/1/index.html b/2020/1/index.html new file mode 100644 index 00000000..a14cf0ce --- /dev/null +++ b/2020/1/index.html @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/1 'Report Repair'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/1

+

Report Repair

+

in C#

+

+

by encse

+
+ +
+ +
+

After saving Christmas five years in a row, you've decided to take a vacation at a nice resort on a tropical island. Surely, Christmas will go on without you.

+

The tropical island has its own currency and is entirely cash-only. The gold coins used there have a little picture of a starfish; the locals just call them stars. None of the currency exchanges seem to have heard of them, but somehow, you'll need to find fifty of these coins by the time you arrive so you can pay the deposit on your room.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day01;
+
+[ProblemName("Report Repair")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var numbers = Numbers(input);
+        return (
+            from x in numbers 
+            let y = 2020 - x
+            where numbers.Contains(y)
+            select x * y
+        ).First();
+    }
+
+    public object PartTwo(string input) {
+        var numbers = Numbers(input);
+        return (
+            from x in numbers 
+            from y in numbers 
+            let z = 2020 - x - y
+            where numbers.Contains(z)
+            select x * y * z
+        ).First();
+    }
+
+    HashSet Numbers(string input) {
+        return input.Split('\n').Select(int.Parse).ToHashSet();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/10/illustration.jpeg b/2020/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/10/illustration.jpeg differ diff --git a/2020/10/index.html b/2020/10/index.html new file mode 100644 index 00000000..eb871c6a --- /dev/null +++ b/2020/10/index.html @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/10 'Adapter Array'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/10

+

Adapter Array

+

in C#

+

+

by encse

+
+ +
+ +
+

Patched into the aircraft's data port, you discover weather forecasts of a massive tropical storm. Before you can figure out whether it will impact your vacation plans, however, your device suddenly turns off!

+

Its battery is dead.

+

Read the full puzzle.

+
+
using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day10;
+
+[ProblemName("Adapter Array")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var jolts = Parse(input);
+        var window = jolts.Skip(1).Zip(jolts).Select(p => (current: p.First, prev: p.Second));
+
+        return
+             window.Count(pair => pair.current - pair.prev == 1) *
+             window.Count(pair => pair.current - pair.prev == 3);
+    }
+
+    public object PartTwo(string input) {
+        var jolts = Parse(input);
+
+        // dynamic programming with rolling variables a, b, c for the function values at i + 1, i + 2 and i + 3.
+        var (a, b, c) = (1L, 0L, 0L); 
+        for (var i = jolts.Count - 2; i >= 0; i--) {
+            var s =  
+                (i + 1 < jolts.Count && jolts[i + 1] - jolts[i] <= 3 ? a : 0) +
+                (i + 2 < jolts.Count && jolts[i + 2] - jolts[i] <= 3 ? b : 0) +
+                (i + 3 < jolts.Count && jolts[i + 3] - jolts[i] <= 3 ? c : 0);
+            (a, b, c) = (s, a, b);
+        }
+        return a;
+    }
+
+    ImmutableList Parse(string input) {
+        var num = input.Split("\n").Select(int.Parse).OrderBy(x => x);
+        return ImmutableList
+            .Create(0)
+            .AddRange(num)
+            .Add(num.Last() + 3);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/11/illustration.jpeg b/2020/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/11/illustration.jpeg differ diff --git a/2020/11/index.html b/2020/11/index.html new file mode 100644 index 00000000..4e217abe --- /dev/null +++ b/2020/11/index.html @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/11 'Seating System'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/11

+

Seating System

+

in C#

+

+

by encse

+
+ +
+ +
+

Your plane lands with plenty of time to spare. The final leg of your journey is a ferry that goes directly to the tropical island where you can finally start your vacation. As you reach the waiting area to board the ferry, you realize you're so early, nobody else has even arrived yet!

+

By modeling the process people use to choose (or abandon) their seat in the waiting area, you're pretty sure you can predict the best place to sit. You make a quick map of the seat layout (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day11;
+
+[ProblemName("Seating System")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 4, _ => true);
+    public object PartTwo(string input) => Solve(input, 5, place => place != '.');
+
+    int Solve(string input, int occupiedLimit, Func placeToCheck) {
+        var (crow, ccol) = (input.Split("\n").Length, input.IndexOf('\n'));
+
+        char PlaceInDirection(char[] st, int idx, int drow, int dcol) {
+            var (irow, icol) = (idx / ccol, idx % ccol);
+            while (true) {
+                (irow, icol) = (irow + drow, icol + dcol);
+                var place =
+                    irow < 0 || irow >= crow ? 'L' :
+                    icol < 0 || icol >= ccol ? 'L' :
+                    st[irow * ccol + icol];
+                if (placeToCheck(place)) {
+                    return place;
+                }
+            }
+        }
+
+        int OccupiedPlacesAround(char[] st, int idx) {
+            var directions = new[] { (0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1) };
+            var occupied = 0;
+            foreach (var (drow, dcol) in directions) {
+                if (PlaceInDirection(st, idx, drow, dcol) == '#') {
+                    occupied++;
+                }
+            }
+            return occupied;
+        }
+
+        var prevState = new char[0];
+        var state = input.Replace("\n", "").Replace("L", "#").ToArray();
+        while (!prevState.SequenceEqual(state)) {
+            prevState = state;
+            state = state.Select((place, i) =>
+                place == '#' && OccupiedPlacesAround(state, i) >= occupiedLimit ? 'L' :
+                place == 'L' && OccupiedPlacesAround(state, i) == 0             ? '#' :
+                place /*otherwise*/
+            ).ToArray();
+        }
+        return state.Count(place => place == '#');
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/12/illustration.jpeg b/2020/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/12/illustration.jpeg differ diff --git a/2020/12/index.html b/2020/12/index.html new file mode 100644 index 00000000..091c2bac --- /dev/null +++ b/2020/12/index.html @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/12 'Rain Risk'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/12

+

Rain Risk

+

in C#

+

+

by encse

+
+ +
+ +
+

Your ferry made decent progress toward the island, but the storm came in faster than anyone expected. The ferry needs to take evasive actions!

+

Unfortunately, the ship's navigation computer seems to be malfunctioning; rather than giving a route directly to safety, it produced extremely circuitous instructions. When the captain uses the PA system to ask if anyone can help, you quickly volunteer.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Numerics;
+
+namespace AdventOfCode.Y2020.Day12;
+
+record State(Complex pos, Complex dir);
+
+[ProblemName("Rain Risk")]
+class Solution : Solver {
+
+    public object PartOne(string input) => MoveShip(input, true);
+    public object PartTwo(string input) => MoveShip(input, false);
+
+    double MoveShip(string input, bool part1) =>
+        input
+            .Split("\n")
+            .Select(line => (line[0], int.Parse(line.Substring(1))))
+            .Aggregate(
+                new State(pos: Complex.Zero, dir: part1 ? Complex.One : new Complex(10, 1)), 
+                (state, line) => 
+                    line switch {
+                        ('N', var arg) when part1 => state with {pos = state.pos + arg * Complex.ImaginaryOne},
+                        ('N', var arg)            => state with {dir = state.dir + arg * Complex.ImaginaryOne},
+                        ('S', var arg) when part1 => state with {pos = state.pos - arg * Complex.ImaginaryOne},
+                        ('S', var arg)            => state with {dir = state.dir - arg * Complex.ImaginaryOne},
+                        ('E', var arg) when part1 => state with {pos = state.pos + arg},
+                        ('E', var arg)            => state with {dir = state.dir + arg},
+                        ('W', var arg) when part1 => state with {pos = state.pos - arg},
+                        ('W', var arg)            => state with {dir = state.dir - arg},
+                        ('F', var arg)            => state with {pos = state.pos + arg * state.dir},
+                        ('L', 90)  or ('R', 270)  => state with {dir =  state.dir * Complex.ImaginaryOne},
+                        ('L', 270) or ('R', 90)   => state with {dir = -state.dir * Complex.ImaginaryOne},
+                        ('L', 180) or ('R', 180)  => state with {dir = -state.dir},
+                        _ => throw new Exception()
+                    }, 
+                state => Math.Abs(state.pos.Imaginary) + Math.Abs(state.pos.Real));
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/13/illustration.jpeg b/2020/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/13/illustration.jpeg differ diff --git a/2020/13/index.html b/2020/13/index.html new file mode 100644 index 00000000..1b602266 --- /dev/null +++ b/2020/13/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/13 'Shuttle Search'' in C# by encse + + + + + + + + + + + + + + +
+
+
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!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/14/illustration.jpeg b/2020/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/14/illustration.jpeg differ diff --git a/2020/14/index.html b/2020/14/index.html new file mode 100644 index 00000000..90a81b3d --- /dev/null +++ b/2020/14/index.html @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/14 'Docking Data'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/14

+

Docking Data

+

in C#

+

+

by encse

+
+ +
+ +
+

As your ferry approaches the sea port, the captain asks for your help again. The computer system that runs this port isn't compatible with the docking program on the ferry, so the docking parameters aren't being correctly initialized in the docking program's memory.

+

After a brief inspection, you discover that the sea port's computer system uses a strange bitmask system in its initialization program. Although you don't have the correct decoder chip handy, you can emulate it in software!

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2020.Day14;
+
+[ProblemName("Docking Data")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var mem = new Dictionary();
+        var orMask = 0L;
+        var andMask = 0xffffffffffffffL;
+        foreach (var line in input.Split("\n")) {
+            if (line.StartsWith("mask")) {
+                var mask = line.Split(" = ")[1];
+                andMask = Convert.ToInt64(mask.Replace("X", "1"), 2);
+                orMask = Convert.ToInt64(mask.Replace("X", "0"), 2);
+            } else {
+                var num = Regex.Matches(line, "\\d+").Select(match => long.Parse(match.Value)).ToArray();
+                mem[num[0]] = num[1] & andMask | orMask;
+            }
+        }
+        return mem.Values.Sum();
+    }
+
+    public object PartTwo(string input) {
+        var mem = new Dictionary();
+        var mask = "";
+        foreach (var line in input.Split("\n")) {
+            if (line.StartsWith("mask")) {
+                mask = line.Split(" = ")[1];
+            } else {
+                var num = Regex.Matches(line, "\\d+").Select(match => long.Parse(match.Value)).ToArray();
+                var (baseAddr, value) = (num[0], num[1]);
+                foreach (var addr in Addresses(baseAddr, mask, 35)) {
+                    mem[addr] = value;
+                }
+
+            }
+        }
+        return mem.Values.Sum();
+    }
+
+    IEnumerable Addresses(long baseAddr, string mask, int i) {
+        if (i == -1) {
+            yield return 0;
+        } else {
+            foreach (var prefix in Addresses(baseAddr, mask, i - 1)) {
+                if (mask[i] == '0') {
+                    yield return (prefix << 1) + ((baseAddr >> 35 - i) & 1);
+                } else if (mask[i] == '1') {
+                    yield return (prefix << 1) + 1;
+                } else {
+                    yield return (prefix << 1);
+                    yield return (prefix << 1) + 1;
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/15/illustration.jpeg b/2020/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/15/illustration.jpeg differ diff --git a/2020/15/index.html b/2020/15/index.html new file mode 100644 index 00000000..28b75da1 --- /dev/null +++ b/2020/15/index.html @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/15 'Rambunctious Recitation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/15

+

Rambunctious Recitation

+

in C#

+

+

by encse

+
+ +
+ +
+

You catch the airport shuttle and try to book a new flight to your vacation island. Due to the storm, all direct flights have been cancelled, but a route is available to get around the storm. You take it.

+

While you wait for your flight, you decide to check in with the Elves back at the North Pole. They're playing a memory game and are ever so excited to explain the rules!

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2020.Day15;
+
+[ProblemName("Rambunctious Recitation")]
+class Solution : Solver {
+
+    public object PartOne(string input) => NumberAt(input, 2020);
+    public object PartTwo(string input) => NumberAt(input, 30000000);
+
+    public int NumberAt(string input, int count) {
+        var numbers = input.Split(",").Select(int.Parse).ToArray();
+        var (lastSeen, number) = (new int[count], numbers[0]);
+        for (var round = 0; round < count; round++) {
+            (lastSeen[number], number) = (round,
+                round < numbers.Length ? numbers[round] :
+                lastSeen[number] == 0  ? 0 :
+                /* otherwise */          round - lastSeen[number]);
+        }
+        return number;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/16/illustration.jpeg b/2020/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/16/illustration.jpeg differ diff --git a/2020/16/index.html b/2020/16/index.html new file mode 100644 index 00000000..d7a6a121 --- /dev/null +++ b/2020/16/index.html @@ -0,0 +1,376 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/16 'Ticket Translation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/16

+

Ticket Translation

+

in C#

+

+

by encse

+
+ +
+ +
+

As you're walking to yet another connecting flight, you realize that one of the legs of your re-routed trip coming up is on a high-speed train. However, the train ticket you were given is in a language you don't understand. You should probably figure out what it says before you get to the train station after the next flight.

+

Unfortunately, you can't actually read the words on the ticket. You can, however, read the numbers, and so you figure out the fields these tickets must have and the valid ranges for values in those fields.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2020.Day16;
+
+record Field(string name, Func isValid);
+record Problem(Field[] fields, int[][] tickets);
+
+[ProblemName("Ticket Translation")]
+class Solution : Solver {
+
+    Field[] FieldCandidates(IEnumerable fields, params int[] values) =>
+        fields.Where(field => values.All(field.isValid)).ToArray();
+
+    public object PartOne(string input) {
+        var problem = Parse(input);
+        // add the values that cannot be associated with any of the fields
+        return (
+            from ticket in problem.tickets 
+            from value in ticket 
+            where !FieldCandidates(problem.fields, value).Any() 
+            select value
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+
+        var problem = Parse(input);
+        // keep valid tickets only
+        var tickets = (
+            from ticket in problem.tickets 
+            where ticket.All(value => FieldCandidates(problem.fields, value).Any()) 
+            select ticket
+        ).ToArray();
+
+        // The problem is set up in a way that we can always find a column
+        // that has just one field-candidate left.
+
+        var fields = problem.fields.ToHashSet();
+        var columns = Enumerable.Range(0, fields.Count).ToHashSet();
+
+        var res = 1L;
+        while (columns.Any()) {
+            foreach (var column in columns) {
+                var valuesInColumn = (from ticket in tickets select ticket[column]).ToArray();
+                var candidates = FieldCandidates(fields, valuesInColumn);
+                if (candidates.Length == 1) {
+                    var field = candidates.Single();
+                    fields.Remove(field);
+                    columns.Remove(column);
+                    if (field.name.StartsWith("departure")) {
+                        res *= valuesInColumn.First();
+                    }
+                    break;
+                }
+            }
+        }
+        return res;
+    }
+
+    Problem Parse(string input) {
+        int[] parseNumbers(string line) => (      
+            from m in Regex.Matches(line, "\\d+") // take the consecutive ranges of digits
+            select int.Parse(m.Value)             // convert them to numbers
+        ).ToArray();
+
+        var blocks = (
+            from block in input.Split("\n\n")     // blocks are delimited by empty lines
+            select block.Split("\n")              // convert them to lines
+        ).ToArray();
+        
+        var fields = (                          
+            from line in blocks.First()           // line <- ["departure location: 49-920 or 932-950", ...]
+            let bounds = parseNumbers(line)       // bounds = [49, 920, 932, 950]
+            select 
+                new Field(
+                    line.Split(":")[0],           // "departure location"
+                    n => 
+                        n >= bounds[0] && n <= bounds[1] || 
+                        n >= bounds[2] && n <= bounds[3]
+                )
+        ).ToArray();
+
+        var tickets = (                         
+            from block in blocks.Skip(1)          // ticket information is in the second and third blocks 
+            let numbers = block.Skip(1)           // skip "your ticket:" / "nearby tickets:"
+            from line in numbers                  // line <- ["337,687,...", "223,323,...", ...]
+            select parseNumbers(line)             // [337, 687, 607]
+        ).ToArray();
+
+        return new Problem(fields, tickets);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/17/illustration.jpeg b/2020/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/17/illustration.jpeg differ diff --git a/2020/17/index.html b/2020/17/index.html new file mode 100644 index 00000000..c48f6bc1 --- /dev/null +++ b/2020/17/index.html @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/17 'Conway Cubes'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/17

+

Conway Cubes

+

in C#

+

+

by encse

+
+ +
+ +
+

As your flight slowly drifts through the sky, the Elves at the Mythical Information Bureau at the North Pole contact you. They'd like some help debugging a malfunctioning experimental energy source aboard one of their super-secret imaging satellites.

+

The experimental energy source is based on cutting-edge technology: a set of Conway Cubes contained in a pocket dimension! When you hear it's having problems, you can't help but agree to take a look.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day17;
+
+[ProblemName("Conway Cubes")]
+class Solution : Solver {
+    public object PartOne(string input) {
+        var ds = (from dx in new[] { -1, 0, 1 }
+                  from dy in new[] { -1, 0, 1 }
+                  from dz in new[] { -1, 0, 1 }
+                  where dx != 0 || dy != 0 || dz != 0
+                  select (dx, dy, dz)).ToArray();
+        return Solve(
+            input,
+            (x, y) => (x: x, y: y, z: 0),
+            (p) => ds.Select(d => (p.x + d.dx, p.y + d.dy, p.z + d.dz)));
+    }
+
+    public object PartTwo(string input) {
+        var ds = (from dx in new[] { -1, 0, 1 }
+                  from dy in new[] { -1, 0, 1 }
+                  from dz in new[] { -1, 0, 1 }
+                  from dw in new[] { -1, 0, 1 }
+                  where dx != 0 || dy != 0 || dz != 0 || dw != 0
+                  select (dx, dy, dz, dw)).ToArray();
+
+        return Solve(
+            input,
+            (x, y) => (x: x, y: y, z: 0, w: 0),
+            (p) => ds.Select(d => (p.x + d.dx, p.y + d.dy, p.z + d.dz, p.w + d.dw)));
+    }
+
+    private int Solve(string input, Func create, Func> neighbours) {
+        var lines = input.Split("\n");
+        var (width, height) = (lines[0].Length, lines.Length);
+        var activePoints = new HashSet(
+            from x in Enumerable.Range(0, width) 
+            from y in Enumerable.Range(0, height) 
+            where lines[y][x] == '#' 
+            select create(x,y)
+        );
+        
+        for (var i = 0; i < 6; i++) {
+            var newActivePoints = new HashSet();
+            var inactivePoints = new Dictionary();
+
+            foreach (var point in activePoints) {
+                var activeNeighbours = 0;
+                foreach (var neighbour in neighbours(point)) {
+                    if (activePoints.Contains(neighbour)) {
+                        activeNeighbours++;
+                    } else {
+                        inactivePoints[neighbour] = inactivePoints.GetValueOrDefault(neighbour) + 1;
+                    }
+                }
+
+                if (activeNeighbours == 2 || activeNeighbours == 3) {
+                    newActivePoints.Add(point);
+                }
+            }
+
+            foreach (var (point, activeNeighbours) in inactivePoints) {
+                if (activeNeighbours == 3) {
+                    newActivePoints.Add(point);
+                }
+            }
+            activePoints = newActivePoints;
+        }
+        return activePoints.Count();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/18/illustration.jpeg b/2020/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/18/illustration.jpeg differ diff --git a/2020/18/index.html b/2020/18/index.html new file mode 100644 index 00000000..6e8a7ab3 --- /dev/null +++ b/2020/18/index.html @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/18 'Operation Order'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/18

+

Operation Order

+

in C#

+

+

by encse

+
+ +
+ +
+

As you look out the window and notice a heavily-forested continent slowly appear over the horizon, you are interrupted by the child sitting next to you. They're curious if you could help them with their math homework.

+

Unfortunately, it seems like this "math" follows different rules than you remember.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2020.Day18;
+
+[ProblemName("Operation Order")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, true);
+    public object PartTwo(string input) => Solve(input, false);
+
+    long Solve(string input, bool part1) {
+        var sum = 0L;
+        foreach (var line in input.Split("\n")) {
+            // https://en.wikipedia.org/wiki/Shunting-yard_algorithm
+
+            var opStack = new Stack();
+            var valStack = new Stack();
+
+            void evalUntil(string ops) {
+                while (!ops.Contains(opStack.Peek())) {
+                    if (opStack.Pop() == '+') {
+                        valStack.Push(valStack.Pop() + valStack.Pop());
+                    } else {
+                        valStack.Push(valStack.Pop() * valStack.Pop());
+                    }
+                }
+            }
+
+            opStack.Push('(');
+
+            foreach (var ch in line) {
+                switch (ch) {
+                    case ' ':
+                        break;
+                    case '*':
+                        evalUntil("(");
+                        opStack.Push('*');
+                        break;
+                    case '+':
+                        evalUntil(part1 ? "(" : "(*");
+                        opStack.Push('+');
+                        break;
+                    case '(':
+                        opStack.Push('(');
+                        break;
+                    case ')':
+                        evalUntil("(");
+                        opStack.Pop();
+                        break;
+                    default:
+                        valStack.Push(long.Parse(ch.ToString()));
+                        break;
+                }
+            }
+
+            evalUntil("(");
+
+            sum += valStack.Single();
+        }
+
+        return sum;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/19/illustration.jpeg b/2020/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/19/illustration.jpeg differ diff --git a/2020/19/index.html b/2020/19/index.html new file mode 100644 index 00000000..52665a0e --- /dev/null +++ b/2020/19/index.html @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/19 'Monster Messages'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/19

+

Monster Messages

+

in C#

+

+

by encse

+
+ +
+ +
+

You land in an airport surrounded by dense forest. As you walk to your high-speed train, the Elves at the Mythical Information Bureau contact you again. They think their satellite has collected an image of a sea monster! Unfortunately, the connection to the satellite is having problems, and many of the messages sent back from the satellite have been corrupted.

+

They sent you a list of the rules valid messages should obey and a list of received messages they've collected so far (your puzzle input).

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using Parser = System.Func>;
+
+namespace AdventOfCode.Y2020.Day19;
+
+[ProblemName("Monster Messages")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, true);
+    public object PartTwo(string input) => Solve(input, false);
+
+    int Solve(string input, bool part1) {
+        var blocks = (
+            from block in input.Split("\n\n") 
+            select block.Split("\n")
+        ).ToArray();
+
+        var rules = new Dictionary(
+            from line in blocks[0]
+                let parts = line.Split(": ")
+                let index = int.Parse(parts[0])
+                let rule = parts[1]
+            select 
+                new KeyValuePair(index, rule)
+        );
+
+        if (!part1) {
+            rules[8] = "42 | 42 8";
+            rules[11] = "42 31 | 42 11 31";
+        }
+
+        // a parser will process some prefix of the input and return the possible remainders (nothing in case of error).
+        var parsers = new Dictionary();
+        Parser getParser(int index) {
+            if (!parsers.ContainsKey(index)) {
+                parsers[index] = (input) => getParser(index)(input); //avoid stack overflows in case of recursion in the grammar
+
+                parsers[index] = 
+                    alt(
+                        from sequence in rules[index].Split(" | ") 
+                        select 
+                            seq(
+                                from item in sequence.Split(" ") 
+                                select
+                                    int.TryParse(item, out var i) ? getParser(i) : literal(item.Trim('"'))
+                            )
+                    );
+            }
+            return parsers[index];
+        }
+
+        var parser = getParser(0);
+        return blocks[1].Count(data => parser(data).Any(st => st == ""));
+    }
+
+    // Parser combinators
+    static Parser literal(string st) =>
+        input => input.StartsWith(st) ? new[] { input.Substring(st.Length) } : new string[0];
+
+    static Parser seq(IEnumerable parsers) {
+        if (parsers.Count() == 1) {
+            return parsers.Single();
+        }
+
+        var parseHead = parsers.First();
+        var parseTail = seq(parsers.Skip(1));
+
+        return input => 
+            from tail in parseHead(input)
+            from rest in parseTail(tail)
+            select rest;
+    }
+
+    static Parser alt(IEnumerable parsers) {
+        if (parsers.Count() == 1) {
+            return parsers.Single();
+        }
+        
+        var arr = parsers.ToArray(); // don't recalc the enumerable in the parse phase
+        return input => 
+            from parser in arr
+            from rest in parser(input)
+            select rest;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/2/illustration.jpeg b/2020/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/2/illustration.jpeg differ diff --git a/2020/2/index.html b/2020/2/index.html new file mode 100644 index 00000000..eb84ed8d --- /dev/null +++ b/2020/2/index.html @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/2 'Password Philosophy'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/2

+

Password Philosophy

+

in C#

+

+

by encse

+
+ +
+ +
+

Your flight departs in a few days from the coastal airport; the easiest way down to the coast from here is via toboggan.

+

The shopkeeper at the North Pole Toboggan Rental Shop is having a bad day. "Something's wrong with our computers; we can't log in!" You ask if you can take a look.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day02;
+
+record PasswordEntry(int a, int b, char ch, string password);
+
+[ProblemName("Password Philosophy")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ValidCount(input, (PasswordEntry pe) => {
+        var count = pe.password.Count(ch => ch == pe.ch);
+        return pe.a <= count && count <= pe.b;
+    });
+
+    public object PartTwo(string input) => ValidCount(input, (PasswordEntry pe) => {
+        return (pe.password[pe.a - 1] == pe.ch) ^ (pe.password[pe.b - 1] == pe.ch);
+    });
+
+    int ValidCount(string input, Func isValid) =>
+        input
+            .Split("\n")
+            .Select(line => {
+                var parts = line.Split(' ');
+                var range = parts[0].Split('-').Select(int.Parse).ToArray();
+                var ch = parts[1][0];
+                return new PasswordEntry(range[0], range[1], ch, parts[2]);
+            })
+            .Count(isValid);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/20/illustration.jpeg b/2020/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/20/illustration.jpeg differ diff --git a/2020/20/index.html b/2020/20/index.html new file mode 100644 index 00000000..250728ed --- /dev/null +++ b/2020/20/index.html @@ -0,0 +1,495 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/20 'Jurassic Jigsaw'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/20

+

Jurassic Jigsaw

+

in C#

+

+

by encse

+
+ +
+ +
+

The high-speed train leaves the forest and quickly carries you south. You can even see a desert in the distance! Since you have some spare time, you might as well see if there was anything interesting in the image the Mythical Information Bureau satellite captured.

+

After decoding the satellite messages, you discover that the data actually contains many small images created by the satellite's camera array. The camera array consists of many cameras; rather than produce a single square image, they produce many smaller square image tiles that need to be reassembled back into a single image.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2020.Day20;
+
+[ProblemName("Jurassic Jigsaw")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var tiles = AssemblePuzzle(input);
+        return 
+            tiles.First().First().id *
+            tiles.First().Last().id *
+            tiles.Last().First().id *
+            tiles.Last().Last().id;
+    }
+
+    public object PartTwo(string input) {
+        var image = MergeTiles(AssemblePuzzle(input));
+
+        var monster = new string[]{
+            "                  # ",
+            "#    ##    ##    ###",
+            " #  #  #  #  #  #   "
+        };
+
+        while (true) {
+            var monsterCount = MatchCount(image, monster);
+            if (monsterCount > 0) {
+                var hashCountInImage = image.ToString().Count(ch => ch == '#');
+                var hashCountInMonster = string.Join("\n", monster).Count(ch => ch == '#');
+                return hashCountInImage - monsterCount * hashCountInMonster;
+            }
+            image.ChangeOrientation();
+        }
+    }
+
+    private Tile[] ParseTiles(string input) {
+        return (
+            from block in input.Split("\n\n")
+            let lines = block.Split("\n")
+            let id = Regex.Match(lines[0], "\\d+").Value
+            let image = lines.Skip(1).Where(x => x != "").ToArray()
+            select new Tile(int.Parse(id), image)
+        ).ToArray();
+    }
+
+    private Tile[][] AssemblePuzzle(string input) {
+        var tiles = ParseTiles(input);
+
+        // Collects tiles sharing a common edge. 
+        // Due to the way the input is created, the list contains
+        // - one item for tiles on the edge or 
+        // - two for inner pieces.
+        var pairs = new Dictionary>();
+        foreach (var tile in tiles) {
+            for (var i = 0; i < 8; i++) {
+                var pattern = tile.Top();
+                if (!pairs.ContainsKey(pattern)) {
+                    pairs[pattern] = new List();
+                }
+                pairs[pattern].Add(tile);
+                tile.ChangeOrientation();
+            }
+        }
+
+        bool isEdge(string pattern) => pairs[pattern].Count == 1;
+        Tile getNeighbour(Tile tile, string pattern) => pairs[pattern].SingleOrDefault(other => other != tile);
+
+        Tile putTileInPlace(Tile above, Tile left) {
+            if (above == null && left == null) {
+                // find top-left corner
+                foreach (var tile in tiles) {
+                    for (var i = 0; i < 8; i++) {
+                        if (isEdge(tile.Top()) && isEdge(tile.Left())) {
+                            return tile;
+                        }
+                        tile.ChangeOrientation();
+                    }
+                }
+            } else {
+                // we know the tile from the inversion structure, just need to find its orientation
+                var tile = above != null ? getNeighbour(above, above.Bottom()) : getNeighbour(left, left.Right());
+                while (true) {
+                    var topMatch = above == null ? isEdge(tile.Top())  : tile.Top() == above.Bottom();
+                    var leftMatch = left == null ? isEdge(tile.Left()) : tile.Left() == left.Right();
+
+                    if (topMatch && leftMatch) {
+                        return tile;
+                    }
+                    tile.ChangeOrientation();
+                }
+            }
+
+            throw new Exception();
+        }
+
+        // once the corner is fixed we can always find a unique tile that matches the one to the left & above
+        // just fill up the tileset one by one
+        var size = (int)Math.Sqrt(tiles.Length);
+        var puzzle = new Tile[size][];
+        for (var irow = 0; irow < size; irow++) {
+            puzzle[irow] = new Tile[size];
+            for (var icol = 0; icol < size; icol++) {
+                var above = irow == 0 ? null : puzzle[irow - 1][icol];
+                var left  = icol == 0 ? null : puzzle[irow][icol - 1];
+                puzzle[irow][icol] = putTileInPlace(above, left);
+            }
+        }
+        return puzzle;
+    }
+
+    private Tile MergeTiles(Tile[][] tiles) {
+        // create a big tile leaving out the borders
+        var image = new List();
+        var tileSize = tiles[0][0].size;
+        var tileCount = tiles.Length;
+        for (var irow = 0; irow < tileCount; irow++) {
+            for (var i = 1; i < tileSize - 1; i++) {
+                var st = "";
+                for (var icol = 0; icol < tileCount; icol++) {
+                    st += tiles[irow][icol].Row(i).Substring(1, tileSize - 2);
+                }
+                image.Add(st);
+            }
+        }
+        return new Tile(42, image.ToArray());
+    }
+
+    int MatchCount(Tile image, params string[] pattern) {
+        var res = 0;
+        var (ccolP, crowP) = (pattern[0].Length, pattern.Length);
+        for (var irow = 0; irow < image.size - crowP; irow++) 
+        for (var icol = 0; icol < image.size - ccolP ; icol++) {
+            bool match() {
+                for (var icolP = 0; icolP < ccolP; icolP++)
+                for (var irowP = 0; irowP < crowP; irowP++) {
+                    if (pattern[irowP][icolP] == '#' && image[irow + irowP, icol + icolP] != '#') {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            if(match()) {
+                res++;
+            }
+        }
+        return res;
+    }
+}
+
+class Tile {
+    public long id;
+    public int size;
+    string[] image;
+
+    // This is a bit tricky, but makes operations fast and easy to implement.
+    //
+    // - orentation % 4 specifies the rotation of the tile
+    // - orientation % 8 >= 4 means the tile is flipped.
+    //
+    // The actual rotation and flipping happens in the indexer, 
+    // where the input coordinates are adjusted accordingly.
+    //
+    // Checking each 8 possible orientation for a tile requires just 7 incrementation of this value.
+    int orentation = 0;
+
+    public Tile(long id, string[] image) {
+        this.id = id;
+        this.image = image;
+        this.size = image.Length;
+    }
+
+    public void ChangeOrientation() {
+        this.orentation++;
+    }
+
+    public char this[int irow, int icol] {
+        get {
+            for (var i = 0; i < orentation % 4; i++) {
+                (irow, icol) = (icol, size - 1 - irow); // rotate
+            }
+
+            if (orentation % 8 >= 4) {
+                icol = size - 1 - icol; // flip vertical axis
+            }
+
+            return this.image[irow][icol];
+        }
+    }
+
+    public string Row(int irow) => GetSlice(irow, 0, 0, 1);
+    public string Col(int icol) => GetSlice(0, icol, 1, 0);
+    public string Top() => Row(0);
+    public string Bottom() => Row(size - 1);
+    public string Left() => Col(0);
+    public string Right() => Col(size - 1);
+
+    public override string ToString() {
+        return $"Tile {id}:\n" + string.Join("\n", Enumerable.Range(0, size).Select(i => Row(i)));
+    }
+
+    string GetSlice(int irow, int icol, int drow, int dcol) {
+        var st = "";
+        for (var i = 0; i < size; i++) {
+            st += this[irow, icol];
+            irow += drow;
+            icol += dcol;
+        }
+        return st;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/21/illustration.jpeg b/2020/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/21/illustration.jpeg differ diff --git a/2020/21/index.html b/2020/21/index.html new file mode 100644 index 00000000..4eb9413c --- /dev/null +++ b/2020/21/index.html @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/21 'Allergen Assessment'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/21

+

Allergen Assessment

+

in C#

+

+

by encse

+
+ +
+ +
+

You reach the train's last stop and the closest you can get to your vacation island without getting wet. There aren't even any boats here, but nothing can stop you now: you build a raft. You just need a few days' worth of food for your journey.

+

You don't speak the local language, so you can't read any ingredients lists. However, sometimes, allergens are listed in a language you do understand. You should be able to use this information to determine which ingredient contains which allergen and work out which foods are safe to take with you on your trip.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day21;
+
+record Problem(
+    HashSet allergens, 
+    HashSet ingredients, 
+    (HashSet ingredients, HashSet allergens)[] mapping);
+
+[ProblemName("Allergen Assessment")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var problem = Parse(input);
+        var suspiciousIngredients = GetIngredientsByAllergene(problem).SelectMany(kvp => kvp.Value).ToHashSet();
+        return problem.mapping
+            .Select(entry => entry.ingredients.Count(ingredient => !suspiciousIngredients.Contains(ingredient)))
+            .Sum();
+    }
+
+    public object PartTwo(string input) {
+        var problem = Parse(input);
+        var ingredientsByAllergene = GetIngredientsByAllergene(problem);
+        
+        // The problem is set up in a way that we can identify the allergene - ingredient pairs one by one. 
+        while (ingredientsByAllergene.Values.Any(ingredients => ingredients.Count > 1)) {
+            foreach (var allergen in problem.allergens) {
+                var candidates = ingredientsByAllergene[allergen];
+                if (candidates.Count == 1) {
+                    foreach (var allergenT in problem.allergens) {
+                        if (allergen != allergenT) {
+                            ingredientsByAllergene[allergenT].Remove(candidates.Single());
+                        }
+                    }
+                }
+            }
+        }
+
+        return string.Join(",", problem.allergens.OrderBy(a => a).Select(a => ingredientsByAllergene[a].Single()));
+    }
+
+    private Problem Parse(string input) {
+        var mapping = (
+            from line in input.Split("\n")
+                let parts = line.Trim(')').Split(" (contains ")
+                let ingredients = parts[0].Split(" ").ToHashSet()
+                let allergens = parts[1].Split(", ").ToHashSet()
+            select (ingredients, allergens)
+        ).ToArray();
+
+        return new Problem(
+            mapping.SelectMany(entry => entry.allergens).ToHashSet(),
+            mapping.SelectMany(entry => entry.ingredients).ToHashSet(),
+            mapping
+        );
+    }
+
+    private Dictionary> GetIngredientsByAllergene(Problem problem) =>
+        problem.allergens.ToDictionary(
+            allergene => allergene, 
+            allergene => problem.mapping
+                .Where(entry => entry.allergens.Contains(allergene))
+                .Aggregate(
+                    problem.ingredients as IEnumerable,
+                    (res, entry) => res.Intersect(entry.ingredients))
+                .ToHashSet());
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/22/illustration.jpeg b/2020/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/22/illustration.jpeg differ diff --git a/2020/22/index.html b/2020/22/index.html new file mode 100644 index 00000000..b94bac18 --- /dev/null +++ b/2020/22/index.html @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/22 'Crab Combat'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/22

+

Crab Combat

+

in C#

+

+

by encse

+
+ +
+ +
+

It only takes a few hours of sailing the ocean on a raft for boredom to sink in. Fortunately, you brought a small deck of space cards! You'd like to play a game of Combat, and there's even an opponent available: a small crab that climbed aboard your raft before you left.

+

Fortunately, it doesn't take long to teach the crab the rules.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day22;
+
+[ProblemName("Crab Combat")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var (deck1, deck2) = Parse(input);
+        while (deck1.Any() && deck2.Any()) {
+
+            var (card1, card2) = (deck1.Dequeue(), deck2.Dequeue());
+
+            bool player1Wins = card1 > card2;
+
+            if (player1Wins) {
+                deck1.Enqueue(card1);
+                deck1.Enqueue(card2);
+            } else {
+                deck2.Enqueue(card2);
+                deck2.Enqueue(card1);
+            }
+        }
+        return Answer(deck1, deck2);
+    }
+
+    public object PartTwo(string input) {
+
+        var (deck1, deck2) = Parse(input);
+
+        bool Game(Queue deck1, Queue deck2) {
+            var seen = new HashSet();
+
+            while (deck1.Any() && deck2.Any()) {
+                var hash = string.Join(",", deck1) + ";" + string.Join(",", deck2);
+                if (seen.Contains(hash)) {
+                    return true; // player 1 wins;
+                }
+                seen.Add(hash);
+
+                var (card1, card2) = (deck1.Dequeue(), deck2.Dequeue());
+
+                bool player1Wins;
+                if (deck1.Count >= card1 && deck2.Count >= card2) {
+                    player1Wins = Game(new Queue(deck1.Take(card1)), new Queue(deck2.Take(card2)));
+                } else {
+                    player1Wins = card1 > card2;
+                }
+
+                if (player1Wins) {
+                    deck1.Enqueue(card1);
+                    deck1.Enqueue(card2);
+                } else {
+                    deck2.Enqueue(card2);
+                    deck2.Enqueue(card1);
+                }
+            }
+            return deck1.Any(); // player1 wins?
+        }
+
+        Game(deck1, deck2);
+
+        return Answer(deck1, deck2);
+    }
+
+    int Answer(Queue deck1, Queue deck2) => 
+        deck1.Concat(deck2).Reverse().Select((c, i) => c * (i + 1)).Sum();
+
+    (Queue deck1, Queue deck2) Parse(string input) {
+
+        var decks = input.Split("\n\n");
+        return (
+            new Queue(decks[0].Split("\n").Skip(1).Select(int.Parse)),
+            new Queue(decks[1].Split("\n").Skip(1).Select(int.Parse))
+        );
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/23/illustration.jpeg b/2020/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/23/illustration.jpeg differ diff --git a/2020/23/index.html b/2020/23/index.html new file mode 100644 index 00000000..2e67acd5 --- /dev/null +++ b/2020/23/index.html @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/23 'Crab Cups'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/23

+

Crab Cups

+

in C#

+

+

by encse

+
+ +
+ +
+

The small crab challenges you to a game! The crab is going to mix up some cups, and you have to predict where they'll end up.

+

The cups will be arranged in a circle and labeled clockwise (your puzzle input). For example, if your labeling were 32415, there would be five cups in the circle; going clockwise around the circle from the first cup, the cups would be labeled 3, 2, 4, 1, 5, and then back to 3 again.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day23;
+
+[ProblemName("Crab Cups")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        string.Join("", Solve(input, 9, 100).Take(8));
+
+    public object PartTwo(string input) {
+        var labels = Solve(input, 1000000, 10000000).Take(2).ToArray();
+        return labels[0] * labels[1];
+    }
+
+    private IEnumerable Solve(string input, int maxLabel, int rotate) {
+        var digits = input.Select(d => int.Parse(d.ToString())).ToArray();
+
+        // A compact linked list representation. The cup's label can be used as the index into the array. 
+        int[] next = Enumerable.Range(1, maxLabel + 1).ToArray();
+        next[0] = -1; // not used
+
+        for (var i = 0; i < digits.Length; i++) {
+            next[digits[i]] = digits[(i + 1) % digits.Length];
+        }
+
+        if (maxLabel > input.Length) {
+            next[maxLabel] = next[digits.Last()];
+            next[digits.Last()] = input.Length + 1;
+        }
+
+        var current = digits.First();
+
+        for (var i = 0; i < rotate; i++) {
+            var removed1 = next[current];
+            var removed2 = next[removed1];
+            var removed3 = next[removed2];
+            next[current] = next[removed3];
+
+            // omg
+            var destination = current;
+            do destination = destination == 1 ? maxLabel : destination - 1;
+            while (destination == removed1 || destination == removed2 || destination == removed3);
+
+            next[removed3] = next[destination];
+            next[destination] = removed1;
+            current = next[current];
+        }
+
+        // return the labels starting from the first cup.
+        var cup = next[1];
+        while (true) {
+            yield return cup;
+            cup = next[cup];
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/24/illustration.jpeg b/2020/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/24/illustration.jpeg differ diff --git a/2020/24/index.html b/2020/24/index.html new file mode 100644 index 00000000..77852b1d --- /dev/null +++ b/2020/24/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/24 'Lobby Layout'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/24

+

Lobby Layout

+

in C#

+

+

by encse

+
+ +
+ +
+

Your raft makes it to the tropical island; it turns out that the small crab was an excellent navigator. You make your way to the resort.

+

As you enter the lobby, you discover a small problem: the floor is being renovated. You can't even reach the check-in desk until they've finished installing the new tile floor.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day24;
+
+record Tile(int x, int y);
+
+[ProblemName("Lobby Layout")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ParseBlackTiles(input).Count();
+
+    public object PartTwo(string input) =>
+        Enumerable.Range(0, 100)
+            .Aggregate(ParseBlackTiles(input), (blackTiles, _) => Flip(blackTiles))
+            .Count();
+
+    Dictionary HexDirections = new Dictionary {
+        {"o",  ( 0,  0)},
+        {"ne", ( 1,  1)},
+        {"nw", (-1,  1)},
+        {"e",  ( 2,  0)},
+        {"w",  (-2,  0)},
+        {"se", ( 1, -1)},
+        {"sw", (-1, -1)},
+    };
+
+    IEnumerable Neighbourhood(Tile tile) =>
+        from dir in HexDirections.Values select new Tile(tile.x + dir.x, tile.y + dir.y);
+
+    HashSet Flip(HashSet blackTiles) {
+        var tiles = (
+            from black in blackTiles
+            from tile in Neighbourhood(black)
+            select tile
+        ).ToHashSet();
+
+        return (
+            from tile in tiles
+            let blacks = Neighbourhood(tile).Count(n => blackTiles.Contains(n))
+            where blacks == 2 || blacks == 3 && blackTiles.Contains(tile)
+            select tile
+        ).ToHashSet();
+    }
+
+    HashSet ParseBlackTiles(string input) {
+        var tiles = new Dictionary();
+
+        foreach (var line in input.Split("\n")) {
+            var tile = Walk(line);
+            tiles[tile] = !tiles.GetValueOrDefault(tile);
+        }
+
+        return (from kvp in tiles where kvp.Value select kvp.Key).ToHashSet();
+    }
+
+    Tile Walk(string line) {
+        var (x, y) = (0, 0);
+        while (line != "") {
+            foreach (var kvp in HexDirections) {
+                if (line.StartsWith(kvp.Key)) {
+                    line = line.Substring(kvp.Key.Length);
+                    (x, y) = (x + kvp.Value.x, y + kvp.Value.y);
+                }
+            }
+        }
+        return new Tile(x, y);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/25/illustration.jpeg b/2020/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/25/illustration.jpeg differ diff --git a/2020/25/index.html b/2020/25/index.html new file mode 100644 index 00000000..0ce09302 --- /dev/null +++ b/2020/25/index.html @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/25 'Combo Breaker'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/25

+

Combo Breaker

+

in C#

+

+

by encse

+
+ +
+ +
+

You finally reach the check-in desk. Unfortunately, their registration systems are currently offline, and they cannot check you in. Noticing the look on your face, they quickly add that tech support is already on the way! They even created all the room keys this morning; you can take yours now and give them your room deposit once the registration system comes back online.

+

The room key is a small RFID card. Your room is on the 25th floor and the elevators are also temporarily out of service, so it takes what little energy you have left to even climb the stairs and navigate the halls. You finally reach the door to your room, swipe your card, and - beep - the light turns red.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2020.Day25;
+
+[ProblemName("Combo Breaker")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        // https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange
+        var numbers = input.Split("\n").Select(int.Parse).ToArray();
+        var mod = 20201227;
+        var pow = 0;
+        var subj = 7L;
+        var num = subj;
+        while (num != numbers[0] && num != numbers[1]) {
+            num = (num * subj) % mod;
+            pow++;
+        }
+
+        subj = num == numbers[0] ? numbers[1] : numbers[0];
+        num = subj;
+        while (pow > 0) {
+            num = (num * subj) % mod;
+            pow--;
+        }
+        return num;
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/3/illustration.jpeg b/2020/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/3/illustration.jpeg differ diff --git a/2020/3/index.html b/2020/3/index.html new file mode 100644 index 00000000..c58bd5ec --- /dev/null +++ b/2020/3/index.html @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/3 'Toboggan Trajectory'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/3

+

Toboggan Trajectory

+

in C#

+

+

by encse

+
+ +
+ +
+

With the toboggan login problems resolved, you set off toward the airport. While travel by toboggan might be easy, it's certainly not safe: there's very minimal steering and the area is covered in trees. You'll need to see which angles will take you near the fewest trees.

+

Due to the local geology, trees in this area only grow on exact integer coordinates in a grid. You make a map (your puzzle input) of the open squares (.) and trees (#) you can see. For example:

+

Read the full puzzle.

+
+
namespace AdventOfCode.Y2020.Day03;
+
+[ProblemName("Toboggan Trajectory")]
+class Solution : Solver {
+
+    public object PartOne(string input) => TreeCount(input, (1, 3));
+    public object PartTwo(string input) => TreeCount(input, (1, 1), (1, 3), (1, 5), (1, 7), (2, 1));
+
+    long TreeCount(string input, params (int drow, int dcol)[] slopes) {
+        var lines = input.Split("\n");
+        var (crow, ccol) = (lines.Length, lines[0].Length);
+        var mul = 1L;
+
+        foreach (var (drow, dcol) in slopes) {
+            var (irow, icol) = (drow, dcol);
+            var trees = 0;
+            while (irow < crow) {
+                if (lines[irow][icol % ccol] == '#') {
+                    trees++;
+                }
+                (irow, icol) = (irow + drow, icol + dcol);
+            }
+            mul *= trees;
+        }
+        return mul;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/4/illustration.jpeg b/2020/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/4/illustration.jpeg differ diff --git a/2020/4/index.html b/2020/4/index.html new file mode 100644 index 00000000..20ea6b11 --- /dev/null +++ b/2020/4/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/4 'Passport Processing'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/4

+

Passport Processing

+

in C#

+

+

by encse

+
+ +
+ +
+

You arrive at the airport only to realize that you grabbed your North Pole Credentials instead of your passport. While these documents are extremely similar, North Pole Credentials aren't issued by a country and therefore aren't actually valid documentation for travel in most of the world.

+

It seems like you're not the only one having problems, though; a very long line has formed for the automatic passport scanners, and the delay could upset your travel itinerary.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2020.Day04;
+
+[ProblemName("Passport Processing")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ValidCount(input, cred => 
+        rxs.All(kvp => cred.ContainsKey(kvp.Key))
+    );
+    
+    public object PartTwo(string input) => ValidCount(input, cred => 
+        rxs.All(kvp =>
+            cred.TryGetValue(kvp.Key, out var value) && Regex.IsMatch(value, "^(" + kvp.Value + ")$")
+        )
+    );
+
+    Dictionary rxs = new Dictionary(){
+        {"byr", "19[2-9][0-9]|200[0-2]"},
+        {"iyr", "201[0-9]|2020"},
+        {"eyr", "202[0-9]|2030"},
+        {"hgt", "1[5-8][0-9]cm|19[0-3]cm|59in|6[0-9]in|7[0-6]in"},
+        {"hcl", "#[0-9a-f]{6}"},
+        {"ecl", "amb|blu|brn|gry|grn|hzl|oth"},
+        {"pid", "[0-9]{9}"},
+    };
+
+    int ValidCount(string input, Func, bool> isValid) =>
+        input
+            .Split("\n\n")
+            .Select(block => block
+                .Split("\n ".ToCharArray())
+                .Select(part => part.Split(":"))
+                .ToDictionary(parts => parts[0], parts => parts[1]))
+            .Count(isValid);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/5/illustration.jpeg b/2020/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/5/illustration.jpeg differ diff --git a/2020/5/index.html b/2020/5/index.html new file mode 100644 index 00000000..970fb631 --- /dev/null +++ b/2020/5/index.html @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/5 'Binary Boarding'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/5

+

Binary Boarding

+

in C#

+

+

by encse

+
+ +
+ +
+

You board your plane only to discover a new problem: you dropped your boarding pass! You aren't sure which seat is yours, and all of the flight attendants are busy with the flood of people that suddenly made it through passport control.

+

You write a quick program to use your phone's camera to scan all of the nearby boarding passes (your puzzle input); perhaps you can find your seat through process of elimination.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day05;
+
+[ProblemName("Binary Boarding")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Seats(input).Max();
+
+    public object PartTwo(string input) {
+        var seats = Seats(input);
+        var (min, max) = (seats.Min(), seats.Max());
+        return Enumerable.Range(min, max - min + 1).Single(id => !seats.Contains(id));
+    }
+
+    HashSet Seats(string input) =>
+        input
+            .Replace("B", "1")
+            .Replace("F", "0")
+            .Replace("R", "1")
+            .Replace("L", "0")
+            .Split("\n")
+            .Select(row => Convert.ToInt32(row, 2))
+            .ToHashSet();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/6/illustration.jpeg b/2020/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/6/illustration.jpeg differ diff --git a/2020/6/index.html b/2020/6/index.html new file mode 100644 index 00000000..97408339 --- /dev/null +++ b/2020/6/index.html @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/6 'Custom Customs'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/6

+

Custom Customs

+

in C#

+

+

by encse

+
+ +
+ +
+

As your flight approaches the regional airport where you'll switch to a much larger plane, customs declaration forms are distributed to the passengers.

+

The form asks a series of 26 yes-or-no questions marked a through z. All you need to do is identify the questions for which anyone in your group answers "yes". Since your group is just you, this doesn't take very long.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day06;
+
+[ProblemName("Custom Customs")]      
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, (a,b) => a.Union(b));
+    public object PartTwo(string input) => Solve(input, (a,b) => a.Intersect(b));
+
+    int Solve(string input, Func, ImmutableHashSet, ImmutableHashSet> combine) {
+        return (
+            from grp in input.Split("\n\n")
+            let answers = from line in grp.Split("\n") select line.ToImmutableHashSet()
+            select answers.Aggregate(combine).Count
+        ).Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/7/illustration.jpeg b/2020/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/7/illustration.jpeg differ diff --git a/2020/7/index.html b/2020/7/index.html new file mode 100644 index 00000000..4f7ba8db --- /dev/null +++ b/2020/7/index.html @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/7 'Handy Haversacks'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/7

+

Handy Haversacks

+

in C#

+

+

by encse

+
+ +
+ +
+

You land at the regional airport in time for your next flight. In fact, it looks like you'll even have time to grab some food: all flights are currently delayed due to issues in luggage processing.

+

Due to recent aviation regulations, many rules (your puzzle input) are being enforced about bags and their contents; bags must be color-coded and must contain specific quantities of other color-coded bags. Apparently, nobody responsible for these regulations considered how long they would take to enforce!

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2020.Day07;
+
+[ProblemName("Handy Haversacks")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var parentsOf = new Dictionary>();
+        foreach (var line in input.Split("\n")) {
+            var descr = ParseLine(line);
+
+            foreach (var (_, bag) in descr.children) {
+                if (!parentsOf.ContainsKey(bag)) {
+                    parentsOf[bag] = new HashSet();
+                }
+                parentsOf[bag].Add(descr.bag);
+            }
+        }
+
+        IEnumerable PathsToRoot(string bag) {
+            yield return bag;
+
+            if (parentsOf.ContainsKey(bag)) {
+                foreach (var container in parentsOf[bag]) {
+                    foreach (var bagT in PathsToRoot(container)) {
+                        yield return bagT;
+                    }
+                }
+            }
+        }
+
+        return PathsToRoot("shiny gold bag").ToHashSet().Count - 1;
+    }
+
+    public object PartTwo(string input) {
+        var childrenOf = new Dictionary>();
+        foreach (var line in input.Split("\n")) {
+            var descr = ParseLine(line);
+            childrenOf[descr.bag] = descr.children;
+        }
+
+        long CountWithChildren(string bag) =>
+            1 + (from child in childrenOf[bag] select child.count * CountWithChildren(child.bag)).Sum();
+
+        return CountWithChildren("shiny gold bag") - 1;
+    }
+
+    (string bag, List<(int count, string bag)> children) ParseLine(string line){
+        var bag = Regex.Match(line, "^[a-z]+ [a-z]+ bag").Value;
+
+        var children =
+            Regex
+                .Matches(line, "(\\d+) ([a-z]+ [a-z]+ bag)")
+                .Select(x => (count: int.Parse(x.Groups[1].Value), bag: x.Groups[2].Value))
+                .ToList();
+        
+        return (bag, children);
+    }
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/8/illustration.jpeg b/2020/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/8/illustration.jpeg differ diff --git a/2020/8/index.html b/2020/8/index.html new file mode 100644 index 00000000..f11e2a91 --- /dev/null +++ b/2020/8/index.html @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/8 'Handheld Halting'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/8

+

Handheld Halting

+

in C#

+

+

by encse

+
+ +
+ +
+

Your flight to the major airline hub reaches cruising altitude without incident. While you consider checking the in-flight menu for one of those drinks that come with a little umbrella, you are interrupted by the kid sitting next to you.

+

Their handheld game console won't turn on! They ask if you can take a look.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day08;
+
+record Stm(string op, int arg);
+
+[ProblemName("Handheld Halting")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Run(Parse(input)).acc;
+
+    public object PartTwo(string input) =>
+        Patches(Parse(input))
+            .Select(Run)
+            .First(res => res.terminated).acc;
+
+    Stm[] Parse(string input) =>
+        input.Split("\n")
+            .Select(line => line.Split(" "))
+            .Select(parts => new Stm(parts[0], int.Parse(parts[1])))
+            .ToArray();
+
+    IEnumerable Patches(Stm[] program) =>
+        Enumerable.Range(0, program.Length)
+            .Where(line => program[line].op != "acc")
+            .Select(lineToPatch =>
+                program.Select((stm, line) =>
+                    line != lineToPatch ? stm :
+                    stm.op == "jmp" ? stm with { op = "nop" } :
+                    stm.op == "nop" ? stm with { op = "jmp" } :
+                    throw new Exception()
+                ).ToArray()
+            );
+
+    (int acc, bool terminated) Run(Stm[] program) {
+        var (ip, acc, seen) = (0, 0, new HashSet());
+
+        while (true) {
+            if (ip >= program.Length) {
+                return (acc, true);
+            } else if (seen.Contains(ip)) {
+                return (acc, false);
+            } else {
+                seen.Add(ip);
+                var stm = program[ip];
+                switch (stm.op) {
+                    case "nop": ip++; break;
+                    case "acc": ip++; acc += stm.arg; break;
+                    case "jmp": ip += stm.arg; break;
+                };
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2020/9/illustration.jpeg b/2020/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2020/9/illustration.jpeg differ diff --git a/2020/9/index.html b/2020/9/index.html new file mode 100644 index 00000000..dc6ad166 --- /dev/null +++ b/2020/9/index.html @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2020/9 'Encoding Error'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2020/9

+

Encoding Error

+

in C#

+

+

by encse

+
+ +
+ +
+

With your neighbor happily enjoying their video game, you turn your attention to an open data port on the little screen in the seat in front of you.

+

Though the port is non-standard, you manage to connect it to your computer through the clever use of several paperclips. Upon connection, the port outputs a series of numbers (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2020.Day09;
+
+[ProblemName("Encoding Error")]
+class Solution : Solver {
+
+    IEnumerable Range(int min, int lim) => Enumerable.Range(min, lim - min);
+
+    public object PartOne(string input) {
+        var numbers = input.Split("\n").Select(long.Parse).ToArray();
+
+        bool Mismatch(int i) => (
+            from j in Range(i - 25, i)
+            from k in Range(j + 1, i)
+            select numbers[j] + numbers[k]
+        ).All(sum => sum != numbers[i]);
+
+        return numbers[Range(25, input.Length).First(Mismatch)];
+    }
+
+    public object PartTwo(string input) {
+        var d = (long)PartOne(input);
+        var lines = input.Split("\n").Select(long.Parse).ToList();
+
+        foreach (var j in Range(0, lines.Count)) {
+            var s = lines[j];
+            foreach (var k in Range(j + 1, lines.Count)) {
+                s += lines[k];
+                if (s > d) {
+                    break;
+                } else if (s == d) {
+                    var range = lines.GetRange(j, k - j + 1);
+                    return range.Min() + range.Max();
+                }
+            }
+        }
+        throw new Exception();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/1/illustration.jpeg b/2021/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/1/illustration.jpeg differ diff --git a/2021/1/index.html b/2021/1/index.html new file mode 100644 index 00000000..3eb3ea19 --- /dev/null +++ b/2021/1/index.html @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/1 'Sonar Sweep'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/1

+

Sonar Sweep

+

in C#

+

+

by encse

+
+ +
+ +
+

You're minding your own business on a ship at sea when the overboard alarm goes off! You rush to see if you can help. Apparently, one of the Elves tripped and accidentally sent the sleigh keys flying into the ocean!

+

Before you know it, you're inside a submarine the Elves keep ready for situations like this. It's covered in Christmas lights (because of course it is), and it even has an experimental antenna that should be able to track the keys if you can boost its signal strength high enough; there's a little meter that indicates the antenna's signal strength by displaying 0-50 stars.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day01;
+
+[ProblemName("Sonar Sweep")]
+class Solution : Solver {
+
+    public object PartOne(string input) => DepthIncrease(Numbers(input));
+
+    public object PartTwo(string input) => DepthIncrease(ThreeMeasurements(Numbers(input)));
+
+    int DepthIncrease(IEnumerable ns) => (
+        from p in Enumerable.Zip(ns, ns.Skip(1)) 
+        where p.First < p.Second 
+        select 1
+    ).Count();
+
+    // the sum of elements in a sliding window of 3
+    IEnumerable ThreeMeasurements(IEnumerable ns) => 
+        from t in Enumerable.Zip(ns, ns.Skip(1), ns.Skip(2)) // ⭐ .Net 6 comes with three way zip
+        select t.First + t.Second + t.Third;
+
+    // parse input to array of numbers
+    IEnumerable Numbers(string input) => 
+        from n in input.Split('\n') 
+        select int.Parse(n);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/10/illustration.jpeg b/2021/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/10/illustration.jpeg differ diff --git a/2021/10/index.html b/2021/10/index.html new file mode 100644 index 00000000..16befdb9 --- /dev/null +++ b/2021/10/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/10 'Syntax Scoring'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/10

+

Syntax Scoring

+

in C#

+

+

by encse

+
+ +
+ +
+

You ask the submarine to determine the best route out of the deep-sea cave, but it only replies:

+
+Syntax error in navigation subsystem on line: all of them
+
+ +

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day10;
+
+[ProblemName("Syntax Scoring")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetScores(input, getSyntaxErrorScore: true).Sum();
+    public object PartTwo(string input) => Median(GetScores(input, getSyntaxErrorScore: false));
+
+    public long Median(IEnumerable items) =>
+        items.OrderBy(x => x).ElementAt(items.Count() / 2);
+
+    IEnumerable GetScores(string input, bool getSyntaxErrorScore) =>
+        input.Split("\n").Select(line => GetScore(line, getSyntaxErrorScore)).Where(score => score > 0);
+
+    long GetScore(string line, bool getSyntaxErrorScore) {
+        // standard stack based approach
+        var stack = new Stack();
+
+        foreach (var ch in line) {
+            switch ((stack.FirstOrDefault(), ch)) {
+                // matching closing parenthesis:
+                case ('(', ')'): stack.Pop(); break;
+                case ('[', ']'): stack.Pop(); break;
+                case ('{', '}'): stack.Pop(); break;
+                case ('<', '>'): stack.Pop(); break;
+                // return early if syntax error found:
+                case (_, ')'): return getSyntaxErrorScore ? 3     : 0;
+                case (_, ']'): return getSyntaxErrorScore ? 57    : 0;
+                case (_, '}'): return getSyntaxErrorScore ? 1197  : 0;
+                case (_, '>'): return getSyntaxErrorScore ? 25137 : 0;
+                // otherwise, it's an opening parenthesis:
+                case (_, _): stack.Push(ch); break;
+            }
+        }
+
+        if (getSyntaxErrorScore) {
+            return 0;
+        } else {
+            return stack
+                .Select(item => 1 + "([{<".IndexOf(item)) // convert chars to digits
+                .Aggregate(0L, (acc, item) => acc * 5 + item); // get base 5 number
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/11/illustration.jpeg b/2021/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/11/illustration.jpeg differ diff --git a/2021/11/index.html b/2021/11/index.html new file mode 100644 index 00000000..6dc32507 --- /dev/null +++ b/2021/11/index.html @@ -0,0 +1,349 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/11 'Dumbo Octopus'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/11

+

Dumbo Octopus

+

in C#

+

+

by encse

+
+ +
+ +
+

You enter a large cavern full of rare bioluminescent dumbo octopuses! They seem to not like the Christmas lights on your submarine, so you turn them off for now.

+

There are 100 octopuses arranged neatly in a 10 by 10 grid. Each octopus slowly gains energy over time and flashes brightly for a moment when its energy is full. Although your lights are off, maybe you could navigate through the cave without disturbing the octopuses if you could predict when the flashes of light will happen.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day11;
+
+[ProblemName("Dumbo Octopus")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Simulate(input).Take(100).Sum();
+    public object PartTwo(string input) => Simulate(input).TakeWhile(flash => flash != 100).Count() + 1;
+
+    // run the simulation in an endless loop, yield flash counts in each step
+    IEnumerable Simulate(string input) {
+
+        var map = GetMap(input);
+
+        while (true) {
+
+            var queue = new Queue();
+            var flashed = new HashSet();
+
+            // increase the energy level of each octopus:
+            foreach (var key in map.Keys) {
+                map[key]++;
+                if (map[key] == 10) {
+                    queue.Enqueue(key);
+                }
+            }
+
+            // those that reach level 10 should flash, use a queue so that flashing can trigger others
+            while (queue.Any()) {
+                var pos = queue.Dequeue();
+                flashed.Add(pos);
+                foreach (var n in Neighbours(pos).Where(x => map.ContainsKey(x))) {
+                    map[n]++;
+                    if (map[n] == 10) {
+                        queue.Enqueue(n);
+                    }
+                }
+            }
+
+            // reset energy level of flashed octopuses
+            foreach (var pos in flashed) {
+                map[pos] = 0;
+            }
+
+            yield return flashed.Count;
+        }
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area using ContainsKey
+    Dictionary GetMap(string input) {
+        var map = input.Split("\n");
+        return new Dictionary(
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(new Pos(x, y), map[y][x] - '0')
+        );
+    }
+
+    IEnumerable Neighbours(Pos pos) =>
+        from dx in new int[] { -1, 0, 1 }
+        from dy in new int[] { -1, 0, 1 }
+        where dx != 0 || dy != 0
+        select new Pos(pos.x + dx, pos.y + dy);
+
+}
+record Pos(int x, int y);
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/12/illustration.jpeg b/2021/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/12/illustration.jpeg differ diff --git a/2021/12/index.html b/2021/12/index.html new file mode 100644 index 00000000..19cf17ff --- /dev/null +++ b/2021/12/index.html @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/12 'Passage Pathing'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/12

+

Passage Pathing

+

in C#

+

+

by encse

+
+ +
+ +
+

With your submarine's subterranean subsystems subsisting suboptimally, the only way you're getting out of this cave anytime soon is by finding a path yourself. Not just a path - the only way to know if you've found the best path is to find all of them.

+

Fortunately, the sensors are still mostly working, and so you build a rough map of the remaining caves (your puzzle input). For example:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day12;
+
+[ProblemName("Passage Pathing")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Explore(input, false);
+    public object PartTwo(string input) => Explore(input, true);
+
+    int Explore(string input, bool part2) {
+        var map = GetMap(input);
+
+        // Recursive approach this time.
+        int pathCount(string currentCave, ImmutableHashSet visitedCaves, bool anySmallCaveWasVisitedTwice) {
+
+            if (currentCave == "end") {
+                return 1;
+            }
+
+            var res = 0;
+            foreach (var cave in map[currentCave]) {
+                var isBigCave = cave.ToUpper() == cave;
+                var seen = visitedCaves.Contains(cave);
+
+                if (!seen || isBigCave) {
+                    // we can visit big caves any number of times, small caves only once
+                    res += pathCount(cave, visitedCaves.Add(cave), anySmallCaveWasVisitedTwice);
+                } else if (part2 && !isBigCave && cave != "start" && !anySmallCaveWasVisitedTwice) {
+                    // part 2 also lets us to visit a single small cave twice (except for start and end)
+                    res += pathCount(cave, visitedCaves, true);
+                }
+            }
+            return res;
+        }
+
+        return pathCount("start", ImmutableHashSet.Create("start"), false);
+    }
+
+    Dictionary GetMap(string input) {
+        // taking all connections 'there and back':
+        var connections =
+            from line in input.Split("\n")
+            let parts = line.Split("-")
+            let caveA = parts[0]
+            let caveB = parts[1]
+            from connection in new[] { (From: caveA, To: caveB), (From: caveB, To: caveA) }
+            select connection;
+
+        // grouped by "from":
+        return (
+            from p in connections
+            group p by p.From into g
+            select g
+        ).ToDictionary(g => g.Key, g => g.Select(connnection => connnection.To).ToArray());
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/13/illustration.jpeg b/2021/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/13/illustration.jpeg differ diff --git a/2021/13/index.html b/2021/13/index.html new file mode 100644 index 00000000..a379503b --- /dev/null +++ b/2021/13/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/13 'Transparent Origami'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/13

+

Transparent Origami

+

in C#

+

+

by encse

+
+ +
+ +
+

You reach another volcanically active part of the cave. It would be nice if you could do some kind of thermal imaging so you could tell ahead of time which caves are too hot to safely enter.

+

Fortunately, the submarine seems to be equipped with a thermal camera! When you activate it, you are greeted with:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day13;
+
+[ProblemName("Transparent Origami")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetFolds(input).First().Count();
+    public object PartTwo(string input) => ToString(GetFolds(input).Last()).Ocr();
+
+    IEnumerable> GetFolds(string input) {
+        var blocks = input.Split("\n\n");
+        // parse points into a hashset
+        var points = (
+            from line in blocks[0].Split("\n")
+            let coords = line.Split(",")
+            select new Point(int.Parse(coords[0]), int.Parse(coords[1]))
+        ).ToHashSet();
+
+        // fold line by line, yielding a new hashset
+        foreach (var line in blocks[1].Split("\n")) {
+            var rule = line.Split("=");
+            if (rule[0].EndsWith("x")) {
+                points = FoldX(int.Parse(rule[1]), points);
+            } else {
+                points = FoldY(int.Parse(rule[1]), points);
+            }
+            yield return points;
+        }
+    }
+
+    string ToString(HashSet d) {
+        var res = "";
+        var height = d.MaxBy(p=>p.y).y;
+        var width = d.MaxBy(p=>p.x).x;
+        for (var y = 0; y <= height; y++) {
+            for (var x = 0; x <= width; x++) {
+                res += d.Contains(new Point(x, y)) ? '#' : ' ';
+            }
+            res += "\n";
+        }
+        return res;
+    }
+
+    HashSet FoldX(int x, HashSet d) =>
+        d.Select(p => p.x > x ? p with { x = 2 * x - p.x } : p).ToHashSet();
+
+    HashSet FoldY(int y, HashSet d) =>
+        d.Select(p => p.y > y ? p with { y = 2 * y - p.y } : p).ToHashSet();
+
+}
+
+record Point(int x, int y);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/14/illustration.jpeg b/2021/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/14/illustration.jpeg differ diff --git a/2021/14/index.html b/2021/14/index.html new file mode 100644 index 00000000..e155c91e --- /dev/null +++ b/2021/14/index.html @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/14 'Extended Polymerization'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/14

+

Extended Polymerization

+

in C#

+

+

by encse

+
+ +
+ +
+

The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has polymerization equipment that would produce suitable materials to reinforce the submarine, and the nearby volcanically-active caves should even have the necessary input elements in sufficient quantities.

+

The submarine manual contains instructions for finding the optimal polymer formula; specifically, it offers a polymer template and a list of pair insertion rules (your puzzle input). You just need to work out what polymer would result after repeating the pair insertion process a few times.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2021.Day14;
+
+[ProblemName("Extended Polymerization")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 10);
+    public object PartTwo(string input) => Solve(input, 40);
+
+    long Solve(string input, int steps) {
+
+        var blocks = input.Split("\n\n");
+
+        // We will start with this polymer:
+        var polymer = blocks[0];
+
+        // These are the 'molecule -> new element' rules
+        var generatedElement = (
+            from line in blocks[1].Split("\n")
+            let parts = line.Split(" -> ")
+            select (molecule: parts[0], element: parts[1])
+        ).ToDictionary(p => p.molecule, p => p.element);
+
+        
+        //                        H H H H H           H
+        //                      H-C-C-C-C-C- ....... -C-H
+        //                        H H H H H           H
+
+        // It's enough to maintain the molecule counts, no need to deal with them individually.
+
+        // Cut the polymer into molecules first:
+        var moleculeCount = new Dictionary();
+        foreach (var i in Enumerable.Range(0, polymer.Length - 1)) {
+            var ab = polymer.Substring(i, 2);
+            moleculeCount[ab] = moleculeCount.GetValueOrDefault(ab) + 1;
+        }
+
+        // Update the map in a loop:
+        for (var i = 0; i < steps; i++) {
+            var updated = new Dictionary();
+            foreach (var (molecule, count) in moleculeCount) {
+                var (a, n, b) = (molecule[0], generatedElement[molecule], molecule[1]);
+                updated[$"{a}{n}"] = updated.GetValueOrDefault($"{a}{n}") + count;
+                updated[$"{n}{b}"] = updated.GetValueOrDefault($"{n}{b}") + count;
+            }
+            moleculeCount = updated;
+        }
+
+        //                        H H H H H           H
+        //                      H-C-C-C-C-C- ....... -C-H
+        //                        H H H H H           H
+
+        // To count the elements consider just one end of each molecule:
+        var elementCounts = new Dictionary();
+        foreach (var (molecule, count) in moleculeCount) {
+            var a = molecule[0];
+            elementCounts[a] = elementCounts.GetValueOrDefault(a) + count;
+        }
+
+        // The # of the closing element is off by one:
+        elementCounts[polymer.Last()]++;
+
+        return elementCounts.Values.Max() - elementCounts.Values.Min();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/15/illustration.jpeg b/2021/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/15/illustration.jpeg differ diff --git a/2021/15/index.html b/2021/15/index.html new file mode 100644 index 00000000..f61cb00f --- /dev/null +++ b/2021/15/index.html @@ -0,0 +1,375 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/15 'Chiton'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/15

+

Chiton

+

in C#

+

+

by encse

+
+ +
+ +
+

You've almost reached the exit of the cave, but the walls are getting closer together. Your submarine can barely still fit, though; the main problem is that the walls of the cave are covered in chitons, and it would be best not to bump any of them.

+

The cavern is large, but has a very low ceiling, restricting your motion to two dimensions. The shape of the cavern resembles a square; a quick scan of chiton density produces a map of risk level throughout the cave (your puzzle input). For example:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Collections.Immutable;
+
+namespace AdventOfCode.Y2021.Day15;
+
+[ProblemName("Chiton")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(GetRiskLevelMap(input));
+    public object PartTwo(string input) => Solve(ScaleUp(GetRiskLevelMap(input)));
+
+    int Solve(Dictionary riskMap) {
+        // Disjktra algorithm
+
+        var topLeft = new Point(0, 0);
+        var bottomRight = new Point(riskMap.Keys.MaxBy(p => p.x).x, riskMap.Keys.MaxBy(p => p.y).y);
+
+        // Visit points in order of cumulated risk
+        // ⭐ .Net 6 finally has a PriorityQueue collection :)
+        var q = new PriorityQueue();
+        var totalRiskMap = new Dictionary();
+
+        totalRiskMap[topLeft] = 0;
+        q.Enqueue(topLeft, 0);
+
+        // Go until we find the bottom right corner
+        while (true) {
+            var p = q.Dequeue();
+
+            if (p == bottomRight) {
+                break;
+            }
+
+            foreach (var n in Neighbours(p)) {
+                if (riskMap.ContainsKey(n)) {
+                    var totalRiskThroughP = totalRiskMap[p] + riskMap[n];
+                    if (totalRiskThroughP < totalRiskMap.GetValueOrDefault(n, int.MaxValue)) {
+                        totalRiskMap[n] = totalRiskThroughP;
+                        q.Enqueue(n, totalRiskThroughP);
+                    }
+                }
+            }
+        }
+
+        // return bottom right corner's total risk:
+        return totalRiskMap[bottomRight];
+    }
+
+    // Create an 5x scaled up map, as described in part 2
+    Dictionary ScaleUp(Dictionary map) {
+        var (ccol, crow) = (map.Keys.MaxBy(p => p.x).x + 1, map.Keys.MaxBy(p => p.y).y + 1);
+
+        var res = new Dictionary(
+            from y in Enumerable.Range(0, crow * 5)
+            from x in Enumerable.Range(0, ccol * 5)
+
+            // x, y and risk level in the original map:
+            let tileY = y % crow
+            let tileX = x % ccol
+            let tileRiskLevel = map[new Point(tileX, tileY)]
+
+            // risk level is increased by tile distance from origin:
+            let tileDistance = (y / crow) + (x / ccol)
+
+            // risk level wraps around from 9 to 1:
+            let riskLevel = (tileRiskLevel + tileDistance - 1) % 9 + 1
+            select new KeyValuePair(new Point(x, y), riskLevel)
+        );
+
+        return res;
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area
+    Dictionary GetRiskLevelMap(string input) {
+        var map = input.Split("\n");
+        return new Dictionary(
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(new Point(x, y), map[y][x] - '0')
+        );
+    }
+
+    IEnumerable Neighbours(Point point) =>
+        new[] {
+           point with {y = point.y + 1},
+           point with {y = point.y - 1},
+           point with {x = point.x + 1},
+           point with {x = point.x - 1},
+        };
+}
+
+record Point(int x, int y);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/16/illustration.jpeg b/2021/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/16/illustration.jpeg differ diff --git a/2021/16/index.html b/2021/16/index.html new file mode 100644 index 00000000..ee38d1c5 --- /dev/null +++ b/2021/16/index.html @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/16 'Packet Decoder'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/16

+

Packet Decoder

+

in C#

+

+

by encse

+
+ +
+ +
+

As you leave the cave and reach open waters, you receive a transmission from the Elves back on the ship.

+

The transmission was sent using the Buoyancy Interchange Transmission System (BITS), a method of packing numeric expressions into a binary sequence. Your submarine's computer has saved the transmission in hexadecimal (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day16;
+
+[ProblemName("Packet Decoder")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        GetTotalVersion(GetPacket(GetReader(input)));
+
+    public object PartTwo(string input) =>
+        Evaluate(GetPacket(GetReader(input)));
+
+    // recursively sum the versions of a packet and its content for part 1:
+    int GetTotalVersion(Packet packet) =>
+        packet.version + packet.packets.Select(GetTotalVersion).Sum();
+
+    // recursively evaluate the packet and its contents based on the type tag for part 2:
+    long Evaluate(Packet packet) {
+
+        var parts = packet.packets.Select(Evaluate).ToArray();
+        return packet.type switch {
+            0 => parts.Sum(),
+            1 => parts.Aggregate(1L, (acc, x) => acc * x),
+            2 => parts.Min(),
+            3 => parts.Max(),
+            4 => packet.payload, // <--- literal packet is handled uniformly
+            5 => parts[0] > parts[1] ? 1 : 0,
+            6 => parts[0] < parts[1] ? 1 : 0,
+            7 => parts[0] == parts[1] ? 1 : 0,
+            _ => throw new Exception()
+        };
+    }
+
+    // convert hex string to bit sequence reader
+    BitSequenceReader GetReader(string input) => new BitSequenceReader(
+        new BitArray((
+            from hexChar in input
+            // get the 4 bits out of a hex char:
+            let value = Convert.ToInt32(hexChar.ToString(), 16)
+            // convert to bitmask
+            from mask in new []{8,4,2,1}
+            select (mask & value) != 0
+        ).ToArray()
+    ));
+
+    // make sense of the bit sequence:
+    Packet GetPacket(BitSequenceReader reader) {
+        var version = reader.ReadInt(3);
+        var type = reader.ReadInt(3);
+        var packets = new List();
+        var payload = 0L;
+
+        if (type == 0x4) {
+            // literal, payload is encoded in the following bits in 5 bit long chunks:
+            while (true) {
+                var isLast = reader.ReadInt(1) == 0;
+                payload = payload * 16 + reader.ReadInt(4);
+                if (isLast) {
+                    break;
+                }
+            }
+        } else if (reader.ReadInt(1) == 0) {
+            // operator, the next 'length' long bit sequence encodes the sub packages:
+            var length = reader.ReadInt(15);
+            var subPackages = reader.GetBitSequenceReader(length);
+            while (subPackages.Any()) {
+                packets.Add(GetPacket(subPackages));
+            }
+        } else {
+            // operator with 'packetCount' sub packages:
+            var packetCount = reader.ReadInt(11);
+            packets.AddRange(from _ in Enumerable.Range(0, packetCount) select GetPacket(reader));
+        }
+
+        return new Packet(version, type, payload, packets.ToArray());
+    }
+}
+
+// Reader class with convenience methods to retrieve n-bit integers and subreaders as needed
+class BitSequenceReader {
+    private BitArray bits;
+    private int ptr;
+
+    public BitSequenceReader(BitArray bits) {
+        this.bits = bits;
+    }
+
+    public bool Any() {
+        return ptr < bits.Length;
+    }
+
+    public BitSequenceReader GetBitSequenceReader(int bitCount) {
+        var bitArray = new BitArray(bitCount);
+        for (var i = 0; i < bitCount; i++) {
+            bitArray.Set(i, bits[ptr++]);
+        }
+        return new BitSequenceReader(bitArray);
+    }
+
+    public int ReadInt(int bitCount) {
+        var res = 0;
+        for (var i = 0; i < bitCount; i++) {
+            res = res * 2 + (bits[ptr++] ? 1 : 0);
+        }
+        return res;
+    }
+}
+
+// Each packet has all fields, type tag tells how to interpret the contents
+record Packet(int version, int type, long payload, Packet[] packets);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/17/illustration.jpeg b/2021/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/17/illustration.jpeg differ diff --git a/2021/17/index.html b/2021/17/index.html new file mode 100644 index 00000000..442d9353 --- /dev/null +++ b/2021/17/index.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/17 'Trick Shot'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/17

+

Trick Shot

+

in C#

+

+

by encse

+
+ +
+ +
+

You finally decode the Elves' message. HI, the message says. You continue searching for the sleigh keys.

+

Ahead of you is what appears to be a large ocean trench. Could the keys have fallen into it? You'd better send a probe to investigate.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2021.Day17;
+
+[ProblemName("Trick Shot")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input).Max();
+    public object PartTwo(string input) => Solve(input).Count();
+
+    // For each vx0, vy0 combination that reaches the target, yield the highest y value of the trajectory:
+    IEnumerable Solve(string input) {
+        // Parse the (signed) integers
+        var m = Regex.Matches(input, "-?[0-9]+").Select(m => int.Parse(m.Value)).ToArray();
+
+        // Get the target rectangle
+        var (xMin, xMax) = (m[0], m[1]);
+        var (yMin, yMax) = (m[2], m[3]);
+
+        // Bounds for the initial horizontal and vertical speeds:
+        var vx0Min = 0;     // Because vx is non negative
+        var vx0Max = xMax;  // For bigger values we jump too much to the right in the first step
+        var vy0Min = yMin;  // For smaller values we jump too deep in the first step
+        var vy0Max = -yMin; // 🍎 Newton says that when the falling probe reaches y = 0, it's speed is -vy0.
+                            // In the next step we go down to -vy0, which should not be deeper than yMin.
+        
+        // Run the simulation in the given bounds, maintaining maxY
+        for (var vx0 = vx0Min; vx0 <= vx0Max; vx0++) {
+            for (var vy0 = vy0Min; vy0 <= vy0Max; vy0++) {
+
+                var (x, y, vx, vy) = (0, 0, vx0, vy0);
+                var maxY = 0;
+
+                // as long as there is any chance to reach the target rectangle:
+                while (x <= xMax && y >= yMin) {
+                   
+                    x += vx;
+                    y += vy;
+                    vy -= 1;
+                    vx = Math.Max(0, vx - 1);
+                    maxY = Math.Max(y, maxY);
+
+                    // if we are within target, yield maxY:
+                    if (x >= xMin && x <= xMax && y >= yMin && y <= yMax) {
+                        yield return maxY;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/18/illustration.jpeg b/2021/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/18/illustration.jpeg differ diff --git a/2021/18/index.html b/2021/18/index.html new file mode 100644 index 00000000..02c9978f --- /dev/null +++ b/2021/18/index.html @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/18 'Snailfish'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/18

+

Snailfish

+

in C#

+

+

by encse

+
+ +
+ +
+

You descend into the ocean trench and encounter some snailfish. They say they saw the sleigh keys! They'll even tell you which direction the keys went if you help one of the smaller snailfish with his math homework.

+

Snailfish numbers aren't like regular numbers. Instead, every snailfish number is a pair - an ordered list of two elements. Each element of the pair can be either a regular number or another pair.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day18;
+
+[ProblemName("Snailfish")]
+class Solution : Solver {
+
+    // WARNING: What follows is obscure nonsense.
+    //
+    //     .-""-.
+    //    /,..___\
+    //   () {_____}
+    //     (/-@-@-\)
+    //     {`-=^=-'}
+    //     {  `-'  } Max
+    //      {     }
+    //       `---'
+
+    public object PartOne(string input) {
+        // sum up all the 'numbers' in the input
+        return input.Split("\n").Select(ParseNumber).Aggregate(
+            new Number(),
+            (acc, number) => !acc.Any() ? number : Sum(acc, number),
+            Magnitude
+        );
+    }
+
+    public object PartTwo(string input) {
+        // get the highest magnitude resulted from adding any two 'numbers' in the input:
+        var numbers = input.Split("\n").Select(ParseNumber).ToArray();
+        return (
+            from i in Enumerable.Range(0, numbers.Length)
+            from j in Enumerable.Range(0, numbers.Length)
+            where i != j
+            select Magnitude(Sum(numbers[i], numbers[j]))
+        ).Max();
+    }
+
+    long Magnitude(Number number) {
+        var itoken = 0; // we will process the number tokenwise
+
+        long computeRecursive() {
+            var token = number[itoken++];
+            if (token.kind == TokenKind.Digit) {
+                // just the number
+                return token.value;
+            } else {
+                // take left and right side of the pair
+                var left = computeRecursive();
+                var right = computeRecursive();
+                itoken++; // don't forget to eat the closing parenthesis
+                return 3 * left + 2 * right;
+            }
+        }
+
+        return computeRecursive();
+    }
+
+
+    // just wrap A and B in a new 'number' and reduce:
+    Number Sum(Number numberA, Number numberB) => Reduce(Number.Pair(numberA, numberB));
+
+    Number Reduce(Number number) {
+        while (Explode(number) || Split(number)) {
+            ; // repeat until we cannot explod or split anymore
+        }
+        return number;
+    }
+
+    bool Explode(Number number) {
+        // exploding means we need to find the first pair in the number 
+        // that is embedded in 4 other pairs and get rid of it:
+        var depth = 0;
+        for (var i = 0; i < number.Count; i++) {
+            if (number[i].kind == TokenKind.Open) {
+                depth++;
+                if (depth == 5) {
+                    // we are deep enough, let's to the reduce part
+
+                    // find the digit to the left (if any) and increase:
+                    for (var j = i - 1; j >= 0; j--) {
+                        if (number[j].kind == TokenKind.Digit) {
+                            number[j] = number[j] with { value = number[j].value + number[i + 1].value };
+                            break;
+                        }
+                    }
+
+                    // find the digit to the right (if any) and increase:
+                    for (var j = i + 3; j < number.Count; j++) {
+                        if (number[j].kind == TokenKind.Digit) {
+                            number[j] = number[j] with { value = number[j].value + number[i + 2].value };
+                            break;
+                        }
+                    }
+
+                    // replace [a b] with 0:
+                    number.RemoveRange(i, 4);
+                    number.Insert(i, new Token(TokenKind.Digit, 0));
+
+                    // successful reduce:
+                    return true;
+                }
+            } else if (number[i].kind == TokenKind.Close) {
+                depth--;
+            }
+        }
+
+        // couldn't reduce:
+        return false;
+    }
+
+    bool Split(Number number) {
+
+        // spliting means we neeed to find a token with a high value and make a pair out of it:
+        for (var i = 0; i < number.Count; i++) {
+            if (number[i].value >= 10) {
+
+                var v = number[i].value;
+                number.RemoveRange(i, 1);
+                number.InsertRange(i, Number.Pair(Number.Digit(v / 2), Number.Digit((v + 1) / 2)));
+
+                // successful split:
+                return true;
+            }
+        }
+        // couldn't split:
+        return false;
+    }
+
+    // tokenize the input to a list of '[' ']' and digit tokens
+    Number ParseNumber(string st) {
+        var res = new Number();
+        var n = "";
+        foreach (var ch in st) {
+            if (ch >= '0' && ch <= '9') {
+                n += ch;
+            } else {
+                if (n != "") {
+                    res.Add(new Token(TokenKind.Digit, int.Parse(n)));
+                    n = "";
+                }
+                if (ch == '[') {
+                    res.Add(new Token(TokenKind.Open));
+                } else if (ch == ']') {
+                    res.Add(new Token(TokenKind.Close));
+                }
+            }
+        }
+        if (n != "") {
+            res.Add(new Token(TokenKind.Digit, int.Parse(n)));
+            n = "";
+        }
+        return res;
+    }
+
+}
+
+// we will work with a list of tokens directly
+enum TokenKind {
+    Open,
+    Close,
+    Digit
+}
+record Token(TokenKind kind, int value = 0);
+
+class Number : List {
+    public static Number Digit(int value) =>
+        new Number(){
+            new Token(TokenKind.Digit, value)
+        };
+
+    public static Number Pair(Number a, Number b) {
+        var number = new Number();
+        number.Add(new Token(TokenKind.Open));
+        number.AddRange(a);
+        number.AddRange(b);
+        number.Add(new Token(TokenKind.Close));
+        return number;
+    }
+};
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/19/illustration.jpeg b/2021/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/19/illustration.jpeg differ diff --git a/2021/19/index.html b/2021/19/index.html new file mode 100644 index 00000000..0a1d1842 --- /dev/null +++ b/2021/19/index.html @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/19 'Beacon Scanner'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/19

+

Beacon Scanner

+

in C#

+

+

by encse

+
+ +
+ +
+

As your probe drifted down through this area, it released an assortment of beacons and scanners into the water. It's difficult to navigate in the pitch black open waters of the ocean trench, but if you can build a map of the trench using data from the scanners, you should be able to safely reach the bottom.

+

The beacons and scanners float motionless in the water; they're designed to maintain the same position for long periods of time. Each scanner is capable of detecting all beacons in a large cube centered on the scanner; beacons that are at most 1000 units away from the scanner in each of the three axes (x, y, and z) have their precise position determined relative to the scanner. However, scanners cannot detect other scanners. The submarine has automatically summarized the relative positions of beacons detected by each scanner (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day19;
+
+[ProblemName("Beacon Scanner")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        LocateScanners(input)
+            .SelectMany(scanner => scanner.GetBeaconsInWorld())
+            .Distinct()
+            .Count();
+
+    public object PartTwo(string input) {
+        var scanners = LocateScanners(input);
+        return (
+            from sA in scanners
+            from sB in scanners
+            where sA != sB
+            select
+                Math.Abs(sA.center.x - sB.center.x) +
+                Math.Abs(sA.center.y - sB.center.y) +
+                Math.Abs(sA.center.z - sB.center.z)
+        ).Max();
+    }
+
+    HashSet LocateScanners(string input) {
+        var scanners = new HashSet(Parse(input));
+        var locatedScanners = new HashSet();
+        var q = new Queue();
+
+        // when a scanner is located, it gets into the queue so that we can
+        // explore its neighbours.
+
+        locatedScanners.Add(scanners.First());
+        q.Enqueue(scanners.First());
+
+        scanners.Remove(scanners.First());
+
+        while (q.Any()) {
+            var scannerA = q.Dequeue();
+            foreach (var scannerB in scanners.ToArray()) {
+                var maybeLocatedScanner = TryToLocate(scannerA, scannerB);
+                if (maybeLocatedScanner != null) {
+
+                    locatedScanners.Add(maybeLocatedScanner);
+                    q.Enqueue(maybeLocatedScanner);
+
+                    scanners.Remove(scannerB); // sic! 
+                }
+            }
+        }
+
+        return locatedScanners;
+    }
+    Scanner TryToLocate(Scanner scannerA, Scanner scannerB) {
+        var beaconsInA = scannerA.GetBeaconsInWorld().ToArray();
+
+        foreach (var (beaconInA, beaconInB) in PotentialMatchingBeacons(scannerA, scannerB)) {
+            // now try to find the orientation for B:
+            var rotatedB = scannerB;
+            for (var rotation = 0; rotation < 24; rotation++, rotatedB = rotatedB.Rotate()) {
+                // Moving the rotated scanner so that beaconA and beaconB overlaps. Are there 12 matches? 
+                var beaconInRotatedB = rotatedB.Transform(beaconInB);
+
+                var locatedB = rotatedB.Translate(new Coord(
+                    beaconInA.x - beaconInRotatedB.x,
+                    beaconInA.y - beaconInRotatedB.y,
+                    beaconInA.z - beaconInRotatedB.z
+                ));
+
+                if (locatedB.GetBeaconsInWorld().Intersect(beaconsInA).Count() >= 12) {
+                    return locatedB;
+                }
+            }
+        }
+
+        // no luck
+        return null;
+    }
+
+    IEnumerable<(Coord beaconInA, Coord beaconInB)> PotentialMatchingBeacons(Scanner scannerA, Scanner scannerB) {
+        // If we had a matching beaconInA and beaconInB and moved the center
+        // of the scanners to these then we would find at least 12 beacons 
+        // with the same coordinates.
+
+        // The only problem is that the rotation of scannerB is not fixed yet.
+
+        // We need to make our check invariant to that:
+
+        // After the translation, we could form a set from each scanner 
+        // taking the absolute values of the x y and z coordinates of their beacons 
+        // and compare those. 
+
+        IEnumerable absCoordinates(Scanner scanner) =>
+            from coord in scanner.GetBeaconsInWorld()
+            from v in new[] { coord.x, coord.y, coord.z }
+            select Math.Abs(v);
+
+        // This is the same no matter how we rotate scannerB, so the two sets should 
+        // have at least 3 * 12 common values (with multiplicity).
+
+        // 🐦 We can also considerably speed up the search with the pigeonhole principle 
+        // which says that it's enough to take all but 11 beacons from A and B. 
+        // If there is no match amongst those, there cannot be 12 matching pairs:
+        IEnumerable pick(IEnumerable ts) => ts.Take(ts.Count() - 11);
+
+        foreach (var beaconInA in pick(scannerA.GetBeaconsInWorld())) {
+            var absA = absCoordinates(
+                scannerA.Translate(new Coord(-beaconInA.x, -beaconInA.y, -beaconInA.z))
+            ).ToHashSet();
+
+            foreach (var beaconInB in pick(scannerB.GetBeaconsInWorld())) {
+                var absB = absCoordinates(
+                    scannerB.Translate(new Coord(-beaconInB.x, -beaconInB.y, -beaconInB.z))
+                );
+
+                if (absB.Count(d => absA.Contains(d)) >= 3 * 12) {
+                    yield return (beaconInA, beaconInB);
+                }
+            }
+        }
+    }
+
+    Scanner[] Parse(string input) => (
+        from block in input.Split("\n\n")
+        let beacons =
+            from line in block.Split("\n").Skip(1)
+            let parts = line.Split(",").Select(int.Parse).ToArray()
+            select new Coord(parts[0], parts[1], parts[2])
+        select new Scanner(new Coord(0, 0, 0), 0, beacons.ToList())
+    ).ToArray();
+}
+
+record Coord(int x, int y, int z);
+record Scanner(Coord center, int rotation, List beaconsInLocal) {
+    public Scanner Rotate() => new Scanner(center, rotation + 1, beaconsInLocal);
+    public Scanner Translate(Coord t) => new Scanner(
+        new Coord(center.x + t.x, center.y + t.y, center.z + t.z), rotation, beaconsInLocal);
+
+    public Coord Transform(Coord coord) {
+        var (x, y, z) = coord;
+
+#pragma warning disable 1717
+        // rotate coordinate system so that x-axis points in the possible 6 directions
+        switch (rotation % 6) {
+            case 0: (x, y, z) = (x, y, z); break;
+            case 1: (x, y, z) = (-x, y, -z); break;
+            case 2: (x, y, z) = (y, -x, z); break;
+            case 3: (x, y, z) = (-y, x, z); break;
+            case 4: (x, y, z) = (z, y, -x); break;
+            case 5: (x, y, z) = (-z, y, x); break;
+        }
+
+        // rotate around x-axis:
+        switch ((rotation / 6) % 4) {
+            case 0: (x, y, z) = (x, y, z); break;
+            case 1: (x, y, z) = (x, -z, y); break;
+            case 2: (x, y, z) = (x, -y, -z); break;
+            case 3: (x, y, z) = (x, z, -y); break;
+        }
+#pragma warning restore
+
+        return new Coord(center.x + x, center.y + y, center.z + z);
+    }
+
+    public IEnumerable GetBeaconsInWorld() {
+        return beaconsInLocal.Select(Transform);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/2/illustration.jpeg b/2021/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/2/illustration.jpeg differ diff --git a/2021/2/index.html b/2021/2/index.html new file mode 100644 index 00000000..caf68ec0 --- /dev/null +++ b/2021/2/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/2 'Dive!'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/2

+

Dive!

+

in C#

+

+

by encse

+
+ +
+ +
+

Now, you need to figure out how to pilot this thing.

+

It seems like the submarine can take a series of commands like forward 1, down 2, or up 3:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day02;
+
+[ProblemName("Dive!")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Parse(input)
+           .Aggregate(
+               new State1(0, 0),
+               (state, step) => step.dir switch {
+                   'f' => state with { x = state.x + step.amount },
+                   'u' => state with { y = state.y - step.amount },
+                   'd' => state with { y = state.y + step.amount },
+                   _ => throw new Exception(),
+               },
+               res => res.x * res.y
+           );
+    }
+
+    public object PartTwo(string input) {
+        return Parse(input)
+           .Aggregate(
+               new State2(0, 0, 0),
+               (state, step) => step.dir switch {
+                   'f' => state with { 
+                              x = state.x + step.amount, 
+                              y = state.y + step.amount * state.aim 
+                          },
+                   'u' => state with { aim = state.aim - step.amount },
+                   'd' => state with { aim = state.aim + step.amount },
+                   _ => throw new Exception(),
+               },
+               res => res.x * res.y
+           );
+    }
+
+    IEnumerable Parse(string st) => 
+        from 
+            line in st.Split('\n')
+            let parts = line.Split()
+        select 
+            new Input(parts[0][0], int.Parse(parts[1]));
+}
+
+record Input(char dir, int amount);
+record State1(int x, int y);
+record State2(int x, int y, int aim);
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/20/illustration.jpeg b/2021/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/20/illustration.jpeg differ diff --git a/2021/20/index.html b/2021/20/index.html new file mode 100644 index 00000000..52d87010 --- /dev/null +++ b/2021/20/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/20 'Trench Map'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/20

+

Trench Map

+

in C#

+

+

by encse

+
+ +
+ +
+

With the scanners fully deployed, you turn their attention to mapping the floor of the ocean trench.

+

When you get back the image from the scanners, it seems to just be random noise. Perhaps you can combine an image enhancement algorithm and the input image (your puzzle input) to clean it up a little.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day20;
+
+[ProblemName("Trench Map")]
+class Solution : Solver {
+
+    public object PartOne(string input) => EnhanceN(input, 2).Count(x => x.Value == 1);
+    public object PartTwo(string input) => EnhanceN(input, 50).Count(x => x.Value == 1);
+
+    // return the N times enhanced image
+    Dictionary EnhanceN(string input, int n) {
+        var blocks = input.Split("\n\n");
+        var (algo, image) = (blocks[0], GetImage(blocks[1]));
+
+        System.Diagnostics.Debug.Assert(algo[0] == '#'); // the image changes parity in each rounds
+
+        var (minX, minY, maxX, maxY) = (0, 0, image.Keys.MaxBy(p => p.x).x, image.Keys.MaxBy(p => p.y).y);
+
+        for (var i = 0; i < n; i++) {
+            var tmp = new Dictionary();
+
+            for (var y = minY - 1; y <= maxY + 1; y++) {
+                for (var x = minX - 1; x <= maxX + 1; x++) {
+
+                    var point = new Point(x, y);
+                    
+                    var index = 0;
+
+                    // it's supposed that neighbours are enumarated in the right order
+                    foreach (var neighbour in Neighbours(point)) {
+
+                        // the trick is in the i % 2 part,
+                        // for even values of i, the infinite part of the image is all zero
+                        // for odd ones, it contains 1-s due to the way the 'algo' is set up.
+                        index = index * 2 + image.GetValueOrDefault(neighbour, i % 2);
+                    }
+
+                    tmp[point] = algo[index] == '#' ? 1 : 0;
+                }
+            }
+
+            // update bounds & image
+            (minX, minY, maxX, maxY) = (minX - 1, minY - 1, maxX + 1, maxY + 1);
+            image = tmp;
+        }
+
+        return image;
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area
+    Dictionary GetImage(string input) {
+        var map = input.Split("\n");
+        return new Dictionary(
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(new Point(x, y), map[y][x] == '#' ? 1 : 0)
+        );
+    }
+
+    IEnumerable Neighbours(Point pos) =>
+        from y in Enumerable.Range(-1, 3)
+        from x in Enumerable.Range(-1, 3)
+        select new Point(pos.x + x, pos.y + y);
+}
+
+record Point(int x, int y);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/21/illustration.jpeg b/2021/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/21/illustration.jpeg differ diff --git a/2021/21/index.html b/2021/21/index.html new file mode 100644 index 00000000..8c29da9b --- /dev/null +++ b/2021/21/index.html @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/21 'Dirac Dice'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/21

+

Dirac Dice

+

in C#

+

+

by encse

+
+ +
+ +
+

There's not much to do as you slowly descend to the bottom of the ocean. The submarine computer challenges you to a nice game of Dirac Dice.

+

This game consists of a single die, two pawns, and a game board with a circular track containing ten spaces marked 1 through 10 clockwise. Each player's starting space is chosen randomly (your puzzle input). Player 1 goes first.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day21;
+
+[ProblemName("Dirac Dice")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        // ⭐ we can convert 3 consecutive throws to a 3-throw with the new .Net 6 Chunk function:
+        var threeRoll = DeterministicThrows().Chunk(3).Select(x => x.Sum());
+
+        // take turns until the active player wins:
+        var round = 0;
+        var (active, other) = Parse(input);
+        foreach (var steps in threeRoll) {
+            round++;
+            active = active.Move(steps);
+            if (active.score >= 1000) {
+                break;
+            }
+            (active, other) = (other, active);
+        }
+
+        return other.score * 3 * round;
+    }
+
+    public object PartTwo(string input) {
+        // win counts tells us how many times the active and the other player wins
+        // if they are starting from the given positions and scores.
+
+        // this function needs to be cached, because we don't have time till eternity.
+        var cache = new Dictionary<(Player, Player), (long, long)>();
+    
+        (long activeWins, long otherWins) winCounts((Player active, Player other) players) {
+            if (players.other.score >= 21) {
+                return (0, 1);
+            }
+
+            if (!cache.ContainsKey(players)) {
+                var (activeWins, otherWins) = (0L, 0L);
+                foreach (var steps in DiracThrows()) {
+                    var wins = winCounts((players.other, players.active.Move(steps)));
+                    // they are switching roles here ^
+                    // hence the return value needs to be swapped as well
+                    activeWins += wins.otherWins;
+                    otherWins += wins.activeWins;
+                }
+                cache[players] = (activeWins, otherWins);
+            }
+            return cache[players];
+        }
+
+        var wins = winCounts(Parse(input));
+        
+        // which player wins more:
+        return Math.Max(wins.activeWins, wins.otherWins);
+    }
+
+    IEnumerable DeterministicThrows() =>
+        from i in Enumerable.Range(1, int.MaxValue)
+        select (i - 1) % 100 + 1;
+
+    IEnumerable DiracThrows() =>
+        from i in new[] { 1, 2, 3 }
+        from j in new[] { 1, 2, 3 }
+        from k in new[] { 1, 2, 3 }
+        select i + j + k;
+
+    (Player active, Player other) Parse(string input) {
+        var players = (
+            from line in input.Split("\n")
+            let parts = line.Split(": ")
+            select new Player(0, int.Parse(parts[1]))
+        ).ToArray();
+        return (players[0], players[1]);
+    }
+}
+
+record Player(int score, int pos) {
+    public Player Move(int steps) {
+        var newPos = (this.pos - 1 + steps) % 10 + 1;
+        return new Player(this.score + newPos, newPos);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/22/illustration.jpeg b/2021/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/22/illustration.jpeg differ diff --git a/2021/22/index.html b/2021/22/index.html new file mode 100644 index 00000000..9fce020e --- /dev/null +++ b/2021/22/index.html @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/22 'Reactor Reboot'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/22

+

Reactor Reboot

+

in C#

+

+

by encse

+
+ +
+ +
+

Operating at these extreme ocean depths has overloaded the submarine's reactor; it needs to be rebooted.

+

The reactor core is made up of a large 3-dimensional grid made up entirely of cubes, one cube per integer 3-dimensional coordinate (x,y,z). Each cube can be either on or off; at the start of the reboot process, they are all off. (Could it be an old model of a reactor you've seen before?)

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2021.Day22;
+
+[ProblemName("Reactor Reboot")]
+class Solution : Solver {
+
+    public object PartOne(string input) => ActiveCubesInRange(input, 50);
+    public object PartTwo(string input) => ActiveCubesInRange(input, int.MaxValue);
+
+    public long ActiveCubesInRange(string input, int range) {
+        var cmds = Parse(input);
+
+        // Recursive approach
+
+        // If we can determine the number of active cubes in subregions
+        // we can compute the effect of the i-th cmd as well:
+        long activeCubesAfterIcmd(int icmd, Region region) {
+
+            if (region.IsEmpty || icmd < 0) {
+                return 0; // empty is empty
+            } else {
+                var intersection = region.Intersect(cmds[icmd].region);
+                var activeInRegion = activeCubesAfterIcmd(icmd - 1, region);
+                var activeInIntersection = activeCubesAfterIcmd(icmd - 1, intersection);
+                var activeOutsideIntersection = activeInRegion - activeInIntersection;
+
+                // outside the intersection is unaffected, the rest is either on or off:
+                return cmds[icmd].turnOff ? activeOutsideIntersection : activeOutsideIntersection + intersection.Volume;
+            }
+        }
+
+        return activeCubesAfterIcmd(
+            cmds.Length - 1,
+            new Region(
+                new Segment(-range, range),
+                new Segment(-range, range),
+                new Segment(-range, range)));
+    }
+
+    Cmd[] Parse(string input) {
+        var res = new List();
+        foreach (var line in input.Split("\n")) {
+            var turnOff = line.StartsWith("off");
+            // get all the numbers with a regexp:
+            var m = Regex.Matches(line, "-?[0-9]+").Select(m => int.Parse(m.Value)).ToArray();
+            res.Add(new Cmd(turnOff, new Region(new Segment(m[0], m[1]), new Segment(m[2], m[3]), new Segment(m[4], m[5]))));
+        }
+        return res.ToArray();
+    }
+}
+
+record Cmd(bool turnOff, Region region);
+
+record Segment(int from, int to) {
+    public bool IsEmpty => from > to;
+    public long Length => IsEmpty ? 0 : to - from + 1;
+
+    public Segment Intersect(Segment that) =>
+        new Segment(Math.Max(this.from, that.from), Math.Min(this.to, that.to));
+}
+
+record Region(Segment x, Segment y, Segment z) {
+    public bool IsEmpty => x.IsEmpty || y.IsEmpty || z.IsEmpty;
+    public long Volume => x.Length * y.Length * z.Length;
+
+    public Region Intersect(Region that) =>
+        new Region(this.x.Intersect(that.x), this.y.Intersect(that.y), this.z.Intersect(that.z));
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/23/illustration.jpeg b/2021/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/23/illustration.jpeg differ diff --git a/2021/23/index.html b/2021/23/index.html new file mode 100644 index 00000000..17701b98 --- /dev/null +++ b/2021/23/index.html @@ -0,0 +1,559 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/23 'Amphipod'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/23

+

Amphipod

+

in C#

+

+

by encse

+
+ +
+ +
+

A group of amphipods notice your fancy submarine and flag you down. "With such an impressive shell," one amphipod says, "surely you can help us with a question that has stumped our best scientists."

+

They go on to explain that a group of timid, stubborn amphipods live in a nearby burrow. Four types of amphipods live there: Amber (A), Bronze (B), Copper (C), and Desert (D). They live in a burrow that consists of a hallway and four side rooms. The side rooms are initially full of amphipods, and the hallway is initially empty.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day23;
+
+[ProblemName("Amphipod")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input);
+    public object PartTwo(string input) => Solve(Upscale(input));
+
+    string Upscale(string input) {
+        var lines = input.Split("\n").ToList();
+        lines.Insert(3, "  #D#C#B#A#");
+        lines.Insert(4, "  #D#B#A#C#");
+        return string.Join("\n", lines);
+    }
+
+    int Solve(string input) {
+        var maze = Maze.Parse(input);
+
+        var q = new PriorityQueue();
+        var cost = new Dictionary();
+
+        q.Enqueue(maze, 0);
+        cost.Add(maze, 0);
+
+        while (q.Count > 0) {
+            maze = q.Dequeue();
+
+            if (maze.Finished()) {
+                return cost[maze];
+            }
+
+            foreach (var n in Neighbours(maze)) {
+                if (cost[maze] + n.cost < cost.GetValueOrDefault(n.maze, int.MaxValue)) {
+                    cost[n.maze] = cost[maze] + n.cost;
+                    q.Enqueue(n.maze, cost[n.maze]);
+                }
+            }
+        }
+
+        throw new Exception();
+    }
+
+    int stepCost(char actor) {
+        return actor == 'A' ? 1 : actor == 'B' ? 10 : actor == 'C' ? 100 : 1000;
+    }
+
+    int getIcolDst(char ch) {
+        return
+            ch == 'A' ? 3 :
+            ch == 'B' ? 5 :
+            ch == 'C' ? 7 :
+            ch == 'D' ? 9 :
+            throw new Exception();
+    }
+
+    (Maze maze, int cost) HallwayToRoom(Maze maze) {
+        for (var icol = 1; icol < 12; icol++) {
+            var ch = maze.ItemAt(new Point(1, icol));
+
+            if (ch == '.') {
+                continue;
+            }
+
+            var icolDst = getIcolDst(ch);
+
+            if (maze.CanMoveToDoor(icol, icolDst) && maze.CanEnterRoom(ch)) {
+                var steps = Math.Abs(icolDst - icol);
+                var pt = new Point(1, icolDst);
+
+                while (maze.ItemAt(pt.Below) == '.') {
+                    pt = pt.Below;
+                    steps++;
+                }
+
+                var l = HallwayToRoom(maze.Move(new Point(1, icol), pt));
+                return (l.maze, l.cost + steps * stepCost(ch));
+            }
+        }
+        return (maze, 0);
+    }
+
+    IEnumerable<(Maze maze, int cost)> RoomToHallway(Maze maze) {
+        var hallwayColumns = new int[] { 1, 2, 4, 6, 8, 10, 11 };
+
+        foreach (var roomColumn in new[] { 3, 5, 7, 9 }) {
+
+            if (maze.FinishedColumn(roomColumn)) {
+                continue;
+            }
+
+            var stepsV = 0;
+            var ptSrc = new Point(1, roomColumn);
+            while (maze.ItemAt(ptSrc) == '.') {
+                ptSrc = ptSrc.Below;
+                stepsV++;
+            }
+
+            var ch = maze.ItemAt(ptSrc);
+            if (ch == '#') {
+                continue;
+            }
+
+            foreach (var dj in new[] { -1, 1 }) {
+                var stepsH = 0;
+                var ptDst = new Point(1, roomColumn);
+                while (maze.ItemAt(ptDst) == '.') {
+
+                    if (hallwayColumns.Contains(ptDst.icol)) {
+                        yield return (maze.Move(ptSrc, ptDst), (stepsV + stepsH) * stepCost(ch));
+                    }
+
+                    if (dj == -1) {
+                        ptDst = ptDst.Left;
+                    } else {
+                        ptDst = ptDst.Right;
+                    }
+                    stepsH++;
+                }
+            }
+        }
+    }
+
+    IEnumerable<(Maze maze, int cost)> Neighbours(Maze maze) {
+        var hallwayToRoom = HallwayToRoom(maze);
+        return hallwayToRoom.cost != 0 ? new[] { hallwayToRoom } : RoomToHallway(maze);
+    }
+
+}
+
+record Point(int irow, int icol) {
+    public Point Below => new Point(irow + 1, icol);
+    public Point Above => new Point(irow - 1, icol);
+    public Point Left => new Point(irow, icol - 1);
+    public Point Right => new Point(irow, icol + 1);
+}
+
+record Maze {
+
+    const int columnMaskA = (1 << 11) | (1 << 15) | (1 << 19) | (1 << 23);
+    const int columnMaskB = (1 << 12) | (1 << 16) | (1 << 20) | (1 << 24);
+    const int columnMaskC = (1 << 13) | (1 << 17) | (1 << 21) | (1 << 25);
+    const int columnMaskD = (1 << 14) | (1 << 18) | (1 << 22) | (1 << 26);
+
+    public static Maze Parse(string input) {
+        var maze = new Maze(columnMaskA, columnMaskB, columnMaskC, columnMaskD);
+        var map = input.Split("\n");
+        foreach (var irow in Enumerable.Range(0, map.Length)) {
+            foreach (var icol in Enumerable.Range(0, map[0].Length)) {
+                maze = maze.SetItem(
+                    new Point(irow, icol), irow < map.Length && icol < map[irow].Length ? map[irow][icol] : '#');
+            }
+        }
+        return maze;
+    }
+
+    int a, b, c, d;
+
+    Maze(int a, int b, int c, int d) {
+        this.a = a;
+        this.b = b;
+        this.c = c;
+        this.d = d;
+    }
+
+    int BitFromPoint(Point pt) =>
+        (pt.irow, pt.icol) switch {
+            (1, 1) => 1 << 0,
+            (1, 2) => 1 << 1,
+            (1, 3) => 1 << 2,
+            (1, 4) => 1 << 3,
+            (1, 5) => 1 << 4,
+            (1, 6) => 1 << 5,
+            (1, 7) => 1 << 6,
+            (1, 8) => 1 << 7,
+            (1, 9) => 1 << 8,
+            (1, 10) => 1 << 9,
+            (1, 11) => 1 << 10,
+
+            (2, 3) => 1 << 11,
+            (2, 5) => 1 << 12,
+            (2, 7) => 1 << 13,
+            (2, 9) => 1 << 14,
+
+            (3, 3) => 1 << 15,
+            (3, 5) => 1 << 16,
+            (3, 7) => 1 << 17,
+            (3, 9) => 1 << 18,
+
+            (4, 3) => 1 << 19,
+            (4, 5) => 1 << 20,
+            (4, 7) => 1 << 21,
+            (4, 9) => 1 << 22,
+
+            (5, 3) => 1 << 23,
+            (5, 5) => 1 << 24,
+            (5, 7) => 1 << 25,
+            (5, 9) => 1 << 26,
+
+            _ => 1 << 31,
+        };
+
+    public bool CanEnterRoom(char ch) =>
+        ch switch {
+            'A' => (b & columnMaskA) == 0 && (c & columnMaskA) == 0 && (d & columnMaskA) == 0,
+            'B' => (a & columnMaskB) == 0 && (c & columnMaskB) == 0 && (d & columnMaskB) == 0,
+            'C' => (a & columnMaskC) == 0 && (b & columnMaskC) == 0 && (d & columnMaskC) == 0,
+            'D' => (a & columnMaskD) == 0 && (b & columnMaskD) == 0 && (c & columnMaskD) == 0,
+            _ => throw new Exception()
+        };
+
+    public bool CanMoveToDoor(int icolFrom, int icolTo) {
+        Point step(Point pt) {
+            return icolFrom < icolTo ? pt.Right : pt.Left;
+        }
+        var pt = step(new Point(1, icolFrom));
+        while (pt.icol != icolTo) {
+            if (this.ItemAt(pt) != '.') {
+                return false;
+            }
+            pt = step(pt);
+        }
+        return true;
+    }
+
+    public bool FinishedColumn(int icol) =>
+        icol switch {
+            3 => a == columnMaskA,
+            5 => b == columnMaskB,
+            7 => c == columnMaskC,
+            9 => d == columnMaskD,
+            _ => throw new Exception()
+        };
+
+    public bool Finished() =>
+        FinishedColumn(3) && FinishedColumn(5) && FinishedColumn(7) && FinishedColumn(9);
+
+    public char ItemAt(Point pt) {
+        var bit = BitFromPoint(pt);
+        return
+            bit == 1 << 31 ? '#' :
+            (a & bit) != 0 ? 'A' :
+            (b & bit) != 0 ? 'B' :
+            (c & bit) != 0 ? 'C' :
+            (d & bit) != 0 ? 'D' :
+            '.';
+    }
+
+    public Maze Move(Point from, Point to) =>
+        SetItem(to, ItemAt(from)).SetItem(from, '.');
+
+    private Maze SetItem(Point pt, char ch) {
+        if (ch == '#') {
+            return this;
+        }
+        var bit = BitFromPoint(pt);
+        if (bit == 1 << 31) {
+            return this;
+        }
+
+        return ch switch {
+            '.' => new Maze(
+                a & ~bit,
+                b & ~bit,
+                c & ~bit,
+                d & ~bit
+            ),
+            'A' => new Maze(a | bit, b & ~bit, c & ~bit, d & ~bit),
+            'B' => new Maze(a & ~bit, b | bit, c & ~bit, d & ~bit),
+            'C' => new Maze(a & ~bit, b & ~bit, c | bit, d & ~bit),
+            'D' => new Maze(a & ~bit, b & ~bit, c & ~bit, d | bit),
+            _ => throw new Exception()
+        };
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/24/illustration.jpeg b/2021/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/24/illustration.jpeg differ diff --git a/2021/24/index.html b/2021/24/index.html new file mode 100644 index 00000000..d818daa9 --- /dev/null +++ b/2021/24/index.html @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/24 'Arithmetic Logic Unit'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/24

+

Arithmetic Logic Unit

+

in C#

+

+

by encse

+
+ +
+ +
+

Magic smoke starts leaking from the submarine's arithmetic logic unit (ALU). Without the ability to perform basic arithmetic and logic functions, the submarine can't produce cool patterns with its Christmas lights!

+

It also can't navigate. Or run the oxygen system.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2021.Day24;
+
+[ProblemName("Arithmetic Logic Unit")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetSerials(input).max;
+    public object PartTwo(string input) => GetSerials(input).min;
+
+    (string min, string max) GetSerials(string input) {
+
+        var digits = Enumerable.Range(1, 9).ToArray();
+
+        // The input has 14 code blocks, each dealing with one digit.
+        // The blocks define 7 pairs of `a`, `b` digits and a `shift` between them.
+        // The input is valid if for each pair the condition `a + shift = b` holds.
+        var stmBlocks = input.Split("inp w\n")[1..]; 
+
+        // Extracts the numeric argument of a statement:
+        var getArgFromLine = (int iblock, Index iline) =>   
+            int.Parse(stmBlocks[iblock].Split('\n')[iline].Split(' ')[^1]);
+
+        // A stack will contain the index of an `a` digit when we find its corresponding `b`.
+        var stack = new Stack();
+       
+        // We will fill up the result when `b` is found.
+        var max = Enumerable.Repeat(int.MinValue, 14).ToArray();
+        var min = Enumerable.Repeat(int.MaxValue, 14).ToArray();
+        
+        for (var j = 0; j < 14; j++) {
+            if (stmBlocks[j].Contains("div z 1")) { 
+                // j points to an `a` digit.
+                stack.Push(j);
+            } else { 
+                // j points to a `b` digit. 
+              
+                // `a` is at i.
+                var i = stack.Pop(); 
+
+                // A part of shift is hidden in each of the two blocks:
+                var shift = getArgFromLine(i, ^4) + getArgFromLine(j, 4);
+
+                // Find the best a and b so that the equation holds
+                foreach (var a in digits) {
+
+                    var b = a + shift;
+
+                    if (digits.Contains(b)) {
+                        if (a > max[i]) {
+                            (max[i], max[j]) = (a, b);
+                        }
+                        if (a < min[i]) {
+                            (min[i], min[j]) = (a, b);
+                        }
+                    }
+                }
+            }
+        }
+
+        // That's all folks
+        return (string.Join("", min), string.Join("", max));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/25/illustration.jpeg b/2021/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/25/illustration.jpeg differ diff --git a/2021/25/index.html b/2021/25/index.html new file mode 100644 index 00000000..a6c2b7a0 --- /dev/null +++ b/2021/25/index.html @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/25 'Sea Cucumber'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/25

+

Sea Cucumber

+

in C#

+

+

by encse

+
+ +
+ +
+

This is it: the bottom of the ocean trench, the last place the sleigh keys could be. Your submarine's experimental antenna still isn't boosted enough to detect the keys, but they must be here. All you need to do is reach the seafloor and find them.

+

At least, you'd touch down on the seafloor if you could; unfortunately, it's completely covered by two large herds of sea cucumbers, and there isn't an open space large enough for your submarine.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+
+namespace AdventOfCode.Y2021.Day25;
+
+[ProblemName("Sea Cucumber")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+
+        var map = input.Split('\n');
+        var (ccol, crow) = (map[0].Length, map.Length);
+
+        int right(int icol) => (icol + 1) % ccol;
+        int left(int icol) => (icol - 1 + ccol) % ccol;
+        int up(int irow) => (irow - 1 + crow) % crow;
+        int down(int irow) => (irow + 1) % crow;
+
+        bool movesRight(int irow, int icol) =>
+            map[irow][icol] == '>' && map[irow][right(icol)] == '.';
+        bool movesDown(int irow, int icol) =>
+            map[irow][icol] == 'v' && map[down(irow)][icol] == '.';
+
+        for(var steps = 1;; steps++) {
+            var anyMoves = false;
+
+            var newMap = new List();
+            for (var irow = 0; irow < crow; irow++) {
+                var st = "";
+                for (var icol = 0; icol < ccol; icol++) {
+                    anyMoves |= movesRight(irow, icol);
+                    st +=
+                        movesRight(irow, icol) ? '.' :
+                        movesRight(irow, left(icol)) ? '>' :
+                        map[irow][icol];
+                    
+                }
+                newMap.Add(st);
+            }
+
+            map = newMap.ToArray();
+            newMap.Clear();
+
+            for (var irow = 0; irow < crow; irow++) {
+                var st = "";
+                for (var icol = 0; icol < ccol; icol++) {
+                    anyMoves |= movesDown(irow, icol);
+                    st +=
+                        movesDown(irow, icol) ? '.' :
+                        movesDown(up(irow), icol) ? 'v' :
+                        map[irow][icol];
+                }
+                newMap.Add(st);
+            }
+
+            map = newMap.ToArray();
+
+            if (!anyMoves) {
+                return steps;
+            } 
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/3/illustration.jpeg b/2021/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/3/illustration.jpeg differ diff --git a/2021/3/index.html b/2021/3/index.html new file mode 100644 index 00000000..378858c6 --- /dev/null +++ b/2021/3/index.html @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/3 'Binary Diagnostic'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/3

+

Binary Diagnostic

+

in C#

+

+

by encse

+
+ +
+ +
+

The submarine has been making some odd creaking noises, so you ask it to produce a diagnostic report just in case.

+

The diagnostic report (your puzzle input) consists of a list of binary numbers which, when decoded properly, can tell you many useful things about the conditions of the submarine. The first parameter to check is the power consumption.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day03;
+
+[ProblemName("Binary Diagnostic")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var diagnosticReport = input.Split("\n");
+        return GammaRate(diagnosticReport) * EpsilonRate(diagnosticReport);
+    }
+
+    public object PartTwo(string input) {
+        var diagnosticReport = input.Split("\n");
+        return OxygenGeneratorRating(diagnosticReport) * Co2ScruberRating(diagnosticReport);
+    }
+
+    int GammaRate(string[] diagnosticReport) => Extract1(diagnosticReport, MostCommonBitAt);
+    int EpsilonRate(string[] diagnosticReport) => Extract1(diagnosticReport, LeastCommonBitAt);
+    int OxygenGeneratorRating(string[] diagnosticReport) => Extract2(diagnosticReport, MostCommonBitAt);
+    int Co2ScruberRating(string[] diagnosticReport) => Extract2(diagnosticReport, LeastCommonBitAt);
+
+    char MostCommonBitAt(string[] lines, int ibit) =>
+        2 * lines.Count(line => line[ibit] == '1') >= lines.Length ? '1' : '0';
+
+    char LeastCommonBitAt(string[] lines, int ibit) =>
+        MostCommonBitAt(lines, ibit) == '1' ? '0' : '1';
+
+    int Extract1(string[] lines, Func selectBitAt) {
+        var cbit = lines[0].Length;
+
+        var bits = "";
+        for (var ibit = 0; ibit < cbit; ibit++) {
+            bits += selectBitAt(lines, ibit);
+        }
+        return Convert.ToInt32(bits, 2);
+    }
+
+    int Extract2(string[] lines, Func selectBitAt) {
+        var cbit = lines[0].Length;
+
+        for (var ibit = 0; lines.Length > 1 && ibit < cbit; ibit++) {
+            var bit = selectBitAt(lines, ibit);
+            lines = lines.Where(line => line[ibit] == bit).ToArray();
+        }
+
+        return Convert.ToInt32(lines[0], 2);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/4/illustration.jpeg b/2021/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/4/illustration.jpeg differ diff --git a/2021/4/index.html b/2021/4/index.html new file mode 100644 index 00000000..98994dce --- /dev/null +++ b/2021/4/index.html @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/4 'Giant Squid'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/4

+

Giant Squid

+

in C#

+

+

by encse

+
+ +
+ +
+

You're already almost 1.5km (almost a mile) below the surface of the ocean, already so deep that you can't see any sunlight. What you can see, however, is a giant squid that has attached itself to the outside of your submarine.

+

Maybe it wants to play bingo?

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day04;
+
+[ProblemName("Giant Squid")] 
+class Solution : Solver {
+
+    public object PartOne(string input) => BoardsInOrderOfCompletion(input).First().score;
+    public object PartTwo(string input) => BoardsInOrderOfCompletion(input).Last().score;
+
+    IEnumerable BoardsInOrderOfCompletion(string input) {
+
+        var blocks = input.Split("\n\n");
+
+        // first block contains the numbers to be drawn, rest describe bingo boards:
+        var numbers = blocks[0].Split(",");
+        var boards = (from block in blocks.Skip(1) select new BingoBoard(block)).ToHashSet();
+
+        // let's play the game
+        foreach (var number in numbers) {
+            foreach (var board in boards.ToArray()) {
+                board.AddNumber(number);
+                if (board.score > 0) {
+                    yield return board;
+                    boards.Remove(board);
+                }
+            }
+        }
+    }
+}
+
+record Cell(string number, bool marked = false);
+
+// Let's be ho-ho-hoOOP this time.
+class BingoBoard {
+
+    public int score { get; private set; }
+    private List cells;
+
+    IEnumerable CellsInRow(int irow) =>
+        from icol in Enumerable.Range(0, 5) select cells[irow * 5 + icol];
+
+    IEnumerable CellsInCol(int icol) =>
+        from irow in Enumerable.Range(0, 5) select cells[irow * 5 + icol];
+
+    public BingoBoard(string st) {
+
+        // split the input into words & read them numbers into cells
+        cells = (
+            from word in st.Split(" \n".ToArray(), StringSplitOptions.RemoveEmptyEntries)
+            select new Cell(word)
+        ).ToList();
+    }
+
+    public void AddNumber(string number) {
+
+        var icell = cells.FindIndex(cell => cell.number == number);
+
+        if (icell >= 0) {
+
+            // mark the cell
+            cells[icell] = cells[icell] with { marked = true };
+
+            // if the board is completed, compute score
+            for (var i = 0; i < 5; i++) {
+                if (
+                    CellsInRow(i).All(cell => cell.marked) ||
+                    CellsInCol(i).All(cell => cell.marked)
+                ) {
+
+                    var unmarkedNumbers =
+                        from cell in cells where !cell.marked select int.Parse(cell.number);
+
+                    score = int.Parse(number) * unmarkedNumbers.Sum();
+                }
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/5/illustration.jpeg b/2021/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/5/illustration.jpeg differ diff --git a/2021/5/index.html b/2021/5/index.html new file mode 100644 index 00000000..558e193c --- /dev/null +++ b/2021/5/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/5 'Hydrothermal Venture'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/5

+

Hydrothermal Venture

+

in C#

+

+

by encse

+
+ +
+ +
+

You come across a field of hydrothermal vents on the ocean floor! These vents constantly produce large, opaque clouds, so it would be best to avoid them if possible.

+

They tend to form in lines; the submarine helpfully produces a list of nearby lines of vents (your puzzle input) for you to review. For example:

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day05;
+
+[ProblemName("Hydrothermal Venture")]
+class Solution : Solver {
+
+    public object PartOne(string input) => GetIntersections(ParseLines(input, skipDiagonals: true)).Count();
+    public object PartTwo(string input) => GetIntersections(ParseLines(input, skipDiagonals: false)).Count();
+
+    IEnumerable GetIntersections(IEnumerable> lines) => 
+        // group all the points and return the intersections:
+        lines.SelectMany(pt => pt).GroupBy(pt => pt).Where(g => g.Count() > 1).Select(g => g.Key);
+    
+    IEnumerable> ParseLines(string input, bool skipDiagonals) =>
+        from line in input.Split("\n")
+        // parse out numbers first:
+        let ns = (
+            from st in line.Split(", ->".ToArray(), StringSplitOptions.RemoveEmptyEntries)
+            select int.Parse(st)
+        ).ToArray()
+
+        // line properties:
+        let start = new Vec2(ns[0], ns[1])
+        let end = new Vec2(ns[2], ns[3])
+        let displacement = new Vec2(end.x - start.x, end.y - start.y)
+        let length = 1 + Math.Max(Math.Abs(displacement.x), Math.Abs(displacement.y))
+        let dir = new Vec2(Math.Sign(displacement.x), Math.Sign(displacement.y))
+
+        // represent lines with a set of points:
+        let points =
+            from i in Enumerable.Range(0, length)
+            select new Vec2(start.x + i * dir.x, start.y + i * dir.y)
+
+        // skip diagonals in part 1:
+        where !skipDiagonals || dir.x == 0 || dir.y == 0  
+
+        select points;
+}
+
+record Vec2(int x, int y);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/6/illustration.jpeg b/2021/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/6/illustration.jpeg differ diff --git a/2021/6/index.html b/2021/6/index.html new file mode 100644 index 00000000..67f483dd --- /dev/null +++ b/2021/6/index.html @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/6 'Lanternfish'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/6

+

Lanternfish

+

in C#

+

+

by encse

+
+ +
+ +
+

The sea floor is getting steeper. Maybe the sleigh keys got carried this way?

+

A massive school of glowing lanternfish swims past. They must spawn quickly to reach such large numbers - maybe exponentially quickly? You should model their growth rate to be sure.

+

Read the full puzzle.

+
+
using System.Linq;
+
+namespace AdventOfCode.Y2021.Day06;
+
+[ProblemName("Lanternfish")]
+class Solution : Solver {
+
+    public object PartOne(string input) => FishCountAfterNDays(input, 80);
+    public object PartTwo(string input) => FishCountAfterNDays(input, 256);
+
+    long FishCountAfterNDays(string input, int days) {
+
+        // group the fish by their timer, no need to deal with them one by one:
+        var fishCountByInternalTimer = new long[9];
+        foreach (var ch in input.Split(',')) {
+            fishCountByInternalTimer[int.Parse(ch)]++;
+        }
+        
+        // we will model a circular shift register, with an additional feedback:
+        //       0123456           78 
+        //   ┌──[.......]─<─(+)───[..]──┐
+        //   └──────>────────┴─────>────┘
+        //     reproduction     newborn
+
+        for (var t = 0; t < days; t++) {
+            fishCountByInternalTimer[(t + 7) % 9] += fishCountByInternalTimer[t % 9];
+        }
+
+        return fishCountByInternalTimer.Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/7/illustration.jpeg b/2021/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/7/illustration.jpeg differ diff --git a/2021/7/index.html b/2021/7/index.html new file mode 100644 index 00000000..45535daf --- /dev/null +++ b/2021/7/index.html @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/7 'The Treachery of Whales'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/7

+

The Treachery of Whales

+

in C#

+

+

by encse

+
+ +
+ +
+

A giant whale has decided your submarine is its next meal, and it's much faster than you are. There's nowhere to run!

+

Suddenly, a swarm of crabs (each in its own tiny submarine - it's too deep for them otherwise) zooms in to rescue you! They seem to be preparing to blast a hole in the ocean floor; sensors indicate a massive underground cave system just beyond where they're aiming!

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day07;
+
+[ProblemName("The Treachery of Whales")]
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        FuelMin(input, fuelConsumption: distance => distance);
+
+    public object PartTwo(string input) => 
+        FuelMin(input, fuelConsumption: distance => (1 + distance) * distance / 2);
+        
+    int FuelMin(string input, Func fuelConsumption) {
+        var positions = input.Split(",").Select(int.Parse).ToArray();
+
+        var totalFuelToReachTarget = (int target) => 
+            positions.Select(position => fuelConsumption(Math.Abs(target - position))).Sum();
+
+        // Minimize the total fuel consumption checking each possible target position.
+        // We have just about 1000 of these, so an O(n^2) algorithm will suffice.
+        var minPosition = positions.Min();
+        var maxPosition = positions.Max();
+        return Enumerable.Range(minPosition, maxPosition - minPosition + 1).Select(totalFuelToReachTarget).Min();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/8/illustration.jpeg b/2021/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/8/illustration.jpeg differ diff --git a/2021/8/index.html b/2021/8/index.html new file mode 100644 index 00000000..d19b1ae1 --- /dev/null +++ b/2021/8/index.html @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/8 'Seven Segment Search'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/8

+

Seven Segment Search

+

in C#

+

+

by encse

+
+ +
+ +
+

You barely reach the safety of the cave when the whale smashes into the cave mouth, collapsing it. Sensors indicate another exit to this cave at a much greater depth, so you have no choice but to press on.

+

As your submarine slowly makes its way through the cave system, you notice that the four-digit seven-segment displays in your submarine are malfunctioning; they must have been damaged during the escape. You'll be in a lot of trouble without them, so you'd better figure out what's wrong.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day08;
+
+[ProblemName("Seven Segment Search")]
+class Solution : Solver {
+
+   /*
+              0:      1:      2:      3:      4:      5:      6:      7:      8:      9:
+             aaaa    ....    aaaa    aaaa    ....    aaaa    aaaa    aaaa    aaaa    aaaa
+            b    c  .    c  .    c  .    c  b    c  b    .  b    .  .    c  b    c  b    c
+            b    c  .    c  .    c  .    c  b    c  b    .  b    .  .    c  b    c  b    c
+             ....    ....    dddd    dddd    dddd    dddd    dddd    ....    dddd    dddd
+            e    f  .    f  e    .  .    f  .    f  .    f  e    f  .    f  e    f  .    f
+            e    f  .    f  e    .  .    f  .    f  .    f  e    f  .    f  e    f  .    f
+             gggg    ....    gggg    gggg    ....    gggg    gggg    ....    gggg    gggg
+    */
+
+    public object PartOne(string input) {
+
+        // we can identify digits 1, 7, 4 and 8 by their active segments count:
+        var segmentCounts = new[] { "cd", "acf", "bcdf", "abcdefg" }.Select(x => x.Length).ToHashSet();
+
+        return (
+            from line in input.Split("\n")
+            let parts = line.Split(" | ")
+            from segment in parts[1].Split(" ")
+            where segmentCounts.Contains(segment.Length)
+            select 1
+        ).Count();
+    }
+
+    public object PartTwo(string input) {
+        var res = 0;
+        foreach(var line in input.Split("\n")) {
+            var parts = line.Split(" | ");
+            var patterns = parts[0].Split(" ").Select(x => x.ToHashSet()).ToArray();
+
+            // let's figure out what segments belong to each digit
+            var digits = new HashSet[10];
+
+            // we can do these by length:
+            digits[1] = patterns.Single(pattern => pattern.Count() == "cf".Length);
+            digits[4] = patterns.Single(pattern => pattern.Count() == "bcdf".Length);
+
+            // it turns out that the following tripplet uniquely identifies the rest:
+            var lookup = (int segmentCount, int commonWithOne, int commonWithFour) =>
+                patterns.Single(pattern => 
+                    pattern.Count() == segmentCount && 
+                    pattern.Intersect(digits[1]).Count() == commonWithOne && 
+                    pattern.Intersect(digits[4]).Count() == commonWithFour
+                );
+            
+            digits[0] = lookup(6, 2, 3);  
+            digits[2] = lookup(5, 1, 2);
+            digits[3] = lookup(5, 2, 3);
+            digits[5] = lookup(5, 1, 3);
+            digits[6] = lookup(6, 1, 3);
+            digits[7] = lookup(3, 2, 2);
+            digits[8] = lookup(7, 2, 4);
+            digits[9] = lookup(6, 2, 4);
+                    
+            var decode = (string v) => 
+                Enumerable.Range(0, 10).Single(i => digits[i].SetEquals(v));
+
+            // Decode the number, Horner would like this.
+            res += parts[1].Split(" ").Aggregate(0, (n, digit) => n * 10 + decode(digit));
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2021/9/illustration.jpeg b/2021/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2021/9/illustration.jpeg differ diff --git a/2021/9/index.html b/2021/9/index.html new file mode 100644 index 00000000..0dea81bb --- /dev/null +++ b/2021/9/index.html @@ -0,0 +1,351 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2021/9 'Smoke Basin'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2021/9

+

Smoke Basin

+

in C#

+

+

by encse

+
+ +
+ +
+

These caves seem to be lava tubes. Parts are even still volcanically active; small hydrothermal vents release smoke into the caves that slowly settles like rain.

+

If you can model how the smoke flows through the caves, you might be able to avoid it and be that much safer. The submarine generates a heightmap of the floor of the nearby caves for you (your puzzle input).

+

Read the full puzzle.

+
+
using System.Collections.Immutable;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2021.Day09;
+
+[ProblemName("Smoke Basin")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var map = GetMap(input);
+
+        // find the 'low points' and return a hash computed from their heights:
+        return GetLowPoints(map).Select(point => 1 + map[point]).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var map = GetMap(input);
+
+        // find the 3 biggest basins and return a hash computed from their size:
+        return GetLowPoints(map)
+            .Select(p => BasinSize(map, p))
+            .OrderByDescending(basinSize => basinSize)
+            .Take(3)
+            .Aggregate(1, (m, basinSize) => m * basinSize);
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area using GetValueOrDefault
+    ImmutableDictionary GetMap(string input) {
+        var map = input.Split("\n");
+        return (
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(new Point(x, y), map[y][x] - '0')
+        ).ToImmutableDictionary();
+    }
+
+    IEnumerable Neighbours(Point point) => 
+        new [] {
+           point with {y = point.y + 1},
+           point with {y = point.y - 1},
+           point with {x = point.x + 1},
+           point with {x = point.x - 1},
+        };
+
+    public IEnumerable GetLowPoints(ImmutableDictionary  map) =>
+        from point in map.Keys 
+        // point is low if each of its neighbours is higher:
+        where Neighbours(point).All(neighbour => map[point] < map.GetValueOrDefault(neighbour, 9))
+        select point;
+
+    public int BasinSize(ImmutableDictionary map, Point point) {
+        // flood fill algorithm
+        var filled = new HashSet{point};
+        var queue = new Queue(filled);
+
+        while (queue.Any()) {
+            foreach (var neighbour in Neighbours(queue.Dequeue()).Except(filled)) {
+                if (map.GetValueOrDefault(neighbour, 9) != 9) {
+                    queue.Enqueue(neighbour);
+                    filled.Add(neighbour);
+                }
+            }
+        }
+        return filled.Count;
+    }
+}
+
+record Point(int x, int y);
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/1/illustration.jpeg b/2022/1/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/1/illustration.jpeg differ diff --git a/2022/1/index.html b/2022/1/index.html new file mode 100644 index 00000000..a43485b4 --- /dev/null +++ b/2022/1/index.html @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/1 'Calorie Counting'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/1

+

Calorie Counting

+

in C#

+

+

by encse

+
+ +
+ +
+

Santa's reindeer typically eat regular reindeer food, but they need a lot of magical energy to deliver presents on Christmas. For that, their favorite snack is a special type of star fruit that only grows deep in the jungle. The Elves have brought you on their annual expedition to the grove where the fruit grows.

+

To supply enough magical energy, the expedition needs to retrieve a minimum of fifty stars by December 25th. Although the Elves assure you that the grove has plenty of fruit, you decide to grab any fruit you see along the way, just in case.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day01;
+
+[ProblemName("Calorie Counting")]      
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        GetCaloriesPerElf(input).First();
+
+    public object PartTwo(string input) =>
+        GetCaloriesPerElf(input).Take(3).Sum();
+
+    // Returns the calories carried by the elves in descending order.
+    private IEnumerable GetCaloriesPerElf(string input) =>
+        from elf in input.Split("\n\n")
+        let calories = elf.Split('\n').Select(int.Parse).Sum()
+        orderby calories descending
+        select calories;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/10/illustration.jpeg b/2022/10/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/10/illustration.jpeg differ diff --git a/2022/10/index.html b/2022/10/index.html new file mode 100644 index 00000000..d7bfb768 --- /dev/null +++ b/2022/10/index.html @@ -0,0 +1,328 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/10 'Cathode-Ray Tube'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/10

+

Cathode-Ray Tube

+

in C#

+

+

by encse

+
+ +
+ +
+

You avoid the ropes, plunge into the river, and swim to shore.

+

The Elves yell something about meeting back up with them upriver, but the river is too loud to tell exactly what they're saying. They finish crossing the bridge and disappear from view.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day10;
+
+[ProblemName("Cathode-Ray Tube")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var sample = new[] { 20, 60, 100, 140, 180, 220 };
+        return Signal(input)
+            .Where(signal => sample.Contains(signal.cycle))
+            .Select(signal => signal.x * signal.cycle)
+            .Sum();
+    }
+
+    public object PartTwo(string input) => 
+        Signal(input)
+            .Select(signal => {
+                var spriteMiddle = signal.x;
+                var screenColumn = (signal.cycle - 1) % 40;
+                return Math.Abs(spriteMiddle - screenColumn) < 2 ? '#' : ' ';
+            })
+            .Chunk(40)
+            .Select(line => new string(line))
+            .Aggregate("", (screen, line) => screen + line + "\n")
+            .Ocr();
+
+    IEnumerable<(int cycle, int x)> Signal(string input) {
+        var (cycle, x) = (1, 1);
+        foreach (var line in input.Split("\n")) {
+            var parts = line.Split(" ");
+            switch (parts[0]) {
+                case "noop":
+                    yield return (cycle++, x);
+                    break;
+                case "addx":
+                    yield return (cycle++, x);
+                    yield return (cycle++, x);
+                    x += int.Parse(parts[1]);
+                    break;
+                default:
+                    throw new ArgumentException(parts[0]);
+            }
+        }
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/11/illustration.jpeg b/2022/11/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/11/illustration.jpeg differ diff --git a/2022/11/index.html b/2022/11/index.html new file mode 100644 index 00000000..a4145f8e --- /dev/null +++ b/2022/11/index.html @@ -0,0 +1,385 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/11 'Monkey in the Middle'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/11

+

Monkey in the Middle

+

in C#

+

+

by encse

+
+ +
+ +
+

As you finally start making your way upriver, you realize your pack is much lighter than you remember. Just then, one of the items from your pack goes flying overhead. Monkeys are playing Keep Away with your missing things!

+

To get your stuff back, you need to be able to predict where the monkeys will throw your items. After some careful observation, you realize the monkeys operate based on how worried you are about each item.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day11;
+
+[ProblemName("Monkey in the Middle")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var monkeys = ParseMonkeys(input);
+        Run(20, monkeys, w => w / 3);
+        return GetMonkeyBusinessLevel(monkeys);
+    }
+
+    public object PartTwo(string input) {
+        var monkeys = ParseMonkeys(input);
+        var mod = monkeys.Aggregate(1, (mod, monkey) => mod * monkey.mod);
+        Run(10_000, monkeys, w => w % mod);
+        return GetMonkeyBusinessLevel(monkeys);
+    }
+
+    Monkey[] ParseMonkeys(string input) =>
+        input.Split("\n\n").Select(ParseMonkey).ToArray();
+
+    Monkey ParseMonkey(string input) {
+        var monkey = new Monkey();
+
+        foreach (var line in input.Split("\n")) {
+            var tryParse = LineParser(line);
+            if (tryParse(@"Monkey (\d+)", out var arg)) {
+                // pass
+            } else if (tryParse("Starting items: (.*)", out arg)) {
+                monkey.items = new Queue(arg.Split(", ").Select(long.Parse));
+            } else if (tryParse(@"Operation: new = old \* old", out _)) {
+                monkey.operation = old => old * old;
+            } else if (tryParse(@"Operation: new = old \* (\d+)", out arg)) {
+                monkey.operation = old => old * int.Parse(arg);
+            } else if (tryParse(@"Operation: new = old \+ (\d+)", out arg)) {
+                monkey.operation = old => old + int.Parse(arg);
+            } else if (tryParse(@"Test: divisible by (\d+)", out arg)) {
+                monkey.mod = int.Parse(arg);
+            } else if (tryParse(@"If true: throw to monkey (\d+)", out arg)) {
+                monkey.passToMonkeyIfDivides = int.Parse(arg);
+            } else if (tryParse(@"If false: throw to monkey (\d+)", out arg)) {
+                monkey.passToMonkeyOtherwise = int.Parse(arg);
+            } else {
+                throw new ArgumentException(line);
+            }
+        }
+        return monkey;
+    }
+
+    long GetMonkeyBusinessLevel(IEnumerable monkeys) => 
+        monkeys
+            .OrderByDescending(monkey => monkey.inspectedItems)
+            .Take(2)
+            .Aggregate(1L, (res, monkey) => res * monkey.inspectedItems);
+
+    void Run(int rounds, Monkey[] monkeys, Func updateWorryLevel) {
+        for (var i = 0; i < rounds; i++) {
+            foreach (var monkey in monkeys) {
+                while (monkey.items.Any()) {
+                    monkey.inspectedItems++;
+
+                    var item = monkey.items.Dequeue();
+                    item = monkey.operation(item);
+                    item = updateWorryLevel(item);
+
+                    var targetMonkey = item % monkey.mod == 0 ?
+                        monkey.passToMonkeyIfDivides :
+                        monkey.passToMonkeyOtherwise;
+
+                    monkeys[targetMonkey].items.Enqueue(item);
+                }
+            }
+        }
+    }
+
+    class Monkey {
+        public Queue items;
+        public Func operation;
+        public int inspectedItems;
+        public int mod;
+        public int passToMonkeyIfDivides, passToMonkeyOtherwise;
+    }
+
+    // converts a line into a tryParse-style parser function
+    TryParse LineParser(string line) {
+        bool match(string pattern, out string arg) {
+            var m = Regex.Match(line, pattern);
+            if (m.Success) {
+                arg = m.Groups[m.Groups.Count - 1].Value;
+                return true;
+            } else {
+                arg = "";
+                return false;
+            }
+        }
+        return match;
+    }
+    delegate bool TryParse(string pattern, out string arg);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/12/illustration.jpeg b/2022/12/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/12/illustration.jpeg differ diff --git a/2022/12/index.html b/2022/12/index.html new file mode 100644 index 00000000..5db674af --- /dev/null +++ b/2022/12/index.html @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/12 'Hill Climbing Algorithm'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/12

+

Hill Climbing Algorithm

+

in C#

+

+

by encse

+
+ +
+ +
+

You try contacting the Elves using your handheld device, but the river you're following must be too low to get a decent signal.

+

You ask the device for a heightmap of the surrounding area (your puzzle input). The heightmap shows the local area from above broken into a grid; the elevation of each square of the grid is given by a single lowercase letter, where a is the lowest elevation, b is the next-lowest, and so on up to the highest elevation, z.

+

Read the full puzzle.

+
+
namespace AdventOfCode.Y2022.Day12;
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+//
+// Standard breadth-first algorithm, starting from the goal node and walking backwards. 
+// I used a dictionary to represent valid coordinates, it's very handy when in need of
+// enumerating all coordinates or checking if we are stepping to valid location.
+//
+[ProblemName("Hill Climbing Algorithm")]
+class Solution : Solver {
+
+    // I feel like a cartographer today
+    record struct Coord(int lat, int lon);
+
+    // we have two 'char' like things, let's introduce wrappers to keep them well separated in code
+    record struct Symbol(char value);
+    record struct Elevation(char value);
+
+    // locations on the map will be represented by the following structure of points-of-interests.
+    record struct Poi(Symbol symbol, Elevation elevation, int distanceFromGoal);
+
+    Symbol startSymbol = new Symbol('S');
+    Symbol goalSymbol = new Symbol('E');
+    Elevation lowestElevation = new Elevation('a');
+    Elevation highestElevation = new Elevation('z');
+
+    public object PartOne(string input) =>
+        GetPois(input)
+            .Single(poi => poi.symbol == startSymbol)
+            .distanceFromGoal;
+
+    public object PartTwo(string input) =>
+        GetPois(input)
+            .Where(poi => poi.elevation == lowestElevation)
+            .Select(poi => poi.distanceFromGoal)
+            .Min();
+
+    IEnumerable GetPois(string input) {
+        var map = ParseMap(input);
+        var goal = map.Keys.Single(point => map[point] == goalSymbol);
+
+        // starting from the goal symbol compute shortest paths for each point of 
+        // the map using a breadth-first search.
+        var poiByCoord = new Dictionary() {
+            {goal, new Poi(goalSymbol, GetElevation(goalSymbol), 0)}
+        };
+
+        var q = new Queue();
+        q.Enqueue(goal);
+        while (q.Any()) {
+            var thisCoord = q.Dequeue();
+            var thisPoi = poiByCoord[thisCoord];
+
+            foreach (var nextCoord in Neighbours(thisCoord).Where(map.ContainsKey)) {
+                if (poiByCoord.ContainsKey(nextCoord)) {
+                    continue;
+                }
+
+                var nextSymbol = map[nextCoord];
+                var nextElevation = GetElevation(nextSymbol);
+
+                if (thisPoi.elevation.value - nextElevation.value <= 1) {
+                    poiByCoord[nextCoord] = new Poi(
+                        symbol: nextSymbol,
+                        elevation: nextElevation,
+                        distanceFromGoal: thisPoi.distanceFromGoal + 1
+                    );
+                    q.Enqueue(nextCoord);
+                }
+            }
+
+        }
+        return poiByCoord.Values;
+    }
+
+    Elevation GetElevation(Symbol symbol) =>
+        symbol.value switch {
+            'S' => lowestElevation,
+            'E' => highestElevation,
+            _ => new Elevation(symbol.value)
+        };
+
+    // locations are parsed into a dictionary so that valid coordinates and
+    // neighbours are easy to deal with
+    ImmutableDictionary ParseMap(string input) {
+        var lines = input.Split("\n");
+        return (
+            from y in Enumerable.Range(0, lines.Length)
+            from x in Enumerable.Range(0, lines[0].Length)
+            select new KeyValuePair(
+                new Coord(x, y), new Symbol(lines[y][x])
+            )
+        ).ToImmutableDictionary();
+    }
+
+    IEnumerable Neighbours(Coord coord) =>
+        new[] {
+           coord with {lat = coord.lat + 1},
+           coord with {lat = coord.lat - 1},
+           coord with {lon = coord.lon + 1},
+           coord with {lon = coord.lon - 1},
+        };
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/13/illustration.jpeg b/2022/13/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/13/illustration.jpeg differ diff --git a/2022/13/index.html b/2022/13/index.html new file mode 100644 index 00000000..49ccfc90 --- /dev/null +++ b/2022/13/index.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/13 'Distress Signal'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/13

+

Distress Signal

+

in C#

+

+

by encse

+
+ +
+ +
+

You climb the hill and again try contacting the Elves. However, you instead receive a signal you weren't expecting: a distress signal.

+

Your handheld device must still not be working properly; the packets from the distress signal got decoded out of order. You'll need to re-order the list of received packets (your puzzle input) to decode the message.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Text.Json.Nodes;
+
+namespace AdventOfCode.Y2022.Day13;
+
+// NOTES: I don't use C# during the year, so I didn't know which Json parser to use 
+// and first went with System.Text.Json, then found a solution on reddit which uses 
+// System.Text.Json.Nodes and could improve my coding a bit.
+// 
+// For part2: I couldn't find a version of OrderBy() that would take a simple comparator 
+// function, and I didn't want to implement a full blown IComparer interface. Then 
+// realised that List has a Sort function which works with just a simple delegate. 
+// Unfortunately it's a void function so there is no way to chain the result further. 
+// So much about using just one expression for Part2.
+// 
+// I didn't have a great idea to deal with the 1 based indexing, but I'm satisfied with 
+// how this looks in general. Well mostly. I managed to overgolf the compare function 
+// at the end...
+// 
+[ProblemName("Distress Signal")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        GetPackets(input)
+            .Chunk(2)
+            .Select((pair, index) => Compare(pair[0], pair[1]) < 0 ? index + 1 : 0)
+            .Sum();
+
+    public object PartTwo(string input) {
+        var divider = GetPackets("[[2]]\n[[6]]").ToList();
+        var packets = GetPackets(input).Concat(divider).ToList();
+        packets.Sort(Compare);
+        return (packets.IndexOf(divider[0]) + 1) * (packets.IndexOf(divider[1]) + 1);
+    }
+
+    IEnumerable GetPackets(string input) =>
+        from line in input.Split("\n") 
+        where !string.IsNullOrEmpty(line) 
+        select JsonNode.Parse(line);
+
+    int Compare(JsonNode nodeA, JsonNode nodeB) {
+        if (nodeA is JsonValue && nodeB is JsonValue) {
+            return (int)nodeA - (int)nodeB;
+        } else {
+            // It's AoC time, let's exploit FirstOrDefault! 
+            // 😈 if all items are equal, compare the length of the arrays 
+            var arrayA = nodeA as JsonArray ?? new JsonArray((int)nodeA);
+            var arrayB = nodeB as JsonArray ?? new JsonArray((int)nodeB);
+            return Enumerable.Zip(arrayA, arrayB)
+                .Select(p => Compare(p.First, p.Second))
+                .FirstOrDefault(c => c != 0, arrayA.Count - arrayB.Count);
+        }
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/14/illustration.jpeg b/2022/14/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/14/illustration.jpeg differ diff --git a/2022/14/index.html b/2022/14/index.html new file mode 100644 index 00000000..4c10af97 --- /dev/null +++ b/2022/14/index.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/14 'Regolith Reservoir'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/14

+

Regolith Reservoir

+

in C#

+

+

by encse

+
+ +
+ +
+

The distress signal leads you to a giant waterfall! Actually, hang on - the signal seems like it's coming from the waterfall itself, and that doesn't make any sense. However, you do notice a little path that leads behind the waterfall.

+

Correction: the distress signal leads you behind a giant waterfall! There seems to be a large cave system here, and the signal definitely leads further inside.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+namespace AdventOfCode.Y2022.Day14;
+
+[ProblemName("Regolith Reservoir")]
+class Solution : Solver {
+    public object PartOne(string input) 
+        => new Cave(input, hasFloor: false).FillWithSand(new Complex(500, 0));
+
+    public object PartTwo(string input)
+         => new Cave(input, hasFloor: true).FillWithSand(new Complex(500, 0));
+}
+
+class Cave {
+    bool hasFloor;
+
+    Dictionary map;
+    int maxImaginary;
+
+    public Cave(string input, bool hasFloor) {
+        this.hasFloor = hasFloor;
+        this.map = new Dictionary();
+
+        foreach (var line in input.Split("\n")) {
+            var steps = (
+                from step in line.Split(" -> ")
+                let parts = step.Split(",")
+                select new Complex(int.Parse(parts[0]), int.Parse(parts[1]))
+            ).ToArray();
+
+            for (var i = 1; i < steps.Length; i++) {
+                FillWithRocks(steps[i - 1], steps[i]);
+            }
+        }
+
+        this.maxImaginary = (int)this.map.Keys.Select(pos => pos.Imaginary).Max();
+    }
+
+    // Adds a line of rocks to the cave
+    public int FillWithRocks(Complex from, Complex to) {
+        var dir = new Complex(
+            Math.Sign(to.Real - from.Real),
+            Math.Sign(to.Imaginary - from.Imaginary)
+        );
+
+        var steps = 0;
+        for (var pos = from; pos != to + dir; pos += dir) {
+            map[pos] = '#';
+            steps ++;
+        }
+        return steps;
+    }
+
+    // Sand flows into the cave from the source location, returns the amount of sand added.
+    public int FillWithSand(Complex sandSource) {
+
+        while (true) {
+            var location = SimulateFallingSand(sandSource);
+
+            // already has sand there
+            if (map.ContainsKey(location)) {
+                break;
+            }
+
+            // flows out into the void
+            if (!hasFloor && location.Imaginary == maxImaginary + 1) {
+                break;
+            }
+
+            map[location] = 'o';
+        }
+
+        return map.Values.Count(x => x == 'o');
+    }
+
+    // Returns the final location of a falling unit of sand following the rules of cave physics
+    Complex SimulateFallingSand(Complex sand) {
+        var down = new Complex(0, 1);
+        var left = new Complex(-1, 1);
+        var right = new Complex(1, 1);
+
+        while (sand.Imaginary < maxImaginary + 1) {
+            if (!map.ContainsKey(sand + down)) {
+                sand += down;
+            } else if (!map.ContainsKey(sand + left)) {
+                sand += left;
+            } else if (!map.ContainsKey(sand + right)) {
+                sand += right;
+            } else {
+                break;
+            }
+        }
+        return sand;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/15/illustration.jpeg b/2022/15/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/15/illustration.jpeg differ diff --git a/2022/15/index.html b/2022/15/index.html new file mode 100644 index 00000000..c0101fbe --- /dev/null +++ b/2022/15/index.html @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/15 'Beacon Exclusion Zone'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/15

+

Beacon Exclusion Zone

+

in C#

+

+

by encse

+
+ +
+ +
+

You feel the ground rumble again as the distress signal leads you to a large network of subterranean tunnels. You don't have time to search them all, but you don't need to: your pack contains a set of deployable sensors that you imagine were originally built to locate lost Elves.

+

The sensors aren't very powerful, but that's okay; your handheld device indicates that you're close enough to the source of the distress signal to use them. You pull the emergency sensor system out of your pack, hit the big button on top, and the sensors zoom off down the tunnels.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day15;
+
+[ProblemName("Beacon Exclusion Zone")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var pairing = Parse(input).ToArray();
+
+        var rects = pairing.Select(pair => pair.ToRect()).ToArray();
+        var left = rects.Select(r => r.Left).Min();
+        var right = rects.Select(r => r.Right).Max();
+
+        var y = 2000000;
+        var res = 0;
+        for (var x = left; x <= right; x++) {
+            var pos = new Pos(x, y);
+            if (pairing.Any(pair => pair.beacon != pos && pair.InRange(pos))) {
+                res++;
+            }
+        }
+        return res;
+    }
+
+    public object PartTwo(string input) {
+        var pairing = Parse(input).ToArray();
+        var area = GetUncoveredAreas(pairing, new Rect(0, 0, 4000001, 4000001)).First();
+        return area.X * 4000000L + area.Y;
+    }
+
+
+    // Parse the 4 numbers with regex from each line and return the list of pairings
+    IEnumerable Parse(string input) {
+        foreach (var line in input.Split("\n")) {
+            var numbers = Regex.Matches(line, @"-?\d+").Select(m => int.Parse(m.Value)).ToArray();
+            yield return new Pair(
+                sensor: new Pos(numbers[0], numbers[1]),
+                beacon: new Pos(numbers[2], numbers[3])
+            );
+        }
+    }
+
+    // Do a quadtree style recursive check for uncovered areas with early exit
+    // when there is proof that the rectangle is fully covered / uncovered
+    IEnumerable GetUncoveredAreas(Pair[] pairing, Rect rect) {
+        // empty rectangle -> doesn't have uncovered areas 👍
+        if (rect.Width == 0 || rect.Height == 0) {
+            yield break;
+        }
+
+        // if all 4 corners of the rectangle are in range of one of the sensors -> it's covered 👍
+        foreach (var pair in pairing) {
+            if (rect.Corners.All(corner => pair.InRange(corner))) {
+                yield break;
+            }
+        }
+
+        // if the rectangle is 1x1 -> we just proved that it's uncovered 👍
+        if (rect.Width == 1 && rect.Height == 1) {
+            yield return rect;
+            yield break;
+        }
+
+        // otherwise split the rectangle into smaller parts and recurse
+        foreach (var rectT in rect.Split()) {
+            foreach (var area in GetUncoveredAreas(pairing, rectT)) {
+                yield return area;
+            }
+        }
+    }
+
+    // ---------
+
+    record struct Pos(int X, int Y);
+
+    // I don't have a better name for a sensor-bacon pair
+    record struct Pair(Pos sensor, Pos beacon) {
+        public int Radius = Manhattan(sensor, beacon);
+
+        public bool InRange(Pos pos) => Manhattan(pos, sensor) <= Radius;
+
+        // The smallest rectangle that covers the whole range of the pairing:
+        // ............................
+        // ..........====#====.........
+        // ..........===B##===.........
+        // ..........==#####==.........
+        // ..........=#######=.........
+        // ..........####S####.........
+        // ..........=#######=.........
+        // ..........==#####==.........
+        // ..........===###===.........
+        // ..........====#====.........
+        // ............................
+        public Rect ToRect() =>
+             new Rect(sensor.X - Radius, sensor.Y - Radius, 2 * Radius + 1, 2 * Radius + 1);
+
+        static int Manhattan(Pos p1, Pos p2) =>
+             Math.Abs(p1.X - p2.X) + Math.Abs(p1.Y - p2.Y);
+    }
+
+    record struct Rect(int X, int Y, int Width, int Height) {
+        public int Left => X;
+        public int Right => X + Width - 1;
+        public int Top => Y;
+        public int Bottom => Y + Height - 1;
+
+        public IEnumerable Corners {
+            get {
+                yield return new Pos(Left, Top);
+                yield return new Pos(Right, Top);
+                yield return new Pos(Right, Bottom);
+                yield return new Pos(Left, Bottom);
+            }
+        }
+
+        // Creates 4 smaller rectangles, might return empty ones with width or height == 0
+        public IEnumerable Split() {
+            var w0 = Width / 2;
+            var w1 = Width - w0;
+            var h0 = Height / 2;
+            var h1 = Height - h0;
+            yield return new Rect(Left, Top, w0, h0);
+            yield return new Rect(Left + w0, Top, w1, h0);
+            yield return new Rect(Left, Top + h0, w0, h1);
+            yield return new Rect(Left + w0, Top + h0, w1, h1);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/16/illustration.jpeg b/2022/16/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/16/illustration.jpeg differ diff --git a/2022/16/index.html b/2022/16/index.html new file mode 100644 index 00000000..207d7283 --- /dev/null +++ b/2022/16/index.html @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/16 'Proboscidea Volcanium'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/16

+

Proboscidea Volcanium

+

in C#

+

+

by encse

+
+ +
+ +
+

The sensors have led you to the origin of the distress signal: yet another handheld device, just like the one the Elves gave you. However, you don't see any Elves around; instead, the device is surrounded by elephants! They must have gotten lost in these tunnels, and one of the elephants apparently figured out how to turn on the distress signal.

+

The ground rumbles again, much stronger this time. What kind of cave is this, exactly? You scan the cave with your handheld device; it reports mostly igneous rock, some ash, pockets of pressurized gas, magma... this isn't just a cave, it's a volcano!

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day16;
+
+[ProblemName("Proboscidea Volcanium")]
+class Solution : Solver {
+
+    record Map(int[,] distances, Valve[] valves);
+    record Valve(int id, string name, int flowRate, string[] tunnels);
+
+    public object PartOne(string input) {
+        return Solve(input, true, 30);
+    }
+    public object PartTwo(string input) {
+        return Solve(input, false, 26);
+    }
+
+    int Solve(string input, bool humanOnly, int time) {
+        var map = Parse(input);
+        var start = map.valves.Single(x => x.name == "AA");
+        var valvesToOpen = map.valves.Where(valve => valve.flowRate > 0).ToArray();
+
+        var cache = new Dictionary();
+        if (humanOnly) {
+            return MaxFlow(cache, map, start, valvesToOpen.ToHashSet(), time);
+        } else {
+            return Pairings(valvesToOpen).Select(pairing =>
+                 MaxFlow(cache, map, start, pairing.human, time) +
+                 MaxFlow(cache, map, start, pairing.elephant, time)
+            ).Max();
+        }
+    }
+
+    // Divide the valves between human and elephant in all possible ways
+    IEnumerable<(HashSet human, HashSet elephant)> Pairings(Valve[] valves) {
+        var maxMask = 1 << (valves.Length - 1);
+
+        for (var mask = 0; mask < maxMask; mask++) {
+            var elephant = new HashSet();
+            var human = new HashSet();
+
+            elephant.Add(valves[0]);
+
+            for (var ivalve = 1; ivalve < valves.Length; ivalve++) {
+                if ((mask & (1 << ivalve)) == 0) {
+                    human.Add(valves[ivalve]);
+                } else {
+                    elephant.Add(valves[ivalve]);
+                }
+            }
+            yield return (human, elephant);
+        }
+    }
+
+    int MaxFlow(
+        Dictionary cache,
+        Map map,
+        Valve currentValve,
+        HashSet valves,
+        int remainingTime
+    ) {
+        string key =
+            remainingTime + "-" +
+            currentValve.id + "-" +
+            string.Join("-", valves.OrderBy(x => x.id).Select(x => x.id));
+
+        if (!cache.ContainsKey(key)) {
+            // current valve gives us this much flow:
+            var flowFromValve = currentValve.flowRate * remainingTime;
+
+            // determine best use of the remaining time:
+            var flowFromRest = 0;
+            foreach (var valve in valves.ToArray()) {
+                var distance = map.distances[currentValve.id, valve.id];
+
+                if (remainingTime >= distance + 1) {
+                    valves.Remove(valve);
+                    remainingTime -= distance + 1;
+
+                    flowFromRest = Math.Max(
+                        flowFromRest, MaxFlow(cache, map, valve, valves, remainingTime));
+
+                    remainingTime += distance + 1;
+                    valves.Add(valve);
+                }
+
+            }
+            cache[key] = flowFromValve + flowFromRest;
+        }
+        return cache[key];
+    }
+
+    Map Parse(string input) {
+        // Valve BB has flow rate=0; tunnels lead to valve CC
+        // Valve CC has flow rate=10; tunnels lead to valves DD, EE
+        var valveList = new List();
+        foreach (var line in input.Split("\n")) {
+            var name = Regex.Match(line, "Valve (.*) has").Groups[1].Value;
+            var flow = int.Parse(Regex.Match(line, @"\d+").Groups[0].Value);
+            var tunnels = Regex.Match(line, "to valves? (.*)").Groups[1].Value.Split(", ");
+            valveList.Add(new Valve(0, name, flow, tunnels));
+        }
+        var valves = valveList
+            .OrderByDescending(valve => valve.flowRate)
+            .Select((v, i) => v with { id = i })
+            .ToArray();
+
+        return new Map(ComputeDistances(valves), valves);
+    }
+
+    int[,] ComputeDistances(Valve[] valves) {
+        // Floyd-Warshall style distance calculation for every pair of valves.
+        // See https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
+        // The only change is that moving from i to i is not enabled.
+        
+        // This is an O(n^3) algorithm, but we are dealing with a low n.
+        var n = valves.Length;
+
+        // Just "big enough" so that infinity + infinity still fits in an int.
+        var infinity = int.MaxValue / 2; 
+
+        var dist = new int[valves.Length, valves.Length];
+        for (var i = 0; i < n; i++) {
+            for (var j = 0; j < n; j++) {
+                var neighbours = valves[i].tunnels.Contains(valves[j].name);
+                dist[i, j] = neighbours ? 1 : infinity;
+            }
+        }
+
+        for (var k = 0; k < n; k++) {
+            for (var i = 0; i < n; i++) {
+                for (var j = 0; j < n; j++) {
+                    dist[i, j] = Math.Min(dist[i,j], dist[i, k] + dist[k, j]);
+                }
+            }
+        }
+        return dist;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/17/illustration.jpeg b/2022/17/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/17/illustration.jpeg differ diff --git a/2022/17/index.html b/2022/17/index.html new file mode 100644 index 00000000..933bb255 --- /dev/null +++ b/2022/17/index.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/17 'Pyroclastic Flow'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/17

+

Pyroclastic Flow

+

in C#

+

+

by encse

+
+ +
+ +
+

Your handheld device has located an alternative exit from the cave for you and the elephants. The ground is rumbling almost continuously now, but the strange valves bought you some time. It's definitely getting warmer in here, though.

+

The tunnels eventually open into a very tall, narrow chamber. Large, oddly-shaped rocks are falling into the chamber from above, presumably due to all the rumbling. If you can't work out where the rocks will fall next, you might be crushed!

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day17;
+
+[ProblemName("Pyroclastic Flow")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return new Tunnel(input, 100).AddRocks(2022).Height;
+    }
+
+    public object PartTwo(string input) {
+        return new Tunnel(input, 100).AddRocks(1000000000000).Height;
+    }
+
+    class Tunnel {
+        int linesToStore;
+
+        List lines = new List();
+        long linesNotStored;
+
+        public long Height => lines.Count + linesNotStored;
+
+        string[][] rocks;
+        string jets;
+        ModCounter irock;
+        ModCounter ijet;
+
+        // Simulation runs so that only the top N lines are kept in the tunnel. 
+        // This is a practical constant, there is NO THEORY BEHIND it.
+        public Tunnel(string jets, int linesToStore) {
+            this.linesToStore = linesToStore;
+            rocks = new string[][]{
+                new []{"####"},
+                new []{" # ", "###", " # "},
+                new []{"  #", "  #", "###"},
+                new []{"#", "#", "#", "#"},
+                new []{"##", "##"}
+            };
+            this.irock = new ModCounter(0, rocks.Length);
+
+            this.jets = jets;
+            this.ijet = new ModCounter(0, jets.Length);
+        }
+
+        public Tunnel AddRocks(long rocksToAdd) {
+            // We are adding rocks one by one until we find a recurring pattern.
+
+            // Then we can jump forward full periods with just increasing the height 
+            // of the cave: the top of the cave should look the same after a full period
+            // so no need to simulate he rocks anymore. 
+
+            // Then we just add the remaining rocks. 
+
+            var seen = new Dictionary();
+            while (rocksToAdd > 0) {
+                var hash = string.Join("", lines.SelectMany(ch => ch));
+                if (seen.TryGetValue(hash, out var cache)) {
+                    // we have seen this pattern, advance forwad as much as possible
+                    var heightOfPeriod = this.Height - cache.height;
+                    var periodLength = cache.rocksToAdd - rocksToAdd;
+                    linesNotStored += (rocksToAdd / periodLength) * heightOfPeriod;
+                    rocksToAdd = rocksToAdd % periodLength;
+                    break;
+                } else {
+                    seen[hash] = (rocksToAdd, this.Height);
+                    this.AddRock();
+                    rocksToAdd--;
+                }
+            }
+
+            while (rocksToAdd > 0) {
+                this.AddRock();
+                rocksToAdd--;
+            }
+            return this;
+        }
+
+        // Adds one rock to the cave
+        public Tunnel AddRock() {
+            var rock = rocks[(int)irock++];
+
+            // make room of 3 lines + the height of the rock
+            for (var i = 0; i < rock.Length + 3; i++) {
+                lines.Insert(0, "|       |".ToArray());
+            }
+
+            // simulate falling
+            var pos = new Pos(0, 3);
+            while (true) {
+                var jet = jets[(int)ijet++];
+                if (jet == '>' && !Hit(rock, pos.Right)) {
+                    pos = pos.Right;
+                } else if (jet == '<' && !Hit(rock, pos.Left)) {
+                    pos = pos.Left;
+                }
+                if (Hit(rock, pos.Below)) {
+                    break;
+                }
+                pos = pos.Below;
+            }
+
+            Draw(rock, pos);
+            return this;
+        }
+
+        // tells if a rock can be placed in the given location or hits something
+        bool Hit(string[] rock, Pos pos) =>
+            Area(rock).Any(pt =>
+                Get(rock, pt) == '#' &&
+                Get(lines, pt + pos) != ' '
+            );
+
+        void Draw(string[] rock, Pos pos) {
+            // draws a rock pattern into the cave at the given x,y coordinates,
+            foreach (var pt in Area(rock)) {
+                if (Get(rock, pt) == '#') {
+                    Set(lines, pt + pos, '#');
+                }
+            }
+           
+            // remove empty lines from the top
+            while (!lines[0].Contains('#')) {
+                lines.RemoveAt(0);
+            }
+
+            // keep the tail
+            while (lines.Count > linesToStore) {
+                lines.RemoveAt(lines.Count - 1);
+                linesNotStored ++;
+            }
+        }
+    }
+
+    static IEnumerable Area(string[] mat) =>
+        from irow in Enumerable.Range(0, mat.Length)
+        from icol in Enumerable.Range(0, mat[0].Length)
+        select new Pos(irow, icol);
+
+    static char Get(IEnumerable> mat, Pos pos) {
+        return (mat.ElementAtOrDefault(pos.irow) ?? "#########").ElementAt(pos.icol);
+    }
+
+    static char Set(IList mat, Pos pos, char ch) {
+        return mat[pos.irow][pos.icol] = ch;
+    }
+
+    record struct Pos(int irow, int icol) {
+        public Pos Left => new Pos(irow, icol - 1);
+        public Pos Right => new Pos(irow, icol + 1);
+        public Pos Below => new Pos(irow + 1, icol);
+        public static Pos operator +(Pos posA, Pos posB) =>
+            new Pos(posA.irow + posB.irow, posA.icol + posB.icol);
+    }
+
+    record struct ModCounter(int index, int mod) {
+        public static explicit operator int(ModCounter c) => c.index;
+        public static ModCounter operator ++(ModCounter c) =>
+            c with { index = c.index == c.mod - 1 ? 0 : c.index + 1 };
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/18/illustration.jpeg b/2022/18/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/18/illustration.jpeg differ diff --git a/2022/18/index.html b/2022/18/index.html new file mode 100644 index 00000000..a3ebdaab --- /dev/null +++ b/2022/18/index.html @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/18 'Boiling Boulders'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/18

+

Boiling Boulders

+

in C#

+

+

by encse

+
+ +
+ +
+

You and the elephants finally reach fresh air. You've emerged near the base of a large volcano that seems to be actively erupting! Fortunately, the lava seems to be flowing away from you and toward the ocean.

+

Bits of lava are still being ejected toward you, so you're sheltering in the cavern exit a little longer. Outside the cave, you can see the lava landing in a pond and hear it loudly hissing as it solidifies.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day18;
+
+[ProblemName("Boiling Boulders")]
+class Solution : Solver {
+
+    record class Point(int x, int y, int z);
+    record class Bounds(Point min, Point max);
+
+    public object PartOne(string input) {
+        var lavaLocations = GetLavaLocations(input).ToHashSet();
+        return lavaLocations.SelectMany(Neighbours).Count(p => !lavaLocations.Contains(p));
+    }
+
+    public object PartTwo(string input) {
+        var lavaLocations = GetLavaLocations(input).ToHashSet();
+        var bounds = GetBounds(lavaLocations);
+        var waterLocations = FillWithWater(bounds.min, bounds, lavaLocations);
+        return lavaLocations.SelectMany(Neighbours).Count(p => waterLocations.Contains(p));
+    }
+    
+    // fills a region with water starting from the given point and avoiding lavalLocations
+    // standard flood fill algorithm
+    HashSet FillWithWater(Point from, Bounds bounds, HashSet lavaLocations) {
+        var result = new HashSet();
+        var q = new Queue();
+
+        result.Add(from);
+        q.Enqueue(from);
+        while (q.Any()) {
+            var water = q.Dequeue();
+            foreach (var neighbour in Neighbours(water)) {
+                if (!result.Contains(neighbour) && 
+                    Within(bounds, neighbour) && 
+                    !lavaLocations.Contains(neighbour)
+                ) {
+                    result.Add(neighbour);
+                    q.Enqueue(neighbour);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    IEnumerable GetLavaLocations(string input) =>
+        from line in input.Split("\n")
+        let coords = line.Split(",").Select(int.Parse).ToArray()
+        select new Point(coords[0], coords[1], coords[2]);
+
+    // returns the enclosing box of a point set, the min and max values are padded by one
+    Bounds GetBounds(IEnumerable points) {
+        var minX = points.Select(p => p.x).Min() - 1;
+        var maxX = points.Select(p => p.x).Max() + 1;
+
+        var minY = points.Select(p => p.y).Min() - 1;
+        var maxY = points.Select(p => p.y).Max() + 1;
+
+        var minZ = points.Select(p => p.z).Min() - 1;
+        var maxZ = points.Select(p => p.z).Max() + 1;
+
+        return new Bounds(new Point(minX, minY, minZ), new Point(maxX, maxY, maxZ));
+    }
+
+    bool Within(Bounds bounds, Point point) =>
+        bounds.min.x <= point.x && point.x <= bounds.max.x &&
+        bounds.min.y <= point.y && point.y <= bounds.max.y &&
+        bounds.min.z <= point.z && point.z <= bounds.max.z;
+
+    IEnumerable Neighbours(Point point) =>
+        new[]{
+           point with { x = point.x - 1 },
+           point with { x = point.x + 1 },
+           point with { y = point.y - 1 },
+           point with { y = point.y + 1 },
+           point with { z = point.z - 1 },
+           point with { z = point.z + 1 }
+        };
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/19/illustration.jpeg b/2022/19/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/19/illustration.jpeg differ diff --git a/2022/19/index.html b/2022/19/index.html new file mode 100644 index 00000000..d7d327e0 --- /dev/null +++ b/2022/19/index.html @@ -0,0 +1,472 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/19 'Not Enough Minerals'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/19

+

Not Enough Minerals

+

in C#

+

+

by encse

+
+ +
+ +
+

Your scans show that the lava did indeed form obsidian!

+

The wind has changed direction enough to stop sending lava droplets toward you, so you and the elephants exit the cave. As you do, you notice a collection of geodes around the pond. Perhaps you could use the obsidian to create some geode-cracking robots and break them open?

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day19;
+
+[ProblemName("Not Enough Minerals")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var res = 0;
+        foreach (var blueprint in Parse(input).Where(bp => bp.id < 100)) {
+            var m = MaxGeodes(blueprint, 24);
+            res += blueprint.id * m;
+        }
+        return res;
+    }
+
+    public object PartTwo(string input) {
+        var res = 1;
+        foreach (var blueprint in Parse(input).Where(bp => bp.id <= 3)) {
+            var m = MaxGeodes(blueprint, 32);
+            res *= m;
+        }
+        return res;
+    }
+
+    // Priority queue based maximum search with LOTS OF PRUNING
+    private int MaxGeodes(Blueprint blueprint, int timeLimit) {
+        var q = new PriorityQueue();
+        var seen = new HashSet();
+
+        enqueue(new State(
+            remainingTime: timeLimit, 
+            available: Nothing, 
+            producing: Ore, 
+            dontBuild: 0
+        ));
+
+        var max = 0;
+        while (q.Count > 0) {
+            var state = q.Dequeue();
+
+            // Queue is ordered by potentialGeodeCount, there is
+            // no point in investigating the remaining items.
+            if (potentialGeodeCount(state) < max) {
+                break;
+            }
+
+            if (!seen.Contains(state)) {
+                seen.Add(state);
+
+                if (state.remainingTime == 0) {
+                    // time is off, just update max
+                    max = Math.Max(max, state.available.geode);
+                } else {
+                    // What robots can be created from the available materials?
+                    var buildableRobots = blueprint.robots
+                        .Where(robot => state.available >= robot.cost)
+                        .ToArray();
+
+                    // 1) build one of them right away
+                    foreach (var robot in buildableRobots) {
+                        if (worthBuilding(state, robot)) {
+                            enqueue(state with {
+                                remainingTime = state.remainingTime - 1,
+                                available = state.available + state.producing - robot.cost,
+                                producing = state.producing + robot.producing,
+                                dontBuild = 0
+                            });
+                        }
+                    }
+
+                    // 2) or wait until next round for more robot types. Don't postpone
+                    //    building of robots which are already available. This is a very
+                    //    very important prunning step. It's about 25 times faster if we 
+                    //    do it this way.
+                    enqueue(
+                        state with {
+                            remainingTime = state.remainingTime - 1,
+                            available = state.available + state.producing,
+                            dontBuild = buildableRobots.Select(robot => robot.id).Sum(),
+                        }
+                    );
+                }
+            }
+        }
+
+        return max;
+
+        // ------- 
+
+        // Upper limit for the maximum geodes we reach when starting from this state. 
+        // Let's be optimistic and suppose that in each step we will be able to build 
+        // a new geode robot...
+        int potentialGeodeCount(State state) {
+            // sum of [state.producing.geode .. state.producing.geode + state.remainingTime - 1]
+            var future = 
+                (2 * state.producing.geode + state.remainingTime - 1) * state.remainingTime / 2;
+            return state.available.geode + future;
+        }
+
+        bool worthBuilding(State state, Robot robot) {
+            // We can explicitly ignore building some robots. 
+            // Robot ids are powers of 2 used as flags in the dontBuild integer.
+            if ((state.dontBuild & robot.id) != 0) {
+                return false;
+            }
+
+            // Our factory can build just a single robot in a round. This gives as 
+            // a prunning condition. Producing more material in a round that we can 
+            // spend on building a new robot is worthless.
+            return state.producing + robot.producing <= blueprint.maxCost;
+        }
+
+        // Just add an item to the search queue, use -potentialGeodeCount as priority 
+        void enqueue(State state) {
+            q.Enqueue(state, -potentialGeodeCount(state));
+        }
+    }
+
+    IEnumerable Parse(string input) {
+        foreach (var line in input.Split("\n")) {
+            var numbers = Regex.Matches(line, @"(\d+)").Select(x => int.Parse(x.Value)).ToArray();
+            yield return new Blueprint(
+                id: numbers[0],
+                new Robot(id: 1, producing: Ore, cost: numbers[1] * Ore),
+                new Robot(id: 2, producing: Clay, cost: numbers[2] * Ore),
+                new Robot(id: 4, producing: Obsidian, cost: numbers[3] * Ore + numbers[4] * Clay),
+                new Robot(id: 8, producing: Geode, cost: numbers[5] * Ore + numbers[6] * Obsidian)
+            );
+        }
+    }
+
+    static Material Nothing = new Material(0, 0, 0, 0);
+    static Material Ore = new Material(1, 0, 0, 0);
+    static Material Clay = new Material(0, 1, 0, 0);
+    static Material Obsidian = new Material(0, 0, 1, 0);
+    static Material Geode = new Material(0, 0, 0, 1);
+
+    record Material(int ore, int clay, int obsidian, int geode) {
+        public static Material operator *(int m, Material a) {
+            return new Material(m * a.ore, m * a.clay, m * a.obsidian, m * a.geode);
+        }
+        public static Material operator +(Material a, Material b) {
+            return new Material(
+                a.ore + b.ore,
+                a.clay + b.clay,
+                a.obsidian + b.obsidian,
+                a.geode + b.geode
+            );
+        }
+
+        public static Material operator -(Material a, Material b) {
+            return new Material(
+                a.ore - b.ore,
+                a.clay - b.clay,
+                a.obsidian - b.obsidian,
+                a.geode - b.geode
+            );
+        }
+
+        public static bool operator <=(Material a, Material b) {
+            return
+                a.ore <= b.ore &&
+                a.clay <= b.clay &&
+                a.obsidian <= b.obsidian &&
+                a.geode <= b.geode;
+        }
+
+        public static bool operator >=(Material a, Material b) {
+            return
+                a.ore >= b.ore &&
+                a.clay >= b.clay &&
+                a.obsidian >= b.obsidian &&
+                a.geode >= b.geode;
+        }
+    }
+
+    record Robot(int id, Material cost, Material producing);
+    record State(int remainingTime, Material available, Material producing, int dontBuild);
+    record Blueprint(int id, params Robot[] robots) {
+        public Material maxCost = new Material(
+            ore: robots.Select(robot => robot.cost.ore).Max(),
+            clay: robots.Select(robot => robot.cost.clay).Max(),
+            obsidian: robots.Select(robot => robot.cost.obsidian).Max(),
+            geode: int.MaxValue
+        );
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/2/illustration.jpeg b/2022/2/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/2/illustration.jpeg differ diff --git a/2022/2/index.html b/2022/2/index.html new file mode 100644 index 00000000..30ef3828 --- /dev/null +++ b/2022/2/index.html @@ -0,0 +1,345 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/2 'Rock Paper Scissors'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/2

+

Rock Paper Scissors

+

in C#

+

+

by encse

+
+ +
+ +
+

The Elves begin to set up camp on the beach. To decide whose tent gets to be closest to the snack storage, a giant Rock Paper Scissors tournament is already in progress.

+

Rock Paper Scissors is a game between two players. Each game contains many rounds; in each round, the players each simultaneously choose one of Rock, Paper, or Scissors using a hand shape. Then, a winner for that round is selected: Rock defeats Scissors, Scissors defeats Paper, and Paper defeats Rock. If both players choose the same shape, the round instead ends in a draw.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day02;
+
+[ProblemName("Rock Paper Scissors")]
+class Solution : Solver {
+
+    // There are many obscure ways of solving this challenge. You can use 
+    // mod 3 arithmetic or play with ASCII encoding. This approach is more 
+    // explicit. I think it is as simple as it gets.
+
+    // We parse the input lines into a pair of Rock/Paper/Scissors signs 
+    // represented by 1,2,3 (the values from the problem description), 
+    // calculate the score for each pair and sum it up.
+
+    // Part one and two differs only in the decoding of the X, Y and Z signs.
+
+    enum Sign {
+        Rock = 1,
+        Paper = 2,
+        Scissors = 3,
+    }
+
+    public object PartOne(string input) => Total(input, Elf, Human1);
+    
+    public object PartTwo(string input) => Total(input, Elf, Human2);
+
+    Sign Elf(string line) =>
+        line[0] == 'A' ? Sign.Rock :
+        line[0] == 'B' ? Sign.Paper :
+        line[0] == 'C' ? Sign.Scissors :
+                         throw new ArgumentException(line);
+
+    Sign Human1(string line) =>   
+        line[2] == 'X' ? Sign.Rock :
+        line[2] == 'Y' ? Sign.Paper :
+        line[2] == 'Z' ? Sign.Scissors :
+                         throw new ArgumentException(line);
+
+    Sign Human2(string line) =>   
+        line[2] == 'X' ? Next(Next(Elf(line))): // elf wins
+        line[2] == 'Y' ? Elf(line) :            // draw
+        line[2] == 'Z' ? Next(Elf(line)) :      // you win
+                         throw new ArgumentException(line);
+          
+    int Total(string input, Func elf, Func human) =>
+        input
+            .Split("\n")
+            .Select(line => Score(elf(line), human(line)))
+            .Sum();
+
+    int Score(Sign elfSign, Sign humanSign) =>
+        humanSign == Next(elfSign)       ? 6 + (int)humanSign : // human wins
+        humanSign == elfSign             ? 3 + (int)humanSign : // draw
+        humanSign == Next(Next(elfSign)) ? 0 + (int)humanSign : // elf wins
+                                          throw new ArgumentException();
+
+    Sign Next(Sign sign) => 
+        sign == Sign.Rock     ? Sign.Paper : 
+        sign == Sign.Paper    ? Sign.Scissors : 
+        sign == Sign.Scissors ? Sign.Rock : 
+                                throw new ArgumentException();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/20/illustration.jpeg b/2022/20/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/20/illustration.jpeg differ diff --git a/2022/20/index.html b/2022/20/index.html new file mode 100644 index 00000000..372d841f --- /dev/null +++ b/2022/20/index.html @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/20 'Grove Positioning System'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/20

+

Grove Positioning System

+

in C#

+

+

by encse

+
+ +
+ +
+

It's finally time to meet back up with the Elves. When you try to contact them, however, you get no reply. Perhaps you're out of range?

+

You know they're headed to the grove where the star fruit grows, so if you can figure out where that is, you should be able to meet back up with them.

+

Read the full puzzle.

+
+
using System.Linq;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2022.Day20;
+
+[ProblemName("Grove Positioning System")]
+class Solution : Solver {
+
+    record Data(int idx, long num);
+
+    public object PartOne(string input) =>
+         GetGrooveCoordinates(Mix(Parse(input, 1)));
+
+    public object PartTwo(string input) {
+        var data = Parse(input, 811589153L);
+        for (var i = 0; i < 10; i++) {
+            data = Mix(data);
+        }
+        return GetGrooveCoordinates(data);
+    }
+
+    List Parse(string input, long m) =>
+        input
+            .Split("\n")
+            .Select((line, idx) => new Data(idx, long.Parse(line) * m))
+            .ToList();
+
+    List Mix(List numsWithIdx) {
+        var mod = numsWithIdx.Count - 1;
+        for (var idx = 0; idx < numsWithIdx.Count; idx++) {
+            var srcIdx = numsWithIdx.FindIndex(x => x.idx == idx);
+            var num = numsWithIdx[srcIdx];
+
+            var dstIdx = (srcIdx + num.num) % mod;
+            if (dstIdx < 0) {
+                dstIdx += mod;
+            }
+
+            numsWithIdx.RemoveAt(srcIdx);
+            numsWithIdx.Insert((int)dstIdx, num);
+        }
+        return numsWithIdx;
+    }
+
+    long GetGrooveCoordinates(List numsWithIdx) {
+        var idx = numsWithIdx.FindIndex(x => x.num == 0);
+        return (
+            numsWithIdx[(idx + 1000) % numsWithIdx.Count].num +
+            numsWithIdx[(idx + 2000) % numsWithIdx.Count].num +
+            numsWithIdx[(idx + 3000) % numsWithIdx.Count].num
+        );
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/21/illustration.jpeg b/2022/21/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/21/illustration.jpeg differ diff --git a/2022/21/index.html b/2022/21/index.html new file mode 100644 index 00000000..3e4057ca --- /dev/null +++ b/2022/21/index.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/21 'Monkey Math'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/21

+

Monkey Math

+

in C#

+

+

by encse

+
+ +
+ +
+

The monkeys are back! You're worried they're going to try to steal your stuff again, but it seems like they're just holding their ground and making various monkey noises at you.

+

Eventually, one of the elephants realizes you don't speak monkey and comes over to interpret. As it turns out, they overheard you talking about trying to find the grove; they can show you a shortcut if you answer their riddle.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day21;
+
+[ProblemName("Monkey Math")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return Parse(input, "root", false).Simplify();
+    }
+
+    public object PartTwo(string input) {
+        var expr = Parse(input, "root", true) as Eq;
+
+        while (!(expr.left is Var)) {
+            expr = Solve(expr);
+        }
+        return expr.right;
+    }
+
+    // One step in rearranging the equation to  =  form.
+    // It is supposed that there is only one variable occurrence in the whole 
+    // expression tree.
+    Eq Solve(Eq eq) =>
+        eq.left switch {
+            Op(Const l, "+", Expr r) => new Eq(r, new Op(eq.right, "-", l).Simplify()),
+            Op(Const l, "*", Expr r) => new Eq(r, new Op(eq.right, "/", l).Simplify()),
+            Op(Expr  l, "+", Expr r) => new Eq(l, new Op(eq.right, "-", r).Simplify()),
+            Op(Expr  l, "-", Expr r) => new Eq(l, new Op(eq.right, "+", r).Simplify()),
+            Op(Expr  l, "*", Expr r) => new Eq(l, new Op(eq.right, "/", r).Simplify()),
+            Op(Expr  l, "/", Expr r) => new Eq(l, new Op(eq.right, "*", r).Simplify()),
+            Const                    => new Eq(eq.right, eq.left),
+            _ => eq
+        };
+
+    // parses the input including the special rules for part2 
+    // and returns the expression with the specified name
+    Expr Parse(string input, string name, bool part2) {
+
+        var context = new Dictionary();
+        foreach (var line in input.Split("\n")) {
+            var parts = line.Split(" ");
+            context[parts[0].TrimEnd(':')] = parts.Skip(1).ToArray();
+        }
+
+        Expr buildExpr(string name) {
+            var parts = context[name];
+            if (part2) {
+                if (name == "humn") {
+                    return new Var("humn");
+                } else if (name == "root") {
+                    return new Eq(buildExpr(parts[0]), buildExpr(parts[2]));
+                }
+            }
+            if (parts.Length == 1) {
+                return new Const(long.Parse(parts[0]));
+            } else {
+                return new Op(buildExpr(parts[0]), parts[1], buildExpr(parts[2]));
+            }
+        }
+
+        return buildExpr(name);
+    }
+
+    // standard expression tree representation
+    interface Expr {
+        Expr Simplify();
+    }
+
+    record Const(long Value) : Expr {
+        public override string ToString() => Value.ToString();
+        public Expr Simplify() => this;
+    }
+
+    record Var(string name) : Expr {
+        public override string ToString() => name;
+        public Expr Simplify() => this;
+    }
+
+    record Eq(Expr left, Expr right) : Expr {
+        public override string ToString() => $"{left} == {right}";
+        public Expr Simplify() => new Eq(left.Simplify(), right.Simplify());
+    }
+
+    record Op(Expr left, string op, Expr right) : Expr {
+        public override string ToString() => $"({left}) {op} ({right})";
+        public Expr Simplify() {
+            return (left.Simplify(), op, right.Simplify()) switch {
+                (Const l, "+", Const r) => new Const(l.Value + r.Value),
+                (Const l, "-", Const r) => new Const(l.Value - r.Value),
+                (Const l, "*", Const r) => new Const(l.Value * r.Value),
+                (Const l, "/", Const r) => new Const(l.Value / r.Value),
+                (Expr l, _, Expr r) => new Op(l, op, r),
+            };
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/22/illustration.jpeg b/2022/22/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/22/illustration.jpeg differ diff --git a/2022/22/index.html b/2022/22/index.html new file mode 100644 index 00000000..1784453b --- /dev/null +++ b/2022/22/index.html @@ -0,0 +1,471 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/22 'Monkey Map'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/22

+

Monkey Map

+

in C#

+

+

by encse

+
+ +
+ +
+

The monkeys take you on a surprisingly easy trail through the jungle. They're even going in roughly the right direction according to your handheld device's Grove Positioning System.

+

As you walk, the monkeys explain that the grove is protected by a force field. To pass through the force field, you have to enter a password; doing so involves tracing a specific path on a strangely-shaped board.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day22;
+
+[ProblemName("Monkey Map")]
+class Solution : Solver {
+    /*
+        The cube is unfolded like this. Each letter identifies an 50x50 square 
+        in the input:
+                 AB
+                 C 
+                DE
+                F 
+        A topology map tells us how cube sides are connected. For example in 
+        case of part 1 the line "A -> B0 C0 B0 E0" means that if we go to the 
+        right from A we get to B, C is down, moving to the left we find B again, 
+        and moving up from A we get to E. The order of directions is always 
+        right, down, left and up.
+
+        The number next to the letter tells us how many 90 degrees we need to 
+        rotate the destination square to point upwards. In case of part 1 we 
+        don't need to rotate so the number is always zero. In part 2 there is 
+        "A -> B0 C0 D2 F1" which means that if we are about to move up from A we 
+        get to F, but F is rotated to the right once, likewise D2 means that D 
+        is on the left of A and it is up side down.
+
+        This mapping was generated from a paper model.
+    */
+
+    public object PartOne(string input) => Solve(
+        input,
+        """"
+        A -> B0 C0 B0 E0
+        B -> A0 B0 A0 B0
+        C -> C0 E0 C0 A0
+        D -> E0 F0 E0 F0
+        E -> D0 A0 D0 C0
+        F -> F0 D0 F0 D0
+        """"
+    );
+    public object PartTwo(string input) => Solve(
+        input,
+        """
+        A -> B0 C0 D2 F1
+        B -> E2 C1 A0 F0
+        C -> B3 E0 D3 A0
+        D -> E0 F0 A2 C1
+        E -> B2 F1 D0 C0
+        F -> E3 B0 A3 D0
+        """
+    );
+
+    const int blockSize = 50;
+    const int right = 0;
+    const int down = 1;
+    const int left = 2;
+    const int up = 3;
+
+    int Solve(string input, string topology) {
+        var (map, cmds) = Parse(input);
+        var state = new State("A", new Coord(0, 0), right);
+
+        foreach (var cmd in cmds) {
+            switch (cmd) {
+                case Left:
+                    state = state with { dir = (state.dir + 3) % 4 };
+                    break;
+                case Right:
+                    state = state with { dir = (state.dir + 1) % 4 };
+                    break;
+                case Forward(var n):
+                    for (var i = 0; i < n; i++) {
+                        var stateNext = Step(topology, state);
+                        var global = ToGlobal(stateNext);
+                        if (map[global.irow][global.icol] == '.') {
+                            state = stateNext;
+                        } else {
+                            break;
+                        }
+                    }
+                    break;
+            }
+        }
+
+        return 1000 * (ToGlobal(state).irow + 1) + 
+                  4 * (ToGlobal(state).icol + 1) + 
+                      state.dir;
+    }
+
+    Coord ToGlobal(State state) => 
+        state.block switch {
+            "A" => state.coord + new Coord(0, blockSize),
+            "B" => state.coord + new Coord(0, 2 * blockSize),
+            "C" => state.coord + new Coord(blockSize, blockSize),
+            "D" => state.coord + new Coord(2 * blockSize, 0),
+            "E" => state.coord + new Coord(2 * blockSize, blockSize),
+            "F" => state.coord + new Coord(3 * blockSize, 0),
+            _ => throw new Exception()
+        };
+
+    State Step(string topology, State state) {
+
+        bool wrapsAround(Coord coord) =>
+            coord.icol < 0 || coord.icol >= blockSize || 
+            coord.irow < 0 || coord.irow >= blockSize;
+
+        var (srcBlock, coord, dir) = state;
+        var dstBlock = srcBlock;
+
+        // take one step, if there is no wrap around we are all right
+        coord = dir switch {
+            left => coord with { icol = coord.icol - 1 },
+            down => coord with { irow = coord.irow + 1 },
+            right => coord with { icol = coord.icol + 1 },
+            up => coord with { irow = coord.irow - 1 },
+            _ => throw new Exception()
+        };
+
+        if (wrapsAround(coord)) {
+            // check the topology, select the dstBlock and rotate coord and dir 
+            // as much as needed this is easier to follow through an example
+            // if srcBlock: "C", dir: 2
+
+            var line = topology.Split('\n').Single(x => x.StartsWith(srcBlock));
+            // line: C -> B3 E0 D3 A0
+
+            var mapping = line.Split(" -> ")[1].Split(" ");
+            // mapping: B3 E0 D3 A0
+
+            var neighbour = mapping[dir];
+            // neighbour: D3
+
+            dstBlock = neighbour.Substring(0, 1);
+            // dstBlock: D
+
+            var rotate = int.Parse(neighbour.Substring(1));
+            // rotate: 3
+
+            // go back to the 0..49 range first, then rotate as much as needed
+            coord = coord with {
+                irow = (coord.irow + blockSize) % blockSize,
+                icol = (coord.icol + blockSize) % blockSize,
+            };
+
+            for (var i = 0; i < rotate; i++) {
+                coord = coord with { 
+                    irow = coord.icol, 
+                    icol = blockSize - coord.irow - 1 
+                };
+                dir = (dir + 1) % 4;
+            }
+        }
+
+        return new State(dstBlock, coord, dir);
+    }
+
+    (string[] map, Cmd[] path) Parse(string input) {
+        var blocks = input.Split("\n\n");
+
+        var map = blocks[0].Split("\n");
+        var commands = Regex
+            .Matches(blocks[1], @"(\d+)|L|R")
+            .Select(m =>
+                m.Value switch {
+                    "L" => new Left(),
+                    "R" => new Right(),
+                    string n => new Forward(int.Parse(n)),
+                })
+            .ToArray();
+
+        return (map, commands);
+    }
+
+    record State(string block, Coord coord, int dir);
+
+    record Coord(int irow, int icol) {
+        public static Coord operator +(Coord a, Coord b) =>
+            new Coord(a.irow + b.irow, a.icol + b.icol);
+
+        public static Coord operator -(Coord a, Coord b) =>
+            new Coord(a.irow - b.irow, a.icol - b.icol);
+    }
+
+    interface Cmd { }
+    record Forward(int n) : Cmd;
+    record Right() : Cmd;
+    record Left() : Cmd;
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/23/illustration.jpeg b/2022/23/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/23/illustration.jpeg differ diff --git a/2022/23/index.html b/2022/23/index.html new file mode 100644 index 00000000..e5c28c54 --- /dev/null +++ b/2022/23/index.html @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/23 'Unstable Diffusion'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/23

+

Unstable Diffusion

+

in C#

+

+

by encse

+
+ +
+ +
+

You enter a large crater of gray dirt where the grove is supposed to be. All around you, plants you imagine were expected to be full of fruit are instead withered and broken. A large group of Elves has formed in the middle of the grove.

+

"...but this volcano has been dormant for months. Without ash, the fruit can't grow!"

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+namespace AdventOfCode.Y2022.Day23;
+
+[ProblemName("Unstable Diffusion")]
+class Solution : Solver {
+
+    // I used complex numbers for a change. The map is represented with a hashset of positions.
+
+    public object PartOne(string input) 
+        => Simulate(Parse(input)).Select(Area).ElementAt(9);
+
+    public object PartTwo(string input) 
+        => Simulate(Parse(input)).Count();
+
+    IEnumerable> Simulate(HashSet elves) {
+        var lookAround = new Queue(new []{ N, S, W, E });
+
+        for (var fixpoint = false; !fixpoint; lookAround.Enqueue(lookAround.Dequeue())) {
+           
+            // 1) collect proposals; for each position (key) compute the list of the elves 
+            //    who want to step there
+            var proposals = new Dictionary>();
+
+            foreach (var elf in elves) {
+                var lonely = Directions.All(dir => !elves.Contains(elf + dir));
+                if (lonely) {
+                    continue;
+                }
+
+                foreach (var dir in lookAround) {
+                    
+                    // elf proposes a postion if nobody stands in that direction
+                    var proposes = ExtendDir(dir).All(d => !elves.Contains(elf + d));
+                    if (proposes) {
+                        var pos = elf + dir;
+                        if (!proposals.ContainsKey(pos)) {
+                            proposals[pos] = new List();
+                        }
+                        proposals[pos].Add(elf);
+                        break;
+                    }
+                }
+            }
+
+            // 2) move elves, compute fixpoint flag
+            fixpoint = true;
+            foreach (var p in proposals) {
+                var (to, from) = p;
+                if (from.Count == 1) {
+                    elves.Remove(from.Single());
+                    elves.Add(to);
+                    fixpoint = false;
+                }
+            }
+
+            yield return elves;
+        }
+    }
+
+    double Area(HashSet elves) {
+        // smallest enclosing rectangle
+        var width = elves.Select(p => p.Real).Max() - 
+                    elves.Select(p => p.Real).Min() + 1;
+
+        var height = elves.Select(p => p.Imaginary).Max() - 
+                     elves.Select(p => p.Imaginary).Min() + 1;
+
+        return width * height - elves.Count;
+    }
+     
+    HashSet Parse(string input) {
+        var lines = input.Split("\n");
+        return (
+            from irow in Enumerable.Range(0, lines.Length)
+            from icol in Enumerable.Range(0, lines[0].Length)
+            where lines[irow][icol] == '#'
+            select new Complex(icol, irow)
+        ).ToHashSet();
+    }
+
+    ///  -------
+
+    static Complex N = new Complex(0, -1);
+    static Complex E = new Complex(1, 0);
+    static Complex S = new Complex(0, 1);
+    static Complex W = new Complex(-1, 0);
+    static Complex NW = N + W;
+    static Complex NE = N + E;
+    static Complex SE = S + E;
+    static Complex SW = S + W;
+
+    static Complex[] Directions = new[] { NW, N, NE, E, SE, S, SW, W };
+
+    // Extends an ordinal position with its intercardinal neighbours
+    Complex[] ExtendDir(Complex dir) =>
+        dir == N ? new[] { NW, N, NE } :
+        dir == E ? new[] { NE, E, SE } :
+        dir == S ? new[] { SW, S, SE } :
+        dir == W ? new[] { NW, W, SW } :
+                   throw new Exception();
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/24/illustration.jpeg b/2022/24/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/24/illustration.jpeg differ diff --git a/2022/24/index.html b/2022/24/index.html new file mode 100644 index 00000000..f94eee48 --- /dev/null +++ b/2022/24/index.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/24 'Blizzard Basin'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/24

+

Blizzard Basin

+

in C#

+

+

by encse

+
+ +
+ +
+

With everything replanted for next year (and with elephants and monkeys to tend the grove), you and the Elves leave for the extraction point.

+

Partway up the mountain that shields the grove is a flat, open area that serves as the extraction point. It's a bit of a climb, but nothing the expedition can't handle.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+
+namespace AdventOfCode.Y2022.Day24;
+
+[ProblemName("Blizzard Basin")]
+class Solution : Solver {
+
+    // We do a standard A* algorithm, the only trick is that
+    // the 'map' always changes as blizzards move, so our position
+    // is now a space time coordinate. 
+    // I used an efficent Maps class that can be queried with these.
+
+    record Pos(int time, int irow, int icol);
+
+    public object PartOne(string input) {
+        var (entry, exit, maps) = Parse(input);
+        return WalkTo(entry, exit, maps).time;
+    }
+
+    public object PartTwo(string input) {
+        var (entry, exit, maps) = Parse(input);
+        var pos = WalkTo(entry, exit, maps);
+        pos = WalkTo(pos, entry, maps);
+        pos = WalkTo(pos, exit, maps);
+        return pos.time;
+    }
+
+    // Standard A* algorithm
+    Pos WalkTo(Pos start, Pos goal, Maps maps) {
+
+        var q = new PriorityQueue();
+
+        int f(Pos pos) {
+            // estimate the remaining step count with Manhattan distance
+            var dist =
+                Math.Abs(goal.irow - pos.irow) +
+                Math.Abs(goal.icol - pos.icol);
+            return pos.time + dist;
+        }
+
+        q.Enqueue(start, f(start));
+        HashSet seen = new HashSet();
+
+        while (q.Count > 0) {
+            var pos = q.Dequeue();
+            if (pos.irow == goal.irow && pos.icol == goal.icol) {
+                return pos;
+            }
+
+            foreach (var nextPos in NextPositions(pos, maps)) {
+                if (!seen.Contains(nextPos)) {
+                    seen.Add(nextPos);
+                    q.Enqueue(nextPos, f(nextPos));
+                }
+            }
+        }
+
+        throw new Exception();
+    }
+
+    // Increase time, look for free neighbours
+    IEnumerable NextPositions(Pos pos, Maps maps) {
+        pos = pos with {time = pos.time + 1};
+        foreach (var nextPos in new Pos[]{
+            pos,
+            pos with {irow=pos.irow -1},
+            pos with {irow=pos.irow +1},
+            pos with {icol=pos.icol -1},
+            pos with {icol=pos.icol +1},
+        }) {
+            if (maps.Get(nextPos) == '.') {
+                yield return nextPos;
+            }
+        }
+    }
+
+    (Pos entry, Pos exit, Maps maps) Parse(string input) {
+        var maps = new Maps(input);
+        var entry = new Pos(0, 0, 1);
+        var exit = new Pos(int.MaxValue, maps.crow - 1, maps.ccol - 2);
+        return (entry, exit, maps);
+    }
+
+    // Space-time indexable map
+    class Maps {
+        private string[] map;
+        public readonly int crow;
+        public readonly int ccol;
+
+        public Maps(string input) {
+            map = input.Split("\n");
+            this.crow = map.Length;
+            this.ccol = map[0].Length;
+        }
+
+        public char Get(Pos pos) {
+            if (pos.irow == 0 && pos.icol == 1) {
+                return '.';
+            }
+            if (pos.irow == crow - 1 && pos.icol == ccol - 2) {
+                return '.';
+            }
+
+            if (pos.irow <= 0 || pos.irow >= crow - 1 || 
+                pos.icol <= 0 || pos.icol >= ccol - 1
+            ) {
+                return '#';
+            }
+
+            // blizzards have a horizontal and a vertical loop
+            // it's easy to check the original postions with going back in time
+            // using modular arithmetic
+            var hmod = ccol - 2;
+            var vmod = crow - 2;
+
+            var icolW = (pos.icol - 1 + hmod - (pos.time % hmod)) % hmod + 1;
+            var icolE = (pos.icol - 1 + hmod + (pos.time % hmod)) % hmod + 1;
+            var icolN = (pos.irow - 1 + vmod - (pos.time % vmod)) % vmod + 1;
+            var icolS = (pos.irow - 1 + vmod + (pos.time % vmod)) % vmod + 1;
+
+            return 
+                map[pos.irow][icolW] == '>' ? '>':
+                map[pos.irow][icolE] == '<' ? '<':
+                map[icolN][pos.icol] == 'v' ? 'v':
+                map[icolS][pos.icol] == '^' ? '^':
+                                              '.';
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/25/illustration.jpeg b/2022/25/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/25/illustration.jpeg differ diff --git a/2022/25/index.html b/2022/25/index.html new file mode 100644 index 00000000..d7222d75 --- /dev/null +++ b/2022/25/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/25 'Full of Hot Air'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/25

+

Full of Hot Air

+

in C#

+

+

by encse

+
+ +
+ +
+

As the expedition finally reaches the extraction point, several large hot air balloons drift down to meet you. Crews quickly start unloading the equipment the balloons brought: many hot air balloon kits, some fuel tanks, and a fuel heating machine.

+

The fuel heating machine is a new addition to the process. When this mountain was a volcano, the ambient temperature was more reasonable; now, it's so cold that the fuel won't work at all without being warmed up first.

+

Read the full puzzle.

+
+
using System.Linq;
+using System;
+
+namespace AdventOfCode.Y2022.Day25;
+
+[ProblemName("Full of Hot Air")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        LongToSnafu(
+            input
+                .Split("\n")
+                .Select(SnafuToLong)
+                .Sum()
+        );
+    
+    // This is just string to number conversion in base 5
+    // with the two special digits that's worth -2 and -1.
+    long SnafuToLong(string snafu) {
+        long res = 0L;
+        foreach (var digit in snafu) {
+            res = res * 5;
+            switch (digit) {
+                case '=': res += -2; break;
+                case '-': res += -1; break;
+                case '0': res += 0; break;
+                case '1': res += 1; break;
+                case '2': res += 2; break;
+            }
+        }
+        return res;
+    }
+
+    // Snafu numbers have digits -2, -1, 0, 1 and 2, so this is almost 
+    // standard base 5 conversion, but when dealing with digits 3 and 4 we 
+    // need to increment the higher decimal place so that we have
+    // something to subtract 2 and 1 from.
+    string LongToSnafu(long d) {
+        var res = "";
+        while (d > 0) {
+            switch (d % 5) {
+                case 0: res = '0' + res; break;
+                case 1: res = '1' + res; break;
+                case 2: res = '2' + res; break;
+                // add 5 and emit -2 because 3 = 5 -2
+                case 3: d+=5; res = '=' + res; break; 
+                // add 5 and emit -1 because 4 = 5 -1
+                case 4: d+=5; res = '-' + res; break;
+            }
+            d /= 5;
+        }
+        return res;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/3/illustration.jpeg b/2022/3/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/3/illustration.jpeg differ diff --git a/2022/3/index.html b/2022/3/index.html new file mode 100644 index 00000000..81d35725 --- /dev/null +++ b/2022/3/index.html @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/3 'Rucksack Reorganization'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/3

+

Rucksack Reorganization

+

in C#

+

+

by encse

+
+ +
+ +
+

One Elf has the important job of loading all of the rucksacks with supplies for the jungle journey. Unfortunately, that Elf didn't quite follow the packing instructions, and so a few items now need to be rearranged.

+

Each rucksack has two large compartments. All items of a given type are meant to go into exactly one of the two compartments. The Elf that did the packing failed to follow this rule for exactly one item type per rucksack.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day03;
+
+[ProblemName("Rucksack Reorganization")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        // A line can be divided into two 'compartments' of equal length. We 
+        // need to find the common item (letter) in them, and convert it to a 
+        // number called 'priority'. Do this for each line and sum the 
+        // priorities. 
+        // We use 'chunk' to split a line in half.
+        input.Split("\n")
+            .Select(line => line.Chunk(line.Length/2)) // 🥩 
+            .Select(GetCommonItemPriority)
+            .Sum();
+
+    public object PartTwo(string input) =>
+        // Here we need to find the common item in three consecutive lines, 
+        // convert it to priority as before, and sum it up along the whole 
+        // input. 
+        // This is again conveniently done using the chunk function.
+        input.Split("\n")
+            .Chunk(3)
+            .Select(GetCommonItemPriority)
+            .Sum();
+
+    private int GetCommonItemPriority(IEnumerable> texts) => (
+        from ch in texts.First()
+        where texts.All(text => text.Contains(ch))
+        select ch < 'a' ? ch - 'A' + 27 : ch - 'a' + 1
+    ).First();
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/4/illustration.jpeg b/2022/4/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/4/illustration.jpeg differ diff --git a/2022/4/index.html b/2022/4/index.html new file mode 100644 index 00000000..e73c744a --- /dev/null +++ b/2022/4/index.html @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/4 'Camp Cleanup'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/4

+

Camp Cleanup

+

in C#

+

+

by encse

+
+ +
+ +
+

Space needs to be cleared before the last supplies can be unloaded from the ships, and so several Elves have been assigned the job of cleaning up sections of the camp. Every section has a unique ID number, and each Elf is assigned a range of section IDs.

+

However, as some of the Elves compare their section assignments with each other, they've noticed that many of the assignments overlap. To try to quickly find overlaps and reduce duplicated effort, the Elves pair up and make a big list of the section assignments for each pair (your puzzle input).

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day04;
+
+[ProblemName("Camp Cleanup")]
+class Solution : Solver {
+    
+    // Each line of the input represents two ranges - job done by two elves.
+    // We need to find those lines where the elves did some work twice.
+    // Part 1 and 2 differs in how we define 'duplicated work'.
+    record struct Range(int from, int to);
+
+    public object PartOne(string input) => DuplicatedWorkCount(input, Contains);
+    public object PartTwo(string input) => DuplicatedWorkCount(input, Overlaps);
+
+    // True if r1 contains r2 [ { } ] 
+    bool Contains(Range r1, Range r2) => r1.from <= r2.from && r2.to <= r1.to; 
+    
+    // True if r1 overlaps r2 { [ } ], the other direction is not checked.
+    bool Overlaps(Range r1, Range r2) => r1.to >= r2.from && r1.from <= r2.to; 
+
+    // DuplicatedWorkCount parses each input line into ranges and applies 
+    // rangeCheck on them to find duplicated work. RangeCheck doesnt have to be 
+    // symmetrical in its arguments, but DuplicatedWorkCount makes it so calling
+    // it twice with the arguments swapped.
+    private int DuplicatedWorkCount(
+        string input, 
+        Func rangeCheck
+    ) {
+        // E.g. '36-41,35-40' becomes [Range(36, 41), Range(35, 40)]
+        var parseRanges = (string line) => 
+            from range in line.Split(',') 
+            let fromTo = range.Split('-').Select(int.Parse)
+            select new Range(fromTo.First(), fromTo.Last());
+
+        return input
+            .Split("\n")
+            .Select(parseRanges)
+            .Count(ranges => 
+                rangeCheck(ranges.First(), ranges.Last()) || 
+                rangeCheck(ranges.Last(), ranges.First())
+            );
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/5/illustration.jpeg b/2022/5/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/5/illustration.jpeg differ diff --git a/2022/5/index.html b/2022/5/index.html new file mode 100644 index 00000000..e3bcbc6f --- /dev/null +++ b/2022/5/index.html @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/5 'Supply Stacks'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/5

+

Supply Stacks

+

in C#

+

+

by encse

+
+ +
+ +
+

The expedition can depart as soon as the final supplies have been unloaded from the ships. Supplies are stored in stacks of marked crates, but because the needed supplies are buried under many other crates, the crates need to be rearranged.

+

The ship has a giant cargo crane capable of moving crates between stacks. To ensure none of the crates get crushed or fall over, the crane operator will rearrange them in a series of carefully-planned steps. After the crates are rearranged, the desired crates will be at the top of each stack.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day05;
+
+[ProblemName("Supply Stacks")]
+class Solution : Solver {
+
+    // The input is parsed into some stacks of 'crates', and move operations 
+    // that is to be applied on them. There is a crane which takes some number 
+    // of crates from one stack and puts them on the top of an other stack. 
+    // Part one and two differs in how this crane works, which is implemented 
+    // by the two 'crateMover' functions.
+    record struct Move(int count, Stack source, Stack target);
+
+    public object PartOne(string input) => MoveCrates(input, CrateMover9000);
+    public object PartTwo(string input) => MoveCrates(input, CrateMover9001);
+
+    void CrateMover9000(Move move) {
+        for (var i = 0; i < move.count; i++) {
+            move.target.Push(move.source.Pop());
+        }
+    }
+
+    void CrateMover9001(Move move) {
+        // same as CrateMover9000 but keeps element order
+        var helper = new Stack();
+        CrateMover9000(move with {target=helper});
+        CrateMover9000(move with {source=helper});
+    }
+
+    string MoveCrates(string input, Action crateMover) {
+        var parts = input.Split("\n\n");
+        
+        var stackDefs = parts[0].Split("\n");
+        // [D]
+        // [N] [C]
+        // [Z] [M] [P]
+        //  1   2   3 
+      
+        // last line defines the number of stacks:
+        var stacks = stackDefs
+            .Last()
+            .Chunk(4)
+            .Select(_ => new Stack())
+            .ToArray();
+        
+        // Each input line is processed in 4 character long chunks in bottom up
+        // order. Push the next element into the next stack (note how the chunk 
+        // and the stack is paired up using the zip function). ' ' means no more 
+        // elements to add, just go to the next chunk.
+        foreach (var line in stackDefs.Reverse().Skip(1)) {
+            foreach (var (stack, item) in stacks.Zip(line.Chunk(4))) {
+                if (item[1] != ' ') {
+                    stack.Push(item[1]);
+                }
+            }
+        }
+
+        // now parse the move operations and crateMover on them:
+        foreach (var line in parts[1].Split("\n")) {
+            // e.g. "move 6 from 4 to 3"
+            var m = Regex.Match(line, @"move (.*) from (.*) to (.*)");
+            var count = int.Parse(m.Groups[1].Value);
+            var from = int.Parse(m.Groups[2].Value) - 1;
+            var to = int.Parse(m.Groups[3].Value) - 1;
+            crateMover(
+                new Move(
+                    count:count, 
+                    source: stacks[from], target: stacks[to]
+                ));
+        }
+
+        // collect the top of each stack:
+        return string.Join("", stacks.Select(stack => stack.Pop()));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/6/illustration.jpeg b/2022/6/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/6/illustration.jpeg differ diff --git a/2022/6/index.html b/2022/6/index.html new file mode 100644 index 00000000..a35f47de --- /dev/null +++ b/2022/6/index.html @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/6 'Tuning Trouble'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/6

+

Tuning Trouble

+

in C#

+

+

by encse

+
+ +
+ +
+

The preparations are finally complete; you and the Elves leave camp on foot and begin to make your way toward the star fruit grove.

+

As you move through the dense undergrowth, one of the Elves gives you a handheld device. He says that it has many fancy features, but the most important one to set up right now is the communication system.

+

Read the full puzzle.

+
+
using System;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day06;
+
+[ProblemName("Tuning Trouble")]
+class Solution : Solver {
+
+    public object PartOne(string input) => StartOfBlock(input, 4);
+    public object PartTwo(string input) => StartOfBlock(input, 14);
+
+    // Slides a window of length l over the input and finds the first position
+    // where each character is different. Returns the right end of the window.
+    int StartOfBlock(string input, int l) =>
+         Enumerable.Range(l, input.Length)
+            .First(i => input.Substring(i - l, l).ToHashSet().Count == l);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/7/illustration.jpeg b/2022/7/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/7/illustration.jpeg differ diff --git a/2022/7/index.html b/2022/7/index.html new file mode 100644 index 00000000..c5c49d6b --- /dev/null +++ b/2022/7/index.html @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/7 'No Space Left On Device'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/7

+

No Space Left On Device

+

in C#

+

+

by encse

+
+ +
+ +
+

You can hear birds chirping and raindrops hitting leaves as the expedition proceeds. Occasionally, you can even hear much louder sounds in the distance; how big do the animals get out here, anyway?

+

The device the Elves gave you has problems with more than just its communication system. You try to run a system update:

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Y2022.Day07;
+
+[ProblemName("No Space Left On Device")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        return GetDirectorySizes(input).Where(size => size < 100000).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var directorySizes = GetDirectorySizes(input);
+        var freeSpace = 70000000 - directorySizes.Max();
+        return directorySizes.Where(size => size + freeSpace >= 30000000).Min();
+    }
+
+    private List GetDirectorySizes(string input) {
+        var path = new Stack();
+        var sizes = new Dictionary();
+        foreach (var line in input.Split("\n")) {
+            if (line == "$ cd ..") {
+                path.Pop();
+            } else if (line.StartsWith("$ cd")) {
+                path.Push(string.Join("", path)+line.Split(" ")[2]);
+            } else if (Regex.Match(line, @"\d+").Success) {
+                var size = int.Parse(line.Split(" ")[0]);
+                foreach (var dir in path) {
+                    sizes[dir] = sizes.GetValueOrDefault(dir) + size;
+                }
+            }
+        }
+        return sizes.Values.ToList();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/8/illustration.jpeg b/2022/8/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/8/illustration.jpeg differ diff --git a/2022/8/index.html b/2022/8/index.html new file mode 100644 index 00000000..842b4b99 --- /dev/null +++ b/2022/8/index.html @@ -0,0 +1,348 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/8 'Treetop Tree House'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/8

+

Treetop Tree House

+

in C#

+

+

by encse

+
+ +
+ +
+

The expedition comes across a peculiar patch of tall trees all planted carefully in a grid. The Elves explain that a previous expedition planted these trees as a reforestation effort. Now, they're curious if this would be a good location for a tree house.

+

First, determine whether there is enough tree cover here to keep a tree house hidden. To do this, you need to count the number of trees that are visible from outside the grid when looking directly along a row or column.

+

Read the full puzzle.

+
+
using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day08;
+
+[ProblemName("Treetop Tree House")]
+class Solution : Solver {
+
+    static Direction Left = new Direction(0, -1);
+    static Direction Right = new Direction(0, 1);
+    static Direction Up = new Direction(-1, 0);
+    static Direction Down = new Direction(1, 0);
+
+    public object PartOne(string input) {
+        var forest = Parse(input);
+
+        return forest.Trees().Count(tree =>
+            forest.IsTallest(tree, Left) || forest.IsTallest(tree, Right) ||
+            forest.IsTallest(tree, Up) || forest.IsTallest(tree, Down)
+        );
+    }
+
+    public object PartTwo(string input) {
+        var forest = Parse(input);
+
+        return forest.Trees().Select(tree =>
+            forest.ViewDistance(tree, Left) * forest.ViewDistance(tree, Right) *
+            forest.ViewDistance(tree, Up) * forest.ViewDistance(tree, Down)
+        ).Max();
+    }
+
+    Forest Parse(string input) {
+        var items = input.Split("\n");
+        var (ccol, crow) = (items[0].Length, items.Length);
+        return new Forest(items, crow, ccol);
+    }
+}
+
+record Direction(int drow, int dcol);
+record Tree(int height, int irow, int icol);
+record Forest(string[] items, int crow, int ccol) {
+
+    public IEnumerable Trees() =>
+        from irow in Enumerable.Range(0, crow)
+        from icol in Enumerable.Range(0, ccol)
+        select new Tree(items[irow][icol], irow, icol);
+
+    public int ViewDistance(Tree tree, Direction dir) =>
+        IsTallest(tree, dir) ? TreesInDirection(tree, dir).Count() 
+                             : SmallerTrees(tree, dir).Count() + 1;
+
+    public bool IsTallest(Tree tree, Direction dir) =>
+        TreesInDirection(tree, dir).All(treeT => treeT.height < tree.height);
+
+    IEnumerable SmallerTrees(Tree tree, Direction dir) =>
+        TreesInDirection(tree, dir).TakeWhile(treeT => treeT.height < tree.height);
+
+    IEnumerable TreesInDirection(Tree tree, Direction dir) {
+        var (first, irow, icol) = (true, tree.irow, tree.icol);
+        while (irow >= 0 && irow < crow && icol >= 0 && icol < ccol) {
+            if (!first) {
+                yield return new Tree(height: items[irow][icol], irow: irow, icol: icol);
+            }
+            (first, irow, icol) = (false, irow + dir.drow, icol + dir.dcol);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2022/9/illustration.jpeg b/2022/9/illustration.jpeg new file mode 100644 index 00000000..d61c3abb Binary files /dev/null and b/2022/9/illustration.jpeg differ diff --git a/2022/9/index.html b/2022/9/index.html new file mode 100644 index 00000000..4af95a65 --- /dev/null +++ b/2022/9/index.html @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2022/9 'Rope Bridge'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2022/9

+

Rope Bridge

+

in C#

+

+

by encse

+
+ +
+ +
+

This rope bridge creaks as you walk along it. You aren't sure how old it is, or whether it can even support your weight.

+

It seems to support the Elves just fine, though. The bridge spans a gorge which was carved out by the massive river far below you.

+

Read the full puzzle.

+
+
using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AdventOfCode.Y2022.Day09;
+
+[ProblemName("Rope Bridge")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Tails(input, 2).ToHashSet().Count;
+    public object PartTwo(string input) => Tails(input, 10).ToHashSet().Count;
+
+    // simulates a rope with the given length as its head moves
+    // according to the input and returns the position of its 
+    // tail knot in each step.
+    private IEnumerable Tails(string input, int ropeLength) {
+        var rope = Enumerable.Repeat(new Knot(0, 0), ropeLength).ToArray();
+        yield return rope.Last();
+
+        foreach (var line in input.Split("\n")) {
+            var parts = line.Split(' ');
+            var dir = parts[0];
+            var dist = int.Parse(parts[1]);
+
+            for (var i = 0; i < dist; i++) {
+                MoveHead(rope, dir);
+                yield return rope.Last();
+            }
+        }
+    }
+
+    record struct Knot(int irow, int icol);
+
+    // moves the head in the given direction, inplace update 
+    // of the rope
+    void MoveHead(Knot[] rope, string dir) {
+        rope[0] = dir switch {
+            "U" => rope[0] with { irow = rope[0].irow - 1 },
+            "D" => rope[0] with { irow = rope[0].irow + 1 },
+            "L" => rope[0] with { icol = rope[0].icol - 1 },
+            "R" => rope[0] with { icol = rope[0].icol + 1 },
+            _ => throw new ArgumentException(dir)
+        };
+
+        // knots move when become disconnected from the previous 
+        // sibling in the rope:
+        for (var i = 1; i < rope.Length; i++) {
+            var drow = rope[i - 1].irow - rope[i].irow; 
+            var dcol = rope[i - 1].icol - rope[i].icol;
+
+            if (Math.Abs(drow) > 1 || Math.Abs(dcol) > 1) {
+                rope[i] = new Knot(
+                    rope[i].irow + Math.Sign(drow), 
+                    rope[i].icol + Math.Sign(dcol)
+                );
+            }
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/1/illustration.jpeg b/2023/1/illustration.jpeg new file mode 100644 index 00000000..2764a949 Binary files /dev/null and b/2023/1/illustration.jpeg differ diff --git a/2023/1/index.html b/2023/1/index.html new file mode 100644 index 00000000..85860bdf --- /dev/null +++ b/2023/1/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/1 'Trebuchet?!'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/1

+

Trebuchet?!

+

in C#

+

+

by encse

+
+ +
+ +
+

Those who need a refresh can read the problem here, +then let's get started. Our Elves need us!

+

Part 1 was super easy, ok, this is day one just to warm up a bit. It's some regular +expression, let's see Part 2!

+

Wait a minute, huhh... what is this? Oneight? What does this even mean? Usually such weird +cases are mentioned in the example input, but not this time! Is it '1', '8' or '18'? Depending on +how one interpreted the problem statement he could spent quite a lot of time on figuring this out.

+

I think this was a little bit of an oversight for day 1, but let's see what's up for tomorrow!

+
+
namespace AdventOfCode.Y2023.Day01;
+
+using System.Linq;
+using System.Text.RegularExpressions;
+
+[ProblemName("Trebuchet?!")]
+class Solution : Solver {
+
+    public object PartOne(string input) =>
+        Solve(input, @"\d");
+
+    public object PartTwo(string input) =>
+        Solve(input, @"\d|one|two|three|four|five|six|seven|eight|nine");
+
+    int Solve(string input, string rx) => (
+        from line in input.Split("\n")
+        let first = Regex.Match(line, rx)
+        let last = Regex.Match(line, rx, RegexOptions.RightToLeft)
+        select ParseMatch(first.Value) * 10 + ParseMatch(last.Value)
+    ).Sum();
+
+    int ParseMatch(string st) => st switch {
+        "one" => 1,
+        "two" => 2,
+        "three" => 3,
+        "four" => 4,
+        "five" => 5,
+        "six" => 6,
+        "seven" => 7,
+        "eight" => 8,
+        "nine" => 9,
+        var d => int.Parse(d)
+    };
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/10/illustration.jpeg b/2023/10/illustration.jpeg new file mode 100644 index 00000000..032b77df Binary files /dev/null and b/2023/10/illustration.jpeg differ diff --git a/2023/10/index.html b/2023/10/index.html new file mode 100644 index 00000000..4a08c090 --- /dev/null +++ b/2023/10/index.html @@ -0,0 +1,375 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/10 'Pipe Maze'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/10

+

Pipe Maze

+

in C#

+

+

by encse

+
+ +
+ +
+

The original problem description is available here.

+

In Part 1 we had to find the length of a loop that was defined by a funky ASCII +art pipe network that even used J, and F characters for the turns.

+

Part 2 asked to compute the area of the loop, I implemented ray casting +for this one. There are lots of other ways to solve this, a similar problem +and different algorithm can be found in Day 18.

+
+
namespace AdventOfCode.Y2023.Day10;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Map = System.Collections.Generic.Dictionary;
+
+[ProblemName("Pipe Maze")]
+class Solution : Solver {
+    static readonly Complex Up = -Complex.ImaginaryOne;
+    static readonly Complex Down = Complex.ImaginaryOne;
+    static readonly Complex Left = -Complex.One;
+    static readonly Complex Right = Complex.One;
+    static readonly Complex[] Dirs = [Up, Right, Down, Left];
+
+    static readonly Dictionary Exits = new Dictionary{
+        {'7', [Left, Down] },
+        {'F', [Right, Down]},
+        {'L', [Up, Right]},
+        {'J', [Up, Left]},
+        {'|', [Up, Down]},
+        {'-', [Left, Right]},
+        {'S', [Up, Down, Left, Right]},
+        {'.', []},
+    };
+
+    public object PartOne(string input) {
+        var map = ParseMap(input);
+        var loop = LoopPositions(map);
+        return loop.Count / 2;
+    }
+
+    public object PartTwo(string input) {
+        var map = ParseMap(input);
+        var loop = LoopPositions(map);
+        return map.Keys.Count(position => Inside(position, map, loop));
+    }
+
+    // Returns the positions that make up the loop containing 'S'
+    HashSet LoopPositions(Map map) {
+        var position = map.Keys.Single(k => map[k] == 'S');
+        var positions = new HashSet();
+
+        // pick a direction connected to a neighbour
+        var dir = Dirs.First(dir => Exits[map[position + dir]].Contains(-dir));
+
+        for (; ; ) {
+            positions.Add(position);
+            position += dir;
+            if (map[position] == 'S') {
+                break;
+            }
+            dir = Exits[map[position]].Single(exit => exit != -dir);
+        }
+        return positions;
+    }
+
+    // Check if position is inside the loop using ray casting algorithm
+    bool Inside(Complex position, Map map, HashSet loop) {
+        // Imagine a small elf starting from the top half of a cell and moving 
+        // to the left jumping over the pipes it encounters. It needs to jump 
+        // over only 'vertically' oriented pipes leading upwards, since it runs 
+        // in the top of the row. Each jump flips the "inside" variable.
+
+        if (loop.Contains(position)) {
+            return false;
+        }
+
+        var inside = false;
+        position += Left;
+        while (map.ContainsKey(position)) {
+            if (loop.Contains(position) && Exits[map[position]].Contains(Up)) {
+                inside = !inside;
+            }
+            position += Left;
+        }
+        return inside;
+    }
+
+    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(pos, cell)
+        ).ToDictionary();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/11/illustration.jpeg b/2023/11/illustration.jpeg new file mode 100644 index 00000000..542eb6e9 Binary files /dev/null and b/2023/11/illustration.jpeg differ diff --git a/2023/11/index.html b/2023/11/index.html new file mode 100644 index 00000000..83954e9a --- /dev/null +++ b/2023/11/index.html @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/11 'Cosmic Expansion'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/11

+

Cosmic Expansion

+

in C#

+

+

by encse

+
+ +
+ +
+

Visit the Advent of Code website for the problem statementhere.

+

A pretty simple problem for today. We had to compute the sum of the pairwise Manhattan distances +of each galaxies (# symbols) in a map.

+

The twist is that moving accross some columns or rows of the map is worths double distance points +(one million in Part 2). But it was not hard to incorporate this into our distance function.

+

I did it this way, but we should mention that since we are computing the distance over each pair, and all operations are commutative and associative, it's probably possible to reorder things a bit which can result in a more efficient algorithm.

+
+
namespace AdventOfCode.Y2023.Day11;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+record Position(int irow, int icol);
+
+[ProblemName("Cosmic Expansion")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 1);
+    public object PartTwo(string input) => Solve(input, 999999);
+
+    long Solve(string input, int expansion) {
+        var map = input.Split("\n");
+
+        Func isRowEmpty = EmptyRows(map).ToHashSet().Contains;
+        Func isColEmpty = EmptyCols(map).ToHashSet().Contains;
+
+        var galaxies = FindAll(map, '#');
+        return (
+            from g1 in galaxies
+            from g2 in galaxies
+            select
+                Distance(g1.irow, g2.irow, expansion, isRowEmpty) +
+                Distance(g1.icol, g2.icol, expansion, isColEmpty)
+        ).Sum() / 2;
+    }
+
+    long Distance(int i1, int i2, int expansion, Func isEmpty) {
+        var a = Math.Min(i1, i2);
+        var d = Math.Abs(i1 - i2);
+        return d + expansion * Enumerable.Range(a, d).Count(isEmpty);
+    }
+
+    IEnumerable EmptyRows(string[] map) =>
+        from irow in Enumerable.Range(0, map.Length)
+        where map[irow].All(ch => ch == '.')
+        select irow;
+
+    IEnumerable EmptyCols(string[] map) =>
+        from icol in Enumerable.Range(0, map[0].Length)
+        where map.All(row => row[icol] == '.')
+        select icol;
+
+    IEnumerable FindAll(string[] map, char ch) =>
+        from irow in Enumerable.Range(0, map.Length)
+        from icol in Enumerable.Range(0, map[0].Length)
+        where map[irow][icol] == ch
+        select new Position(irow, icol);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/12/illustration.jpeg b/2023/12/illustration.jpeg new file mode 100644 index 00000000..21c6ccdb Binary files /dev/null and b/2023/12/illustration.jpeg differ diff --git a/2023/12/index.html b/2023/12/index.html new file mode 100644 index 00000000..9791cc70 --- /dev/null +++ b/2023/12/index.html @@ -0,0 +1,380 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/12 'Hot Springs'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/12

+

Hot Springs

+

in C#

+

+

by encse

+
+ +
+ +
+

If you are not familiar with the problem, you can read i here.

+

A day of memoized functions / dynamic programming. Each line of the input has some pattern (string) and constraints (numbers). Going over the pattern we need to figure out what should be put in the place of the ? symbols so that it satisfies the constraints on the right. How many ways are to satisfy all conditions?

+

This cries out for recursion, you can find the details below.

+

In Part 2 the input is transformed to something bigger with a process +called unfolding. It's the same question as before, the sole +purpose of the unfolding is to force us adding memoization to the +algorithm we came up with in Part 1.

+
+
namespace AdventOfCode.Y2023.Day12;
+
+using System;
+using System.Collections.Immutable;
+using System.Linq;
+using Cache = System.Collections.Generic.Dictionary<
+    (string, System.Collections.Immutable.ImmutableStack), long>;
+
+[ProblemName("Hot Springs")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, 1);
+    public object PartTwo(string input) => Solve(input, 5);
+
+    // After unfolding the input we process it line by line computing the possible 
+    // combinations for each. We use memoized recursion to speed up PartTwo.
+    // 
+    // The computation is recursive by nature, and goes over the pattern and numbers
+    // in tandem branching on '?' symbols and consuming as much of dead springs
+    // as dictated by the next number when a '#' is found. The symbol that follows 
+    // a dead range needs special treatment: it cannot be a '#', and if it was a '?'
+    // we should consider it as a '.' according to the problem statement.
+    // 
+    // I like to use immutable datastructures when dealing with problems that
+    // involves backtracking, it's not immediately obvious from the solution below
+    // but using a mutable stack or list would cause a lot of headache.
+
+    long Solve(string input, int repeat) => (
+        from line in input.Split("\n")
+        let parts = line.Split(" ")
+        let pattern = Unfold(parts[0], '?', repeat)
+        let numString = Unfold(parts[1], ',', repeat)
+        let nums = numString.Split(',').Select(int.Parse)
+        select
+            Compute(pattern, ImmutableStack.CreateRange(nums.Reverse()), new Cache())
+    ).Sum();
+
+    string Unfold(string st, char join, int unfold) =>
+        string.Join(join, Enumerable.Repeat(st, unfold));
+
+    long Compute(string pattern, ImmutableStack nums, Cache cache) {
+        if (!cache.ContainsKey((pattern, nums))) {
+            cache[(pattern, nums)] = Dispatch(pattern, nums, cache);
+        }
+        return cache[(pattern, nums)];
+    }
+
+    long Dispatch(string pattern, ImmutableStack nums, Cache cache) {
+        return pattern.FirstOrDefault() switch {
+            '.' => ProcessDot(pattern, nums, cache),
+            '?' => ProcessQuestion(pattern, nums, cache),
+            '#' => ProcessHash(pattern, nums, cache),
+            _ => ProcessEnd(pattern, nums, cache),
+        };
+    }
+
+    long ProcessEnd(string _, ImmutableStack nums, Cache __) {
+        // no numbers left at the end of pattern -> good
+        return nums.Any() ? 0 : 1;
+    }
+
+    long ProcessDot(string pattern, ImmutableStack nums, Cache cache) {
+        // consume one spring and recurse
+        return Compute(pattern[1..], nums, cache);
+    }
+
+    long ProcessQuestion(string pattern, ImmutableStack nums, Cache cache) {
+        // recurse both ways
+        return Compute("." + pattern[1..], nums, cache) +
+            Compute("#" + pattern[1..], nums, cache);
+    }
+
+    long ProcessHash(string pattern, ImmutableStack nums, Cache cache) {
+        // take the first number and consume that many dead springs, recurse
+
+        if (!nums.Any()) {
+            return 0; // no more numbers left, this is no good
+        }
+
+        var n = nums.Peek();
+        nums = nums.Pop();
+
+        var potentiallyDead = pattern.TakeWhile(s => s == '#' || s == '?').Count();
+
+        if (potentiallyDead < n) {
+            return 0; // not enough dead springs 
+        } else if (pattern.Length == n) {
+            return Compute("", nums, cache);
+        } else if (pattern[n] == '#') {
+            return 0; // dead spring follows the range -> not good
+        } else {
+            return Compute(pattern[(n + 1)..], nums, cache);
+        }
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/13/illustration.jpeg b/2023/13/illustration.jpeg new file mode 100644 index 00000000..034cf2d8 Binary files /dev/null and b/2023/13/illustration.jpeg differ diff --git a/2023/13/index.html b/2023/13/index.html new file mode 100644 index 00000000..f2ba81d4 --- /dev/null +++ b/2023/13/index.html @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/13 'Point of Incidence'' in C# by encse + + + + + + + + + + + + + + +
+
+
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;
+
+[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 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(pos, cell)
+        ).ToDictionary();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/14/illustration.jpeg b/2023/14/illustration.jpeg new file mode 100644 index 00000000..3d5dbea0 Binary files /dev/null and b/2023/14/illustration.jpeg differ diff --git a/2023/14/index.html b/2023/14/index.html new file mode 100644 index 00000000..066d7f56 --- /dev/null +++ b/2023/14/index.html @@ -0,0 +1,370 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/14 'Parabolic Reflector Dish'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/14

+

Parabolic Reflector Dish

+

in C#

+

+

by encse

+
+ +
+ +
+

The task description is copyrighted, but it's available here.

+

We are playing Boulder Dash today, but instead of moving a character on the screen +we tilt the screen itself and move all the boulders at once. The task asks us to implement tilting +in each directions (North, South, East and West), but I just implemented North and kept rotating +the board by 90 degrees.

+

Then we start tilting like crazy - four billion times. When you see iterate for <a big number> you immediately start looking for some repetition. This is not different with today's problem either. In just about a hundred steps the board enters into a loop, so we can jump +over the rest of the tilting work and just read the result out from the list of states we collected.

+
+
namespace AdventOfCode.Y2023.Day14;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Map = char[][];
+
+[ProblemName("Parabolic Reflector Dish")]
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        Measure(Tilt(Parse(input)));
+
+    public object PartTwo(string input) => 
+        Measure(Iterate(Parse(input), Cycle, 1_000_000_000));
+
+    Map Parse(string input) => (
+        from l in input.Split('\n') select l.ToCharArray()
+    ).ToArray();
+
+    int Crow(char[][] map) => map.Length;
+    int Ccol(char[][] map) => map[0].Length;
+
+    Map Iterate(Map map, Func cycle, int count) {
+        // The usual trick: keep iterating until we find a loop, make a shortcut
+        // and read the result from the accumulated history.
+        var history = new List();
+        while (count > 0) {
+            map = cycle(map);
+            count--;
+
+            var mapString = string.Join("\n", map.Select(l=> new string(l)));
+            var idx = history.IndexOf(mapString);
+            if (idx < 0) {
+                history.Add(mapString);
+            } else {
+                var loopLength = history.Count - idx;
+                var remainder = count % loopLength; 
+                return Parse(history[idx + remainder]);
+            }
+        }
+        return map;
+    }
+
+    Map Cycle(Map map) {
+        for (var i = 0; i < 4; i++) {
+            map = Rotate(Tilt(map));
+        }
+        return map;
+    }
+
+    // Tilt the map to the North, so that the 'O' tiles roll to the top.
+    Map Tilt(Map map) {
+        for (var icol = 0; icol < Ccol(map); icol++) {
+            var irowT = 0; // tells where to roll up the next 'O' tile
+            for (var irowS = 0; irowS < Crow(map); irowS++) {
+                if (map[irowS][icol] == '#') {
+                    irowT = irowS + 1;
+                } else if (map[irowS][icol] == 'O') {
+                    map[irowS][icol] = '.'; 
+                    map[irowT][icol] = 'O'; 
+                    irowT++;
+                }
+            }
+        }
+        return map;
+    }
+
+    // Ugly coordinate magic, turns the map 90º clockwise
+    Map Rotate(Map src) {
+        var dst = new char[Crow(src)][];
+        for (var irow = 0; irow < Ccol(src); irow++) {
+            dst[irow] = new char[Ccol(src)];
+            for (var icol = 0; icol < Crow(src); icol++) {
+                dst[irow][icol] = src[Crow(src) - icol - 1][irow];
+            }
+        }
+        return dst;
+    }
+
+    // returns the cummulated distances of 'O' tiles from the bottom of the map
+    int Measure(Map map) =>  
+        map.Select((row, irow) => 
+            (Crow(map) - irow) * row.Count(ch => ch == 'O')
+        ).Sum();
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/15/illustration.jpeg b/2023/15/illustration.jpeg new file mode 100644 index 00000000..a338e941 Binary files /dev/null and b/2023/15/illustration.jpeg differ diff --git a/2023/15/index.html b/2023/15/index.html new file mode 100644 index 00000000..c0010bd6 --- /dev/null +++ b/2023/15/index.html @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/15 'Lens Library'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/15

+

Lens Library

+

in C#

+

+

by encse

+
+ +
+ +
+

Let's revisit the problem description here.

+

Part 1 was super simple. What's funny is that I saw a similar hash algorithm yesterday +in someone else's solution, where he stored the hashes of the visited states instead +of serializing it as a whole.

+

For the second part, I created a function that applies one statement to +an array of boxes at hand. The signature is set up so that I can use it to Aggregate +all steps seeded with an initial set of 256 empty boxes. We are transforming boxes +to boxes while applying the steps in a row. The function passed as the third argument +is used to extract the computing power from the final state of the box array.

+

I'm describing it in a functional way, but there is no purity under the hood. We +are working with and modifying the same box objects during the process.

+
+
namespace AdventOfCode.Y2023.Day15;
+
+using System.Collections.Generic;
+using System.Linq;
+using Boxes = System.Collections.Generic.List[];
+
+record Lens(string label, int focalLength);
+record Step(string label, int? focalLength);
+
+[ProblemName("Lens Library")]
+class Solution : Solver {
+
+    public object PartOne(string input) => input.Split(',').Select(Hash).Sum();
+
+    // "funcionally imperative of imperatively functional", only for 🎄
+    public object PartTwo(string input) =>
+        ParseSteps(input).Aggregate(MakeBoxes(256), UpdateBoxes, GetFocusingPower);
+
+    Boxes UpdateBoxes(Boxes boxes, Step step) {
+        var box = boxes[Hash(step.label)];
+        var ilens = box.FindIndex(lens => lens.label == step.label);
+
+        if (!step.focalLength.HasValue && ilens >= 0) {
+            box.RemoveAt(ilens);
+        } else if (step.focalLength.HasValue && ilens >= 0) {
+            box[ilens] = new Lens(step.label, step.focalLength.Value);
+        } else if (step.focalLength.HasValue && ilens < 0) {
+            box.Add(new Lens(step.label, step.focalLength.Value));
+        }
+        return boxes;
+    }
+
+    IEnumerable ParseSteps(string input) =>
+        from item in input.Split(',')
+        let parts = item.Split('-', '=')
+        select new Step(parts[0], parts[1] == "" ? null : int.Parse(parts[1]));
+
+    Boxes MakeBoxes(int count) =>
+        Enumerable.Range(0, count).Select(_ => new List()).ToArray();
+
+    int GetFocusingPower(Boxes boxes) => (
+        from ibox in Enumerable.Range(0, boxes.Length)
+        from ilens in Enumerable.Range(0, boxes[ibox].Count)
+        select (ibox + 1) * (ilens + 1) * boxes[ibox][ilens].focalLength
+    ).Sum();
+
+    int Hash(string st) => st.Aggregate(0, (ch, a) => (ch + a) * 17 % 256);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/16/illustration.jpeg b/2023/16/illustration.jpeg new file mode 100644 index 00000000..bd921cad Binary files /dev/null and b/2023/16/illustration.jpeg differ diff --git a/2023/16/index.html b/2023/16/index.html new file mode 100644 index 00000000..034480ad --- /dev/null +++ b/2023/16/index.html @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/16 'The Floor Will Be Lava'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/16

+

The Floor Will Be Lava

+

in C#

+

+

by encse

+
+ +
+ +
+

The original problem description is available here.

+

I was a bit worried when I saw Part 1, because it let the window open for a complicated optimization +for Part 2. But it just turned out to be the same thing as Part 1 iterated along the edges of the map.

+

I went with the proven strategy and represented the map as a dictionary indexed by complex numbers. It's +easy to check the bounds, and changing positions is just complex arithmetic.

+

At first I created a long switch case to determine how a beam changes its way when encountering +mirrors and splitters, but it turns out that in many cases it just continues in the same direction. +Splitting can be handled in just two lines for the vertical and horizontal case. Finally my choice of +the coordinate system makes turning around mirrors very simple: the coordinates flip when the mirror +is facing \ and just an additional multiplication by -1 is needed for the / case.

+
+
namespace AdventOfCode.Y2023.Day16;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Map = System.Collections.Generic.Dictionary;
+using Beam = (System.Numerics.Complex pos, System.Numerics.Complex dir);
+
+[ProblemName("The Floor Will Be Lava")]
+class Solution : Solver {
+
+    static readonly Complex Up = -Complex.ImaginaryOne;
+    static readonly Complex Down = Complex.ImaginaryOne;
+    static readonly Complex Left = -Complex.One;
+    static readonly Complex Right = Complex.One;
+
+    public object PartOne(string input) =>
+        EnergizedCells(ParseMap(input), (Complex.Zero, Right));
+
+    public object PartTwo(string input) {
+        var map = ParseMap(input);
+        return (from beam in StartBeams(map) select EnergizedCells(map, beam)).Max();
+    }
+
+    // follow the beam in the map and return the energized cell count. 
+    int EnergizedCells(Map map, Beam beam) {
+
+        // this is essentially just a flood fill algorithm.
+        var q = new Queue([beam]);
+        var seen = new HashSet();
+
+        while (q.TryDequeue(out beam)) {
+            seen.Add(beam);
+            foreach (var dir in Exits(map[beam.pos], beam.dir)) {
+                var pos = beam.pos + dir;
+                if (map.ContainsKey(pos) && !seen.Contains((pos, dir))) {
+                    q.Enqueue((pos, dir));
+                }
+            }
+        }
+
+        return seen.Select(beam => beam.pos).Distinct().Count();
+    }
+
+    // go around the edges (top, right, bottom, left order) of the map
+    // and return the inward pointing directions
+    IEnumerable StartBeams(Map map) {
+        var br = map.Keys.MaxBy(pos => pos.Imaginary + pos.Real);
+        return [
+            ..from pos in map.Keys where pos.Real == 0 select (pos, Down),
+            ..from pos in map.Keys where pos.Real == br.Real select (pos, Left),
+            ..from pos in map.Keys where pos.Imaginary == br.Imaginary select (pos, Up),
+            ..from pos in map.Keys where pos.Imaginary == 0 select (pos, Right),
+        ];
+    }
+
+    // using a dictionary helps with bounds check (simply containskey):
+    Map ParseMap(string input) {
+        var lines = input.Split('\n');
+        return (
+            from irow in Enumerable.Range(0, lines.Length)
+            from icol in Enumerable.Range(0, lines[0].Length)
+            let cell = lines[irow][icol]
+            let pos = new Complex(icol, irow)
+            select new KeyValuePair(pos, cell)
+        ).ToDictionary();
+    }
+
+    // the 'exit' direction(s) of the given cell when entered by a beam moving in 'dir'
+    // we have some special cases for mirrors and spliters, the rest keeps the direction
+    Complex[] Exits(char cell, Complex dir) => cell switch {
+        '-' when dir == Up || dir == Down => [Left, Right],
+        '|' when dir == Left || dir == Right => [Up, Down],
+        '/' => [-new Complex(dir.Imaginary, dir.Real)],
+        '\\' => [new Complex(dir.Imaginary, dir.Real)],
+        _ => [dir]
+    };
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/17/illustration.jpeg b/2023/17/illustration.jpeg new file mode 100644 index 00000000..8c04f08d Binary files /dev/null and b/2023/17/illustration.jpeg differ diff --git a/2023/17/index.html b/2023/17/index.html new file mode 100644 index 00000000..c8494198 --- /dev/null +++ b/2023/17/index.html @@ -0,0 +1,356 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/17 'Clumsy Crucible'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/17

+

Clumsy Crucible

+

in C#

+

+

by encse

+
+ +
+ +
+

Visit the Advent of Code website for the problem statement here.

+

Part 1 and Part 2 differ only in the rules for the small and ultra crucibles. And it turns +out those can be represented by just two integers: one for the minimum steps the crucible +needs to move forward before it can make a turn (or stop), and an other one that puts an +upper limit on the distance it can go in a straight line.

+

The algorithmic part is a pretty standard graph search implemented with a priority queue. +If you've seen one, you've seen them all. We are starting from the top left corner with the +only goal state in the bottom right. Since we are minimizing for heatloss, we can use +that as the priority of the queue items.

+
+
namespace AdventOfCode.Y2023.Day17;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using Map = System.Collections.Generic.Dictionary;
+
+record Crucible(Complex pos, Complex dir, int straight);
+
+[ProblemName("Clumsy Crucible")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Heatloss(input, 0, 3);
+    public object PartTwo(string input) => Heatloss(input, 4, 10);
+
+    // Graph search using a priority queue. We can simply store the heatloss in 
+    // the priority.
+    int Heatloss(string input, int minStraight, int maxStraight) {
+        var map = ParseMap(input);
+        var goal = map.Keys.MaxBy(pos => pos.Imaginary + pos.Real);
+        var q = new PriorityQueue();
+
+        // initial direction: right or down
+        q.Enqueue(new Crucible(pos: 0, dir: 1, straight: 0), 0);
+        q.Enqueue(new Crucible(pos: 0, dir: Complex.ImaginaryOne, straight: 0), 0);
+
+        var seen = new HashSet();
+        while (q.TryDequeue(out var crucible, out var heatloss)) {
+            if (crucible.pos == goal && crucible.straight >= minStraight) {
+                return heatloss;
+            }
+            foreach (var next in Moves(crucible, minStraight, maxStraight)) {
+                if (map.ContainsKey(next.pos) && !seen.Contains(next)) {
+                    seen.Add(next);
+                    q.Enqueue(next, heatloss + map[next.pos]);
+                }
+            }
+        }
+        throw new Exception();
+    }
+
+    // returns possible next states based on the rules
+    IEnumerable Moves(Crucible c, int minStraight, int maxStraight) {
+        if (c.straight < maxStraight) {
+            yield return c with { 
+                pos = c.pos + c.dir, 
+                straight = c.straight + 1 
+            };
+        }
+
+        if (c.straight >= minStraight) {
+            var dir = c.dir * Complex.ImaginaryOne;
+            yield return new Crucible(c.pos + dir, dir, 1);
+            yield return new Crucible(c.pos - dir, -dir, 1);
+        }
+    }
+
+    // using a dictionary helps with bounds check (simply containskey):
+    Map ParseMap(string input) {
+        var lines = input.Split('\n');
+        return (
+            from irow in Enumerable.Range(0, lines.Length)
+            from icol in Enumerable.Range(0, lines[0].Length)
+            let cell = int.Parse(lines[irow].Substring(icol, 1))
+            let pos = new Complex(icol, irow)
+            select new KeyValuePair(pos, cell)
+        ).ToDictionary();
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/18/illustration.jpeg b/2023/18/illustration.jpeg new file mode 100644 index 00000000..2d45b35e Binary files /dev/null and b/2023/18/illustration.jpeg differ diff --git a/2023/18/index.html b/2023/18/index.html new file mode 100644 index 00000000..84a07fde --- /dev/null +++ b/2023/18/index.html @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/18 'Lavaduct Lagoon'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/18

+

Lavaduct Lagoon

+

in C#

+

+

by encse

+
+ +
+ +
+

If you are not familiar with the problem, you can read it here.

+

Both parts ask for the integer area covered by some polygon. But it +wouldn't be Advent of Code, if the polygon came in the form of coordinates. +First we are dealing with some odd dig instruction list with hex colors.

+

The polygon in Part 1 is much smaller and one can use any algorithm from flood fill +to ray casting, but Part 2 makes it clear that we need to pull out the bigger guns.

+

I heard about the Shoelace formula, but haven't used it in practice yet. I knew +that I can calculate the (signed) area of a polygon by summing up some determinants +using the neighbouring vertices. But I haven't heard about Pick's theorem before, so +it made me think for a while to extend this idea to return the integer area instead +of the real one.

+

Having solved Part 1 I could somehow guess the right formula involving half the +boundary plus 1, which sounds just right and was enough for Part 2, then still +being puzzled I went to the solution thread and read about Pick.

+

Pick's theorem connects the area returned by the Shoelace formula with the number +of interior points and points in the boundary. The problem asked for the sum of these.

+

I give myself an extra ⭐ for learning something today.

+
+
namespace AdventOfCode.Y2023.Day18;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+[ProblemName("Lavaduct Lagoon")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Area(Steps1(input));
+    public object PartTwo(string input) => Area(Steps2(input));
+
+    IEnumerable Steps1(string input) =>
+        from line in input.Split('\n')
+        let parts = line.Split(' ')
+        let dir = parts[0] switch {
+            "R" => Complex.One,
+            "U" => -Complex.ImaginaryOne,
+            "L" => -Complex.One,
+            "D" => Complex.ImaginaryOne,
+            _ => throw new Exception()
+        }
+        let dist = int.Parse(parts[1])
+        select dir * dist;
+
+    IEnumerable Steps2(string input) =>
+        from line in input.Split('\n')
+        let hex = line.Split(' ')[2]
+        let dir = hex[7] switch {
+            '0' => Complex.One,
+            '1' => -Complex.ImaginaryOne,
+            '2' => -Complex.One,
+            '3' => Complex.ImaginaryOne,
+            _ => throw new Exception()
+        }
+        let dist = Convert.ToInt32(hex[2..7], 16)
+        select dir * dist;
+
+    // We are using a combination of the shoelace formula with Pick's theorem
+    double Area(IEnumerable steps) {
+        var vertices = Vertices(steps).ToList();
+
+        // Shoelace formula https://en.wikipedia.org/wiki/Shoelace_formula
+        var shiftedVertices = vertices.Skip(1).Append(vertices[0]);
+        var shoelaces =
+            from points in vertices.Zip(shiftedVertices)
+            let p1 = points.First
+            let p2 = points.Second
+            select p1.Real * p2.Imaginary - p1.Imaginary * p2.Real;
+        var area = Math.Abs(shoelaces.Sum()) / 2;
+
+        // Pick's theorem  https://en.wikipedia.org/wiki/Pick%27s_theorem
+        var boundary = steps.Select(x => x.Magnitude).Sum();
+        var interior = area - boundary / 2 + 1;
+
+        // Integer area
+        return boundary + interior;
+    }
+
+    IEnumerable Vertices(IEnumerable steps) {
+        var pos = Complex.Zero;
+        foreach (var step in steps) {
+            pos += step;
+            yield return pos;
+        }
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/19/illustration.jpeg b/2023/19/illustration.jpeg new file mode 100644 index 00000000..bc895699 Binary files /dev/null and b/2023/19/illustration.jpeg differ diff --git a/2023/19/index.html b/2023/19/index.html new file mode 100644 index 00000000..0dcf2215 --- /dev/null +++ b/2023/19/index.html @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/19 'Aplenty'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/19

+

Aplenty

+

in C#

+

+

by encse

+
+ +
+ +
+

Those who need a refresh can read the problem here.

+

Part 1 is an implementation challenge, where you need to model some virtual +machine following certain rules. I jumped on that and wrote it while sipping my +morning coffee. But this is Day 19 and there has to be a twist. We got a totally +different challenge for the second half. It's like opening your calendar and +finding two chocolates instead of one. Yay!

+

Part 2 looks frightening first, but not for a seasoned Advent of Coder with +multiple dimension travels behind his back. It's asking for the volume of a +hypercube. Don't believe? Think about it. We start from a 4000 x 4000 x 4000 x 4000 +cube and slice it up to smaller parts based on the conditions we are given. +(It becomes more of a hyperectangle during this process, but let's not be picky +about names.) At the end we get to some smallish cubes which are either +Accepted or fully Rejected. This algorithm is a bit +similar to what we did in Day 5 and I tried to code it like that.

+

Just follow the instructions precisely and Part 2 is tamed. To clean things up a +bit, we can even reuse this to implement Part 1. (So much about our nice +interpreter from the morning.) Go over the list of parts as they were tiny +1 x 1 x 1 x 1 cubes and check if they are accepted or not.

+

The code is the longest I've written so far, but it's hopefully readable +after this introduction.

+
+
namespace AdventOfCode.Y2023.Day19;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Numerics;
+using Rules = System.Collections.Generic.Dictionary;
+using Cube = System.Collections.Immutable.ImmutableArray;
+
+record Range(int begin, int end);
+record Cond(int dim, char op, int num, string state);
+
+[ProblemName("Aplenty")]
+class Solution : Solver {
+
+    // Part 1 can be understood in the context of Part 2. Part 2 asks to compute 
+    // the accepted volume of a four dimensional hypercube. It has some elaborate 
+    // way to slice up the cube parallel to its edges to smaller and smaller pieces 
+    // and decide if the final sub-sub cubes are accepted or not. Our Part 2 
+    // algorithm follows these rules and returns the 'accepted'volume we are 
+    // looking for. 
+
+    // We can use this algorithm to solve Part 1 starting from unit sized cubes
+    // and checking if they are fully accepted or not.
+
+    public object PartOne(string input) {
+        var parts = input.Split("\n\n");
+        var rules = ParseRules(parts[0]);
+        return (
+            from cube in ParseUnitCube(parts[1])
+            where AcceptedVolume(rules, cube) == 1
+            select cube.Select(r => r.begin).Sum()
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var parts = input.Split("\n\n");
+        var rules = ParseRules(parts[0]);
+        var cube = Enumerable.Repeat(new Range(1, 4000), 4).ToImmutableArray();
+        return AcceptedVolume(rules, cube);
+    }
+
+    BigInteger AcceptedVolume(Rules rules, Cube cube) {
+        var q = new Queue<(Cube cube, string state)>();
+        q.Enqueue((cube, "in"));
+
+        BigInteger res = 0;
+        while (q.Any()) {
+            (cube, var state) = q.Dequeue();
+            if (cube.Any(coord => coord.end < coord.begin)) {
+                continue; // cube is empty
+            } else if (state == "R") {
+                continue; // cube is rejected
+            } else if (state == "A") {
+                res += Volume(cube); // cube is accepted
+            } else {
+                foreach (var stm in rules[state].Split(",")) {
+                    Cond cond = TryParseCond(stm);
+                    if (cond == null) {
+                        q.Enqueue((cube, stm));
+                    } else if (cond.op == '<') {
+                        var (cube1, cube2) = CutCube(cube, cond.dim, cond.num - 1);
+                        q.Enqueue((cube1, cond.state));
+                        cube = cube2;
+                    } else if (cond?.op == '>') {
+                        var (cube1, cube2) = CutCube(cube, cond.dim, cond.num);
+                        cube = cube1;
+                        q.Enqueue((cube2, cond.state));
+                    } 
+                }
+            }
+        }
+        return res;
+    }
+
+    BigInteger Volume(Cube cube) =>
+        cube.Aggregate(BigInteger.One, (m, r) => m * (r.end - r.begin + 1));
+  
+    // Cuts a cube along the specified dimension, other dimensions are unaffected.
+    (Cube lo, Cube hi) CutCube(Cube cube, int dim, int num) {
+        var r = cube[dim];
+        return (
+            cube.SetItem(dim, r with { end = Math.Min(num, r.end) }),
+            cube.SetItem(dim, r with { begin = Math.Max(r.begin, num + 1) })
+        );
+    }
+
+    Cond TryParseCond(string st) =>
+        st.Split('<', '>', ':') switch {
+            ["x", var num, var state] => new Cond(0, st[1], int.Parse(num), state),
+            ["m", var num, var state] => new Cond(1, st[1], int.Parse(num), state),
+            ["a", var num, var state] => new Cond(2, st[1], int.Parse(num), state),
+            ["s", var num, var state] => new Cond(3, st[1], int.Parse(num), state),
+            _ => null
+        };
+
+    Rules ParseRules(string input) => (
+        from line in input.Split('\n')
+        let parts = line.Split('{', '}')
+        select new KeyValuePair(parts[0], parts[1])
+    ).ToDictionary();
+
+    IEnumerable ParseUnitCube(string input) =>
+        from line in input.Split('\n')
+        let nums = Regex.Matches(line, @"\d+").Select(m => int.Parse(m.Value))
+        select nums.Select(n => new Range(n, n)).ToImmutableArray();
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/2/illustration.jpeg b/2023/2/illustration.jpeg new file mode 100644 index 00000000..78bdd14a Binary files /dev/null and b/2023/2/illustration.jpeg differ diff --git a/2023/2/index.html b/2023/2/index.html new file mode 100644 index 00000000..ccd6c5da --- /dev/null +++ b/2023/2/index.html @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/2 'Cube Conundrum'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/2

+

Cube Conundrum

+

in C#

+

+

by encse

+
+ +
+ +
+

The task description is copyrighted, but it's available here.

+

Ok, now we are on track. The hardest part of this problem is the parsing, but I introduced a helper that can extract a number in the context of some regular expression which works like a breeze. What's more, we only need to keep track of the maximum of the red, green and blue boxes, so our Game struct becomes just four integers.

+

The actual algorithm for Part 1 and Part 2 is very simple, and linq makes it quite readable as well.

+
+
namespace AdventOfCode.Y2023.Day02;
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+record Game(int id, int red, int green, int blue);
+
+[ProblemName("Cube Conundrum")]
+class Solution : Solver {
+
+    public object PartOne(string input) => (
+        from line in input.Split("\n")
+        let game = ParseGame(line)
+        where game.red <= 12 && game.green <= 13 && game.blue <= 14
+        select game.id
+    ).Sum();
+
+    public object PartTwo(string input) => (
+        from line in input.Split("\n")
+        let game = ParseGame(line)
+        select game.red * game.green * game.blue
+    ).Sum();
+
+    // no need to keep track of the individual rounds in a game, just return 
+    // the maximum of the red, green, blue boxes
+    Game ParseGame(string line) =>
+        new Game(
+            ParseInts(line, @"Game (\d+)").First(),
+            ParseInts(line, @"(\d+) red").Max(),
+            ParseInts(line, @"(\d+) green").Max(),
+            ParseInts(line, @"(\d+) blue").Max()
+        );
+
+    // extracts integers from a string identified by a single regex group.
+    IEnumerable ParseInts(string st, string rx) =>
+        from m in Regex.Matches(st, rx)
+        select int.Parse(m.Groups[1].Value);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/20/illustration.jpeg b/2023/20/illustration.jpeg new file mode 100644 index 00000000..772a67c5 Binary files /dev/null and b/2023/20/illustration.jpeg differ diff --git a/2023/20/index.html b/2023/20/index.html new file mode 100644 index 00000000..4b318241 --- /dev/null +++ b/2023/20/index.html @@ -0,0 +1,406 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/20 'Pulse Propagation'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/20

+

Pulse Propagation

+

in C#

+

+

by encse

+
+ +
+ +
+

The task description is copyrighted, but it's available here.

+

I modeled Part 1 following the description closely. I didn't want to introduce separate +classes for the gate types, instead created just one Gate type with a function parameter that defines the inner logic. It basically tells what should be emitted when a signal comes in the gate's input.

+

Building on this, I defined factory functions for each +gate type (Nand, FlipFlop and Repeater). I know that this is +Elf logic, but it's 🎄, what did you expect?

+

I added a function that triggers the button and executes all the logic until things settle down. +It returns all signals that were emitted, so that I can work with them in both parts.

+

I think Part 1 doesn't need more explanation. Part 2 however, is a different beast. It's a reverse +engineering problem. We need to tell how many times the button is to be pressed until a +single high value is emitted to the rx gate. The catch is that we need to understand a +bit what's happening, because just blindly pressing the button will not terminate in a reasonable time.

+

I layed out the graph using Graphviz to see what's going on. This immediately showed that +broadcaster feeds four different subgraphs. These work in isolation and a Nand gate +connects their output into rx. Further investigation shows that each subgraph runs in a loop +that has prime length (at least for my input). We just need to multiply +them to solve the second half of the problem.

+
+
namespace AdventOfCode.Y2023.Day20;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using Signal = (string sender, string receiver, bool value);
+
+record Gate(string[] inputs, Func> handle);
+
+[ProblemName("Pulse Propagation")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var gates = ParseGates(input);
+        var values = (
+            from _ in Enumerable.Range(0, 1000)
+            from signal in Trigger(gates)
+            select signal.value
+        ).ToArray();
+        return values.Count(v => v) * values.Count(v => !v);
+    }
+
+    public object PartTwo(string input) {
+        // The input has a special structure. Broadcaster feeds 4 disconnected 
+        // substructures which are channeled into a single nand gate at the end. 
+        // The nand gate is connected into rx. I checked that the substructures 
+        // work in a loop, that has prime length. Just need to multiply them all.
+        var gates = ParseGates(input);
+        var nand = gates["rx"].inputs.Single();
+        var branches = gates[nand].inputs;
+        return branches.Aggregate(1L, (m, branch) => m * LoopLength(input, branch));
+    }
+
+    int LoopLength(string input, string output) {
+        var gates = ParseGates(input);
+        for (var i = 1; ; i++) {
+            var signals = Trigger(gates);
+            if (signals.Any(s => s.sender == output && s.value)) {
+                return i;
+            }
+        }
+    }
+
+    // emits a button press, executes until things settle down and returns 
+    // all signals for investigation.
+    IEnumerable Trigger(Dictionary gates) {
+        var q = new Queue();
+        q.Enqueue(new Signal("button", "broadcaster", false));
+
+        while (q.TryDequeue(out var signal)) {
+            yield return signal;
+
+            var handler = gates[signal.receiver];
+            foreach (var signalT in handler.handle(signal)) {
+                q.Enqueue(signalT);
+            }
+        }
+    }
+
+    Dictionary ParseGates(string input) {
+        input += "\nrx ->"; // an extra rule for rx with no output
+
+        var descriptions =
+            from line in input.Split('\n')
+            let words = Regex.Matches(line, "\\w+").Select(m => m.Value).ToArray()
+            select (kind: line[0], name: words.First(), outputs: words[1..]);
+
+        var inputs = (string name) => (
+            from d in descriptions where d.outputs.Contains(name) select d.name
+        ).ToArray();
+        
+        return descriptions.ToDictionary(
+            d => d.name,
+            d => d.kind switch {
+                '&' => NandGate(d.name, inputs(d.name), d.outputs),
+                '%' => FlipFlop(d.name, inputs(d.name), d.outputs),
+                _ => Repeater(d.name, inputs(d.name), d.outputs)
+            }
+        );
+    }
+
+    Gate NandGate(string name, string[] inputs, string[] outputs) {
+        // initially assign low value for each input:
+        var state = inputs.ToDictionary(input => input, _ => false);
+
+        return new Gate(inputs, (Signal signal) => {
+            state[signal.sender] = signal.value;
+            var value = !state.Values.All(b => b);
+            return outputs.Select(o => new Signal(name, o, value));
+        });
+    }
+
+    Gate FlipFlop(string name, string[] inputs, string[] outputs) {
+        var state = false;
+
+        return new Gate(inputs, (Signal signal) => {
+            if (!signal.value) {
+                state = !state;
+                return outputs.Select(o => new Signal(name, o, state));
+            } else {
+                return [];
+            }
+        });
+    }
+
+    Gate Repeater(string name, string[] inputs, string[] outputs) {
+        return new Gate(inputs, (Signal s) =>
+            from o in outputs select new Signal(name, o, s.value)
+        );
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/21/illustration.jpeg b/2023/21/illustration.jpeg new file mode 100644 index 00000000..843c9e1c Binary files /dev/null and b/2023/21/illustration.jpeg differ diff --git a/2023/21/index.html b/2023/21/index.html new file mode 100644 index 00000000..1fac5ee5 --- /dev/null +++ b/2023/21/index.html @@ -0,0 +1,382 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/21 'Step Counter'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/21

+

Step Counter

+

in C#

+

+

by encse

+
+ +
+ +
+

Let's revisit the problem description here.

+

At first I solved this with carefully maintaining the number of different +tiles (the 131x131 regions that repeat indefinitely) after each step. It +turns out that there are only nine tile categories based on the direction +closest to the starting point. The elf can go straight left, up, right +and down and reach the next tile without obstacles. This is a special +property of the input.

+

Each tile in a category can be in a few hundred different states. The +first one (what I call the seed) is the point where the elf enters the +tile. This can be the center of an edge or one of its corners. After +seeding, the tile ages on its own pace. Thanks to an other property of +the input, tiles are not affected by their neighbourhood. Aging continues +until a tile grows up, when it starts to oscillate between just two +states back and forth.

+

My first solution involved a 9 by 260 matrix containing the number of +tiles in each state. I implemented the aging process and carefully +computed when to seed new tiles for each category.

+

It turns out that if we are looking at only steps where n = 131 * k + 65 +we can compute how many tiles are in each position of the matrix. +I haven't gone through this whole process, just checked a few examples +until I convinced myself that each and every item in the matrix is either +constant or a linear or quadratic function of n.

+

This is not that hard to see as it sounds. After some lead in at the +beginning, things start to work like this: in each batch of 131 steps a +set of center tiles and a set of corner styles is generated. +Always 4 center tiles come in, but corner tiles are linear in n: 1,2,3... +That is the grown up population for center tiles must be linear in n, +and quadratic for the corners (can be computed using triangular numbers).

+

If we know the active positions for each tile category and state, we +can multiply it with the number of tiles and sum it up to get the result. +This all means that if we reorganize the equations we get to a form of:

+
    a * n^2 + b * n + c      if n = k * 131 + 65
+
+

We just need to compute this polynom for 3 values and interpolate. +Finally evaluate for n = 26501365 which happens to be 202300 * 131 + 65 +to get the final result.

+
+
namespace AdventOfCode.Y2023.Day21;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+
+[ProblemName("Step Counter")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Steps(ParseMap(input)).ElementAt(64);
+    public object PartTwo(string input) {
+        // Exploiting some nice properties of the input it reduces to quadratic 
+        // interpolation over 3 points: k * 131 + 65 for k = 0, 1, 2
+        // I used the Newton method.
+        var steps = Steps(ParseMap(input)).Take(328).ToArray();
+
+        (decimal x0, decimal y0) = (65, steps[65]);
+        (decimal x1, decimal y1) = (196, steps[196]);
+        (decimal x2, decimal y2) = (327, steps[327]);
+
+        decimal y01 = (y1 - y0) / (x1 - x0);
+        decimal y12 = (y2 - y1) / (x2 - x1);
+        decimal y012 = (y12 - y01) / (x2 - x0);
+
+        var n = 26501365;
+        return decimal.Round(y0 + y01 * (n - x0) + y012 * (n - x0) * (n - x1));
+    }
+
+    // walks around and returns the number of available positions at each step
+    IEnumerable Steps(HashSet map) {
+        var positions = new HashSet { new Complex(65, 65) };
+        while(true) {
+            yield return positions.Count;
+            positions = Step(map, positions);
+        }
+    }
+    
+    HashSet Step(HashSet map, HashSet positions) {
+        Complex[] dirs = [1, -1, Complex.ImaginaryOne, -Complex.ImaginaryOne];
+
+        var res = new HashSet();
+        foreach (var pos in positions) {
+            foreach (var dir in dirs) {
+                var posT = pos + dir;
+                var tileCol = Mod(posT.Real, 131);
+                var tileRow = Mod(posT.Imaginary, 131);
+                if (map.Contains(new Complex(tileCol, tileRow))) {
+                    res.Add(posT);
+                }
+            }
+        }
+        return res;
+    }
+
+    // the double % takes care of negative numbers
+    double Mod(double n, int m) => ((n % m) + m) % m;
+
+    HashSet ParseMap(string input) {
+        var lines = input.Split("\n");
+        return (
+            from irow in Enumerable.Range(0, lines.Length)
+            from icol in Enumerable.Range(0, lines[0].Length)
+            where lines[irow][icol] != '#'
+            select new Complex(icol, irow)
+        ).ToHashSet();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/22/illustration.jpeg b/2023/22/illustration.jpeg new file mode 100644 index 00000000..135992b9 Binary files /dev/null and b/2023/22/illustration.jpeg differ diff --git a/2023/22/index.html b/2023/22/index.html new file mode 100644 index 00000000..1f2f245c --- /dev/null +++ b/2023/22/index.html @@ -0,0 +1,393 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/22 'Sand Slabs'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/22

+

Sand Slabs

+

in C#

+

+

by encse

+
+ +
+ +
+

The original problem description is available +here.

+

We deserved a simple one today. I started with a function that applies gravity to +the blocks. It orders them in ascending Z order then just runs over the list and +pushes each block down as much as possible. The result is a nicely packed jenga tower.

+

Several helper strucures were introduced to make things easier. I have a Range and +a Block with some helpers like IntersectsXY that tells if the X-Y projection of +two blocks are in cover.

+

I also created a function that returns the support structure of our model at hand, +so that I can tell the upper and lower neighbours of each block easily.

+

The eye catching Kaboom function goes over the input and selects each block for +desintegration. It calculates the number of blocks that start falling when this +single block disappears. The result is a list of integers, which can be used +to answer both questions for today.

+
+
namespace AdventOfCode.Y2023.Day22;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+record Range(int begin, int end);
+record Block(Range x, Range y, Range z) {
+    public int Top => z.end;
+    public int Bottom => z.begin;
+}
+record Supports(
+    Dictionary> blocksAbove,
+    Dictionary> blocksBelow
+);
+
+[ProblemName("Sand Slabs")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Kaboom(input).Count(x => x == 0);
+    public object PartTwo(string input) => Kaboom(input).Sum();
+
+    // desintegrates the blocks one by one and returns how many blocks would
+    // start falling because of that.
+    IEnumerable Kaboom(string input) {
+        var blocks = Fall(ParseBlocks(input));
+        var supports = GetSupports(blocks);
+
+        foreach (var desintegratedBlock in blocks) {
+            var q = new Queue();
+            q.Enqueue(desintegratedBlock);
+
+            var falling = new HashSet();
+            while (q.TryDequeue(out var block)) {
+                falling.Add(block);
+
+                var blocksStartFalling =
+                    from blockT in supports.blocksAbove[block]
+                    where supports.blocksBelow[blockT].IsSubsetOf(falling)
+                    select blockT;
+
+                foreach (var blockT in blocksStartFalling) {
+                    q.Enqueue(blockT);
+                }
+            }
+            yield return falling.Count - 1; // -1: desintegratedBlock doesn't count 
+        }
+    }
+
+    // applies 'gravity' to the blocks.
+    Block[] Fall(Block[] blocks) {
+
+        // sort them in Z first so that we can work in bottom to top order
+        blocks = blocks.OrderBy(block => block.Bottom).ToArray();
+
+        for (var i = 0; i < blocks.Length; i++) {
+            var newBottom = 1;
+            for (var j = 0; j < i; j++) {
+                if (IntersectsXY(blocks[i], blocks[j])) {
+                    newBottom = Math.Max(newBottom, blocks[j].Top + 1);
+                }
+            }
+            var fall = blocks[i].Bottom - newBottom;
+            blocks[i] = blocks[i] with {
+                z = new Range(blocks[i].Bottom - fall, blocks[i].Top - fall)
+            };
+        }
+        return blocks;
+    }
+
+    // calculate upper and lower neighbours for each block
+    Supports GetSupports(Block[] blocks) {
+        var blocksAbove = blocks.ToDictionary(b => b, _ => new HashSet());
+        var blocksBelow = blocks.ToDictionary(b => b, _ => new HashSet());
+        for (var i = 0; i < blocks.Length; i++) {
+            for (var j = i + 1; j < blocks.Length; j++) {
+                var zNeighbours = blocks[j].Bottom == 1 + blocks[i].Top;
+                if (zNeighbours && IntersectsXY(blocks[i], blocks[j])) {
+                    blocksBelow[blocks[j]].Add(blocks[i]);
+                    blocksAbove[blocks[i]].Add(blocks[j]);
+                }
+            }
+        }
+        return new Supports(blocksAbove, blocksBelow);
+    }
+
+    bool IntersectsXY(Block blockA, Block blockB) =>
+        Intersects(blockA.x, blockB.x) && Intersects(blockA.y, blockB.y);
+
+    // see https://stackoverflow.com/a/3269471
+    bool Intersects(Range r1, Range r2) => r1.begin <= r2.end && r2.begin <= r1.end;
+
+    Block[] ParseBlocks(string input) => (
+        from line in input.Split('\n')
+        let numbers = line.Split(',','~').Select(int.Parse).ToArray()
+        select new Block(
+            x: new Range(numbers[0], numbers[3]), 
+            y: new Range(numbers[1], numbers[4]), 
+            z: new Range(numbers[2], numbers[5])
+        )
+    ).ToArray();
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/23/illustration.jpeg b/2023/23/illustration.jpeg new file mode 100644 index 00000000..cdd40350 Binary files /dev/null and b/2023/23/illustration.jpeg differ diff --git a/2023/23/index.html b/2023/23/index.html new file mode 100644 index 00000000..cceef1bc --- /dev/null +++ b/2023/23/index.html @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/23 'A Long Walk'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/23

+

A Long Walk

+

in C#

+

+

by encse

+
+ +
+ +
+

Visit the Advent of Code website for the problem statement here.

+

Today's problem looked frightening first, because it's asking for the longest +path between two points of a map. Shortest path is a no brainer with Dijkstra +or whatever graph search, but I don't know about an efficient way to calculate +the longest one. I have a feeling that it is somehow related to the Hamiltonian path +which is NP-complete, so there might not even exists a super efficient algorithm to +solve today's problem in the generic case.

+

But this is a puzzle, so let's get to it. I decided to convert the problem from +map traversal to graph traversal first. Created nodes from the crossroads of +the map (those tiles that connect 3 or more "." cells). Also assigned a node to +the entry and one to the exit.

+

Two nodes become connected if there is a road between them. That is, they are +reachable following the path in the map without visiting other crossroads in +between.

+

This reduced the problem quite a bit. In my case it went down to about 30 nodes +and 120 edges for Part 2. Part 1 is even smaller with 60 edges or so.

+

This graph is small enough to solve it using dynamic programming with a cache. +Since we have just 30+ nodes, I represented them as powers of 2 and a set of +these became a bitset stored in a long.

+
+
namespace AdventOfCode.Y2023.Day23;
+
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Linq;
+using Map = System.Collections.Generic.Dictionary;
+using Node = long;
+record Edge(Node start, Node end, int distance);
+
+[ProblemName("A Long Walk")]
+class Solution : Solver {
+
+    // Instead of dealing with the 'map' tiles directly, we convert it to a graph.
+    // Nodes: the entry tile, the exit and the crossroad tiles.
+    // Edges: two nodes are connected if there is a direct path between them that 
+    //        doesn't contain crossroads.
+    // This reduces a problem to ~30 nodes and 120 edges for the Part 2 case
+    // which can be solved using a dynamic programming approach.
+
+    static readonly Complex Up = -Complex.ImaginaryOne;
+    static readonly Complex Down = Complex.ImaginaryOne;
+    static readonly Complex Left = -1;
+    static readonly Complex Right = 1;
+    static readonly Complex[] Dirs = [Up, Down, Left, Right];
+
+    Dictionary exits = new() {
+        ['<'] = [Left],
+        ['>'] = [Right],
+        ['^'] = [Up],
+        ['v'] = [Down],
+        ['.'] = Dirs,
+        ['#'] = []
+    };
+
+    public object PartOne(string input) => Solve(input);
+    public object PartTwo(string input) => Solve(RemoveSlopes(input));
+
+    string RemoveSlopes(string st) =>
+        string.Join("", st.Select(ch => ">v<^".Contains(ch) ? '.' : ch));
+
+    int Solve(string input) {
+        var (nodes, edges) = MakeGraph(input);
+        var (start, goal) = (nodes.First(), nodes.Last()); 
+
+        // Dynamic programming using a cache, 'visited' is a bitset of 'nodes'.
+        var cache = new Dictionary<(Node, long), int>();
+        int LongestPath(Node node, long visited) {
+            if (node == goal) {
+                return 0;
+            } else if ((visited & node) != 0) {
+                return int.MinValue; // small enough to represent '-infinity'
+            }
+            var key = (node, visited);
+            if (!cache.ContainsKey(key)) {
+                cache[key] = edges
+                    .Where(e => e.start == node)
+                    .Select(e => e.distance + LongestPath(e.end, visited | node))
+                    .Max();
+            }
+            return cache[key];
+        }
+        return LongestPath(start, 0); 
+    }
+
+    (Node[], Edge[]) MakeGraph(string input) {
+        var map = ParseMap(input);
+
+        // row-major order: 'entry' node comes first and 'exit' is last
+        var nodePos = (
+            from pos in map.Keys
+            orderby pos.Imaginary, pos.Real
+            where IsFree(map, pos) && !IsRoad(map, pos)
+            select pos
+        ).ToArray();
+
+        var nodes = (
+            from i in Enumerable.Range(0, nodePos.Length) select 1L << i
+        ).ToArray();
+
+        var edges = (
+            from i in Enumerable.Range(0, nodePos.Length)
+            from j in Enumerable.Range(0, nodePos.Length)
+            where i != j
+            let distance = Distance(map, nodePos[i], nodePos[j])
+            where distance > 0
+            select new Edge(nodes[i], nodes[j], distance)
+        ).ToArray();
+
+        return (nodes, edges);
+    }
+
+    // Length of the road between two crossroads; -1 if not neighbours
+    int Distance(Map map, Complex crossroadA, Complex crossroadB) {
+        var q = new Queue<(Complex, int)>();
+        q.Enqueue((crossroadA, 0));
+
+        var visited = new HashSet { crossroadA };
+        while (q.Any()) {
+            var (pos, dist) = q.Dequeue();
+            foreach (var dir in exits[map[pos]]) {
+                var posT = pos + dir;
+                if (posT == crossroadB) {
+                    return dist + 1;
+                }  else if (IsRoad(map, posT) && !visited.Contains(posT)) {
+                    visited.Add(posT);
+                    q.Enqueue((posT, dist + 1));
+                }
+            }
+        }
+        return -1;
+    }
+
+    bool IsFree(Map map, Complex p) =>
+        map.ContainsKey(p) && map[p] != '#';
+
+    bool IsRoad(Map map, Complex p) => 
+        IsFree(map, p) && Dirs.Count(d => IsFree(map, p + d)) == 2;
+
+    Map ParseMap(string input) {
+        var lines = input.Split('\n');
+        return (
+            from irow in Enumerable.Range(0, lines.Length)
+            from icol in Enumerable.Range(0, lines[0].Length)
+            let pos = new Complex(icol, irow)
+            select new KeyValuePair(pos, lines[irow][icol])
+        ).ToDictionary();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/24/illustration.jpeg b/2023/24/illustration.jpeg new file mode 100644 index 00000000..77f5b727 Binary files /dev/null and b/2023/24/illustration.jpeg differ diff --git a/2023/24/index.html b/2023/24/index.html new file mode 100644 index 00000000..06d001ed --- /dev/null +++ b/2023/24/index.html @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/24 'Never Tell Me The Odds'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/24

+

Never Tell Me The Odds

+

in C#

+

+

by encse

+
+ +
+ +
+

If you are not familiar with the problem, you can read it here.

+

A bit unexpectedly we are given a geometry problem that requires floating +point numbers. I don't remember if this was ever needed in Advent of Code.

+

Part 1 asks to find the intesection of two 2 dimensional lines. This is +simple enough, but .Net doesn't have a built in matrix library, so I had to +inline everything that was needed. Part 2 was much more interesting. We have +to find a position and velocity of a stone that hits all particles provided in +the input. The particles move in a 3D line now.

+

I solved this first using the Chinese Remainder Theorem, but I didn't like it +because it was totally independent of Part 1, almost like two different problems. +I went looking around in others' solutions until I found a good one that is easy +to follow.

+

The idea is that we try to guess the speed of our stone (a for loop), then assuming +that it is the right velocity create a new reference frame that moves with +that speed. The stone doesn't move in this frame, it has some fixed coordinates +somewhere. Now transform each particle into this reference frame as well. Since the +stone is not moving, if we properly guessed the speed, we find that each particle +meets at the same point. This must be the stone's location.

+

We can reuse code from Part 1, just need to project everything to the XY +plane first to compute the stone's (x,y) position, then do the same in the XZ +or YZ plane to get z as well.

+
+
namespace AdventOfCode.Y2023.Day24;
+
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Data;
+
+record Vec2(decimal x0, decimal x1);
+record Vec3(decimal x0, decimal x1, decimal x2);
+record Particle2(Vec2 pos, Vec2 vel);
+record Particle3(Vec3 pos, Vec3 vel);
+
+[ProblemName("Never Tell Me The Odds")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var particles = Project(ParseParticles(input), v => (v.x0, v.x1));
+
+        var inRange = (decimal d) => 2e14m <= d && d <= 4e14m;
+
+        var inFuture = (Particle2 p, Vec2 pos) => 
+            Math.Sign(pos.x0 - p.pos.x0) == Math.Sign(p.vel.x0);
+
+        var res = 0;
+        for (var i = 0; i < particles.Length; i++) {
+            for (var j = i + 1; j < particles.Length; j++) {
+                var pos = Intersection(particles[i], particles[j]);
+                if (pos != null && 
+                    inRange(pos.x0) && 
+                    inRange(pos.x1) &&
+                    inFuture(particles[i], pos) && 
+                    inFuture(particles[j], pos)
+                ) {
+                    res++;
+                }
+            }
+        }
+        return res;
+    }
+
+    public object PartTwo(string input) {
+        var particles = ParseParticles(input);
+        var stoneXY = Solve2D(Project(particles, vec => (vec.x0, vec.x1)));
+        var stoneXZ = Solve2D(Project(particles, vec => (vec.x0, vec.x2)));
+        return Math.Round(stoneXY.x0 + stoneXY.x1 + stoneXZ.x1);
+    }
+
+    Vec2 Solve2D(Particle2[] particles) {
+        // We try to guess the speed of our stone (a for loop), then supposing 
+        // that it is the right velocity we create a new reference frame that 
+        // moves with that speed. The stone doesn't move in this frame, it has 
+        // some fixed unknown coordinates. Now transform each particle into 
+        // this reference frame as well. Since the stone is not moving, if we 
+        // properly guessed the speed, we find that each particle meets at the 
+        // same point. This must be the stone's location.
+
+        var translateV = (Particle2 p, Vec2 vel) =>
+            new Particle2(p.pos, new Vec2(p.vel.x0 - vel.x0, p.vel.x1 - vel.x1));
+
+        var s = 500; //arbitrary limits for the brute force that worked for me.
+        for (var v1 = -s; v1 < s; v1++) {
+            for (var v2 = -s; v2 < s; v2++) {
+                var vel = new Vec2(v1, v2);
+
+                // p0 and p1 are linearly independent (for me) => stone != null
+                var stone = Intersection(
+                    translateV(particles[0], vel),
+                    translateV(particles[1], vel)
+                );
+
+                if (particles.All(p => Hits(translateV(p, vel), stone))) {
+                    return stone;
+                }
+            }
+        }
+        throw new Exception();
+    }
+
+    bool Hits(Particle2 p, Vec2 pos) {
+        var d = (pos.x0 - p.pos.x0) * p.vel.x1 - (pos.x1 - p.pos.x1) * p.vel.x0;
+        return Math.Abs(d) < (decimal)0.0001;
+    }
+
+    Vec2 Intersection(Particle2 p1, Particle2 p2) {
+        // this would look way better if I had a matrix library at my disposal.
+        var determinant = p1.vel.x0 * p2.vel.x1 - p1.vel.x1 * p2.vel.x0;
+        if (determinant == 0) {
+            return null; //particles don't meet
+        }
+        
+        var b0 = p1.vel.x0 * p1.pos.x1 - p1.vel.x1 * p1.pos.x0;
+        var b1 = p2.vel.x0 * p2.pos.x1 - p2.vel.x1 * p2.pos.x0;
+       
+        return new (
+             (p2.vel.x0 * b0 - p1.vel.x0 * b1) / determinant,
+             (p2.vel.x1 * b0 - p1.vel.x1 * b1) / determinant
+         );
+    }
+
+    Particle3[] ParseParticles(string input) => [..
+        from line in input.Split('\n')
+        let v = ParseNum(line)
+        select new Particle3(new (v[0], v[1], v[2]), new (v[3], v[4], v[5]))
+    ];
+
+    decimal[] ParseNum(string l) => [.. 
+        from m in Regex.Matches(l, @"-?\d+") select decimal.Parse(m.Value)
+    ];
+
+    // Project particles to a 2D plane:
+    Particle2[] Project(Particle3[] ps, Func proj) => [..
+        from p in ps select new Particle2(
+            new Vec2(proj(p.pos).Item1, proj(p.pos).Item2),
+            new Vec2(proj(p.vel).Item1, proj(p.vel).Item2)
+        )
+    ];
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/25/illustration.jpeg b/2023/25/illustration.jpeg new file mode 100644 index 00000000..42399f31 Binary files /dev/null and b/2023/25/illustration.jpeg differ diff --git a/2023/25/index.html b/2023/25/index.html new file mode 100644 index 00000000..95b35da1 --- /dev/null +++ b/2023/25/index.html @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/25 'Snowverload'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/25

+

Snowverload

+

in C#

+

+

by encse

+
+ +
+ +
+

Those who need a refresh can read the problem here.

+

This is our last day and these are historically not very hard. The puzzle is asking us +to cut an undirected graph into two components by removing only three edges. I had +absolutely no idea how to do that in an effective way, so it was time to consult the +literature. Soon enough I found Karger's algorithm +on Wikipedia.

+

It's a randomized algorithm that works on non-weighted, undirected graphs like ours. +It finds some cut which is not necessarily minimal, but there is a good chance +that it finds the minimal one in a few tries. This is the Elf way!

+

Karger's is not hard to implement, but I'm not used to do this kind of things lately, +so I spent quite a lot of time getting it right. One mistake was that I didn't +add the edges in the reverse direction: the input contains them only in one way. Then it was not obvious what to do with multiple edges between two nodes, because the algorithm needs to create these. +But it has started to work and I just let it do its thing in a loop and it really +found a cut with 3 edges in a few milliseconds.

+

It was easy to extend the algorithm to return the sizes of the two components as well. +Part 1 asks for the product of these. Part 2 is a meta puzzle, it requires to complete +all other challenges from the previous days, but I already finished those, so I can +conclude season today (Dec 25th).

+

Thanks for joining me! If you find this work useful or want to get in touch +(even just saying hello), find me on Github or +Twitter.

+

Psst! There is game hidden in this site.

+
+
namespace AdventOfCode.Y2023.Day25;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+[ProblemName("Snowverload")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        Random r = new Random(25);
+
+        // run Karger's algorithm until it finds a cut with 3 edges
+        var (cutSize, c1, c2) = FindCut(input, r);
+        while (cutSize != 3) {
+            (cutSize, c1, c2) = FindCut(input, r);
+        }
+        return c1 * c2;
+    }
+
+    // https://en.wikipedia.org/wiki/Karger%27s_algorithm
+    // Karger's algorithm finds a cut of a graph and returns its size. 
+    // It's not necessarily the minimal cut, because it's a randomized algorithm 
+    // but it's 'likely' to find the minimal cut in reasonable time. 
+    // The algorithm is extended to return the sizes of the two components 
+    // separated by the cut as well.
+    (int size, int c1, int c2) FindCut(string input, Random r) {
+        var graph = Parse(input);
+        var componentSize = graph.Keys.ToDictionary(k => k, _ => 1);
+
+        // updates backreferences of oldNode to point to newNode
+        var rebind = (string oldNode, string newNode) => {
+            foreach (var n in graph[oldNode]) {
+                while (graph[n].Remove(oldNode)) {
+                    graph[n].Add(newNode);
+                }
+            }
+        };
+
+        for (var id = 0; graph.Count > 2; id++) {
+            // decrease the the number of nodes by one. First select two nodes u 
+            // and v connected with an edge. Introduce a new node that inherits 
+            // every edge going out of these (excluding the edges between them). 
+            // Set the new nodes' component size to the sum of the component 
+            // sizes of u and v. Remove u and v from the graph.
+            var u = graph.Keys.ElementAt(r.Next(graph.Count));
+            var v = graph[u][r.Next(graph[u].Count)];
+
+            var merged = "merge-" + id;
+            graph[merged] = [
+                ..from n in graph[u] where n != v select n,
+                ..from n in graph[v] where n != u select n
+            ];
+            rebind(u, merged);
+            rebind(v, merged);
+
+            componentSize[merged] = componentSize[u] + componentSize[v];
+
+            graph.Remove(u);
+            graph.Remove(v);
+        }
+
+        // two nodes remain with some edges between them, the number of those 
+        // edges equals to the size of the cut. Component size tells the number 
+        // of nodes in the two sides created by the cut.
+        var nodeA = graph.Keys.First();
+        var nodeB = graph.Keys.Last();
+        return (graph[nodeA].Count(), componentSize[nodeA], componentSize[nodeB]);
+    }
+
+    // returns an adjacency list representation of the input. Edges are recorded 
+    // both ways, unlike in the input which contains them in one direction only.
+    Dictionary> Parse(string input) {
+        var graph = new Dictionary>();
+
+        var registerEdge = (string u, string v) => {
+            if (!graph.ContainsKey(u)) {
+                graph[u] = new();
+            }
+            graph[u].Add(v);
+        };
+
+        foreach (var line in input.Split('\n')) {
+            var parts = line.Split(": ");
+            var u = parts[0];
+            var nodes = parts[1].Split(' ');
+            foreach (var v in nodes) {
+                registerEdge(u, v);
+                registerEdge(v, u);
+            }
+        }
+        return graph;
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/3/illustration.jpeg b/2023/3/illustration.jpeg new file mode 100644 index 00000000..c31a3973 Binary files /dev/null and b/2023/3/illustration.jpeg differ diff --git a/2023/3/index.html b/2023/3/index.html new file mode 100644 index 00000000..9538a591 --- /dev/null +++ b/2023/3/index.html @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/3 'Gear Ratios'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/3

+

Gear Ratios

+

in C#

+

+

by encse

+
+ +
+ +
+

Let's revisit the problem description here.

+

There are multiple ways to footgun ourselves with this one, if somebody is not +careful with the parser. I solved this problem using regular expressions. First I +searched for all numbers and symbols, then collected those that were +adjacent to each other.

+

I did the same trick in Part 2, but now searched for all gear symbols (*) and +filtered out those that are adjacent to exactly two numbers.

+

Probably the hardest part is to tell if two matches are adjacent or not.

+
+
namespace AdventOfCode.Y2023.Day03;
+
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+[ProblemName("Gear Ratios")]
+class Solution : Solver {
+
+    // Introduce a Parse function that returns the interesting 'blocks' of texts 
+    // and positions using a regex. Then just filter and match these according
+    // to the problem spec.
+
+    public object PartOne(string input) {
+        var rows = input.Split("\n");
+        var symbols = Parse(rows, new Regex(@"[^.0-9]"));
+        var nums = Parse(rows, new Regex(@"\d+"));
+
+        return (
+            from n in nums
+            where symbols.Any(s => Adjacent(s, n))
+            select n.Int
+        ).Sum();
+    }
+
+    public object PartTwo(string input) {
+        var rows = input.Split("\n");
+        var gears = Parse(rows, new Regex(@"\*"));
+        var numbers = Parse(rows, new Regex(@"\d+"));
+
+        return (
+            from g in gears
+            let neighbours = from n in numbers where Adjacent(n, g) select n.Int
+            where neighbours.Count() == 2
+            select neighbours.First() * neighbours.Last()
+        ).Sum();
+    }
+
+    // checks that the parts are touching each other, i.e. rows are within 1 
+    // step and also the columns (using https://stackoverflow.com/a/3269471).
+    bool Adjacent(Part p1, Part p2) =>
+        Math.Abs(p2.Irow - p1.Irow) <= 1 &&
+        p1.Icol <= p2.Icol + p2.Text.Length &&
+        p2.Icol <= p1.Icol + p1.Text.Length;
+
+    // returns the matches of rx with its coordinates
+    Part[] Parse(string[] rows, Regex rx) => (
+        from irow in Enumerable.Range(0, rows.Length)
+        from match in rx.Matches(rows[irow])
+        select new Part(match.Value, irow, match.Index)
+    ).ToArray();
+}
+
+record Part(string Text, int Irow, int Icol) {
+    public int Int => int.Parse(Text);
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/4/illustration.jpeg b/2023/4/illustration.jpeg new file mode 100644 index 00000000..04e0b6e6 Binary files /dev/null and b/2023/4/illustration.jpeg differ diff --git a/2023/4/index.html b/2023/4/index.html new file mode 100644 index 00000000..2b53ffde --- /dev/null +++ b/2023/4/index.html @@ -0,0 +1,326 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/4 'Scratchcards'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/4

+

Scratchcards

+

in C#

+

+

by encse

+
+ +
+ +
+

The original problem description is available here.

+

An other day! In Part 1 we need to determine how many winning numbers we have +in a scratch card, this is simple enough.

+

Part 2 can be treated in a very-very bad way if somebody doesn't notice that it's +nothing else but a loop!. We start with a single card #1 and see how many +cards we are winning, this will generate some new cards of id 2, 3 and so. Then move +to card(s) #2 and continue this process until the end of the list. Return +the number of all cards we dealt with.

+
+
namespace AdventOfCode.Y2023.Day04;
+
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+record Card(int matches);
+
+[ProblemName("Scratchcards")]
+class Solution : Solver {
+
+    public object PartOne(string input) => (
+         from line in input.Split("\n")
+         let card = ParseCard(line)
+         where card.matches > 0
+         select Math.Pow(2, card.matches - 1)
+    ).Sum();
+
+    // Quite imperatively, just walk over the cards keeping track of the counts.
+    public object PartTwo(string input) {
+        var cards = input.Split("\n").Select(ParseCard).ToArray();
+        var counts = cards.Select(_ => 1).ToArray();
+
+        for (var i = 0; i < cards.Length; i++) {
+            var (card, count) = (cards[i], counts[i]);
+            for (var j = 0; j < card.matches; j++) {
+                counts[i + j + 1] += count;
+            }
+        }
+        return counts.Sum();
+    }
+
+    // Only the match count is relevant for a card
+    Card ParseCard(string line) {
+        var parts = line.Split(':', '|');
+        var l = from m in Regex.Matches(parts[1], @"\d+") select m.Value;
+        var r = from m in Regex.Matches(parts[2], @"\d+") select m.Value;
+        return new Card(l.Intersect(r).Count());
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/5/illustration.jpeg b/2023/5/illustration.jpeg new file mode 100644 index 00000000..228173ec Binary files /dev/null and b/2023/5/illustration.jpeg differ diff --git a/2023/5/index.html b/2023/5/index.html new file mode 100644 index 00000000..fb61eb73 --- /dev/null +++ b/2023/5/index.html @@ -0,0 +1,361 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/5 'If You Give A Seed A Fertilizer'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/5

+

If You Give A Seed A Fertilizer

+

in C#

+

+

by encse

+
+ +
+ +
+

Visit the Advent of Code website for the problem statement here.

+

A more tricky problem today. We have a set of numbers that need to be transformed by a series of maps, then we need to return the minimum of all outcomes.

+

This might sound simple, but Part 2 transforms it to a more interesting problem where the inputs are not numbers but ranges. Our maps split the ranges into other ranges, so a lot of special cases and possible off-by-one errors appear on the horizon.

+

I created a function that deals with just one map but multiple ranges. The ranges are fed into a queue and I process them one by one. There are just three possiblites: the map tells nothing about the range, it maps the range to a single range or some cutting is required. The first cases are simply enough, only the last one is interesting. It can happen that our range need to be cut into 2, 3, 4 or even more parts, so this would be hard to handle in a single step. So what I did was simply just make a single cut that generates two new ranges and add these back to the queue. They will be taken care about later. At the end they will be cut enough times so that the parts can be processed by one of the two simple cases above.

+

Having a function to do the heavy lifting, I can push all ranges though all the maps easily, then take the minimum of the result.

+
+
namespace AdventOfCode.Y2023.Day05;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+record Range(long begin, long end);
+
+[ProblemName("If You Give A Seed A Fertilizer")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, PartOneRanges);
+    public object PartTwo(string input) => Solve(input, PartTwoRanges);
+
+    long Solve(string input, Func, IEnumerable> parseSeeds) {
+        var blocks = input.Split("\n\n");
+        var seedRanges = parseSeeds(ParseNumbers(blocks[0])).ToList();
+        var maps = blocks.Skip(1).Select(ParseMap).ToArray();
+
+        // Project each range through the series of maps, this will result some
+        // new ranges. Return the leftmost value (minimum) of these.
+        return maps.Aggregate(seedRanges, Project).Select(r => r.begin).Min();
+    }
+
+    List Project(List inputRanges, Dictionary map) {
+        var input = new Queue(inputRanges);
+        var output = new List();
+
+        while (input.Any()) {
+            var range = input.Dequeue();
+            // If no entry intersects our range -> just add it to the output. 
+            // If an entry completely contains the range -> add after mapping.
+            // Otherwise, some entry partly covers the range. In this case 'chop' 
+            // the range into two halfs getting rid of the intersection. The new 
+            // pieces are added back to the queue for further processing and will be 
+            // ultimately consumed by the first two cases.
+            var src = map.Keys.FirstOrDefault(src => Intersects(src, range));
+            if (src == null) {
+                output.Add(range);
+            } else if (src.begin <= range.begin && range.end <= src.end) {
+                var dst = map[src];
+                var shift = dst.begin - src.begin;
+                output.Add(new Range(range.begin + shift, range.end + shift));
+            } else if (range.begin < src.begin) {
+                input.Enqueue(new Range(range.begin, src.begin - 1));
+                input.Enqueue(new Range(src.begin, range.end));
+            } else {
+                input.Enqueue(new Range(range.begin, src.end));
+                input.Enqueue(new Range(src.end + 1, range.end));
+            }
+        }
+        return output;
+    }
+
+    // see https://stackoverflow.com/a/3269471
+    bool Intersects(Range r1, Range r2) => r1.begin <= r2.end && r2.begin <= r1.end;
+
+    // consider each number as a range of 1 length
+    IEnumerable PartOneRanges(IEnumerable numbers) =>
+        from n in numbers select new Range(n, n);
+
+    // chunk is a great way to iterate over the pairs of numbers
+    IEnumerable PartTwoRanges(IEnumerable numbers) =>
+        from n in numbers.Chunk(2) select new Range(n[0], n[0] + n[1] - 1);
+
+    IEnumerable ParseNumbers(string input) =>
+        from m in Regex.Matches(input, @"\d+") select long.Parse(m.Value);
+
+    Dictionary ParseMap(string input) => (
+        from line in input.Split("\n").Skip(1)
+        let parts = ParseNumbers(line).ToArray()
+        select new KeyValuePair(
+            new Range(parts[1], parts[2] + parts[1] - 1),
+            new Range(parts[0], parts[2] + parts[0] - 1))
+    ).ToDictionary();
+}
+
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/6/illustration.jpeg b/2023/6/illustration.jpeg new file mode 100644 index 00000000..04ff19cd Binary files /dev/null and b/2023/6/illustration.jpeg differ diff --git a/2023/6/index.html b/2023/6/index.html new file mode 100644 index 00000000..27711c18 --- /dev/null +++ b/2023/6/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/6 'Wait For It'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/6

+

Wait For It

+

in C#

+

+

by encse

+
+ +
+ +
+

If you are not familiar with the problem, you can read it here.

+

This has been a simple problem, could be solved even with brute forcing, but I went the +maths path and implemented a quadratic equation solver instead.

+

It's easy to compute how far our boat moves if we wait for x ms at the beginning. +The solution to this equation tells us the x-es for which we break the record distance.

+

Part 2 is just Part 1 with bigger numbers.

+
+
namespace AdventOfCode.Y2023.Day06;
+
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+[ProblemName("Wait For It")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input);
+    public object PartTwo(string input) => Solve(input.Replace(" ", ""));
+
+    long Solve(string input) {
+        var rows = input.Split("\n");
+        var times = Parse(rows[0]);
+        var records = Parse(rows[1]);
+
+        var res = 1L;
+        for (var i = 0; i < times.Length; i++) {
+            res *= WinningMoves(times[i], records[i]);
+        }
+        return res;
+    }
+
+    long WinningMoves(long time, long record) {
+        // If we wait x ms, our boat moves `(time - x) * x` millimeters.
+        // This breaks the record when `(time - x) * x > record`
+        // or `-x^2  + time * x - record > 0`.
+
+        // get the roots first
+        var (x1, x2) = SolveEq(-1, time, -record);
+        
+        // integers in between the roots
+        var maxX = (long)Math.Ceiling(x2) - 1;
+        var minX = (long)Math.Floor(x1) + 1;
+        return maxX - minX + 1; 
+    }
+
+    // solves ax^2 + bx + c = 0 (supposing two different roots)
+    (double, double) SolveEq(long a, long b, long c) {
+        var d = Math.Sqrt(b * b - 4 * a * c);
+        var x1 = (-b - d) / (2 * a);
+        var x2 = (-b + d) / (2 * a);
+        return (Math.Min(x1, x2), Math.Max(x1, x2));
+    }
+
+    long[] Parse(string input) => (
+        from m in Regex.Matches(input, @"\d+")
+        select long.Parse(m.Value)
+    ).ToArray();
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/7/illustration.jpeg b/2023/7/illustration.jpeg new file mode 100644 index 00000000..beb93d33 Binary files /dev/null and b/2023/7/illustration.jpeg differ diff --git a/2023/7/index.html b/2023/7/index.html new file mode 100644 index 00000000..2bf7031c --- /dev/null +++ b/2023/7/index.html @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/7 'Camel Cards'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/7

+

Camel Cards

+

in C#

+

+

by encse

+
+ +
+ +
+

Those who need a refresh can read the problem here.

+

We are playing poker Camel Cards today! In Part 1 we need to evalute hands and put them in order. Each +hand has what I call a pattern value: five of a kind, poker, full house, three of a kind, double +pair or pair and some individual card value such as: 1, 2, ..., J, Q, K, or A.

+

Pattern value becomes one number, card value becomes an other number then let linq do the ordering for me.

+

Part 2 is not much different, but the individual card value changes, and J becomes +a joker that can replace any other cards. I made a shortcut here and just reused the functions from Part 1.

+
+
namespace AdventOfCode.Y2023.Day07;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+[ProblemName("Camel Cards")]
+class Solution : Solver {
+
+    // Each 'hand' gets points based on the card's individual value and  
+    // pattern value.
+
+    public object PartOne(string input) => Solve(input, Part1Points);
+    public object PartTwo(string input) => Solve(input, Part2Points);
+
+    (long, long) Part1Points(string hand) =>
+        (PatternValue(hand), CardValue(hand, "123456789TJQKA"));
+
+    (long, long) Part2Points(string hand) {
+        var cards = "J123456789TQKA";
+        var patternValue = 
+            cards.Select(ch => PatternValue(hand.Replace('J', ch))).Max();
+        return (patternValue, CardValue(hand, cards));
+    }
+
+    // map cards to their indices in cardOrder. E.g. for 123456789TJQKA
+    // A8A8A becomes (13)(7)(13)(7)(13), 9A34Q becomes (8)(13)(2)(3)(11)
+    long CardValue(string hand, string cardOrder) =>
+        Pack(hand.Select(card => cardOrder.IndexOf(card)));
+
+    // map cards to the number of their occurrences in the hand then order them 
+    // such thatA8A8A becomes 33322, 9A34Q becomes 11111 and K99AA becomes 22221
+    long PatternValue(string hand) =>
+        Pack(hand.Select(card => hand.Count(x => x == card)).OrderDescending());
+
+    long Pack(IEnumerable numbers) => 
+        numbers.Aggregate(1L, (a, v) => (a * 256) + v);
+
+    int Solve(string input, Func getPoints) {
+        var bidsByRanking = (
+            from line in input.Split("\n")
+            let hand = line.Split(" ")[0]
+            let bid = int.Parse(line.Split(" ")[1])
+            orderby getPoints(hand)
+            select bid
+        );
+
+        return bidsByRanking.Select((bid, rank) => (rank + 1) * bid).Sum();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/8/illustration.jpeg b/2023/8/illustration.jpeg new file mode 100644 index 00000000..f4243ea8 Binary files /dev/null and b/2023/8/illustration.jpeg differ diff --git a/2023/8/index.html b/2023/8/index.html new file mode 100644 index 00000000..54a5dce4 --- /dev/null +++ b/2023/8/index.html @@ -0,0 +1,332 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/8 'Haunted Wasteland'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/8

+

Haunted Wasteland

+

in C#

+

+

by encse

+
+ +
+ +
+

The task description is copyrighted, but it's available here.

+

We need to implement some process that is called wandering around the desert and it's essentially a +series of dictionary lookups that lead to other dictionary lookups.

+

Pretty dry as I'm writing it down, but the point is that after some iterations we get from AAA to ZZZ. +Part 1 asks for the number of steps needed for that.

+

Part 2 gives it a spin and is asking us to start from all nodes that end with the letter A at once, +and continue wandering around in parallel until we reach Z nodes simultanously in every path!

+

Obviously, this would take ages to wait out, but fortunately the input is specially crafted so that we can take the least common multiplier of the length of the individual loops and return just that.

+
+
namespace AdventOfCode.Y2023.Day08;
+
+using System.Linq;
+using System.Text.RegularExpressions;
+using Map = System.Collections.Generic.Dictionary;
+
+[ProblemName("Haunted Wasteland")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, "AAA", "ZZZ");
+    public object PartTwo(string input) => Solve(input, "A", "Z");
+
+    long Solve(string input, string aMarker, string zMarker) {
+        var blocks = input.Split("\n\n");
+        var dirs = blocks[0];
+        var map = ParseMap(blocks[1]);
+
+        // From each start node calculate the steps to the first Z node, then 
+        // suppose that if we continue wandering around in the desert the 
+        /// distance between the Z nodes is always the same.
+        // The input was set up this way, which justifies the use of LCM in 
+        // computing the final result.
+        return map.Keys
+            .Where(w => w.EndsWith(aMarker))
+            .Select(w => StepsToZ(w, zMarker, dirs, map))
+            .Aggregate(1L, Lcm);
+    }
+
+    long Lcm(long a, long b) => a * b / Gcd(a, b);
+    long Gcd(long a, long b) => b == 0 ? a : Gcd(b, a % b);
+
+    long StepsToZ(string current, string zMarker, string dirs, Map map) {
+        var i = 0;
+        while (!current.EndsWith(zMarker)) {
+            var dir = dirs[i % dirs.Length];
+            current =  dir == 'L' ? map[current].Left : map[current].Right;
+            i++;
+        }
+        return i;
+    }
+
+    Map ParseMap(string input) =>
+        input.Split("\n")
+            .Select(line => Regex.Matches(line, "[A-Z]+"))
+            .ToDictionary(m => m[0].Value, m => (m[1].Value, m[2].Value));
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2023/9/illustration.jpeg b/2023/9/illustration.jpeg new file mode 100644 index 00000000..aa73a230 Binary files /dev/null and b/2023/9/illustration.jpeg differ diff --git a/2023/9/index.html b/2023/9/index.html new file mode 100644 index 00000000..cf94f933 --- /dev/null +++ b/2023/9/index.html @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2023/9 'Mirage Maintenance'' in C# by encse + + + + + + + + + + + + + + +
+
+
01020304050607080910111213141516171819202122232425
+
+
+
+
+ +
+ +
+

Advent of Code

+

2023/9

+

Mirage Maintenance

+

in C#

+

+

by encse

+
+ +
+ +
+

Let's revisit the problem description here.

+

We are implementing an extrapolation algorithm that reminds me to my +university years when we did Newton interpolation, or was it Lagrange? I don't +remember anymore, but it was using a similar algorithm to this.

+

Part 1 and Part 2 differs only in the direction of the extrapolation, and one +can be implemented using the other, just like I did it below.

+
+
namespace AdventOfCode.Y2023.Day09;
+
+using System;
+using System.Linq;
+
+[ProblemName("Mirage Maintenance")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, ExtrapolateRight);
+    public object PartTwo(string input) => Solve(input, ExtrapolateLeft);
+
+    long Solve(string input, Func extrapolate) =>
+        input.Split("\n").Select(ParseNumbers).Select(extrapolate).Sum();
+
+    long[] ParseNumbers(string line) =>
+        line.Split(" ").Select(long.Parse).ToArray();
+
+    // It's a common trick to zip a sequence with the skipped version of itself
+    long[] Diff(long[] numbers) =>
+        numbers.Zip(numbers.Skip(1)).Select(p => p.Second - p.First).ToArray();
+
+    // I went a bit further and recurse until there are no numbers left. It's
+    // more compact this way and doesn't affect the runtime much.
+    long ExtrapolateRight(long[] numbers) =>
+        !numbers.Any() ? 0 : ExtrapolateRight(Diff(numbers)) + numbers.Last();
+
+    long ExtrapolateLeft(long[] numbers) =>
+       ExtrapolateRight(numbers.Reverse().ToArray());
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/1/illustration.jpeg b/2024/1/illustration.jpeg new file mode 100644 index 00000000..c5dbd40d Binary files /dev/null and b/2024/1/illustration.jpeg differ diff --git a/2024/1/index.html b/2024/1/index.html new file mode 100644 index 00000000..8a618ff7 --- /dev/null +++ b/2024/1/index.html @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/1 'Historian Hysteria'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/1

+

Historian Hysteria

+

in C#

+

+

by encse

+
+ +
+ +
+

The Chief Historian is always present for the big Christmas sleigh launch, but nobody has seen him in months! Last anyone heard, he was visiting locations that are historically significant to the North Pole; a group of Senior Historians has asked you to accompany them as they check the places they think he was most likely to visit.

+

Read the full puzzle.

+

Our warm-up puzzle involves list comparisons. It'll take me a bit of time to get back into C#, as I find it a bit noisy now, but anyway... The first half is simply calculating the pairwise differences between two lists. The second half involves summing the elements of the first list, weighted by their occurrences in the second list.

+

This is a much better starting point than last year's infamous oneight puzzle!

+
+
namespace AdventOfCode.Y2024.Day01;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+
+[ProblemName("Historian Hysteria")]
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        // go over the sorted columns pairwise and sum the difference of the pairs
+        Enumerable.Zip(Column(input, 0), Column(input, 1))
+            .Select(p =>  Math.Abs(p.First - p.Second))
+            .Sum();
+
+    public object PartTwo(string input) {
+        // sum the elements of the left column weighted by its occurrences in the right
+        // ⭐ .Net 9 comes with a new CountBy function
+        var weights = Column(input, 1).CountBy(x=>x).ToDictionary();
+        return Column(input, 0).Select(num => weights.GetValueOrDefault(num) * num).Sum();
+    }
+
+    IEnumerable Column(string input, int column) =>
+        from line in input.Split("\n")
+        let nums = line.Split("   ").Select(int.Parse).ToArray()
+        orderby nums[column]
+        select nums[column];
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/10/illustration.jpeg b/2024/10/illustration.jpeg new file mode 100644 index 00000000..4c66aecd Binary files /dev/null and b/2024/10/illustration.jpeg differ diff --git a/2024/10/index.html b/2024/10/index.html new file mode 100644 index 00000000..68344a82 --- /dev/null +++ b/2024/10/index.html @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/10 'Hoof It'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/10

+

Hoof It

+

in C#

+

+

by encse

+
+ +
+ +
+

You all arrive at a Lava Production Facility on a floating island in the sky. As the others begin to search the massive industrial complex, you feel a small nose boop your leg and look down to discover a reindeer wearing a hard hat.

+

The reindeer is holding a book titled "Lava Island Hiking Guide". However, when you open the book, you discover that most of it seems to have been scorched by lava! As you're about to ask how you can help, the reindeer brings you a blank topographic map of the surrounding area (your puzzle input) and looks up at you excitedly.

+

Read the full puzzle.

+

Today's problem is surprisingly straightforward compared to yesterday's pointer juggling. We finally get to use our favorite queue data structure to implement a flood fill. I saw this coming...

+

As usual, we use a dictionary with complex numbers to parse the input. The meat of the solution is in GetTrailsFrom, which returns all trails starting at a specific trailhead.

+

The difference between Part 1 and Part 2 lies in how distinct trails are defined. I decided to return all trails keyed by their trailheads in GetAllTrails and delegate the distinctness logic to PartOne and PartTwo.

+

A nice and easy task for today!

+
+
namespace AdventOfCode.Y2024.Day10;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Numerics;
+
+using Map = System.Collections.Immutable.ImmutableDictionary;
+
+[ProblemName("Hoof It")]
+class Solution : Solver {
+
+    Complex Up = Complex.ImaginaryOne;
+    Complex Down = -Complex.ImaginaryOne;
+    Complex Left = -1;
+    Complex Right = 1;
+
+    public object PartOne(string input) => GetAllTrails(input).Sum(t => t.Value.Distinct().Count());
+    public object PartTwo(string input) => GetAllTrails(input).Sum(t => t.Value.Count());
+
+    Dictionary> GetAllTrails(string input) {
+        var map = GetMap(input);
+        return GetTrailHeads(map).ToDictionary(t => t, t => GetTrailsFrom(map, t));
+    }
+
+    IEnumerable GetTrailHeads(Map map) => map.Keys.Where(pos => map[pos] == '0');
+
+    List GetTrailsFrom(Map map, Complex trailHead) {
+        // standard floodfill algorithm using a queue
+        var positions = new Queue();
+        positions.Enqueue(trailHead);
+        var trails = new List();
+        while (positions.Any()) {
+            var point = positions.Dequeue();
+            if (map[point] == '9') {
+                trails.Add(point);
+            } else {
+                foreach (var dir in new[] { Up, Down, Left, Right }) {
+                    if (map.GetValueOrDefault(point + dir) == map[point] + 1) {
+                        positions.Enqueue(point + dir);
+                    }
+                }
+            }
+        }
+        return trails;
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area using GetValueOrDefault
+    Map GetMap(string input) {
+        var map = input.Split("\n");
+        return (
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(x + y * Down, map[y][x])
+        ).ToImmutableDictionary();
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/11/illustration.jpeg b/2024/11/illustration.jpeg new file mode 100644 index 00000000..04d52a2c Binary files /dev/null and b/2024/11/illustration.jpeg differ diff --git a/2024/11/index.html b/2024/11/index.html new file mode 100644 index 00000000..efa732f6 --- /dev/null +++ b/2024/11/index.html @@ -0,0 +1,322 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/11 'Plutonian Pebbles'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/11

+

Plutonian Pebbles

+

in C#

+

+

by encse

+
+ +
+ +
+

The ancient civilization on Pluto was known for its ability to manipulate spacetime, and while The Historians explore their infinite corridors, you've noticed a strange set of physics-defying stones.

+

At first glance, they seem like normal stones: they're arranged in a perfectly straight line, and each stone has a number engraved on it.

+

Read the full puzzle.

+

Today is all about dynamic programming and cached calculations. Our goal is to determine the number of stones based on specific rules derived from the numbers engraved on them. Without careful optimization, this process can quickly spiral out of control.

+

To address this, I encoded the stone generation logic inside the Eval function and added a cache to prevent exponential growth.

+

I discovered the ConcurrentDictionary class, which includes a convenient GetOrAdd method. While this functionality is missing in regular Dictionary variants, it allows the caching logic to be neatly encapsulated in a single place. I decided to "abuse" it a bit here, even though my solution doesn’t involve any concurrency at all.

+

There is an iterative approach to solving this problem as well, which progresses one blink at a time while keeping track of how many times each number occurs at each step. Working through this approach is left as an exercise for the reader.

+
+
namespace AdventOfCode.Y2024.Day11;
+
+using System.Linq;
+
+using Cache = System.Collections.Concurrent.ConcurrentDictionary<(string, int), long>;
+
+[ProblemName("Plutonian Pebbles")]
+class Solution : Solver {
+
+    public object PartOne(string input) => StoneCount(input, 25);
+
+    public object PartTwo(string input) => StoneCount(input, 75);
+
+    long StoneCount(string input, int blinks) {
+        var cache = new Cache();
+        return input.Split(" ").Sum(n => Eval(long.Parse(n), blinks, cache));
+    }
+
+    // Recursively calculates the total number of stones generated by a single engravement (n)
+    // after a specified number of blinks. Uses caching to optimize and prevent exponential
+    // computation by storing intermediate results.
+    long Eval(long n, int blinks, Cache cache) =>
+        cache.GetOrAdd((n.ToString(), blinks), key => 
+            key switch {
+                (_, 0)   => 1,
+
+                ("0", _) => 
+                    Eval(1, blinks - 1, cache),
+                
+                (var st, _) when st.Length % 2 == 0 =>
+                    Eval(long.Parse(st[0..(st.Length / 2)]), blinks - 1, cache) +
+                    Eval(long.Parse(st[(st.Length / 2)..]),  blinks - 1, cache),
+
+                _ =>  
+                    Eval(2024 * n, blinks - 1, cache)   
+            }
+        );
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/12/illustration.jpeg b/2024/12/illustration.jpeg new file mode 100644 index 00000000..62c1d43f Binary files /dev/null and b/2024/12/illustration.jpeg differ diff --git a/2024/12/index.html b/2024/12/index.html new file mode 100644 index 00000000..9d376ecb --- /dev/null +++ b/2024/12/index.html @@ -0,0 +1,411 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/12 'Garden Groups'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/12

+

Garden Groups

+

in C#

+

+

by encse

+
+ +
+ +
+

Why not search for the Chief Historian near the gardener and his massive farm? There's plenty of food, so The Historians grab something to eat while they search.

+

You're about to settle near a complex arrangement of garden plots when some Elves ask if you can lend a hand. They'd like to set up fences around each region of garden plots, but they can't figure out how much fence they need to order or how much it will cost. They hand you a map (your puzzle input) of the garden plots.

+

Read the full puzzle.

+

One can sense that the difficulty has ramped up today with a more complex problem involving area and perimeter calculations.

+

First we determine the connected components (regions) of plants of the same type. This is done by picking a position of the +garden and applying a standard flood-fill algorithm to it. The result is a region. As we process each region, we carefully +remove all affected positions and then pick an untouched position to repeat the process. In a few iterations, the entire +garden is associated with the correct regions. The size of the regions corresponds to the area in question. This logic +is implemented in the GetRegions function below.

+

The second part of the problem, however, is more intriguing: how do we calculate the lengths of the fences? In part 1, this is +relatively simple because we just iterate through each region and count the neighboring cells that belong to a different regions. +This tells how many fence is needed. Unfortunately, this logic doesn't work for part 2...

+

I attempted to implement a "walk-around" approach, which involves finding a fence segment and tracing it like a line-following +robot while counting the turns. The challenge with this approach is that some regions have holes, that require fences as well +and I didnt want to implement hole finding.

+

Later realized that it is probably more straightforward to collect the fence segments along straight lines scanning the garden +from top to bottom an right to left. This is how I solved the problem.

+

Finally went to reddit and read the hint: the number of segments equal to the number of corners... In other words difference +between part 1 and 2 is very small. In part 1 we are building an edge detector which becomes a corner detector in part 2. I changed +my implementation to that.

+

This concludes our day 12. I'll take an extra ⭐ for learning something new again.

+
+
namespace AdventOfCode.Y2024.Day12;
+
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Numerics;
+
+using Region = System.Collections.Generic.HashSet;
+using System;
+
+[ProblemName("Garden Groups")]
+class Solution : Solver {
+
+    Complex Up = Complex.ImaginaryOne;
+    Complex Down = -Complex.ImaginaryOne;
+    Complex Left = -1;
+    Complex Right = 1;
+
+    public object PartOne(string input) => CalculateFencePrice(input, FindEdges);
+
+    public object PartTwo(string input) => CalculateFencePrice(input, FindCorners);
+
+    int CalculateFencePrice(string input, MeasurePerimeter measure){
+        var regions = GetRegions(input);
+        var res = 0;
+        foreach (var region in regions.Values.Distinct()) {
+            var perimeter = 0;
+            foreach (var pt in region) {
+                perimeter += measure(regions, pt);
+            }
+            res += region.Count() * perimeter;
+        }
+        return res;
+    }    
+   
+    delegate int MeasurePerimeter(Dictionary map, Complex pt);
+
+    int FindEdges(Dictionary map, Complex pt) {
+        var res = 0;
+        var region = map[pt];
+        foreach (var du in new[] { Right, Down, Left, Up}) {
+            // x.
+            if (map.GetValueOrDefault(pt + du) != region) {
+                res++;
+            }
+        }
+        return res;
+    }
+
+    int FindCorners(Dictionary map, Complex pt) {
+        var res = 0;
+        var region = map[pt];
+
+        // rotate du and dv and check for the 4 corner types
+        foreach (var (du, dv) in new[] { (Up, Right), (Right, Down), (Down, Left), (Left, Up) }) {
+            //  ..
+            //  x.
+            if (map.GetValueOrDefault(pt + du) != region && 
+                map.GetValueOrDefault(pt + dv) != region
+            ) {
+                res++; 
+            }
+
+            //  x.
+            //  xx
+            if (map.GetValueOrDefault(pt + du) == region && 
+                map.GetValueOrDefault(pt + dv) == region &&  
+                map.GetValueOrDefault(pt + du + dv) != region
+            ) {
+                res++;
+            }
+        }
+        return res;
+    }
+
+    // Maps the positions of plants in a garden to their corresponding regions, grouping plants 
+    // of the same type into contiguous regions.
+    Dictionary GetRegions(string input) {
+        var lines = input.Split("\n");
+        var garden = (
+            from y in Enumerable.Range(0, lines.Length)
+            from x in Enumerable.Range(0, lines[0].Length)
+            select new KeyValuePair(x + y * Down, lines[y][x])
+        ).ToDictionary();
+
+        // go over the positions of the garden and use a floodfill to determine the region
+        var res = new Dictionary();
+        var positions = garden.Keys.ToHashSet();
+        while (positions.Any()) {
+            var pivot = positions.First();
+            var region = new Region { pivot };
+
+            var q = new Queue();
+            q.Enqueue(pivot);
+
+            var plant = garden[pivot];
+
+            while (q.Any()) {
+                var point = q.Dequeue();
+                res[point] = region;
+                positions.Remove(point);
+                foreach (var dir in new[] { Up, Down, Left, Right }) {
+                    if (!region.Contains(point + dir) && garden.GetValueOrDefault(point + dir) == plant) {
+                        region.Add(point + dir);
+                        q.Enqueue(point + dir);
+                    }
+                }
+            }
+        }
+        return res;
+    }
+
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/2/illustration.jpeg b/2024/2/illustration.jpeg new file mode 100644 index 00000000..cebc3245 Binary files /dev/null and b/2024/2/illustration.jpeg differ diff --git a/2024/2/index.html b/2024/2/index.html new file mode 100644 index 00000000..b0c336c0 --- /dev/null +++ b/2024/2/index.html @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/2 'Red-Nosed Reports'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/2

+

Red-Nosed Reports

+

in C#

+

+

by encse

+
+ +
+ +
+

Fortunately, the first location The Historians want to search isn't a long walk from the Chief Historian's office.

+

While the Red-Nosed Reindeer nuclear fusion/fission plant appears to contain no sign of the Chief Historian, the engineers there run up to you as soon as they see you. Apparently, they still talk about the time Rudolph was saved through molecular synthesis from a single electron.

+

Read the full puzzle.

+

I created a function to check the validity of a single input line. This is achieved using the usual method of zipping the input with itself to generate a list of consecutive pairs. The next step involves checking the monotonicity condition (either increasing or decreasing) for each pair.

+

The second part of the problem is addressed with another helper function. This function takes an input sequence and generates attenuated versions of it in all possible ways, by omitting zero or one elements from the sample.

+
+
namespace AdventOfCode.Y2024.Day02;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+[ProblemName("Red-Nosed Reports")]
+class Solution : Solver {
+
+    public object PartOne(string input) => 
+        ParseSamples(input).Count(Valid);
+
+    public object PartTwo(string input) => 
+        ParseSamples(input).Count(samples => Attenuate(samples).Any(Valid));
+
+    IEnumerable ParseSamples(string input) => 
+        from line in input.Split("\n")
+        let samples = line.Split(" ").Select(int.Parse)
+        select samples.ToArray();
+
+    // Generates all possible variations of the input sequence by omitting 
+    // either zero or one element from it.
+    IEnumerable Attenuate(int[] samples) =>
+        from i in Enumerable.Range(0, samples.Length+1)
+        let before = samples.Take(i - 1)
+        let after = samples.Skip(i)
+        select Enumerable.Concat(before, after).ToArray();
+
+    // Checks the monothinicity condition by examining consecutive elements
+    bool Valid(int[] samples) {
+        var pairs = Enumerable.Zip(samples, samples.Skip(1));
+        return
+            pairs.All(p => 1 <= p.Second - p.First && p.Second - p.First <= 3) ||
+            pairs.All(p => 1 <= p.First - p.Second && p.First - p.Second <= 3);
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/3/illustration.jpeg b/2024/3/illustration.jpeg new file mode 100644 index 00000000..e19c0a13 Binary files /dev/null and b/2024/3/illustration.jpeg differ diff --git a/2024/3/index.html b/2024/3/index.html new file mode 100644 index 00000000..c595367d --- /dev/null +++ b/2024/3/index.html @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/3 'Mull It Over'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/3

+

Mull It Over

+

in C#

+

+

by encse

+
+ +
+ +
+

"Our computers are having issues, so I have no idea if we have any Chief Historians in stock! You're welcome to check the warehouse, though," says the mildly flustered shopkeeper at the North Pole Toboggan Rental Shop. The Historians head out to take a look.

+

The shopkeeper turns to you. "Any chance you can see why our computers are having issues again?"

+

Read the full puzzle.

+

I took a functional approach today. Regular expressions are ugly beasts, I normally try avoid them. Fortunately, we're not writing production code here. Otherwise... everything is just a fold if you look at it from a distance.

+
+
namespace AdventOfCode.Y2024.Day03;
+
+using System.Linq;
+using System.Text.RegularExpressions;
+
+[ProblemName("Mull It Over")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Solve(input, @"mul\((\d{1,3}),(\d{1,3})\)");
+
+    public object PartTwo(string input) => Solve(input, @"mul\((\d{1,3}),(\d{1,3})\)|don't\(\)|do\(\)");
+
+    long Solve(string input, string rx) {
+        // overly functionaly approach...
+        var matches = Regex.Matches(input, rx, RegexOptions.Multiline);
+        return matches.Aggregate(
+            (enabled: true, res: 0L), 
+            (acc, m) => 
+                (m.Value, acc.res, acc.enabled) switch {
+                    ("don't()", _, _)  => (false, acc.res),
+                    ("do()", _, _)     => (true, acc.res),
+                    (_, var res, true) => 
+                        (true, res + int.Parse(m.Groups[1].Value) * int.Parse(m.Groups[2].Value)),
+                    _ => acc
+                },
+            acc => acc.res
+        );
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/4/illustration.jpeg b/2024/4/illustration.jpeg new file mode 100644 index 00000000..a5fdc091 Binary files /dev/null and b/2024/4/illustration.jpeg differ diff --git a/2024/4/index.html b/2024/4/index.html new file mode 100644 index 00000000..f4e65a47 --- /dev/null +++ b/2024/4/index.html @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/4 'Ceres Search'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/4

+

Ceres Search

+

in C#

+

+

by encse

+
+ +
+ +
+

"Looks like the Chief's not here. Next!" One of The Historians pulls out a device and pushes the only button on it. After a brief flash, you recognize the interior of the Ceres monitoring station! +As the search for the Chief continues, a small Elf who lives on the station tugs on your shirt; she'd like to know if you could help her with her word search. She only has to find one word: XMAS.

+

Read the full puzzle.

+

I employed my proven tactic of converting the input into a dictionary, using coordinates as keys. This approach makes it straightforward to iterate over the keys and check whether they fall within the bounds of the map.

+

Representing coordinates with complex numbers is another effective technique for handling steps in various directions.

+

The algorithm itself is a straightforward brute-force check of all starting positions and reading orders.

+
+
namespace AdventOfCode.Y2024.Day04;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Numerics;
+using System.Linq;
+
+using Map = System.Collections.Immutable.ImmutableDictionary;
+
+[ProblemName("Ceres Search")]
+class Solution : Solver {
+
+    Complex Up = -Complex.ImaginaryOne;
+    Complex Down = Complex.ImaginaryOne;
+    Complex Left = -1;
+    Complex Right = 1;
+
+    public object PartOne(string input) {
+        var mat = GetMap(input);
+        return (
+            from pt in mat.Keys
+            from dir in  new[] { Right, Right + Down, Down + Left, Down}
+            where Matches(mat, pt, dir, "XMAS")
+            select 1
+        ).Count();
+    }
+
+    public object PartTwo(string input) {
+        var mat = GetMap(input);
+        return (
+            from pt in mat.Keys
+            where 
+                Matches(mat, pt + Up + Left, Down + Right, "MAS") && 
+                Matches(mat, pt + Down + Left, Up + Right, "MAS")
+            select 1
+        ).Count();
+    }
+
+    // check if the pattern (or its reverse) can be read in the given direction 
+    // starting from pt
+    bool Matches(Map map, Complex pt, Complex dir, string pattern) {
+        var chars = Enumerable.Range(0, pattern.Length)
+            .Select(i => map.GetValueOrDefault(pt + i * dir))
+            .ToArray();
+        return
+            Enumerable.SequenceEqual(chars, pattern) ||
+            Enumerable.SequenceEqual(chars, pattern.Reverse());
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area using GetValueOrDefault
+    Map GetMap(string input) {
+        var map = input.Split("\n");
+        return (
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(Complex.ImaginaryOne * y + x, map[y][x])
+        ).ToImmutableDictionary();
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/5/illustration.jpeg b/2024/5/illustration.jpeg new file mode 100644 index 00000000..d270b7fa Binary files /dev/null and b/2024/5/illustration.jpeg differ diff --git a/2024/5/index.html b/2024/5/index.html new file mode 100644 index 00000000..7e07baac --- /dev/null +++ b/2024/5/index.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/5 'Print Queue'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/5

+

Print Queue

+

in C#

+

+

by encse

+
+ +
+ +
+

Satisfied with their search on Ceres, the squadron of scholars suggests subsequently scanning the stationery stacks of sub-basement 17.

+

The North Pole printing department is busier than ever this close to Christmas, and while The Historians continue their search of this historically significant facility, an Elf operating a very familiar printer beckons you over.

+

The Elf must recognize you, because they waste no time explaining that the new sleigh launch safety manual updates won't print correctly. Failure to update the safety manuals would be dire indeed, so you offer your services.

+

Read the full puzzle.

+

The constraints in both my input and the provided sample input define a total ordering of the pages, which I leveraged in my solution. (*) I implemented a custom parser that returns the list of updates to be printed and a page comparison function. That's all we need. In Part1, we check which updates are in the correct order, while in Part2, we handle the remaining updates by applying .NET's built-in OrderBy function with our custom comparer.

+

(*) others say that the ordering is not total, in fact there are loops in it. But it was not an issue for the update lines we need to sort. So the thing below works only because of the Elf magic of X-mas.

+
+
namespace AdventOfCode.Y2024.Day05;
+
+using System.Collections.Generic;
+using System.Linq;
+
+[ProblemName("Print Queue")]
+class Solution : Solver {
+
+    public object PartOne(string input) {
+        var (updates, comparer) = Parse(input);
+        return updates
+            .Where(pages => Sorted(pages, comparer))
+            .Sum(GetMiddlePage);
+    }
+
+    public object PartTwo(string input) {
+        var (updates, comparer) = Parse(input);
+        return updates
+            .Where(pages => !Sorted(pages, comparer))
+            .Select(pages => pages.OrderBy(p => p, comparer).ToArray())
+            .Sum(GetMiddlePage);
+    }
+
+    (string[][] updates, Comparer) Parse(string input) {
+        var parts = input.Split("\n\n");
+
+        var ordering = new HashSet(parts[0].Split("\n"));
+        var comparer = 
+            Comparer.Create((p1, p2) => ordering.Contains(p1 + "|" + p2) ? -1 : 1);
+
+        var updates = parts[1].Split("\n").Select(line => line.Split(",")).ToArray();
+        return (updates, comparer);
+    }
+    
+    int GetMiddlePage(string[] nums) => int.Parse(nums[nums.Length / 2]);
+   
+    bool Sorted(string[] pages, Comparer comparer) =>
+        Enumerable.SequenceEqual(pages, pages.OrderBy(x=>x, comparer));
+
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/6/illustration.jpeg b/2024/6/illustration.jpeg new file mode 100644 index 00000000..62e5e434 Binary files /dev/null and b/2024/6/illustration.jpeg differ diff --git a/2024/6/index.html b/2024/6/index.html new file mode 100644 index 00000000..c31867a5 --- /dev/null +++ b/2024/6/index.html @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/6 'Guard Gallivant'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/6

+

Guard Gallivant

+

in C#

+

+

by encse

+
+ +
+ +
+

The Historians use their fancy device again, this time to whisk you all away to the North Pole prototype suit manufacturing lab... in the year 1518! It turns out that having direct access to history is very convenient for a group of historians.

+

You still have to be careful of time paradoxes, and so it will be important to avoid anyone from 1518 while The Historians search for the Chief. Unfortunately, a single guard is patrolling this part of the lab.

+

Read the full puzzle.

+

This has been a straightforward implementation challenge. I wrote a Walk function that tracks the guard's movement and returns the visited locations. It also determines whether the guard enters a loop or exits the grid. Part1 utilizes only the location information, while Part2 adds blockers along the guard's path and counts the instances where he starts walking in a cycle.

+

To make a 90º turn in 2D you need swap the coordinates and multiply one of them by -1. The turn can be clockwise or counterclockwise, it depends on which coordinate was multiplied.

+

Here we use complex numbers to represent coordinates, and we get the same effect by simply multiplying with ImaginaryOne or i. -i turns right, and i to left (but this depends on how you draw your coordinate system of course, 'i' points upwards in mine).

+

It's not complicated at all, but if sounds a bit magical to You, try it out on a few vectors by hand.

+
+
namespace AdventOfCode.Y2024.Day06;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Numerics;
+
+using Map = System.Collections.Generic.Dictionary;
+
+[ProblemName("Guard Gallivant")]
+class Solution : Solver {
+
+    Complex Up = Complex.ImaginaryOne;
+    Complex TurnRight = -Complex.ImaginaryOne;
+
+    public object PartOne(string input) {
+        var (map, start) = Parse(input);
+        return Walk(map, start).positions.Count();
+    }
+
+    public object PartTwo(string input) {
+        var (map, start) = Parse(input);
+        var positions = Walk(map, start).positions;
+        var loops = 0;
+        // simply try a blocker in each locations visited by the guard and count the loops
+        foreach (var block in positions.Where(pos => map[pos] == '.')) {
+            map[block] = '#';
+            if (Walk(map, start).isLoop) {
+                loops++;
+            }
+            map[block] = '.';
+        }
+        return loops;
+    }
+
+    // returns the positions visited when starting from 'pos', isLoop is set if the 
+    // guard enters a cycle.
+    (IEnumerable positions, bool isLoop) Walk(Map map, Complex pos) {
+        var seen = new HashSet<(Complex pos, Complex dir)>();
+        var dir = Up;
+        while (map.ContainsKey(pos) && !seen.Contains((pos, dir))) {
+            seen.Add((pos, dir));
+            if (map.GetValueOrDefault(pos + dir) == '#') {
+                dir *= TurnRight;
+            } else {
+                pos += dir;
+            }
+        }
+        return (
+            positions: seen.Select(s => s.pos).Distinct(),
+            isLoop: seen.Contains((pos, dir))
+        );
+    }
+
+    // store the grid in a dictionary, to make bounds checks and navigation simple
+    // start represents the starting postion of the guard
+    (Map map, Complex start) Parse(string input) {
+        var lines = input.Split("\n");
+        var map = (
+            from y in Enumerable.Range(0, lines.Length)
+            from x in Enumerable.Range(0, lines[0].Length)
+            select new KeyValuePair(-Up * y + x, lines[y][x])
+        ).ToDictionary();
+
+        var start = map.First(x => x.Value == '^').Key;
+        
+        return (map, start);
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/7/illustration.jpeg b/2024/7/illustration.jpeg new file mode 100644 index 00000000..f08fd6f2 Binary files /dev/null and b/2024/7/illustration.jpeg differ diff --git a/2024/7/index.html b/2024/7/index.html new file mode 100644 index 00000000..5600e6be --- /dev/null +++ b/2024/7/index.html @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/7 'Bridge Repair'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/7

+

Bridge Repair

+

in C#

+

+

by encse

+
+ +
+ +
+

The Historians take you to a familiar rope bridge over a river in the middle of a jungle. The Chief isn't on this side of the bridge, though; maybe he's on the other side?

+

When you go to cross the bridge, you notice a group of engineers trying to repair it. (Apparently, it breaks pretty frequently.) You won't be able to cross until it's fixed.

+

Read the full puzzle.

+

It's time to pull out the recursion guns. I introduced a checker logic that goes through the numbers in one line of input and tries all possible operators on the accumulated result to reach the target.

+

The common logic that parses the input and executes the checker was extracted into a single Solve function, but I found it more readable to have distinct checkers for the two parts of the problem.

+

Everything runs in about a second, but since it's just a single line, I couldn't stand and added an optimization in Check2 to exit early when the accumulated result exceeds the target.

+
+
namespace AdventOfCode.Y2024.Day07;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+[ProblemName("Bridge Repair")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Filter(input, Check1).Sum();
+    public object PartTwo(string input) => Filter(input, Check2).Sum();
+
+    // returns those calibrations that are valid according to the checker
+    private IEnumerable Filter(string input, Func, bool> check) => 
+        from line in input.Split("\n")
+            let parts = Regex.Matches(line, @"\d+").Select(m=>long.Parse(m.Value))
+            let target = parts.First()
+            let nums = parts.Skip(1).ToList()
+        where check(target, nums[0], nums[1..])
+        select target;
+
+    // separate checkers provided for the two parts, these recursive functions go
+    // over the numbers and use all allowed operators to update the accumulated result.
+    // at the end of the recursion we simply check if we reached the target
+    private bool Check1(long target, long acc, List nums) =>
+        nums switch {
+            [] => target == acc,
+            _  => Check1(target, acc * nums[0], nums[1..]) ||
+                  Check1(target, acc + nums[0], nums[1..])
+        };
+
+    private bool Check2(long target, long acc, List nums) =>
+        nums switch {
+            _ when acc > target => false, // optimization: early exit from deadend
+            [] => target == acc,
+            _  => Check2(target, long.Parse($"{acc}{nums[0]}"), nums[1..]) ||
+                  Check2(target, acc * nums[0], nums[1..]) ||
+                  Check2(target, acc + nums[0], nums[1..])
+        };
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/8/illustration.jpeg b/2024/8/illustration.jpeg new file mode 100644 index 00000000..c15028cb Binary files /dev/null and b/2024/8/illustration.jpeg differ diff --git a/2024/8/index.html b/2024/8/index.html new file mode 100644 index 00000000..859ab078 --- /dev/null +++ b/2024/8/index.html @@ -0,0 +1,350 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/8 'Resonant Collinearity'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/8

+

Resonant Collinearity

+

in C#

+

+

by encse

+
+ +
+ +
+

You find yourselves on the roof of a top-secret Easter Bunny installation.

+

While The Historians do their thing, you take a look at the familiar huge antenna. Much to your surprise, it seems to have been reconfigured to emit a signal that makes people 0.1% more likely to buy Easter Bunny brand Imitation Mediocre Chocolate as a Christmas gift! Unthinkable!

+

Read the full puzzle.

+

Continuing the steps I started yesterday, I extracted a common function (GetUniquePositions) that takes a parameter to generate antinode positions, representing the difference between part one and part two.

+

getAntinodes returns the antinode positions of srcAntenna on the dstAntenna side. It doesn’t need to be symmetric — i.e., it doesn’t have to return the antinodes on the srcAntenna side — because GetUniquePositions will call it with the parameters swapped as well. This allows us to handle only one direction at a time.

+

The generators are fairly straightforward: I simply take steps in the direction determined by the antennas, starting from the destination. Since I represented coordinates using complex numbers again, there’s no need for any special handling on the algebra side, regular + and - operations work.

+

The GetAntinodes delegate is introduced only for documentation purposes. It looks better to my eyes than an ugly Func<> with four type parameters would in GetUniquePositions-s signature.

+
+
namespace AdventOfCode.Y2024.Day08;
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Numerics;
+
+using Map = System.Collections.Immutable.ImmutableDictionary;
+
+[ProblemName("Resonant Collinearity")]
+class Solution : Solver {
+    public object PartOne(string input) => GetUniquePositions(input, GetAntinodes1).Count();
+    public object PartTwo(string input) => GetUniquePositions(input, GetAntinodes2).Count();
+
+    HashSet GetUniquePositions(string input, GetAntinodes getAntinodes) {
+        var map = GetMap(input);
+
+        var antennaLocations = (
+            from pos in map.Keys 
+            where char.IsAsciiLetterOrDigit(map[pos])
+            select pos
+        ).ToArray();
+
+        return (
+             from srcAntenna in antennaLocations
+             from dstAntenna in antennaLocations
+             where srcAntenna != dstAntenna && map[srcAntenna] == map[dstAntenna]
+             from antinode in getAntinodes(srcAntenna, dstAntenna, map)
+             select antinode
+         ).ToHashSet();
+    }
+
+    // returns the antinode positions of srcAntenna on the dstAntenna side
+    delegate IEnumerable GetAntinodes(Complex srcAntenna, Complex dstAntenna, Map map);
+
+    // in part 1 we just look at the immediate neighbour
+    IEnumerable GetAntinodes1(Complex srcAntenna, Complex dstAntenna, Map map) {
+        var dir = dstAntenna - srcAntenna;
+        var antinote = dstAntenna + dir;
+        if (map.Keys.Contains(antinote)) {
+            yield return antinote;
+        }
+    }
+
+    // in part 2 this becomes a cycle, plus dstAntenna is also a valid position now
+    IEnumerable GetAntinodes2(Complex srcAntenna, Complex dstAntenna, Map map) {
+        var dir = dstAntenna - srcAntenna;
+        var antinote = dstAntenna;
+        while (map.Keys.Contains(antinote)) {
+            yield return antinote;
+            antinote += dir;
+        }
+    }
+
+    // store the points in a dictionary so that we can iterate over them and 
+    // to easily deal with points outside the area using GetValueOrDefault
+    Map GetMap(string input) {
+        var map = input.Split("\n");
+        return (
+            from y in Enumerable.Range(0, map.Length)
+            from x in Enumerable.Range(0, map[0].Length)
+            select new KeyValuePair(x - y * Complex.ImaginaryOne, map[y][x])
+        ).ToImmutableDictionary();
+    }
+}
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/2024/9/illustration.jpeg b/2024/9/illustration.jpeg new file mode 100644 index 00000000..7e5c69dd Binary files /dev/null and b/2024/9/illustration.jpeg differ diff --git a/2024/9/index.html b/2024/9/index.html new file mode 100644 index 00000000..119d0ba2 --- /dev/null +++ b/2024/9/index.html @@ -0,0 +1,361 @@ + + + + + + + + + + + + + + + + + + Advent of Code 2024/9 'Disk Fragmenter'' in C# by encse + + + + + + + + + + + + + + +
+
+
010203040506070809101112
+
+
+
+
+ +
+ +
+

Advent of Code

+

2024/9

+

Disk Fragmenter

+

in C#

+

+

by encse

+
+ +
+ +
+

Another push of the button leaves you in the familiar hallways of some friendly amphipods! Good thing you each somehow got your own personal mini submarine. The Historians jet away in search of the Chief, mostly by driving directly into walls.

+

While The Historians quickly figure out how to pilot these things, you notice an amphipod in the corner struggling with his computer. He's trying to make more contiguous free space by compacting all of the files, but his program isn't working; you offer to help.

+

Read the full puzzle.

+

I'm taking a break from using LINQ today and turning my attention to the low-level world of linked lists instead. I discovered a way to express both paths using a single CompactFs function with a fragmentsEnabled parameter. CompactFs operates with two pointers, i and j, which define the scan range we’re working on. i starts at the beginning of the disk, while j starts at the end and moves backward. When i points to a free space and j points to a used space, we call RelocateBlock, which moves j (or parts of j, depending on whether fragmentation is enabled) to a free space found after i.

+

The rest involves careful pointer arithmetic and linked list management, where I aim to avoid overwriting the data I’ll need in the next line. I find this surprisingly hard to get right when working with linked lists...

+
+
namespace AdventOfCode.Y2024.Day09;
+
+using System.Linq;
+
+using Fs = System.Collections.Generic.LinkedList;
+using Node = System.Collections.Generic.LinkedListNode;
+record struct Block(int fileId, int length) { }
+
+[ProblemName("Disk Fragmenter")]
+class Solution : Solver {
+
+    public object PartOne(string input) => Checksum(CompactFs(Parse(input), fragmentsEnabled: true));
+
+    public object PartTwo(string input) => Checksum(CompactFs(Parse(input), fragmentsEnabled: false));
+
+    // moves used blocks of the filesystem towards the beginning of the disk using RelocateBlock
+    Fs CompactFs(Fs fs, bool fragmentsEnabled) {
+        var (i, j) = (fs.First, fs.Last);
+        while (i != j) {
+            if (i.Value.fileId != -1) {
+                i = i.Next;
+            } else if (j.Value.fileId == -1) {
+                j = j.Previous;
+            } else {
+                RelocateBlock(fs, i, j, fragmentsEnabled);
+                j = j.Previous;
+            }
+        }
+        return fs;
+    }
+
+    // Relocates the contents of block `j` to a free space starting after the given node `start`. 
+    // - Searches for the first suitable free block after `start`.
+    // - If a block of equal size is found, `j` is moved entirely to that block.
+    // - If a larger block is found, part of it is used for `j`, and the remainder is split into 
+    //   a new free block.
+    // - If a smaller block is found and fragmentation is enabled, a portion of `j` is moved to fit, 
+    //   leaving the remainder in place.
+    void RelocateBlock(Fs fs, Node start, Node j, bool fragmentsEnabled) {
+        for (var i = start; i != j; i = i.Next) {
+            if (i.Value.fileId != -1) {
+                // noop
+            } else if (i.Value.length == j.Value.length) {
+                (i.Value, j.Value) = (j.Value, i.Value);
+                return;
+            } else if (i.Value.length > j.Value.length) {
+                var d = i.Value.length - j.Value.length;
+                i.Value = j.Value;
+                j.Value = j.Value with { fileId = -1 };
+                fs.AddAfter(i, new Block(-1, d));
+                return;
+            } else if (i.Value.length < j.Value.length && fragmentsEnabled) {
+                var d = j.Value.length - i.Value.length;
+                i.Value = i.Value with { fileId = j.Value.fileId };
+                j.Value = j.Value with { length = d };
+                fs.AddAfter(j, new Block(-1, i.Value.length));
+            }
+        }
+    }
+
+    long Checksum(Fs fs) {
+        var res = 0L;
+        var l = 0;
+        for (var i = fs.First; i != null; i = i.Next) {
+            for (var k = 0; k < i.Value.length; k++) {
+                if (i.Value.fileId != -1) {
+                    res += l * i.Value.fileId;
+                }
+                l++;
+            }
+        }
+        return res;
+    }
+
+    Fs Parse(string input) {
+        return new Fs(input.Select((ch, i) => new Block(i % 2 == 1 ? -1 : i / 2, ch - '0')));
+    }
+}
+
+

Please ☆ my repo if you like it!

+
+ +
+
+ © + Advent of Code is a registered trademark in the US + Images provided by Bing image creator +
+ + + + + + + + \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 00000000..9c931b10 --- /dev/null +++ b/404.html @@ -0,0 +1,2 @@ + + diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..dfac70bb --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +aoc.csokavar.hu \ No newline at end of file diff --git a/android-chrome-192x192.png b/android-chrome-192x192.png new file mode 100644 index 00000000..00444eee Binary files /dev/null and b/android-chrome-192x192.png differ diff --git a/android-chrome-512x512.png b/android-chrome-512x512.png new file mode 100644 index 00000000..ac878c39 Binary files /dev/null and b/android-chrome-512x512.png differ diff --git a/apple-touch-icon.png b/apple-touch-icon.png new file mode 100644 index 00000000..bf6729c6 Binary files /dev/null and b/apple-touch-icon.png differ diff --git a/browserconfig.xml b/browserconfig.xml new file mode 100644 index 00000000..b3930d0f --- /dev/null +++ b/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/docs/node_modules/.bin/marked b/docs/node_modules/.bin/marked new file mode 120000 index 00000000..6827ff33 --- /dev/null +++ b/docs/node_modules/.bin/marked @@ -0,0 +1 @@ +../marked/bin/marked.js \ No newline at end of file diff --git a/docs/node_modules/.package-lock.json b/docs/node_modules/.package-lock.json new file mode 100644 index 00000000..17064d55 --- /dev/null +++ b/docs/node_modules/.package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "docs", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/marked": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.3.tgz", + "integrity": "sha512-Ai0cepvl2NHnTcO9jYDtcOEtVBNVYR31XnEA3BndO7f5As1wzpcOceSUM8FDkNLJNIODcLpDTWay/qQhqbuMvg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + } + } +} diff --git a/docs/node_modules/marked/LICENSE.md b/docs/node_modules/marked/LICENSE.md new file mode 100644 index 00000000..4bd2d4a0 --- /dev/null +++ b/docs/node_modules/marked/LICENSE.md @@ -0,0 +1,44 @@ +# License information + +## Contribution License Agreement + +If you contribute code to this project, you are implicitly allowing your code +to be distributed under the MIT license. You are also implicitly verifying that +all code is your original work. `` + +## Marked + +Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/) +Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +## Markdown + +Copyright © 2004, John Gruber +http://daringfireball.net/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name “Markdown” nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. diff --git a/docs/node_modules/marked/README.md b/docs/node_modules/marked/README.md new file mode 100644 index 00000000..b7bf8075 --- /dev/null +++ b/docs/node_modules/marked/README.md @@ -0,0 +1,106 @@ + + + + +# Marked + +[![npm](https://badgen.net/npm/v/marked)](https://www.npmjs.com/package/marked) +[![install size](https://badgen.net/packagephobia/install/marked)](https://packagephobia.now.sh/result?p=marked) +[![downloads](https://badgen.net/npm/dt/marked)](https://www.npmjs.com/package/marked) +[![github actions](https://github.com/markedjs/marked/workflows/Tests/badge.svg)](https://github.com/markedjs/marked/actions) +[![snyk](https://snyk.io/test/npm/marked/badge.svg)](https://snyk.io/test/npm/marked) + +- ⚡ built for speed +- ⬇️ low-level compiler for parsing markdown without caching or blocking for long periods of time +- ⚖️ light-weight while implementing all markdown features from the supported flavors & specifications +- 🌐 works in a browser, on a server, or from a command line interface (CLI) + +## Demo + +Checkout the [demo page](https://marked.js.org/demo/) to see marked in action ⛹️ + +## Docs + +Our [documentation pages](https://marked.js.org) are also rendered using marked 💯 + +Also read about: + +* [Options](https://marked.js.org/using_advanced) +* [Extensibility](https://marked.js.org/using_pro) + +## Compatibility + +**Node.js:** Only [current and LTS](https://nodejs.org/en/about/releases/) Node.js versions are supported. End of life Node.js versions may become incompatible with Marked at any point in time. + +**Browser:** Not IE11 :) + +## Installation + +**CLI:** + +```sh +npm install -g marked +``` + +**In-browser:** + +```sh +npm install marked +``` + +## Usage + +### Warning: 🚨 Marked does not [sanitize](https://marked.js.org/using_advanced#options) the output HTML. Please use a sanitize library, like [DOMPurify](https://github.com/cure53/DOMPurify) (recommended), [sanitize-html](https://github.com/apostrophecms/sanitize-html) or [insane](https://github.com/bevacqua/insane) on the *output* HTML! 🚨 + +``` +DOMPurify.sanitize(marked.parse(``)); +``` + +**CLI** + +``` bash +# Example with stdin input +$ marked -o hello.html +hello world +^D +$ cat hello.html +

hello world

+``` + +```bash +# Print all options +$ marked --help +``` + +**Browser** + +```html + + + + + Marked in the browser + + +
+ + + + +``` +or import esm module + +```html + +``` + +## License + +Copyright (c) 2011-2022, Christopher Jeffrey. (MIT License) diff --git a/docs/node_modules/marked/bin/main.js b/docs/node_modules/marked/bin/main.js new file mode 100644 index 00000000..b20689b3 --- /dev/null +++ b/docs/node_modules/marked/bin/main.js @@ -0,0 +1,282 @@ +#!/usr/bin/env node + +/** + * Marked CLI + * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License) + */ + +import { promises } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { homedir } from 'node:os'; +import { createRequire } from 'node:module'; +import { marked } from '../lib/marked.esm.js'; + +const { access, readFile, writeFile } = promises; +const require = createRequire(import.meta.url); + +/** + * @param {Process} nodeProcess inject process so it can be mocked in tests. + */ +export async function main(nodeProcess) { + /** + * Man Page + */ + async function help() { + const { spawn } = await import('child_process'); + const { fileURLToPath } = await import('url'); + + const options = { + cwd: nodeProcess.cwd(), + env: nodeProcess.env, + stdio: 'inherit', + }; + + const __dirname = dirname(fileURLToPath(import.meta.url)); + const helpText = await readFile(resolve(__dirname, '../man/marked.1.md'), 'utf8'); + + await new Promise(res => { + const manProcess = spawn('man', [resolve(__dirname, '../man/marked.1')], options); + nodeProcess.on('SIGINT', () => { + manProcess.kill('SIGINT'); + }); + + manProcess.on('error', () => { + console.log(helpText); + }) + .on('close', res); + }); + } + + async function version() { + const pkg = require('../package.json'); + console.log(pkg.version); + } + + /** + * Main + */ + async function start(argv) { + const files = []; + const options = {}; + let input; + let output; + let string; + let arg; + let tokens; + let config; + let opt; + let noclobber; + + function getArg() { + let arg = argv.shift(); + + if (arg.indexOf('--') === 0) { + // e.g. --opt + arg = arg.split('='); + if (arg.length > 1) { + // e.g. --opt=val + argv.unshift(arg.slice(1).join('=')); + } + arg = arg[0]; + } else if (arg[0] === '-') { + if (arg.length > 2) { + // e.g. -abc + argv = arg.substring(1).split('').map(function(ch) { + return '-' + ch; + }).concat(argv); + arg = argv.shift(); + } else { + // e.g. -a + } + } else { + // e.g. foo + } + + return arg; + } + + while (argv.length) { + arg = getArg(); + switch (arg) { + case '-o': + case '--output': + output = argv.shift(); + break; + case '-i': + case '--input': + input = argv.shift(); + break; + case '-s': + case '--string': + string = argv.shift(); + break; + case '-t': + case '--tokens': + tokens = true; + break; + case '-c': + case '--config': + config = argv.shift(); + break; + case '-n': + case '--no-clobber': + noclobber = true; + break; + case '-h': + case '--help': + return await help(); + case '-v': + case '--version': + return await version(); + default: + if (arg.indexOf('--') === 0) { + opt = camelize(arg.replace(/^--(no-)?/, '')); + if (!(opt in marked.defaults)) { + continue; + } + if (arg.indexOf('--no-') === 0) { + options[opt] = typeof marked.defaults[opt] !== 'boolean' + ? null + : false; + } else { + options[opt] = typeof marked.defaults[opt] !== 'boolean' + ? argv.shift() + : true; + } + } else { + files.push(arg); + } + break; + } + } + + async function getData() { + if (!input) { + if (files.length <= 2) { + if (string) { + return string; + } + return await getStdin(); + } + input = files.pop(); + } + return await readFile(input, 'utf8'); + } + + function resolveFile(file) { + return resolve(file.replace(/^~/, homedir)); + } + + function fileExists(file) { + return access(resolveFile(file)).then(() => true, () => false); + } + + async function runConfig(file) { + const configFile = resolveFile(file); + let markedConfig; + try { + // try require for json + markedConfig = require(configFile); + } catch (err) { + if (err.code !== 'ERR_REQUIRE_ESM') { + throw err; + } + // must import esm + markedConfig = await import('file:///' + configFile); + } + + if (markedConfig.default) { + markedConfig = markedConfig.default; + } + + if (typeof markedConfig === 'function') { + markedConfig(marked); + } else { + marked.use(markedConfig); + } + } + + const data = await getData(); + + if (config) { + if (!await fileExists(config)) { + throw Error(`Cannot load config file '${config}'`); + } + + await runConfig(config); + } else { + const defaultConfig = [ + '~/.marked.json', + '~/.marked.js', + '~/.marked/index.js', + ]; + + for (const configFile of defaultConfig) { + if (await fileExists(configFile)) { + await runConfig(configFile); + break; + } + } + } + + const html = tokens + ? JSON.stringify(marked.lexer(data, options), null, 2) + : await marked.parse(data, options); + + if (output) { + if (noclobber && await fileExists(output)) { + throw Error('marked: output file \'' + output + '\' already exists, disable the \'-n\' / \'--no-clobber\' flag to overwrite\n'); + } + return await writeFile(output, html); + } + + nodeProcess.stdout.write(html + '\n'); + } + + /** + * Helpers + */ + function getStdin() { + return new Promise((resolve, reject) => { + const stdin = nodeProcess.stdin; + let buff = ''; + + stdin.setEncoding('utf8'); + + stdin.on('data', function(data) { + buff += data; + }); + + stdin.on('error', function(err) { + reject(err); + }); + + stdin.on('end', function() { + resolve(buff); + }); + + stdin.resume(); + }); + } + + /** + * @param {string} text + */ + function camelize(text) { + return text.replace(/(\w)-(\w)/g, function(_, a, b) { + return a + b.toUpperCase(); + }); + } + + try { + await start(nodeProcess.argv.slice()); + nodeProcess.exit(0); + } catch (err) { + if (err.code === 'ENOENT') { + nodeProcess.stderr.write('marked: ' + err.path + ': No such file or directory'); + } else { + nodeProcess.stderr.write(err.message); + } + return nodeProcess.exit(1); + } +} diff --git a/docs/node_modules/marked/bin/marked.js b/docs/node_modules/marked/bin/marked.js new file mode 100755 index 00000000..e2dd816f --- /dev/null +++ b/docs/node_modules/marked/bin/marked.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node + +/** + * Marked CLI + * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License) + */ + +import { main } from './main.js'; + +/** + * Expose / Entry Point + */ + +process.title = 'marked'; +main(process); diff --git a/docs/node_modules/marked/lib/marked.cjs b/docs/node_modules/marked/lib/marked.cjs new file mode 100644 index 00000000..66ce9681 --- /dev/null +++ b/docs/node_modules/marked/lib/marked.cjs @@ -0,0 +1,2570 @@ +/** + * marked v15.0.3 - a markdown parser + * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +'use strict'; + +/** + * Gets the original marked default options. + */ +function _getDefaults() { + return { + async: false, + breaks: false, + extensions: null, + gfm: true, + hooks: null, + pedantic: false, + renderer: null, + silent: false, + tokenizer: null, + walkTokens: null, + }; +} +exports.defaults = _getDefaults(); +function changeDefaults(newDefaults) { + exports.defaults = newDefaults; +} + +const noopTest = { exec: () => null }; +function edit(regex, opt = '') { + let source = typeof regex === 'string' ? regex : regex.source; + const obj = { + replace: (name, val) => { + let valSource = typeof val === 'string' ? val : val.source; + valSource = valSource.replace(other.caret, '$1'); + source = source.replace(name, valSource); + return obj; + }, + getRegex: () => { + return new RegExp(source, opt); + }, + }; + return obj; +} +const other = { + codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, + outputLinkReplace: /\\([\[\]])/g, + indentCodeCompensation: /^(\s+)(?:```)/, + beginningSpace: /^\s+/, + endingHash: /#$/, + startingSpaceChar: /^ /, + endingSpaceChar: / $/, + nonSpaceChar: /[^ ]/, + newLineCharGlobal: /\n/g, + tabCharGlobal: /\t/g, + multipleSpaceGlobal: /\s+/g, + blankLine: /^[ \t]*$/, + doubleBlankLine: /\n[ \t]*\n[ \t]*$/, + blockquoteStart: /^ {0,3}>/, + blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, + blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, + listReplaceTabs: /^\t+/, + listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, + listIsTask: /^\[[ xX]\] /, + listReplaceTask: /^\[[ xX]\] +/, + anyLine: /\n.*\n/, + hrefBrackets: /^<(.*)>$/, + tableDelimiter: /[:|]/, + tableAlignChars: /^\||\| *$/g, + tableRowBlankLine: /\n[ \t]*$/, + tableAlignRight: /^ *-+: *$/, + tableAlignCenter: /^ *:-+: *$/, + tableAlignLeft: /^ *:-+ *$/, + startATag: /^/i, + startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, + endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, + startAngleBracket: /^$/, + pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, + unicodeAlphaNumeric: /[\p{L}\p{N}]/u, + escapeTest: /[&<>"']/, + escapeReplace: /[&<>"']/g, + escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, + escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, + unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, + caret: /(^|[^\[])\^/g, + percentDecode: /%25/g, + findPipe: /\|/g, + splitPipe: / \|/, + slashPipe: /\\\|/g, + carriageReturn: /\r\n|\r/g, + spaceLine: /^ +$/gm, + notSpaceStart: /^\S*/, + endingNewline: /\n$/, + listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), + nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`), + hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), + fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`), + headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`), + htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'), +}; +/** + * Block-Level Grammar + */ +const newline = /^(?:[ \t]*(?:\n|$))+/; +const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/; +const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/; +const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/; +const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/; +const bullet = /(?:[*+-]|\d{1,9}[.)])/; +const lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/) + .replace(/bull/g, bullet) // lists can interrupt + .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt + .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt + .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt + .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt + .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt + .getRegex(); +const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/; +const blockText = /^[^\n]+/; +const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/; +const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/) + .replace('label', _blockLabel) + .replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/) + .getRegex(); +const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/) + .replace(/bull/g, bullet) + .getRegex(); +const _tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title' + + '|tr|track|ul'; +const _comment = /|$))/; +const html = edit('^ {0,3}(?:' // optional indentation + + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6) + + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag + + ')', 'i') + .replace('comment', _comment) + .replace('tag', _tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); +const paragraph = edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(); +const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/) + .replace('paragraph', paragraph) + .getRegex(); +/** + * Normal Block Grammar + */ +const blockNormal = { + blockquote, + code: blockCode, + def, + fences, + heading, + hr, + html, + lheading, + list, + newline, + paragraph, + table: noopTest, + text: blockText, +}; +/** + * GFM Block Grammar + */ +const gfmTable = edit('^ *([^\\n ].*)\\n' // Header + + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align + + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('blockquote', ' {0,3}>') + .replace('code', '(?: {4}| {0,3}\t)[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // tables can be interrupted by type (6) html blocks + .getRegex(); +const blockGfm = { + ...blockNormal, + table: gfmTable, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('table', gfmTable) // interrupt paragraphs with table + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(), +}; +/** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ +const blockPedantic = { + ...blockNormal, + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', _comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' *#{1,6} *[^\n]') + .replace('lheading', lheading) + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('|fences', '') + .replace('|list', '') + .replace('|html', '') + .replace('|tag', '') + .getRegex(), +}; +/** + * Inline-Level Grammar + */ +const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/; +const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/; +const br = /^( {2,}|\\)\n(?!\s*$)/; +const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\ +const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g; +const emStrongLDelim = edit(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/, 'u') + .replace(/punct/g, _punctuation) + .getRegex(); +const emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong + + '|[^*]+(?=[^*])' // Consume to delim + + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter + + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter + + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter + + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter + + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter + + '|notPunctSpace(\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +// (6) Not allowed for _ +const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong + + '|[^_]+(?=[^_])' // Consume to delim + + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter + + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter + + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter + + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter + + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +const anyPunctuation = edit(/\\(punct)/, 'gu') + .replace(/punct/g, _punctuation) + .getRegex(); +const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/) + .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/) + .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/) + .getRegex(); +const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex(); +const tag = edit('^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^') // CDATA section + .replace('comment', _inlineComment) + .replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/) + .getRegex(); +const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; +const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/) + .replace('label', _inlineLabel) + .replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/) + .replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/) + .getRegex(); +const reflink = edit(/^!?\[(label)\]\[(ref)\]/) + .replace('label', _inlineLabel) + .replace('ref', _blockLabel) + .getRegex(); +const nolink = edit(/^!?\[(ref)\](?:\[\])?/) + .replace('ref', _blockLabel) + .getRegex(); +const reflinkSearch = edit('reflink|nolink(?!\\()', 'g') + .replace('reflink', reflink) + .replace('nolink', nolink) + .getRegex(); +/** + * Normal Inline Grammar + */ +const inlineNormal = { + _backpedal: noopTest, // only used for GFM url + anyPunctuation, + autolink, + blockSkip, + br, + code: inlineCode, + del: noopTest, + emStrongLDelim, + emStrongRDelimAst, + emStrongRDelimUnd, + escape: escape$1, + link, + nolink, + punctuation, + reflink, + reflinkSearch, + tag, + text: inlineText, + url: noopTest, +}; +/** + * Pedantic Inline Grammar + */ +const inlinePedantic = { + ...inlineNormal, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', _inlineLabel) + .getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', _inlineLabel) + .getRegex(), +}; +/** + * GFM Inline Grammar + */ +const inlineGfm = { + ...inlineNormal, + escape: edit(escape$1).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i') + .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\': '>', + '"': '"', + "'": ''', +}; +const getEscapeReplacement = (ch) => escapeReplacements[ch]; +function escape(html, encode) { + if (encode) { + if (other.escapeTest.test(html)) { + return html.replace(other.escapeReplace, getEscapeReplacement); + } + } + else { + if (other.escapeTestNoEncode.test(html)) { + return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement); + } + } + return html; +} +function cleanUrl(href) { + try { + href = encodeURI(href).replace(other.percentDecode, '%'); + } + catch { + return null; + } + return href; +} +function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + const row = tableRow.replace(other.findPipe, (match, offset, str) => { + let escaped = false; + let curr = offset; + while (--curr >= 0 && str[curr] === '\\') + escaped = !escaped; + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } + else { + // add space before unescaped | + return ' |'; + } + }), cells = row.split(other.splitPipe); + let i = 0; + // First/last cell in a row cannot be empty if it has no leading/trailing pipe + if (!cells[0].trim()) { + cells.shift(); + } + if (cells.length > 0 && !cells.at(-1)?.trim()) { + cells.pop(); + } + if (count) { + if (cells.length > count) { + cells.splice(count); + } + else { + while (cells.length < count) + cells.push(''); + } + } + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(other.slashPipe, '|'); + } + return cells; +} +/** + * Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + * /c*$/ is vulnerable to REDOS. + * + * @param str + * @param c + * @param invert Remove suffix of non-c chars instead. Default falsey. + */ +function rtrim(str, c, invert) { + const l = str.length; + if (l === 0) { + return ''; + } + // Length of suffix matching the invert condition. + let suffLen = 0; + // Step left until we fail to match the invert condition. + while (suffLen < l) { + const currChar = str.charAt(l - suffLen - 1); + if (currChar === c && !invert) { + suffLen++; + } + else if (currChar !== c && invert) { + suffLen++; + } + else { + break; + } + } + return str.slice(0, l - suffLen); +} +function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + let level = 0; + for (let i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } + else if (str[i] === b[0]) { + level++; + } + else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; +} + +function outputLink(cap, link, raw, lexer, rules) { + const href = link.href; + const title = link.title || null; + const text = cap[1].replace(rules.other.outputLinkReplace, '$1'); + if (cap[0].charAt(0) !== '!') { + lexer.state.inLink = true; + const token = { + type: 'link', + raw, + href, + title, + text, + tokens: lexer.inlineTokens(text), + }; + lexer.state.inLink = false; + return token; + } + return { + type: 'image', + raw, + href, + title, + text, + }; +} +function indentCodeCompensation(raw, text, rules) { + const matchIndentToCode = raw.match(rules.other.indentCodeCompensation); + if (matchIndentToCode === null) { + return text; + } + const indentToCode = matchIndentToCode[1]; + return text + .split('\n') + .map(node => { + const matchIndentInNode = node.match(rules.other.beginningSpace); + if (matchIndentInNode === null) { + return node; + } + const [indentInNode] = matchIndentInNode; + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + return node; + }) + .join('\n'); +} +/** + * Tokenizer + */ +class _Tokenizer { + options; + rules; // set by the lexer + lexer; // set by the lexer + constructor(options) { + this.options = options || exports.defaults; + } + space(src) { + const cap = this.rules.block.newline.exec(src); + if (cap && cap[0].length > 0) { + return { + type: 'space', + raw: cap[0], + }; + } + } + code(src) { + const cap = this.rules.block.code.exec(src); + if (cap) { + const text = cap[0].replace(this.rules.other.codeRemoveIndent, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic + ? rtrim(text, '\n') + : text, + }; + } + } + fences(src) { + const cap = this.rules.block.fences.exec(src); + if (cap) { + const raw = cap[0]; + const text = indentCodeCompensation(raw, cap[3] || '', this.rules); + return { + type: 'code', + raw, + lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2], + text, + }; + } + } + heading(src) { + const cap = this.rules.block.heading.exec(src); + if (cap) { + let text = cap[2].trim(); + // remove trailing #s + if (this.rules.other.endingHash.test(text)) { + const trimmed = rtrim(text, '#'); + if (this.options.pedantic) { + text = trimmed.trim(); + } + else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + return { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text, + tokens: this.lexer.inline(text), + }; + } + } + hr(src) { + const cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: 'hr', + raw: rtrim(cap[0], '\n'), + }; + } + } + blockquote(src) { + const cap = this.rules.block.blockquote.exec(src); + if (cap) { + let lines = rtrim(cap[0], '\n').split('\n'); + let raw = ''; + let text = ''; + const tokens = []; + while (lines.length > 0) { + let inBlockquote = false; + const currentLines = []; + let i; + for (i = 0; i < lines.length; i++) { + // get lines up to a continuation + if (this.rules.other.blockquoteStart.test(lines[i])) { + currentLines.push(lines[i]); + inBlockquote = true; + } + else if (!inBlockquote) { + currentLines.push(lines[i]); + } + else { + break; + } + } + lines = lines.slice(i); + const currentRaw = currentLines.join('\n'); + const currentText = currentRaw + // precede setext continuation with 4 spaces so it isn't a setext + .replace(this.rules.other.blockquoteSetextReplace, '\n $1') + .replace(this.rules.other.blockquoteSetextReplace2, ''); + raw = raw ? `${raw}\n${currentRaw}` : currentRaw; + text = text ? `${text}\n${currentText}` : currentText; + // parse blockquote lines as top level tokens + // merge paragraphs if this is a continuation + const top = this.lexer.state.top; + this.lexer.state.top = true; + this.lexer.blockTokens(currentText, tokens, true); + this.lexer.state.top = top; + // if there is no continuation then we are done + if (lines.length === 0) { + break; + } + const lastToken = tokens.at(-1); + if (lastToken?.type === 'code') { + // blockquote continuation cannot be preceded by a code block + break; + } + else if (lastToken?.type === 'blockquote') { + // include continuation in nested blockquote + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.blockquote(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.text.length) + newToken.text; + break; + } + else if (lastToken?.type === 'list') { + // include continuation in nested list + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.list(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw; + lines = newText.substring(tokens.at(-1).raw.length).split('\n'); + continue; + } + } + return { + type: 'blockquote', + raw, + tokens, + text, + }; + } + } + list(src) { + let cap = this.rules.block.list.exec(src); + if (cap) { + let bull = cap[1].trim(); + const isordered = bull.length > 1; + const list = { + type: 'list', + raw: '', + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [], + }; + bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`; + if (this.options.pedantic) { + bull = isordered ? bull : '[*+-]'; + } + // Get next list item + const itemRegex = this.rules.other.listItemRegex(bull); + let endsWithBlankLine = false; + // Check if current bullet point can start a new List Item + while (src) { + let endEarly = false; + let raw = ''; + let itemContents = ''; + if (!(cap = itemRegex.exec(src))) { + break; + } + if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?) + break; + } + raw = cap[0]; + src = src.substring(raw.length); + let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length)); + let nextLine = src.split('\n', 1)[0]; + let blankLine = !line.trim(); + let indent = 0; + if (this.options.pedantic) { + indent = 2; + itemContents = line.trimStart(); + } + else if (blankLine) { + indent = cap[1].length + 1; + } + else { + indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char + indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent + itemContents = line.slice(indent); + indent += cap[1].length; + } + if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line + raw += nextLine + '\n'; + src = src.substring(nextLine.length + 1); + endEarly = true; + } + if (!endEarly) { + const nextBulletRegex = this.rules.other.nextBulletRegex(indent); + const hrRegex = this.rules.other.hrRegex(indent); + const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent); + const headingBeginRegex = this.rules.other.headingBeginRegex(indent); + const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent); + // Check if following lines should be included in List Item + while (src) { + const rawLine = src.split('\n', 1)[0]; + let nextLineWithoutTabs; + nextLine = rawLine; + // Re-align to follow commonmark nesting rules + if (this.options.pedantic) { + nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' '); + nextLineWithoutTabs = nextLine; + } + else { + nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' '); + } + // End list item if found code fences + if (fencesBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new heading + if (headingBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of html block + if (htmlBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new bullet + if (nextBulletRegex.test(nextLine)) { + break; + } + // Horizontal rule found + if (hrRegex.test(nextLine)) { + break; + } + if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible + itemContents += '\n' + nextLineWithoutTabs.slice(indent); + } + else { + // not enough indentation + if (blankLine) { + break; + } + // paragraph continuation unless last line was a different block level element + if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block + break; + } + if (fencesBeginRegex.test(line)) { + break; + } + if (headingBeginRegex.test(line)) { + break; + } + if (hrRegex.test(line)) { + break; + } + itemContents += '\n' + nextLine; + } + if (!blankLine && !nextLine.trim()) { // Check if current line is blank + blankLine = true; + } + raw += rawLine + '\n'; + src = src.substring(rawLine.length + 1); + line = nextLineWithoutTabs.slice(indent); + } + } + if (!list.loose) { + // If the previous item ended with a blank line, the list is loose + if (endsWithBlankLine) { + list.loose = true; + } + else if (this.rules.other.doubleBlankLine.test(raw)) { + endsWithBlankLine = true; + } + } + let istask = null; + let ischecked; + // Check for task list items + if (this.options.gfm) { + istask = this.rules.other.listIsTask.exec(itemContents); + if (istask) { + ischecked = istask[0] !== '[ ] '; + itemContents = itemContents.replace(this.rules.other.listReplaceTask, ''); + } + } + list.items.push({ + type: 'list_item', + raw, + task: !!istask, + checked: ischecked, + loose: false, + text: itemContents, + tokens: [], + }); + list.raw += raw; + } + // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic + const lastItem = list.items.at(-1); + if (lastItem) { + lastItem.raw = lastItem.raw.trimEnd(); + lastItem.text = lastItem.text.trimEnd(); + } + list.raw = list.raw.trimEnd(); + // Item child tokens handled here at end because we needed to have the final item to trim it first + for (let i = 0; i < list.items.length; i++) { + this.lexer.state.top = false; + list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []); + if (!list.loose) { + // Check if list should be loose + const spacers = list.items[i].tokens.filter(t => t.type === 'space'); + const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw)); + list.loose = hasMultipleLineBreaks; + } + } + // Set all items to loose if list is loose + if (list.loose) { + for (let i = 0; i < list.items.length; i++) { + list.items[i].loose = true; + } + } + return list; + } + } + html(src) { + const cap = this.rules.block.html.exec(src); + if (cap) { + const token = { + type: 'html', + block: true, + raw: cap[0], + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0], + }; + return token; + } + } + def(src) { + const cap = this.rules.block.def.exec(src); + if (cap) { + const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' '); + const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : ''; + const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3]; + return { + type: 'def', + tag, + raw: cap[0], + href, + title, + }; + } + } + table(src) { + const cap = this.rules.block.table.exec(src); + if (!cap) { + return; + } + if (!this.rules.other.tableDelimiter.test(cap[2])) { + // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading + return; + } + const headers = splitCells(cap[1]); + const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|'); + const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : []; + const item = { + type: 'table', + raw: cap[0], + header: [], + align: [], + rows: [], + }; + if (headers.length !== aligns.length) { + // header and align columns must be equal, rows can be different. + return; + } + for (const align of aligns) { + if (this.rules.other.tableAlignRight.test(align)) { + item.align.push('right'); + } + else if (this.rules.other.tableAlignCenter.test(align)) { + item.align.push('center'); + } + else if (this.rules.other.tableAlignLeft.test(align)) { + item.align.push('left'); + } + else { + item.align.push(null); + } + } + for (let i = 0; i < headers.length; i++) { + item.header.push({ + text: headers[i], + tokens: this.lexer.inline(headers[i]), + header: true, + align: item.align[i], + }); + } + for (const row of rows) { + item.rows.push(splitCells(row, item.header.length).map((cell, i) => { + return { + text: cell, + tokens: this.lexer.inline(cell), + header: false, + align: item.align[i], + }; + })); + } + return item; + } + lheading(src) { + const cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1], + tokens: this.lexer.inline(cap[1]), + }; + } + } + paragraph(src) { + const cap = this.rules.block.paragraph.exec(src); + if (cap) { + const text = cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1]; + return { + type: 'paragraph', + raw: cap[0], + text, + tokens: this.lexer.inline(text), + }; + } + } + text(src) { + const cap = this.rules.block.text.exec(src); + if (cap) { + return { + type: 'text', + raw: cap[0], + text: cap[0], + tokens: this.lexer.inline(cap[0]), + }; + } + } + escape(src) { + const cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: cap[1], + }; + } + } + tag(src) { + const cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) { + this.lexer.state.inLink = true; + } + else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) { + this.lexer.state.inLink = false; + } + if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = true; + } + else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = false; + } + return { + type: 'html', + raw: cap[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: false, + text: cap[0], + }; + } + } + link(src) { + const cap = this.rules.inline.link.exec(src); + if (cap) { + const trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) { + // commonmark requires matching angle brackets + if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) { + return; + } + // ending angle bracket cannot be escaped + const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\'); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } + else { + // find closing parenthesis + const lastParenIndex = findClosingBracket(cap[2], '()'); + if (lastParenIndex > -1) { + const start = cap[0].indexOf('!') === 0 ? 5 : 4; + const linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + let href = cap[2]; + let title = ''; + if (this.options.pedantic) { + // split pedantic href and title + const link = this.rules.other.pedanticHrefTitle.exec(href); + if (link) { + href = link[1]; + title = link[3]; + } + } + else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim(); + if (this.rules.other.startAngleBracket.test(href)) { + if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } + else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href, + title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title, + }, cap[0], this.lexer, this.rules); + } + } + reflink(src, links) { + let cap; + if ((cap = this.rules.inline.reflink.exec(src)) + || (cap = this.rules.inline.nolink.exec(src))) { + const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' '); + const link = links[linkString.toLowerCase()]; + if (!link) { + const text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text, + }; + } + return outputLink(cap, link, cap[0], this.lexer, this.rules); + } + } + emStrong(src, maskedSrc, prevChar = '') { + let match = this.rules.inline.emStrongLDelim.exec(src); + if (!match) + return; + // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well + if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) + return; + const nextChar = match[1] || match[2] || ''; + if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) { + // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below) + const lLength = [...match[0]].length - 1; + let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0; + const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + endReg.lastIndex = 0; + // Clip maskedSrc to same section of string as src (move to lexer?) + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) + continue; // skip single * in __abc*abc__ + rLength = [...rDelim].length; + if (match[3] || match[4]) { // found another Left Delim + delimTotal += rLength; + continue; + } + else if (match[5] || match[6]) { // either Left or Right Delim + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; // CommonMark Emphasis Rules 9-10 + } + } + delimTotal -= rLength; + if (delimTotal > 0) + continue; // Haven't found enough closing delimiters + // Remove extra characters. *a*** -> *a* + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); + // char length can be >1 for unicode characters; + const lastCharLength = [...match[0]][0].length; + const raw = src.slice(0, lLength + match.index + lastCharLength + rLength); + // Create `em` if smallest delimiter has odd char count. *a*** + if (Math.min(lLength, rLength) % 2) { + const text = raw.slice(1, -1); + return { + type: 'em', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + // Create 'strong' if smallest delimiter has even char count. **a*** + const text = raw.slice(2, -2); + return { + type: 'strong', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + } + } + codespan(src) { + const cap = this.rules.inline.code.exec(src); + if (cap) { + let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' '); + const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text); + const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + return { + type: 'codespan', + raw: cap[0], + text, + }; + } + } + br(src) { + const cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: 'br', + raw: cap[0], + }; + } + } + del(src) { + const cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2], + tokens: this.lexer.inlineTokens(cap[2]), + }; + } + } + autolink(src) { + const cap = this.rules.inline.autolink.exec(src); + if (cap) { + let text, href; + if (cap[2] === '@') { + text = cap[1]; + href = 'mailto:' + text; + } + else { + text = cap[1]; + href = text; + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + url(src) { + let cap; + if (cap = this.rules.inline.url.exec(src)) { + let text, href; + if (cap[2] === '@') { + text = cap[0]; + href = 'mailto:' + text; + } + else { + // do extended autolink path validation + let prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? ''; + } while (prevCapZero !== cap[0]); + text = cap[0]; + if (cap[1] === 'www.') { + href = 'http://' + cap[0]; + } + else { + href = cap[0]; + } + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + inlineText(src) { + const cap = this.rules.inline.text.exec(src); + if (cap) { + const escaped = this.lexer.state.inRawBlock; + return { + type: 'text', + raw: cap[0], + text: cap[0], + escaped, + }; + } + } +} + +/** + * Block Lexer + */ +class _Lexer { + tokens; + options; + state; + tokenizer; + inlineQueue; + constructor(options) { + // TokenList cannot be created in one go + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || exports.defaults; + this.options.tokenizer = this.options.tokenizer || new _Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + this.tokenizer.lexer = this; + this.inlineQueue = []; + this.state = { + inLink: false, + inRawBlock: false, + top: true, + }; + const rules = { + other, + block: block.normal, + inline: inline.normal, + }; + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } + else if (this.options.gfm) { + rules.block = block.gfm; + if (this.options.breaks) { + rules.inline = inline.breaks; + } + else { + rules.inline = inline.gfm; + } + } + this.tokenizer.rules = rules; + } + /** + * Expose Rules + */ + static get rules() { + return { + block, + inline, + }; + } + /** + * Static Lex Method + */ + static lex(src, options) { + const lexer = new _Lexer(options); + return lexer.lex(src); + } + /** + * Static Lex Inline Method + */ + static lexInline(src, options) { + const lexer = new _Lexer(options); + return lexer.inlineTokens(src); + } + /** + * Preprocessing + */ + lex(src) { + src = src.replace(other.carriageReturn, '\n'); + this.blockTokens(src, this.tokens); + for (let i = 0; i < this.inlineQueue.length; i++) { + const next = this.inlineQueue[i]; + this.inlineTokens(next.src, next.tokens); + } + this.inlineQueue = []; + return this.tokens; + } + blockTokens(src, tokens = [], lastParagraphClipped = false) { + if (this.options.pedantic) { + src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, ''); + } + while (src) { + let token; + if (this.options.extensions?.block?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // newline + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.raw.length === 1 && lastToken !== undefined) { + // if there's a single \n as a spacer, it's terminating the last line, + // so move it there so that we don't get unnecessary paragraph tags + lastToken.raw += '\n'; + } + else { + tokens.push(token); + } + continue; + } + // code + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + // An indented code block cannot interrupt a paragraph. + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + // fences + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // heading + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // hr + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // blockquote + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // list + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // html + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // def + if (token = this.tokenizer.def(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.raw; + this.inlineQueue.at(-1).src = lastToken.text; + } + else if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title, + }; + } + continue; + } + // table (gfm) + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // lheading + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // top-level paragraph + // prevent paragraph consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startBlock) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startBlock.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) { + const lastToken = tokens.at(-1); + if (lastParagraphClipped && lastToken?.type === 'paragraph') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } + // text + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + this.state.top = true; + return tokens; + } + inline(src, tokens = []) { + this.inlineQueue.push({ src, tokens }); + return tokens; + } + /** + * Lexing/Compiling + */ + inlineTokens(src, tokens = []) { + // String with links masked to avoid interference with em and strong + let maskedSrc = src; + let match = null; + // Mask out reflinks + if (this.tokens.links) { + const links = Object.keys(this.tokens.links); + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + + '[' + 'a'.repeat(match[0].length - 2) + ']' + + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + // Mask out other blocks + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + // Mask out escaped characters + while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + } + let keepPrevChar = false; + let prevChar = ''; + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + keepPrevChar = false; + let token; + // extensions + if (this.options.extensions?.inline?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // escape + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // tag + if (token = this.tokenizer.tag(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // link + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // reflink, nolink + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.type === 'text' && lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + // em & strong + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // code + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // br + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // del (gfm) + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // autolink + if (token = this.tokenizer.autolink(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // url (gfm) + if (!this.state.inLink && (token = this.tokenizer.url(src))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // text + // prevent inlineText consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startInline) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startInline.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (token = this.tokenizer.inlineText(cutSrc)) { + src = src.substring(token.raw.length); + if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started + prevChar = token.raw.slice(-1); + } + keepPrevChar = true; + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + return tokens; + } +} + +/** + * Renderer + */ +class _Renderer { + options; + parser; // set by the parser + constructor(options) { + this.options = options || exports.defaults; + } + space(token) { + return ''; + } + code({ text, lang, escaped }) { + const langString = (lang || '').match(other.notSpaceStart)?.[0]; + const code = text.replace(other.endingNewline, '') + '\n'; + if (!langString) { + return '
'
+                + (escaped ? code : escape(code, true))
+                + '
\n'; + } + return '
'
+            + (escaped ? code : escape(code, true))
+            + '
\n'; + } + blockquote({ tokens }) { + const body = this.parser.parse(tokens); + return `
\n${body}
\n`; + } + html({ text }) { + return text; + } + heading({ tokens, depth }) { + return `${this.parser.parseInline(tokens)}\n`; + } + hr(token) { + return '
\n'; + } + list(token) { + const ordered = token.ordered; + const start = token.start; + let body = ''; + for (let j = 0; j < token.items.length; j++) { + const item = token.items[j]; + body += this.listitem(item); + } + const type = ordered ? 'ol' : 'ul'; + const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startAttr + '>\n' + body + '\n'; + } + listitem(item) { + let itemBody = ''; + if (item.task) { + const checkbox = this.checkbox({ checked: !!item.checked }); + if (item.loose) { + if (item.tokens[0]?.type === 'paragraph') { + item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text); + item.tokens[0].tokens[0].escaped = true; + } + } + else { + item.tokens.unshift({ + type: 'text', + raw: checkbox + ' ', + text: checkbox + ' ', + escaped: true, + }); + } + } + else { + itemBody += checkbox + ' '; + } + } + itemBody += this.parser.parse(item.tokens, !!item.loose); + return `
  • ${itemBody}
  • \n`; + } + checkbox({ checked }) { + return ''; + } + paragraph({ tokens }) { + return `

    ${this.parser.parseInline(tokens)}

    \n`; + } + table(token) { + let header = ''; + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + body += this.tablerow({ text: cell }); + } + if (body) + body = `${body}`; + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; + } + tablerow({ text }) { + return `\n${text}\n`; + } + tablecell(token) { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + } + /** + * span level renderer + */ + strong({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + em({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + codespan({ text }) { + return `${escape(text, true)}`; + } + br(token) { + return '
    '; + } + del({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + link({ href, title, tokens }) { + const text = this.parser.parseInline(tokens); + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return text; + } + href = cleanHref; + let out = '
    '; + return out; + } + image({ href, title, text }) { + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return escape(text); + } + href = cleanHref; + let out = `${text} { + const tokens = genericToken[childTokens].flat(Infinity); + values = values.concat(this.walkTokens(tokens, callback)); + }); + } + else if (genericToken.tokens) { + values = values.concat(this.walkTokens(genericToken.tokens, callback)); + } + } + } + } + return values; + } + use(...args) { + const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} }; + args.forEach((pack) => { + // copy options to new object + const opts = { ...pack }; + // set async to true if it was set to true before + opts.async = this.defaults.async || opts.async || false; + // ==-- Parse "addon" extensions --== // + if (pack.extensions) { + pack.extensions.forEach((ext) => { + if (!ext.name) { + throw new Error('extension name required'); + } + if ('renderer' in ext) { // Renderer extensions + const prevRenderer = extensions.renderers[ext.name]; + if (prevRenderer) { + // Replace extension with func to run new extension but fall back if false + extensions.renderers[ext.name] = function (...args) { + let ret = ext.renderer.apply(this, args); + if (ret === false) { + ret = prevRenderer.apply(this, args); + } + return ret; + }; + } + else { + extensions.renderers[ext.name] = ext.renderer; + } + } + if ('tokenizer' in ext) { // Tokenizer Extensions + if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) { + throw new Error("extension level must be 'block' or 'inline'"); + } + const extLevel = extensions[ext.level]; + if (extLevel) { + extLevel.unshift(ext.tokenizer); + } + else { + extensions[ext.level] = [ext.tokenizer]; + } + if (ext.start) { // Function to check for start of token + if (ext.level === 'block') { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } + else { + extensions.startBlock = [ext.start]; + } + } + else if (ext.level === 'inline') { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } + else { + extensions.startInline = [ext.start]; + } + } + } + } + if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + opts.extensions = extensions; + } + // ==-- Parse "overwrite" extensions --== // + if (pack.renderer) { + const renderer = this.defaults.renderer || new _Renderer(this.defaults); + for (const prop in pack.renderer) { + if (!(prop in renderer)) { + throw new Error(`renderer '${prop}' does not exist`); + } + if (['options', 'parser'].includes(prop)) { + // ignore options property + continue; + } + const rendererProp = prop; + const rendererFunc = pack.renderer[rendererProp]; + const prevRenderer = renderer[rendererProp]; + // Replace renderer with func to run extension, but fall back if false + renderer[rendererProp] = (...args) => { + let ret = rendererFunc.apply(renderer, args); + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + return ret || ''; + }; + } + opts.renderer = renderer; + } + if (pack.tokenizer) { + const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults); + for (const prop in pack.tokenizer) { + if (!(prop in tokenizer)) { + throw new Error(`tokenizer '${prop}' does not exist`); + } + if (['options', 'rules', 'lexer'].includes(prop)) { + // ignore options, rules, and lexer properties + continue; + } + const tokenizerProp = prop; + const tokenizerFunc = pack.tokenizer[tokenizerProp]; + const prevTokenizer = tokenizer[tokenizerProp]; + // Replace tokenizer with func to run extension, but fall back if false + // @ts-expect-error cannot type tokenizer function dynamically + tokenizer[tokenizerProp] = (...args) => { + let ret = tokenizerFunc.apply(tokenizer, args); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + return ret; + }; + } + opts.tokenizer = tokenizer; + } + // ==-- Parse Hooks extensions --== // + if (pack.hooks) { + const hooks = this.defaults.hooks || new _Hooks(); + for (const prop in pack.hooks) { + if (!(prop in hooks)) { + throw new Error(`hook '${prop}' does not exist`); + } + if (['options', 'block'].includes(prop)) { + // ignore options and block properties + continue; + } + const hooksProp = prop; + const hooksFunc = pack.hooks[hooksProp]; + const prevHook = hooks[hooksProp]; + if (_Hooks.passThroughHooks.has(prop)) { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (arg) => { + if (this.defaults.async) { + return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => { + return prevHook.call(hooks, ret); + }); + } + const ret = hooksFunc.call(hooks, arg); + return prevHook.call(hooks, ret); + }; + } + else { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (...args) => { + let ret = hooksFunc.apply(hooks, args); + if (ret === false) { + ret = prevHook.apply(hooks, args); + } + return ret; + }; + } + } + opts.hooks = hooks; + } + // ==-- Parse WalkTokens extensions --== // + if (pack.walkTokens) { + const walkTokens = this.defaults.walkTokens; + const packWalktokens = pack.walkTokens; + opts.walkTokens = function (token) { + let values = []; + values.push(packWalktokens.call(this, token)); + if (walkTokens) { + values = values.concat(walkTokens.call(this, token)); + } + return values; + }; + } + this.defaults = { ...this.defaults, ...opts }; + }); + return this; + } + setOptions(opt) { + this.defaults = { ...this.defaults, ...opt }; + return this; + } + lexer(src, options) { + return _Lexer.lex(src, options ?? this.defaults); + } + parser(tokens, options) { + return _Parser.parse(tokens, options ?? this.defaults); + } + parseMarkdown(blockType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parse = (src, options) => { + const origOpt = { ...options }; + const opt = { ...this.defaults, ...origOpt }; + const throwError = this.onError(!!opt.silent, !!opt.async); + // throw error if an extension set async to true but parse was called with async: false + if (this.defaults.async === true && origOpt.async === false) { + return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.')); + } + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + return throwError(new Error('marked(): input parameter is undefined or null')); + } + if (typeof src !== 'string') { + return throwError(new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected')); + } + if (opt.hooks) { + opt.hooks.options = opt; + opt.hooks.block = blockType; + } + const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline); + const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline); + if (opt.async) { + return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src) + .then(src => lexer(src, opt)) + .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens) + .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens) + .then(tokens => parser(tokens, opt)) + .then(html => opt.hooks ? opt.hooks.postprocess(html) : html) + .catch(throwError); + } + try { + if (opt.hooks) { + src = opt.hooks.preprocess(src); + } + let tokens = lexer(src, opt); + if (opt.hooks) { + tokens = opt.hooks.processAllTokens(tokens); + } + if (opt.walkTokens) { + this.walkTokens(tokens, opt.walkTokens); + } + let html = parser(tokens, opt); + if (opt.hooks) { + html = opt.hooks.postprocess(html); + } + return html; + } + catch (e) { + return throwError(e); + } + }; + return parse; + } + onError(silent, async) { + return (e) => { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (silent) { + const msg = '

    An error occurred:

    '
    +                    + escape(e.message + '', true)
    +                    + '
    '; + if (async) { + return Promise.resolve(msg); + } + return msg; + } + if (async) { + return Promise.reject(e); + } + throw e; + }; + } +} + +const markedInstance = new Marked(); +function marked(src, opt) { + return markedInstance.parse(src, opt); +} +/** + * Sets the default options. + * + * @param options Hash of options + */ +marked.options = + marked.setOptions = function (options) { + markedInstance.setOptions(options); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; + }; +/** + * Gets the original marked default options. + */ +marked.getDefaults = _getDefaults; +marked.defaults = exports.defaults; +/** + * Use Extension + */ +marked.use = function (...args) { + markedInstance.use(...args); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; +}; +/** + * Run callback for every token + */ +marked.walkTokens = function (tokens, callback) { + return markedInstance.walkTokens(tokens, callback); +}; +/** + * Compiles markdown to HTML without enclosing `p` tag. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @return String of compiled HTML + */ +marked.parseInline = markedInstance.parseInline; +/** + * Expose + */ +marked.Parser = _Parser; +marked.parser = _Parser.parse; +marked.Renderer = _Renderer; +marked.TextRenderer = _TextRenderer; +marked.Lexer = _Lexer; +marked.lexer = _Lexer.lex; +marked.Tokenizer = _Tokenizer; +marked.Hooks = _Hooks; +marked.parse = marked; +const options = marked.options; +const setOptions = marked.setOptions; +const use = marked.use; +const walkTokens = marked.walkTokens; +const parseInline = marked.parseInline; +const parse = marked; +const parser = _Parser.parse; +const lexer = _Lexer.lex; + +exports.Hooks = _Hooks; +exports.Lexer = _Lexer; +exports.Marked = Marked; +exports.Parser = _Parser; +exports.Renderer = _Renderer; +exports.TextRenderer = _TextRenderer; +exports.Tokenizer = _Tokenizer; +exports.getDefaults = _getDefaults; +exports.lexer = lexer; +exports.marked = marked; +exports.options = options; +exports.parse = parse; +exports.parseInline = parseInline; +exports.parser = parser; +exports.setOptions = setOptions; +exports.use = use; +exports.walkTokens = walkTokens; +//# sourceMappingURL=marked.cjs.map diff --git a/docs/node_modules/marked/lib/marked.cjs.map b/docs/node_modules/marked/lib/marked.cjs.map new file mode 100644 index 00000000..a106920f --- /dev/null +++ b/docs/node_modules/marked/lib/marked.cjs.map @@ -0,0 +1 @@ +{"version":3,"file":"marked.cjs","sources":["../src/defaults.ts","../src/rules.ts","../src/helpers.ts","../src/Tokenizer.ts","../src/Lexer.ts","../src/Renderer.ts","../src/TextRenderer.ts","../src/Parser.ts","../src/Hooks.ts","../src/Instance.ts","../src/marked.ts"],"sourcesContent":["/**\n * Gets the original marked default options.\n */\nexport function _getDefaults() {\n return {\n async: false,\n breaks: false,\n extensions: null,\n gfm: true,\n hooks: null,\n pedantic: false,\n renderer: null,\n silent: false,\n tokenizer: null,\n walkTokens: null,\n };\n}\nexport let _defaults = _getDefaults();\nexport function changeDefaults(newDefaults) {\n _defaults = newDefaults;\n}\n","const noopTest = { exec: () => null };\nfunction edit(regex, opt = '') {\n let source = typeof regex === 'string' ? regex : regex.source;\n const obj = {\n replace: (name, val) => {\n let valSource = typeof val === 'string' ? val : val.source;\n valSource = valSource.replace(other.caret, '$1');\n source = source.replace(name, valSource);\n return obj;\n },\n getRegex: () => {\n return new RegExp(source, opt);\n },\n };\n return obj;\n}\nexport const other = {\n codeRemoveIndent: /^(?: {1,4}| {0,3}\\t)/gm,\n outputLinkReplace: /\\\\([\\[\\]])/g,\n indentCodeCompensation: /^(\\s+)(?:```)/,\n beginningSpace: /^\\s+/,\n endingHash: /#$/,\n startingSpaceChar: /^ /,\n endingSpaceChar: / $/,\n nonSpaceChar: /[^ ]/,\n newLineCharGlobal: /\\n/g,\n tabCharGlobal: /\\t/g,\n multipleSpaceGlobal: /\\s+/g,\n blankLine: /^[ \\t]*$/,\n doubleBlankLine: /\\n[ \\t]*\\n[ \\t]*$/,\n blockquoteStart: /^ {0,3}>/,\n blockquoteSetextReplace: /\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,\n blockquoteSetextReplace2: /^ {0,3}>[ \\t]?/gm,\n listReplaceTabs: /^\\t+/,\n listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,\n listIsTask: /^\\[[ xX]\\] /,\n listReplaceTask: /^\\[[ xX]\\] +/,\n anyLine: /\\n.*\\n/,\n hrefBrackets: /^<(.*)>$/,\n tableDelimiter: /[:|]/,\n tableAlignChars: /^\\||\\| *$/g,\n tableRowBlankLine: /\\n[ \\t]*$/,\n tableAlignRight: /^ *-+: *$/,\n tableAlignCenter: /^ *:-+: *$/,\n tableAlignLeft: /^ *:-+ *$/,\n startATag: /^
    /i,\n startPreScriptTag: /^<(pre|code|kbd|script)(\\s|>)/i,\n endPreScriptTag: /^<\\/(pre|code|kbd|script)(\\s|>)/i,\n startAngleBracket: /^$/,\n pedanticHrefTitle: /^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,\n unicodeAlphaNumeric: /[\\p{L}\\p{N}]/u,\n escapeTest: /[&<>\"']/,\n escapeReplace: /[&<>\"']/g,\n escapeTestNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,\n escapeReplaceNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,\n unescapeTest: /&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,\n caret: /(^|[^\\[])\\^/g,\n percentDecode: /%25/g,\n findPipe: /\\|/g,\n splitPipe: / \\|/,\n slashPipe: /\\\\\\|/g,\n carriageReturn: /\\r\\n|\\r/g,\n spaceLine: /^ +$/gm,\n notSpaceStart: /^\\S*/,\n endingNewline: /\\n$/,\n listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\\t ][^\\\\n]*)?(?:\\\\n|$))`),\n nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \\t][^\\\\n]*)?(?:\\\\n|$))`),\n hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),\n fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\\`\\`\\`|~~~)`),\n headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),\n htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'),\n};\n/**\n * Block-Level Grammar\n */\nconst newline = /^(?:[ \\t]*(?:\\n|$))+/;\nconst blockCode = /^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/;\nconst fences = /^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/;\nconst hr = /^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/;\nconst heading = /^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/;\nconst bullet = /(?:[*+-]|\\d{1,9}[.)])/;\nconst lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/)\n .replace(/bull/g, bullet) // lists can interrupt\n .replace(/blockCode/g, /(?: {4}| {0,3}\\t)/) // indented code blocks can interrupt\n .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n .getRegex();\nconst _paragraph = /^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/;\nconst blockText = /^[^\\n]+/;\nconst _blockLabel = /(?!\\s*\\])(?:\\\\.|[^\\[\\]\\\\])+/;\nconst def = edit(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/)\n .replace('label', _blockLabel)\n .replace('title', /(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/)\n .getRegex();\nconst list = edit(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/)\n .replace(/bull/g, bullet)\n .getRegex();\nconst _tag = 'address|article|aside|base|basefont|blockquote|body|caption'\n + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'\n + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'\n + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'\n + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title'\n + '|tr|track|ul';\nconst _comment = /|$))/;\nconst html = edit('^ {0,3}(?:' // optional indentation\n + '<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:[^\\\\n]*\\\\n+|$)' // (1)\n + '|comment[^\\\\n]*(\\\\n+|$)' // (2)\n + '|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)' // (3)\n + '|\\\\n*|$)' // (4)\n + '|\\\\n*|$)' // (5)\n + '|)[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (6)\n + '|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) open tag\n + '|(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) closing tag\n + ')', 'i')\n .replace('comment', _comment)\n .replace('tag', _tag)\n .replace('attribute', / +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst paragraph = edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex();\nconst blockquote = edit(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/)\n .replace('paragraph', paragraph)\n .getRegex();\n/**\n * Normal Block Grammar\n */\nconst blockNormal = {\n blockquote,\n code: blockCode,\n def,\n fences,\n heading,\n hr,\n html,\n lheading,\n list,\n newline,\n paragraph,\n table: noopTest,\n text: blockText,\n};\n/**\n * GFM Block Grammar\n */\nconst gfmTable = edit('^ *([^\\\\n ].*)\\\\n' // Header\n + ' {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)' // Align\n + '(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)') // Cells\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('blockquote', ' {0,3}>')\n .replace('code', '(?: {4}| {0,3}\\t)[^\\\\n]')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // tables can be interrupted by type (6) html blocks\n .getRegex();\nconst blockGfm = {\n ...blockNormal,\n table: gfmTable,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('table', gfmTable) // interrupt paragraphs with table\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex(),\n};\n/**\n * Pedantic grammar (original John Gruber's loose markdown specification)\n */\nconst blockPedantic = {\n ...blockNormal,\n html: edit('^ *(?:comment *(?:\\\\n|\\\\s*$)'\n + '|<(tag)[\\\\s\\\\S]+? *(?:\\\\n{2,}|\\\\s*$)' // closed tag\n + '|\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))')\n .replace('comment', _comment)\n .replace(/tag/g, '(?!(?:'\n + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'\n + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'\n + '\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b')\n .getRegex(),\n def: /^ *\\[([^\\]]+)\\]: *]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,\n heading: /^(#{1,6})(.*)(?:\\n+|$)/,\n fences: noopTest, // fences not supported\n lheading: /^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' *#{1,6} *[^\\n]')\n .replace('lheading', lheading)\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('|fences', '')\n .replace('|list', '')\n .replace('|html', '')\n .replace('|tag', '')\n .getRegex(),\n};\n/**\n * Inline-Level Grammar\n */\nconst escape = /^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/;\nconst inlineCode = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst br = /^( {2,}|\\\\)\\n(?!\\s*$)/;\nconst inlineText = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\\nconst blockSkip = /\\[[^[\\]]*?\\]\\((?:\\\\.|[^\\\\\\(\\)]|\\((?:\\\\.|[^\\\\\\(\\)])*\\))*\\)|`[^`]*?`|<[^<>]*?>/g;\nconst emStrongLDelim = edit(/^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/, 'u')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)' // Skip orphan inside strong\n + '|[^*]+(?=[^*])' // Consume to delim\n + '|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)' // (1) #*** can only be a Right Delimiter\n + '|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter\n + '|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter\n + '|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)' // (4) ***# can only be Left Delimiter\n + '|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter\n + '|notPunctSpace(\\\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\n// (6) Not allowed for _\nconst emStrongRDelimUnd = edit('^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)' // Skip orphan inside strong\n + '|[^_]+(?=[^_])' // Consume to delim\n + '|(?!_)punct(_+)(?=[\\\\s]|$)' // (1) #___ can only be a Right Delimiter\n + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter\n + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter\n + '|[\\\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter\n + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst anyPunctuation = edit(/\\\\(punct)/, 'gu')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst autolink = edit(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/)\n .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/)\n .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/)\n .getRegex();\nconst _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();\nconst tag = edit('^comment'\n + '|^' // self-closing tag\n + '|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>' // open tag\n + '|^<\\\\?[\\\\s\\\\S]*?\\\\?>' // processing instruction, e.g. \n + '|^' // declaration, e.g. \n + '|^') // CDATA section\n .replace('comment', _inlineComment)\n .replace('attribute', /\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst _inlineLabel = /(?:\\[(?:\\\\.|[^\\[\\]\\\\])*\\]|\\\\.|`[^`]*`|[^\\[\\]\\\\`])*?/;\nconst link = edit(/^!?\\[(label)\\]\\(\\s*(href)(?:\\s+(title))?\\s*\\)/)\n .replace('label', _inlineLabel)\n .replace('href', /<(?:\\\\.|[^\\n<>\\\\])+>|[^\\s\\x00-\\x1f]*/)\n .replace('title', /\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/)\n .getRegex();\nconst reflink = edit(/^!?\\[(label)\\]\\[(ref)\\]/)\n .replace('label', _inlineLabel)\n .replace('ref', _blockLabel)\n .getRegex();\nconst nolink = edit(/^!?\\[(ref)\\](?:\\[\\])?/)\n .replace('ref', _blockLabel)\n .getRegex();\nconst reflinkSearch = edit('reflink|nolink(?!\\\\()', 'g')\n .replace('reflink', reflink)\n .replace('nolink', nolink)\n .getRegex();\n/**\n * Normal Inline Grammar\n */\nconst inlineNormal = {\n _backpedal: noopTest, // only used for GFM url\n anyPunctuation,\n autolink,\n blockSkip,\n br,\n code: inlineCode,\n del: noopTest,\n emStrongLDelim,\n emStrongRDelimAst,\n emStrongRDelimUnd,\n escape,\n link,\n nolink,\n punctuation,\n reflink,\n reflinkSearch,\n tag,\n text: inlineText,\n url: noopTest,\n};\n/**\n * Pedantic Inline Grammar\n */\nconst inlinePedantic = {\n ...inlineNormal,\n link: edit(/^!?\\[(label)\\]\\((.*?)\\)/)\n .replace('label', _inlineLabel)\n .getRegex(),\n reflink: edit(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/)\n .replace('label', _inlineLabel)\n .getRegex(),\n};\n/**\n * GFM Inline Grammar\n */\nconst inlineGfm = {\n ...inlineNormal,\n escape: edit(escape).replace('])', '~|])').getRegex(),\n url: edit(/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/, 'i')\n .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)\n .getRegex(),\n _backpedal: /(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,\n del: /^(~~?)(?=[^\\s~])((?:\\\\.|[^\\\\])*?(?:\\\\.|[^\\s~\\\\]))\\1(?=[^~]|$)/,\n text: /^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\': '>',\n '\"': '"',\n \"'\": ''',\n};\nconst getEscapeReplacement = (ch) => escapeReplacements[ch];\nexport function escape(html, encode) {\n if (encode) {\n if (other.escapeTest.test(html)) {\n return html.replace(other.escapeReplace, getEscapeReplacement);\n }\n }\n else {\n if (other.escapeTestNoEncode.test(html)) {\n return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);\n }\n }\n return html;\n}\nexport function unescape(html) {\n // explicitly match decimal, hex, and named HTML entities\n return html.replace(other.unescapeTest, (_, n) => {\n n = n.toLowerCase();\n if (n === 'colon')\n return ':';\n if (n.charAt(0) === '#') {\n return n.charAt(1) === 'x'\n ? String.fromCharCode(parseInt(n.substring(2), 16))\n : String.fromCharCode(+n.substring(1));\n }\n return '';\n });\n}\nexport function cleanUrl(href) {\n try {\n href = encodeURI(href).replace(other.percentDecode, '%');\n }\n catch {\n return null;\n }\n return href;\n}\nexport function splitCells(tableRow, count) {\n // ensure that every cell-delimiting pipe has a space\n // before it to distinguish it from an escaped pipe\n const row = tableRow.replace(other.findPipe, (match, offset, str) => {\n let escaped = false;\n let curr = offset;\n while (--curr >= 0 && str[curr] === '\\\\')\n escaped = !escaped;\n if (escaped) {\n // odd number of slashes means | is escaped\n // so we leave it alone\n return '|';\n }\n else {\n // add space before unescaped |\n return ' |';\n }\n }), cells = row.split(other.splitPipe);\n let i = 0;\n // First/last cell in a row cannot be empty if it has no leading/trailing pipe\n if (!cells[0].trim()) {\n cells.shift();\n }\n if (cells.length > 0 && !cells.at(-1)?.trim()) {\n cells.pop();\n }\n if (count) {\n if (cells.length > count) {\n cells.splice(count);\n }\n else {\n while (cells.length < count)\n cells.push('');\n }\n }\n for (; i < cells.length; i++) {\n // leading or trailing whitespace is ignored per the gfm spec\n cells[i] = cells[i].trim().replace(other.slashPipe, '|');\n }\n return cells;\n}\n/**\n * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').\n * /c*$/ is vulnerable to REDOS.\n *\n * @param str\n * @param c\n * @param invert Remove suffix of non-c chars instead. Default falsey.\n */\nexport function rtrim(str, c, invert) {\n const l = str.length;\n if (l === 0) {\n return '';\n }\n // Length of suffix matching the invert condition.\n let suffLen = 0;\n // Step left until we fail to match the invert condition.\n while (suffLen < l) {\n const currChar = str.charAt(l - suffLen - 1);\n if (currChar === c && !invert) {\n suffLen++;\n }\n else if (currChar !== c && invert) {\n suffLen++;\n }\n else {\n break;\n }\n }\n return str.slice(0, l - suffLen);\n}\nexport function findClosingBracket(str, b) {\n if (str.indexOf(b[1]) === -1) {\n return -1;\n }\n let level = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '\\\\') {\n i++;\n }\n else if (str[i] === b[0]) {\n level++;\n }\n else if (str[i] === b[1]) {\n level--;\n if (level < 0) {\n return i;\n }\n }\n }\n return -1;\n}\n","import { _defaults } from './defaults.ts';\nimport { rtrim, splitCells, findClosingBracket, } from './helpers.ts';\nfunction outputLink(cap, link, raw, lexer, rules) {\n const href = link.href;\n const title = link.title || null;\n const text = cap[1].replace(rules.other.outputLinkReplace, '$1');\n if (cap[0].charAt(0) !== '!') {\n lexer.state.inLink = true;\n const token = {\n type: 'link',\n raw,\n href,\n title,\n text,\n tokens: lexer.inlineTokens(text),\n };\n lexer.state.inLink = false;\n return token;\n }\n return {\n type: 'image',\n raw,\n href,\n title,\n text,\n };\n}\nfunction indentCodeCompensation(raw, text, rules) {\n const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);\n if (matchIndentToCode === null) {\n return text;\n }\n const indentToCode = matchIndentToCode[1];\n return text\n .split('\\n')\n .map(node => {\n const matchIndentInNode = node.match(rules.other.beginningSpace);\n if (matchIndentInNode === null) {\n return node;\n }\n const [indentInNode] = matchIndentInNode;\n if (indentInNode.length >= indentToCode.length) {\n return node.slice(indentToCode.length);\n }\n return node;\n })\n .join('\\n');\n}\n/**\n * Tokenizer\n */\nexport class _Tokenizer {\n options;\n rules; // set by the lexer\n lexer; // set by the lexer\n constructor(options) {\n this.options = options || _defaults;\n }\n space(src) {\n const cap = this.rules.block.newline.exec(src);\n if (cap && cap[0].length > 0) {\n return {\n type: 'space',\n raw: cap[0],\n };\n }\n }\n code(src) {\n const cap = this.rules.block.code.exec(src);\n if (cap) {\n const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');\n return {\n type: 'code',\n raw: cap[0],\n codeBlockStyle: 'indented',\n text: !this.options.pedantic\n ? rtrim(text, '\\n')\n : text,\n };\n }\n }\n fences(src) {\n const cap = this.rules.block.fences.exec(src);\n if (cap) {\n const raw = cap[0];\n const text = indentCodeCompensation(raw, cap[3] || '', this.rules);\n return {\n type: 'code',\n raw,\n lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],\n text,\n };\n }\n }\n heading(src) {\n const cap = this.rules.block.heading.exec(src);\n if (cap) {\n let text = cap[2].trim();\n // remove trailing #s\n if (this.rules.other.endingHash.test(text)) {\n const trimmed = rtrim(text, '#');\n if (this.options.pedantic) {\n text = trimmed.trim();\n }\n else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {\n // CommonMark requires space before trailing #s\n text = trimmed.trim();\n }\n }\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[1].length,\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n hr(src) {\n const cap = this.rules.block.hr.exec(src);\n if (cap) {\n return {\n type: 'hr',\n raw: rtrim(cap[0], '\\n'),\n };\n }\n }\n blockquote(src) {\n const cap = this.rules.block.blockquote.exec(src);\n if (cap) {\n let lines = rtrim(cap[0], '\\n').split('\\n');\n let raw = '';\n let text = '';\n const tokens = [];\n while (lines.length > 0) {\n let inBlockquote = false;\n const currentLines = [];\n let i;\n for (i = 0; i < lines.length; i++) {\n // get lines up to a continuation\n if (this.rules.other.blockquoteStart.test(lines[i])) {\n currentLines.push(lines[i]);\n inBlockquote = true;\n }\n else if (!inBlockquote) {\n currentLines.push(lines[i]);\n }\n else {\n break;\n }\n }\n lines = lines.slice(i);\n const currentRaw = currentLines.join('\\n');\n const currentText = currentRaw\n // precede setext continuation with 4 spaces so it isn't a setext\n .replace(this.rules.other.blockquoteSetextReplace, '\\n $1')\n .replace(this.rules.other.blockquoteSetextReplace2, '');\n raw = raw ? `${raw}\\n${currentRaw}` : currentRaw;\n text = text ? `${text}\\n${currentText}` : currentText;\n // parse blockquote lines as top level tokens\n // merge paragraphs if this is a continuation\n const top = this.lexer.state.top;\n this.lexer.state.top = true;\n this.lexer.blockTokens(currentText, tokens, true);\n this.lexer.state.top = top;\n // if there is no continuation then we are done\n if (lines.length === 0) {\n break;\n }\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'code') {\n // blockquote continuation cannot be preceded by a code block\n break;\n }\n else if (lastToken?.type === 'blockquote') {\n // include continuation in nested blockquote\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.blockquote(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.text.length) + newToken.text;\n break;\n }\n else if (lastToken?.type === 'list') {\n // include continuation in nested list\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.list(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;\n lines = newText.substring(tokens.at(-1).raw.length).split('\\n');\n continue;\n }\n }\n return {\n type: 'blockquote',\n raw,\n tokens,\n text,\n };\n }\n }\n list(src) {\n let cap = this.rules.block.list.exec(src);\n if (cap) {\n let bull = cap[1].trim();\n const isordered = bull.length > 1;\n const list = {\n type: 'list',\n raw: '',\n ordered: isordered,\n start: isordered ? +bull.slice(0, -1) : '',\n loose: false,\n items: [],\n };\n bull = isordered ? `\\\\d{1,9}\\\\${bull.slice(-1)}` : `\\\\${bull}`;\n if (this.options.pedantic) {\n bull = isordered ? bull : '[*+-]';\n }\n // Get next list item\n const itemRegex = this.rules.other.listItemRegex(bull);\n let endsWithBlankLine = false;\n // Check if current bullet point can start a new List Item\n while (src) {\n let endEarly = false;\n let raw = '';\n let itemContents = '';\n if (!(cap = itemRegex.exec(src))) {\n break;\n }\n if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)\n break;\n }\n raw = cap[0];\n src = src.substring(raw.length);\n let line = cap[2].split('\\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length));\n let nextLine = src.split('\\n', 1)[0];\n let blankLine = !line.trim();\n let indent = 0;\n if (this.options.pedantic) {\n indent = 2;\n itemContents = line.trimStart();\n }\n else if (blankLine) {\n indent = cap[1].length + 1;\n }\n else {\n indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char\n indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent\n itemContents = line.slice(indent);\n indent += cap[1].length;\n }\n if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line\n raw += nextLine + '\\n';\n src = src.substring(nextLine.length + 1);\n endEarly = true;\n }\n if (!endEarly) {\n const nextBulletRegex = this.rules.other.nextBulletRegex(indent);\n const hrRegex = this.rules.other.hrRegex(indent);\n const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);\n const headingBeginRegex = this.rules.other.headingBeginRegex(indent);\n const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);\n // Check if following lines should be included in List Item\n while (src) {\n const rawLine = src.split('\\n', 1)[0];\n let nextLineWithoutTabs;\n nextLine = rawLine;\n // Re-align to follow commonmark nesting rules\n if (this.options.pedantic) {\n nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' ');\n nextLineWithoutTabs = nextLine;\n }\n else {\n nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' ');\n }\n // End list item if found code fences\n if (fencesBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new heading\n if (headingBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of html block\n if (htmlBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new bullet\n if (nextBulletRegex.test(nextLine)) {\n break;\n }\n // Horizontal rule found\n if (hrRegex.test(nextLine)) {\n break;\n }\n if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible\n itemContents += '\\n' + nextLineWithoutTabs.slice(indent);\n }\n else {\n // not enough indentation\n if (blankLine) {\n break;\n }\n // paragraph continuation unless last line was a different block level element\n if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block\n break;\n }\n if (fencesBeginRegex.test(line)) {\n break;\n }\n if (headingBeginRegex.test(line)) {\n break;\n }\n if (hrRegex.test(line)) {\n break;\n }\n itemContents += '\\n' + nextLine;\n }\n if (!blankLine && !nextLine.trim()) { // Check if current line is blank\n blankLine = true;\n }\n raw += rawLine + '\\n';\n src = src.substring(rawLine.length + 1);\n line = nextLineWithoutTabs.slice(indent);\n }\n }\n if (!list.loose) {\n // If the previous item ended with a blank line, the list is loose\n if (endsWithBlankLine) {\n list.loose = true;\n }\n else if (this.rules.other.doubleBlankLine.test(raw)) {\n endsWithBlankLine = true;\n }\n }\n let istask = null;\n let ischecked;\n // Check for task list items\n if (this.options.gfm) {\n istask = this.rules.other.listIsTask.exec(itemContents);\n if (istask) {\n ischecked = istask[0] !== '[ ] ';\n itemContents = itemContents.replace(this.rules.other.listReplaceTask, '');\n }\n }\n list.items.push({\n type: 'list_item',\n raw,\n task: !!istask,\n checked: ischecked,\n loose: false,\n text: itemContents,\n tokens: [],\n });\n list.raw += raw;\n }\n // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic\n const lastItem = list.items.at(-1);\n if (lastItem) {\n lastItem.raw = lastItem.raw.trimEnd();\n lastItem.text = lastItem.text.trimEnd();\n }\n list.raw = list.raw.trimEnd();\n // Item child tokens handled here at end because we needed to have the final item to trim it first\n for (let i = 0; i < list.items.length; i++) {\n this.lexer.state.top = false;\n list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);\n if (!list.loose) {\n // Check if list should be loose\n const spacers = list.items[i].tokens.filter(t => t.type === 'space');\n const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw));\n list.loose = hasMultipleLineBreaks;\n }\n }\n // Set all items to loose if list is loose\n if (list.loose) {\n for (let i = 0; i < list.items.length; i++) {\n list.items[i].loose = true;\n }\n }\n return list;\n }\n }\n html(src) {\n const cap = this.rules.block.html.exec(src);\n if (cap) {\n const token = {\n type: 'html',\n block: true,\n raw: cap[0],\n pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',\n text: cap[0],\n };\n return token;\n }\n }\n def(src) {\n const cap = this.rules.block.def.exec(src);\n if (cap) {\n const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' ');\n const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';\n const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];\n return {\n type: 'def',\n tag,\n raw: cap[0],\n href,\n title,\n };\n }\n }\n table(src) {\n const cap = this.rules.block.table.exec(src);\n if (!cap) {\n return;\n }\n if (!this.rules.other.tableDelimiter.test(cap[2])) {\n // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading\n return;\n }\n const headers = splitCells(cap[1]);\n const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');\n const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\\n') : [];\n const item = {\n type: 'table',\n raw: cap[0],\n header: [],\n align: [],\n rows: [],\n };\n if (headers.length !== aligns.length) {\n // header and align columns must be equal, rows can be different.\n return;\n }\n for (const align of aligns) {\n if (this.rules.other.tableAlignRight.test(align)) {\n item.align.push('right');\n }\n else if (this.rules.other.tableAlignCenter.test(align)) {\n item.align.push('center');\n }\n else if (this.rules.other.tableAlignLeft.test(align)) {\n item.align.push('left');\n }\n else {\n item.align.push(null);\n }\n }\n for (let i = 0; i < headers.length; i++) {\n item.header.push({\n text: headers[i],\n tokens: this.lexer.inline(headers[i]),\n header: true,\n align: item.align[i],\n });\n }\n for (const row of rows) {\n item.rows.push(splitCells(row, item.header.length).map((cell, i) => {\n return {\n text: cell,\n tokens: this.lexer.inline(cell),\n header: false,\n align: item.align[i],\n };\n }));\n }\n return item;\n }\n lheading(src) {\n const cap = this.rules.block.lheading.exec(src);\n if (cap) {\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[2].charAt(0) === '=' ? 1 : 2,\n text: cap[1],\n tokens: this.lexer.inline(cap[1]),\n };\n }\n }\n paragraph(src) {\n const cap = this.rules.block.paragraph.exec(src);\n if (cap) {\n const text = cap[1].charAt(cap[1].length - 1) === '\\n'\n ? cap[1].slice(0, -1)\n : cap[1];\n return {\n type: 'paragraph',\n raw: cap[0],\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n text(src) {\n const cap = this.rules.block.text.exec(src);\n if (cap) {\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n tokens: this.lexer.inline(cap[0]),\n };\n }\n }\n escape(src) {\n const cap = this.rules.inline.escape.exec(src);\n if (cap) {\n return {\n type: 'escape',\n raw: cap[0],\n text: cap[1],\n };\n }\n }\n tag(src) {\n const cap = this.rules.inline.tag.exec(src);\n if (cap) {\n if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {\n this.lexer.state.inLink = true;\n }\n else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {\n this.lexer.state.inLink = false;\n }\n if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = true;\n }\n else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = false;\n }\n return {\n type: 'html',\n raw: cap[0],\n inLink: this.lexer.state.inLink,\n inRawBlock: this.lexer.state.inRawBlock,\n block: false,\n text: cap[0],\n };\n }\n }\n link(src) {\n const cap = this.rules.inline.link.exec(src);\n if (cap) {\n const trimmedUrl = cap[2].trim();\n if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {\n // commonmark requires matching angle brackets\n if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n return;\n }\n // ending angle bracket cannot be escaped\n const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\\\');\n if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {\n return;\n }\n }\n else {\n // find closing parenthesis\n const lastParenIndex = findClosingBracket(cap[2], '()');\n if (lastParenIndex > -1) {\n const start = cap[0].indexOf('!') === 0 ? 5 : 4;\n const linkLen = start + cap[1].length + lastParenIndex;\n cap[2] = cap[2].substring(0, lastParenIndex);\n cap[0] = cap[0].substring(0, linkLen).trim();\n cap[3] = '';\n }\n }\n let href = cap[2];\n let title = '';\n if (this.options.pedantic) {\n // split pedantic href and title\n const link = this.rules.other.pedanticHrefTitle.exec(href);\n if (link) {\n href = link[1];\n title = link[3];\n }\n }\n else {\n title = cap[3] ? cap[3].slice(1, -1) : '';\n }\n href = href.trim();\n if (this.rules.other.startAngleBracket.test(href)) {\n if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n // pedantic allows starting angle bracket without ending angle bracket\n href = href.slice(1);\n }\n else {\n href = href.slice(1, -1);\n }\n }\n return outputLink(cap, {\n href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,\n title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title,\n }, cap[0], this.lexer, this.rules);\n }\n }\n reflink(src, links) {\n let cap;\n if ((cap = this.rules.inline.reflink.exec(src))\n || (cap = this.rules.inline.nolink.exec(src))) {\n const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' ');\n const link = links[linkString.toLowerCase()];\n if (!link) {\n const text = cap[0].charAt(0);\n return {\n type: 'text',\n raw: text,\n text,\n };\n }\n return outputLink(cap, link, cap[0], this.lexer, this.rules);\n }\n }\n emStrong(src, maskedSrc, prevChar = '') {\n let match = this.rules.inline.emStrongLDelim.exec(src);\n if (!match)\n return;\n // _ can't be between two alphanumerics. \\p{L}\\p{N} includes non-english alphabet/numbers as well\n if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric))\n return;\n const nextChar = match[1] || match[2] || '';\n if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {\n // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)\n const lLength = [...match[0]].length - 1;\n let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;\n const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;\n endReg.lastIndex = 0;\n // Clip maskedSrc to same section of string as src (move to lexer?)\n maskedSrc = maskedSrc.slice(-1 * src.length + lLength);\n while ((match = endReg.exec(maskedSrc)) != null) {\n rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];\n if (!rDelim)\n continue; // skip single * in __abc*abc__\n rLength = [...rDelim].length;\n if (match[3] || match[4]) { // found another Left Delim\n delimTotal += rLength;\n continue;\n }\n else if (match[5] || match[6]) { // either Left or Right Delim\n if (lLength % 3 && !((lLength + rLength) % 3)) {\n midDelimTotal += rLength;\n continue; // CommonMark Emphasis Rules 9-10\n }\n }\n delimTotal -= rLength;\n if (delimTotal > 0)\n continue; // Haven't found enough closing delimiters\n // Remove extra characters. *a*** -> *a*\n rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);\n // char length can be >1 for unicode characters;\n const lastCharLength = [...match[0]][0].length;\n const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);\n // Create `em` if smallest delimiter has odd char count. *a***\n if (Math.min(lLength, rLength) % 2) {\n const text = raw.slice(1, -1);\n return {\n type: 'em',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n // Create 'strong' if smallest delimiter has even char count. **a***\n const text = raw.slice(2, -2);\n return {\n type: 'strong',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n }\n }\n codespan(src) {\n const cap = this.rules.inline.code.exec(src);\n if (cap) {\n let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' ');\n const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);\n const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);\n if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {\n text = text.substring(1, text.length - 1);\n }\n return {\n type: 'codespan',\n raw: cap[0],\n text,\n };\n }\n }\n br(src) {\n const cap = this.rules.inline.br.exec(src);\n if (cap) {\n return {\n type: 'br',\n raw: cap[0],\n };\n }\n }\n del(src) {\n const cap = this.rules.inline.del.exec(src);\n if (cap) {\n return {\n type: 'del',\n raw: cap[0],\n text: cap[2],\n tokens: this.lexer.inlineTokens(cap[2]),\n };\n }\n }\n autolink(src) {\n const cap = this.rules.inline.autolink.exec(src);\n if (cap) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[1];\n href = 'mailto:' + text;\n }\n else {\n text = cap[1];\n href = text;\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n url(src) {\n let cap;\n if (cap = this.rules.inline.url.exec(src)) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[0];\n href = 'mailto:' + text;\n }\n else {\n // do extended autolink path validation\n let prevCapZero;\n do {\n prevCapZero = cap[0];\n cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';\n } while (prevCapZero !== cap[0]);\n text = cap[0];\n if (cap[1] === 'www.') {\n href = 'http://' + cap[0];\n }\n else {\n href = cap[0];\n }\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n inlineText(src) {\n const cap = this.rules.inline.text.exec(src);\n if (cap) {\n const escaped = this.lexer.state.inRawBlock;\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n escaped,\n };\n }\n }\n}\n","import { _Tokenizer } from './Tokenizer.ts';\nimport { _defaults } from './defaults.ts';\nimport { other, block, inline } from './rules.ts';\n/**\n * Block Lexer\n */\nexport class _Lexer {\n tokens;\n options;\n state;\n tokenizer;\n inlineQueue;\n constructor(options) {\n // TokenList cannot be created in one go\n this.tokens = [];\n this.tokens.links = Object.create(null);\n this.options = options || _defaults;\n this.options.tokenizer = this.options.tokenizer || new _Tokenizer();\n this.tokenizer = this.options.tokenizer;\n this.tokenizer.options = this.options;\n this.tokenizer.lexer = this;\n this.inlineQueue = [];\n this.state = {\n inLink: false,\n inRawBlock: false,\n top: true,\n };\n const rules = {\n other,\n block: block.normal,\n inline: inline.normal,\n };\n if (this.options.pedantic) {\n rules.block = block.pedantic;\n rules.inline = inline.pedantic;\n }\n else if (this.options.gfm) {\n rules.block = block.gfm;\n if (this.options.breaks) {\n rules.inline = inline.breaks;\n }\n else {\n rules.inline = inline.gfm;\n }\n }\n this.tokenizer.rules = rules;\n }\n /**\n * Expose Rules\n */\n static get rules() {\n return {\n block,\n inline,\n };\n }\n /**\n * Static Lex Method\n */\n static lex(src, options) {\n const lexer = new _Lexer(options);\n return lexer.lex(src);\n }\n /**\n * Static Lex Inline Method\n */\n static lexInline(src, options) {\n const lexer = new _Lexer(options);\n return lexer.inlineTokens(src);\n }\n /**\n * Preprocessing\n */\n lex(src) {\n src = src.replace(other.carriageReturn, '\\n');\n this.blockTokens(src, this.tokens);\n for (let i = 0; i < this.inlineQueue.length; i++) {\n const next = this.inlineQueue[i];\n this.inlineTokens(next.src, next.tokens);\n }\n this.inlineQueue = [];\n return this.tokens;\n }\n blockTokens(src, tokens = [], lastParagraphClipped = false) {\n if (this.options.pedantic) {\n src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');\n }\n while (src) {\n let token;\n if (this.options.extensions?.block?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // newline\n if (token = this.tokenizer.space(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.raw.length === 1 && lastToken !== undefined) {\n // if there's a single \\n as a spacer, it's terminating the last line,\n // so move it there so that we don't get unnecessary paragraph tags\n lastToken.raw += '\\n';\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // code\n if (token = this.tokenizer.code(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n // An indented code block cannot interrupt a paragraph.\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // fences\n if (token = this.tokenizer.fences(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // heading\n if (token = this.tokenizer.heading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // hr\n if (token = this.tokenizer.hr(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // blockquote\n if (token = this.tokenizer.blockquote(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // list\n if (token = this.tokenizer.list(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // html\n if (token = this.tokenizer.html(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // def\n if (token = this.tokenizer.def(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.raw;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else if (!this.tokens.links[token.tag]) {\n this.tokens.links[token.tag] = {\n href: token.href,\n title: token.title,\n };\n }\n continue;\n }\n // table (gfm)\n if (token = this.tokenizer.table(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // lheading\n if (token = this.tokenizer.lheading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // top-level paragraph\n // prevent paragraph consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startBlock) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startBlock.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {\n const lastToken = tokens.at(-1);\n if (lastParagraphClipped && lastToken?.type === 'paragraph') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n lastParagraphClipped = cutSrc.length !== src.length;\n src = src.substring(token.raw.length);\n continue;\n }\n // text\n if (token = this.tokenizer.text(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n this.state.top = true;\n return tokens;\n }\n inline(src, tokens = []) {\n this.inlineQueue.push({ src, tokens });\n return tokens;\n }\n /**\n * Lexing/Compiling\n */\n inlineTokens(src, tokens = []) {\n // String with links masked to avoid interference with em and strong\n let maskedSrc = src;\n let match = null;\n // Mask out reflinks\n if (this.tokens.links) {\n const links = Object.keys(this.tokens.links);\n if (links.length > 0) {\n while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {\n if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {\n maskedSrc = maskedSrc.slice(0, match.index)\n + '[' + 'a'.repeat(match[0].length - 2) + ']'\n + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);\n }\n }\n }\n }\n // Mask out other blocks\n while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);\n }\n // Mask out escaped characters\n while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);\n }\n let keepPrevChar = false;\n let prevChar = '';\n while (src) {\n if (!keepPrevChar) {\n prevChar = '';\n }\n keepPrevChar = false;\n let token;\n // extensions\n if (this.options.extensions?.inline?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // escape\n if (token = this.tokenizer.escape(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // tag\n if (token = this.tokenizer.tag(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // link\n if (token = this.tokenizer.link(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // reflink, nolink\n if (token = this.tokenizer.reflink(src, this.tokens.links)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.type === 'text' && lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // em & strong\n if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // code\n if (token = this.tokenizer.codespan(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // br\n if (token = this.tokenizer.br(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // del (gfm)\n if (token = this.tokenizer.del(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // autolink\n if (token = this.tokenizer.autolink(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // url (gfm)\n if (!this.state.inLink && (token = this.tokenizer.url(src))) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // text\n // prevent inlineText consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startInline) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startInline.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (token = this.tokenizer.inlineText(cutSrc)) {\n src = src.substring(token.raw.length);\n if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started\n prevChar = token.raw.slice(-1);\n }\n keepPrevChar = true;\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n return tokens;\n }\n}\n","import { _defaults } from './defaults.ts';\nimport { cleanUrl, escape, } from './helpers.ts';\nimport { other } from './rules.ts';\n/**\n * Renderer\n */\nexport class _Renderer {\n options;\n parser; // set by the parser\n constructor(options) {\n this.options = options || _defaults;\n }\n space(token) {\n return '';\n }\n code({ text, lang, escaped }) {\n const langString = (lang || '').match(other.notSpaceStart)?.[0];\n const code = text.replace(other.endingNewline, '') + '\\n';\n if (!langString) {\n return '
    '\n                + (escaped ? code : escape(code, true))\n                + '
    \\n';\n }\n return '
    '\n            + (escaped ? code : escape(code, true))\n            + '
    \\n';\n }\n blockquote({ tokens }) {\n const body = this.parser.parse(tokens);\n return `
    \\n${body}
    \\n`;\n }\n html({ text }) {\n return text;\n }\n heading({ tokens, depth }) {\n return `${this.parser.parseInline(tokens)}\\n`;\n }\n hr(token) {\n return '
    \\n';\n }\n list(token) {\n const ordered = token.ordered;\n const start = token.start;\n let body = '';\n for (let j = 0; j < token.items.length; j++) {\n const item = token.items[j];\n body += this.listitem(item);\n }\n const type = ordered ? 'ol' : 'ul';\n const startAttr = (ordered && start !== 1) ? (' start=\"' + start + '\"') : '';\n return '<' + type + startAttr + '>\\n' + body + '\\n';\n }\n listitem(item) {\n let itemBody = '';\n if (item.task) {\n const checkbox = this.checkbox({ checked: !!item.checked });\n if (item.loose) {\n if (item.tokens[0]?.type === 'paragraph') {\n item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;\n if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {\n item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);\n item.tokens[0].tokens[0].escaped = true;\n }\n }\n else {\n item.tokens.unshift({\n type: 'text',\n raw: checkbox + ' ',\n text: checkbox + ' ',\n escaped: true,\n });\n }\n }\n else {\n itemBody += checkbox + ' ';\n }\n }\n itemBody += this.parser.parse(item.tokens, !!item.loose);\n return `
  • ${itemBody}
  • \\n`;\n }\n checkbox({ checked }) {\n return '';\n }\n paragraph({ tokens }) {\n return `

    ${this.parser.parseInline(tokens)}

    \\n`;\n }\n table(token) {\n let header = '';\n // header\n let cell = '';\n for (let j = 0; j < token.header.length; j++) {\n cell += this.tablecell(token.header[j]);\n }\n header += this.tablerow({ text: cell });\n let body = '';\n for (let j = 0; j < token.rows.length; j++) {\n const row = token.rows[j];\n cell = '';\n for (let k = 0; k < row.length; k++) {\n cell += this.tablecell(row[k]);\n }\n body += this.tablerow({ text: cell });\n }\n if (body)\n body = `${body}`;\n return '\\n'\n + '\\n'\n + header\n + '\\n'\n + body\n + '
    \\n';\n }\n tablerow({ text }) {\n return `\\n${text}\\n`;\n }\n tablecell(token) {\n const content = this.parser.parseInline(token.tokens);\n const type = token.header ? 'th' : 'td';\n const tag = token.align\n ? `<${type} align=\"${token.align}\">`\n : `<${type}>`;\n return tag + content + `\\n`;\n }\n /**\n * span level renderer\n */\n strong({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n em({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n codespan({ text }) {\n return `${escape(text, true)}`;\n }\n br(token) {\n return '
    ';\n }\n del({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n link({ href, title, tokens }) {\n const text = this.parser.parseInline(tokens);\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return text;\n }\n href = cleanHref;\n let out = '
    ';\n return out;\n }\n image({ href, title, text }) {\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return escape(text);\n }\n href = cleanHref;\n let out = `\"${text}\"`;\n {\n const tokens = genericToken[childTokens].flat(Infinity);\n values = values.concat(this.walkTokens(tokens, callback));\n });\n }\n else if (genericToken.tokens) {\n values = values.concat(this.walkTokens(genericToken.tokens, callback));\n }\n }\n }\n }\n return values;\n }\n use(...args) {\n const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };\n args.forEach((pack) => {\n // copy options to new object\n const opts = { ...pack };\n // set async to true if it was set to true before\n opts.async = this.defaults.async || opts.async || false;\n // ==-- Parse \"addon\" extensions --== //\n if (pack.extensions) {\n pack.extensions.forEach((ext) => {\n if (!ext.name) {\n throw new Error('extension name required');\n }\n if ('renderer' in ext) { // Renderer extensions\n const prevRenderer = extensions.renderers[ext.name];\n if (prevRenderer) {\n // Replace extension with func to run new extension but fall back if false\n extensions.renderers[ext.name] = function (...args) {\n let ret = ext.renderer.apply(this, args);\n if (ret === false) {\n ret = prevRenderer.apply(this, args);\n }\n return ret;\n };\n }\n else {\n extensions.renderers[ext.name] = ext.renderer;\n }\n }\n if ('tokenizer' in ext) { // Tokenizer Extensions\n if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {\n throw new Error(\"extension level must be 'block' or 'inline'\");\n }\n const extLevel = extensions[ext.level];\n if (extLevel) {\n extLevel.unshift(ext.tokenizer);\n }\n else {\n extensions[ext.level] = [ext.tokenizer];\n }\n if (ext.start) { // Function to check for start of token\n if (ext.level === 'block') {\n if (extensions.startBlock) {\n extensions.startBlock.push(ext.start);\n }\n else {\n extensions.startBlock = [ext.start];\n }\n }\n else if (ext.level === 'inline') {\n if (extensions.startInline) {\n extensions.startInline.push(ext.start);\n }\n else {\n extensions.startInline = [ext.start];\n }\n }\n }\n }\n if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens\n extensions.childTokens[ext.name] = ext.childTokens;\n }\n });\n opts.extensions = extensions;\n }\n // ==-- Parse \"overwrite\" extensions --== //\n if (pack.renderer) {\n const renderer = this.defaults.renderer || new _Renderer(this.defaults);\n for (const prop in pack.renderer) {\n if (!(prop in renderer)) {\n throw new Error(`renderer '${prop}' does not exist`);\n }\n if (['options', 'parser'].includes(prop)) {\n // ignore options property\n continue;\n }\n const rendererProp = prop;\n const rendererFunc = pack.renderer[rendererProp];\n const prevRenderer = renderer[rendererProp];\n // Replace renderer with func to run extension, but fall back if false\n renderer[rendererProp] = (...args) => {\n let ret = rendererFunc.apply(renderer, args);\n if (ret === false) {\n ret = prevRenderer.apply(renderer, args);\n }\n return ret || '';\n };\n }\n opts.renderer = renderer;\n }\n if (pack.tokenizer) {\n const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);\n for (const prop in pack.tokenizer) {\n if (!(prop in tokenizer)) {\n throw new Error(`tokenizer '${prop}' does not exist`);\n }\n if (['options', 'rules', 'lexer'].includes(prop)) {\n // ignore options, rules, and lexer properties\n continue;\n }\n const tokenizerProp = prop;\n const tokenizerFunc = pack.tokenizer[tokenizerProp];\n const prevTokenizer = tokenizer[tokenizerProp];\n // Replace tokenizer with func to run extension, but fall back if false\n // @ts-expect-error cannot type tokenizer function dynamically\n tokenizer[tokenizerProp] = (...args) => {\n let ret = tokenizerFunc.apply(tokenizer, args);\n if (ret === false) {\n ret = prevTokenizer.apply(tokenizer, args);\n }\n return ret;\n };\n }\n opts.tokenizer = tokenizer;\n }\n // ==-- Parse Hooks extensions --== //\n if (pack.hooks) {\n const hooks = this.defaults.hooks || new _Hooks();\n for (const prop in pack.hooks) {\n if (!(prop in hooks)) {\n throw new Error(`hook '${prop}' does not exist`);\n }\n if (['options', 'block'].includes(prop)) {\n // ignore options and block properties\n continue;\n }\n const hooksProp = prop;\n const hooksFunc = pack.hooks[hooksProp];\n const prevHook = hooks[hooksProp];\n if (_Hooks.passThroughHooks.has(prop)) {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (arg) => {\n if (this.defaults.async) {\n return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {\n return prevHook.call(hooks, ret);\n });\n }\n const ret = hooksFunc.call(hooks, arg);\n return prevHook.call(hooks, ret);\n };\n }\n else {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (...args) => {\n let ret = hooksFunc.apply(hooks, args);\n if (ret === false) {\n ret = prevHook.apply(hooks, args);\n }\n return ret;\n };\n }\n }\n opts.hooks = hooks;\n }\n // ==-- Parse WalkTokens extensions --== //\n if (pack.walkTokens) {\n const walkTokens = this.defaults.walkTokens;\n const packWalktokens = pack.walkTokens;\n opts.walkTokens = function (token) {\n let values = [];\n values.push(packWalktokens.call(this, token));\n if (walkTokens) {\n values = values.concat(walkTokens.call(this, token));\n }\n return values;\n };\n }\n this.defaults = { ...this.defaults, ...opts };\n });\n return this;\n }\n setOptions(opt) {\n this.defaults = { ...this.defaults, ...opt };\n return this;\n }\n lexer(src, options) {\n return _Lexer.lex(src, options ?? this.defaults);\n }\n parser(tokens, options) {\n return _Parser.parse(tokens, options ?? this.defaults);\n }\n parseMarkdown(blockType) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const parse = (src, options) => {\n const origOpt = { ...options };\n const opt = { ...this.defaults, ...origOpt };\n const throwError = this.onError(!!opt.silent, !!opt.async);\n // throw error if an extension set async to true but parse was called with async: false\n if (this.defaults.async === true && origOpt.async === false) {\n return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.'));\n }\n // throw error in case of non string input\n if (typeof src === 'undefined' || src === null) {\n return throwError(new Error('marked(): input parameter is undefined or null'));\n }\n if (typeof src !== 'string') {\n return throwError(new Error('marked(): input parameter is of type '\n + Object.prototype.toString.call(src) + ', string expected'));\n }\n if (opt.hooks) {\n opt.hooks.options = opt;\n opt.hooks.block = blockType;\n }\n const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline);\n const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline);\n if (opt.async) {\n return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)\n .then(src => lexer(src, opt))\n .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens)\n .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)\n .then(tokens => parser(tokens, opt))\n .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)\n .catch(throwError);\n }\n try {\n if (opt.hooks) {\n src = opt.hooks.preprocess(src);\n }\n let tokens = lexer(src, opt);\n if (opt.hooks) {\n tokens = opt.hooks.processAllTokens(tokens);\n }\n if (opt.walkTokens) {\n this.walkTokens(tokens, opt.walkTokens);\n }\n let html = parser(tokens, opt);\n if (opt.hooks) {\n html = opt.hooks.postprocess(html);\n }\n return html;\n }\n catch (e) {\n return throwError(e);\n }\n };\n return parse;\n }\n onError(silent, async) {\n return (e) => {\n e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n if (silent) {\n const msg = '

    An error occurred:

    '\n                    + escape(e.message + '', true)\n                    + '
    ';\n if (async) {\n return Promise.resolve(msg);\n }\n return msg;\n }\n if (async) {\n return Promise.reject(e);\n }\n throw e;\n };\n }\n}\n","import { _Lexer } from './Lexer.ts';\nimport { _Parser } from './Parser.ts';\nimport { _Tokenizer } from './Tokenizer.ts';\nimport { _Renderer } from './Renderer.ts';\nimport { _TextRenderer } from './TextRenderer.ts';\nimport { _Hooks } from './Hooks.ts';\nimport { Marked } from './Instance.ts';\nimport { _getDefaults, changeDefaults, _defaults, } from './defaults.ts';\nconst markedInstance = new Marked();\nexport function marked(src, opt) {\n return markedInstance.parse(src, opt);\n}\n/**\n * Sets the default options.\n *\n * @param options Hash of options\n */\nmarked.options =\n marked.setOptions = function (options) {\n markedInstance.setOptions(options);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n };\n/**\n * Gets the original marked default options.\n */\nmarked.getDefaults = _getDefaults;\nmarked.defaults = _defaults;\n/**\n * Use Extension\n */\nmarked.use = function (...args) {\n markedInstance.use(...args);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n};\n/**\n * Run callback for every token\n */\nmarked.walkTokens = function (tokens, callback) {\n return markedInstance.walkTokens(tokens, callback);\n};\n/**\n * Compiles markdown to HTML without enclosing `p` tag.\n *\n * @param src String of markdown source to be compiled\n * @param options Hash of options\n * @return String of compiled HTML\n */\nmarked.parseInline = markedInstance.parseInline;\n/**\n * Expose\n */\nmarked.Parser = _Parser;\nmarked.parser = _Parser.parse;\nmarked.Renderer = _Renderer;\nmarked.TextRenderer = _TextRenderer;\nmarked.Lexer = _Lexer;\nmarked.lexer = _Lexer.lex;\nmarked.Tokenizer = _Tokenizer;\nmarked.Hooks = _Hooks;\nmarked.parse = marked;\nexport const options = marked.options;\nexport const setOptions = marked.setOptions;\nexport const use = marked.use;\nexport const walkTokens = marked.walkTokens;\nexport const parseInline = marked.parseInline;\nexport const parse = marked;\nexport const parser = _Parser.parse;\nexport const lexer = _Lexer.lex;\nexport { _defaults as defaults, _getDefaults as getDefaults } from './defaults.ts';\nexport { _Lexer as Lexer } from './Lexer.ts';\nexport { _Parser as Parser } from './Parser.ts';\nexport { _Tokenizer as Tokenizer } from './Tokenizer.ts';\nexport { _Renderer as Renderer } from './Renderer.ts';\nexport { _TextRenderer as TextRenderer } from './TextRenderer.ts';\nexport { _Hooks as Hooks } from './Hooks.ts';\nexport { Marked } from './Instance.ts';\n"],"names":["_defaults","escape"],"mappings":"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"} \ No newline at end of file diff --git a/docs/node_modules/marked/lib/marked.d.cts b/docs/node_modules/marked/lib/marked.d.cts new file mode 100644 index 00000000..026652b0 --- /dev/null +++ b/docs/node_modules/marked/lib/marked.d.cts @@ -0,0 +1,727 @@ +// Generated by dts-bundle-generator v9.5.1 + +export type MarkedToken = (Tokens.Blockquote | Tokens.Br | Tokens.Code | Tokens.Codespan | Tokens.Def | Tokens.Del | Tokens.Em | Tokens.Escape | Tokens.Heading | Tokens.Hr | Tokens.HTML | Tokens.Image | Tokens.Link | Tokens.List | Tokens.ListItem | Tokens.Paragraph | Tokens.Space | Tokens.Strong | Tokens.Table | Tokens.Tag | Tokens.Text); +export type Token = (MarkedToken | Tokens.Generic); +export declare namespace Tokens { + interface Blockquote { + type: "blockquote"; + raw: string; + text: string; + tokens: Token[]; + } + interface Br { + type: "br"; + raw: string; + } + interface Checkbox { + checked: boolean; + } + interface Code { + type: "code"; + raw: string; + codeBlockStyle?: "indented"; + lang?: string; + text: string; + escaped?: boolean; + } + interface Codespan { + type: "codespan"; + raw: string; + text: string; + } + interface Def { + type: "def"; + raw: string; + tag: string; + href: string; + title: string; + } + interface Del { + type: "del"; + raw: string; + text: string; + tokens: Token[]; + } + interface Em { + type: "em"; + raw: string; + text: string; + tokens: Token[]; + } + interface Escape { + type: "escape"; + raw: string; + text: string; + } + interface Generic { + [index: string]: any; + type: string; + raw: string; + tokens?: Token[]; + } + interface Heading { + type: "heading"; + raw: string; + depth: number; + text: string; + tokens: Token[]; + } + interface Hr { + type: "hr"; + raw: string; + } + interface HTML { + type: "html"; + raw: string; + pre: boolean; + text: string; + block: boolean; + } + interface Image { + type: "image"; + raw: string; + href: string; + title: string | null; + text: string; + } + interface Link { + type: "link"; + raw: string; + href: string; + title?: string | null; + text: string; + tokens: Token[]; + } + interface List { + type: "list"; + raw: string; + ordered: boolean; + start: number | ""; + loose: boolean; + items: ListItem[]; + } + interface ListItem { + type: "list_item"; + raw: string; + task: boolean; + checked?: boolean; + loose: boolean; + text: string; + tokens: Token[]; + } + interface Paragraph { + type: "paragraph"; + raw: string; + pre?: boolean; + text: string; + tokens: Token[]; + } + interface Space { + type: "space"; + raw: string; + } + interface Strong { + type: "strong"; + raw: string; + text: string; + tokens: Token[]; + } + interface Table { + type: "table"; + raw: string; + align: Array<"center" | "left" | "right" | null>; + header: TableCell[]; + rows: TableCell[][]; + } + interface TableCell { + text: string; + tokens: Token[]; + header: boolean; + align: "center" | "left" | "right" | null; + } + interface TableRow { + text: string; + } + interface Tag { + type: "html"; + raw: string; + inLink: boolean; + inRawBlock: boolean; + text: string; + block: boolean; + } + interface Text { + type: "text"; + raw: string; + text: string; + tokens?: Token[]; + escaped?: boolean; + } +} +export type Links = Record>; +export type TokensList = Token[] & { + links: Links; +}; +/** + * Renderer + */ +declare class _Renderer { + options: MarkedOptions; + parser: _Parser; + constructor(options?: MarkedOptions); + space(token: Tokens.Space): string; + code({ text, lang, escaped }: Tokens.Code): string; + blockquote({ tokens }: Tokens.Blockquote): string; + html({ text }: Tokens.HTML | Tokens.Tag): string; + heading({ tokens, depth }: Tokens.Heading): string; + hr(token: Tokens.Hr): string; + list(token: Tokens.List): string; + listitem(item: Tokens.ListItem): string; + checkbox({ checked }: Tokens.Checkbox): string; + paragraph({ tokens }: Tokens.Paragraph): string; + table(token: Tokens.Table): string; + tablerow({ text }: Tokens.TableRow): string; + tablecell(token: Tokens.TableCell): string; + /** + * span level renderer + */ + strong({ tokens }: Tokens.Strong): string; + em({ tokens }: Tokens.Em): string; + codespan({ text }: Tokens.Codespan): string; + br(token: Tokens.Br): string; + del({ tokens }: Tokens.Del): string; + link({ href, title, tokens }: Tokens.Link): string; + image({ href, title, text }: Tokens.Image): string; + text(token: Tokens.Text | Tokens.Escape): string; +} +/** + * TextRenderer + * returns only the textual part of the token + */ +declare class _TextRenderer { + strong({ text }: Tokens.Strong): string; + em({ text }: Tokens.Em): string; + codespan({ text }: Tokens.Codespan): string; + del({ text }: Tokens.Del): string; + html({ text }: Tokens.HTML | Tokens.Tag): string; + text({ text }: Tokens.Text | Tokens.Escape | Tokens.Tag): string; + link({ text }: Tokens.Link): string; + image({ text }: Tokens.Image): string; + br(): string; +} +/** + * Parsing & Compiling + */ +declare class _Parser { + options: MarkedOptions; + renderer: _Renderer; + textRenderer: _TextRenderer; + constructor(options?: MarkedOptions); + /** + * Static Parse Method + */ + static parse(tokens: Token[], options?: MarkedOptions): string; + /** + * Static Parse Inline Method + */ + static parseInline(tokens: Token[], options?: MarkedOptions): string; + /** + * Parse Loop + */ + parse(tokens: Token[], top?: boolean): string; + /** + * Parse Inline Tokens + */ + parseInline(tokens: Token[], renderer?: _Renderer | _TextRenderer): string; +} +declare const other: { + codeRemoveIndent: RegExp; + outputLinkReplace: RegExp; + indentCodeCompensation: RegExp; + beginningSpace: RegExp; + endingHash: RegExp; + startingSpaceChar: RegExp; + endingSpaceChar: RegExp; + nonSpaceChar: RegExp; + newLineCharGlobal: RegExp; + tabCharGlobal: RegExp; + multipleSpaceGlobal: RegExp; + blankLine: RegExp; + doubleBlankLine: RegExp; + blockquoteStart: RegExp; + blockquoteSetextReplace: RegExp; + blockquoteSetextReplace2: RegExp; + listReplaceTabs: RegExp; + listReplaceNesting: RegExp; + listIsTask: RegExp; + listReplaceTask: RegExp; + anyLine: RegExp; + hrefBrackets: RegExp; + tableDelimiter: RegExp; + tableAlignChars: RegExp; + tableRowBlankLine: RegExp; + tableAlignRight: RegExp; + tableAlignCenter: RegExp; + tableAlignLeft: RegExp; + startATag: RegExp; + endATag: RegExp; + startPreScriptTag: RegExp; + endPreScriptTag: RegExp; + startAngleBracket: RegExp; + endAngleBracket: RegExp; + pedanticHrefTitle: RegExp; + unicodeAlphaNumeric: RegExp; + escapeTest: RegExp; + escapeReplace: RegExp; + escapeTestNoEncode: RegExp; + escapeReplaceNoEncode: RegExp; + unescapeTest: RegExp; + caret: RegExp; + percentDecode: RegExp; + findPipe: RegExp; + splitPipe: RegExp; + slashPipe: RegExp; + carriageReturn: RegExp; + spaceLine: RegExp; + notSpaceStart: RegExp; + endingNewline: RegExp; + listItemRegex: (bull: string) => RegExp; + nextBulletRegex: (indent: number) => RegExp; + hrRegex: (indent: number) => RegExp; + fencesBeginRegex: (indent: number) => RegExp; + headingBeginRegex: (indent: number) => RegExp; + htmlBeginRegex: (indent: number) => RegExp; +}; +declare const blockNormal: { + blockquote: RegExp; + code: RegExp; + def: RegExp; + fences: RegExp; + heading: RegExp; + hr: RegExp; + html: RegExp; + lheading: RegExp; + list: RegExp; + newline: RegExp; + paragraph: RegExp; + table: RegExp; + text: RegExp; +}; +export type BlockKeys = keyof typeof blockNormal; +declare const inlineNormal: { + _backpedal: RegExp; + anyPunctuation: RegExp; + autolink: RegExp; + blockSkip: RegExp; + br: RegExp; + code: RegExp; + del: RegExp; + emStrongLDelim: RegExp; + emStrongRDelimAst: RegExp; + emStrongRDelimUnd: RegExp; + escape: RegExp; + link: RegExp; + nolink: RegExp; + punctuation: RegExp; + reflink: RegExp; + reflinkSearch: RegExp; + tag: RegExp; + text: RegExp; + url: RegExp; +}; +export type InlineKeys = keyof typeof inlineNormal; +export interface Rules { + other: typeof other; + block: Record; + inline: Record; +} +/** + * Tokenizer + */ +declare class _Tokenizer { + options: MarkedOptions; + rules: Rules; + lexer: _Lexer; + constructor(options?: MarkedOptions); + space(src: string): Tokens.Space | undefined; + code(src: string): Tokens.Code | undefined; + fences(src: string): Tokens.Code | undefined; + heading(src: string): Tokens.Heading | undefined; + hr(src: string): Tokens.Hr | undefined; + blockquote(src: string): Tokens.Blockquote | undefined; + list(src: string): Tokens.List | undefined; + html(src: string): Tokens.HTML | undefined; + def(src: string): Tokens.Def | undefined; + table(src: string): Tokens.Table | undefined; + lheading(src: string): Tokens.Heading | undefined; + paragraph(src: string): Tokens.Paragraph | undefined; + text(src: string): Tokens.Text | undefined; + escape(src: string): Tokens.Escape | undefined; + tag(src: string): Tokens.Tag | undefined; + link(src: string): Tokens.Link | Tokens.Image | undefined; + reflink(src: string, links: Links): Tokens.Link | Tokens.Image | Tokens.Text | undefined; + emStrong(src: string, maskedSrc: string, prevChar?: string): Tokens.Em | Tokens.Strong | undefined; + codespan(src: string): Tokens.Codespan | undefined; + br(src: string): Tokens.Br | undefined; + del(src: string): Tokens.Del | undefined; + autolink(src: string): Tokens.Link | undefined; + url(src: string): Tokens.Link | undefined; + inlineText(src: string): Tokens.Text | undefined; +} +declare class _Hooks { + options: MarkedOptions; + block?: boolean; + constructor(options?: MarkedOptions); + static passThroughHooks: Set; + /** + * Process markdown before marked + */ + preprocess(markdown: string): string; + /** + * Process HTML after marked is finished + */ + postprocess(html: string): string; + /** + * Process all tokens before walk tokens + */ + processAllTokens(tokens: Token[] | TokensList): Token[] | TokensList; + /** + * Provide function to tokenize markdown + */ + provideLexer(): typeof _Lexer.lexInline; + /** + * Provide function to parse tokens + */ + provideParser(): typeof _Parser.parse; +} +export interface TokenizerThis { + lexer: _Lexer; +} +export type TokenizerExtensionFunction = (this: TokenizerThis, src: string, tokens: Token[] | TokensList) => Tokens.Generic | undefined; +export type TokenizerStartFunction = (this: TokenizerThis, src: string) => number | void; +export interface TokenizerExtension { + name: string; + level: "block" | "inline"; + start?: TokenizerStartFunction; + tokenizer: TokenizerExtensionFunction; + childTokens?: string[]; +} +export interface RendererThis { + parser: _Parser; +} +export type RendererExtensionFunction = (this: RendererThis, token: Tokens.Generic) => string | false | undefined; +export interface RendererExtension { + name: string; + renderer: RendererExtensionFunction; +} +export type TokenizerAndRendererExtension = TokenizerExtension | RendererExtension | (TokenizerExtension & RendererExtension); +export type HooksApi = Omit<_Hooks, "constructor" | "options" | "block">; +export type HooksObject = { + [K in keyof HooksApi]?: (this: _Hooks, ...args: Parameters) => ReturnType | Promise>; +}; +export type RendererApi = Omit<_Renderer, "constructor" | "options" | "parser">; +export type RendererObject = { + [K in keyof RendererApi]?: (this: _Renderer, ...args: Parameters) => ReturnType | false; +}; +export type TokenizerApi = Omit<_Tokenizer, "constructor" | "options" | "rules" | "lexer">; +export type TokenizerObject = { + [K in keyof TokenizerApi]?: (this: _Tokenizer, ...args: Parameters) => ReturnType | false; +}; +export interface MarkedExtension { + /** + * True will tell marked to await any walkTokens functions before parsing the tokens and returning an HTML string. + */ + async?: boolean; + /** + * Enable GFM line breaks. This option requires the gfm option to be true. + */ + breaks?: boolean; + /** + * Add tokenizers and renderers to marked + */ + extensions?: TokenizerAndRendererExtension[] | null; + /** + * Enable GitHub flavored markdown. + */ + gfm?: boolean; + /** + * Hooks are methods that hook into some part of marked. + * preprocess is called to process markdown before sending it to marked. + * processAllTokens is called with the TokensList before walkTokens. + * postprocess is called to process html after marked has finished parsing. + * provideLexer is called to provide a function to tokenize markdown. + * provideParser is called to provide a function to parse tokens. + */ + hooks?: HooksObject | null; + /** + * Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior. + */ + pedantic?: boolean; + /** + * Type: object Default: new Renderer() + * + * An object containing functions to render tokens to HTML. + */ + renderer?: RendererObject | null; + /** + * Shows an HTML error message when rendering fails. + */ + silent?: boolean; + /** + * The tokenizer defines how to turn markdown text into tokens. + */ + tokenizer?: TokenizerObject | null; + /** + * The walkTokens function gets called with every token. + * Child tokens are called before moving on to sibling tokens. + * Each token is passed by reference so updates are persisted when passed to the parser. + * The return value of the function is ignored. + */ + walkTokens?: ((token: Token) => void | Promise) | null; +} +export interface MarkedOptions extends Omit { + /** + * Hooks are methods that hook into some part of marked. + */ + hooks?: _Hooks | null; + /** + * Type: object Default: new Renderer() + * + * An object containing functions to render tokens to HTML. + */ + renderer?: _Renderer | null; + /** + * The tokenizer defines how to turn markdown text into tokens. + */ + tokenizer?: _Tokenizer | null; + /** + * Custom extensions + */ + extensions?: null | { + renderers: { + [name: string]: RendererExtensionFunction; + }; + childTokens: { + [name: string]: string[]; + }; + inline?: TokenizerExtensionFunction[]; + block?: TokenizerExtensionFunction[]; + startInline?: TokenizerStartFunction[]; + startBlock?: TokenizerStartFunction[]; + }; + /** + * walkTokens function returns array of values for Promise.all + */ + walkTokens?: null | ((token: Token) => void | Promise | (void | Promise)[]); +} +/** + * Block Lexer + */ +declare class _Lexer { + tokens: TokensList; + options: MarkedOptions; + state: { + inLink: boolean; + inRawBlock: boolean; + top: boolean; + }; + private tokenizer; + private inlineQueue; + constructor(options?: MarkedOptions); + /** + * Expose Rules + */ + static get rules(): { + block: { + normal: { + blockquote: RegExp; + code: RegExp; + def: RegExp; + fences: RegExp; + heading: RegExp; + hr: RegExp; + html: RegExp; + lheading: RegExp; + list: RegExp; + newline: RegExp; + paragraph: RegExp; + table: RegExp; + text: RegExp; + }; + gfm: Record<"code" | "blockquote" | "hr" | "html" | "table" | "text" | "def" | "heading" | "list" | "paragraph" | "fences" | "lheading" | "newline", RegExp>; + pedantic: Record<"code" | "blockquote" | "hr" | "html" | "table" | "text" | "def" | "heading" | "list" | "paragraph" | "fences" | "lheading" | "newline", RegExp>; + }; + inline: { + normal: { + _backpedal: RegExp; + anyPunctuation: RegExp; + autolink: RegExp; + blockSkip: RegExp; + br: RegExp; + code: RegExp; + del: RegExp; + emStrongLDelim: RegExp; + emStrongRDelimAst: RegExp; + emStrongRDelimUnd: RegExp; + escape: RegExp; + link: RegExp; + nolink: RegExp; + punctuation: RegExp; + reflink: RegExp; + reflinkSearch: RegExp; + tag: RegExp; + text: RegExp; + url: RegExp; + }; + gfm: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + breaks: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + pedantic: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + }; + }; + /** + * Static Lex Method + */ + static lex(src: string, options?: MarkedOptions): TokensList; + /** + * Static Lex Inline Method + */ + static lexInline(src: string, options?: MarkedOptions): Token[]; + /** + * Preprocessing + */ + lex(src: string): TokensList; + /** + * Lexing + */ + blockTokens(src: string, tokens?: Token[], lastParagraphClipped?: boolean): Token[]; + blockTokens(src: string, tokens?: TokensList, lastParagraphClipped?: boolean): TokensList; + inline(src: string, tokens?: Token[]): Token[]; + /** + * Lexing/Compiling + */ + inlineTokens(src: string, tokens?: Token[]): Token[]; +} +/** + * Gets the original marked default options. + */ +declare function _getDefaults(): MarkedOptions; +declare let _defaults: MarkedOptions; +export type MaybePromise = void | Promise; +export declare class Marked { + defaults: MarkedOptions; + options: (opt: MarkedOptions) => this; + parse: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + Parser: typeof _Parser; + Renderer: typeof _Renderer; + TextRenderer: typeof _TextRenderer; + Lexer: typeof _Lexer; + Tokenizer: typeof _Tokenizer; + Hooks: typeof _Hooks; + constructor(...args: MarkedExtension[]); + /** + * Run callback for every token + */ + walkTokens(tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]): MaybePromise[]; + use(...args: MarkedExtension[]): this; + setOptions(opt: MarkedOptions): this; + lexer(src: string, options?: MarkedOptions): TokensList; + parser(tokens: Token[], options?: MarkedOptions): string; + private parseMarkdown; + private onError; +} +/** + * Compiles markdown to HTML asynchronously. + * + * @param src String of markdown source to be compiled + * @param options Hash of options, having async: true + * @return Promise of string of compiled HTML + */ +export declare function marked(src: string, options: MarkedOptions & { + async: true; +}): Promise; +/** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param options Optional hash of options + * @return String of compiled HTML. Will be a Promise of string if async is set to true by any extensions. + */ +export declare function marked(src: string, options: MarkedOptions & { + async: false; +}): string; +export declare function marked(src: string, options: MarkedOptions & { + async: true; +}): Promise; +export declare function marked(src: string, options?: MarkedOptions | null): string | Promise; +export declare namespace marked { + var options: (options: MarkedOptions) => typeof marked; + var setOptions: (options: MarkedOptions) => typeof marked; + var getDefaults: typeof _getDefaults; + var defaults: MarkedOptions; + var use: (...args: MarkedExtension[]) => typeof marked; + var walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[]; + var parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + var Parser: typeof _Parser; + var parser: typeof _Parser.parse; + var Renderer: typeof _Renderer; + var TextRenderer: typeof _TextRenderer; + var Lexer: typeof _Lexer; + var lexer: typeof _Lexer.lex; + var Tokenizer: typeof _Tokenizer; + var Hooks: typeof _Hooks; + var parse: typeof marked; +} +export declare const options: (options: MarkedOptions) => typeof marked; +export declare const setOptions: (options: MarkedOptions) => typeof marked; +export declare const use: (...args: MarkedExtension[]) => typeof marked; +export declare const walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[]; +export declare const parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; +}; +export declare const parse: typeof marked; +export declare const parser: typeof _Parser.parse; +export declare const lexer: typeof _Lexer.lex; + +export { + _Hooks as Hooks, + _Lexer as Lexer, + _Parser as Parser, + _Renderer as Renderer, + _TextRenderer as TextRenderer, + _Tokenizer as Tokenizer, + _defaults as defaults, + _getDefaults as getDefaults, +}; + +export {}; diff --git a/docs/node_modules/marked/lib/marked.d.ts b/docs/node_modules/marked/lib/marked.d.ts new file mode 100644 index 00000000..026652b0 --- /dev/null +++ b/docs/node_modules/marked/lib/marked.d.ts @@ -0,0 +1,727 @@ +// Generated by dts-bundle-generator v9.5.1 + +export type MarkedToken = (Tokens.Blockquote | Tokens.Br | Tokens.Code | Tokens.Codespan | Tokens.Def | Tokens.Del | Tokens.Em | Tokens.Escape | Tokens.Heading | Tokens.Hr | Tokens.HTML | Tokens.Image | Tokens.Link | Tokens.List | Tokens.ListItem | Tokens.Paragraph | Tokens.Space | Tokens.Strong | Tokens.Table | Tokens.Tag | Tokens.Text); +export type Token = (MarkedToken | Tokens.Generic); +export declare namespace Tokens { + interface Blockquote { + type: "blockquote"; + raw: string; + text: string; + tokens: Token[]; + } + interface Br { + type: "br"; + raw: string; + } + interface Checkbox { + checked: boolean; + } + interface Code { + type: "code"; + raw: string; + codeBlockStyle?: "indented"; + lang?: string; + text: string; + escaped?: boolean; + } + interface Codespan { + type: "codespan"; + raw: string; + text: string; + } + interface Def { + type: "def"; + raw: string; + tag: string; + href: string; + title: string; + } + interface Del { + type: "del"; + raw: string; + text: string; + tokens: Token[]; + } + interface Em { + type: "em"; + raw: string; + text: string; + tokens: Token[]; + } + interface Escape { + type: "escape"; + raw: string; + text: string; + } + interface Generic { + [index: string]: any; + type: string; + raw: string; + tokens?: Token[]; + } + interface Heading { + type: "heading"; + raw: string; + depth: number; + text: string; + tokens: Token[]; + } + interface Hr { + type: "hr"; + raw: string; + } + interface HTML { + type: "html"; + raw: string; + pre: boolean; + text: string; + block: boolean; + } + interface Image { + type: "image"; + raw: string; + href: string; + title: string | null; + text: string; + } + interface Link { + type: "link"; + raw: string; + href: string; + title?: string | null; + text: string; + tokens: Token[]; + } + interface List { + type: "list"; + raw: string; + ordered: boolean; + start: number | ""; + loose: boolean; + items: ListItem[]; + } + interface ListItem { + type: "list_item"; + raw: string; + task: boolean; + checked?: boolean; + loose: boolean; + text: string; + tokens: Token[]; + } + interface Paragraph { + type: "paragraph"; + raw: string; + pre?: boolean; + text: string; + tokens: Token[]; + } + interface Space { + type: "space"; + raw: string; + } + interface Strong { + type: "strong"; + raw: string; + text: string; + tokens: Token[]; + } + interface Table { + type: "table"; + raw: string; + align: Array<"center" | "left" | "right" | null>; + header: TableCell[]; + rows: TableCell[][]; + } + interface TableCell { + text: string; + tokens: Token[]; + header: boolean; + align: "center" | "left" | "right" | null; + } + interface TableRow { + text: string; + } + interface Tag { + type: "html"; + raw: string; + inLink: boolean; + inRawBlock: boolean; + text: string; + block: boolean; + } + interface Text { + type: "text"; + raw: string; + text: string; + tokens?: Token[]; + escaped?: boolean; + } +} +export type Links = Record>; +export type TokensList = Token[] & { + links: Links; +}; +/** + * Renderer + */ +declare class _Renderer { + options: MarkedOptions; + parser: _Parser; + constructor(options?: MarkedOptions); + space(token: Tokens.Space): string; + code({ text, lang, escaped }: Tokens.Code): string; + blockquote({ tokens }: Tokens.Blockquote): string; + html({ text }: Tokens.HTML | Tokens.Tag): string; + heading({ tokens, depth }: Tokens.Heading): string; + hr(token: Tokens.Hr): string; + list(token: Tokens.List): string; + listitem(item: Tokens.ListItem): string; + checkbox({ checked }: Tokens.Checkbox): string; + paragraph({ tokens }: Tokens.Paragraph): string; + table(token: Tokens.Table): string; + tablerow({ text }: Tokens.TableRow): string; + tablecell(token: Tokens.TableCell): string; + /** + * span level renderer + */ + strong({ tokens }: Tokens.Strong): string; + em({ tokens }: Tokens.Em): string; + codespan({ text }: Tokens.Codespan): string; + br(token: Tokens.Br): string; + del({ tokens }: Tokens.Del): string; + link({ href, title, tokens }: Tokens.Link): string; + image({ href, title, text }: Tokens.Image): string; + text(token: Tokens.Text | Tokens.Escape): string; +} +/** + * TextRenderer + * returns only the textual part of the token + */ +declare class _TextRenderer { + strong({ text }: Tokens.Strong): string; + em({ text }: Tokens.Em): string; + codespan({ text }: Tokens.Codespan): string; + del({ text }: Tokens.Del): string; + html({ text }: Tokens.HTML | Tokens.Tag): string; + text({ text }: Tokens.Text | Tokens.Escape | Tokens.Tag): string; + link({ text }: Tokens.Link): string; + image({ text }: Tokens.Image): string; + br(): string; +} +/** + * Parsing & Compiling + */ +declare class _Parser { + options: MarkedOptions; + renderer: _Renderer; + textRenderer: _TextRenderer; + constructor(options?: MarkedOptions); + /** + * Static Parse Method + */ + static parse(tokens: Token[], options?: MarkedOptions): string; + /** + * Static Parse Inline Method + */ + static parseInline(tokens: Token[], options?: MarkedOptions): string; + /** + * Parse Loop + */ + parse(tokens: Token[], top?: boolean): string; + /** + * Parse Inline Tokens + */ + parseInline(tokens: Token[], renderer?: _Renderer | _TextRenderer): string; +} +declare const other: { + codeRemoveIndent: RegExp; + outputLinkReplace: RegExp; + indentCodeCompensation: RegExp; + beginningSpace: RegExp; + endingHash: RegExp; + startingSpaceChar: RegExp; + endingSpaceChar: RegExp; + nonSpaceChar: RegExp; + newLineCharGlobal: RegExp; + tabCharGlobal: RegExp; + multipleSpaceGlobal: RegExp; + blankLine: RegExp; + doubleBlankLine: RegExp; + blockquoteStart: RegExp; + blockquoteSetextReplace: RegExp; + blockquoteSetextReplace2: RegExp; + listReplaceTabs: RegExp; + listReplaceNesting: RegExp; + listIsTask: RegExp; + listReplaceTask: RegExp; + anyLine: RegExp; + hrefBrackets: RegExp; + tableDelimiter: RegExp; + tableAlignChars: RegExp; + tableRowBlankLine: RegExp; + tableAlignRight: RegExp; + tableAlignCenter: RegExp; + tableAlignLeft: RegExp; + startATag: RegExp; + endATag: RegExp; + startPreScriptTag: RegExp; + endPreScriptTag: RegExp; + startAngleBracket: RegExp; + endAngleBracket: RegExp; + pedanticHrefTitle: RegExp; + unicodeAlphaNumeric: RegExp; + escapeTest: RegExp; + escapeReplace: RegExp; + escapeTestNoEncode: RegExp; + escapeReplaceNoEncode: RegExp; + unescapeTest: RegExp; + caret: RegExp; + percentDecode: RegExp; + findPipe: RegExp; + splitPipe: RegExp; + slashPipe: RegExp; + carriageReturn: RegExp; + spaceLine: RegExp; + notSpaceStart: RegExp; + endingNewline: RegExp; + listItemRegex: (bull: string) => RegExp; + nextBulletRegex: (indent: number) => RegExp; + hrRegex: (indent: number) => RegExp; + fencesBeginRegex: (indent: number) => RegExp; + headingBeginRegex: (indent: number) => RegExp; + htmlBeginRegex: (indent: number) => RegExp; +}; +declare const blockNormal: { + blockquote: RegExp; + code: RegExp; + def: RegExp; + fences: RegExp; + heading: RegExp; + hr: RegExp; + html: RegExp; + lheading: RegExp; + list: RegExp; + newline: RegExp; + paragraph: RegExp; + table: RegExp; + text: RegExp; +}; +export type BlockKeys = keyof typeof blockNormal; +declare const inlineNormal: { + _backpedal: RegExp; + anyPunctuation: RegExp; + autolink: RegExp; + blockSkip: RegExp; + br: RegExp; + code: RegExp; + del: RegExp; + emStrongLDelim: RegExp; + emStrongRDelimAst: RegExp; + emStrongRDelimUnd: RegExp; + escape: RegExp; + link: RegExp; + nolink: RegExp; + punctuation: RegExp; + reflink: RegExp; + reflinkSearch: RegExp; + tag: RegExp; + text: RegExp; + url: RegExp; +}; +export type InlineKeys = keyof typeof inlineNormal; +export interface Rules { + other: typeof other; + block: Record; + inline: Record; +} +/** + * Tokenizer + */ +declare class _Tokenizer { + options: MarkedOptions; + rules: Rules; + lexer: _Lexer; + constructor(options?: MarkedOptions); + space(src: string): Tokens.Space | undefined; + code(src: string): Tokens.Code | undefined; + fences(src: string): Tokens.Code | undefined; + heading(src: string): Tokens.Heading | undefined; + hr(src: string): Tokens.Hr | undefined; + blockquote(src: string): Tokens.Blockquote | undefined; + list(src: string): Tokens.List | undefined; + html(src: string): Tokens.HTML | undefined; + def(src: string): Tokens.Def | undefined; + table(src: string): Tokens.Table | undefined; + lheading(src: string): Tokens.Heading | undefined; + paragraph(src: string): Tokens.Paragraph | undefined; + text(src: string): Tokens.Text | undefined; + escape(src: string): Tokens.Escape | undefined; + tag(src: string): Tokens.Tag | undefined; + link(src: string): Tokens.Link | Tokens.Image | undefined; + reflink(src: string, links: Links): Tokens.Link | Tokens.Image | Tokens.Text | undefined; + emStrong(src: string, maskedSrc: string, prevChar?: string): Tokens.Em | Tokens.Strong | undefined; + codespan(src: string): Tokens.Codespan | undefined; + br(src: string): Tokens.Br | undefined; + del(src: string): Tokens.Del | undefined; + autolink(src: string): Tokens.Link | undefined; + url(src: string): Tokens.Link | undefined; + inlineText(src: string): Tokens.Text | undefined; +} +declare class _Hooks { + options: MarkedOptions; + block?: boolean; + constructor(options?: MarkedOptions); + static passThroughHooks: Set; + /** + * Process markdown before marked + */ + preprocess(markdown: string): string; + /** + * Process HTML after marked is finished + */ + postprocess(html: string): string; + /** + * Process all tokens before walk tokens + */ + processAllTokens(tokens: Token[] | TokensList): Token[] | TokensList; + /** + * Provide function to tokenize markdown + */ + provideLexer(): typeof _Lexer.lexInline; + /** + * Provide function to parse tokens + */ + provideParser(): typeof _Parser.parse; +} +export interface TokenizerThis { + lexer: _Lexer; +} +export type TokenizerExtensionFunction = (this: TokenizerThis, src: string, tokens: Token[] | TokensList) => Tokens.Generic | undefined; +export type TokenizerStartFunction = (this: TokenizerThis, src: string) => number | void; +export interface TokenizerExtension { + name: string; + level: "block" | "inline"; + start?: TokenizerStartFunction; + tokenizer: TokenizerExtensionFunction; + childTokens?: string[]; +} +export interface RendererThis { + parser: _Parser; +} +export type RendererExtensionFunction = (this: RendererThis, token: Tokens.Generic) => string | false | undefined; +export interface RendererExtension { + name: string; + renderer: RendererExtensionFunction; +} +export type TokenizerAndRendererExtension = TokenizerExtension | RendererExtension | (TokenizerExtension & RendererExtension); +export type HooksApi = Omit<_Hooks, "constructor" | "options" | "block">; +export type HooksObject = { + [K in keyof HooksApi]?: (this: _Hooks, ...args: Parameters) => ReturnType | Promise>; +}; +export type RendererApi = Omit<_Renderer, "constructor" | "options" | "parser">; +export type RendererObject = { + [K in keyof RendererApi]?: (this: _Renderer, ...args: Parameters) => ReturnType | false; +}; +export type TokenizerApi = Omit<_Tokenizer, "constructor" | "options" | "rules" | "lexer">; +export type TokenizerObject = { + [K in keyof TokenizerApi]?: (this: _Tokenizer, ...args: Parameters) => ReturnType | false; +}; +export interface MarkedExtension { + /** + * True will tell marked to await any walkTokens functions before parsing the tokens and returning an HTML string. + */ + async?: boolean; + /** + * Enable GFM line breaks. This option requires the gfm option to be true. + */ + breaks?: boolean; + /** + * Add tokenizers and renderers to marked + */ + extensions?: TokenizerAndRendererExtension[] | null; + /** + * Enable GitHub flavored markdown. + */ + gfm?: boolean; + /** + * Hooks are methods that hook into some part of marked. + * preprocess is called to process markdown before sending it to marked. + * processAllTokens is called with the TokensList before walkTokens. + * postprocess is called to process html after marked has finished parsing. + * provideLexer is called to provide a function to tokenize markdown. + * provideParser is called to provide a function to parse tokens. + */ + hooks?: HooksObject | null; + /** + * Conform to obscure parts of markdown.pl as much as possible. Don't fix any of the original markdown bugs or poor behavior. + */ + pedantic?: boolean; + /** + * Type: object Default: new Renderer() + * + * An object containing functions to render tokens to HTML. + */ + renderer?: RendererObject | null; + /** + * Shows an HTML error message when rendering fails. + */ + silent?: boolean; + /** + * The tokenizer defines how to turn markdown text into tokens. + */ + tokenizer?: TokenizerObject | null; + /** + * The walkTokens function gets called with every token. + * Child tokens are called before moving on to sibling tokens. + * Each token is passed by reference so updates are persisted when passed to the parser. + * The return value of the function is ignored. + */ + walkTokens?: ((token: Token) => void | Promise) | null; +} +export interface MarkedOptions extends Omit { + /** + * Hooks are methods that hook into some part of marked. + */ + hooks?: _Hooks | null; + /** + * Type: object Default: new Renderer() + * + * An object containing functions to render tokens to HTML. + */ + renderer?: _Renderer | null; + /** + * The tokenizer defines how to turn markdown text into tokens. + */ + tokenizer?: _Tokenizer | null; + /** + * Custom extensions + */ + extensions?: null | { + renderers: { + [name: string]: RendererExtensionFunction; + }; + childTokens: { + [name: string]: string[]; + }; + inline?: TokenizerExtensionFunction[]; + block?: TokenizerExtensionFunction[]; + startInline?: TokenizerStartFunction[]; + startBlock?: TokenizerStartFunction[]; + }; + /** + * walkTokens function returns array of values for Promise.all + */ + walkTokens?: null | ((token: Token) => void | Promise | (void | Promise)[]); +} +/** + * Block Lexer + */ +declare class _Lexer { + tokens: TokensList; + options: MarkedOptions; + state: { + inLink: boolean; + inRawBlock: boolean; + top: boolean; + }; + private tokenizer; + private inlineQueue; + constructor(options?: MarkedOptions); + /** + * Expose Rules + */ + static get rules(): { + block: { + normal: { + blockquote: RegExp; + code: RegExp; + def: RegExp; + fences: RegExp; + heading: RegExp; + hr: RegExp; + html: RegExp; + lheading: RegExp; + list: RegExp; + newline: RegExp; + paragraph: RegExp; + table: RegExp; + text: RegExp; + }; + gfm: Record<"code" | "blockquote" | "hr" | "html" | "table" | "text" | "def" | "heading" | "list" | "paragraph" | "fences" | "lheading" | "newline", RegExp>; + pedantic: Record<"code" | "blockquote" | "hr" | "html" | "table" | "text" | "def" | "heading" | "list" | "paragraph" | "fences" | "lheading" | "newline", RegExp>; + }; + inline: { + normal: { + _backpedal: RegExp; + anyPunctuation: RegExp; + autolink: RegExp; + blockSkip: RegExp; + br: RegExp; + code: RegExp; + del: RegExp; + emStrongLDelim: RegExp; + emStrongRDelimAst: RegExp; + emStrongRDelimUnd: RegExp; + escape: RegExp; + link: RegExp; + nolink: RegExp; + punctuation: RegExp; + reflink: RegExp; + reflinkSearch: RegExp; + tag: RegExp; + text: RegExp; + url: RegExp; + }; + gfm: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + breaks: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + pedantic: Record<"link" | "code" | "url" | "br" | "del" | "text" | "escape" | "tag" | "reflink" | "nolink" | "_backpedal" | "anyPunctuation" | "autolink" | "blockSkip" | "emStrongLDelim" | "emStrongRDelimAst" | "emStrongRDelimUnd" | "punctuation" | "reflinkSearch", RegExp>; + }; + }; + /** + * Static Lex Method + */ + static lex(src: string, options?: MarkedOptions): TokensList; + /** + * Static Lex Inline Method + */ + static lexInline(src: string, options?: MarkedOptions): Token[]; + /** + * Preprocessing + */ + lex(src: string): TokensList; + /** + * Lexing + */ + blockTokens(src: string, tokens?: Token[], lastParagraphClipped?: boolean): Token[]; + blockTokens(src: string, tokens?: TokensList, lastParagraphClipped?: boolean): TokensList; + inline(src: string, tokens?: Token[]): Token[]; + /** + * Lexing/Compiling + */ + inlineTokens(src: string, tokens?: Token[]): Token[]; +} +/** + * Gets the original marked default options. + */ +declare function _getDefaults(): MarkedOptions; +declare let _defaults: MarkedOptions; +export type MaybePromise = void | Promise; +export declare class Marked { + defaults: MarkedOptions; + options: (opt: MarkedOptions) => this; + parse: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + Parser: typeof _Parser; + Renderer: typeof _Renderer; + TextRenderer: typeof _TextRenderer; + Lexer: typeof _Lexer; + Tokenizer: typeof _Tokenizer; + Hooks: typeof _Hooks; + constructor(...args: MarkedExtension[]); + /** + * Run callback for every token + */ + walkTokens(tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]): MaybePromise[]; + use(...args: MarkedExtension[]): this; + setOptions(opt: MarkedOptions): this; + lexer(src: string, options?: MarkedOptions): TokensList; + parser(tokens: Token[], options?: MarkedOptions): string; + private parseMarkdown; + private onError; +} +/** + * Compiles markdown to HTML asynchronously. + * + * @param src String of markdown source to be compiled + * @param options Hash of options, having async: true + * @return Promise of string of compiled HTML + */ +export declare function marked(src: string, options: MarkedOptions & { + async: true; +}): Promise; +/** + * Compiles markdown to HTML. + * + * @param src String of markdown source to be compiled + * @param options Optional hash of options + * @return String of compiled HTML. Will be a Promise of string if async is set to true by any extensions. + */ +export declare function marked(src: string, options: MarkedOptions & { + async: false; +}): string; +export declare function marked(src: string, options: MarkedOptions & { + async: true; +}): Promise; +export declare function marked(src: string, options?: MarkedOptions | null): string | Promise; +export declare namespace marked { + var options: (options: MarkedOptions) => typeof marked; + var setOptions: (options: MarkedOptions) => typeof marked; + var getDefaults: typeof _getDefaults; + var defaults: MarkedOptions; + var use: (...args: MarkedExtension[]) => typeof marked; + var walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[]; + var parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; + }; + var Parser: typeof _Parser; + var parser: typeof _Parser.parse; + var Renderer: typeof _Renderer; + var TextRenderer: typeof _TextRenderer; + var Lexer: typeof _Lexer; + var lexer: typeof _Lexer.lex; + var Tokenizer: typeof _Tokenizer; + var Hooks: typeof _Hooks; + var parse: typeof marked; +} +export declare const options: (options: MarkedOptions) => typeof marked; +export declare const setOptions: (options: MarkedOptions) => typeof marked; +export declare const use: (...args: MarkedExtension[]) => typeof marked; +export declare const walkTokens: (tokens: Token[] | TokensList, callback: (token: Token) => MaybePromise | MaybePromise[]) => MaybePromise[]; +export declare const parseInline: { + (src: string, options: MarkedOptions & { + async: true; + }): Promise; + (src: string, options: MarkedOptions & { + async: false; + }): string; + (src: string, options?: MarkedOptions | null): string | Promise; +}; +export declare const parse: typeof marked; +export declare const parser: typeof _Parser.parse; +export declare const lexer: typeof _Lexer.lex; + +export { + _Hooks as Hooks, + _Lexer as Lexer, + _Parser as Parser, + _Renderer as Renderer, + _TextRenderer as TextRenderer, + _Tokenizer as Tokenizer, + _defaults as defaults, + _getDefaults as getDefaults, +}; + +export {}; diff --git a/docs/node_modules/marked/lib/marked.esm.js b/docs/node_modules/marked/lib/marked.esm.js new file mode 100644 index 00000000..5cbe91d7 --- /dev/null +++ b/docs/node_modules/marked/lib/marked.esm.js @@ -0,0 +1,2552 @@ +/** + * marked v15.0.3 - a markdown parser + * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +/** + * Gets the original marked default options. + */ +function _getDefaults() { + return { + async: false, + breaks: false, + extensions: null, + gfm: true, + hooks: null, + pedantic: false, + renderer: null, + silent: false, + tokenizer: null, + walkTokens: null, + }; +} +let _defaults = _getDefaults(); +function changeDefaults(newDefaults) { + _defaults = newDefaults; +} + +const noopTest = { exec: () => null }; +function edit(regex, opt = '') { + let source = typeof regex === 'string' ? regex : regex.source; + const obj = { + replace: (name, val) => { + let valSource = typeof val === 'string' ? val : val.source; + valSource = valSource.replace(other.caret, '$1'); + source = source.replace(name, valSource); + return obj; + }, + getRegex: () => { + return new RegExp(source, opt); + }, + }; + return obj; +} +const other = { + codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, + outputLinkReplace: /\\([\[\]])/g, + indentCodeCompensation: /^(\s+)(?:```)/, + beginningSpace: /^\s+/, + endingHash: /#$/, + startingSpaceChar: /^ /, + endingSpaceChar: / $/, + nonSpaceChar: /[^ ]/, + newLineCharGlobal: /\n/g, + tabCharGlobal: /\t/g, + multipleSpaceGlobal: /\s+/g, + blankLine: /^[ \t]*$/, + doubleBlankLine: /\n[ \t]*\n[ \t]*$/, + blockquoteStart: /^ {0,3}>/, + blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, + blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, + listReplaceTabs: /^\t+/, + listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, + listIsTask: /^\[[ xX]\] /, + listReplaceTask: /^\[[ xX]\] +/, + anyLine: /\n.*\n/, + hrefBrackets: /^<(.*)>$/, + tableDelimiter: /[:|]/, + tableAlignChars: /^\||\| *$/g, + tableRowBlankLine: /\n[ \t]*$/, + tableAlignRight: /^ *-+: *$/, + tableAlignCenter: /^ *:-+: *$/, + tableAlignLeft: /^ *:-+ *$/, + startATag: /^
    /i, + startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, + endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, + startAngleBracket: /^$/, + pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, + unicodeAlphaNumeric: /[\p{L}\p{N}]/u, + escapeTest: /[&<>"']/, + escapeReplace: /[&<>"']/g, + escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, + escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, + unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, + caret: /(^|[^\[])\^/g, + percentDecode: /%25/g, + findPipe: /\|/g, + splitPipe: / \|/, + slashPipe: /\\\|/g, + carriageReturn: /\r\n|\r/g, + spaceLine: /^ +$/gm, + notSpaceStart: /^\S*/, + endingNewline: /\n$/, + listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), + nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`), + hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), + fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`), + headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`), + htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'), +}; +/** + * Block-Level Grammar + */ +const newline = /^(?:[ \t]*(?:\n|$))+/; +const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/; +const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/; +const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/; +const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/; +const bullet = /(?:[*+-]|\d{1,9}[.)])/; +const lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/) + .replace(/bull/g, bullet) // lists can interrupt + .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt + .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt + .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt + .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt + .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt + .getRegex(); +const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/; +const blockText = /^[^\n]+/; +const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/; +const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/) + .replace('label', _blockLabel) + .replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/) + .getRegex(); +const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/) + .replace(/bull/g, bullet) + .getRegex(); +const _tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title' + + '|tr|track|ul'; +const _comment = /|$))/; +const html = edit('^ {0,3}(?:' // optional indentation + + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6) + + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag + + ')', 'i') + .replace('comment', _comment) + .replace('tag', _tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); +const paragraph = edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(); +const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/) + .replace('paragraph', paragraph) + .getRegex(); +/** + * Normal Block Grammar + */ +const blockNormal = { + blockquote, + code: blockCode, + def, + fences, + heading, + hr, + html, + lheading, + list, + newline, + paragraph, + table: noopTest, + text: blockText, +}; +/** + * GFM Block Grammar + */ +const gfmTable = edit('^ *([^\\n ].*)\\n' // Header + + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align + + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('blockquote', ' {0,3}>') + .replace('code', '(?: {4}| {0,3}\t)[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // tables can be interrupted by type (6) html blocks + .getRegex(); +const blockGfm = { + ...blockNormal, + table: gfmTable, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('table', gfmTable) // interrupt paragraphs with table + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(), +}; +/** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ +const blockPedantic = { + ...blockNormal, + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', _comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' *#{1,6} *[^\n]') + .replace('lheading', lheading) + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('|fences', '') + .replace('|list', '') + .replace('|html', '') + .replace('|tag', '') + .getRegex(), +}; +/** + * Inline-Level Grammar + */ +const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/; +const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/; +const br = /^( {2,}|\\)\n(?!\s*$)/; +const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\ +const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g; +const emStrongLDelim = edit(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/, 'u') + .replace(/punct/g, _punctuation) + .getRegex(); +const emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong + + '|[^*]+(?=[^*])' // Consume to delim + + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter + + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter + + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter + + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter + + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter + + '|notPunctSpace(\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +// (6) Not allowed for _ +const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong + + '|[^_]+(?=[^_])' // Consume to delim + + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter + + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter + + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter + + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter + + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); +const anyPunctuation = edit(/\\(punct)/, 'gu') + .replace(/punct/g, _punctuation) + .getRegex(); +const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/) + .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/) + .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/) + .getRegex(); +const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex(); +const tag = edit('^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^') // CDATA section + .replace('comment', _inlineComment) + .replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/) + .getRegex(); +const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; +const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/) + .replace('label', _inlineLabel) + .replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/) + .replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/) + .getRegex(); +const reflink = edit(/^!?\[(label)\]\[(ref)\]/) + .replace('label', _inlineLabel) + .replace('ref', _blockLabel) + .getRegex(); +const nolink = edit(/^!?\[(ref)\](?:\[\])?/) + .replace('ref', _blockLabel) + .getRegex(); +const reflinkSearch = edit('reflink|nolink(?!\\()', 'g') + .replace('reflink', reflink) + .replace('nolink', nolink) + .getRegex(); +/** + * Normal Inline Grammar + */ +const inlineNormal = { + _backpedal: noopTest, // only used for GFM url + anyPunctuation, + autolink, + blockSkip, + br, + code: inlineCode, + del: noopTest, + emStrongLDelim, + emStrongRDelimAst, + emStrongRDelimUnd, + escape: escape$1, + link, + nolink, + punctuation, + reflink, + reflinkSearch, + tag, + text: inlineText, + url: noopTest, +}; +/** + * Pedantic Inline Grammar + */ +const inlinePedantic = { + ...inlineNormal, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', _inlineLabel) + .getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', _inlineLabel) + .getRegex(), +}; +/** + * GFM Inline Grammar + */ +const inlineGfm = { + ...inlineNormal, + escape: edit(escape$1).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i') + .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\': '>', + '"': '"', + "'": ''', +}; +const getEscapeReplacement = (ch) => escapeReplacements[ch]; +function escape(html, encode) { + if (encode) { + if (other.escapeTest.test(html)) { + return html.replace(other.escapeReplace, getEscapeReplacement); + } + } + else { + if (other.escapeTestNoEncode.test(html)) { + return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement); + } + } + return html; +} +function cleanUrl(href) { + try { + href = encodeURI(href).replace(other.percentDecode, '%'); + } + catch { + return null; + } + return href; +} +function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + const row = tableRow.replace(other.findPipe, (match, offset, str) => { + let escaped = false; + let curr = offset; + while (--curr >= 0 && str[curr] === '\\') + escaped = !escaped; + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } + else { + // add space before unescaped | + return ' |'; + } + }), cells = row.split(other.splitPipe); + let i = 0; + // First/last cell in a row cannot be empty if it has no leading/trailing pipe + if (!cells[0].trim()) { + cells.shift(); + } + if (cells.length > 0 && !cells.at(-1)?.trim()) { + cells.pop(); + } + if (count) { + if (cells.length > count) { + cells.splice(count); + } + else { + while (cells.length < count) + cells.push(''); + } + } + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(other.slashPipe, '|'); + } + return cells; +} +/** + * Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + * /c*$/ is vulnerable to REDOS. + * + * @param str + * @param c + * @param invert Remove suffix of non-c chars instead. Default falsey. + */ +function rtrim(str, c, invert) { + const l = str.length; + if (l === 0) { + return ''; + } + // Length of suffix matching the invert condition. + let suffLen = 0; + // Step left until we fail to match the invert condition. + while (suffLen < l) { + const currChar = str.charAt(l - suffLen - 1); + if (currChar === c && !invert) { + suffLen++; + } + else if (currChar !== c && invert) { + suffLen++; + } + else { + break; + } + } + return str.slice(0, l - suffLen); +} +function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + let level = 0; + for (let i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } + else if (str[i] === b[0]) { + level++; + } + else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; +} + +function outputLink(cap, link, raw, lexer, rules) { + const href = link.href; + const title = link.title || null; + const text = cap[1].replace(rules.other.outputLinkReplace, '$1'); + if (cap[0].charAt(0) !== '!') { + lexer.state.inLink = true; + const token = { + type: 'link', + raw, + href, + title, + text, + tokens: lexer.inlineTokens(text), + }; + lexer.state.inLink = false; + return token; + } + return { + type: 'image', + raw, + href, + title, + text, + }; +} +function indentCodeCompensation(raw, text, rules) { + const matchIndentToCode = raw.match(rules.other.indentCodeCompensation); + if (matchIndentToCode === null) { + return text; + } + const indentToCode = matchIndentToCode[1]; + return text + .split('\n') + .map(node => { + const matchIndentInNode = node.match(rules.other.beginningSpace); + if (matchIndentInNode === null) { + return node; + } + const [indentInNode] = matchIndentInNode; + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + return node; + }) + .join('\n'); +} +/** + * Tokenizer + */ +class _Tokenizer { + options; + rules; // set by the lexer + lexer; // set by the lexer + constructor(options) { + this.options = options || _defaults; + } + space(src) { + const cap = this.rules.block.newline.exec(src); + if (cap && cap[0].length > 0) { + return { + type: 'space', + raw: cap[0], + }; + } + } + code(src) { + const cap = this.rules.block.code.exec(src); + if (cap) { + const text = cap[0].replace(this.rules.other.codeRemoveIndent, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic + ? rtrim(text, '\n') + : text, + }; + } + } + fences(src) { + const cap = this.rules.block.fences.exec(src); + if (cap) { + const raw = cap[0]; + const text = indentCodeCompensation(raw, cap[3] || '', this.rules); + return { + type: 'code', + raw, + lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2], + text, + }; + } + } + heading(src) { + const cap = this.rules.block.heading.exec(src); + if (cap) { + let text = cap[2].trim(); + // remove trailing #s + if (this.rules.other.endingHash.test(text)) { + const trimmed = rtrim(text, '#'); + if (this.options.pedantic) { + text = trimmed.trim(); + } + else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + return { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text, + tokens: this.lexer.inline(text), + }; + } + } + hr(src) { + const cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: 'hr', + raw: rtrim(cap[0], '\n'), + }; + } + } + blockquote(src) { + const cap = this.rules.block.blockquote.exec(src); + if (cap) { + let lines = rtrim(cap[0], '\n').split('\n'); + let raw = ''; + let text = ''; + const tokens = []; + while (lines.length > 0) { + let inBlockquote = false; + const currentLines = []; + let i; + for (i = 0; i < lines.length; i++) { + // get lines up to a continuation + if (this.rules.other.blockquoteStart.test(lines[i])) { + currentLines.push(lines[i]); + inBlockquote = true; + } + else if (!inBlockquote) { + currentLines.push(lines[i]); + } + else { + break; + } + } + lines = lines.slice(i); + const currentRaw = currentLines.join('\n'); + const currentText = currentRaw + // precede setext continuation with 4 spaces so it isn't a setext + .replace(this.rules.other.blockquoteSetextReplace, '\n $1') + .replace(this.rules.other.blockquoteSetextReplace2, ''); + raw = raw ? `${raw}\n${currentRaw}` : currentRaw; + text = text ? `${text}\n${currentText}` : currentText; + // parse blockquote lines as top level tokens + // merge paragraphs if this is a continuation + const top = this.lexer.state.top; + this.lexer.state.top = true; + this.lexer.blockTokens(currentText, tokens, true); + this.lexer.state.top = top; + // if there is no continuation then we are done + if (lines.length === 0) { + break; + } + const lastToken = tokens.at(-1); + if (lastToken?.type === 'code') { + // blockquote continuation cannot be preceded by a code block + break; + } + else if (lastToken?.type === 'blockquote') { + // include continuation in nested blockquote + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.blockquote(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.text.length) + newToken.text; + break; + } + else if (lastToken?.type === 'list') { + // include continuation in nested list + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.list(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw; + lines = newText.substring(tokens.at(-1).raw.length).split('\n'); + continue; + } + } + return { + type: 'blockquote', + raw, + tokens, + text, + }; + } + } + list(src) { + let cap = this.rules.block.list.exec(src); + if (cap) { + let bull = cap[1].trim(); + const isordered = bull.length > 1; + const list = { + type: 'list', + raw: '', + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [], + }; + bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`; + if (this.options.pedantic) { + bull = isordered ? bull : '[*+-]'; + } + // Get next list item + const itemRegex = this.rules.other.listItemRegex(bull); + let endsWithBlankLine = false; + // Check if current bullet point can start a new List Item + while (src) { + let endEarly = false; + let raw = ''; + let itemContents = ''; + if (!(cap = itemRegex.exec(src))) { + break; + } + if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?) + break; + } + raw = cap[0]; + src = src.substring(raw.length); + let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length)); + let nextLine = src.split('\n', 1)[0]; + let blankLine = !line.trim(); + let indent = 0; + if (this.options.pedantic) { + indent = 2; + itemContents = line.trimStart(); + } + else if (blankLine) { + indent = cap[1].length + 1; + } + else { + indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char + indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent + itemContents = line.slice(indent); + indent += cap[1].length; + } + if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line + raw += nextLine + '\n'; + src = src.substring(nextLine.length + 1); + endEarly = true; + } + if (!endEarly) { + const nextBulletRegex = this.rules.other.nextBulletRegex(indent); + const hrRegex = this.rules.other.hrRegex(indent); + const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent); + const headingBeginRegex = this.rules.other.headingBeginRegex(indent); + const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent); + // Check if following lines should be included in List Item + while (src) { + const rawLine = src.split('\n', 1)[0]; + let nextLineWithoutTabs; + nextLine = rawLine; + // Re-align to follow commonmark nesting rules + if (this.options.pedantic) { + nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' '); + nextLineWithoutTabs = nextLine; + } + else { + nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' '); + } + // End list item if found code fences + if (fencesBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new heading + if (headingBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of html block + if (htmlBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new bullet + if (nextBulletRegex.test(nextLine)) { + break; + } + // Horizontal rule found + if (hrRegex.test(nextLine)) { + break; + } + if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible + itemContents += '\n' + nextLineWithoutTabs.slice(indent); + } + else { + // not enough indentation + if (blankLine) { + break; + } + // paragraph continuation unless last line was a different block level element + if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block + break; + } + if (fencesBeginRegex.test(line)) { + break; + } + if (headingBeginRegex.test(line)) { + break; + } + if (hrRegex.test(line)) { + break; + } + itemContents += '\n' + nextLine; + } + if (!blankLine && !nextLine.trim()) { // Check if current line is blank + blankLine = true; + } + raw += rawLine + '\n'; + src = src.substring(rawLine.length + 1); + line = nextLineWithoutTabs.slice(indent); + } + } + if (!list.loose) { + // If the previous item ended with a blank line, the list is loose + if (endsWithBlankLine) { + list.loose = true; + } + else if (this.rules.other.doubleBlankLine.test(raw)) { + endsWithBlankLine = true; + } + } + let istask = null; + let ischecked; + // Check for task list items + if (this.options.gfm) { + istask = this.rules.other.listIsTask.exec(itemContents); + if (istask) { + ischecked = istask[0] !== '[ ] '; + itemContents = itemContents.replace(this.rules.other.listReplaceTask, ''); + } + } + list.items.push({ + type: 'list_item', + raw, + task: !!istask, + checked: ischecked, + loose: false, + text: itemContents, + tokens: [], + }); + list.raw += raw; + } + // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic + const lastItem = list.items.at(-1); + if (lastItem) { + lastItem.raw = lastItem.raw.trimEnd(); + lastItem.text = lastItem.text.trimEnd(); + } + list.raw = list.raw.trimEnd(); + // Item child tokens handled here at end because we needed to have the final item to trim it first + for (let i = 0; i < list.items.length; i++) { + this.lexer.state.top = false; + list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []); + if (!list.loose) { + // Check if list should be loose + const spacers = list.items[i].tokens.filter(t => t.type === 'space'); + const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw)); + list.loose = hasMultipleLineBreaks; + } + } + // Set all items to loose if list is loose + if (list.loose) { + for (let i = 0; i < list.items.length; i++) { + list.items[i].loose = true; + } + } + return list; + } + } + html(src) { + const cap = this.rules.block.html.exec(src); + if (cap) { + const token = { + type: 'html', + block: true, + raw: cap[0], + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0], + }; + return token; + } + } + def(src) { + const cap = this.rules.block.def.exec(src); + if (cap) { + const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' '); + const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : ''; + const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3]; + return { + type: 'def', + tag, + raw: cap[0], + href, + title, + }; + } + } + table(src) { + const cap = this.rules.block.table.exec(src); + if (!cap) { + return; + } + if (!this.rules.other.tableDelimiter.test(cap[2])) { + // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading + return; + } + const headers = splitCells(cap[1]); + const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|'); + const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : []; + const item = { + type: 'table', + raw: cap[0], + header: [], + align: [], + rows: [], + }; + if (headers.length !== aligns.length) { + // header and align columns must be equal, rows can be different. + return; + } + for (const align of aligns) { + if (this.rules.other.tableAlignRight.test(align)) { + item.align.push('right'); + } + else if (this.rules.other.tableAlignCenter.test(align)) { + item.align.push('center'); + } + else if (this.rules.other.tableAlignLeft.test(align)) { + item.align.push('left'); + } + else { + item.align.push(null); + } + } + for (let i = 0; i < headers.length; i++) { + item.header.push({ + text: headers[i], + tokens: this.lexer.inline(headers[i]), + header: true, + align: item.align[i], + }); + } + for (const row of rows) { + item.rows.push(splitCells(row, item.header.length).map((cell, i) => { + return { + text: cell, + tokens: this.lexer.inline(cell), + header: false, + align: item.align[i], + }; + })); + } + return item; + } + lheading(src) { + const cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1], + tokens: this.lexer.inline(cap[1]), + }; + } + } + paragraph(src) { + const cap = this.rules.block.paragraph.exec(src); + if (cap) { + const text = cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1]; + return { + type: 'paragraph', + raw: cap[0], + text, + tokens: this.lexer.inline(text), + }; + } + } + text(src) { + const cap = this.rules.block.text.exec(src); + if (cap) { + return { + type: 'text', + raw: cap[0], + text: cap[0], + tokens: this.lexer.inline(cap[0]), + }; + } + } + escape(src) { + const cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: cap[1], + }; + } + } + tag(src) { + const cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) { + this.lexer.state.inLink = true; + } + else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) { + this.lexer.state.inLink = false; + } + if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = true; + } + else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = false; + } + return { + type: 'html', + raw: cap[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: false, + text: cap[0], + }; + } + } + link(src) { + const cap = this.rules.inline.link.exec(src); + if (cap) { + const trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) { + // commonmark requires matching angle brackets + if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) { + return; + } + // ending angle bracket cannot be escaped + const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\'); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } + else { + // find closing parenthesis + const lastParenIndex = findClosingBracket(cap[2], '()'); + if (lastParenIndex > -1) { + const start = cap[0].indexOf('!') === 0 ? 5 : 4; + const linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + let href = cap[2]; + let title = ''; + if (this.options.pedantic) { + // split pedantic href and title + const link = this.rules.other.pedanticHrefTitle.exec(href); + if (link) { + href = link[1]; + title = link[3]; + } + } + else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim(); + if (this.rules.other.startAngleBracket.test(href)) { + if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } + else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href, + title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title, + }, cap[0], this.lexer, this.rules); + } + } + reflink(src, links) { + let cap; + if ((cap = this.rules.inline.reflink.exec(src)) + || (cap = this.rules.inline.nolink.exec(src))) { + const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' '); + const link = links[linkString.toLowerCase()]; + if (!link) { + const text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text, + }; + } + return outputLink(cap, link, cap[0], this.lexer, this.rules); + } + } + emStrong(src, maskedSrc, prevChar = '') { + let match = this.rules.inline.emStrongLDelim.exec(src); + if (!match) + return; + // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well + if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) + return; + const nextChar = match[1] || match[2] || ''; + if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) { + // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below) + const lLength = [...match[0]].length - 1; + let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0; + const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + endReg.lastIndex = 0; + // Clip maskedSrc to same section of string as src (move to lexer?) + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) + continue; // skip single * in __abc*abc__ + rLength = [...rDelim].length; + if (match[3] || match[4]) { // found another Left Delim + delimTotal += rLength; + continue; + } + else if (match[5] || match[6]) { // either Left or Right Delim + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; // CommonMark Emphasis Rules 9-10 + } + } + delimTotal -= rLength; + if (delimTotal > 0) + continue; // Haven't found enough closing delimiters + // Remove extra characters. *a*** -> *a* + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); + // char length can be >1 for unicode characters; + const lastCharLength = [...match[0]][0].length; + const raw = src.slice(0, lLength + match.index + lastCharLength + rLength); + // Create `em` if smallest delimiter has odd char count. *a*** + if (Math.min(lLength, rLength) % 2) { + const text = raw.slice(1, -1); + return { + type: 'em', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + // Create 'strong' if smallest delimiter has even char count. **a*** + const text = raw.slice(2, -2); + return { + type: 'strong', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + } + } + codespan(src) { + const cap = this.rules.inline.code.exec(src); + if (cap) { + let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' '); + const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text); + const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + return { + type: 'codespan', + raw: cap[0], + text, + }; + } + } + br(src) { + const cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: 'br', + raw: cap[0], + }; + } + } + del(src) { + const cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2], + tokens: this.lexer.inlineTokens(cap[2]), + }; + } + } + autolink(src) { + const cap = this.rules.inline.autolink.exec(src); + if (cap) { + let text, href; + if (cap[2] === '@') { + text = cap[1]; + href = 'mailto:' + text; + } + else { + text = cap[1]; + href = text; + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + url(src) { + let cap; + if (cap = this.rules.inline.url.exec(src)) { + let text, href; + if (cap[2] === '@') { + text = cap[0]; + href = 'mailto:' + text; + } + else { + // do extended autolink path validation + let prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? ''; + } while (prevCapZero !== cap[0]); + text = cap[0]; + if (cap[1] === 'www.') { + href = 'http://' + cap[0]; + } + else { + href = cap[0]; + } + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + inlineText(src) { + const cap = this.rules.inline.text.exec(src); + if (cap) { + const escaped = this.lexer.state.inRawBlock; + return { + type: 'text', + raw: cap[0], + text: cap[0], + escaped, + }; + } + } +} + +/** + * Block Lexer + */ +class _Lexer { + tokens; + options; + state; + tokenizer; + inlineQueue; + constructor(options) { + // TokenList cannot be created in one go + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || _defaults; + this.options.tokenizer = this.options.tokenizer || new _Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + this.tokenizer.lexer = this; + this.inlineQueue = []; + this.state = { + inLink: false, + inRawBlock: false, + top: true, + }; + const rules = { + other, + block: block.normal, + inline: inline.normal, + }; + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } + else if (this.options.gfm) { + rules.block = block.gfm; + if (this.options.breaks) { + rules.inline = inline.breaks; + } + else { + rules.inline = inline.gfm; + } + } + this.tokenizer.rules = rules; + } + /** + * Expose Rules + */ + static get rules() { + return { + block, + inline, + }; + } + /** + * Static Lex Method + */ + static lex(src, options) { + const lexer = new _Lexer(options); + return lexer.lex(src); + } + /** + * Static Lex Inline Method + */ + static lexInline(src, options) { + const lexer = new _Lexer(options); + return lexer.inlineTokens(src); + } + /** + * Preprocessing + */ + lex(src) { + src = src.replace(other.carriageReturn, '\n'); + this.blockTokens(src, this.tokens); + for (let i = 0; i < this.inlineQueue.length; i++) { + const next = this.inlineQueue[i]; + this.inlineTokens(next.src, next.tokens); + } + this.inlineQueue = []; + return this.tokens; + } + blockTokens(src, tokens = [], lastParagraphClipped = false) { + if (this.options.pedantic) { + src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, ''); + } + while (src) { + let token; + if (this.options.extensions?.block?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // newline + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.raw.length === 1 && lastToken !== undefined) { + // if there's a single \n as a spacer, it's terminating the last line, + // so move it there so that we don't get unnecessary paragraph tags + lastToken.raw += '\n'; + } + else { + tokens.push(token); + } + continue; + } + // code + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + // An indented code block cannot interrupt a paragraph. + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + // fences + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // heading + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // hr + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // blockquote + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // list + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // html + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // def + if (token = this.tokenizer.def(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.raw; + this.inlineQueue.at(-1).src = lastToken.text; + } + else if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title, + }; + } + continue; + } + // table (gfm) + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // lheading + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // top-level paragraph + // prevent paragraph consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startBlock) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startBlock.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) { + const lastToken = tokens.at(-1); + if (lastParagraphClipped && lastToken?.type === 'paragraph') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } + // text + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + this.state.top = true; + return tokens; + } + inline(src, tokens = []) { + this.inlineQueue.push({ src, tokens }); + return tokens; + } + /** + * Lexing/Compiling + */ + inlineTokens(src, tokens = []) { + // String with links masked to avoid interference with em and strong + let maskedSrc = src; + let match = null; + // Mask out reflinks + if (this.tokens.links) { + const links = Object.keys(this.tokens.links); + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + + '[' + 'a'.repeat(match[0].length - 2) + ']' + + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + // Mask out other blocks + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + // Mask out escaped characters + while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + } + let keepPrevChar = false; + let prevChar = ''; + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + keepPrevChar = false; + let token; + // extensions + if (this.options.extensions?.inline?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // escape + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // tag + if (token = this.tokenizer.tag(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // link + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // reflink, nolink + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.type === 'text' && lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + // em & strong + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // code + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // br + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // del (gfm) + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // autolink + if (token = this.tokenizer.autolink(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // url (gfm) + if (!this.state.inLink && (token = this.tokenizer.url(src))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // text + // prevent inlineText consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startInline) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startInline.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (token = this.tokenizer.inlineText(cutSrc)) { + src = src.substring(token.raw.length); + if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started + prevChar = token.raw.slice(-1); + } + keepPrevChar = true; + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + return tokens; + } +} + +/** + * Renderer + */ +class _Renderer { + options; + parser; // set by the parser + constructor(options) { + this.options = options || _defaults; + } + space(token) { + return ''; + } + code({ text, lang, escaped }) { + const langString = (lang || '').match(other.notSpaceStart)?.[0]; + const code = text.replace(other.endingNewline, '') + '\n'; + if (!langString) { + return '
    '
    +                + (escaped ? code : escape(code, true))
    +                + '
    \n'; + } + return '
    '
    +            + (escaped ? code : escape(code, true))
    +            + '
    \n'; + } + blockquote({ tokens }) { + const body = this.parser.parse(tokens); + return `
    \n${body}
    \n`; + } + html({ text }) { + return text; + } + heading({ tokens, depth }) { + return `${this.parser.parseInline(tokens)}\n`; + } + hr(token) { + return '
    \n'; + } + list(token) { + const ordered = token.ordered; + const start = token.start; + let body = ''; + for (let j = 0; j < token.items.length; j++) { + const item = token.items[j]; + body += this.listitem(item); + } + const type = ordered ? 'ol' : 'ul'; + const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startAttr + '>\n' + body + '\n'; + } + listitem(item) { + let itemBody = ''; + if (item.task) { + const checkbox = this.checkbox({ checked: !!item.checked }); + if (item.loose) { + if (item.tokens[0]?.type === 'paragraph') { + item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text); + item.tokens[0].tokens[0].escaped = true; + } + } + else { + item.tokens.unshift({ + type: 'text', + raw: checkbox + ' ', + text: checkbox + ' ', + escaped: true, + }); + } + } + else { + itemBody += checkbox + ' '; + } + } + itemBody += this.parser.parse(item.tokens, !!item.loose); + return `
  • ${itemBody}
  • \n`; + } + checkbox({ checked }) { + return ''; + } + paragraph({ tokens }) { + return `

    ${this.parser.parseInline(tokens)}

    \n`; + } + table(token) { + let header = ''; + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + body += this.tablerow({ text: cell }); + } + if (body) + body = `${body}`; + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; + } + tablerow({ text }) { + return `\n${text}\n`; + } + tablecell(token) { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + } + /** + * span level renderer + */ + strong({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + em({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + codespan({ text }) { + return `${escape(text, true)}`; + } + br(token) { + return '
    '; + } + del({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + link({ href, title, tokens }) { + const text = this.parser.parseInline(tokens); + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return text; + } + href = cleanHref; + let out = '
    '; + return out; + } + image({ href, title, text }) { + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return escape(text); + } + href = cleanHref; + let out = `${text} { + const tokens = genericToken[childTokens].flat(Infinity); + values = values.concat(this.walkTokens(tokens, callback)); + }); + } + else if (genericToken.tokens) { + values = values.concat(this.walkTokens(genericToken.tokens, callback)); + } + } + } + } + return values; + } + use(...args) { + const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} }; + args.forEach((pack) => { + // copy options to new object + const opts = { ...pack }; + // set async to true if it was set to true before + opts.async = this.defaults.async || opts.async || false; + // ==-- Parse "addon" extensions --== // + if (pack.extensions) { + pack.extensions.forEach((ext) => { + if (!ext.name) { + throw new Error('extension name required'); + } + if ('renderer' in ext) { // Renderer extensions + const prevRenderer = extensions.renderers[ext.name]; + if (prevRenderer) { + // Replace extension with func to run new extension but fall back if false + extensions.renderers[ext.name] = function (...args) { + let ret = ext.renderer.apply(this, args); + if (ret === false) { + ret = prevRenderer.apply(this, args); + } + return ret; + }; + } + else { + extensions.renderers[ext.name] = ext.renderer; + } + } + if ('tokenizer' in ext) { // Tokenizer Extensions + if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) { + throw new Error("extension level must be 'block' or 'inline'"); + } + const extLevel = extensions[ext.level]; + if (extLevel) { + extLevel.unshift(ext.tokenizer); + } + else { + extensions[ext.level] = [ext.tokenizer]; + } + if (ext.start) { // Function to check for start of token + if (ext.level === 'block') { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } + else { + extensions.startBlock = [ext.start]; + } + } + else if (ext.level === 'inline') { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } + else { + extensions.startInline = [ext.start]; + } + } + } + } + if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + opts.extensions = extensions; + } + // ==-- Parse "overwrite" extensions --== // + if (pack.renderer) { + const renderer = this.defaults.renderer || new _Renderer(this.defaults); + for (const prop in pack.renderer) { + if (!(prop in renderer)) { + throw new Error(`renderer '${prop}' does not exist`); + } + if (['options', 'parser'].includes(prop)) { + // ignore options property + continue; + } + const rendererProp = prop; + const rendererFunc = pack.renderer[rendererProp]; + const prevRenderer = renderer[rendererProp]; + // Replace renderer with func to run extension, but fall back if false + renderer[rendererProp] = (...args) => { + let ret = rendererFunc.apply(renderer, args); + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + return ret || ''; + }; + } + opts.renderer = renderer; + } + if (pack.tokenizer) { + const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults); + for (const prop in pack.tokenizer) { + if (!(prop in tokenizer)) { + throw new Error(`tokenizer '${prop}' does not exist`); + } + if (['options', 'rules', 'lexer'].includes(prop)) { + // ignore options, rules, and lexer properties + continue; + } + const tokenizerProp = prop; + const tokenizerFunc = pack.tokenizer[tokenizerProp]; + const prevTokenizer = tokenizer[tokenizerProp]; + // Replace tokenizer with func to run extension, but fall back if false + // @ts-expect-error cannot type tokenizer function dynamically + tokenizer[tokenizerProp] = (...args) => { + let ret = tokenizerFunc.apply(tokenizer, args); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + return ret; + }; + } + opts.tokenizer = tokenizer; + } + // ==-- Parse Hooks extensions --== // + if (pack.hooks) { + const hooks = this.defaults.hooks || new _Hooks(); + for (const prop in pack.hooks) { + if (!(prop in hooks)) { + throw new Error(`hook '${prop}' does not exist`); + } + if (['options', 'block'].includes(prop)) { + // ignore options and block properties + continue; + } + const hooksProp = prop; + const hooksFunc = pack.hooks[hooksProp]; + const prevHook = hooks[hooksProp]; + if (_Hooks.passThroughHooks.has(prop)) { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (arg) => { + if (this.defaults.async) { + return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => { + return prevHook.call(hooks, ret); + }); + } + const ret = hooksFunc.call(hooks, arg); + return prevHook.call(hooks, ret); + }; + } + else { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (...args) => { + let ret = hooksFunc.apply(hooks, args); + if (ret === false) { + ret = prevHook.apply(hooks, args); + } + return ret; + }; + } + } + opts.hooks = hooks; + } + // ==-- Parse WalkTokens extensions --== // + if (pack.walkTokens) { + const walkTokens = this.defaults.walkTokens; + const packWalktokens = pack.walkTokens; + opts.walkTokens = function (token) { + let values = []; + values.push(packWalktokens.call(this, token)); + if (walkTokens) { + values = values.concat(walkTokens.call(this, token)); + } + return values; + }; + } + this.defaults = { ...this.defaults, ...opts }; + }); + return this; + } + setOptions(opt) { + this.defaults = { ...this.defaults, ...opt }; + return this; + } + lexer(src, options) { + return _Lexer.lex(src, options ?? this.defaults); + } + parser(tokens, options) { + return _Parser.parse(tokens, options ?? this.defaults); + } + parseMarkdown(blockType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parse = (src, options) => { + const origOpt = { ...options }; + const opt = { ...this.defaults, ...origOpt }; + const throwError = this.onError(!!opt.silent, !!opt.async); + // throw error if an extension set async to true but parse was called with async: false + if (this.defaults.async === true && origOpt.async === false) { + return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.')); + } + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + return throwError(new Error('marked(): input parameter is undefined or null')); + } + if (typeof src !== 'string') { + return throwError(new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected')); + } + if (opt.hooks) { + opt.hooks.options = opt; + opt.hooks.block = blockType; + } + const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline); + const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline); + if (opt.async) { + return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src) + .then(src => lexer(src, opt)) + .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens) + .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens) + .then(tokens => parser(tokens, opt)) + .then(html => opt.hooks ? opt.hooks.postprocess(html) : html) + .catch(throwError); + } + try { + if (opt.hooks) { + src = opt.hooks.preprocess(src); + } + let tokens = lexer(src, opt); + if (opt.hooks) { + tokens = opt.hooks.processAllTokens(tokens); + } + if (opt.walkTokens) { + this.walkTokens(tokens, opt.walkTokens); + } + let html = parser(tokens, opt); + if (opt.hooks) { + html = opt.hooks.postprocess(html); + } + return html; + } + catch (e) { + return throwError(e); + } + }; + return parse; + } + onError(silent, async) { + return (e) => { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (silent) { + const msg = '

    An error occurred:

    '
    +                    + escape(e.message + '', true)
    +                    + '
    '; + if (async) { + return Promise.resolve(msg); + } + return msg; + } + if (async) { + return Promise.reject(e); + } + throw e; + }; + } +} + +const markedInstance = new Marked(); +function marked(src, opt) { + return markedInstance.parse(src, opt); +} +/** + * Sets the default options. + * + * @param options Hash of options + */ +marked.options = + marked.setOptions = function (options) { + markedInstance.setOptions(options); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; + }; +/** + * Gets the original marked default options. + */ +marked.getDefaults = _getDefaults; +marked.defaults = _defaults; +/** + * Use Extension + */ +marked.use = function (...args) { + markedInstance.use(...args); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; +}; +/** + * Run callback for every token + */ +marked.walkTokens = function (tokens, callback) { + return markedInstance.walkTokens(tokens, callback); +}; +/** + * Compiles markdown to HTML without enclosing `p` tag. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @return String of compiled HTML + */ +marked.parseInline = markedInstance.parseInline; +/** + * Expose + */ +marked.Parser = _Parser; +marked.parser = _Parser.parse; +marked.Renderer = _Renderer; +marked.TextRenderer = _TextRenderer; +marked.Lexer = _Lexer; +marked.lexer = _Lexer.lex; +marked.Tokenizer = _Tokenizer; +marked.Hooks = _Hooks; +marked.parse = marked; +const options = marked.options; +const setOptions = marked.setOptions; +const use = marked.use; +const walkTokens = marked.walkTokens; +const parseInline = marked.parseInline; +const parse = marked; +const parser = _Parser.parse; +const lexer = _Lexer.lex; + +export { _Hooks as Hooks, _Lexer as Lexer, Marked, _Parser as Parser, _Renderer as Renderer, _TextRenderer as TextRenderer, _Tokenizer as Tokenizer, _defaults as defaults, _getDefaults as getDefaults, lexer, marked, options, parse, parseInline, parser, setOptions, use, walkTokens }; +//# sourceMappingURL=marked.esm.js.map diff --git a/docs/node_modules/marked/lib/marked.esm.js.map b/docs/node_modules/marked/lib/marked.esm.js.map new file mode 100644 index 00000000..2a864c8b --- /dev/null +++ b/docs/node_modules/marked/lib/marked.esm.js.map @@ -0,0 +1 @@ +{"version":3,"file":"marked.esm.js","sources":["../src/defaults.ts","../src/rules.ts","../src/helpers.ts","../src/Tokenizer.ts","../src/Lexer.ts","../src/Renderer.ts","../src/TextRenderer.ts","../src/Parser.ts","../src/Hooks.ts","../src/Instance.ts","../src/marked.ts"],"sourcesContent":["/**\n * Gets the original marked default options.\n */\nexport function _getDefaults() {\n return {\n async: false,\n breaks: false,\n extensions: null,\n gfm: true,\n hooks: null,\n pedantic: false,\n renderer: null,\n silent: false,\n tokenizer: null,\n walkTokens: null,\n };\n}\nexport let _defaults = _getDefaults();\nexport function changeDefaults(newDefaults) {\n _defaults = newDefaults;\n}\n","const noopTest = { exec: () => null };\nfunction edit(regex, opt = '') {\n let source = typeof regex === 'string' ? regex : regex.source;\n const obj = {\n replace: (name, val) => {\n let valSource = typeof val === 'string' ? val : val.source;\n valSource = valSource.replace(other.caret, '$1');\n source = source.replace(name, valSource);\n return obj;\n },\n getRegex: () => {\n return new RegExp(source, opt);\n },\n };\n return obj;\n}\nexport const other = {\n codeRemoveIndent: /^(?: {1,4}| {0,3}\\t)/gm,\n outputLinkReplace: /\\\\([\\[\\]])/g,\n indentCodeCompensation: /^(\\s+)(?:```)/,\n beginningSpace: /^\\s+/,\n endingHash: /#$/,\n startingSpaceChar: /^ /,\n endingSpaceChar: / $/,\n nonSpaceChar: /[^ ]/,\n newLineCharGlobal: /\\n/g,\n tabCharGlobal: /\\t/g,\n multipleSpaceGlobal: /\\s+/g,\n blankLine: /^[ \\t]*$/,\n doubleBlankLine: /\\n[ \\t]*\\n[ \\t]*$/,\n blockquoteStart: /^ {0,3}>/,\n blockquoteSetextReplace: /\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,\n blockquoteSetextReplace2: /^ {0,3}>[ \\t]?/gm,\n listReplaceTabs: /^\\t+/,\n listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,\n listIsTask: /^\\[[ xX]\\] /,\n listReplaceTask: /^\\[[ xX]\\] +/,\n anyLine: /\\n.*\\n/,\n hrefBrackets: /^<(.*)>$/,\n tableDelimiter: /[:|]/,\n tableAlignChars: /^\\||\\| *$/g,\n tableRowBlankLine: /\\n[ \\t]*$/,\n tableAlignRight: /^ *-+: *$/,\n tableAlignCenter: /^ *:-+: *$/,\n tableAlignLeft: /^ *:-+ *$/,\n startATag: /^
    /i,\n startPreScriptTag: /^<(pre|code|kbd|script)(\\s|>)/i,\n endPreScriptTag: /^<\\/(pre|code|kbd|script)(\\s|>)/i,\n startAngleBracket: /^$/,\n pedanticHrefTitle: /^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,\n unicodeAlphaNumeric: /[\\p{L}\\p{N}]/u,\n escapeTest: /[&<>\"']/,\n escapeReplace: /[&<>\"']/g,\n escapeTestNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,\n escapeReplaceNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,\n unescapeTest: /&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,\n caret: /(^|[^\\[])\\^/g,\n percentDecode: /%25/g,\n findPipe: /\\|/g,\n splitPipe: / \\|/,\n slashPipe: /\\\\\\|/g,\n carriageReturn: /\\r\\n|\\r/g,\n spaceLine: /^ +$/gm,\n notSpaceStart: /^\\S*/,\n endingNewline: /\\n$/,\n listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\\t ][^\\\\n]*)?(?:\\\\n|$))`),\n nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \\t][^\\\\n]*)?(?:\\\\n|$))`),\n hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),\n fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\\`\\`\\`|~~~)`),\n headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),\n htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'),\n};\n/**\n * Block-Level Grammar\n */\nconst newline = /^(?:[ \\t]*(?:\\n|$))+/;\nconst blockCode = /^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/;\nconst fences = /^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/;\nconst hr = /^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/;\nconst heading = /^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/;\nconst bullet = /(?:[*+-]|\\d{1,9}[.)])/;\nconst lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/)\n .replace(/bull/g, bullet) // lists can interrupt\n .replace(/blockCode/g, /(?: {4}| {0,3}\\t)/) // indented code blocks can interrupt\n .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n .getRegex();\nconst _paragraph = /^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/;\nconst blockText = /^[^\\n]+/;\nconst _blockLabel = /(?!\\s*\\])(?:\\\\.|[^\\[\\]\\\\])+/;\nconst def = edit(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/)\n .replace('label', _blockLabel)\n .replace('title', /(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/)\n .getRegex();\nconst list = edit(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/)\n .replace(/bull/g, bullet)\n .getRegex();\nconst _tag = 'address|article|aside|base|basefont|blockquote|body|caption'\n + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'\n + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'\n + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'\n + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title'\n + '|tr|track|ul';\nconst _comment = /|$))/;\nconst html = edit('^ {0,3}(?:' // optional indentation\n + '<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:[^\\\\n]*\\\\n+|$)' // (1)\n + '|comment[^\\\\n]*(\\\\n+|$)' // (2)\n + '|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)' // (3)\n + '|\\\\n*|$)' // (4)\n + '|\\\\n*|$)' // (5)\n + '|)[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (6)\n + '|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) open tag\n + '|(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) closing tag\n + ')', 'i')\n .replace('comment', _comment)\n .replace('tag', _tag)\n .replace('attribute', / +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst paragraph = edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex();\nconst blockquote = edit(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/)\n .replace('paragraph', paragraph)\n .getRegex();\n/**\n * Normal Block Grammar\n */\nconst blockNormal = {\n blockquote,\n code: blockCode,\n def,\n fences,\n heading,\n hr,\n html,\n lheading,\n list,\n newline,\n paragraph,\n table: noopTest,\n text: blockText,\n};\n/**\n * GFM Block Grammar\n */\nconst gfmTable = edit('^ *([^\\\\n ].*)\\\\n' // Header\n + ' {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)' // Align\n + '(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)') // Cells\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('blockquote', ' {0,3}>')\n .replace('code', '(?: {4}| {0,3}\\t)[^\\\\n]')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // tables can be interrupted by type (6) html blocks\n .getRegex();\nconst blockGfm = {\n ...blockNormal,\n table: gfmTable,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('table', gfmTable) // interrupt paragraphs with table\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex(),\n};\n/**\n * Pedantic grammar (original John Gruber's loose markdown specification)\n */\nconst blockPedantic = {\n ...blockNormal,\n html: edit('^ *(?:comment *(?:\\\\n|\\\\s*$)'\n + '|<(tag)[\\\\s\\\\S]+? *(?:\\\\n{2,}|\\\\s*$)' // closed tag\n + '|\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))')\n .replace('comment', _comment)\n .replace(/tag/g, '(?!(?:'\n + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'\n + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'\n + '\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b')\n .getRegex(),\n def: /^ *\\[([^\\]]+)\\]: *]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,\n heading: /^(#{1,6})(.*)(?:\\n+|$)/,\n fences: noopTest, // fences not supported\n lheading: /^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' *#{1,6} *[^\\n]')\n .replace('lheading', lheading)\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('|fences', '')\n .replace('|list', '')\n .replace('|html', '')\n .replace('|tag', '')\n .getRegex(),\n};\n/**\n * Inline-Level Grammar\n */\nconst escape = /^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/;\nconst inlineCode = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst br = /^( {2,}|\\\\)\\n(?!\\s*$)/;\nconst inlineText = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\\nconst blockSkip = /\\[[^[\\]]*?\\]\\((?:\\\\.|[^\\\\\\(\\)]|\\((?:\\\\.|[^\\\\\\(\\)])*\\))*\\)|`[^`]*?`|<[^<>]*?>/g;\nconst emStrongLDelim = edit(/^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/, 'u')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)' // Skip orphan inside strong\n + '|[^*]+(?=[^*])' // Consume to delim\n + '|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)' // (1) #*** can only be a Right Delimiter\n + '|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter\n + '|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter\n + '|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)' // (4) ***# can only be Left Delimiter\n + '|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter\n + '|notPunctSpace(\\\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\n// (6) Not allowed for _\nconst emStrongRDelimUnd = edit('^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)' // Skip orphan inside strong\n + '|[^_]+(?=[^_])' // Consume to delim\n + '|(?!_)punct(_+)(?=[\\\\s]|$)' // (1) #___ can only be a Right Delimiter\n + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter\n + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter\n + '|[\\\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter\n + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst anyPunctuation = edit(/\\\\(punct)/, 'gu')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst autolink = edit(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/)\n .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/)\n .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/)\n .getRegex();\nconst _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();\nconst tag = edit('^comment'\n + '|^' // self-closing tag\n + '|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>' // open tag\n + '|^<\\\\?[\\\\s\\\\S]*?\\\\?>' // processing instruction, e.g. \n + '|^' // declaration, e.g. \n + '|^') // CDATA section\n .replace('comment', _inlineComment)\n .replace('attribute', /\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst _inlineLabel = /(?:\\[(?:\\\\.|[^\\[\\]\\\\])*\\]|\\\\.|`[^`]*`|[^\\[\\]\\\\`])*?/;\nconst link = edit(/^!?\\[(label)\\]\\(\\s*(href)(?:\\s+(title))?\\s*\\)/)\n .replace('label', _inlineLabel)\n .replace('href', /<(?:\\\\.|[^\\n<>\\\\])+>|[^\\s\\x00-\\x1f]*/)\n .replace('title', /\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/)\n .getRegex();\nconst reflink = edit(/^!?\\[(label)\\]\\[(ref)\\]/)\n .replace('label', _inlineLabel)\n .replace('ref', _blockLabel)\n .getRegex();\nconst nolink = edit(/^!?\\[(ref)\\](?:\\[\\])?/)\n .replace('ref', _blockLabel)\n .getRegex();\nconst reflinkSearch = edit('reflink|nolink(?!\\\\()', 'g')\n .replace('reflink', reflink)\n .replace('nolink', nolink)\n .getRegex();\n/**\n * Normal Inline Grammar\n */\nconst inlineNormal = {\n _backpedal: noopTest, // only used for GFM url\n anyPunctuation,\n autolink,\n blockSkip,\n br,\n code: inlineCode,\n del: noopTest,\n emStrongLDelim,\n emStrongRDelimAst,\n emStrongRDelimUnd,\n escape,\n link,\n nolink,\n punctuation,\n reflink,\n reflinkSearch,\n tag,\n text: inlineText,\n url: noopTest,\n};\n/**\n * Pedantic Inline Grammar\n */\nconst inlinePedantic = {\n ...inlineNormal,\n link: edit(/^!?\\[(label)\\]\\((.*?)\\)/)\n .replace('label', _inlineLabel)\n .getRegex(),\n reflink: edit(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/)\n .replace('label', _inlineLabel)\n .getRegex(),\n};\n/**\n * GFM Inline Grammar\n */\nconst inlineGfm = {\n ...inlineNormal,\n escape: edit(escape).replace('])', '~|])').getRegex(),\n url: edit(/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/, 'i')\n .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)\n .getRegex(),\n _backpedal: /(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,\n del: /^(~~?)(?=[^\\s~])((?:\\\\.|[^\\\\])*?(?:\\\\.|[^\\s~\\\\]))\\1(?=[^~]|$)/,\n text: /^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\': '>',\n '\"': '"',\n \"'\": ''',\n};\nconst getEscapeReplacement = (ch) => escapeReplacements[ch];\nexport function escape(html, encode) {\n if (encode) {\n if (other.escapeTest.test(html)) {\n return html.replace(other.escapeReplace, getEscapeReplacement);\n }\n }\n else {\n if (other.escapeTestNoEncode.test(html)) {\n return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);\n }\n }\n return html;\n}\nexport function unescape(html) {\n // explicitly match decimal, hex, and named HTML entities\n return html.replace(other.unescapeTest, (_, n) => {\n n = n.toLowerCase();\n if (n === 'colon')\n return ':';\n if (n.charAt(0) === '#') {\n return n.charAt(1) === 'x'\n ? String.fromCharCode(parseInt(n.substring(2), 16))\n : String.fromCharCode(+n.substring(1));\n }\n return '';\n });\n}\nexport function cleanUrl(href) {\n try {\n href = encodeURI(href).replace(other.percentDecode, '%');\n }\n catch {\n return null;\n }\n return href;\n}\nexport function splitCells(tableRow, count) {\n // ensure that every cell-delimiting pipe has a space\n // before it to distinguish it from an escaped pipe\n const row = tableRow.replace(other.findPipe, (match, offset, str) => {\n let escaped = false;\n let curr = offset;\n while (--curr >= 0 && str[curr] === '\\\\')\n escaped = !escaped;\n if (escaped) {\n // odd number of slashes means | is escaped\n // so we leave it alone\n return '|';\n }\n else {\n // add space before unescaped |\n return ' |';\n }\n }), cells = row.split(other.splitPipe);\n let i = 0;\n // First/last cell in a row cannot be empty if it has no leading/trailing pipe\n if (!cells[0].trim()) {\n cells.shift();\n }\n if (cells.length > 0 && !cells.at(-1)?.trim()) {\n cells.pop();\n }\n if (count) {\n if (cells.length > count) {\n cells.splice(count);\n }\n else {\n while (cells.length < count)\n cells.push('');\n }\n }\n for (; i < cells.length; i++) {\n // leading or trailing whitespace is ignored per the gfm spec\n cells[i] = cells[i].trim().replace(other.slashPipe, '|');\n }\n return cells;\n}\n/**\n * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').\n * /c*$/ is vulnerable to REDOS.\n *\n * @param str\n * @param c\n * @param invert Remove suffix of non-c chars instead. Default falsey.\n */\nexport function rtrim(str, c, invert) {\n const l = str.length;\n if (l === 0) {\n return '';\n }\n // Length of suffix matching the invert condition.\n let suffLen = 0;\n // Step left until we fail to match the invert condition.\n while (suffLen < l) {\n const currChar = str.charAt(l - suffLen - 1);\n if (currChar === c && !invert) {\n suffLen++;\n }\n else if (currChar !== c && invert) {\n suffLen++;\n }\n else {\n break;\n }\n }\n return str.slice(0, l - suffLen);\n}\nexport function findClosingBracket(str, b) {\n if (str.indexOf(b[1]) === -1) {\n return -1;\n }\n let level = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '\\\\') {\n i++;\n }\n else if (str[i] === b[0]) {\n level++;\n }\n else if (str[i] === b[1]) {\n level--;\n if (level < 0) {\n return i;\n }\n }\n }\n return -1;\n}\n","import { _defaults } from './defaults.ts';\nimport { rtrim, splitCells, findClosingBracket, } from './helpers.ts';\nfunction outputLink(cap, link, raw, lexer, rules) {\n const href = link.href;\n const title = link.title || null;\n const text = cap[1].replace(rules.other.outputLinkReplace, '$1');\n if (cap[0].charAt(0) !== '!') {\n lexer.state.inLink = true;\n const token = {\n type: 'link',\n raw,\n href,\n title,\n text,\n tokens: lexer.inlineTokens(text),\n };\n lexer.state.inLink = false;\n return token;\n }\n return {\n type: 'image',\n raw,\n href,\n title,\n text,\n };\n}\nfunction indentCodeCompensation(raw, text, rules) {\n const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);\n if (matchIndentToCode === null) {\n return text;\n }\n const indentToCode = matchIndentToCode[1];\n return text\n .split('\\n')\n .map(node => {\n const matchIndentInNode = node.match(rules.other.beginningSpace);\n if (matchIndentInNode === null) {\n return node;\n }\n const [indentInNode] = matchIndentInNode;\n if (indentInNode.length >= indentToCode.length) {\n return node.slice(indentToCode.length);\n }\n return node;\n })\n .join('\\n');\n}\n/**\n * Tokenizer\n */\nexport class _Tokenizer {\n options;\n rules; // set by the lexer\n lexer; // set by the lexer\n constructor(options) {\n this.options = options || _defaults;\n }\n space(src) {\n const cap = this.rules.block.newline.exec(src);\n if (cap && cap[0].length > 0) {\n return {\n type: 'space',\n raw: cap[0],\n };\n }\n }\n code(src) {\n const cap = this.rules.block.code.exec(src);\n if (cap) {\n const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');\n return {\n type: 'code',\n raw: cap[0],\n codeBlockStyle: 'indented',\n text: !this.options.pedantic\n ? rtrim(text, '\\n')\n : text,\n };\n }\n }\n fences(src) {\n const cap = this.rules.block.fences.exec(src);\n if (cap) {\n const raw = cap[0];\n const text = indentCodeCompensation(raw, cap[3] || '', this.rules);\n return {\n type: 'code',\n raw,\n lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],\n text,\n };\n }\n }\n heading(src) {\n const cap = this.rules.block.heading.exec(src);\n if (cap) {\n let text = cap[2].trim();\n // remove trailing #s\n if (this.rules.other.endingHash.test(text)) {\n const trimmed = rtrim(text, '#');\n if (this.options.pedantic) {\n text = trimmed.trim();\n }\n else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {\n // CommonMark requires space before trailing #s\n text = trimmed.trim();\n }\n }\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[1].length,\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n hr(src) {\n const cap = this.rules.block.hr.exec(src);\n if (cap) {\n return {\n type: 'hr',\n raw: rtrim(cap[0], '\\n'),\n };\n }\n }\n blockquote(src) {\n const cap = this.rules.block.blockquote.exec(src);\n if (cap) {\n let lines = rtrim(cap[0], '\\n').split('\\n');\n let raw = '';\n let text = '';\n const tokens = [];\n while (lines.length > 0) {\n let inBlockquote = false;\n const currentLines = [];\n let i;\n for (i = 0; i < lines.length; i++) {\n // get lines up to a continuation\n if (this.rules.other.blockquoteStart.test(lines[i])) {\n currentLines.push(lines[i]);\n inBlockquote = true;\n }\n else if (!inBlockquote) {\n currentLines.push(lines[i]);\n }\n else {\n break;\n }\n }\n lines = lines.slice(i);\n const currentRaw = currentLines.join('\\n');\n const currentText = currentRaw\n // precede setext continuation with 4 spaces so it isn't a setext\n .replace(this.rules.other.blockquoteSetextReplace, '\\n $1')\n .replace(this.rules.other.blockquoteSetextReplace2, '');\n raw = raw ? `${raw}\\n${currentRaw}` : currentRaw;\n text = text ? `${text}\\n${currentText}` : currentText;\n // parse blockquote lines as top level tokens\n // merge paragraphs if this is a continuation\n const top = this.lexer.state.top;\n this.lexer.state.top = true;\n this.lexer.blockTokens(currentText, tokens, true);\n this.lexer.state.top = top;\n // if there is no continuation then we are done\n if (lines.length === 0) {\n break;\n }\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'code') {\n // blockquote continuation cannot be preceded by a code block\n break;\n }\n else if (lastToken?.type === 'blockquote') {\n // include continuation in nested blockquote\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.blockquote(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.text.length) + newToken.text;\n break;\n }\n else if (lastToken?.type === 'list') {\n // include continuation in nested list\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.list(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;\n lines = newText.substring(tokens.at(-1).raw.length).split('\\n');\n continue;\n }\n }\n return {\n type: 'blockquote',\n raw,\n tokens,\n text,\n };\n }\n }\n list(src) {\n let cap = this.rules.block.list.exec(src);\n if (cap) {\n let bull = cap[1].trim();\n const isordered = bull.length > 1;\n const list = {\n type: 'list',\n raw: '',\n ordered: isordered,\n start: isordered ? +bull.slice(0, -1) : '',\n loose: false,\n items: [],\n };\n bull = isordered ? `\\\\d{1,9}\\\\${bull.slice(-1)}` : `\\\\${bull}`;\n if (this.options.pedantic) {\n bull = isordered ? bull : '[*+-]';\n }\n // Get next list item\n const itemRegex = this.rules.other.listItemRegex(bull);\n let endsWithBlankLine = false;\n // Check if current bullet point can start a new List Item\n while (src) {\n let endEarly = false;\n let raw = '';\n let itemContents = '';\n if (!(cap = itemRegex.exec(src))) {\n break;\n }\n if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)\n break;\n }\n raw = cap[0];\n src = src.substring(raw.length);\n let line = cap[2].split('\\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length));\n let nextLine = src.split('\\n', 1)[0];\n let blankLine = !line.trim();\n let indent = 0;\n if (this.options.pedantic) {\n indent = 2;\n itemContents = line.trimStart();\n }\n else if (blankLine) {\n indent = cap[1].length + 1;\n }\n else {\n indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char\n indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent\n itemContents = line.slice(indent);\n indent += cap[1].length;\n }\n if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line\n raw += nextLine + '\\n';\n src = src.substring(nextLine.length + 1);\n endEarly = true;\n }\n if (!endEarly) {\n const nextBulletRegex = this.rules.other.nextBulletRegex(indent);\n const hrRegex = this.rules.other.hrRegex(indent);\n const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);\n const headingBeginRegex = this.rules.other.headingBeginRegex(indent);\n const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);\n // Check if following lines should be included in List Item\n while (src) {\n const rawLine = src.split('\\n', 1)[0];\n let nextLineWithoutTabs;\n nextLine = rawLine;\n // Re-align to follow commonmark nesting rules\n if (this.options.pedantic) {\n nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' ');\n nextLineWithoutTabs = nextLine;\n }\n else {\n nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' ');\n }\n // End list item if found code fences\n if (fencesBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new heading\n if (headingBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of html block\n if (htmlBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new bullet\n if (nextBulletRegex.test(nextLine)) {\n break;\n }\n // Horizontal rule found\n if (hrRegex.test(nextLine)) {\n break;\n }\n if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible\n itemContents += '\\n' + nextLineWithoutTabs.slice(indent);\n }\n else {\n // not enough indentation\n if (blankLine) {\n break;\n }\n // paragraph continuation unless last line was a different block level element\n if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block\n break;\n }\n if (fencesBeginRegex.test(line)) {\n break;\n }\n if (headingBeginRegex.test(line)) {\n break;\n }\n if (hrRegex.test(line)) {\n break;\n }\n itemContents += '\\n' + nextLine;\n }\n if (!blankLine && !nextLine.trim()) { // Check if current line is blank\n blankLine = true;\n }\n raw += rawLine + '\\n';\n src = src.substring(rawLine.length + 1);\n line = nextLineWithoutTabs.slice(indent);\n }\n }\n if (!list.loose) {\n // If the previous item ended with a blank line, the list is loose\n if (endsWithBlankLine) {\n list.loose = true;\n }\n else if (this.rules.other.doubleBlankLine.test(raw)) {\n endsWithBlankLine = true;\n }\n }\n let istask = null;\n let ischecked;\n // Check for task list items\n if (this.options.gfm) {\n istask = this.rules.other.listIsTask.exec(itemContents);\n if (istask) {\n ischecked = istask[0] !== '[ ] ';\n itemContents = itemContents.replace(this.rules.other.listReplaceTask, '');\n }\n }\n list.items.push({\n type: 'list_item',\n raw,\n task: !!istask,\n checked: ischecked,\n loose: false,\n text: itemContents,\n tokens: [],\n });\n list.raw += raw;\n }\n // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic\n const lastItem = list.items.at(-1);\n if (lastItem) {\n lastItem.raw = lastItem.raw.trimEnd();\n lastItem.text = lastItem.text.trimEnd();\n }\n list.raw = list.raw.trimEnd();\n // Item child tokens handled here at end because we needed to have the final item to trim it first\n for (let i = 0; i < list.items.length; i++) {\n this.lexer.state.top = false;\n list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);\n if (!list.loose) {\n // Check if list should be loose\n const spacers = list.items[i].tokens.filter(t => t.type === 'space');\n const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw));\n list.loose = hasMultipleLineBreaks;\n }\n }\n // Set all items to loose if list is loose\n if (list.loose) {\n for (let i = 0; i < list.items.length; i++) {\n list.items[i].loose = true;\n }\n }\n return list;\n }\n }\n html(src) {\n const cap = this.rules.block.html.exec(src);\n if (cap) {\n const token = {\n type: 'html',\n block: true,\n raw: cap[0],\n pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',\n text: cap[0],\n };\n return token;\n }\n }\n def(src) {\n const cap = this.rules.block.def.exec(src);\n if (cap) {\n const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' ');\n const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';\n const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];\n return {\n type: 'def',\n tag,\n raw: cap[0],\n href,\n title,\n };\n }\n }\n table(src) {\n const cap = this.rules.block.table.exec(src);\n if (!cap) {\n return;\n }\n if (!this.rules.other.tableDelimiter.test(cap[2])) {\n // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading\n return;\n }\n const headers = splitCells(cap[1]);\n const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');\n const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\\n') : [];\n const item = {\n type: 'table',\n raw: cap[0],\n header: [],\n align: [],\n rows: [],\n };\n if (headers.length !== aligns.length) {\n // header and align columns must be equal, rows can be different.\n return;\n }\n for (const align of aligns) {\n if (this.rules.other.tableAlignRight.test(align)) {\n item.align.push('right');\n }\n else if (this.rules.other.tableAlignCenter.test(align)) {\n item.align.push('center');\n }\n else if (this.rules.other.tableAlignLeft.test(align)) {\n item.align.push('left');\n }\n else {\n item.align.push(null);\n }\n }\n for (let i = 0; i < headers.length; i++) {\n item.header.push({\n text: headers[i],\n tokens: this.lexer.inline(headers[i]),\n header: true,\n align: item.align[i],\n });\n }\n for (const row of rows) {\n item.rows.push(splitCells(row, item.header.length).map((cell, i) => {\n return {\n text: cell,\n tokens: this.lexer.inline(cell),\n header: false,\n align: item.align[i],\n };\n }));\n }\n return item;\n }\n lheading(src) {\n const cap = this.rules.block.lheading.exec(src);\n if (cap) {\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[2].charAt(0) === '=' ? 1 : 2,\n text: cap[1],\n tokens: this.lexer.inline(cap[1]),\n };\n }\n }\n paragraph(src) {\n const cap = this.rules.block.paragraph.exec(src);\n if (cap) {\n const text = cap[1].charAt(cap[1].length - 1) === '\\n'\n ? cap[1].slice(0, -1)\n : cap[1];\n return {\n type: 'paragraph',\n raw: cap[0],\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n text(src) {\n const cap = this.rules.block.text.exec(src);\n if (cap) {\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n tokens: this.lexer.inline(cap[0]),\n };\n }\n }\n escape(src) {\n const cap = this.rules.inline.escape.exec(src);\n if (cap) {\n return {\n type: 'escape',\n raw: cap[0],\n text: cap[1],\n };\n }\n }\n tag(src) {\n const cap = this.rules.inline.tag.exec(src);\n if (cap) {\n if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {\n this.lexer.state.inLink = true;\n }\n else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {\n this.lexer.state.inLink = false;\n }\n if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = true;\n }\n else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = false;\n }\n return {\n type: 'html',\n raw: cap[0],\n inLink: this.lexer.state.inLink,\n inRawBlock: this.lexer.state.inRawBlock,\n block: false,\n text: cap[0],\n };\n }\n }\n link(src) {\n const cap = this.rules.inline.link.exec(src);\n if (cap) {\n const trimmedUrl = cap[2].trim();\n if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {\n // commonmark requires matching angle brackets\n if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n return;\n }\n // ending angle bracket cannot be escaped\n const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\\\');\n if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {\n return;\n }\n }\n else {\n // find closing parenthesis\n const lastParenIndex = findClosingBracket(cap[2], '()');\n if (lastParenIndex > -1) {\n const start = cap[0].indexOf('!') === 0 ? 5 : 4;\n const linkLen = start + cap[1].length + lastParenIndex;\n cap[2] = cap[2].substring(0, lastParenIndex);\n cap[0] = cap[0].substring(0, linkLen).trim();\n cap[3] = '';\n }\n }\n let href = cap[2];\n let title = '';\n if (this.options.pedantic) {\n // split pedantic href and title\n const link = this.rules.other.pedanticHrefTitle.exec(href);\n if (link) {\n href = link[1];\n title = link[3];\n }\n }\n else {\n title = cap[3] ? cap[3].slice(1, -1) : '';\n }\n href = href.trim();\n if (this.rules.other.startAngleBracket.test(href)) {\n if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n // pedantic allows starting angle bracket without ending angle bracket\n href = href.slice(1);\n }\n else {\n href = href.slice(1, -1);\n }\n }\n return outputLink(cap, {\n href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,\n title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title,\n }, cap[0], this.lexer, this.rules);\n }\n }\n reflink(src, links) {\n let cap;\n if ((cap = this.rules.inline.reflink.exec(src))\n || (cap = this.rules.inline.nolink.exec(src))) {\n const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' ');\n const link = links[linkString.toLowerCase()];\n if (!link) {\n const text = cap[0].charAt(0);\n return {\n type: 'text',\n raw: text,\n text,\n };\n }\n return outputLink(cap, link, cap[0], this.lexer, this.rules);\n }\n }\n emStrong(src, maskedSrc, prevChar = '') {\n let match = this.rules.inline.emStrongLDelim.exec(src);\n if (!match)\n return;\n // _ can't be between two alphanumerics. \\p{L}\\p{N} includes non-english alphabet/numbers as well\n if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric))\n return;\n const nextChar = match[1] || match[2] || '';\n if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {\n // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)\n const lLength = [...match[0]].length - 1;\n let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;\n const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;\n endReg.lastIndex = 0;\n // Clip maskedSrc to same section of string as src (move to lexer?)\n maskedSrc = maskedSrc.slice(-1 * src.length + lLength);\n while ((match = endReg.exec(maskedSrc)) != null) {\n rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];\n if (!rDelim)\n continue; // skip single * in __abc*abc__\n rLength = [...rDelim].length;\n if (match[3] || match[4]) { // found another Left Delim\n delimTotal += rLength;\n continue;\n }\n else if (match[5] || match[6]) { // either Left or Right Delim\n if (lLength % 3 && !((lLength + rLength) % 3)) {\n midDelimTotal += rLength;\n continue; // CommonMark Emphasis Rules 9-10\n }\n }\n delimTotal -= rLength;\n if (delimTotal > 0)\n continue; // Haven't found enough closing delimiters\n // Remove extra characters. *a*** -> *a*\n rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);\n // char length can be >1 for unicode characters;\n const lastCharLength = [...match[0]][0].length;\n const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);\n // Create `em` if smallest delimiter has odd char count. *a***\n if (Math.min(lLength, rLength) % 2) {\n const text = raw.slice(1, -1);\n return {\n type: 'em',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n // Create 'strong' if smallest delimiter has even char count. **a***\n const text = raw.slice(2, -2);\n return {\n type: 'strong',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n }\n }\n codespan(src) {\n const cap = this.rules.inline.code.exec(src);\n if (cap) {\n let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' ');\n const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);\n const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);\n if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {\n text = text.substring(1, text.length - 1);\n }\n return {\n type: 'codespan',\n raw: cap[0],\n text,\n };\n }\n }\n br(src) {\n const cap = this.rules.inline.br.exec(src);\n if (cap) {\n return {\n type: 'br',\n raw: cap[0],\n };\n }\n }\n del(src) {\n const cap = this.rules.inline.del.exec(src);\n if (cap) {\n return {\n type: 'del',\n raw: cap[0],\n text: cap[2],\n tokens: this.lexer.inlineTokens(cap[2]),\n };\n }\n }\n autolink(src) {\n const cap = this.rules.inline.autolink.exec(src);\n if (cap) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[1];\n href = 'mailto:' + text;\n }\n else {\n text = cap[1];\n href = text;\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n url(src) {\n let cap;\n if (cap = this.rules.inline.url.exec(src)) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[0];\n href = 'mailto:' + text;\n }\n else {\n // do extended autolink path validation\n let prevCapZero;\n do {\n prevCapZero = cap[0];\n cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';\n } while (prevCapZero !== cap[0]);\n text = cap[0];\n if (cap[1] === 'www.') {\n href = 'http://' + cap[0];\n }\n else {\n href = cap[0];\n }\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n inlineText(src) {\n const cap = this.rules.inline.text.exec(src);\n if (cap) {\n const escaped = this.lexer.state.inRawBlock;\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n escaped,\n };\n }\n }\n}\n","import { _Tokenizer } from './Tokenizer.ts';\nimport { _defaults } from './defaults.ts';\nimport { other, block, inline } from './rules.ts';\n/**\n * Block Lexer\n */\nexport class _Lexer {\n tokens;\n options;\n state;\n tokenizer;\n inlineQueue;\n constructor(options) {\n // TokenList cannot be created in one go\n this.tokens = [];\n this.tokens.links = Object.create(null);\n this.options = options || _defaults;\n this.options.tokenizer = this.options.tokenizer || new _Tokenizer();\n this.tokenizer = this.options.tokenizer;\n this.tokenizer.options = this.options;\n this.tokenizer.lexer = this;\n this.inlineQueue = [];\n this.state = {\n inLink: false,\n inRawBlock: false,\n top: true,\n };\n const rules = {\n other,\n block: block.normal,\n inline: inline.normal,\n };\n if (this.options.pedantic) {\n rules.block = block.pedantic;\n rules.inline = inline.pedantic;\n }\n else if (this.options.gfm) {\n rules.block = block.gfm;\n if (this.options.breaks) {\n rules.inline = inline.breaks;\n }\n else {\n rules.inline = inline.gfm;\n }\n }\n this.tokenizer.rules = rules;\n }\n /**\n * Expose Rules\n */\n static get rules() {\n return {\n block,\n inline,\n };\n }\n /**\n * Static Lex Method\n */\n static lex(src, options) {\n const lexer = new _Lexer(options);\n return lexer.lex(src);\n }\n /**\n * Static Lex Inline Method\n */\n static lexInline(src, options) {\n const lexer = new _Lexer(options);\n return lexer.inlineTokens(src);\n }\n /**\n * Preprocessing\n */\n lex(src) {\n src = src.replace(other.carriageReturn, '\\n');\n this.blockTokens(src, this.tokens);\n for (let i = 0; i < this.inlineQueue.length; i++) {\n const next = this.inlineQueue[i];\n this.inlineTokens(next.src, next.tokens);\n }\n this.inlineQueue = [];\n return this.tokens;\n }\n blockTokens(src, tokens = [], lastParagraphClipped = false) {\n if (this.options.pedantic) {\n src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');\n }\n while (src) {\n let token;\n if (this.options.extensions?.block?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // newline\n if (token = this.tokenizer.space(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.raw.length === 1 && lastToken !== undefined) {\n // if there's a single \\n as a spacer, it's terminating the last line,\n // so move it there so that we don't get unnecessary paragraph tags\n lastToken.raw += '\\n';\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // code\n if (token = this.tokenizer.code(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n // An indented code block cannot interrupt a paragraph.\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // fences\n if (token = this.tokenizer.fences(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // heading\n if (token = this.tokenizer.heading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // hr\n if (token = this.tokenizer.hr(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // blockquote\n if (token = this.tokenizer.blockquote(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // list\n if (token = this.tokenizer.list(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // html\n if (token = this.tokenizer.html(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // def\n if (token = this.tokenizer.def(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.raw;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else if (!this.tokens.links[token.tag]) {\n this.tokens.links[token.tag] = {\n href: token.href,\n title: token.title,\n };\n }\n continue;\n }\n // table (gfm)\n if (token = this.tokenizer.table(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // lheading\n if (token = this.tokenizer.lheading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // top-level paragraph\n // prevent paragraph consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startBlock) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startBlock.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {\n const lastToken = tokens.at(-1);\n if (lastParagraphClipped && lastToken?.type === 'paragraph') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n lastParagraphClipped = cutSrc.length !== src.length;\n src = src.substring(token.raw.length);\n continue;\n }\n // text\n if (token = this.tokenizer.text(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n this.state.top = true;\n return tokens;\n }\n inline(src, tokens = []) {\n this.inlineQueue.push({ src, tokens });\n return tokens;\n }\n /**\n * Lexing/Compiling\n */\n inlineTokens(src, tokens = []) {\n // String with links masked to avoid interference with em and strong\n let maskedSrc = src;\n let match = null;\n // Mask out reflinks\n if (this.tokens.links) {\n const links = Object.keys(this.tokens.links);\n if (links.length > 0) {\n while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {\n if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {\n maskedSrc = maskedSrc.slice(0, match.index)\n + '[' + 'a'.repeat(match[0].length - 2) + ']'\n + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);\n }\n }\n }\n }\n // Mask out other blocks\n while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);\n }\n // Mask out escaped characters\n while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);\n }\n let keepPrevChar = false;\n let prevChar = '';\n while (src) {\n if (!keepPrevChar) {\n prevChar = '';\n }\n keepPrevChar = false;\n let token;\n // extensions\n if (this.options.extensions?.inline?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // escape\n if (token = this.tokenizer.escape(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // tag\n if (token = this.tokenizer.tag(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // link\n if (token = this.tokenizer.link(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // reflink, nolink\n if (token = this.tokenizer.reflink(src, this.tokens.links)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.type === 'text' && lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // em & strong\n if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // code\n if (token = this.tokenizer.codespan(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // br\n if (token = this.tokenizer.br(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // del (gfm)\n if (token = this.tokenizer.del(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // autolink\n if (token = this.tokenizer.autolink(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // url (gfm)\n if (!this.state.inLink && (token = this.tokenizer.url(src))) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // text\n // prevent inlineText consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startInline) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startInline.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (token = this.tokenizer.inlineText(cutSrc)) {\n src = src.substring(token.raw.length);\n if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started\n prevChar = token.raw.slice(-1);\n }\n keepPrevChar = true;\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n return tokens;\n }\n}\n","import { _defaults } from './defaults.ts';\nimport { cleanUrl, escape, } from './helpers.ts';\nimport { other } from './rules.ts';\n/**\n * Renderer\n */\nexport class _Renderer {\n options;\n parser; // set by the parser\n constructor(options) {\n this.options = options || _defaults;\n }\n space(token) {\n return '';\n }\n code({ text, lang, escaped }) {\n const langString = (lang || '').match(other.notSpaceStart)?.[0];\n const code = text.replace(other.endingNewline, '') + '\\n';\n if (!langString) {\n return '
    '\n                + (escaped ? code : escape(code, true))\n                + '
    \\n';\n }\n return '
    '\n            + (escaped ? code : escape(code, true))\n            + '
    \\n';\n }\n blockquote({ tokens }) {\n const body = this.parser.parse(tokens);\n return `
    \\n${body}
    \\n`;\n }\n html({ text }) {\n return text;\n }\n heading({ tokens, depth }) {\n return `${this.parser.parseInline(tokens)}\\n`;\n }\n hr(token) {\n return '
    \\n';\n }\n list(token) {\n const ordered = token.ordered;\n const start = token.start;\n let body = '';\n for (let j = 0; j < token.items.length; j++) {\n const item = token.items[j];\n body += this.listitem(item);\n }\n const type = ordered ? 'ol' : 'ul';\n const startAttr = (ordered && start !== 1) ? (' start=\"' + start + '\"') : '';\n return '<' + type + startAttr + '>\\n' + body + '\\n';\n }\n listitem(item) {\n let itemBody = '';\n if (item.task) {\n const checkbox = this.checkbox({ checked: !!item.checked });\n if (item.loose) {\n if (item.tokens[0]?.type === 'paragraph') {\n item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;\n if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {\n item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);\n item.tokens[0].tokens[0].escaped = true;\n }\n }\n else {\n item.tokens.unshift({\n type: 'text',\n raw: checkbox + ' ',\n text: checkbox + ' ',\n escaped: true,\n });\n }\n }\n else {\n itemBody += checkbox + ' ';\n }\n }\n itemBody += this.parser.parse(item.tokens, !!item.loose);\n return `
  • ${itemBody}
  • \\n`;\n }\n checkbox({ checked }) {\n return '';\n }\n paragraph({ tokens }) {\n return `

    ${this.parser.parseInline(tokens)}

    \\n`;\n }\n table(token) {\n let header = '';\n // header\n let cell = '';\n for (let j = 0; j < token.header.length; j++) {\n cell += this.tablecell(token.header[j]);\n }\n header += this.tablerow({ text: cell });\n let body = '';\n for (let j = 0; j < token.rows.length; j++) {\n const row = token.rows[j];\n cell = '';\n for (let k = 0; k < row.length; k++) {\n cell += this.tablecell(row[k]);\n }\n body += this.tablerow({ text: cell });\n }\n if (body)\n body = `${body}`;\n return '\\n'\n + '\\n'\n + header\n + '\\n'\n + body\n + '
    \\n';\n }\n tablerow({ text }) {\n return `\\n${text}\\n`;\n }\n tablecell(token) {\n const content = this.parser.parseInline(token.tokens);\n const type = token.header ? 'th' : 'td';\n const tag = token.align\n ? `<${type} align=\"${token.align}\">`\n : `<${type}>`;\n return tag + content + `\\n`;\n }\n /**\n * span level renderer\n */\n strong({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n em({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n codespan({ text }) {\n return `${escape(text, true)}`;\n }\n br(token) {\n return '
    ';\n }\n del({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n link({ href, title, tokens }) {\n const text = this.parser.parseInline(tokens);\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return text;\n }\n href = cleanHref;\n let out = '
    ';\n return out;\n }\n image({ href, title, text }) {\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return escape(text);\n }\n href = cleanHref;\n let out = `\"${text}\"`;\n {\n const tokens = genericToken[childTokens].flat(Infinity);\n values = values.concat(this.walkTokens(tokens, callback));\n });\n }\n else if (genericToken.tokens) {\n values = values.concat(this.walkTokens(genericToken.tokens, callback));\n }\n }\n }\n }\n return values;\n }\n use(...args) {\n const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };\n args.forEach((pack) => {\n // copy options to new object\n const opts = { ...pack };\n // set async to true if it was set to true before\n opts.async = this.defaults.async || opts.async || false;\n // ==-- Parse \"addon\" extensions --== //\n if (pack.extensions) {\n pack.extensions.forEach((ext) => {\n if (!ext.name) {\n throw new Error('extension name required');\n }\n if ('renderer' in ext) { // Renderer extensions\n const prevRenderer = extensions.renderers[ext.name];\n if (prevRenderer) {\n // Replace extension with func to run new extension but fall back if false\n extensions.renderers[ext.name] = function (...args) {\n let ret = ext.renderer.apply(this, args);\n if (ret === false) {\n ret = prevRenderer.apply(this, args);\n }\n return ret;\n };\n }\n else {\n extensions.renderers[ext.name] = ext.renderer;\n }\n }\n if ('tokenizer' in ext) { // Tokenizer Extensions\n if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {\n throw new Error(\"extension level must be 'block' or 'inline'\");\n }\n const extLevel = extensions[ext.level];\n if (extLevel) {\n extLevel.unshift(ext.tokenizer);\n }\n else {\n extensions[ext.level] = [ext.tokenizer];\n }\n if (ext.start) { // Function to check for start of token\n if (ext.level === 'block') {\n if (extensions.startBlock) {\n extensions.startBlock.push(ext.start);\n }\n else {\n extensions.startBlock = [ext.start];\n }\n }\n else if (ext.level === 'inline') {\n if (extensions.startInline) {\n extensions.startInline.push(ext.start);\n }\n else {\n extensions.startInline = [ext.start];\n }\n }\n }\n }\n if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens\n extensions.childTokens[ext.name] = ext.childTokens;\n }\n });\n opts.extensions = extensions;\n }\n // ==-- Parse \"overwrite\" extensions --== //\n if (pack.renderer) {\n const renderer = this.defaults.renderer || new _Renderer(this.defaults);\n for (const prop in pack.renderer) {\n if (!(prop in renderer)) {\n throw new Error(`renderer '${prop}' does not exist`);\n }\n if (['options', 'parser'].includes(prop)) {\n // ignore options property\n continue;\n }\n const rendererProp = prop;\n const rendererFunc = pack.renderer[rendererProp];\n const prevRenderer = renderer[rendererProp];\n // Replace renderer with func to run extension, but fall back if false\n renderer[rendererProp] = (...args) => {\n let ret = rendererFunc.apply(renderer, args);\n if (ret === false) {\n ret = prevRenderer.apply(renderer, args);\n }\n return ret || '';\n };\n }\n opts.renderer = renderer;\n }\n if (pack.tokenizer) {\n const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);\n for (const prop in pack.tokenizer) {\n if (!(prop in tokenizer)) {\n throw new Error(`tokenizer '${prop}' does not exist`);\n }\n if (['options', 'rules', 'lexer'].includes(prop)) {\n // ignore options, rules, and lexer properties\n continue;\n }\n const tokenizerProp = prop;\n const tokenizerFunc = pack.tokenizer[tokenizerProp];\n const prevTokenizer = tokenizer[tokenizerProp];\n // Replace tokenizer with func to run extension, but fall back if false\n // @ts-expect-error cannot type tokenizer function dynamically\n tokenizer[tokenizerProp] = (...args) => {\n let ret = tokenizerFunc.apply(tokenizer, args);\n if (ret === false) {\n ret = prevTokenizer.apply(tokenizer, args);\n }\n return ret;\n };\n }\n opts.tokenizer = tokenizer;\n }\n // ==-- Parse Hooks extensions --== //\n if (pack.hooks) {\n const hooks = this.defaults.hooks || new _Hooks();\n for (const prop in pack.hooks) {\n if (!(prop in hooks)) {\n throw new Error(`hook '${prop}' does not exist`);\n }\n if (['options', 'block'].includes(prop)) {\n // ignore options and block properties\n continue;\n }\n const hooksProp = prop;\n const hooksFunc = pack.hooks[hooksProp];\n const prevHook = hooks[hooksProp];\n if (_Hooks.passThroughHooks.has(prop)) {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (arg) => {\n if (this.defaults.async) {\n return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {\n return prevHook.call(hooks, ret);\n });\n }\n const ret = hooksFunc.call(hooks, arg);\n return prevHook.call(hooks, ret);\n };\n }\n else {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (...args) => {\n let ret = hooksFunc.apply(hooks, args);\n if (ret === false) {\n ret = prevHook.apply(hooks, args);\n }\n return ret;\n };\n }\n }\n opts.hooks = hooks;\n }\n // ==-- Parse WalkTokens extensions --== //\n if (pack.walkTokens) {\n const walkTokens = this.defaults.walkTokens;\n const packWalktokens = pack.walkTokens;\n opts.walkTokens = function (token) {\n let values = [];\n values.push(packWalktokens.call(this, token));\n if (walkTokens) {\n values = values.concat(walkTokens.call(this, token));\n }\n return values;\n };\n }\n this.defaults = { ...this.defaults, ...opts };\n });\n return this;\n }\n setOptions(opt) {\n this.defaults = { ...this.defaults, ...opt };\n return this;\n }\n lexer(src, options) {\n return _Lexer.lex(src, options ?? this.defaults);\n }\n parser(tokens, options) {\n return _Parser.parse(tokens, options ?? this.defaults);\n }\n parseMarkdown(blockType) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const parse = (src, options) => {\n const origOpt = { ...options };\n const opt = { ...this.defaults, ...origOpt };\n const throwError = this.onError(!!opt.silent, !!opt.async);\n // throw error if an extension set async to true but parse was called with async: false\n if (this.defaults.async === true && origOpt.async === false) {\n return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.'));\n }\n // throw error in case of non string input\n if (typeof src === 'undefined' || src === null) {\n return throwError(new Error('marked(): input parameter is undefined or null'));\n }\n if (typeof src !== 'string') {\n return throwError(new Error('marked(): input parameter is of type '\n + Object.prototype.toString.call(src) + ', string expected'));\n }\n if (opt.hooks) {\n opt.hooks.options = opt;\n opt.hooks.block = blockType;\n }\n const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline);\n const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline);\n if (opt.async) {\n return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)\n .then(src => lexer(src, opt))\n .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens)\n .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)\n .then(tokens => parser(tokens, opt))\n .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)\n .catch(throwError);\n }\n try {\n if (opt.hooks) {\n src = opt.hooks.preprocess(src);\n }\n let tokens = lexer(src, opt);\n if (opt.hooks) {\n tokens = opt.hooks.processAllTokens(tokens);\n }\n if (opt.walkTokens) {\n this.walkTokens(tokens, opt.walkTokens);\n }\n let html = parser(tokens, opt);\n if (opt.hooks) {\n html = opt.hooks.postprocess(html);\n }\n return html;\n }\n catch (e) {\n return throwError(e);\n }\n };\n return parse;\n }\n onError(silent, async) {\n return (e) => {\n e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n if (silent) {\n const msg = '

    An error occurred:

    '\n                    + escape(e.message + '', true)\n                    + '
    ';\n if (async) {\n return Promise.resolve(msg);\n }\n return msg;\n }\n if (async) {\n return Promise.reject(e);\n }\n throw e;\n };\n }\n}\n","import { _Lexer } from './Lexer.ts';\nimport { _Parser } from './Parser.ts';\nimport { _Tokenizer } from './Tokenizer.ts';\nimport { _Renderer } from './Renderer.ts';\nimport { _TextRenderer } from './TextRenderer.ts';\nimport { _Hooks } from './Hooks.ts';\nimport { Marked } from './Instance.ts';\nimport { _getDefaults, changeDefaults, _defaults, } from './defaults.ts';\nconst markedInstance = new Marked();\nexport function marked(src, opt) {\n return markedInstance.parse(src, opt);\n}\n/**\n * Sets the default options.\n *\n * @param options Hash of options\n */\nmarked.options =\n marked.setOptions = function (options) {\n markedInstance.setOptions(options);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n };\n/**\n * Gets the original marked default options.\n */\nmarked.getDefaults = _getDefaults;\nmarked.defaults = _defaults;\n/**\n * Use Extension\n */\nmarked.use = function (...args) {\n markedInstance.use(...args);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n};\n/**\n * Run callback for every token\n */\nmarked.walkTokens = function (tokens, callback) {\n return markedInstance.walkTokens(tokens, callback);\n};\n/**\n * Compiles markdown to HTML without enclosing `p` tag.\n *\n * @param src String of markdown source to be compiled\n * @param options Hash of options\n * @return String of compiled HTML\n */\nmarked.parseInline = markedInstance.parseInline;\n/**\n * Expose\n */\nmarked.Parser = _Parser;\nmarked.parser = _Parser.parse;\nmarked.Renderer = _Renderer;\nmarked.TextRenderer = _TextRenderer;\nmarked.Lexer = _Lexer;\nmarked.lexer = _Lexer.lex;\nmarked.Tokenizer = _Tokenizer;\nmarked.Hooks = _Hooks;\nmarked.parse = marked;\nexport const options = marked.options;\nexport const setOptions = marked.setOptions;\nexport const use = marked.use;\nexport const walkTokens = marked.walkTokens;\nexport const parseInline = marked.parseInline;\nexport const parse = marked;\nexport const parser = _Parser.parse;\nexport const lexer = _Lexer.lex;\nexport { _defaults as defaults, _getDefaults as getDefaults } from './defaults.ts';\nexport { _Lexer as Lexer } from './Lexer.ts';\nexport { _Parser as Parser } from './Parser.ts';\nexport { _Tokenizer as Tokenizer } from './Tokenizer.ts';\nexport { _Renderer as Renderer } from './Renderer.ts';\nexport { _TextRenderer as TextRenderer } from './TextRenderer.ts';\nexport { _Hooks as Hooks } from './Hooks.ts';\nexport { Marked } from './Instance.ts';\n"],"names":["escape"],"mappings":"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"} \ No newline at end of file diff --git a/docs/node_modules/marked/lib/marked.umd.js b/docs/node_modules/marked/lib/marked.umd.js new file mode 100644 index 00000000..95dbaf5d --- /dev/null +++ b/docs/node_modules/marked/lib/marked.umd.js @@ -0,0 +1,2576 @@ +/** + * marked v15.0.3 - a markdown parser + * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + +/** + * DO NOT EDIT THIS FILE + * The code in this file is generated from files in ./src/ + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.marked = {})); +})(this, (function (exports) { 'use strict'; + + /** + * Gets the original marked default options. + */ + function _getDefaults() { + return { + async: false, + breaks: false, + extensions: null, + gfm: true, + hooks: null, + pedantic: false, + renderer: null, + silent: false, + tokenizer: null, + walkTokens: null, + }; + } + exports.defaults = _getDefaults(); + function changeDefaults(newDefaults) { + exports.defaults = newDefaults; + } + + const noopTest = { exec: () => null }; + function edit(regex, opt = '') { + let source = typeof regex === 'string' ? regex : regex.source; + const obj = { + replace: (name, val) => { + let valSource = typeof val === 'string' ? val : val.source; + valSource = valSource.replace(other.caret, '$1'); + source = source.replace(name, valSource); + return obj; + }, + getRegex: () => { + return new RegExp(source, opt); + }, + }; + return obj; + } + const other = { + codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, + outputLinkReplace: /\\([\[\]])/g, + indentCodeCompensation: /^(\s+)(?:```)/, + beginningSpace: /^\s+/, + endingHash: /#$/, + startingSpaceChar: /^ /, + endingSpaceChar: / $/, + nonSpaceChar: /[^ ]/, + newLineCharGlobal: /\n/g, + tabCharGlobal: /\t/g, + multipleSpaceGlobal: /\s+/g, + blankLine: /^[ \t]*$/, + doubleBlankLine: /\n[ \t]*\n[ \t]*$/, + blockquoteStart: /^ {0,3}>/, + blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, + blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, + listReplaceTabs: /^\t+/, + listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, + listIsTask: /^\[[ xX]\] /, + listReplaceTask: /^\[[ xX]\] +/, + anyLine: /\n.*\n/, + hrefBrackets: /^<(.*)>$/, + tableDelimiter: /[:|]/, + tableAlignChars: /^\||\| *$/g, + tableRowBlankLine: /\n[ \t]*$/, + tableAlignRight: /^ *-+: *$/, + tableAlignCenter: /^ *:-+: *$/, + tableAlignLeft: /^ *:-+ *$/, + startATag: /^
    /i, + startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, + endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, + startAngleBracket: /^$/, + pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, + unicodeAlphaNumeric: /[\p{L}\p{N}]/u, + escapeTest: /[&<>"']/, + escapeReplace: /[&<>"']/g, + escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, + escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, + unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, + caret: /(^|[^\[])\^/g, + percentDecode: /%25/g, + findPipe: /\|/g, + splitPipe: / \|/, + slashPipe: /\\\|/g, + carriageReturn: /\r\n|\r/g, + spaceLine: /^ +$/gm, + notSpaceStart: /^\S*/, + endingNewline: /\n$/, + listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`), + nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`), + hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), + fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`), + headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`), + htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'), + }; + /** + * Block-Level Grammar + */ + const newline = /^(?:[ \t]*(?:\n|$))+/; + const blockCode = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/; + const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/; + const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/; + const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/; + const bullet = /(?:[*+-]|\d{1,9}[.)])/; + const lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/) + .replace(/bull/g, bullet) // lists can interrupt + .replace(/blockCode/g, /(?: {4}| {0,3}\t)/) // indented code blocks can interrupt + .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt + .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt + .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt + .replace(/html/g, / {0,3}<[^\n>]+>\n/) // block html can interrupt + .getRegex(); + const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/; + const blockText = /^[^\n]+/; + const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/; + const def = edit(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/) + .replace('label', _blockLabel) + .replace('title', /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/) + .getRegex(); + const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/) + .replace(/bull/g, bullet) + .getRegex(); + const _tag = 'address|article|aside|base|basefont|blockquote|body|caption' + + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title' + + '|tr|track|ul'; + const _comment = /|$))/; + const html = edit('^ {0,3}(?:' // optional indentation + + '<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)' // (1) + + '|comment[^\\n]*(\\n+|$)' // (2) + + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3) + + '|\\n*|$)' // (4) + + '|\\n*|$)' // (5) + + '|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (6) + + '|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) open tag + + '|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)' // (7) closing tag + + ')', 'i') + .replace('comment', _comment) + .replace('tag', _tag) + .replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/) + .getRegex(); + const paragraph = edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(); + const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/) + .replace('paragraph', paragraph) + .getRegex(); + /** + * Normal Block Grammar + */ + const blockNormal = { + blockquote, + code: blockCode, + def, + fences, + heading, + hr, + html, + lheading, + list, + newline, + paragraph, + table: noopTest, + text: blockText, + }; + /** + * GFM Block Grammar + */ + const gfmTable = edit('^ *([^\\n ].*)\\n' // Header + + ' {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)' // Align + + '(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)') // Cells + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('blockquote', ' {0,3}>') + .replace('code', '(?: {4}| {0,3}\t)[^\\n]') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // tables can be interrupted by type (6) html blocks + .getRegex(); + const blockGfm = { + ...blockNormal, + table: gfmTable, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' {0,3}#{1,6}(?:\\s|$)') + .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs + .replace('table', gfmTable) // interrupt paragraphs with table + .replace('blockquote', ' {0,3}>') + .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n') + .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt + .replace('html', ')|<(?:script|pre|style|textarea|!--)') + .replace('tag', _tag) // pars can be interrupted by type (6) html blocks + .getRegex(), + }; + /** + * Pedantic grammar (original John Gruber's loose markdown specification) + */ + const blockPedantic = { + ...blockNormal, + html: edit('^ *(?:comment *(?:\\n|\\s*$)' + + '|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)' // closed tag + + '|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))') + .replace('comment', _comment) + .replace(/tag/g, '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b') + .getRegex(), + def: /^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, + heading: /^(#{1,6})(.*)(?:\n+|$)/, + fences: noopTest, // fences not supported + lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, + paragraph: edit(_paragraph) + .replace('hr', hr) + .replace('heading', ' *#{1,6} *[^\n]') + .replace('lheading', lheading) + .replace('|table', '') + .replace('blockquote', ' {0,3}>') + .replace('|fences', '') + .replace('|list', '') + .replace('|html', '') + .replace('|tag', '') + .getRegex(), + }; + /** + * Inline-Level Grammar + */ + const escape$1 = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/; + const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/; + const br = /^( {2,}|\\)\n(?!\s*$)/; + const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\ + const blockSkip = /\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g; + const emStrongLDelim = edit(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/, 'u') + .replace(/punct/g, _punctuation) + .getRegex(); + const emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)' // Skip orphan inside strong + + '|[^*]+(?=[^*])' // Consume to delim + + '|(?!\\*)punct(\\*+)(?=[\\s]|$)' // (1) #*** can only be a Right Delimiter + + '|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter + + '|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter + + '|[\\s](\\*+)(?!\\*)(?=punct)' // (4) ***# can only be Left Delimiter + + '|(?!\\*)punct(\\*+)(?!\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter + + '|notPunctSpace(\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); + // (6) Not allowed for _ + const emStrongRDelimUnd = edit('^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)' // Skip orphan inside strong + + '|[^_]+(?=[^_])' // Consume to delim + + '|(?!_)punct(_+)(?=[\\s]|$)' // (1) #___ can only be a Right Delimiter + + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter + + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter + + '|[\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter + + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter + .replace(/notPunctSpace/g, _notPunctuationOrSpace) + .replace(/punctSpace/g, _punctuationOrSpace) + .replace(/punct/g, _punctuation) + .getRegex(); + const anyPunctuation = edit(/\\(punct)/, 'gu') + .replace(/punct/g, _punctuation) + .getRegex(); + const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/) + .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/) + .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/) + .getRegex(); + const _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex(); + const tag = edit('^comment' + + '|^' // self-closing tag + + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag + + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. + + '|^' // declaration, e.g. + + '|^') // CDATA section + .replace('comment', _inlineComment) + .replace('attribute', /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/) + .getRegex(); + const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/; + const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/) + .replace('label', _inlineLabel) + .replace('href', /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/) + .replace('title', /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/) + .getRegex(); + const reflink = edit(/^!?\[(label)\]\[(ref)\]/) + .replace('label', _inlineLabel) + .replace('ref', _blockLabel) + .getRegex(); + const nolink = edit(/^!?\[(ref)\](?:\[\])?/) + .replace('ref', _blockLabel) + .getRegex(); + const reflinkSearch = edit('reflink|nolink(?!\\()', 'g') + .replace('reflink', reflink) + .replace('nolink', nolink) + .getRegex(); + /** + * Normal Inline Grammar + */ + const inlineNormal = { + _backpedal: noopTest, // only used for GFM url + anyPunctuation, + autolink, + blockSkip, + br, + code: inlineCode, + del: noopTest, + emStrongLDelim, + emStrongRDelimAst, + emStrongRDelimUnd, + escape: escape$1, + link, + nolink, + punctuation, + reflink, + reflinkSearch, + tag, + text: inlineText, + url: noopTest, + }; + /** + * Pedantic Inline Grammar + */ + const inlinePedantic = { + ...inlineNormal, + link: edit(/^!?\[(label)\]\((.*?)\)/) + .replace('label', _inlineLabel) + .getRegex(), + reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/) + .replace('label', _inlineLabel) + .getRegex(), + }; + /** + * GFM Inline Grammar + */ + const inlineGfm = { + ...inlineNormal, + escape: edit(escape$1).replace('])', '~|])').getRegex(), + url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, 'i') + .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/) + .getRegex(), + _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, + del: /^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/, + text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\': '>', + '"': '"', + "'": ''', + }; + const getEscapeReplacement = (ch) => escapeReplacements[ch]; + function escape(html, encode) { + if (encode) { + if (other.escapeTest.test(html)) { + return html.replace(other.escapeReplace, getEscapeReplacement); + } + } + else { + if (other.escapeTestNoEncode.test(html)) { + return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement); + } + } + return html; + } + function cleanUrl(href) { + try { + href = encodeURI(href).replace(other.percentDecode, '%'); + } + catch { + return null; + } + return href; + } + function splitCells(tableRow, count) { + // ensure that every cell-delimiting pipe has a space + // before it to distinguish it from an escaped pipe + const row = tableRow.replace(other.findPipe, (match, offset, str) => { + let escaped = false; + let curr = offset; + while (--curr >= 0 && str[curr] === '\\') + escaped = !escaped; + if (escaped) { + // odd number of slashes means | is escaped + // so we leave it alone + return '|'; + } + else { + // add space before unescaped | + return ' |'; + } + }), cells = row.split(other.splitPipe); + let i = 0; + // First/last cell in a row cannot be empty if it has no leading/trailing pipe + if (!cells[0].trim()) { + cells.shift(); + } + if (cells.length > 0 && !cells.at(-1)?.trim()) { + cells.pop(); + } + if (count) { + if (cells.length > count) { + cells.splice(count); + } + else { + while (cells.length < count) + cells.push(''); + } + } + for (; i < cells.length; i++) { + // leading or trailing whitespace is ignored per the gfm spec + cells[i] = cells[i].trim().replace(other.slashPipe, '|'); + } + return cells; + } + /** + * Remove trailing 'c's. Equivalent to str.replace(/c*$/, ''). + * /c*$/ is vulnerable to REDOS. + * + * @param str + * @param c + * @param invert Remove suffix of non-c chars instead. Default falsey. + */ + function rtrim(str, c, invert) { + const l = str.length; + if (l === 0) { + return ''; + } + // Length of suffix matching the invert condition. + let suffLen = 0; + // Step left until we fail to match the invert condition. + while (suffLen < l) { + const currChar = str.charAt(l - suffLen - 1); + if (currChar === c && !invert) { + suffLen++; + } + else if (currChar !== c && invert) { + suffLen++; + } + else { + break; + } + } + return str.slice(0, l - suffLen); + } + function findClosingBracket(str, b) { + if (str.indexOf(b[1]) === -1) { + return -1; + } + let level = 0; + for (let i = 0; i < str.length; i++) { + if (str[i] === '\\') { + i++; + } + else if (str[i] === b[0]) { + level++; + } + else if (str[i] === b[1]) { + level--; + if (level < 0) { + return i; + } + } + } + return -1; + } + + function outputLink(cap, link, raw, lexer, rules) { + const href = link.href; + const title = link.title || null; + const text = cap[1].replace(rules.other.outputLinkReplace, '$1'); + if (cap[0].charAt(0) !== '!') { + lexer.state.inLink = true; + const token = { + type: 'link', + raw, + href, + title, + text, + tokens: lexer.inlineTokens(text), + }; + lexer.state.inLink = false; + return token; + } + return { + type: 'image', + raw, + href, + title, + text, + }; + } + function indentCodeCompensation(raw, text, rules) { + const matchIndentToCode = raw.match(rules.other.indentCodeCompensation); + if (matchIndentToCode === null) { + return text; + } + const indentToCode = matchIndentToCode[1]; + return text + .split('\n') + .map(node => { + const matchIndentInNode = node.match(rules.other.beginningSpace); + if (matchIndentInNode === null) { + return node; + } + const [indentInNode] = matchIndentInNode; + if (indentInNode.length >= indentToCode.length) { + return node.slice(indentToCode.length); + } + return node; + }) + .join('\n'); + } + /** + * Tokenizer + */ + class _Tokenizer { + options; + rules; // set by the lexer + lexer; // set by the lexer + constructor(options) { + this.options = options || exports.defaults; + } + space(src) { + const cap = this.rules.block.newline.exec(src); + if (cap && cap[0].length > 0) { + return { + type: 'space', + raw: cap[0], + }; + } + } + code(src) { + const cap = this.rules.block.code.exec(src); + if (cap) { + const text = cap[0].replace(this.rules.other.codeRemoveIndent, ''); + return { + type: 'code', + raw: cap[0], + codeBlockStyle: 'indented', + text: !this.options.pedantic + ? rtrim(text, '\n') + : text, + }; + } + } + fences(src) { + const cap = this.rules.block.fences.exec(src); + if (cap) { + const raw = cap[0]; + const text = indentCodeCompensation(raw, cap[3] || '', this.rules); + return { + type: 'code', + raw, + lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2], + text, + }; + } + } + heading(src) { + const cap = this.rules.block.heading.exec(src); + if (cap) { + let text = cap[2].trim(); + // remove trailing #s + if (this.rules.other.endingHash.test(text)) { + const trimmed = rtrim(text, '#'); + if (this.options.pedantic) { + text = trimmed.trim(); + } + else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) { + // CommonMark requires space before trailing #s + text = trimmed.trim(); + } + } + return { + type: 'heading', + raw: cap[0], + depth: cap[1].length, + text, + tokens: this.lexer.inline(text), + }; + } + } + hr(src) { + const cap = this.rules.block.hr.exec(src); + if (cap) { + return { + type: 'hr', + raw: rtrim(cap[0], '\n'), + }; + } + } + blockquote(src) { + const cap = this.rules.block.blockquote.exec(src); + if (cap) { + let lines = rtrim(cap[0], '\n').split('\n'); + let raw = ''; + let text = ''; + const tokens = []; + while (lines.length > 0) { + let inBlockquote = false; + const currentLines = []; + let i; + for (i = 0; i < lines.length; i++) { + // get lines up to a continuation + if (this.rules.other.blockquoteStart.test(lines[i])) { + currentLines.push(lines[i]); + inBlockquote = true; + } + else if (!inBlockquote) { + currentLines.push(lines[i]); + } + else { + break; + } + } + lines = lines.slice(i); + const currentRaw = currentLines.join('\n'); + const currentText = currentRaw + // precede setext continuation with 4 spaces so it isn't a setext + .replace(this.rules.other.blockquoteSetextReplace, '\n $1') + .replace(this.rules.other.blockquoteSetextReplace2, ''); + raw = raw ? `${raw}\n${currentRaw}` : currentRaw; + text = text ? `${text}\n${currentText}` : currentText; + // parse blockquote lines as top level tokens + // merge paragraphs if this is a continuation + const top = this.lexer.state.top; + this.lexer.state.top = true; + this.lexer.blockTokens(currentText, tokens, true); + this.lexer.state.top = top; + // if there is no continuation then we are done + if (lines.length === 0) { + break; + } + const lastToken = tokens.at(-1); + if (lastToken?.type === 'code') { + // blockquote continuation cannot be preceded by a code block + break; + } + else if (lastToken?.type === 'blockquote') { + // include continuation in nested blockquote + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.blockquote(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.text.length) + newToken.text; + break; + } + else if (lastToken?.type === 'list') { + // include continuation in nested list + const oldToken = lastToken; + const newText = oldToken.raw + '\n' + lines.join('\n'); + const newToken = this.list(newText); + tokens[tokens.length - 1] = newToken; + raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw; + text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw; + lines = newText.substring(tokens.at(-1).raw.length).split('\n'); + continue; + } + } + return { + type: 'blockquote', + raw, + tokens, + text, + }; + } + } + list(src) { + let cap = this.rules.block.list.exec(src); + if (cap) { + let bull = cap[1].trim(); + const isordered = bull.length > 1; + const list = { + type: 'list', + raw: '', + ordered: isordered, + start: isordered ? +bull.slice(0, -1) : '', + loose: false, + items: [], + }; + bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`; + if (this.options.pedantic) { + bull = isordered ? bull : '[*+-]'; + } + // Get next list item + const itemRegex = this.rules.other.listItemRegex(bull); + let endsWithBlankLine = false; + // Check if current bullet point can start a new List Item + while (src) { + let endEarly = false; + let raw = ''; + let itemContents = ''; + if (!(cap = itemRegex.exec(src))) { + break; + } + if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?) + break; + } + raw = cap[0]; + src = src.substring(raw.length); + let line = cap[2].split('\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length)); + let nextLine = src.split('\n', 1)[0]; + let blankLine = !line.trim(); + let indent = 0; + if (this.options.pedantic) { + indent = 2; + itemContents = line.trimStart(); + } + else if (blankLine) { + indent = cap[1].length + 1; + } + else { + indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char + indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent + itemContents = line.slice(indent); + indent += cap[1].length; + } + if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line + raw += nextLine + '\n'; + src = src.substring(nextLine.length + 1); + endEarly = true; + } + if (!endEarly) { + const nextBulletRegex = this.rules.other.nextBulletRegex(indent); + const hrRegex = this.rules.other.hrRegex(indent); + const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent); + const headingBeginRegex = this.rules.other.headingBeginRegex(indent); + const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent); + // Check if following lines should be included in List Item + while (src) { + const rawLine = src.split('\n', 1)[0]; + let nextLineWithoutTabs; + nextLine = rawLine; + // Re-align to follow commonmark nesting rules + if (this.options.pedantic) { + nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' '); + nextLineWithoutTabs = nextLine; + } + else { + nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' '); + } + // End list item if found code fences + if (fencesBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new heading + if (headingBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of html block + if (htmlBeginRegex.test(nextLine)) { + break; + } + // End list item if found start of new bullet + if (nextBulletRegex.test(nextLine)) { + break; + } + // Horizontal rule found + if (hrRegex.test(nextLine)) { + break; + } + if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible + itemContents += '\n' + nextLineWithoutTabs.slice(indent); + } + else { + // not enough indentation + if (blankLine) { + break; + } + // paragraph continuation unless last line was a different block level element + if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block + break; + } + if (fencesBeginRegex.test(line)) { + break; + } + if (headingBeginRegex.test(line)) { + break; + } + if (hrRegex.test(line)) { + break; + } + itemContents += '\n' + nextLine; + } + if (!blankLine && !nextLine.trim()) { // Check if current line is blank + blankLine = true; + } + raw += rawLine + '\n'; + src = src.substring(rawLine.length + 1); + line = nextLineWithoutTabs.slice(indent); + } + } + if (!list.loose) { + // If the previous item ended with a blank line, the list is loose + if (endsWithBlankLine) { + list.loose = true; + } + else if (this.rules.other.doubleBlankLine.test(raw)) { + endsWithBlankLine = true; + } + } + let istask = null; + let ischecked; + // Check for task list items + if (this.options.gfm) { + istask = this.rules.other.listIsTask.exec(itemContents); + if (istask) { + ischecked = istask[0] !== '[ ] '; + itemContents = itemContents.replace(this.rules.other.listReplaceTask, ''); + } + } + list.items.push({ + type: 'list_item', + raw, + task: !!istask, + checked: ischecked, + loose: false, + text: itemContents, + tokens: [], + }); + list.raw += raw; + } + // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic + const lastItem = list.items.at(-1); + if (lastItem) { + lastItem.raw = lastItem.raw.trimEnd(); + lastItem.text = lastItem.text.trimEnd(); + } + list.raw = list.raw.trimEnd(); + // Item child tokens handled here at end because we needed to have the final item to trim it first + for (let i = 0; i < list.items.length; i++) { + this.lexer.state.top = false; + list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []); + if (!list.loose) { + // Check if list should be loose + const spacers = list.items[i].tokens.filter(t => t.type === 'space'); + const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw)); + list.loose = hasMultipleLineBreaks; + } + } + // Set all items to loose if list is loose + if (list.loose) { + for (let i = 0; i < list.items.length; i++) { + list.items[i].loose = true; + } + } + return list; + } + } + html(src) { + const cap = this.rules.block.html.exec(src); + if (cap) { + const token = { + type: 'html', + block: true, + raw: cap[0], + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0], + }; + return token; + } + } + def(src) { + const cap = this.rules.block.def.exec(src); + if (cap) { + const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' '); + const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : ''; + const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3]; + return { + type: 'def', + tag, + raw: cap[0], + href, + title, + }; + } + } + table(src) { + const cap = this.rules.block.table.exec(src); + if (!cap) { + return; + } + if (!this.rules.other.tableDelimiter.test(cap[2])) { + // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading + return; + } + const headers = splitCells(cap[1]); + const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|'); + const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\n') : []; + const item = { + type: 'table', + raw: cap[0], + header: [], + align: [], + rows: [], + }; + if (headers.length !== aligns.length) { + // header and align columns must be equal, rows can be different. + return; + } + for (const align of aligns) { + if (this.rules.other.tableAlignRight.test(align)) { + item.align.push('right'); + } + else if (this.rules.other.tableAlignCenter.test(align)) { + item.align.push('center'); + } + else if (this.rules.other.tableAlignLeft.test(align)) { + item.align.push('left'); + } + else { + item.align.push(null); + } + } + for (let i = 0; i < headers.length; i++) { + item.header.push({ + text: headers[i], + tokens: this.lexer.inline(headers[i]), + header: true, + align: item.align[i], + }); + } + for (const row of rows) { + item.rows.push(splitCells(row, item.header.length).map((cell, i) => { + return { + text: cell, + tokens: this.lexer.inline(cell), + header: false, + align: item.align[i], + }; + })); + } + return item; + } + lheading(src) { + const cap = this.rules.block.lheading.exec(src); + if (cap) { + return { + type: 'heading', + raw: cap[0], + depth: cap[2].charAt(0) === '=' ? 1 : 2, + text: cap[1], + tokens: this.lexer.inline(cap[1]), + }; + } + } + paragraph(src) { + const cap = this.rules.block.paragraph.exec(src); + if (cap) { + const text = cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1]; + return { + type: 'paragraph', + raw: cap[0], + text, + tokens: this.lexer.inline(text), + }; + } + } + text(src) { + const cap = this.rules.block.text.exec(src); + if (cap) { + return { + type: 'text', + raw: cap[0], + text: cap[0], + tokens: this.lexer.inline(cap[0]), + }; + } + } + escape(src) { + const cap = this.rules.inline.escape.exec(src); + if (cap) { + return { + type: 'escape', + raw: cap[0], + text: cap[1], + }; + } + } + tag(src) { + const cap = this.rules.inline.tag.exec(src); + if (cap) { + if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) { + this.lexer.state.inLink = true; + } + else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) { + this.lexer.state.inLink = false; + } + if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = true; + } + else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) { + this.lexer.state.inRawBlock = false; + } + return { + type: 'html', + raw: cap[0], + inLink: this.lexer.state.inLink, + inRawBlock: this.lexer.state.inRawBlock, + block: false, + text: cap[0], + }; + } + } + link(src) { + const cap = this.rules.inline.link.exec(src); + if (cap) { + const trimmedUrl = cap[2].trim(); + if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) { + // commonmark requires matching angle brackets + if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) { + return; + } + // ending angle bracket cannot be escaped + const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\'); + if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) { + return; + } + } + else { + // find closing parenthesis + const lastParenIndex = findClosingBracket(cap[2], '()'); + if (lastParenIndex > -1) { + const start = cap[0].indexOf('!') === 0 ? 5 : 4; + const linkLen = start + cap[1].length + lastParenIndex; + cap[2] = cap[2].substring(0, lastParenIndex); + cap[0] = cap[0].substring(0, linkLen).trim(); + cap[3] = ''; + } + } + let href = cap[2]; + let title = ''; + if (this.options.pedantic) { + // split pedantic href and title + const link = this.rules.other.pedanticHrefTitle.exec(href); + if (link) { + href = link[1]; + title = link[3]; + } + } + else { + title = cap[3] ? cap[3].slice(1, -1) : ''; + } + href = href.trim(); + if (this.rules.other.startAngleBracket.test(href)) { + if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) { + // pedantic allows starting angle bracket without ending angle bracket + href = href.slice(1); + } + else { + href = href.slice(1, -1); + } + } + return outputLink(cap, { + href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href, + title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title, + }, cap[0], this.lexer, this.rules); + } + } + reflink(src, links) { + let cap; + if ((cap = this.rules.inline.reflink.exec(src)) + || (cap = this.rules.inline.nolink.exec(src))) { + const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' '); + const link = links[linkString.toLowerCase()]; + if (!link) { + const text = cap[0].charAt(0); + return { + type: 'text', + raw: text, + text, + }; + } + return outputLink(cap, link, cap[0], this.lexer, this.rules); + } + } + emStrong(src, maskedSrc, prevChar = '') { + let match = this.rules.inline.emStrongLDelim.exec(src); + if (!match) + return; + // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well + if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric)) + return; + const nextChar = match[1] || match[2] || ''; + if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) { + // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below) + const lLength = [...match[0]].length - 1; + let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0; + const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd; + endReg.lastIndex = 0; + // Clip maskedSrc to same section of string as src (move to lexer?) + maskedSrc = maskedSrc.slice(-1 * src.length + lLength); + while ((match = endReg.exec(maskedSrc)) != null) { + rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6]; + if (!rDelim) + continue; // skip single * in __abc*abc__ + rLength = [...rDelim].length; + if (match[3] || match[4]) { // found another Left Delim + delimTotal += rLength; + continue; + } + else if (match[5] || match[6]) { // either Left or Right Delim + if (lLength % 3 && !((lLength + rLength) % 3)) { + midDelimTotal += rLength; + continue; // CommonMark Emphasis Rules 9-10 + } + } + delimTotal -= rLength; + if (delimTotal > 0) + continue; // Haven't found enough closing delimiters + // Remove extra characters. *a*** -> *a* + rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); + // char length can be >1 for unicode characters; + const lastCharLength = [...match[0]][0].length; + const raw = src.slice(0, lLength + match.index + lastCharLength + rLength); + // Create `em` if smallest delimiter has odd char count. *a*** + if (Math.min(lLength, rLength) % 2) { + const text = raw.slice(1, -1); + return { + type: 'em', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + // Create 'strong' if smallest delimiter has even char count. **a*** + const text = raw.slice(2, -2); + return { + type: 'strong', + raw, + text, + tokens: this.lexer.inlineTokens(text), + }; + } + } + } + codespan(src) { + const cap = this.rules.inline.code.exec(src); + if (cap) { + let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' '); + const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text); + const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text); + if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) { + text = text.substring(1, text.length - 1); + } + return { + type: 'codespan', + raw: cap[0], + text, + }; + } + } + br(src) { + const cap = this.rules.inline.br.exec(src); + if (cap) { + return { + type: 'br', + raw: cap[0], + }; + } + } + del(src) { + const cap = this.rules.inline.del.exec(src); + if (cap) { + return { + type: 'del', + raw: cap[0], + text: cap[2], + tokens: this.lexer.inlineTokens(cap[2]), + }; + } + } + autolink(src) { + const cap = this.rules.inline.autolink.exec(src); + if (cap) { + let text, href; + if (cap[2] === '@') { + text = cap[1]; + href = 'mailto:' + text; + } + else { + text = cap[1]; + href = text; + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + url(src) { + let cap; + if (cap = this.rules.inline.url.exec(src)) { + let text, href; + if (cap[2] === '@') { + text = cap[0]; + href = 'mailto:' + text; + } + else { + // do extended autolink path validation + let prevCapZero; + do { + prevCapZero = cap[0]; + cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? ''; + } while (prevCapZero !== cap[0]); + text = cap[0]; + if (cap[1] === 'www.') { + href = 'http://' + cap[0]; + } + else { + href = cap[0]; + } + } + return { + type: 'link', + raw: cap[0], + text, + href, + tokens: [ + { + type: 'text', + raw: text, + text, + }, + ], + }; + } + } + inlineText(src) { + const cap = this.rules.inline.text.exec(src); + if (cap) { + const escaped = this.lexer.state.inRawBlock; + return { + type: 'text', + raw: cap[0], + text: cap[0], + escaped, + }; + } + } + } + + /** + * Block Lexer + */ + class _Lexer { + tokens; + options; + state; + tokenizer; + inlineQueue; + constructor(options) { + // TokenList cannot be created in one go + this.tokens = []; + this.tokens.links = Object.create(null); + this.options = options || exports.defaults; + this.options.tokenizer = this.options.tokenizer || new _Tokenizer(); + this.tokenizer = this.options.tokenizer; + this.tokenizer.options = this.options; + this.tokenizer.lexer = this; + this.inlineQueue = []; + this.state = { + inLink: false, + inRawBlock: false, + top: true, + }; + const rules = { + other, + block: block.normal, + inline: inline.normal, + }; + if (this.options.pedantic) { + rules.block = block.pedantic; + rules.inline = inline.pedantic; + } + else if (this.options.gfm) { + rules.block = block.gfm; + if (this.options.breaks) { + rules.inline = inline.breaks; + } + else { + rules.inline = inline.gfm; + } + } + this.tokenizer.rules = rules; + } + /** + * Expose Rules + */ + static get rules() { + return { + block, + inline, + }; + } + /** + * Static Lex Method + */ + static lex(src, options) { + const lexer = new _Lexer(options); + return lexer.lex(src); + } + /** + * Static Lex Inline Method + */ + static lexInline(src, options) { + const lexer = new _Lexer(options); + return lexer.inlineTokens(src); + } + /** + * Preprocessing + */ + lex(src) { + src = src.replace(other.carriageReturn, '\n'); + this.blockTokens(src, this.tokens); + for (let i = 0; i < this.inlineQueue.length; i++) { + const next = this.inlineQueue[i]; + this.inlineTokens(next.src, next.tokens); + } + this.inlineQueue = []; + return this.tokens; + } + blockTokens(src, tokens = [], lastParagraphClipped = false) { + if (this.options.pedantic) { + src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, ''); + } + while (src) { + let token; + if (this.options.extensions?.block?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // newline + if (token = this.tokenizer.space(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.raw.length === 1 && lastToken !== undefined) { + // if there's a single \n as a spacer, it's terminating the last line, + // so move it there so that we don't get unnecessary paragraph tags + lastToken.raw += '\n'; + } + else { + tokens.push(token); + } + continue; + } + // code + if (token = this.tokenizer.code(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + // An indented code block cannot interrupt a paragraph. + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + // fences + if (token = this.tokenizer.fences(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // heading + if (token = this.tokenizer.heading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // hr + if (token = this.tokenizer.hr(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // blockquote + if (token = this.tokenizer.blockquote(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // list + if (token = this.tokenizer.list(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // html + if (token = this.tokenizer.html(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // def + if (token = this.tokenizer.def(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.raw; + this.inlineQueue.at(-1).src = lastToken.text; + } + else if (!this.tokens.links[token.tag]) { + this.tokens.links[token.tag] = { + href: token.href, + title: token.title, + }; + } + continue; + } + // table (gfm) + if (token = this.tokenizer.table(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // lheading + if (token = this.tokenizer.lheading(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // top-level paragraph + // prevent paragraph consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startBlock) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startBlock.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) { + const lastToken = tokens.at(-1); + if (lastParagraphClipped && lastToken?.type === 'paragraph') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + lastParagraphClipped = cutSrc.length !== src.length; + src = src.substring(token.raw.length); + continue; + } + // text + if (token = this.tokenizer.text(src)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += '\n' + token.raw; + lastToken.text += '\n' + token.text; + this.inlineQueue.pop(); + this.inlineQueue.at(-1).src = lastToken.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + this.state.top = true; + return tokens; + } + inline(src, tokens = []) { + this.inlineQueue.push({ src, tokens }); + return tokens; + } + /** + * Lexing/Compiling + */ + inlineTokens(src, tokens = []) { + // String with links masked to avoid interference with em and strong + let maskedSrc = src; + let match = null; + // Mask out reflinks + if (this.tokens.links) { + const links = Object.keys(this.tokens.links); + if (links.length > 0) { + while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) { + if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) { + maskedSrc = maskedSrc.slice(0, match.index) + + '[' + 'a'.repeat(match[0].length - 2) + ']' + + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex); + } + } + } + } + // Mask out other blocks + while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex); + } + // Mask out escaped characters + while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) { + maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex); + } + let keepPrevChar = false; + let prevChar = ''; + while (src) { + if (!keepPrevChar) { + prevChar = ''; + } + keepPrevChar = false; + let token; + // extensions + if (this.options.extensions?.inline?.some((extTokenizer) => { + if (token = extTokenizer.call({ lexer: this }, src, tokens)) { + src = src.substring(token.raw.length); + tokens.push(token); + return true; + } + return false; + })) { + continue; + } + // escape + if (token = this.tokenizer.escape(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // tag + if (token = this.tokenizer.tag(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // link + if (token = this.tokenizer.link(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // reflink, nolink + if (token = this.tokenizer.reflink(src, this.tokens.links)) { + src = src.substring(token.raw.length); + const lastToken = tokens.at(-1); + if (token.type === 'text' && lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + // em & strong + if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // code + if (token = this.tokenizer.codespan(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // br + if (token = this.tokenizer.br(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // del (gfm) + if (token = this.tokenizer.del(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // autolink + if (token = this.tokenizer.autolink(src)) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // url (gfm) + if (!this.state.inLink && (token = this.tokenizer.url(src))) { + src = src.substring(token.raw.length); + tokens.push(token); + continue; + } + // text + // prevent inlineText consuming extensions by clipping 'src' to extension start + let cutSrc = src; + if (this.options.extensions?.startInline) { + let startIndex = Infinity; + const tempSrc = src.slice(1); + let tempStart; + this.options.extensions.startInline.forEach((getStartIndex) => { + tempStart = getStartIndex.call({ lexer: this }, tempSrc); + if (typeof tempStart === 'number' && tempStart >= 0) { + startIndex = Math.min(startIndex, tempStart); + } + }); + if (startIndex < Infinity && startIndex >= 0) { + cutSrc = src.substring(0, startIndex + 1); + } + } + if (token = this.tokenizer.inlineText(cutSrc)) { + src = src.substring(token.raw.length); + if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started + prevChar = token.raw.slice(-1); + } + keepPrevChar = true; + const lastToken = tokens.at(-1); + if (lastToken?.type === 'text') { + lastToken.raw += token.raw; + lastToken.text += token.text; + } + else { + tokens.push(token); + } + continue; + } + if (src) { + const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0); + if (this.options.silent) { + console.error(errMsg); + break; + } + else { + throw new Error(errMsg); + } + } + } + return tokens; + } + } + + /** + * Renderer + */ + class _Renderer { + options; + parser; // set by the parser + constructor(options) { + this.options = options || exports.defaults; + } + space(token) { + return ''; + } + code({ text, lang, escaped }) { + const langString = (lang || '').match(other.notSpaceStart)?.[0]; + const code = text.replace(other.endingNewline, '') + '\n'; + if (!langString) { + return '
    '
    +                    + (escaped ? code : escape(code, true))
    +                    + '
    \n'; + } + return '
    '
    +                + (escaped ? code : escape(code, true))
    +                + '
    \n'; + } + blockquote({ tokens }) { + const body = this.parser.parse(tokens); + return `
    \n${body}
    \n`; + } + html({ text }) { + return text; + } + heading({ tokens, depth }) { + return `${this.parser.parseInline(tokens)}\n`; + } + hr(token) { + return '
    \n'; + } + list(token) { + const ordered = token.ordered; + const start = token.start; + let body = ''; + for (let j = 0; j < token.items.length; j++) { + const item = token.items[j]; + body += this.listitem(item); + } + const type = ordered ? 'ol' : 'ul'; + const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : ''; + return '<' + type + startAttr + '>\n' + body + '\n'; + } + listitem(item) { + let itemBody = ''; + if (item.task) { + const checkbox = this.checkbox({ checked: !!item.checked }); + if (item.loose) { + if (item.tokens[0]?.type === 'paragraph') { + item.tokens[0].text = checkbox + ' ' + item.tokens[0].text; + if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') { + item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text); + item.tokens[0].tokens[0].escaped = true; + } + } + else { + item.tokens.unshift({ + type: 'text', + raw: checkbox + ' ', + text: checkbox + ' ', + escaped: true, + }); + } + } + else { + itemBody += checkbox + ' '; + } + } + itemBody += this.parser.parse(item.tokens, !!item.loose); + return `
  • ${itemBody}
  • \n`; + } + checkbox({ checked }) { + return ''; + } + paragraph({ tokens }) { + return `

    ${this.parser.parseInline(tokens)}

    \n`; + } + table(token) { + let header = ''; + // header + let cell = ''; + for (let j = 0; j < token.header.length; j++) { + cell += this.tablecell(token.header[j]); + } + header += this.tablerow({ text: cell }); + let body = ''; + for (let j = 0; j < token.rows.length; j++) { + const row = token.rows[j]; + cell = ''; + for (let k = 0; k < row.length; k++) { + cell += this.tablecell(row[k]); + } + body += this.tablerow({ text: cell }); + } + if (body) + body = `${body}`; + return '\n' + + '\n' + + header + + '\n' + + body + + '
    \n'; + } + tablerow({ text }) { + return `\n${text}\n`; + } + tablecell(token) { + const content = this.parser.parseInline(token.tokens); + const type = token.header ? 'th' : 'td'; + const tag = token.align + ? `<${type} align="${token.align}">` + : `<${type}>`; + return tag + content + `\n`; + } + /** + * span level renderer + */ + strong({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + em({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + codespan({ text }) { + return `${escape(text, true)}`; + } + br(token) { + return '
    '; + } + del({ tokens }) { + return `${this.parser.parseInline(tokens)}`; + } + link({ href, title, tokens }) { + const text = this.parser.parseInline(tokens); + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return text; + } + href = cleanHref; + let out = '
    '; + return out; + } + image({ href, title, text }) { + const cleanHref = cleanUrl(href); + if (cleanHref === null) { + return escape(text); + } + href = cleanHref; + let out = `${text} { + const tokens = genericToken[childTokens].flat(Infinity); + values = values.concat(this.walkTokens(tokens, callback)); + }); + } + else if (genericToken.tokens) { + values = values.concat(this.walkTokens(genericToken.tokens, callback)); + } + } + } + } + return values; + } + use(...args) { + const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} }; + args.forEach((pack) => { + // copy options to new object + const opts = { ...pack }; + // set async to true if it was set to true before + opts.async = this.defaults.async || opts.async || false; + // ==-- Parse "addon" extensions --== // + if (pack.extensions) { + pack.extensions.forEach((ext) => { + if (!ext.name) { + throw new Error('extension name required'); + } + if ('renderer' in ext) { // Renderer extensions + const prevRenderer = extensions.renderers[ext.name]; + if (prevRenderer) { + // Replace extension with func to run new extension but fall back if false + extensions.renderers[ext.name] = function (...args) { + let ret = ext.renderer.apply(this, args); + if (ret === false) { + ret = prevRenderer.apply(this, args); + } + return ret; + }; + } + else { + extensions.renderers[ext.name] = ext.renderer; + } + } + if ('tokenizer' in ext) { // Tokenizer Extensions + if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) { + throw new Error("extension level must be 'block' or 'inline'"); + } + const extLevel = extensions[ext.level]; + if (extLevel) { + extLevel.unshift(ext.tokenizer); + } + else { + extensions[ext.level] = [ext.tokenizer]; + } + if (ext.start) { // Function to check for start of token + if (ext.level === 'block') { + if (extensions.startBlock) { + extensions.startBlock.push(ext.start); + } + else { + extensions.startBlock = [ext.start]; + } + } + else if (ext.level === 'inline') { + if (extensions.startInline) { + extensions.startInline.push(ext.start); + } + else { + extensions.startInline = [ext.start]; + } + } + } + } + if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens + extensions.childTokens[ext.name] = ext.childTokens; + } + }); + opts.extensions = extensions; + } + // ==-- Parse "overwrite" extensions --== // + if (pack.renderer) { + const renderer = this.defaults.renderer || new _Renderer(this.defaults); + for (const prop in pack.renderer) { + if (!(prop in renderer)) { + throw new Error(`renderer '${prop}' does not exist`); + } + if (['options', 'parser'].includes(prop)) { + // ignore options property + continue; + } + const rendererProp = prop; + const rendererFunc = pack.renderer[rendererProp]; + const prevRenderer = renderer[rendererProp]; + // Replace renderer with func to run extension, but fall back if false + renderer[rendererProp] = (...args) => { + let ret = rendererFunc.apply(renderer, args); + if (ret === false) { + ret = prevRenderer.apply(renderer, args); + } + return ret || ''; + }; + } + opts.renderer = renderer; + } + if (pack.tokenizer) { + const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults); + for (const prop in pack.tokenizer) { + if (!(prop in tokenizer)) { + throw new Error(`tokenizer '${prop}' does not exist`); + } + if (['options', 'rules', 'lexer'].includes(prop)) { + // ignore options, rules, and lexer properties + continue; + } + const tokenizerProp = prop; + const tokenizerFunc = pack.tokenizer[tokenizerProp]; + const prevTokenizer = tokenizer[tokenizerProp]; + // Replace tokenizer with func to run extension, but fall back if false + // @ts-expect-error cannot type tokenizer function dynamically + tokenizer[tokenizerProp] = (...args) => { + let ret = tokenizerFunc.apply(tokenizer, args); + if (ret === false) { + ret = prevTokenizer.apply(tokenizer, args); + } + return ret; + }; + } + opts.tokenizer = tokenizer; + } + // ==-- Parse Hooks extensions --== // + if (pack.hooks) { + const hooks = this.defaults.hooks || new _Hooks(); + for (const prop in pack.hooks) { + if (!(prop in hooks)) { + throw new Error(`hook '${prop}' does not exist`); + } + if (['options', 'block'].includes(prop)) { + // ignore options and block properties + continue; + } + const hooksProp = prop; + const hooksFunc = pack.hooks[hooksProp]; + const prevHook = hooks[hooksProp]; + if (_Hooks.passThroughHooks.has(prop)) { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (arg) => { + if (this.defaults.async) { + return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => { + return prevHook.call(hooks, ret); + }); + } + const ret = hooksFunc.call(hooks, arg); + return prevHook.call(hooks, ret); + }; + } + else { + // @ts-expect-error cannot type hook function dynamically + hooks[hooksProp] = (...args) => { + let ret = hooksFunc.apply(hooks, args); + if (ret === false) { + ret = prevHook.apply(hooks, args); + } + return ret; + }; + } + } + opts.hooks = hooks; + } + // ==-- Parse WalkTokens extensions --== // + if (pack.walkTokens) { + const walkTokens = this.defaults.walkTokens; + const packWalktokens = pack.walkTokens; + opts.walkTokens = function (token) { + let values = []; + values.push(packWalktokens.call(this, token)); + if (walkTokens) { + values = values.concat(walkTokens.call(this, token)); + } + return values; + }; + } + this.defaults = { ...this.defaults, ...opts }; + }); + return this; + } + setOptions(opt) { + this.defaults = { ...this.defaults, ...opt }; + return this; + } + lexer(src, options) { + return _Lexer.lex(src, options ?? this.defaults); + } + parser(tokens, options) { + return _Parser.parse(tokens, options ?? this.defaults); + } + parseMarkdown(blockType) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const parse = (src, options) => { + const origOpt = { ...options }; + const opt = { ...this.defaults, ...origOpt }; + const throwError = this.onError(!!opt.silent, !!opt.async); + // throw error if an extension set async to true but parse was called with async: false + if (this.defaults.async === true && origOpt.async === false) { + return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.')); + } + // throw error in case of non string input + if (typeof src === 'undefined' || src === null) { + return throwError(new Error('marked(): input parameter is undefined or null')); + } + if (typeof src !== 'string') { + return throwError(new Error('marked(): input parameter is of type ' + + Object.prototype.toString.call(src) + ', string expected')); + } + if (opt.hooks) { + opt.hooks.options = opt; + opt.hooks.block = blockType; + } + const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline); + const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline); + if (opt.async) { + return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src) + .then(src => lexer(src, opt)) + .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens) + .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens) + .then(tokens => parser(tokens, opt)) + .then(html => opt.hooks ? opt.hooks.postprocess(html) : html) + .catch(throwError); + } + try { + if (opt.hooks) { + src = opt.hooks.preprocess(src); + } + let tokens = lexer(src, opt); + if (opt.hooks) { + tokens = opt.hooks.processAllTokens(tokens); + } + if (opt.walkTokens) { + this.walkTokens(tokens, opt.walkTokens); + } + let html = parser(tokens, opt); + if (opt.hooks) { + html = opt.hooks.postprocess(html); + } + return html; + } + catch (e) { + return throwError(e); + } + }; + return parse; + } + onError(silent, async) { + return (e) => { + e.message += '\nPlease report this to https://github.com/markedjs/marked.'; + if (silent) { + const msg = '

    An error occurred:

    '
    +                        + escape(e.message + '', true)
    +                        + '
    '; + if (async) { + return Promise.resolve(msg); + } + return msg; + } + if (async) { + return Promise.reject(e); + } + throw e; + }; + } + } + + const markedInstance = new Marked(); + function marked(src, opt) { + return markedInstance.parse(src, opt); + } + /** + * Sets the default options. + * + * @param options Hash of options + */ + marked.options = + marked.setOptions = function (options) { + markedInstance.setOptions(options); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; + }; + /** + * Gets the original marked default options. + */ + marked.getDefaults = _getDefaults; + marked.defaults = exports.defaults; + /** + * Use Extension + */ + marked.use = function (...args) { + markedInstance.use(...args); + marked.defaults = markedInstance.defaults; + changeDefaults(marked.defaults); + return marked; + }; + /** + * Run callback for every token + */ + marked.walkTokens = function (tokens, callback) { + return markedInstance.walkTokens(tokens, callback); + }; + /** + * Compiles markdown to HTML without enclosing `p` tag. + * + * @param src String of markdown source to be compiled + * @param options Hash of options + * @return String of compiled HTML + */ + marked.parseInline = markedInstance.parseInline; + /** + * Expose + */ + marked.Parser = _Parser; + marked.parser = _Parser.parse; + marked.Renderer = _Renderer; + marked.TextRenderer = _TextRenderer; + marked.Lexer = _Lexer; + marked.lexer = _Lexer.lex; + marked.Tokenizer = _Tokenizer; + marked.Hooks = _Hooks; + marked.parse = marked; + const options = marked.options; + const setOptions = marked.setOptions; + const use = marked.use; + const walkTokens = marked.walkTokens; + const parseInline = marked.parseInline; + const parse = marked; + const parser = _Parser.parse; + const lexer = _Lexer.lex; + + exports.Hooks = _Hooks; + exports.Lexer = _Lexer; + exports.Marked = Marked; + exports.Parser = _Parser; + exports.Renderer = _Renderer; + exports.TextRenderer = _TextRenderer; + exports.Tokenizer = _Tokenizer; + exports.getDefaults = _getDefaults; + exports.lexer = lexer; + exports.marked = marked; + exports.options = options; + exports.parse = parse; + exports.parseInline = parseInline; + exports.parser = parser; + exports.setOptions = setOptions; + exports.use = use; + exports.walkTokens = walkTokens; + +})); +//# sourceMappingURL=marked.umd.js.map diff --git a/docs/node_modules/marked/lib/marked.umd.js.map b/docs/node_modules/marked/lib/marked.umd.js.map new file mode 100644 index 00000000..906a2b63 --- /dev/null +++ b/docs/node_modules/marked/lib/marked.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"marked.umd.js","sources":["../src/defaults.ts","../src/rules.ts","../src/helpers.ts","../src/Tokenizer.ts","../src/Lexer.ts","../src/Renderer.ts","../src/TextRenderer.ts","../src/Parser.ts","../src/Hooks.ts","../src/Instance.ts","../src/marked.ts"],"sourcesContent":["/**\n * Gets the original marked default options.\n */\nexport function _getDefaults() {\n return {\n async: false,\n breaks: false,\n extensions: null,\n gfm: true,\n hooks: null,\n pedantic: false,\n renderer: null,\n silent: false,\n tokenizer: null,\n walkTokens: null,\n };\n}\nexport let _defaults = _getDefaults();\nexport function changeDefaults(newDefaults) {\n _defaults = newDefaults;\n}\n","const noopTest = { exec: () => null };\nfunction edit(regex, opt = '') {\n let source = typeof regex === 'string' ? regex : regex.source;\n const obj = {\n replace: (name, val) => {\n let valSource = typeof val === 'string' ? val : val.source;\n valSource = valSource.replace(other.caret, '$1');\n source = source.replace(name, valSource);\n return obj;\n },\n getRegex: () => {\n return new RegExp(source, opt);\n },\n };\n return obj;\n}\nexport const other = {\n codeRemoveIndent: /^(?: {1,4}| {0,3}\\t)/gm,\n outputLinkReplace: /\\\\([\\[\\]])/g,\n indentCodeCompensation: /^(\\s+)(?:```)/,\n beginningSpace: /^\\s+/,\n endingHash: /#$/,\n startingSpaceChar: /^ /,\n endingSpaceChar: / $/,\n nonSpaceChar: /[^ ]/,\n newLineCharGlobal: /\\n/g,\n tabCharGlobal: /\\t/g,\n multipleSpaceGlobal: /\\s+/g,\n blankLine: /^[ \\t]*$/,\n doubleBlankLine: /\\n[ \\t]*\\n[ \\t]*$/,\n blockquoteStart: /^ {0,3}>/,\n blockquoteSetextReplace: /\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,\n blockquoteSetextReplace2: /^ {0,3}>[ \\t]?/gm,\n listReplaceTabs: /^\\t+/,\n listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,\n listIsTask: /^\\[[ xX]\\] /,\n listReplaceTask: /^\\[[ xX]\\] +/,\n anyLine: /\\n.*\\n/,\n hrefBrackets: /^<(.*)>$/,\n tableDelimiter: /[:|]/,\n tableAlignChars: /^\\||\\| *$/g,\n tableRowBlankLine: /\\n[ \\t]*$/,\n tableAlignRight: /^ *-+: *$/,\n tableAlignCenter: /^ *:-+: *$/,\n tableAlignLeft: /^ *:-+ *$/,\n startATag: /^
    /i,\n startPreScriptTag: /^<(pre|code|kbd|script)(\\s|>)/i,\n endPreScriptTag: /^<\\/(pre|code|kbd|script)(\\s|>)/i,\n startAngleBracket: /^$/,\n pedanticHrefTitle: /^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,\n unicodeAlphaNumeric: /[\\p{L}\\p{N}]/u,\n escapeTest: /[&<>\"']/,\n escapeReplace: /[&<>\"']/g,\n escapeTestNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,\n escapeReplaceNoEncode: /[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,\n unescapeTest: /&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,\n caret: /(^|[^\\[])\\^/g,\n percentDecode: /%25/g,\n findPipe: /\\|/g,\n splitPipe: / \\|/,\n slashPipe: /\\\\\\|/g,\n carriageReturn: /\\r\\n|\\r/g,\n spaceLine: /^ +$/gm,\n notSpaceStart: /^\\S*/,\n endingNewline: /\\n$/,\n listItemRegex: (bull) => new RegExp(`^( {0,3}${bull})((?:[\\t ][^\\\\n]*)?(?:\\\\n|$))`),\n nextBulletRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \\t][^\\\\n]*)?(?:\\\\n|$))`),\n hrRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),\n fencesBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\\`\\`\\`|~~~)`),\n headingBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),\n htmlBeginRegex: (indent) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<(?:[a-z].*>|!--)`, 'i'),\n};\n/**\n * Block-Level Grammar\n */\nconst newline = /^(?:[ \\t]*(?:\\n|$))+/;\nconst blockCode = /^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/;\nconst fences = /^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/;\nconst hr = /^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/;\nconst heading = /^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/;\nconst bullet = /(?:[*+-]|\\d{1,9}[.)])/;\nconst lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/)\n .replace(/bull/g, bullet) // lists can interrupt\n .replace(/blockCode/g, /(?: {4}| {0,3}\\t)/) // indented code blocks can interrupt\n .replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/) // fenced code blocks can interrupt\n .replace(/blockquote/g, / {0,3}>/) // blockquote can interrupt\n .replace(/heading/g, / {0,3}#{1,6}/) // ATX heading can interrupt\n .replace(/html/g, / {0,3}<[^\\n>]+>\\n/) // block html can interrupt\n .getRegex();\nconst _paragraph = /^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/;\nconst blockText = /^[^\\n]+/;\nconst _blockLabel = /(?!\\s*\\])(?:\\\\.|[^\\[\\]\\\\])+/;\nconst def = edit(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/)\n .replace('label', _blockLabel)\n .replace('title', /(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/)\n .getRegex();\nconst list = edit(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/)\n .replace(/bull/g, bullet)\n .getRegex();\nconst _tag = 'address|article|aside|base|basefont|blockquote|body|caption'\n + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption'\n + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe'\n + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option'\n + '|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title'\n + '|tr|track|ul';\nconst _comment = /|$))/;\nconst html = edit('^ {0,3}(?:' // optional indentation\n + '<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:[^\\\\n]*\\\\n+|$)' // (1)\n + '|comment[^\\\\n]*(\\\\n+|$)' // (2)\n + '|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)' // (3)\n + '|\\\\n*|$)' // (4)\n + '|\\\\n*|$)' // (5)\n + '|)[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (6)\n + '|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) open tag\n + '|(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \\t]*)+\\\\n|$)' // (7) closing tag\n + ')', 'i')\n .replace('comment', _comment)\n .replace('tag', _tag)\n .replace('attribute', / +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst paragraph = edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex();\nconst blockquote = edit(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/)\n .replace('paragraph', paragraph)\n .getRegex();\n/**\n * Normal Block Grammar\n */\nconst blockNormal = {\n blockquote,\n code: blockCode,\n def,\n fences,\n heading,\n hr,\n html,\n lheading,\n list,\n newline,\n paragraph,\n table: noopTest,\n text: blockText,\n};\n/**\n * GFM Block Grammar\n */\nconst gfmTable = edit('^ *([^\\\\n ].*)\\\\n' // Header\n + ' {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)' // Align\n + '(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)') // Cells\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('blockquote', ' {0,3}>')\n .replace('code', '(?: {4}| {0,3}\\t)[^\\\\n]')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // tables can be interrupted by type (6) html blocks\n .getRegex();\nconst blockGfm = {\n ...blockNormal,\n table: gfmTable,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' {0,3}#{1,6}(?:\\\\s|$)')\n .replace('|lheading', '') // setext headings don't interrupt commonmark paragraphs\n .replace('table', gfmTable) // interrupt paragraphs with table\n .replace('blockquote', ' {0,3}>')\n .replace('fences', ' {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n')\n .replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt\n .replace('html', ')|<(?:script|pre|style|textarea|!--)')\n .replace('tag', _tag) // pars can be interrupted by type (6) html blocks\n .getRegex(),\n};\n/**\n * Pedantic grammar (original John Gruber's loose markdown specification)\n */\nconst blockPedantic = {\n ...blockNormal,\n html: edit('^ *(?:comment *(?:\\\\n|\\\\s*$)'\n + '|<(tag)[\\\\s\\\\S]+? *(?:\\\\n{2,}|\\\\s*$)' // closed tag\n + '|\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))')\n .replace('comment', _comment)\n .replace(/tag/g, '(?!(?:'\n + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub'\n + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)'\n + '\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b')\n .getRegex(),\n def: /^ *\\[([^\\]]+)\\]: *]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,\n heading: /^(#{1,6})(.*)(?:\\n+|$)/,\n fences: noopTest, // fences not supported\n lheading: /^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,\n paragraph: edit(_paragraph)\n .replace('hr', hr)\n .replace('heading', ' *#{1,6} *[^\\n]')\n .replace('lheading', lheading)\n .replace('|table', '')\n .replace('blockquote', ' {0,3}>')\n .replace('|fences', '')\n .replace('|list', '')\n .replace('|html', '')\n .replace('|tag', '')\n .getRegex(),\n};\n/**\n * Inline-Level Grammar\n */\nconst escape = /^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/;\nconst inlineCode = /^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/;\nconst br = /^( {2,}|\\\\)\\n(?!\\s*$)/;\nconst inlineText = /^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\\nconst blockSkip = /\\[[^[\\]]*?\\]\\((?:\\\\.|[^\\\\\\(\\)]|\\((?:\\\\.|[^\\\\\\(\\)])*\\))*\\)|`[^`]*?`|<[^<>]*?>/g;\nconst emStrongLDelim = edit(/^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/, 'u')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst emStrongRDelimAst = edit('^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)' // Skip orphan inside strong\n + '|[^*]+(?=[^*])' // Consume to delim\n + '|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)' // (1) #*** can only be a Right Delimiter\n + '|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)' // (2) a***#, a*** can only be a Right Delimiter\n + '|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)' // (3) #***a, ***a can only be Left Delimiter\n + '|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)' // (4) ***# can only be Left Delimiter\n + '|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)' // (5) #***# can be either Left or Right Delimiter\n + '|notPunctSpace(\\\\*+)(?=notPunctSpace)', 'gu') // (6) a***a can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\n// (6) Not allowed for _\nconst emStrongRDelimUnd = edit('^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)' // Skip orphan inside strong\n + '|[^_]+(?=[^_])' // Consume to delim\n + '|(?!_)punct(_+)(?=[\\\\s]|$)' // (1) #___ can only be a Right Delimiter\n + '|notPunctSpace(_+)(?!_)(?=punctSpace|$)' // (2) a___#, a___ can only be a Right Delimiter\n + '|(?!_)punctSpace(_+)(?=notPunctSpace)' // (3) #___a, ___a can only be Left Delimiter\n + '|[\\\\s](_+)(?!_)(?=punct)' // (4) ___# can only be Left Delimiter\n + '|(?!_)punct(_+)(?!_)(?=punct)', 'gu') // (5) #___# can be either Left or Right Delimiter\n .replace(/notPunctSpace/g, _notPunctuationOrSpace)\n .replace(/punctSpace/g, _punctuationOrSpace)\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst anyPunctuation = edit(/\\\\(punct)/, 'gu')\n .replace(/punct/g, _punctuation)\n .getRegex();\nconst autolink = edit(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/)\n .replace('scheme', /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/)\n .replace('email', /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/)\n .getRegex();\nconst _inlineComment = edit(_comment).replace('(?:-->|$)', '-->').getRegex();\nconst tag = edit('^comment'\n + '|^' // self-closing tag\n + '|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>' // open tag\n + '|^<\\\\?[\\\\s\\\\S]*?\\\\?>' // processing instruction, e.g. \n + '|^' // declaration, e.g. \n + '|^') // CDATA section\n .replace('comment', _inlineComment)\n .replace('attribute', /\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/)\n .getRegex();\nconst _inlineLabel = /(?:\\[(?:\\\\.|[^\\[\\]\\\\])*\\]|\\\\.|`[^`]*`|[^\\[\\]\\\\`])*?/;\nconst link = edit(/^!?\\[(label)\\]\\(\\s*(href)(?:\\s+(title))?\\s*\\)/)\n .replace('label', _inlineLabel)\n .replace('href', /<(?:\\\\.|[^\\n<>\\\\])+>|[^\\s\\x00-\\x1f]*/)\n .replace('title', /\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/)\n .getRegex();\nconst reflink = edit(/^!?\\[(label)\\]\\[(ref)\\]/)\n .replace('label', _inlineLabel)\n .replace('ref', _blockLabel)\n .getRegex();\nconst nolink = edit(/^!?\\[(ref)\\](?:\\[\\])?/)\n .replace('ref', _blockLabel)\n .getRegex();\nconst reflinkSearch = edit('reflink|nolink(?!\\\\()', 'g')\n .replace('reflink', reflink)\n .replace('nolink', nolink)\n .getRegex();\n/**\n * Normal Inline Grammar\n */\nconst inlineNormal = {\n _backpedal: noopTest, // only used for GFM url\n anyPunctuation,\n autolink,\n blockSkip,\n br,\n code: inlineCode,\n del: noopTest,\n emStrongLDelim,\n emStrongRDelimAst,\n emStrongRDelimUnd,\n escape,\n link,\n nolink,\n punctuation,\n reflink,\n reflinkSearch,\n tag,\n text: inlineText,\n url: noopTest,\n};\n/**\n * Pedantic Inline Grammar\n */\nconst inlinePedantic = {\n ...inlineNormal,\n link: edit(/^!?\\[(label)\\]\\((.*?)\\)/)\n .replace('label', _inlineLabel)\n .getRegex(),\n reflink: edit(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/)\n .replace('label', _inlineLabel)\n .getRegex(),\n};\n/**\n * GFM Inline Grammar\n */\nconst inlineGfm = {\n ...inlineNormal,\n escape: edit(escape).replace('])', '~|])').getRegex(),\n url: edit(/^((?:ftp|https?):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/, 'i')\n .replace('email', /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/)\n .getRegex(),\n _backpedal: /(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,\n del: /^(~~?)(?=[^\\s~])((?:\\\\.|[^\\\\])*?(?:\\\\.|[^\\s~\\\\]))\\1(?=[^~]|$)/,\n text: /^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\': '>',\n '\"': '"',\n \"'\": ''',\n};\nconst getEscapeReplacement = (ch) => escapeReplacements[ch];\nexport function escape(html, encode) {\n if (encode) {\n if (other.escapeTest.test(html)) {\n return html.replace(other.escapeReplace, getEscapeReplacement);\n }\n }\n else {\n if (other.escapeTestNoEncode.test(html)) {\n return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);\n }\n }\n return html;\n}\nexport function unescape(html) {\n // explicitly match decimal, hex, and named HTML entities\n return html.replace(other.unescapeTest, (_, n) => {\n n = n.toLowerCase();\n if (n === 'colon')\n return ':';\n if (n.charAt(0) === '#') {\n return n.charAt(1) === 'x'\n ? String.fromCharCode(parseInt(n.substring(2), 16))\n : String.fromCharCode(+n.substring(1));\n }\n return '';\n });\n}\nexport function cleanUrl(href) {\n try {\n href = encodeURI(href).replace(other.percentDecode, '%');\n }\n catch {\n return null;\n }\n return href;\n}\nexport function splitCells(tableRow, count) {\n // ensure that every cell-delimiting pipe has a space\n // before it to distinguish it from an escaped pipe\n const row = tableRow.replace(other.findPipe, (match, offset, str) => {\n let escaped = false;\n let curr = offset;\n while (--curr >= 0 && str[curr] === '\\\\')\n escaped = !escaped;\n if (escaped) {\n // odd number of slashes means | is escaped\n // so we leave it alone\n return '|';\n }\n else {\n // add space before unescaped |\n return ' |';\n }\n }), cells = row.split(other.splitPipe);\n let i = 0;\n // First/last cell in a row cannot be empty if it has no leading/trailing pipe\n if (!cells[0].trim()) {\n cells.shift();\n }\n if (cells.length > 0 && !cells.at(-1)?.trim()) {\n cells.pop();\n }\n if (count) {\n if (cells.length > count) {\n cells.splice(count);\n }\n else {\n while (cells.length < count)\n cells.push('');\n }\n }\n for (; i < cells.length; i++) {\n // leading or trailing whitespace is ignored per the gfm spec\n cells[i] = cells[i].trim().replace(other.slashPipe, '|');\n }\n return cells;\n}\n/**\n * Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').\n * /c*$/ is vulnerable to REDOS.\n *\n * @param str\n * @param c\n * @param invert Remove suffix of non-c chars instead. Default falsey.\n */\nexport function rtrim(str, c, invert) {\n const l = str.length;\n if (l === 0) {\n return '';\n }\n // Length of suffix matching the invert condition.\n let suffLen = 0;\n // Step left until we fail to match the invert condition.\n while (suffLen < l) {\n const currChar = str.charAt(l - suffLen - 1);\n if (currChar === c && !invert) {\n suffLen++;\n }\n else if (currChar !== c && invert) {\n suffLen++;\n }\n else {\n break;\n }\n }\n return str.slice(0, l - suffLen);\n}\nexport function findClosingBracket(str, b) {\n if (str.indexOf(b[1]) === -1) {\n return -1;\n }\n let level = 0;\n for (let i = 0; i < str.length; i++) {\n if (str[i] === '\\\\') {\n i++;\n }\n else if (str[i] === b[0]) {\n level++;\n }\n else if (str[i] === b[1]) {\n level--;\n if (level < 0) {\n return i;\n }\n }\n }\n return -1;\n}\n","import { _defaults } from './defaults.ts';\nimport { rtrim, splitCells, findClosingBracket, } from './helpers.ts';\nfunction outputLink(cap, link, raw, lexer, rules) {\n const href = link.href;\n const title = link.title || null;\n const text = cap[1].replace(rules.other.outputLinkReplace, '$1');\n if (cap[0].charAt(0) !== '!') {\n lexer.state.inLink = true;\n const token = {\n type: 'link',\n raw,\n href,\n title,\n text,\n tokens: lexer.inlineTokens(text),\n };\n lexer.state.inLink = false;\n return token;\n }\n return {\n type: 'image',\n raw,\n href,\n title,\n text,\n };\n}\nfunction indentCodeCompensation(raw, text, rules) {\n const matchIndentToCode = raw.match(rules.other.indentCodeCompensation);\n if (matchIndentToCode === null) {\n return text;\n }\n const indentToCode = matchIndentToCode[1];\n return text\n .split('\\n')\n .map(node => {\n const matchIndentInNode = node.match(rules.other.beginningSpace);\n if (matchIndentInNode === null) {\n return node;\n }\n const [indentInNode] = matchIndentInNode;\n if (indentInNode.length >= indentToCode.length) {\n return node.slice(indentToCode.length);\n }\n return node;\n })\n .join('\\n');\n}\n/**\n * Tokenizer\n */\nexport class _Tokenizer {\n options;\n rules; // set by the lexer\n lexer; // set by the lexer\n constructor(options) {\n this.options = options || _defaults;\n }\n space(src) {\n const cap = this.rules.block.newline.exec(src);\n if (cap && cap[0].length > 0) {\n return {\n type: 'space',\n raw: cap[0],\n };\n }\n }\n code(src) {\n const cap = this.rules.block.code.exec(src);\n if (cap) {\n const text = cap[0].replace(this.rules.other.codeRemoveIndent, '');\n return {\n type: 'code',\n raw: cap[0],\n codeBlockStyle: 'indented',\n text: !this.options.pedantic\n ? rtrim(text, '\\n')\n : text,\n };\n }\n }\n fences(src) {\n const cap = this.rules.block.fences.exec(src);\n if (cap) {\n const raw = cap[0];\n const text = indentCodeCompensation(raw, cap[3] || '', this.rules);\n return {\n type: 'code',\n raw,\n lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, '$1') : cap[2],\n text,\n };\n }\n }\n heading(src) {\n const cap = this.rules.block.heading.exec(src);\n if (cap) {\n let text = cap[2].trim();\n // remove trailing #s\n if (this.rules.other.endingHash.test(text)) {\n const trimmed = rtrim(text, '#');\n if (this.options.pedantic) {\n text = trimmed.trim();\n }\n else if (!trimmed || this.rules.other.endingSpaceChar.test(trimmed)) {\n // CommonMark requires space before trailing #s\n text = trimmed.trim();\n }\n }\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[1].length,\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n hr(src) {\n const cap = this.rules.block.hr.exec(src);\n if (cap) {\n return {\n type: 'hr',\n raw: rtrim(cap[0], '\\n'),\n };\n }\n }\n blockquote(src) {\n const cap = this.rules.block.blockquote.exec(src);\n if (cap) {\n let lines = rtrim(cap[0], '\\n').split('\\n');\n let raw = '';\n let text = '';\n const tokens = [];\n while (lines.length > 0) {\n let inBlockquote = false;\n const currentLines = [];\n let i;\n for (i = 0; i < lines.length; i++) {\n // get lines up to a continuation\n if (this.rules.other.blockquoteStart.test(lines[i])) {\n currentLines.push(lines[i]);\n inBlockquote = true;\n }\n else if (!inBlockquote) {\n currentLines.push(lines[i]);\n }\n else {\n break;\n }\n }\n lines = lines.slice(i);\n const currentRaw = currentLines.join('\\n');\n const currentText = currentRaw\n // precede setext continuation with 4 spaces so it isn't a setext\n .replace(this.rules.other.blockquoteSetextReplace, '\\n $1')\n .replace(this.rules.other.blockquoteSetextReplace2, '');\n raw = raw ? `${raw}\\n${currentRaw}` : currentRaw;\n text = text ? `${text}\\n${currentText}` : currentText;\n // parse blockquote lines as top level tokens\n // merge paragraphs if this is a continuation\n const top = this.lexer.state.top;\n this.lexer.state.top = true;\n this.lexer.blockTokens(currentText, tokens, true);\n this.lexer.state.top = top;\n // if there is no continuation then we are done\n if (lines.length === 0) {\n break;\n }\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'code') {\n // blockquote continuation cannot be preceded by a code block\n break;\n }\n else if (lastToken?.type === 'blockquote') {\n // include continuation in nested blockquote\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.blockquote(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.text.length) + newToken.text;\n break;\n }\n else if (lastToken?.type === 'list') {\n // include continuation in nested list\n const oldToken = lastToken;\n const newText = oldToken.raw + '\\n' + lines.join('\\n');\n const newToken = this.list(newText);\n tokens[tokens.length - 1] = newToken;\n raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;\n text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;\n lines = newText.substring(tokens.at(-1).raw.length).split('\\n');\n continue;\n }\n }\n return {\n type: 'blockquote',\n raw,\n tokens,\n text,\n };\n }\n }\n list(src) {\n let cap = this.rules.block.list.exec(src);\n if (cap) {\n let bull = cap[1].trim();\n const isordered = bull.length > 1;\n const list = {\n type: 'list',\n raw: '',\n ordered: isordered,\n start: isordered ? +bull.slice(0, -1) : '',\n loose: false,\n items: [],\n };\n bull = isordered ? `\\\\d{1,9}\\\\${bull.slice(-1)}` : `\\\\${bull}`;\n if (this.options.pedantic) {\n bull = isordered ? bull : '[*+-]';\n }\n // Get next list item\n const itemRegex = this.rules.other.listItemRegex(bull);\n let endsWithBlankLine = false;\n // Check if current bullet point can start a new List Item\n while (src) {\n let endEarly = false;\n let raw = '';\n let itemContents = '';\n if (!(cap = itemRegex.exec(src))) {\n break;\n }\n if (this.rules.block.hr.test(src)) { // End list if bullet was actually HR (possibly move into itemRegex?)\n break;\n }\n raw = cap[0];\n src = src.substring(raw.length);\n let line = cap[2].split('\\n', 1)[0].replace(this.rules.other.listReplaceTabs, (t) => ' '.repeat(3 * t.length));\n let nextLine = src.split('\\n', 1)[0];\n let blankLine = !line.trim();\n let indent = 0;\n if (this.options.pedantic) {\n indent = 2;\n itemContents = line.trimStart();\n }\n else if (blankLine) {\n indent = cap[1].length + 1;\n }\n else {\n indent = cap[2].search(this.rules.other.nonSpaceChar); // Find first non-space char\n indent = indent > 4 ? 1 : indent; // Treat indented code blocks (> 4 spaces) as having only 1 indent\n itemContents = line.slice(indent);\n indent += cap[1].length;\n }\n if (blankLine && this.rules.other.blankLine.test(nextLine)) { // Items begin with at most one blank line\n raw += nextLine + '\\n';\n src = src.substring(nextLine.length + 1);\n endEarly = true;\n }\n if (!endEarly) {\n const nextBulletRegex = this.rules.other.nextBulletRegex(indent);\n const hrRegex = this.rules.other.hrRegex(indent);\n const fencesBeginRegex = this.rules.other.fencesBeginRegex(indent);\n const headingBeginRegex = this.rules.other.headingBeginRegex(indent);\n const htmlBeginRegex = this.rules.other.htmlBeginRegex(indent);\n // Check if following lines should be included in List Item\n while (src) {\n const rawLine = src.split('\\n', 1)[0];\n let nextLineWithoutTabs;\n nextLine = rawLine;\n // Re-align to follow commonmark nesting rules\n if (this.options.pedantic) {\n nextLine = nextLine.replace(this.rules.other.listReplaceNesting, ' ');\n nextLineWithoutTabs = nextLine;\n }\n else {\n nextLineWithoutTabs = nextLine.replace(this.rules.other.tabCharGlobal, ' ');\n }\n // End list item if found code fences\n if (fencesBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new heading\n if (headingBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of html block\n if (htmlBeginRegex.test(nextLine)) {\n break;\n }\n // End list item if found start of new bullet\n if (nextBulletRegex.test(nextLine)) {\n break;\n }\n // Horizontal rule found\n if (hrRegex.test(nextLine)) {\n break;\n }\n if (nextLineWithoutTabs.search(this.rules.other.nonSpaceChar) >= indent || !nextLine.trim()) { // Dedent if possible\n itemContents += '\\n' + nextLineWithoutTabs.slice(indent);\n }\n else {\n // not enough indentation\n if (blankLine) {\n break;\n }\n // paragraph continuation unless last line was a different block level element\n if (line.replace(this.rules.other.tabCharGlobal, ' ').search(this.rules.other.nonSpaceChar) >= 4) { // indented code block\n break;\n }\n if (fencesBeginRegex.test(line)) {\n break;\n }\n if (headingBeginRegex.test(line)) {\n break;\n }\n if (hrRegex.test(line)) {\n break;\n }\n itemContents += '\\n' + nextLine;\n }\n if (!blankLine && !nextLine.trim()) { // Check if current line is blank\n blankLine = true;\n }\n raw += rawLine + '\\n';\n src = src.substring(rawLine.length + 1);\n line = nextLineWithoutTabs.slice(indent);\n }\n }\n if (!list.loose) {\n // If the previous item ended with a blank line, the list is loose\n if (endsWithBlankLine) {\n list.loose = true;\n }\n else if (this.rules.other.doubleBlankLine.test(raw)) {\n endsWithBlankLine = true;\n }\n }\n let istask = null;\n let ischecked;\n // Check for task list items\n if (this.options.gfm) {\n istask = this.rules.other.listIsTask.exec(itemContents);\n if (istask) {\n ischecked = istask[0] !== '[ ] ';\n itemContents = itemContents.replace(this.rules.other.listReplaceTask, '');\n }\n }\n list.items.push({\n type: 'list_item',\n raw,\n task: !!istask,\n checked: ischecked,\n loose: false,\n text: itemContents,\n tokens: [],\n });\n list.raw += raw;\n }\n // Do not consume newlines at end of final item. Alternatively, make itemRegex *start* with any newlines to simplify/speed up endsWithBlankLine logic\n const lastItem = list.items.at(-1);\n if (lastItem) {\n lastItem.raw = lastItem.raw.trimEnd();\n lastItem.text = lastItem.text.trimEnd();\n }\n list.raw = list.raw.trimEnd();\n // Item child tokens handled here at end because we needed to have the final item to trim it first\n for (let i = 0; i < list.items.length; i++) {\n this.lexer.state.top = false;\n list.items[i].tokens = this.lexer.blockTokens(list.items[i].text, []);\n if (!list.loose) {\n // Check if list should be loose\n const spacers = list.items[i].tokens.filter(t => t.type === 'space');\n const hasMultipleLineBreaks = spacers.length > 0 && spacers.some(t => this.rules.other.anyLine.test(t.raw));\n list.loose = hasMultipleLineBreaks;\n }\n }\n // Set all items to loose if list is loose\n if (list.loose) {\n for (let i = 0; i < list.items.length; i++) {\n list.items[i].loose = true;\n }\n }\n return list;\n }\n }\n html(src) {\n const cap = this.rules.block.html.exec(src);\n if (cap) {\n const token = {\n type: 'html',\n block: true,\n raw: cap[0],\n pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',\n text: cap[0],\n };\n return token;\n }\n }\n def(src) {\n const cap = this.rules.block.def.exec(src);\n if (cap) {\n const tag = cap[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, ' ');\n const href = cap[2] ? cap[2].replace(this.rules.other.hrefBrackets, '$1').replace(this.rules.inline.anyPunctuation, '$1') : '';\n const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, '$1') : cap[3];\n return {\n type: 'def',\n tag,\n raw: cap[0],\n href,\n title,\n };\n }\n }\n table(src) {\n const cap = this.rules.block.table.exec(src);\n if (!cap) {\n return;\n }\n if (!this.rules.other.tableDelimiter.test(cap[2])) {\n // delimiter row must have a pipe (|) or colon (:) otherwise it is a setext heading\n return;\n }\n const headers = splitCells(cap[1]);\n const aligns = cap[2].replace(this.rules.other.tableAlignChars, '').split('|');\n const rows = cap[3]?.trim() ? cap[3].replace(this.rules.other.tableRowBlankLine, '').split('\\n') : [];\n const item = {\n type: 'table',\n raw: cap[0],\n header: [],\n align: [],\n rows: [],\n };\n if (headers.length !== aligns.length) {\n // header and align columns must be equal, rows can be different.\n return;\n }\n for (const align of aligns) {\n if (this.rules.other.tableAlignRight.test(align)) {\n item.align.push('right');\n }\n else if (this.rules.other.tableAlignCenter.test(align)) {\n item.align.push('center');\n }\n else if (this.rules.other.tableAlignLeft.test(align)) {\n item.align.push('left');\n }\n else {\n item.align.push(null);\n }\n }\n for (let i = 0; i < headers.length; i++) {\n item.header.push({\n text: headers[i],\n tokens: this.lexer.inline(headers[i]),\n header: true,\n align: item.align[i],\n });\n }\n for (const row of rows) {\n item.rows.push(splitCells(row, item.header.length).map((cell, i) => {\n return {\n text: cell,\n tokens: this.lexer.inline(cell),\n header: false,\n align: item.align[i],\n };\n }));\n }\n return item;\n }\n lheading(src) {\n const cap = this.rules.block.lheading.exec(src);\n if (cap) {\n return {\n type: 'heading',\n raw: cap[0],\n depth: cap[2].charAt(0) === '=' ? 1 : 2,\n text: cap[1],\n tokens: this.lexer.inline(cap[1]),\n };\n }\n }\n paragraph(src) {\n const cap = this.rules.block.paragraph.exec(src);\n if (cap) {\n const text = cap[1].charAt(cap[1].length - 1) === '\\n'\n ? cap[1].slice(0, -1)\n : cap[1];\n return {\n type: 'paragraph',\n raw: cap[0],\n text,\n tokens: this.lexer.inline(text),\n };\n }\n }\n text(src) {\n const cap = this.rules.block.text.exec(src);\n if (cap) {\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n tokens: this.lexer.inline(cap[0]),\n };\n }\n }\n escape(src) {\n const cap = this.rules.inline.escape.exec(src);\n if (cap) {\n return {\n type: 'escape',\n raw: cap[0],\n text: cap[1],\n };\n }\n }\n tag(src) {\n const cap = this.rules.inline.tag.exec(src);\n if (cap) {\n if (!this.lexer.state.inLink && this.rules.other.startATag.test(cap[0])) {\n this.lexer.state.inLink = true;\n }\n else if (this.lexer.state.inLink && this.rules.other.endATag.test(cap[0])) {\n this.lexer.state.inLink = false;\n }\n if (!this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = true;\n }\n else if (this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(cap[0])) {\n this.lexer.state.inRawBlock = false;\n }\n return {\n type: 'html',\n raw: cap[0],\n inLink: this.lexer.state.inLink,\n inRawBlock: this.lexer.state.inRawBlock,\n block: false,\n text: cap[0],\n };\n }\n }\n link(src) {\n const cap = this.rules.inline.link.exec(src);\n if (cap) {\n const trimmedUrl = cap[2].trim();\n if (!this.options.pedantic && this.rules.other.startAngleBracket.test(trimmedUrl)) {\n // commonmark requires matching angle brackets\n if (!(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n return;\n }\n // ending angle bracket cannot be escaped\n const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\\\');\n if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {\n return;\n }\n }\n else {\n // find closing parenthesis\n const lastParenIndex = findClosingBracket(cap[2], '()');\n if (lastParenIndex > -1) {\n const start = cap[0].indexOf('!') === 0 ? 5 : 4;\n const linkLen = start + cap[1].length + lastParenIndex;\n cap[2] = cap[2].substring(0, lastParenIndex);\n cap[0] = cap[0].substring(0, linkLen).trim();\n cap[3] = '';\n }\n }\n let href = cap[2];\n let title = '';\n if (this.options.pedantic) {\n // split pedantic href and title\n const link = this.rules.other.pedanticHrefTitle.exec(href);\n if (link) {\n href = link[1];\n title = link[3];\n }\n }\n else {\n title = cap[3] ? cap[3].slice(1, -1) : '';\n }\n href = href.trim();\n if (this.rules.other.startAngleBracket.test(href)) {\n if (this.options.pedantic && !(this.rules.other.endAngleBracket.test(trimmedUrl))) {\n // pedantic allows starting angle bracket without ending angle bracket\n href = href.slice(1);\n }\n else {\n href = href.slice(1, -1);\n }\n }\n return outputLink(cap, {\n href: href ? href.replace(this.rules.inline.anyPunctuation, '$1') : href,\n title: title ? title.replace(this.rules.inline.anyPunctuation, '$1') : title,\n }, cap[0], this.lexer, this.rules);\n }\n }\n reflink(src, links) {\n let cap;\n if ((cap = this.rules.inline.reflink.exec(src))\n || (cap = this.rules.inline.nolink.exec(src))) {\n const linkString = (cap[2] || cap[1]).replace(this.rules.other.multipleSpaceGlobal, ' ');\n const link = links[linkString.toLowerCase()];\n if (!link) {\n const text = cap[0].charAt(0);\n return {\n type: 'text',\n raw: text,\n text,\n };\n }\n return outputLink(cap, link, cap[0], this.lexer, this.rules);\n }\n }\n emStrong(src, maskedSrc, prevChar = '') {\n let match = this.rules.inline.emStrongLDelim.exec(src);\n if (!match)\n return;\n // _ can't be between two alphanumerics. \\p{L}\\p{N} includes non-english alphabet/numbers as well\n if (match[3] && prevChar.match(this.rules.other.unicodeAlphaNumeric))\n return;\n const nextChar = match[1] || match[2] || '';\n if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {\n // unicode Regex counts emoji as 1 char; spread into array for proper count (used multiple times below)\n const lLength = [...match[0]].length - 1;\n let rDelim, rLength, delimTotal = lLength, midDelimTotal = 0;\n const endReg = match[0][0] === '*' ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;\n endReg.lastIndex = 0;\n // Clip maskedSrc to same section of string as src (move to lexer?)\n maskedSrc = maskedSrc.slice(-1 * src.length + lLength);\n while ((match = endReg.exec(maskedSrc)) != null) {\n rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];\n if (!rDelim)\n continue; // skip single * in __abc*abc__\n rLength = [...rDelim].length;\n if (match[3] || match[4]) { // found another Left Delim\n delimTotal += rLength;\n continue;\n }\n else if (match[5] || match[6]) { // either Left or Right Delim\n if (lLength % 3 && !((lLength + rLength) % 3)) {\n midDelimTotal += rLength;\n continue; // CommonMark Emphasis Rules 9-10\n }\n }\n delimTotal -= rLength;\n if (delimTotal > 0)\n continue; // Haven't found enough closing delimiters\n // Remove extra characters. *a*** -> *a*\n rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);\n // char length can be >1 for unicode characters;\n const lastCharLength = [...match[0]][0].length;\n const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);\n // Create `em` if smallest delimiter has odd char count. *a***\n if (Math.min(lLength, rLength) % 2) {\n const text = raw.slice(1, -1);\n return {\n type: 'em',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n // Create 'strong' if smallest delimiter has even char count. **a***\n const text = raw.slice(2, -2);\n return {\n type: 'strong',\n raw,\n text,\n tokens: this.lexer.inlineTokens(text),\n };\n }\n }\n }\n codespan(src) {\n const cap = this.rules.inline.code.exec(src);\n if (cap) {\n let text = cap[2].replace(this.rules.other.newLineCharGlobal, ' ');\n const hasNonSpaceChars = this.rules.other.nonSpaceChar.test(text);\n const hasSpaceCharsOnBothEnds = this.rules.other.startingSpaceChar.test(text) && this.rules.other.endingSpaceChar.test(text);\n if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {\n text = text.substring(1, text.length - 1);\n }\n return {\n type: 'codespan',\n raw: cap[0],\n text,\n };\n }\n }\n br(src) {\n const cap = this.rules.inline.br.exec(src);\n if (cap) {\n return {\n type: 'br',\n raw: cap[0],\n };\n }\n }\n del(src) {\n const cap = this.rules.inline.del.exec(src);\n if (cap) {\n return {\n type: 'del',\n raw: cap[0],\n text: cap[2],\n tokens: this.lexer.inlineTokens(cap[2]),\n };\n }\n }\n autolink(src) {\n const cap = this.rules.inline.autolink.exec(src);\n if (cap) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[1];\n href = 'mailto:' + text;\n }\n else {\n text = cap[1];\n href = text;\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n url(src) {\n let cap;\n if (cap = this.rules.inline.url.exec(src)) {\n let text, href;\n if (cap[2] === '@') {\n text = cap[0];\n href = 'mailto:' + text;\n }\n else {\n // do extended autolink path validation\n let prevCapZero;\n do {\n prevCapZero = cap[0];\n cap[0] = this.rules.inline._backpedal.exec(cap[0])?.[0] ?? '';\n } while (prevCapZero !== cap[0]);\n text = cap[0];\n if (cap[1] === 'www.') {\n href = 'http://' + cap[0];\n }\n else {\n href = cap[0];\n }\n }\n return {\n type: 'link',\n raw: cap[0],\n text,\n href,\n tokens: [\n {\n type: 'text',\n raw: text,\n text,\n },\n ],\n };\n }\n }\n inlineText(src) {\n const cap = this.rules.inline.text.exec(src);\n if (cap) {\n const escaped = this.lexer.state.inRawBlock;\n return {\n type: 'text',\n raw: cap[0],\n text: cap[0],\n escaped,\n };\n }\n }\n}\n","import { _Tokenizer } from './Tokenizer.ts';\nimport { _defaults } from './defaults.ts';\nimport { other, block, inline } from './rules.ts';\n/**\n * Block Lexer\n */\nexport class _Lexer {\n tokens;\n options;\n state;\n tokenizer;\n inlineQueue;\n constructor(options) {\n // TokenList cannot be created in one go\n this.tokens = [];\n this.tokens.links = Object.create(null);\n this.options = options || _defaults;\n this.options.tokenizer = this.options.tokenizer || new _Tokenizer();\n this.tokenizer = this.options.tokenizer;\n this.tokenizer.options = this.options;\n this.tokenizer.lexer = this;\n this.inlineQueue = [];\n this.state = {\n inLink: false,\n inRawBlock: false,\n top: true,\n };\n const rules = {\n other,\n block: block.normal,\n inline: inline.normal,\n };\n if (this.options.pedantic) {\n rules.block = block.pedantic;\n rules.inline = inline.pedantic;\n }\n else if (this.options.gfm) {\n rules.block = block.gfm;\n if (this.options.breaks) {\n rules.inline = inline.breaks;\n }\n else {\n rules.inline = inline.gfm;\n }\n }\n this.tokenizer.rules = rules;\n }\n /**\n * Expose Rules\n */\n static get rules() {\n return {\n block,\n inline,\n };\n }\n /**\n * Static Lex Method\n */\n static lex(src, options) {\n const lexer = new _Lexer(options);\n return lexer.lex(src);\n }\n /**\n * Static Lex Inline Method\n */\n static lexInline(src, options) {\n const lexer = new _Lexer(options);\n return lexer.inlineTokens(src);\n }\n /**\n * Preprocessing\n */\n lex(src) {\n src = src.replace(other.carriageReturn, '\\n');\n this.blockTokens(src, this.tokens);\n for (let i = 0; i < this.inlineQueue.length; i++) {\n const next = this.inlineQueue[i];\n this.inlineTokens(next.src, next.tokens);\n }\n this.inlineQueue = [];\n return this.tokens;\n }\n blockTokens(src, tokens = [], lastParagraphClipped = false) {\n if (this.options.pedantic) {\n src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');\n }\n while (src) {\n let token;\n if (this.options.extensions?.block?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // newline\n if (token = this.tokenizer.space(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.raw.length === 1 && lastToken !== undefined) {\n // if there's a single \\n as a spacer, it's terminating the last line,\n // so move it there so that we don't get unnecessary paragraph tags\n lastToken.raw += '\\n';\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // code\n if (token = this.tokenizer.code(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n // An indented code block cannot interrupt a paragraph.\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // fences\n if (token = this.tokenizer.fences(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // heading\n if (token = this.tokenizer.heading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // hr\n if (token = this.tokenizer.hr(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // blockquote\n if (token = this.tokenizer.blockquote(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // list\n if (token = this.tokenizer.list(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // html\n if (token = this.tokenizer.html(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // def\n if (token = this.tokenizer.def(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'paragraph' || lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.raw;\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else if (!this.tokens.links[token.tag]) {\n this.tokens.links[token.tag] = {\n href: token.href,\n title: token.title,\n };\n }\n continue;\n }\n // table (gfm)\n if (token = this.tokenizer.table(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // lheading\n if (token = this.tokenizer.lheading(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // top-level paragraph\n // prevent paragraph consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startBlock) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startBlock.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {\n const lastToken = tokens.at(-1);\n if (lastParagraphClipped && lastToken?.type === 'paragraph') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n lastParagraphClipped = cutSrc.length !== src.length;\n src = src.substring(token.raw.length);\n continue;\n }\n // text\n if (token = this.tokenizer.text(src)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += '\\n' + token.raw;\n lastToken.text += '\\n' + token.text;\n this.inlineQueue.pop();\n this.inlineQueue.at(-1).src = lastToken.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n this.state.top = true;\n return tokens;\n }\n inline(src, tokens = []) {\n this.inlineQueue.push({ src, tokens });\n return tokens;\n }\n /**\n * Lexing/Compiling\n */\n inlineTokens(src, tokens = []) {\n // String with links masked to avoid interference with em and strong\n let maskedSrc = src;\n let match = null;\n // Mask out reflinks\n if (this.tokens.links) {\n const links = Object.keys(this.tokens.links);\n if (links.length > 0) {\n while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {\n if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {\n maskedSrc = maskedSrc.slice(0, match.index)\n + '[' + 'a'.repeat(match[0].length - 2) + ']'\n + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);\n }\n }\n }\n }\n // Mask out other blocks\n while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '[' + 'a'.repeat(match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);\n }\n // Mask out escaped characters\n while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {\n maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);\n }\n let keepPrevChar = false;\n let prevChar = '';\n while (src) {\n if (!keepPrevChar) {\n prevChar = '';\n }\n keepPrevChar = false;\n let token;\n // extensions\n if (this.options.extensions?.inline?.some((extTokenizer) => {\n if (token = extTokenizer.call({ lexer: this }, src, tokens)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n return true;\n }\n return false;\n })) {\n continue;\n }\n // escape\n if (token = this.tokenizer.escape(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // tag\n if (token = this.tokenizer.tag(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // link\n if (token = this.tokenizer.link(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // reflink, nolink\n if (token = this.tokenizer.reflink(src, this.tokens.links)) {\n src = src.substring(token.raw.length);\n const lastToken = tokens.at(-1);\n if (token.type === 'text' && lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n // em & strong\n if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // code\n if (token = this.tokenizer.codespan(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // br\n if (token = this.tokenizer.br(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // del (gfm)\n if (token = this.tokenizer.del(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // autolink\n if (token = this.tokenizer.autolink(src)) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // url (gfm)\n if (!this.state.inLink && (token = this.tokenizer.url(src))) {\n src = src.substring(token.raw.length);\n tokens.push(token);\n continue;\n }\n // text\n // prevent inlineText consuming extensions by clipping 'src' to extension start\n let cutSrc = src;\n if (this.options.extensions?.startInline) {\n let startIndex = Infinity;\n const tempSrc = src.slice(1);\n let tempStart;\n this.options.extensions.startInline.forEach((getStartIndex) => {\n tempStart = getStartIndex.call({ lexer: this }, tempSrc);\n if (typeof tempStart === 'number' && tempStart >= 0) {\n startIndex = Math.min(startIndex, tempStart);\n }\n });\n if (startIndex < Infinity && startIndex >= 0) {\n cutSrc = src.substring(0, startIndex + 1);\n }\n }\n if (token = this.tokenizer.inlineText(cutSrc)) {\n src = src.substring(token.raw.length);\n if (token.raw.slice(-1) !== '_') { // Track prevChar before string of ____ started\n prevChar = token.raw.slice(-1);\n }\n keepPrevChar = true;\n const lastToken = tokens.at(-1);\n if (lastToken?.type === 'text') {\n lastToken.raw += token.raw;\n lastToken.text += token.text;\n }\n else {\n tokens.push(token);\n }\n continue;\n }\n if (src) {\n const errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);\n if (this.options.silent) {\n console.error(errMsg);\n break;\n }\n else {\n throw new Error(errMsg);\n }\n }\n }\n return tokens;\n }\n}\n","import { _defaults } from './defaults.ts';\nimport { cleanUrl, escape, } from './helpers.ts';\nimport { other } from './rules.ts';\n/**\n * Renderer\n */\nexport class _Renderer {\n options;\n parser; // set by the parser\n constructor(options) {\n this.options = options || _defaults;\n }\n space(token) {\n return '';\n }\n code({ text, lang, escaped }) {\n const langString = (lang || '').match(other.notSpaceStart)?.[0];\n const code = text.replace(other.endingNewline, '') + '\\n';\n if (!langString) {\n return '
    '\n                + (escaped ? code : escape(code, true))\n                + '
    \\n';\n }\n return '
    '\n            + (escaped ? code : escape(code, true))\n            + '
    \\n';\n }\n blockquote({ tokens }) {\n const body = this.parser.parse(tokens);\n return `
    \\n${body}
    \\n`;\n }\n html({ text }) {\n return text;\n }\n heading({ tokens, depth }) {\n return `${this.parser.parseInline(tokens)}\\n`;\n }\n hr(token) {\n return '
    \\n';\n }\n list(token) {\n const ordered = token.ordered;\n const start = token.start;\n let body = '';\n for (let j = 0; j < token.items.length; j++) {\n const item = token.items[j];\n body += this.listitem(item);\n }\n const type = ordered ? 'ol' : 'ul';\n const startAttr = (ordered && start !== 1) ? (' start=\"' + start + '\"') : '';\n return '<' + type + startAttr + '>\\n' + body + '\\n';\n }\n listitem(item) {\n let itemBody = '';\n if (item.task) {\n const checkbox = this.checkbox({ checked: !!item.checked });\n if (item.loose) {\n if (item.tokens[0]?.type === 'paragraph') {\n item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;\n if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {\n item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);\n item.tokens[0].tokens[0].escaped = true;\n }\n }\n else {\n item.tokens.unshift({\n type: 'text',\n raw: checkbox + ' ',\n text: checkbox + ' ',\n escaped: true,\n });\n }\n }\n else {\n itemBody += checkbox + ' ';\n }\n }\n itemBody += this.parser.parse(item.tokens, !!item.loose);\n return `
  • ${itemBody}
  • \\n`;\n }\n checkbox({ checked }) {\n return '';\n }\n paragraph({ tokens }) {\n return `

    ${this.parser.parseInline(tokens)}

    \\n`;\n }\n table(token) {\n let header = '';\n // header\n let cell = '';\n for (let j = 0; j < token.header.length; j++) {\n cell += this.tablecell(token.header[j]);\n }\n header += this.tablerow({ text: cell });\n let body = '';\n for (let j = 0; j < token.rows.length; j++) {\n const row = token.rows[j];\n cell = '';\n for (let k = 0; k < row.length; k++) {\n cell += this.tablecell(row[k]);\n }\n body += this.tablerow({ text: cell });\n }\n if (body)\n body = `${body}`;\n return '\\n'\n + '\\n'\n + header\n + '\\n'\n + body\n + '
    \\n';\n }\n tablerow({ text }) {\n return `\\n${text}\\n`;\n }\n tablecell(token) {\n const content = this.parser.parseInline(token.tokens);\n const type = token.header ? 'th' : 'td';\n const tag = token.align\n ? `<${type} align=\"${token.align}\">`\n : `<${type}>`;\n return tag + content + `\\n`;\n }\n /**\n * span level renderer\n */\n strong({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n em({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n codespan({ text }) {\n return `${escape(text, true)}`;\n }\n br(token) {\n return '
    ';\n }\n del({ tokens }) {\n return `${this.parser.parseInline(tokens)}`;\n }\n link({ href, title, tokens }) {\n const text = this.parser.parseInline(tokens);\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return text;\n }\n href = cleanHref;\n let out = '
    ';\n return out;\n }\n image({ href, title, text }) {\n const cleanHref = cleanUrl(href);\n if (cleanHref === null) {\n return escape(text);\n }\n href = cleanHref;\n let out = `\"${text}\"`;\n {\n const tokens = genericToken[childTokens].flat(Infinity);\n values = values.concat(this.walkTokens(tokens, callback));\n });\n }\n else if (genericToken.tokens) {\n values = values.concat(this.walkTokens(genericToken.tokens, callback));\n }\n }\n }\n }\n return values;\n }\n use(...args) {\n const extensions = this.defaults.extensions || { renderers: {}, childTokens: {} };\n args.forEach((pack) => {\n // copy options to new object\n const opts = { ...pack };\n // set async to true if it was set to true before\n opts.async = this.defaults.async || opts.async || false;\n // ==-- Parse \"addon\" extensions --== //\n if (pack.extensions) {\n pack.extensions.forEach((ext) => {\n if (!ext.name) {\n throw new Error('extension name required');\n }\n if ('renderer' in ext) { // Renderer extensions\n const prevRenderer = extensions.renderers[ext.name];\n if (prevRenderer) {\n // Replace extension with func to run new extension but fall back if false\n extensions.renderers[ext.name] = function (...args) {\n let ret = ext.renderer.apply(this, args);\n if (ret === false) {\n ret = prevRenderer.apply(this, args);\n }\n return ret;\n };\n }\n else {\n extensions.renderers[ext.name] = ext.renderer;\n }\n }\n if ('tokenizer' in ext) { // Tokenizer Extensions\n if (!ext.level || (ext.level !== 'block' && ext.level !== 'inline')) {\n throw new Error(\"extension level must be 'block' or 'inline'\");\n }\n const extLevel = extensions[ext.level];\n if (extLevel) {\n extLevel.unshift(ext.tokenizer);\n }\n else {\n extensions[ext.level] = [ext.tokenizer];\n }\n if (ext.start) { // Function to check for start of token\n if (ext.level === 'block') {\n if (extensions.startBlock) {\n extensions.startBlock.push(ext.start);\n }\n else {\n extensions.startBlock = [ext.start];\n }\n }\n else if (ext.level === 'inline') {\n if (extensions.startInline) {\n extensions.startInline.push(ext.start);\n }\n else {\n extensions.startInline = [ext.start];\n }\n }\n }\n }\n if ('childTokens' in ext && ext.childTokens) { // Child tokens to be visited by walkTokens\n extensions.childTokens[ext.name] = ext.childTokens;\n }\n });\n opts.extensions = extensions;\n }\n // ==-- Parse \"overwrite\" extensions --== //\n if (pack.renderer) {\n const renderer = this.defaults.renderer || new _Renderer(this.defaults);\n for (const prop in pack.renderer) {\n if (!(prop in renderer)) {\n throw new Error(`renderer '${prop}' does not exist`);\n }\n if (['options', 'parser'].includes(prop)) {\n // ignore options property\n continue;\n }\n const rendererProp = prop;\n const rendererFunc = pack.renderer[rendererProp];\n const prevRenderer = renderer[rendererProp];\n // Replace renderer with func to run extension, but fall back if false\n renderer[rendererProp] = (...args) => {\n let ret = rendererFunc.apply(renderer, args);\n if (ret === false) {\n ret = prevRenderer.apply(renderer, args);\n }\n return ret || '';\n };\n }\n opts.renderer = renderer;\n }\n if (pack.tokenizer) {\n const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);\n for (const prop in pack.tokenizer) {\n if (!(prop in tokenizer)) {\n throw new Error(`tokenizer '${prop}' does not exist`);\n }\n if (['options', 'rules', 'lexer'].includes(prop)) {\n // ignore options, rules, and lexer properties\n continue;\n }\n const tokenizerProp = prop;\n const tokenizerFunc = pack.tokenizer[tokenizerProp];\n const prevTokenizer = tokenizer[tokenizerProp];\n // Replace tokenizer with func to run extension, but fall back if false\n // @ts-expect-error cannot type tokenizer function dynamically\n tokenizer[tokenizerProp] = (...args) => {\n let ret = tokenizerFunc.apply(tokenizer, args);\n if (ret === false) {\n ret = prevTokenizer.apply(tokenizer, args);\n }\n return ret;\n };\n }\n opts.tokenizer = tokenizer;\n }\n // ==-- Parse Hooks extensions --== //\n if (pack.hooks) {\n const hooks = this.defaults.hooks || new _Hooks();\n for (const prop in pack.hooks) {\n if (!(prop in hooks)) {\n throw new Error(`hook '${prop}' does not exist`);\n }\n if (['options', 'block'].includes(prop)) {\n // ignore options and block properties\n continue;\n }\n const hooksProp = prop;\n const hooksFunc = pack.hooks[hooksProp];\n const prevHook = hooks[hooksProp];\n if (_Hooks.passThroughHooks.has(prop)) {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (arg) => {\n if (this.defaults.async) {\n return Promise.resolve(hooksFunc.call(hooks, arg)).then(ret => {\n return prevHook.call(hooks, ret);\n });\n }\n const ret = hooksFunc.call(hooks, arg);\n return prevHook.call(hooks, ret);\n };\n }\n else {\n // @ts-expect-error cannot type hook function dynamically\n hooks[hooksProp] = (...args) => {\n let ret = hooksFunc.apply(hooks, args);\n if (ret === false) {\n ret = prevHook.apply(hooks, args);\n }\n return ret;\n };\n }\n }\n opts.hooks = hooks;\n }\n // ==-- Parse WalkTokens extensions --== //\n if (pack.walkTokens) {\n const walkTokens = this.defaults.walkTokens;\n const packWalktokens = pack.walkTokens;\n opts.walkTokens = function (token) {\n let values = [];\n values.push(packWalktokens.call(this, token));\n if (walkTokens) {\n values = values.concat(walkTokens.call(this, token));\n }\n return values;\n };\n }\n this.defaults = { ...this.defaults, ...opts };\n });\n return this;\n }\n setOptions(opt) {\n this.defaults = { ...this.defaults, ...opt };\n return this;\n }\n lexer(src, options) {\n return _Lexer.lex(src, options ?? this.defaults);\n }\n parser(tokens, options) {\n return _Parser.parse(tokens, options ?? this.defaults);\n }\n parseMarkdown(blockType) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const parse = (src, options) => {\n const origOpt = { ...options };\n const opt = { ...this.defaults, ...origOpt };\n const throwError = this.onError(!!opt.silent, !!opt.async);\n // throw error if an extension set async to true but parse was called with async: false\n if (this.defaults.async === true && origOpt.async === false) {\n return throwError(new Error('marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.'));\n }\n // throw error in case of non string input\n if (typeof src === 'undefined' || src === null) {\n return throwError(new Error('marked(): input parameter is undefined or null'));\n }\n if (typeof src !== 'string') {\n return throwError(new Error('marked(): input parameter is of type '\n + Object.prototype.toString.call(src) + ', string expected'));\n }\n if (opt.hooks) {\n opt.hooks.options = opt;\n opt.hooks.block = blockType;\n }\n const lexer = opt.hooks ? opt.hooks.provideLexer() : (blockType ? _Lexer.lex : _Lexer.lexInline);\n const parser = opt.hooks ? opt.hooks.provideParser() : (blockType ? _Parser.parse : _Parser.parseInline);\n if (opt.async) {\n return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src)\n .then(src => lexer(src, opt))\n .then(tokens => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens)\n .then(tokens => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens)\n .then(tokens => parser(tokens, opt))\n .then(html => opt.hooks ? opt.hooks.postprocess(html) : html)\n .catch(throwError);\n }\n try {\n if (opt.hooks) {\n src = opt.hooks.preprocess(src);\n }\n let tokens = lexer(src, opt);\n if (opt.hooks) {\n tokens = opt.hooks.processAllTokens(tokens);\n }\n if (opt.walkTokens) {\n this.walkTokens(tokens, opt.walkTokens);\n }\n let html = parser(tokens, opt);\n if (opt.hooks) {\n html = opt.hooks.postprocess(html);\n }\n return html;\n }\n catch (e) {\n return throwError(e);\n }\n };\n return parse;\n }\n onError(silent, async) {\n return (e) => {\n e.message += '\\nPlease report this to https://github.com/markedjs/marked.';\n if (silent) {\n const msg = '

    An error occurred:

    '\n                    + escape(e.message + '', true)\n                    + '
    ';\n if (async) {\n return Promise.resolve(msg);\n }\n return msg;\n }\n if (async) {\n return Promise.reject(e);\n }\n throw e;\n };\n }\n}\n","import { _Lexer } from './Lexer.ts';\nimport { _Parser } from './Parser.ts';\nimport { _Tokenizer } from './Tokenizer.ts';\nimport { _Renderer } from './Renderer.ts';\nimport { _TextRenderer } from './TextRenderer.ts';\nimport { _Hooks } from './Hooks.ts';\nimport { Marked } from './Instance.ts';\nimport { _getDefaults, changeDefaults, _defaults, } from './defaults.ts';\nconst markedInstance = new Marked();\nexport function marked(src, opt) {\n return markedInstance.parse(src, opt);\n}\n/**\n * Sets the default options.\n *\n * @param options Hash of options\n */\nmarked.options =\n marked.setOptions = function (options) {\n markedInstance.setOptions(options);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n };\n/**\n * Gets the original marked default options.\n */\nmarked.getDefaults = _getDefaults;\nmarked.defaults = _defaults;\n/**\n * Use Extension\n */\nmarked.use = function (...args) {\n markedInstance.use(...args);\n marked.defaults = markedInstance.defaults;\n changeDefaults(marked.defaults);\n return marked;\n};\n/**\n * Run callback for every token\n */\nmarked.walkTokens = function (tokens, callback) {\n return markedInstance.walkTokens(tokens, callback);\n};\n/**\n * Compiles markdown to HTML without enclosing `p` tag.\n *\n * @param src String of markdown source to be compiled\n * @param options Hash of options\n * @return String of compiled HTML\n */\nmarked.parseInline = markedInstance.parseInline;\n/**\n * Expose\n */\nmarked.Parser = _Parser;\nmarked.parser = _Parser.parse;\nmarked.Renderer = _Renderer;\nmarked.TextRenderer = _TextRenderer;\nmarked.Lexer = _Lexer;\nmarked.lexer = _Lexer.lex;\nmarked.Tokenizer = _Tokenizer;\nmarked.Hooks = _Hooks;\nmarked.parse = marked;\nexport const options = marked.options;\nexport const setOptions = marked.setOptions;\nexport const use = marked.use;\nexport const walkTokens = marked.walkTokens;\nexport const parseInline = marked.parseInline;\nexport const parse = marked;\nexport const parser = _Parser.parse;\nexport const lexer = _Lexer.lex;\nexport { _defaults as defaults, _getDefaults as getDefaults } from './defaults.ts';\nexport { _Lexer as Lexer } from './Lexer.ts';\nexport { _Parser as Parser } from './Parser.ts';\nexport { _Tokenizer as Tokenizer } from './Tokenizer.ts';\nexport { _Renderer as Renderer } from './Renderer.ts';\nexport { _TextRenderer as TextRenderer } from './TextRenderer.ts';\nexport { _Hooks as Hooks } from './Hooks.ts';\nexport { Marked } from './Instance.ts';\n"],"names":["_defaults","escape"],"mappings":"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"} \ No newline at end of file diff --git a/docs/node_modules/marked/man/marked.1 b/docs/node_modules/marked/man/marked.1 new file mode 100644 index 00000000..29b13a2a --- /dev/null +++ b/docs/node_modules/marked/man/marked.1 @@ -0,0 +1,111 @@ +.TH "MARKED" "1" "November 2024" "15.0.2" +.SH "NAME" +\fBmarked\fR \- a javascript markdown parser +.SH SYNOPSIS +.P +\fBmarked\fP [\fB\-o\fP ] [\fB\-i\fP ] [\fB\-s\fP ] [\fB\-c\fP ] [\fB\-\-help\fP] [\fB\-\-version\fP] [\fB\-\-tokens\fP] [\fB\-\-no\-clobber\fP] [\fB\-\-pedantic\fP] [\fB\-\-gfm\fP] [\fB\-\-breaks\fP] [\fB\-\-no\-etc\.\.\.\fP] [\fB\-\-silent\fP] [filename] +.SH DESCRIPTION +.P +marked is a full\-featured javascript markdown parser, built for speed\. +.br +It also includes multiple GFM features\. +.SH EXAMPLES +.RS 2 +.nf +cat in\.md | marked > out\.html +.fi +.RE +.RS 2 +.nf +echo "hello *world*" | marked +.fi +.RE +.RS 2 +.nf +marked \-o out\.html \-i in\.md \-\-gfm +.fi +.RE +.RS 2 +.nf +marked \-\-output="hello world\.html" \-i in\.md \-\-no\-breaks +.fi +.RE +.SH OPTIONS + +.RS 1 +.IP \(bu 2 +\-o, \-\-output [output file] +.br +Specify file output\. If none is specified, write to stdout\. +.IP \(bu 2 +\-i, \-\-input [input file] +.br +Specify file input, otherwise use last argument as input file\. +.br +If no input file is specified, read from stdin\. +.IP \(bu 2 +\-s, \-\-string [markdown string] +.br +Specify string input instead of a file\. +.IP \(bu 2 +\-c, \-\-config [config file] +.br +Specify config file to use instead of the default \fB~/\.marked\.json\fP or \fB~/\.marked\.js\fP or \fB~/\.marked/index\.js\fP\|\. +.IP \(bu 2 +\-t, \-\-tokens +.br +Output a token list instead of html\. +.IP \(bu 2 +\-n, \-\-no\-clobber +.br +Do not overwrite \fBoutput\fP if it exists\. +.IP \(bu 2 +\-\-pedantic +.br +Conform to obscure parts of markdown\.pl as much as possible\. +.br +Don't fix original markdown bugs\. +.IP \(bu 2 +\-\-gfm +.br +Enable github flavored markdown\. +.IP \(bu 2 +\-\-breaks +.br +Enable GFM line breaks\. Only works with the gfm option\. +.IP \(bu 2 +\-\-no\-breaks, \-no\-etc\.\.\. +.br +The inverse of any of the marked options above\. +.IP \(bu 2 +\-\-silent +.br +Silence error output\. +.IP \(bu 2 +\-h, \-\-help +.br +Display help information\. + +.RE +.SH CONFIGURATION +.P +For configuring and running programmatically\. +.P +Example +.RS 2 +.nf +import { Marked } from 'marked'; +const marked = new Marked({ gfm: true }); +marked\.parse('*foo*'); +.fi +.RE +.SH BUGS +.P +Please report any bugs to https://github.com/markedjs/marked +.SH LICENSE +.P +Copyright (c) 2011\-2014, Christopher Jeffrey (MIT License)\. +.SH SEE ALSO +.P +markdown(1), nodejs(1) + diff --git a/docs/node_modules/marked/man/marked.1.md b/docs/node_modules/marked/man/marked.1.md new file mode 100644 index 00000000..d5b94a45 --- /dev/null +++ b/docs/node_modules/marked/man/marked.1.md @@ -0,0 +1,92 @@ +# marked(1) -- a javascript markdown parser + +## SYNOPSIS + +`marked` [`-o` ] [`-i` ] [`-s` ] [`-c` ] [`--help`] [`--version`] [`--tokens`] [`--no-clobber`] [`--pedantic`] [`--gfm`] [`--breaks`] [`--no-etc...`] [`--silent`] [filename] + +## DESCRIPTION + +marked is a full-featured javascript markdown parser, built for speed. +It also includes multiple GFM features. + +## EXAMPLES + +```sh +cat in.md | marked > out.html +``` + +```sh +echo "hello *world*" | marked +``` + +```sh +marked -o out.html -i in.md --gfm +``` + +```sh +marked --output="hello world.html" -i in.md --no-breaks +``` + +## OPTIONS + +* -o, --output [output file] +Specify file output. If none is specified, write to stdout. + +* -i, --input [input file] +Specify file input, otherwise use last argument as input file. +If no input file is specified, read from stdin. + +* -s, --string [markdown string] +Specify string input instead of a file. + +* -c, --config [config file] +Specify config file to use instead of the default `~/.marked.json` or `~/.marked.js` or `~/.marked/index.js`. + +* -t, --tokens +Output a token list instead of html. + +* -n, --no-clobber +Do not overwrite `output` if it exists. + +* --pedantic +Conform to obscure parts of markdown.pl as much as possible. +Don't fix original markdown bugs. + +* --gfm +Enable github flavored markdown. + +* --breaks +Enable GFM line breaks. Only works with the gfm option. + +* --no-breaks, -no-etc... +The inverse of any of the marked options above. + +* --silent +Silence error output. + +* -h, --help +Display help information. + +## CONFIGURATION + +For configuring and running programmatically. + +Example + +```js +import { Marked } from 'marked'; +const marked = new Marked({ gfm: true }); +marked.parse('*foo*'); +``` + +## BUGS + +Please report any bugs to . + +## LICENSE + +Copyright (c) 2011-2014, Christopher Jeffrey (MIT License). + +## SEE ALSO + +markdown(1), nodejs(1) diff --git a/docs/node_modules/marked/marked.min.js b/docs/node_modules/marked/marked.min.js new file mode 100644 index 00000000..19825bcf --- /dev/null +++ b/docs/node_modules/marked/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked v15.0.3 - a markdown parser + * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s={exec:()=>null};function r(e,t=""){let n="string"==typeof e?e:e.source;const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(i.caret,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}const i={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^
    /i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>new RegExp(`^( {0,3}${e})((?:[\t ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),hrRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,"i")},l=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,o=/(?:[*+-]|\d{1,9}[.)])/,a=r(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,o).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).getRegex(),c=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,h=/(?!\s*\])(?:\\.|[^\[\]\\])+/,p=r(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",h).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),u=r(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,o).getRegex(),g="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",k=/|$))/,d=r("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ \t]*)+\\n|$))","i").replace("comment",k).replace("tag",g).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),f=r(c).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex(),x={blockquote:r(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",f).getRegex(),code:/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,def:p,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:l,html:d,lheading:a,list:u,newline:/^(?:[ \t]*(?:\n|$))+/,paragraph:f,table:s,text:/^[^\n]+/},b=r("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3}\t)[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex(),w={...x,table:b,paragraph:r(c).replace("hr",l).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",b).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",g).getRegex()},m={...x,html:r("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",k).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:s,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:r(c).replace("hr",l).replace("heading"," *#{1,6} *[^\n]").replace("lheading",a).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},y=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,$=/^( {2,}|\\)\n(?!\s*$)/,R=/[\p{P}\p{S}]/u,S=/[\s\p{P}\p{S}]/u,T=/[^\s\p{P}\p{S}]/u,z=r(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,S).getRegex(),A=r(/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,"u").replace(/punct/g,R).getRegex(),_=r("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)","gu").replace(/notPunctSpace/g,T).replace(/punctSpace/g,S).replace(/punct/g,R).getRegex(),P=r("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,T).replace(/punctSpace/g,S).replace(/punct/g,R).getRegex(),I=r(/\\(punct)/,"gu").replace(/punct/g,R).getRegex(),L=r(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),B=r(k).replace("(?:--\x3e|$)","--\x3e").getRegex(),C=r("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",B).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),E=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,q=r(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",E).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Z=r(/^!?\[(label)\]\[(ref)\]/).replace("label",E).replace("ref",h).getRegex(),v=r(/^!?\[(ref)\](?:\[\])?/).replace("ref",h).getRegex(),D={_backpedal:s,anyPunctuation:I,autolink:L,blockSkip:/\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g,br:$,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:s,emStrongLDelim:A,emStrongRDelimAst:_,emStrongRDelimUnd:P,escape:y,link:q,nolink:v,punctuation:z,reflink:Z,reflinkSearch:r("reflink|nolink(?!\\()","g").replace("reflink",Z).replace("nolink",v).getRegex(),tag:C,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},H=e=>G[e];function X(e,t){if(t){if(i.escapeTest.test(e))return e.replace(i.escapeReplace,H)}else if(i.escapeTestNoEncode.test(e))return e.replace(i.escapeReplaceNoEncode,H);return e}function F(e){try{e=encodeURI(e).replace(i.percentDecode,"%")}catch{return null}return e}function U(e,t){const n=e.replace(i.findPipe,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(i.splitPipe);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:J(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t,n){const s=e.match(n.other.indentCodeCompensation);if(null===s)return t;const r=s[1];return t.split("\n").map((e=>{const t=e.match(n.other.beginningSpace);if(null===t)return e;const[s]=t;return s.length>=r.length?e.slice(r.length):e})).join("\n")}(e,t[3]||"",this.rules);return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(this.rules.other.endingHash.test(e)){const t=J(e,"#");this.options.pedantic?e=t.trim():t&&!this.rules.other.endingSpaceChar.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:J(t[0],"\n")}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let e=J(t[0],"\n").split("\n"),n="",s="";const r=[];for(;e.length>0;){let t=!1;const i=[];let l;for(l=0;l1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=this.rules.other.listItemRegex(n);let l=!1;for(;e;){let n=!1,s="",o="";if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;s=t[0],e=e.substring(s.length);let a=t[2].split("\n",1)[0].replace(this.rules.other.listReplaceTabs,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=!a.trim(),p=0;if(this.options.pedantic?(p=2,o=a.trimStart()):h?p=t[1].length+1:(p=t[2].search(this.rules.other.nonSpaceChar),p=p>4?1:p,o=a.slice(p),p+=t[1].length),h&&this.rules.other.blankLine.test(c)&&(s+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=this.rules.other.nextBulletRegex(p),n=this.rules.other.hrRegex(p),r=this.rules.other.fencesBeginRegex(p),i=this.rules.other.headingBeginRegex(p),l=this.rules.other.htmlBeginRegex(p);for(;e;){const u=e.split("\n",1)[0];let g;if(c=u,this.options.pedantic?(c=c.replace(this.rules.other.listReplaceNesting," "),g=c):g=c.replace(this.rules.other.tabCharGlobal," "),r.test(c))break;if(i.test(c))break;if(l.test(c))break;if(t.test(c))break;if(n.test(c))break;if(g.search(this.rules.other.nonSpaceChar)>=p||!c.trim())o+="\n"+g.slice(p);else{if(h)break;if(a.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4)break;if(r.test(a))break;if(i.test(a))break;if(n.test(a))break;o+="\n"+c}h||c.trim()||(h=!0),s+=u+"\n",e=e.substring(u.length+1),a=g.slice(p)}}r.loose||(l?r.loose=!0:this.rules.other.doubleBlankLine.test(s)&&(l=!0));let u,g=null;this.options.gfm&&(g=this.rules.other.listIsTask.exec(o),g&&(u="[ ] "!==g[0],o=o.replace(this.rules.other.listReplaceTask,""))),r.items.push({type:"list_item",raw:s,task:!!g,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=s}const o=r.items.at(-1);o&&(o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd()),r.raw=r.raw.trimEnd();for(let e=0;e"space"===e.type)),n=t.length>0&&t.some((e=>this.rules.other.anyLine.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e({text:e,tokens:this.lexer.inline(e),header:!1,align:i.align[t]}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(e)){if(!this.rules.other.endAngleBracket.test(e))return;const t=J(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=this.rules.other.pedanticHrefTitle.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),this.rules.other.startAngleBracket.test(n)&&(n=this.options.pedantic&&!this.rules.other.endAngleBracket.test(e)?n.slice(1):n.slice(1,-1)),K(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return K(n,e,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(this.rules.other.newLineCharGlobal," ");const n=this.rules.other.nonSpaceChar.test(e),s=this.rules.other.startingSpaceChar.test(e)&&this.rules.other.endingSpaceChar.test(e);return n&&s&&(e=e.substring(1,e.length-1)),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=t[1],n="mailto:"+e):(e=t[1],n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=t[0],n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=t[0],n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){const e=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:e}}}}class W{tokens;options;state;tokenizer;inlineQueue;constructor(t){this.tokens=[],this.tokens.links=Object.create(null),this.options=t||e.defaults,this.options.tokenizer=this.options.tokenizer||new V,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};const n={other:i,block:j.normal,inline:N.normal};this.options.pedantic?(n.block=j.pedantic,n.inline=N.pedantic):this.options.gfm&&(n.block=j.gfm,this.options.breaks?n.inline=N.breaks:n.inline=N.gfm),this.tokenizer.rules=n}static get rules(){return{block:j,inline:N}}static lex(e,t){return new W(t).lex(e)}static lexInline(e,t){return new W(t).inlineTokens(e)}lex(e){e=e.replace(i.carriageReturn,"\n"),this.blockTokens(e,this.tokens);for(let e=0;e!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.space(e)){e=e.substring(s.raw.length);const n=t.at(-1);1===s.raw.length&&void 0!==n?n.raw+="\n":t.push(s);continue}if(s=this.tokenizer.code(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.at(-1).src=n.text):t.push(s);continue}if(s=this.tokenizer.fences(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.heading(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.hr(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.blockquote(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.list(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.html(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.def(e)){e=e.substring(s.raw.length);const n=t.at(-1);"paragraph"===n?.type||"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.raw,this.inlineQueue.at(-1).src=n.text):this.tokens.links[s.tag]||(this.tokens.links[s.tag]={href:s.href,title:s.title});continue}if(s=this.tokenizer.table(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.lheading(e)){e=e.substring(s.raw.length),t.push(s);continue}let r=e;if(this.options.extensions?.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(s=this.tokenizer.paragraph(r))){const i=t.at(-1);n&&"paragraph"===i?.type?(i.raw+="\n"+s.raw,i.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=i.text):t.push(s),n=r.length!==e.length,e=e.substring(s.raw.length)}else if(s=this.tokenizer.text(e)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===n?.type?(n.raw+="\n"+s.raw,n.text+="\n"+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=n.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,s=null;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(s=this.tokenizer.rules.inline.reflinkSearch.exec(n));)e.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(s=this.tokenizer.rules.inline.blockSkip.exec(n));)n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(s=this.tokenizer.rules.inline.anyPunctuation.exec(n));)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let r=!1,i="";for(;e;){let s;if(r||(i=""),r=!1,this.options.extensions?.inline?.some((n=>!!(s=n.call({lexer:this},e,t))&&(e=e.substring(s.raw.length),t.push(s),!0))))continue;if(s=this.tokenizer.escape(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.tag(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.link(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(s.raw.length);const n=t.at(-1);"text"===s.type&&"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s);continue}if(s=this.tokenizer.emStrong(e,n,i)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.codespan(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.br(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.del(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.autolink(e)){e=e.substring(s.raw.length),t.push(s);continue}if(!this.state.inLink&&(s=this.tokenizer.url(e))){e=e.substring(s.raw.length),t.push(s);continue}let l=e;if(this.options.extensions?.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(l=e.substring(0,t+1))}if(s=this.tokenizer.inlineText(l)){e=e.substring(s.raw.length),"_"!==s.raw.slice(-1)&&(i=s.raw.slice(-1)),r=!0;const n=t.at(-1);"text"===n?.type?(n.raw+=s.raw,n.text+=s.text):t.push(s)}else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return t}}class Y{options;parser;constructor(t){this.options=t||e.defaults}space(e){return""}code({text:e,lang:t,escaped:n}){const s=(t||"").match(i.notSpaceStart)?.[0],r=e.replace(i.endingNewline,"")+"\n";return s?'
    '+(n?r:X(r,!0))+"
    \n":"
    "+(n?r:X(r,!0))+"
    \n"}blockquote({tokens:e}){return`
    \n${this.parser.parse(e)}
    \n`}html({text:e}){return e}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)}\n`}hr(e){return"
    \n"}list(e){const t=e.ordered,n=e.start;let s="";for(let t=0;t\n"+s+"\n"}listitem(e){let t="";if(e.task){const n=this.checkbox({checked:!!e.checked});e.loose?"paragraph"===e.tokens[0]?.type?(e.tokens[0].text=n+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&"text"===e.tokens[0].tokens[0].type&&(e.tokens[0].tokens[0].text=n+" "+X(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:n+" ",text:n+" ",escaped:!0}):t+=n+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`
  • ${t}
  • \n`}checkbox({checked:e}){return"'}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    \n`}table(e){let t="",n="";for(let t=0;t${s}`),"\n\n"+t+"\n"+s+"
    \n"}tablerow({text:e}){return`\n${e}\n`}tablecell(e){const t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`\n`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${X(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){const s=this.parser.parseInline(n),r=F(e);if(null===r)return s;let i='
    ",i}image({href:e,title:t,text:n}){const s=F(e);if(null===s)return X(n);let r=`${n}{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new Y(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if(["options","parser"].includes(n))continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new V(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new ne;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if(["options","block"].includes(n))continue;const s=n,r=e.hooks[s],i=t[s];ne.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return W.lex(e,t??this.defaults)}parser(e,t){return te.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{const s={...n},r={...this.defaults,...s},i=this.onError(!!r.silent,!!r.async);if(!0===this.defaults.async&&!1===s.async)return i(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(null==t)return i(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof t)return i(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));r.hooks&&(r.hooks.options=r,r.hooks.block=e);const l=r.hooks?r.hooks.provideLexer():e?W.lex:W.lexInline,o=r.hooks?r.hooks.provideParser():e?te.parse:te.parseInline;if(r.async)return Promise.resolve(r.hooks?r.hooks.preprocess(t):t).then((e=>l(e,r))).then((e=>r.hooks?r.hooks.processAllTokens(e):e)).then((e=>r.walkTokens?Promise.all(this.walkTokens(e,r.walkTokens)).then((()=>e)):e)).then((e=>o(e,r))).then((e=>r.hooks?r.hooks.postprocess(e):e)).catch(i);try{r.hooks&&(t=r.hooks.preprocess(t));let e=l(t,r);r.hooks&&(e=r.hooks.processAllTokens(e)),r.walkTokens&&this.walkTokens(e,r.walkTokens);let n=o(e,r);return r.hooks&&(n=r.hooks.postprocess(n)),n}catch(e){return i(e)}}}onError(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+X(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const re=new se;function ie(e,t){return re.parse(e,t)}ie.options=ie.setOptions=function(e){return re.setOptions(e),ie.defaults=re.defaults,n(ie.defaults),ie},ie.getDefaults=t,ie.defaults=e.defaults,ie.use=function(...e){return re.use(...e),ie.defaults=re.defaults,n(ie.defaults),ie},ie.walkTokens=function(e,t){return re.walkTokens(e,t)},ie.parseInline=re.parseInline,ie.Parser=te,ie.parser=te.parse,ie.Renderer=Y,ie.TextRenderer=ee,ie.Lexer=W,ie.lexer=W.lex,ie.Tokenizer=V,ie.Hooks=ne,ie.parse=ie;const le=ie.options,oe=ie.setOptions,ae=ie.use,ce=ie.walkTokens,he=ie.parseInline,pe=ie,ue=te.parse,ge=W.lex;e.Hooks=ne,e.Lexer=W,e.Marked=se,e.Parser=te,e.Renderer=Y,e.TextRenderer=ee,e.Tokenizer=V,e.getDefaults=t,e.lexer=ge,e.marked=ie,e.options=le,e.parse=pe,e.parseInline=he,e.parser=ue,e.setOptions=oe,e.use=ae,e.walkTokens=ce})); diff --git a/docs/node_modules/marked/package.json b/docs/node_modules/marked/package.json new file mode 100644 index 00000000..36753635 --- /dev/null +++ b/docs/node_modules/marked/package.json @@ -0,0 +1,108 @@ +{ + "name": "marked", + "description": "A markdown parser built for speed", + "author": "Christopher Jeffrey", + "version": "15.0.3", + "type": "module", + "main": "./lib/marked.cjs", + "module": "./lib/marked.esm.js", + "browser": "./lib/marked.umd.js", + "types": "./lib/marked.d.ts", + "bin": { + "marked": "bin/marked.js" + }, + "man": "./man/marked.1", + "files": [ + "bin/", + "lib/", + "man/", + "marked.min.js" + ], + "exports": { + ".": { + "import": { + "types": "./lib/marked.d.ts", + "default": "./lib/marked.esm.js" + }, + "default": { + "types": "./lib/marked.d.cts", + "default": "./lib/marked.cjs" + } + }, + "./bin/marked": "./bin/marked.js", + "./marked.min.js": "./marked.min.js", + "./package.json": "./package.json" + }, + "publishConfig": { + "provenance": true + }, + "repository": "git://github.com/markedjs/marked.git", + "homepage": "https://marked.js.org", + "bugs": { + "url": "http://github.com/markedjs/marked/issues" + }, + "license": "MIT", + "keywords": [ + "markdown", + "markup", + "html" + ], + "tags": [ + "markdown", + "markup", + "html" + ], + "devDependencies": { + "@arethetypeswrong/cli": "^0.17.0", + "@markedjs/eslint-config": "^1.0.8", + "@markedjs/testutils": "14.1.1-0", + "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.1", + "@semantic-release/commit-analyzer": "^13.0.0", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^11.0.1", + "@semantic-release/npm": "^12.0.1", + "@semantic-release/release-notes-generator": "^14.0.1", + "cheerio": "1.0.0", + "commonmark": "0.31.2", + "cross-env": "^7.0.3", + "dts-bundle-generator": "^9.5.1", + "eslint": "^9.14.0", + "highlight.js": "^11.10.0", + "markdown-it": "14.1.0", + "marked-highlight": "^2.2.1", + "marked-man": "^2.1.0", + "recheck": "^4.4.5", + "rollup": "^4.27.4", + "semantic-release": "^24.2.0", + "titleize": "^4.0.0", + "tslib": "^2.8.1", + "typescript": "5.7.2" + }, + "scripts": { + "bench": "npm run build && node test/bench.js", + "build": "npm run rollup && npm run build:types && npm run build:man", + "build:docs": "npm run build && node docs/build.js", + "build:man": "marked-man man/marked.1.md > man/marked.1", + "build:reset": "git checkout upstream/master lib/marked.cjs lib/marked.umd.js lib/marked.esm.js marked.min.js", + "build:types": "tsc && dts-bundle-generator --export-referenced-types --project tsconfig.json -o lib/marked.d.ts src/marked.ts && dts-bundle-generator --export-referenced-types --project tsconfig.json -o lib/marked.d.cts src/marked.ts", + "lint": "eslint --fix", + "rollup": "rollup -c rollup.config.js", + "rules": "node test/rules.js", + "test": "npm run build && npm run test:specs && npm run test:unit", + "test:all": "npm test && npm run test:umd && npm run test:types && npm run test:lint", + "test:lint": "eslint", + "test:only": "npm run build && npm run test:specs:only && npm run test:unit:only", + "test:redos": "node test/recheck.js > vuln.js", + "test:specs:only": "node --test --test-only --test-reporter=spec test/run-spec-tests.js", + "test:specs": "node --test --test-reporter=spec test/run-spec-tests.js", + "test:types": "tsc --project tsconfig-type-test.json && attw -P --exclude-entrypoints ./bin/marked ./marked.min.js", + "test:umd": "node test/umd-test.js", + "test:unit:only": "node --test --test-only --test-reporter=spec test/unit/*.test.js", + "test:unit": "node --test --test-reporter=spec test/unit/*.test.js", + "test:update": "node test/update-specs.js" + }, + "engines": { + "node": ">= 18" + } +} diff --git a/favicon-16x16.png b/favicon-16x16.png new file mode 100644 index 00000000..ca6fbddd Binary files /dev/null and b/favicon-16x16.png differ diff --git a/favicon-32x32.png b/favicon-32x32.png new file mode 100644 index 00000000..d4fac82e Binary files /dev/null and b/favicon-32x32.png differ diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..70d3d947 Binary files /dev/null and b/favicon.ico differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..1ab8c6ca --- /dev/null +++ b/index.html @@ -0,0 +1,10 @@ + + + diff --git a/mstile-150x150.png b/mstile-150x150.png new file mode 100644 index 00000000..f1d02c0d Binary files /dev/null and b/mstile-150x150.png differ diff --git a/safari-pinned-tab.svg b/safari-pinned-tab.svg new file mode 100644 index 00000000..46cebff2 --- /dev/null +++ b/safari-pinned-tab.svg @@ -0,0 +1,110 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + + + + + diff --git a/site.webmanifest b/site.webmanifest new file mode 100644 index 00000000..b20abb7c --- /dev/null +++ b/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +}