diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 72d51b560..000000000 --- a/.editorconfig +++ /dev/null @@ -1,126 +0,0 @@ -############################### -# Core EditorConfig Options # -############################### -root = true -# All files -[*] -indent_style = space - -# XML project files -[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] -indent_size = 2 - -# XML config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] -indent_size = 2 - -# Code files -[*.{cs,csx,vb,vbx}] -indent_size = 4 -insert_final_newline = true -charset = utf-8-bom -############################### -# .NET Coding Conventions # -############################### -[*.{cs,vb}] -# Organize usings -dotnet_sort_system_directives_first = true -# this. preferences -dotnet_style_qualification_for_field = false:silent -dotnet_style_qualification_for_property = false:silent -dotnet_style_qualification_for_method = false:silent -dotnet_style_qualification_for_event = false:silent -# Language keywords vs BCL types preferences -dotnet_style_predefined_type_for_locals_parameters_members = true:silent -dotnet_style_predefined_type_for_member_access = true:silent -# Parentheses preferences -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent -# Modifier preferences -dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent -dotnet_style_readonly_field = true:suggestion -# Expression-level preferences -dotnet_style_object_initializer = true:suggestion -dotnet_style_collection_initializer = true:suggestion -dotnet_style_explicit_tuple_names = true:suggestion -dotnet_style_null_propagation = true:suggestion -dotnet_style_coalesce_expression = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent -dotnet_style_prefer_inferred_tuple_names = true:suggestion -dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion -dotnet_style_prefer_auto_properties = true:silent -dotnet_style_prefer_conditional_expression_over_assignment = true:silent -dotnet_style_prefer_conditional_expression_over_return = true:silent -############################### -# Naming Conventions # -############################### -# Style Definitions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# Use PascalCase for constant fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.applicable_accessibilities = * -dotnet_naming_symbols.constant_fields.required_modifiers = const -############################### -# C# Coding Conventions # -############################### -[*.cs] -# var preferences -csharp_style_var_for_built_in_types = true:silent -csharp_style_var_when_type_is_apparent = true:silent -csharp_style_var_elsewhere = true:silent -# Expression-bodied members -csharp_style_expression_bodied_methods = false:silent -csharp_style_expression_bodied_constructors = false:silent -csharp_style_expression_bodied_operators = false:silent -csharp_style_expression_bodied_properties = true:silent -csharp_style_expression_bodied_indexers = true:silent -csharp_style_expression_bodied_accessors = true:silent -# Pattern matching preferences -csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion -csharp_style_pattern_matching_over_as_with_null_check = true:suggestion -# Null-checking preferences -csharp_style_throw_expression = true:suggestion -csharp_style_conditional_delegate_call = true:suggestion -# Modifier preferences -csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion -# Expression-level preferences -csharp_prefer_braces = true:silent -csharp_style_deconstructed_variable_declaration = true:suggestion -csharp_prefer_simple_default_expression = true:suggestion -csharp_style_prefer_local_over_anonymous_function = true:suggestion -csharp_style_inlined_variable_declaration = true:suggestion -############################### -# C# Formatting Rules # -############################### -# New line preferences -csharp_new_line_before_open_brace = false -csharp_new_line_before_else = false -csharp_new_line_before_catch = false -csharp_new_line_before_finally = false -csharp_new_line_before_members_in_object_initializers = false -csharp_new_line_before_members_in_anonymous_types = false -csharp_new_line_between_query_expression_clauses = false -# Indentation preferences -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left -# Space preferences -csharp_space_after_cast = false -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_parentheses = false -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -# Wrapping preferences -csharp_preserve_single_line_statements = true -csharp_preserve_single_line_blocks = true \ No newline at end of file diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 989d37c12..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -**/input.in filter=git-crypt diff=git-crypt diff --git a/.github/workflows/update-docs.yaml b/.github/workflows/update-docs.yaml deleted file mode 100644 index 62acdb9ae..000000000 --- a/.github/workflows/update-docs.yaml +++ /dev/null @@ -1,53 +0,0 @@ -name: Update Docs - -on: - push: - branches: - - master - -jobs: - update-docs: - runs-on: ubuntu-latest - - permissions: - # Give the default GITHUB_TOKEN write permission to commit and push the - # added or changed files to the repository. - contents: write - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Configure Git - run: | - # Configure Git - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: '16' # Update based on your project's requirements - - - name: Build - run: | - cd docs; - npm install - cd .. - ls -la - node docs/build.js - - - - name: Checkout docs repository - uses: actions/checkout@v3 - with: - path: distr - ref: docs - - - name: Deploy docs - run: | - rsync -av --exclude='.git/' --del build/ distr/ - cd distr - git add . - git commit -m "Update docs on $(date)" - git push --force origin docs diff --git a/.gitignore b/.gitignore index f96db2252..30143d296 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ bin obj -aoc-crypt.key -docs/node_modules -build +session.txt +.vs/* diff --git a/.vs/adventofcode/v17/TestStore/0/000.testlog b/.vs/adventofcode/v17/TestStore/0/000.testlog new file mode 100644 index 000000000..6bbf10ed8 Binary files /dev/null and b/.vs/adventofcode/v17/TestStore/0/000.testlog differ diff --git a/.vs/adventofcode/v17/TestStore/0/testlog.manifest b/.vs/adventofcode/v17/TestStore/0/testlog.manifest new file mode 100644 index 000000000..e92ede29d Binary files /dev/null and b/.vs/adventofcode/v17/TestStore/0/testlog.manifest differ diff --git a/.vscode/launch.json b/.vscode/launch.json index 86b12f55e..75419e564 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/bin/Debug/net9.0/adventofcode.dll", + "program": "${workspaceFolder}/bin/Debug/net8.0/adventofcode.dll", "args": ["${relativeFileDirname}"], "cwd": "${workspaceFolder}", // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window diff --git a/2015/Day01/README.md b/2015/Day01/README.md deleted file mode 100644 index e6654b029..000000000 --- a/2015/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Not Quite Lisp --- -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! - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2015/day/1) description._ diff --git a/2015/Day01/Solution.cs b/2015/Day01/Solution.cs deleted file mode 100644 index 48673bec0..000000000 --- a/2015/Day01/Solution.cs +++ /dev/null @@ -1,20 +0,0 @@ -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); - } - } -} diff --git a/2015/Day01/illustration.jpeg b/2015/Day01/illustration.jpeg deleted file mode 100644 index 999d41141..000000000 Binary files a/2015/Day01/illustration.jpeg and /dev/null differ diff --git a/2015/Day01/input.in b/2015/Day01/input.in deleted file mode 100644 index efdae0d4d..000000000 Binary files a/2015/Day01/input.in and /dev/null differ diff --git a/2015/Day01/input.refout b/2015/Day01/input.refout deleted file mode 100644 index a0be33c18..000000000 --- a/2015/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -280 -1797 \ No newline at end of file diff --git a/2015/Day02/README.md b/2015/Day02/README.md deleted file mode 100644 index 91b468e7c..000000000 --- a/2015/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: I Was Told There Would Be No Math --- -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](https://en.wikipedia.org/wiki/Cuboid#Rectangular_cuboid)), 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](https://adventofcode.com/2015/day/2). \ No newline at end of file diff --git a/2015/Day02/Solution.cs b/2015/Day02/Solution.cs deleted file mode 100644 index 1b2260082..000000000 --- a/2015/Day02/Solution.cs +++ /dev/null @@ -1,25 +0,0 @@ -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); - } -} diff --git a/2015/Day02/illustration.jpeg b/2015/Day02/illustration.jpeg deleted file mode 100644 index 23432437a..000000000 Binary files a/2015/Day02/illustration.jpeg and /dev/null differ diff --git a/2015/Day02/input.in b/2015/Day02/input.in deleted file mode 100644 index ee590c717..000000000 Binary files a/2015/Day02/input.in and /dev/null differ diff --git a/2015/Day02/input.refout b/2015/Day02/input.refout deleted file mode 100644 index f3d21caef..000000000 --- a/2015/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1606483 -3842356 diff --git a/2015/Day03/README.md b/2015/Day03/README.md deleted file mode 100644 index 06678a506..000000000 --- a/2015/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Perfectly Spherical Houses in a Vacuum --- -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](https://adventofcode.com/2015/day/3). \ No newline at end of file diff --git a/2015/Day03/Solution.cs b/2015/Day03/Solution.cs deleted file mode 100644 index 4e381e1b5..000000000 --- a/2015/Day03/Solution.cs +++ /dev/null @@ -1,35 +0,0 @@ -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(); - } -} diff --git a/2015/Day03/illustration.jpeg b/2015/Day03/illustration.jpeg deleted file mode 100644 index 60cacbd93..000000000 Binary files a/2015/Day03/illustration.jpeg and /dev/null differ diff --git a/2015/Day03/input.in b/2015/Day03/input.in deleted file mode 100644 index 065d2f825..000000000 Binary files a/2015/Day03/input.in and /dev/null differ diff --git a/2015/Day03/input.refout b/2015/Day03/input.refout deleted file mode 100644 index 8c7d2c327..000000000 --- a/2015/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2572 -2631 diff --git a/2015/Day04/README.md b/2015/Day04/README.md deleted file mode 100644 index a52193422..000000000 --- a/2015/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: The Ideal Stocking Stuffer --- -Santa needs help [mining](https://en.wikipedia.org/wiki/Bitcoin#Mining) some AdventCoins (very similar to [bitcoins](https://en.wikipedia.org/wiki/Bitcoin)) to use as gifts for all the economically forward-thinking little girls and boys. - -To do this, he needs to find [MD5](https://en.wikipedia.org/wiki/MD5) hashes which, in [hexadecimal](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2015/day/4). \ No newline at end of file diff --git a/2015/Day04/Solution.cs b/2015/Day04/Solution.cs deleted file mode 100644 index a487524e2..000000000 --- a/2015/Day04/Solution.cs +++ /dev/null @@ -1,42 +0,0 @@ -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; - } - } -} diff --git a/2015/Day04/illustration.jpeg b/2015/Day04/illustration.jpeg deleted file mode 100644 index 243d89a1b..000000000 Binary files a/2015/Day04/illustration.jpeg and /dev/null differ diff --git a/2015/Day04/input.in b/2015/Day04/input.in deleted file mode 100644 index 7f2ce7a96..000000000 Binary files a/2015/Day04/input.in and /dev/null differ diff --git a/2015/Day04/input.refout b/2015/Day04/input.refout deleted file mode 100644 index f26b6b1be..000000000 --- a/2015/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -282749 -9962624 diff --git a/2015/Day05/README.md b/2015/Day05/README.md deleted file mode 100644 index 0c3382404..000000000 --- a/2015/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Doesn't He Have Intern-Elves For This? --- -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](https://adventofcode.com/2015/day/5). \ No newline at end of file diff --git a/2015/Day05/Solution.cs b/2015/Day05/Solution.cs deleted file mode 100644 index e82c867ed..000000000 --- a/2015/Day05/Solution.cs +++ /dev/null @@ -1,22 +0,0 @@ -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; - }); -} diff --git a/2015/Day05/illustration.jpeg b/2015/Day05/illustration.jpeg deleted file mode 100644 index 8ba151e3c..000000000 Binary files a/2015/Day05/illustration.jpeg and /dev/null differ diff --git a/2015/Day05/input.in b/2015/Day05/input.in deleted file mode 100644 index 78609b050..000000000 Binary files a/2015/Day05/input.in and /dev/null differ diff --git a/2015/Day05/input.refout b/2015/Day05/input.refout deleted file mode 100644 index a0f7914c7..000000000 --- a/2015/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -255 -55 diff --git a/2015/Day06/README.md b/2015/Day06/README.md deleted file mode 100644 index bc54a864c..000000000 --- a/2015/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Probably a Fire Hazard --- -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](https://adventofcode.com/2015/day/6). \ No newline at end of file diff --git a/2015/Day06/Solution.cs b/2015/Day06/Solution.cs deleted file mode 100644 index 945c9dd95..000000000 --- a/2015/Day06/Solution.cs +++ /dev/null @@ -1,36 +0,0 @@ -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(); - } -} diff --git a/2015/Day06/illustration.jpeg b/2015/Day06/illustration.jpeg deleted file mode 100644 index 3b62f677b..000000000 Binary files a/2015/Day06/illustration.jpeg and /dev/null differ diff --git a/2015/Day06/input.in b/2015/Day06/input.in deleted file mode 100644 index be73cadf4..000000000 Binary files a/2015/Day06/input.in and /dev/null differ diff --git a/2015/Day06/input.refout b/2015/Day06/input.refout deleted file mode 100644 index 5bd6465cd..000000000 --- a/2015/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -569999 -17836115 diff --git a/2015/Day07/README.md b/2015/Day07/README.md deleted file mode 100644 index 7a4b1c9a3..000000000 --- a/2015/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: Some Assembly Required --- -This year, Santa brought little Bobby Tables a set of wires and [bitwise logic gates](https://en.wikipedia.org/wiki/Bitwise_operation)! 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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2015/day/7). \ No newline at end of file diff --git a/2015/Day07/Solution.cs b/2015/Day07/Solution.cs deleted file mode 100644 index 7a1ad6788..000000000 --- a/2015/Day07/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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; - } -} diff --git a/2015/Day07/input.in b/2015/Day07/input.in deleted file mode 100644 index 21197948f..000000000 Binary files a/2015/Day07/input.in and /dev/null differ diff --git a/2015/Day07/input.refout b/2015/Day07/input.refout deleted file mode 100644 index 6c659d484..000000000 --- a/2015/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -46065 -14134 diff --git a/2015/Day08/README.md b/2015/Day08/README.md deleted file mode 100644 index acd31d5fc..000000000 --- a/2015/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Matchsticks --- -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](https://en.wikipedia.org/wiki/Escape_sequences_in_C), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [Perl](http://perldoc.perl.org/perlop.html#Quote-and-Quote-like-Operators), [Python](https://docs.python.org/2.0/ref/strings.html), and even [PHP](http://php.net/manual/en/language.types.string.php#language.types.string.syntax.double) handle special characters in very similar ways. - -Read the [full puzzle](https://adventofcode.com/2015/day/8). \ No newline at end of file diff --git a/2015/Day08/Solution.cs b/2015/Day08/Solution.cs deleted file mode 100644 index b9ce2d39c..000000000 --- a/2015/Day08/Solution.cs +++ /dev/null @@ -1,20 +0,0 @@ -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(); - -} diff --git a/2015/Day08/input.in b/2015/Day08/input.in deleted file mode 100644 index a37076b5a..000000000 Binary files a/2015/Day08/input.in and /dev/null differ diff --git a/2015/Day08/input.refout b/2015/Day08/input.refout deleted file mode 100644 index 16f9530e1..000000000 --- a/2015/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1371 -2117 diff --git a/2015/Day09/README.md b/2015/Day09/README.md deleted file mode 100644 index 9ea9bfada..000000000 --- a/2015/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: All in a Single Night --- -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](https://adventofcode.com/2015/day/9). \ No newline at end of file diff --git a/2015/Day09/Solution.cs b/2015/Day09/Solution.cs deleted file mode 100644 index d0f622e6d..000000000 --- a/2015/Day09/Solution.cs +++ /dev/null @@ -1,47 +0,0 @@ -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); - } -} diff --git a/2015/Day09/input.in b/2015/Day09/input.in deleted file mode 100644 index 9873e3051..000000000 Binary files a/2015/Day09/input.in and /dev/null differ diff --git a/2015/Day09/input.refout b/2015/Day09/input.refout deleted file mode 100644 index f6426cb51..000000000 --- a/2015/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -141 -736 diff --git a/2015/Day10/README.md b/2015/Day10/README.md deleted file mode 100644 index e09b557f0..000000000 --- a/2015/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Elves Look, Elves Say --- -Today, the Elves are playing a game called [look-and-say](https://en.wikipedia.org/wiki/Look-and-say_sequence). 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` `1`s). - -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](https://adventofcode.com/2015/day/10). \ No newline at end of file diff --git a/2015/Day10/Solution.cs b/2015/Day10/Solution.cs deleted file mode 100644 index 6e4060069..000000000 --- a/2015/Day10/Solution.cs +++ /dev/null @@ -1,36 +0,0 @@ -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; - } - } -} diff --git a/2015/Day10/input.in b/2015/Day10/input.in deleted file mode 100644 index 33556dd98..000000000 Binary files a/2015/Day10/input.in and /dev/null differ diff --git a/2015/Day10/input.refout b/2015/Day10/input.refout deleted file mode 100644 index 9864dc870..000000000 --- a/2015/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -492982 -6989950 diff --git a/2015/Day11/README.md b/2015/Day11/README.md deleted file mode 100644 index f2d68ae2a..000000000 --- a/2015/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Corporate Policy --- -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](https://adventofcode.com/2015/day/11). \ No newline at end of file diff --git a/2015/Day11/Solution.cs b/2015/Day11/Solution.cs deleted file mode 100644 index 561441ea8..000000000 --- a/2015/Day11/Solution.cs +++ /dev/null @@ -1,39 +0,0 @@ -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; - } - } -} diff --git a/2015/Day11/input.in b/2015/Day11/input.in deleted file mode 100644 index cf3823d95..000000000 Binary files a/2015/Day11/input.in and /dev/null differ diff --git a/2015/Day11/input.refout b/2015/Day11/input.refout deleted file mode 100644 index 440db0b25..000000000 --- a/2015/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -cqjxxyzz -cqkaabcc diff --git a/2015/Day12/README.md b/2015/Day12/README.md deleted file mode 100644 index 45ad4b14e..000000000 --- a/2015/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: JSAbacusFramework.io --- -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](http://json.org/) 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](https://adventofcode.com/2015/day/12). \ No newline at end of file diff --git a/2015/Day12/Solution.cs b/2015/Day12/Solution.cs deleted file mode 100644 index 93df6ae3b..000000000 --- a/2015/Day12/Solution.cs +++ /dev/null @@ -1,27 +0,0 @@ -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); - } -} diff --git a/2015/Day12/input.in b/2015/Day12/input.in deleted file mode 100644 index 6bce44176..000000000 Binary files a/2015/Day12/input.in and /dev/null differ diff --git a/2015/Day12/input.refout b/2015/Day12/input.refout deleted file mode 100644 index dbc02f05e..000000000 --- a/2015/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -119433 -68466 diff --git a/2015/Day13/README.md b/2015/Day13/README.md deleted file mode 100644 index c126f8ae3..000000000 --- a/2015/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Knights of the Dinner Table --- -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](https://adventofcode.com/2015/day/13). \ No newline at end of file diff --git a/2015/Day13/Solution.cs b/2015/Day13/Solution.cs deleted file mode 100644 index 8872115ed..000000000 --- a/2015/Day13/Solution.cs +++ /dev/null @@ -1,55 +0,0 @@ -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); - } -} diff --git a/2015/Day13/input.in b/2015/Day13/input.in deleted file mode 100644 index 67565872d..000000000 Binary files a/2015/Day13/input.in and /dev/null differ diff --git a/2015/Day13/input.refout b/2015/Day13/input.refout deleted file mode 100644 index ae343b96d..000000000 --- a/2015/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -709 -668 diff --git a/2015/Day14/README.md b/2015/Day14/README.md deleted file mode 100644 index c731da059..000000000 --- a/2015/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Reindeer Olympics --- -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](https://adventofcode.com/2015/day/14). \ No newline at end of file diff --git a/2015/Day14/Solution.cs b/2015/Day14/Solution.cs deleted file mode 100644 index 9383366a1..000000000 --- a/2015/Day14/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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; - } - } -} diff --git a/2015/Day14/input.in b/2015/Day14/input.in deleted file mode 100644 index c32701b9d..000000000 Binary files a/2015/Day14/input.in and /dev/null differ diff --git a/2015/Day14/input.refout b/2015/Day14/input.refout deleted file mode 100644 index 406063643..000000000 --- a/2015/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2640 -1102 diff --git a/2015/Day15/README.md b/2015/Day15/README.md deleted file mode 100644 index b6a9deacf..000000000 --- a/2015/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Science for Hungry People --- -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](https://adventofcode.com/2015/day/15). \ No newline at end of file diff --git a/2015/Day15/Solution.cs b/2015/Day15/Solution.cs deleted file mode 100644 index e9bb51047..000000000 --- a/2015/Day15/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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(); - } - } - } - } -} diff --git a/2015/Day15/input.in b/2015/Day15/input.in deleted file mode 100644 index 2a15a4bdf..000000000 Binary files a/2015/Day15/input.in and /dev/null differ diff --git a/2015/Day15/input.refout b/2015/Day15/input.refout deleted file mode 100644 index 849708d4f..000000000 --- a/2015/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -13882464 -11171160 \ No newline at end of file diff --git a/2015/Day16/README.md b/2015/Day16/README.md deleted file mode 100644 index 2af56e4cf..000000000 --- a/2015/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Aunt Sue --- -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](https://adventofcode.com/2015/day/16). \ No newline at end of file diff --git a/2015/Day16/Solution.cs b/2015/Day16/Solution.cs deleted file mode 100644 index 88fa21e40..000000000 --- a/2015/Day16/Solution.cs +++ /dev/null @@ -1,44 +0,0 @@ -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(); -} diff --git a/2015/Day16/input.in b/2015/Day16/input.in deleted file mode 100644 index 88299f18a..000000000 Binary files a/2015/Day16/input.in and /dev/null differ diff --git a/2015/Day16/input.refout b/2015/Day16/input.refout deleted file mode 100644 index cfcb52c27..000000000 --- a/2015/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -373 -260 diff --git a/2015/Day17/README.md b/2015/Day17/README.md deleted file mode 100644 index b38b90141..000000000 --- a/2015/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: No Such Thing as Too Much --- -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](https://adventofcode.com/2015/day/17). \ No newline at end of file diff --git a/2015/Day17/Solution.cs b/2015/Day17/Solution.cs deleted file mode 100644 index 154d6486d..000000000 --- a/2015/Day17/Solution.cs +++ /dev/null @@ -1,40 +0,0 @@ -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); - } -} diff --git a/2015/Day17/input.in b/2015/Day17/input.in deleted file mode 100644 index ebbf7e7ad..000000000 Binary files a/2015/Day17/input.in and /dev/null differ diff --git a/2015/Day17/input.refout b/2015/Day17/input.refout deleted file mode 100644 index 7d01df13d..000000000 --- a/2015/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1638 -17 diff --git a/2015/Day18/README.md b/2015/Day18/README.md deleted file mode 100644 index 05f646e0c..000000000 --- a/2015/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Like a GIF For Your Yard --- -After the [million lights incident](6), 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](https://adventofcode.com/2015/day/18). \ No newline at end of file diff --git a/2015/Day18/Solution.cs b/2015/Day18/Solution.cs deleted file mode 100644 index c2ab8a765..000000000 --- a/2015/Day18/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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(); -} diff --git a/2015/Day18/input.in b/2015/Day18/input.in deleted file mode 100644 index 9c8fa75ed..000000000 Binary files a/2015/Day18/input.in and /dev/null differ diff --git a/2015/Day18/input.refout b/2015/Day18/input.refout deleted file mode 100644 index e2ce4ee17..000000000 --- a/2015/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -821 -886 diff --git a/2015/Day19/README.md b/2015/Day19/README.md deleted file mode 100644 index 143c9b75b..000000000 --- a/2015/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Medicine for Rudolph --- -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](https://adventofcode.com/2015/day/19). \ No newline at end of file diff --git a/2015/Day19/Solution.cs b/2015/Day19/Solution.cs deleted file mode 100644 index 8a9e6c922..000000000 --- a/2015/Day19/Solution.cs +++ /dev/null @@ -1,75 +0,0 @@ -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); - } -} diff --git a/2015/Day19/input.in b/2015/Day19/input.in deleted file mode 100644 index e9fd053f8..000000000 Binary files a/2015/Day19/input.in and /dev/null differ diff --git a/2015/Day19/input.refout b/2015/Day19/input.refout deleted file mode 100644 index 3199c5365..000000000 --- a/2015/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -518 -200 diff --git a/2015/Day20/README.md b/2015/Day20/README.md deleted file mode 100644 index 7948d8a4b..000000000 --- a/2015/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Infinite Elves and Infinite Houses --- -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](https://adventofcode.com/2015/day/20). \ No newline at end of file diff --git a/2015/Day20/Solution.cs b/2015/Day20/Solution.cs deleted file mode 100644 index c3373106a..000000000 --- a/2015/Day20/Solution.cs +++ /dev/null @@ -1,36 +0,0 @@ -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; - - } -} diff --git a/2015/Day20/input.in b/2015/Day20/input.in deleted file mode 100644 index 70de3846e..000000000 Binary files a/2015/Day20/input.in and /dev/null differ diff --git a/2015/Day20/input.refout b/2015/Day20/input.refout deleted file mode 100644 index 4f317373c..000000000 --- a/2015/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -831600 -884520 diff --git a/2015/Day21/README.md b/2015/Day21/README.md deleted file mode 100644 index b35a9cffb..000000000 --- a/2015/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: RPG Simulator 20XX --- -Little Henry Case got a new video game for Christmas. It's an [RPG](https://en.wikipedia.org/wiki/Role-playing_video_game), and he's stuck on a boss. He needs to know what equipment to buy at the shop. He hands you the [controller](https://en.wikipedia.org/wiki/Game_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](https://adventofcode.com/2015/day/21). \ No newline at end of file diff --git a/2015/Day21/Solution.cs b/2015/Day21/Solution.cs deleted file mode 100644 index 98e5b1fcb..000000000 --- a/2015/Day21/Solution.cs +++ /dev/null @@ -1,84 +0,0 @@ -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()); - } - -} diff --git a/2015/Day21/input.in b/2015/Day21/input.in deleted file mode 100644 index 86a205cfd..000000000 Binary files a/2015/Day21/input.in and /dev/null differ diff --git a/2015/Day21/input.refout b/2015/Day21/input.refout deleted file mode 100644 index acfccc904..000000000 --- a/2015/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -121 -201 diff --git a/2015/Day22/README.md b/2015/Day22/README.md deleted file mode 100644 index 26a245daa..000000000 --- a/2015/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Wizard Simulator 20XX --- -Little Henry Case decides that defeating bosses with [swords and stuff](21) 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](https://adventofcode.com/2015/day/22). \ No newline at end of file diff --git a/2015/Day22/Solution.cs b/2015/Day22/Solution.cs deleted file mode 100644 index 7580320d7..000000000 --- a/2015/Day22/Solution.cs +++ /dev/null @@ -1,186 +0,0 @@ -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; - } - } -} diff --git a/2015/Day22/input.in b/2015/Day22/input.in deleted file mode 100644 index c3d03ea5f..000000000 Binary files a/2015/Day22/input.in and /dev/null differ diff --git a/2015/Day22/input.refout b/2015/Day22/input.refout deleted file mode 100644 index d72d09e9a..000000000 --- a/2015/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1824 -1937 diff --git a/2015/Day23/README.md b/2015/Day23/README.md deleted file mode 100644 index 03c6983b0..000000000 --- a/2015/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Opening the Turing Lock --- -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](https://en.wikipedia.org/wiki/Processor_register) and six [instructions](https://en.wikipedia.org/wiki/Instruction_set) (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](https://en.wikipedia.org/wiki/Natural_number), and begin with a value of `0`. The instructions are as follows: - -Read the [full puzzle](https://adventofcode.com/2015/day/23). \ No newline at end of file diff --git a/2015/Day23/Solution.cs b/2015/Day23/Solution.cs deleted file mode 100644 index 98e74bd2f..000000000 --- a/2015/Day23/Solution.cs +++ /dev/null @@ -1,56 +0,0 @@ -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"); - } -} diff --git a/2015/Day23/input.in b/2015/Day23/input.in deleted file mode 100644 index a34fa99f1..000000000 Binary files a/2015/Day23/input.in and /dev/null differ diff --git a/2015/Day23/input.refout b/2015/Day23/input.refout deleted file mode 100644 index 6064a4e8b..000000000 --- a/2015/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -170 -247 diff --git a/2015/Day24/README.md b/2015/Day24/README.md deleted file mode 100644 index c00ce7cf2..000000000 --- a/2015/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: It Hangs in the Balance --- -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](https://adventofcode.com/2015/day/24). \ No newline at end of file diff --git a/2015/Day24/Solution.cs b/2015/Day24/Solution.cs deleted file mode 100644 index 154e425f5..000000000 --- a/2015/Day24/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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; - } - } -} diff --git a/2015/Day24/input.in b/2015/Day24/input.in deleted file mode 100644 index 3d36932f3..000000000 Binary files a/2015/Day24/input.in and /dev/null differ diff --git a/2015/Day24/input.refout b/2015/Day24/input.refout deleted file mode 100644 index 319f8bda5..000000000 --- a/2015/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -10723906903 -74850409 diff --git a/2015/Day25/README.md b/2015/Day25/README.md deleted file mode 100644 index 9107dfdd5..000000000 --- a/2015/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Let It Snow --- -Merry Christmas! Santa is booting up his weather machine; looks like you might get a [white Christmas](1) 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](https://en.wikipedia.org/wiki/Copy_protection#Early_video_games). 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](https://adventofcode.com/2015/day/25). \ No newline at end of file diff --git a/2015/Day25/Solution.cs b/2015/Day25/Solution.cs deleted file mode 100644 index efc643128..000000000 --- a/2015/Day25/Solution.cs +++ /dev/null @@ -1,28 +0,0 @@ -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)); - } -} diff --git a/2015/Day25/input.in b/2015/Day25/input.in deleted file mode 100644 index d4c53d3dd..000000000 Binary files a/2015/Day25/input.in and /dev/null differ diff --git a/2015/Day25/input.refout b/2015/Day25/input.refout deleted file mode 100644 index 3d80891c5..000000000 --- a/2015/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -2650453 diff --git a/2015/README.md b/2015/README.md deleted file mode 100644 index a98cc6d87..000000000 --- a/2015/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2015) -Check out https://adventofcode.com/2015. - - diff --git a/2015/SplashScreen.cs b/2015/SplashScreen.cs deleted file mode 100644 index 64c664e9c..000000000 --- a/2015/SplashScreen.cs +++ /dev/null @@ -1,514 +0,0 @@ -using System; - -namespace AdventOfCode.Y2015; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ {:year 2015}\n "); - Write(0xcc00, false, "\n "); - Write(0xffff66, true, "| \n \\|/ "); - Write(0xffff66, true, "\n --*-- "); - Write(0xcccccc, true, "25 "); - Write(0xffff66, true, "**\n "); - Write(0x9900, false, " >"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<< "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<<< "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<< "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<<< "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, " >>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0x9900, false, ">>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">>"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, ">>"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<< "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, " | | \n | | "); - Write(0xcccccc, false, " \n _ _ __ ___|___|___ __ _ _ \n "); - Write(0xcccccc, false, " \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2015/calendar.svg b/2015/calendar.svg deleted file mode 100644 index 40356baaa..000000000 --- a/2015/calendar.svg +++ /dev/null @@ -1,51 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  {:year 2015} -  -                        |                                -                       \|/                               -                      --*--                        25 ** -                       >o<                         24 ** -                      >>O<<                        23 ** -                     >o>>>@<                       22 ** -                    >@<<*<O<<                      21 ** -                   >>o>>O>@<<<                     20 ** -                  >o>o>O>>@<<<<                    19 ** -                 >>o<<<O<o>*<*<<                   18 ** -                >@>>>o>>>@>o<<O<<                  17 ** -               >>*>>O>@>>>*<<<o>O<                 16 ** -              >>@>>o>*>>>@<<<O<O<<<                15 ** -             >>@<<o<<<@>>*<<@>@>@>O<               14 ** -            >*<<O>>>*<<*<@<O<<<O<<O<<              13 ** -           >@>>>o>>>@<o>>@<<O>>>O<<<o<             12 ** -          >o>O<@<<<o<*>@<<O<<<O>>>*>O<<            11 ** -         >@>*>>>o>>@<O>o>@<O>>>@>*>o<<O<           10 ** -        >>@>>>*>>o<O>>>o>o>>o>O<<<*<<<O<<           9 ** -       >>@<o>>O>O<*<<O>O>>*<*<o<<<*>*<o>o<          8 ** -      >>O<O<o<<o>>@>>o<<*<<<o>>>O<o<<o>*<@<         7 ** -     >>@<o>>>O>O<o>>O<<<*<o<<o<<*<<O<<@>>>o<        6 ** -    >>@>>>O>@>*<<<o>*>o<o>>@<<<@<<*>>@<O<<*<<       5 ** -   >>O<<O<<<*<*<<<*<<O<<@<<o>>*>>@<O<<o<<@<<<<      4 ** -  >@<<O<@>>O>>>*<<o>>>*>@<<O>O>*<O>>>O>>o>>>@<<     3 ** - >>@<@>o<<o<<<o>>>O<@<<*>*>>>*<@<@>>>*<*>O<@>>O<    2 ** ->>*>>@>*<<<*<<@>>O<*<<*<<*>>>o>>>@<<O<*<*>>*<<o<<   1 ** -                      |   |                              -                      |   |                              -           _  _ __ ___|___|___ __ _  _                   - - - - \ No newline at end of file diff --git a/2016/Day01/README.md b/2016/Day01/README.md deleted file mode 100644 index 4c302f2ce..000000000 --- a/2016/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: No Time for a Taxicab --- -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! - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2016/day/1) description._ diff --git a/2016/Day01/Solution.cs b/2016/Day01/Solution.cs deleted file mode 100644 index c182debd9..000000000 --- a/2016/Day01/Solution.cs +++ /dev/null @@ -1,47 +0,0 @@ -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); - } - } - } -} diff --git a/2016/Day01/input.in b/2016/Day01/input.in deleted file mode 100644 index 687ec0109..000000000 Binary files a/2016/Day01/input.in and /dev/null differ diff --git a/2016/Day01/input.refout b/2016/Day01/input.refout deleted file mode 100644 index c721c8776..000000000 --- a/2016/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -241 -116 \ No newline at end of file diff --git a/2016/Day02/README.md b/2016/Day02/README.md deleted file mode 100644 index 345a8b762..000000000 --- a/2016/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Bathroom Security --- -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](https://adventofcode.com/2016/day/2). \ No newline at end of file diff --git a/2016/Day02/Solution.cs b/2016/Day02/Solution.cs deleted file mode 100644 index ed6093e9a..000000000 --- a/2016/Day02/Solution.cs +++ /dev/null @@ -1,35 +0,0 @@ -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; - } -} diff --git a/2016/Day02/input.in b/2016/Day02/input.in deleted file mode 100644 index df0dff54a..000000000 Binary files a/2016/Day02/input.in and /dev/null differ diff --git a/2016/Day02/input.refout b/2016/Day02/input.refout deleted file mode 100644 index e4ea5d438..000000000 --- a/2016/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -18843 -67BB9 diff --git a/2016/Day03/README.md b/2016/Day03/README.md deleted file mode 100644 index cd2bf19f7..000000000 --- a/2016/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Squares With Three Sides --- -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](https://adventofcode.com/2016/day/3). \ No newline at end of file diff --git a/2016/Day03/Solution.cs b/2016/Day03/Solution.cs deleted file mode 100644 index d2aae2804..000000000 --- a/2016/Day03/Solution.cs +++ /dev/null @@ -1,49 +0,0 @@ -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; - } -} diff --git a/2016/Day03/input.in b/2016/Day03/input.in deleted file mode 100644 index 84fc5ad53..000000000 Binary files a/2016/Day03/input.in and /dev/null differ diff --git a/2016/Day03/input.refout b/2016/Day03/input.refout deleted file mode 100644 index db37dd155..000000000 --- a/2016/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -982 -1826 diff --git a/2016/Day04/README.md b/2016/Day04/README.md deleted file mode 100644 index 39105dd2f..000000000 --- a/2016/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Security Through Obscurity --- -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](https://adventofcode.com/2016/day/4). \ No newline at end of file diff --git a/2016/Day04/Solution.cs b/2016/Day04/Solution.cs deleted file mode 100644 index 1f849f1e0..000000000 --- a/2016/Day04/Solution.cs +++ /dev/null @@ -1,33 +0,0 @@ -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); - - } -} diff --git a/2016/Day04/input.in b/2016/Day04/input.in deleted file mode 100644 index c951db70c..000000000 Binary files a/2016/Day04/input.in and /dev/null differ diff --git a/2016/Day04/input.refout b/2016/Day04/input.refout deleted file mode 100644 index af0c1afc2..000000000 --- a/2016/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -361724 -482 diff --git a/2016/Day05/README.md b/2016/Day05/README.md deleted file mode 100644 index e510a6e67..000000000 --- a/2016/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: How About a Nice Game of Chess? --- -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](https://en.wikipedia.org/wiki/Hackers_(film)) [movies](https://en.wikipedia.org/wiki/WarGames). - -The *eight-character password* for the door is generated one character at a time by finding the [MD5](https://en.wikipedia.org/wiki/MD5) hash of some Door ID (your puzzle input) and an increasing integer index (starting with `0`). - -Read the [full puzzle](https://adventofcode.com/2016/day/5). \ No newline at end of file diff --git a/2016/Day05/Solution.cs b/2016/Day05/Solution.cs deleted file mode 100644 index d050541bd..000000000 --- a/2016/Day05/Solution.cs +++ /dev/null @@ -1,75 +0,0 @@ -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++; - } -} diff --git a/2016/Day05/input.in b/2016/Day05/input.in deleted file mode 100644 index b5738f5d8..000000000 Binary files a/2016/Day05/input.in and /dev/null differ diff --git a/2016/Day05/input.refout b/2016/Day05/input.refout deleted file mode 100644 index 4af3e6497..000000000 --- a/2016/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -f97c354d -863dde27 diff --git a/2016/Day06/README.md b/2016/Day06/README.md deleted file mode 100644 index d93688e72..000000000 --- a/2016/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Signals and Noise --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2016/day/6). \ No newline at end of file diff --git a/2016/Day06/Solution.cs b/2016/Day06/Solution.cs deleted file mode 100644 index 34c51528d..000000000 --- a/2016/Day06/Solution.cs +++ /dev/null @@ -1,22 +0,0 @@ -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); - } -} diff --git a/2016/Day06/input.in b/2016/Day06/input.in deleted file mode 100644 index 9873339f3..000000000 Binary files a/2016/Day06/input.in and /dev/null differ diff --git a/2016/Day06/input.refout b/2016/Day06/input.refout deleted file mode 100644 index 770f21cac..000000000 --- a/2016/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -afwlyyyq -bhkzekao diff --git a/2016/Day07/README.md b/2016/Day07/README.md deleted file mode 100644 index 089886307..000000000 --- a/2016/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: Internet Protocol Version 7 --- -While snooping around the local network of EBHQ, you compile a list of [IP addresses](https://en.wikipedia.org/wiki/IP_address) (they're IPv7, of course; [IPv6](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2016/day/7). \ No newline at end of file diff --git a/2016/Day07/Solution.cs b/2016/Day07/Solution.cs deleted file mode 100644 index 799aac943..000000000 --- a/2016/Day07/Solution.cs +++ /dev/null @@ -1,61 +0,0 @@ -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); - } - } -} diff --git a/2016/Day07/input.in b/2016/Day07/input.in deleted file mode 100644 index ec26a4f10..000000000 Binary files a/2016/Day07/input.in and /dev/null differ diff --git a/2016/Day07/input.refout b/2016/Day07/input.refout deleted file mode 100644 index 91e64be76..000000000 --- a/2016/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -118 -260 diff --git a/2016/Day08/README.md b/2016/Day08/README.md deleted file mode 100644 index 6f22b40ab..000000000 --- a/2016/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Two-Factor Authentication --- -You come across a door implementing what you can only assume is an implementation of [two-factor authentication](https://en.wikipedia.org/wiki/Multi-factor_authentication) after a long game of [requirements](https://en.wikipedia.org/wiki/Requirement) [telephone](https://en.wikipedia.org/wiki/Chinese_whispers). - -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](https://www.google.com/search?q=tiny+lcd&tbm=isch), and you type that code on a keypad. Then, presumably, the door unlocks. - -Read the [full puzzle](https://adventofcode.com/2016/day/8). \ No newline at end of file diff --git a/2016/Day08/Solution.cs b/2016/Day08/Solution.cs deleted file mode 100644 index df27c2622..000000000 --- a/2016/Day08/Solution.cs +++ /dev/null @@ -1,76 +0,0 @@ -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; - } - } -} diff --git a/2016/Day08/input.in b/2016/Day08/input.in deleted file mode 100644 index 09aee8aee..000000000 Binary files a/2016/Day08/input.in and /dev/null differ diff --git a/2016/Day08/input.refout b/2016/Day08/input.refout deleted file mode 100644 index f9ca26155..000000000 --- a/2016/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -110 -ZJHRKCPLYJ diff --git a/2016/Day09/README.md b/2016/Day09/README.md deleted file mode 100644 index 594534d99..000000000 --- a/2016/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Explosives in Cyberspace --- -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](https://adventofcode.com/2016/day/9). \ No newline at end of file diff --git a/2016/Day09/Solution.cs b/2016/Day09/Solution.cs deleted file mode 100644 index 372ab6d04..000000000 --- a/2016/Day09/Solution.cs +++ /dev/null @@ -1,33 +0,0 @@ -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; - } -} diff --git a/2016/Day09/input.in b/2016/Day09/input.in deleted file mode 100644 index 84798735c..000000000 Binary files a/2016/Day09/input.in and /dev/null differ diff --git a/2016/Day09/input.refout b/2016/Day09/input.refout deleted file mode 100644 index 51d073eaf..000000000 --- a/2016/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -123908 -10755693147 diff --git a/2016/Day10/README.md b/2016/Day10/README.md deleted file mode 100644 index d03015e16..000000000 --- a/2016/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Balance Bots --- -You come upon a factory in which many robots are [zooming around](https://www.youtube.com/watch?v=JnkMyfQ5YfY&t=40) 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](https://adventofcode.com/2016/day/10). \ No newline at end of file diff --git a/2016/Day10/Solution.cs b/2016/Day10/Solution.cs deleted file mode 100644 index 43938ec23..000000000 --- a/2016/Day10/Solution.cs +++ /dev/null @@ -1,77 +0,0 @@ -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; -} diff --git a/2016/Day10/input.in b/2016/Day10/input.in deleted file mode 100644 index 4c8c4256a..000000000 Binary files a/2016/Day10/input.in and /dev/null differ diff --git a/2016/Day10/input.refout b/2016/Day10/input.refout deleted file mode 100644 index c266b20a0..000000000 --- a/2016/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -98 -4042 diff --git a/2016/Day11/README.md b/2016/Day11/README.md deleted file mode 100644 index eaac04c4a..000000000 --- a/2016/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Radioisotope Thermoelectric Generators --- -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](https://en.wikipedia.org/wiki/Radioisotope_thermoelectric_generator) (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](https://adventofcode.com/2016/day/11). \ No newline at end of file diff --git a/2016/Day11/Solution.cs b/2016/Day11/Solution.cs deleted file mode 100644 index 0b90bb405..000000000 --- a/2016/Day11/Solution.cs +++ /dev/null @@ -1,185 +0,0 @@ -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(); - } -} diff --git a/2016/Day11/input.in b/2016/Day11/input.in deleted file mode 100644 index 70310eded..000000000 Binary files a/2016/Day11/input.in and /dev/null differ diff --git a/2016/Day11/input.refout b/2016/Day11/input.refout deleted file mode 100644 index 279830ba7..000000000 --- a/2016/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -31 -55 diff --git a/2016/Day12/README.md b/2016/Day12/README.md deleted file mode 100644 index 8783e7dc1..000000000 --- a/2016/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Leonardo's Monorail --- -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](https://www.google.com/search?q=tiger+lilies&tbm=isch), you manage to decrypt some of the files you extracted from the servers downstairs. - -Read the [full puzzle](https://adventofcode.com/2016/day/12). \ No newline at end of file diff --git a/2016/Day12/Solution.cs b/2016/Day12/Solution.cs deleted file mode 100644 index cd9d3bd65..000000000 --- a/2016/Day12/Solution.cs +++ /dev/null @@ -1,53 +0,0 @@ -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"); - } -} diff --git a/2016/Day12/input.in b/2016/Day12/input.in deleted file mode 100644 index e4a51aade..000000000 Binary files a/2016/Day12/input.in and /dev/null differ diff --git a/2016/Day12/input.refout b/2016/Day12/input.refout deleted file mode 100644 index ffe4fb955..000000000 --- a/2016/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -318003 -9227657 diff --git a/2016/Day13/README.md b/2016/Day13/README.md deleted file mode 100644 index 37cfc68bf..000000000 --- a/2016/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: A Maze of Twisty Little Cubicles --- -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](https://adventofcode.com/2016/day/13). \ No newline at end of file diff --git a/2016/Day13/Solution.cs b/2016/Day13/Solution.cs deleted file mode 100644 index ea7682293..000000000 --- a/2016/Day13/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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)); - } - } - } - } - } - } -} diff --git a/2016/Day13/input.in b/2016/Day13/input.in deleted file mode 100644 index c12c644c8..000000000 Binary files a/2016/Day13/input.in and /dev/null differ diff --git a/2016/Day13/input.refout b/2016/Day13/input.refout deleted file mode 100644 index 628a5115f..000000000 --- a/2016/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -92 -124 diff --git a/2016/Day14/README.md b/2016/Day14/README.md deleted file mode 100644 index 5d0c9057c..000000000 --- a/2016/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: One-Time Pad --- -In order to communicate securely with Santa while you're on this mission, you've been using a [one-time pad](https://en.wikipedia.org/wiki/One-time_pad) that you [generate](https://en.wikipedia.org/wiki/Security_through_obscurity) 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](https://en.wikipedia.org/wiki/MD5) of a pre-arranged [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) (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](https://adventofcode.com/2016/day/14). \ No newline at end of file diff --git a/2016/Day14/Solution.cs b/2016/Day14/Solution.cs deleted file mode 100644 index 18d77532f..000000000 --- a/2016/Day14/Solution.cs +++ /dev/null @@ -1,99 +0,0 @@ -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; - } - } - } -} diff --git a/2016/Day14/input.in b/2016/Day14/input.in deleted file mode 100644 index fa1a5b352..000000000 Binary files a/2016/Day14/input.in and /dev/null differ diff --git a/2016/Day14/input.refout b/2016/Day14/input.refout deleted file mode 100644 index 0a3027bae..000000000 --- a/2016/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -18626 -20092 diff --git a/2016/Day15/README.md b/2016/Day15/README.md deleted file mode 100644 index e0930ef41..000000000 --- a/2016/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Timing is Everything --- -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](https://youtu.be/IxDoO9oODOk?t=177) 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](https://adventofcode.com/2016/day/15). \ No newline at end of file diff --git a/2016/Day15/Solution.cs b/2016/Day15/Solution.cs deleted file mode 100644 index f8621d485..000000000 --- a/2016/Day15/Solution.cs +++ /dev/null @@ -1,27 +0,0 @@ -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); - } - } -} diff --git a/2016/Day15/input.in b/2016/Day15/input.in deleted file mode 100644 index d98a91e50..000000000 Binary files a/2016/Day15/input.in and /dev/null differ diff --git a/2016/Day15/input.refout b/2016/Day15/input.refout deleted file mode 100644 index 5016a01fd..000000000 --- a/2016/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -317371 -2080951 \ No newline at end of file diff --git a/2016/Day16/README.md b/2016/Day16/README.md deleted file mode 100644 index e5a6546ce..000000000 --- a/2016/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Dragon Checksum --- -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](https://en.wikipedia.org/wiki/Dragon_curve). - -Read the [full puzzle](https://adventofcode.com/2016/day/16). \ No newline at end of file diff --git a/2016/Day16/Solution.cs b/2016/Day16/Solution.cs deleted file mode 100644 index 8075b29e9..000000000 --- a/2016/Day16/Solution.cs +++ /dev/null @@ -1,32 +0,0 @@ -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; - } -} diff --git a/2016/Day16/input.in b/2016/Day16/input.in deleted file mode 100644 index 6d0d69381..000000000 Binary files a/2016/Day16/input.in and /dev/null differ diff --git a/2016/Day16/input.refout b/2016/Day16/input.refout deleted file mode 100644 index ed762602f..000000000 --- a/2016/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -10011010010010010 -10101011110100011 diff --git a/2016/Day17/README.md b/2016/Day17/README.md deleted file mode 100644 index 7cc530e50..000000000 --- a/2016/Day17/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## --- Day 17: Two Steps Forward --- -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](https://adventofcode.com/2016/day/17). \ No newline at end of file diff --git a/2016/Day17/Solution.cs b/2016/Day17/Solution.cs deleted file mode 100644 index 7689db5ce..000000000 --- a/2016/Day17/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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'); - } -} diff --git a/2016/Day17/input.in b/2016/Day17/input.in deleted file mode 100644 index a868569aa..000000000 Binary files a/2016/Day17/input.in and /dev/null differ diff --git a/2016/Day17/input.refout b/2016/Day17/input.refout deleted file mode 100644 index 38a82a4e3..000000000 --- a/2016/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -DDRRUDLRRD -488 diff --git a/2016/Day18/README.md b/2016/Day18/README.md deleted file mode 100644 index aa4737079..000000000 --- a/2016/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Like a Rogue --- -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](https://nethackwiki.com/wiki/Trap), 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](https://adventofcode.com/2016/day/18). \ No newline at end of file diff --git a/2016/Day18/Solution.cs b/2016/Day18/Solution.cs deleted file mode 100644 index 4ceb5b27c..000000000 --- a/2016/Day18/Solution.cs +++ /dev/null @@ -1,37 +0,0 @@ -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; - } -} diff --git a/2016/Day18/input.in b/2016/Day18/input.in deleted file mode 100644 index ca1d62f7f..000000000 Binary files a/2016/Day18/input.in and /dev/null differ diff --git a/2016/Day18/input.refout b/2016/Day18/input.refout deleted file mode 100644 index 7f6ad48ba..000000000 --- a/2016/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1939 -19999535 diff --git a/2016/Day19/README.md b/2016/Day19/README.md deleted file mode 100644 index 5bfdef034..000000000 --- a/2016/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: An Elephant Named Joseph --- -The Elves contact you over a highly secure emergency channel. Back at the North Pole, the Elves are busy misunderstanding [White Elephant parties](https://en.wikipedia.org/wiki/White_elephant_gift_exchange). - -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](https://adventofcode.com/2016/day/19). \ No newline at end of file diff --git a/2016/Day19/Solution.cs b/2016/Day19/Solution.cs deleted file mode 100644 index 8d1d61064..000000000 --- a/2016/Day19/Solution.cs +++ /dev/null @@ -1,46 +0,0 @@ -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; - } -} diff --git a/2016/Day19/input.in b/2016/Day19/input.in deleted file mode 100644 index e1bea95a1..000000000 Binary files a/2016/Day19/input.in and /dev/null differ diff --git a/2016/Day19/input.refout b/2016/Day19/input.refout deleted file mode 100644 index 6379a451c..000000000 --- a/2016/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1834471 -1420064 diff --git a/2016/Day20/README.md b/2016/Day20/README.md deleted file mode 100644 index f91a56fec..000000000 --- a/2016/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Firewall Rules --- -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](https://en.wikipedia.org/wiki/IPv4#Addressing). - -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](https://en.wikipedia.org/wiki/Dot-decimal_notation) notation, they are written as plain [32-bit integers](https://en.wikipedia.org/wiki/32-bit), which can have any value from `0` through `4294967295`, inclusive. - -Read the [full puzzle](https://adventofcode.com/2016/day/20). \ No newline at end of file diff --git a/2016/Day20/Solution.cs b/2016/Day20/Solution.cs deleted file mode 100644 index 771e31b35..000000000 --- a/2016/Day20/Solution.cs +++ /dev/null @@ -1,48 +0,0 @@ -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(); -} diff --git a/2016/Day20/input.in b/2016/Day20/input.in deleted file mode 100644 index 06143dbaf..000000000 Binary files a/2016/Day20/input.in and /dev/null differ diff --git a/2016/Day20/input.refout b/2016/Day20/input.refout deleted file mode 100644 index a32c75872..000000000 --- a/2016/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -19449262 -119 diff --git a/2016/Day21/README.md b/2016/Day21/README.md deleted file mode 100644 index a38e2892c..000000000 --- a/2016/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Scrambled Letters and Hash --- -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](https://adventofcode.com/2016/day/21). \ No newline at end of file diff --git a/2016/Day21/Solution.cs b/2016/Day21/Solution.cs deleted file mode 100644 index 6f684362b..000000000 --- a/2016/Day21/Solution.cs +++ /dev/null @@ -1,140 +0,0 @@ -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; - } -} diff --git a/2016/Day21/input.in b/2016/Day21/input.in deleted file mode 100644 index 859177f85..000000000 Binary files a/2016/Day21/input.in and /dev/null differ diff --git a/2016/Day21/input.refout b/2016/Day21/input.refout deleted file mode 100644 index cd57f7075..000000000 --- a/2016/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -ghfacdbe -fhgcdaeb diff --git a/2016/Day22/README.md b/2016/Day22/README.md deleted file mode 100644 index 152ace850..000000000 --- a/2016/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Grid Computing --- -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](https://adventofcode.com/2016/day/22). \ No newline at end of file diff --git a/2016/Day22/Solution.cs b/2016/Day22/Solution.cs deleted file mode 100644 index d36b5e5c9..000000000 --- a/2016/Day22/Solution.cs +++ /dev/null @@ -1,140 +0,0 @@ -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; } } - } -} diff --git a/2016/Day22/input.in b/2016/Day22/input.in deleted file mode 100644 index 1c0570dda..000000000 Binary files a/2016/Day22/input.in and /dev/null differ diff --git a/2016/Day22/input.refout b/2016/Day22/input.refout deleted file mode 100644 index d5bea675e..000000000 --- a/2016/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1007 -242 diff --git a/2016/Day23/README.md b/2016/Day23/README.md deleted file mode 100644 index 6312da7fa..000000000 --- a/2016/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Safe Cracking --- -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](https://adventofcode.com/2016/day/23). \ No newline at end of file diff --git a/2016/Day23/Solution.cs b/2016/Day23/Solution.cs deleted file mode 100644 index 6b6a6b200..000000000 --- a/2016/Day23/Solution.cs +++ /dev/null @@ -1,85 +0,0 @@ -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(); -} diff --git a/2016/Day23/input.in b/2016/Day23/input.in deleted file mode 100644 index ea5304016..000000000 Binary files a/2016/Day23/input.in and /dev/null differ diff --git a/2016/Day23/input.refout b/2016/Day23/input.refout deleted file mode 100644 index 06c80095a..000000000 --- a/2016/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -10223 -479006783 diff --git a/2016/Day24/README.md b/2016/Day24/README.md deleted file mode 100644 index ca42bf3f9..000000000 --- a/2016/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Air Duct Spelunking --- -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](https://adventofcode.com/2016/day/24). \ No newline at end of file diff --git a/2016/Day24/Solution.cs b/2016/Day24/Solution.cs deleted file mode 100644 index daa435049..000000000 --- a/2016/Day24/Solution.cs +++ /dev/null @@ -1,105 +0,0 @@ -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]; - } - } -} diff --git a/2016/Day24/input.in b/2016/Day24/input.in deleted file mode 100644 index 5051464fd..000000000 Binary files a/2016/Day24/input.in and /dev/null differ diff --git a/2016/Day24/input.refout b/2016/Day24/input.refout deleted file mode 100644 index 93c5bf687..000000000 --- a/2016/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -474 -696 diff --git a/2016/Day25/README.md b/2016/Day25/README.md deleted file mode 100644 index 268d84818..000000000 --- a/2016/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Clock Signal --- -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](https://adventofcode.com/2016/day/25). \ No newline at end of file diff --git a/2016/Day25/Solution.cs b/2016/Day25/Solution.cs deleted file mode 100644 index 8dd6297d7..000000000 --- a/2016/Day25/Solution.cs +++ /dev/null @@ -1,75 +0,0 @@ -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(); -} diff --git a/2016/Day25/input.in b/2016/Day25/input.in deleted file mode 100644 index 98d287199..000000000 Binary files a/2016/Day25/input.in and /dev/null differ diff --git a/2016/Day25/input.refout b/2016/Day25/input.refout deleted file mode 100644 index 86a030719..000000000 --- a/2016/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -192 diff --git a/2016/README.md b/2016/README.md deleted file mode 100644 index d3ef6bd90..000000000 --- a/2016/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2016) -Check out https://adventofcode.com/2016. - - diff --git a/2016/SplashScreen.cs b/2016/SplashScreen.cs deleted file mode 100644 index 04fac5852..000000000 --- a/2016/SplashScreen.cs +++ /dev/null @@ -1,265 +0,0 @@ -using System; - -namespace AdventOfCode.Y2016; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ // 2016\n \n "); - Write(0xcc00, false, " "); - Write(0xffff66, true, "( ( ( ( ((*)) ) ) ) ) \n "); - Write(0x666666, false, " | \n +-|---+ "); - Write(0x666666, false, " \n / | /| \n "); - Write(0x666666, false, " +-----+ | \n |"); - Write(0x333333, false, "::"); - Write(0xffff66, true, ":"); - Write(0x333333, false, "::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " +----+ |"); - Write(0x333333, false, "::"); - Write(0x9900, true, ":"); - Write(0x333333, false, "::"); - Write(0x666666, false, "| |---+ +-----------+ "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " / / \\ |"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":::"); - Write(0x333333, false, ":"); - Write(0x666666, false, "| | /| / \\\\\\\\\\\\ [] /| "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " / / / \\|"); - Write(0x9900, true, ":::::"); - Write(0x666666, false, "| | / | / \\\\\\\\\\\\ [] / | "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " / / / / \\"); - Write(0x333333, false, "::"); - Write(0x553322, true, ":"); - Write(0x333333, false, "::"); - Write(0x666666, false, "|/ / | +-----------+ | "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " +----+ / / / \\------+ ------|"); - Write(0x333333, false, "::::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |-----\\ / / / \\=====| ------|"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |------\\ / / / \\====| | |"); - Write(0x66ff, true, ":::"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":::"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |-------\\ / / / +===| | |"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |--------\\ / / /|===| | |"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |---------\\ / / |===| | /|"); - Write(0x66ff, true, ":::"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":::"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":::"); - Write(0x666666, false, "| | "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |----------\\ / |===| / //|"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":"); - Write(0x666666, false, "| / "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " +-----------+ |===| / //||"); - Write(0x333333, false, "::::"); - Write(0x66ff, true, ":"); - Write(0x333333, false, ":"); - Write(0x66ff, true, ":"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "|/ "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, "::::::::"); - Write(0x666666, false, "| |===|/__//___________________ "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0xff0000, true, ":::"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":::"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "| |______//|_____...._________ "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "| | //| ____/ /_/___ "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ---|"); - Write(0x333333, false, "::::"); - Write(0x9900, true, ":::"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "| |--------|[][]|_|[][]_\\------ "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "----|"); - Write(0x333333, false, "::"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, "::::::"); - Write(0x666666, false, "| |--------------------------- "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " || |"); - Write(0x333333, false, "::"); - Write(0xff0000, true, ":::"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":::"); - Write(0x333333, false, "::"); - Write(0x666666, false, "| | //| || / / / || || "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " || |"); - Write(0x333333, false, "::"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x333333, false, "::"); - Write(0x666666, false, "| | //| || / / || "); - Write(0xffff66, true, "*"); - Write(0x666666, false, " || "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0x333333, false, "::::::"); - Write(0x9900, true, ":::"); - Write(0x333333, false, "::"); - Write(0x666666, false, "| |//| / / / "); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0x333333, false, "::::"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, "::::"); - Write(0x666666, false, "| //| / / ___"); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "<"); - Write(0x666666, false, "____ "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0x333333, false, "::::"); - Write(0xff0000, true, ":::"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":::"); - Write(0x666666, false, "| //| / / / / "); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0x666666, false, " / "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0x333333, false, "::::"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0xff0000, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x333333, false, ":"); - Write(0x9900, true, ":"); - Write(0x666666, false, "| //| / / / "); - Write(0xaaaaaa, false, "_| |_"); - Write(0x666666, false, " / "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " |"); - Write(0x333333, false, "::::::::"); - Write(0x9900, true, ":::"); - Write(0x666666, false, "|//| / / / /___________/ "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ==============//======+...+==================== \n - - - - - - -// - - -/ / - -"); - Write(0x666666, false, " - - - - - - - - \n ==============//|============================== \n "); - Write(0x666666, false, " //| \n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2016/calendar.svg b/2016/calendar.svg deleted file mode 100644 index 001a5323e..000000000 --- a/2016/calendar.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  // 2016 -  -(       (    (  ( ((*)) )  )    )       )                -                    |                                    -                  +-|---+                                -                 /  |  /|                                -                +-----+ |                                -                |:::::| |                          25 ** -        +----+  |:::::| |---+      +-----------+   24 ** -       /    / \ |:::::| |  /|     / \\\\\\ [] /|   23 ** -      /    / / \|:::::| | / |    / \\\\\\ [] / |   22 ** -     /    / / / \:::::|/ /  |   +-----------+  |   21 ** -    +----+ / / / \------+ ------|:::::::::::|  |   20 ** -    |-----\ / / / \=====| ------|:::::::::::|  |   19 ** -    |------\ / / / \====|   |   |:::::::::::|  |   18 ** -    |-------\ / / / +===|   |   |:::::::::::|  |   17 ** -    |--------\ / / /|===|   |   |:::::::::::|  |   16 ** -    |---------\ / / |===|   |  /|:::::::::::|  |   15 ** -    |----------\ /  |===|  /  //|:::::::::::| /    14 ** -    +-----------+   |===| /  //||:::::::::::|/     13 ** -    |:::::::::::|   |===|/__//___________________  12 ** -    |:::::::::::|   |______//|_____...._________   11 ** -    |:::::::::::|   |     //| ____/ /_/___         10 ** - ---|:::::::::::|   |--------|[][]|_|[][]_\------   9 ** -----|:::::::::::|   |---------------------------    8 ** - || |:::::::::::|   |  //| ||  / / / ||      ||     7 ** - || |:::::::::::|   | //|  || /   /  ||  *   ||     6 ** -    |:::::::::::|   |//|     / / /      >o<         5 ** -    |:::::::::::|   //|     /   /   ___>@>O<____    4 ** -    |:::::::::::|  //|     / / /   /  >O>o<@<  /    3 ** -    |:::::::::::| //|     /   /   /    _| |_  /     2 ** -    |:::::::::::|//|     / / /   /___________/      1 ** -  ==============//======+...+====================        -  - - - - - - -// - - -/   / - - - - - - - - - -         -==============//|==============================          -             //|                                         - - - - \ No newline at end of file diff --git a/2017/Day01/README.md b/2017/Day01/README.md deleted file mode 100644 index ceb540a18..000000000 --- a/2017/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Inverse Captcha --- -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. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2017/day/1) description._ diff --git a/2017/Day01/Solution.cs b/2017/Day01/Solution.cs deleted file mode 100755 index 2f114aa8c..000000000 --- a/2017/Day01/Solution.cs +++ /dev/null @@ -1,19 +0,0 @@ -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(); - } -} diff --git a/2017/Day01/input.in b/2017/Day01/input.in deleted file mode 100644 index a2138c7ab..000000000 Binary files a/2017/Day01/input.in and /dev/null differ diff --git a/2017/Day01/input.refout b/2017/Day01/input.refout deleted file mode 100644 index 6250b7ce4..000000000 --- a/2017/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1253 -1278 \ No newline at end of file diff --git a/2017/Day02/README.md b/2017/Day02/README.md deleted file mode 100644 index f2bb4b766..000000000 --- a/2017/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Corruption Checksum --- -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](https://adventofcode.com/2017/day/2). \ No newline at end of file diff --git a/2017/Day02/Solution.cs b/2017/Day02/Solution.cs deleted file mode 100755 index ab500a9eb..000000000 --- a/2017/Day02/Solution.cs +++ /dev/null @@ -1,26 +0,0 @@ -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(); - } -} diff --git a/2017/Day02/input.in b/2017/Day02/input.in deleted file mode 100644 index e09ace427..000000000 Binary files a/2017/Day02/input.in and /dev/null differ diff --git a/2017/Day02/input.refout b/2017/Day02/input.refout deleted file mode 100644 index b3bf129bd..000000000 --- a/2017/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -32121 -197 diff --git a/2017/Day03/README.md b/2017/Day03/README.md deleted file mode 100644 index 8bf5afc07..000000000 --- a/2017/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Spiral Memory --- -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](https://adventofcode.com/2017/day/3). \ No newline at end of file diff --git a/2017/Day03/Solution.cs b/2017/Day03/Solution.cs deleted file mode 100755 index b823a0328..000000000 --- a/2017/Day03/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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); -} diff --git a/2017/Day03/input.in b/2017/Day03/input.in deleted file mode 100644 index 799a453dc..000000000 Binary files a/2017/Day03/input.in and /dev/null differ diff --git a/2017/Day03/input.refout b/2017/Day03/input.refout deleted file mode 100644 index 3605eb183..000000000 --- a/2017/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -430 -312453 diff --git a/2017/Day04/README.md b/2017/Day04/README.md deleted file mode 100644 index 1c942d90a..000000000 --- a/2017/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: High-Entropy Passphrases --- -A new system policy has been put in place that requires all accounts to use a *passphrase* instead of simply a pass*word*. 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](https://adventofcode.com/2017/day/4). \ No newline at end of file diff --git a/2017/Day04/Solution.cs b/2017/Day04/Solution.cs deleted file mode 100755 index c4f1cffe0..000000000 --- a/2017/Day04/Solution.cs +++ /dev/null @@ -1,20 +0,0 @@ -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(); -} diff --git a/2017/Day04/input.in b/2017/Day04/input.in deleted file mode 100644 index a2a581f41..000000000 Binary files a/2017/Day04/input.in and /dev/null differ diff --git a/2017/Day04/input.refout b/2017/Day04/input.refout deleted file mode 100644 index 8b537252d..000000000 --- a/2017/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -455 -186 diff --git a/2017/Day05/README.md b/2017/Day05/README.md deleted file mode 100644 index 838976f6a..000000000 --- a/2017/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: A Maze of Twisty Trampolines, All Alike --- -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](https://adventofcode.com/2017/day/5). \ No newline at end of file diff --git a/2017/Day05/Solution.cs b/2017/Day05/Solution.cs deleted file mode 100755 index 021d73de9..000000000 --- a/2017/Day05/Solution.cs +++ /dev/null @@ -1,25 +0,0 @@ -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; - } -} diff --git a/2017/Day05/input.in b/2017/Day05/input.in deleted file mode 100644 index a6f2d41e0..000000000 Binary files a/2017/Day05/input.in and /dev/null differ diff --git a/2017/Day05/input.refout b/2017/Day05/input.refout deleted file mode 100644 index 17c796bbf..000000000 --- a/2017/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -374269 -27720699 diff --git a/2017/Day06/README.md b/2017/Day06/README.md deleted file mode 100644 index a3a4fd7ba..000000000 --- a/2017/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Memory Reallocation --- -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](https://adventofcode.com/2017/day/6). \ No newline at end of file diff --git a/2017/Day06/Solution.cs b/2017/Day06/Solution.cs deleted file mode 100755 index e37b91233..000000000 --- a/2017/Day06/Solution.cs +++ /dev/null @@ -1,43 +0,0 @@ -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--; - } - } -} diff --git a/2017/Day06/input.in b/2017/Day06/input.in deleted file mode 100644 index 90d310c5a..000000000 Binary files a/2017/Day06/input.in and /dev/null differ diff --git a/2017/Day06/input.refout b/2017/Day06/input.refout deleted file mode 100644 index 7c5b5110a..000000000 --- a/2017/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6681 -2392 diff --git a/2017/Day07/README.md b/2017/Day07/README.md deleted file mode 100644 index 5d8adfa75..000000000 --- a/2017/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: Recursive Circus --- -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](https://adventofcode.com/2017/day/7). \ No newline at end of file diff --git a/2017/Day07/Solution.cs b/2017/Day07/Solution.cs deleted file mode 100755 index 8f6c361d7..000000000 --- a/2017/Day07/Solution.cs +++ /dev/null @@ -1,82 +0,0 @@ -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); - } - } -} diff --git a/2017/Day07/input.in b/2017/Day07/input.in deleted file mode 100644 index 0f1f687ea..000000000 Binary files a/2017/Day07/input.in and /dev/null differ diff --git a/2017/Day07/input.refout b/2017/Day07/input.refout deleted file mode 100644 index d3b8398ea..000000000 --- a/2017/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -vvsvez -362 diff --git a/2017/Day08/README.md b/2017/Day08/README.md deleted file mode 100644 index b8a09384d..000000000 --- a/2017/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: I Heard You Like Registers --- -You receive a signal directly from the CPU. Because of your recent assistance with [jump instructions](5), 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](https://adventofcode.com/2017/day/8). \ No newline at end of file diff --git a/2017/Day08/Solution.cs b/2017/Day08/Solution.cs deleted file mode 100755 index 30396292d..000000000 --- a/2017/Day08/Solution.cs +++ /dev/null @@ -1,46 +0,0 @@ -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()); - } -} diff --git a/2017/Day08/input.in b/2017/Day08/input.in deleted file mode 100644 index 94afcf93d..000000000 Binary files a/2017/Day08/input.in and /dev/null differ diff --git a/2017/Day08/input.refout b/2017/Day08/input.refout deleted file mode 100644 index 90866527f..000000000 --- a/2017/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6343 -7184 diff --git a/2017/Day09/README.md b/2017/Day09/README.md deleted file mode 100644 index 03e6ad6b8..000000000 --- a/2017/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Stream Processing --- -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](https://adventofcode.com/2017/day/9). \ No newline at end of file diff --git a/2017/Day09/Solution.cs b/2017/Day09/Solution.cs deleted file mode 100755 index 01b4a2f62..000000000 --- a/2017/Day09/Solution.cs +++ /dev/null @@ -1,49 +0,0 @@ -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); - } - } - } - } -} diff --git a/2017/Day09/input.in b/2017/Day09/input.in deleted file mode 100644 index 2de7e7361..000000000 Binary files a/2017/Day09/input.in and /dev/null differ diff --git a/2017/Day09/input.refout b/2017/Day09/input.refout deleted file mode 100644 index 6dd2325c9..000000000 --- a/2017/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -14212 -6569 diff --git a/2017/Day10/README.md b/2017/Day10/README.md deleted file mode 100644 index 525202279..000000000 --- a/2017/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Knot Hash --- -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](https://adventofcode.com/2017/day/10). \ No newline at end of file diff --git a/2017/Day10/Solution.cs b/2017/Day10/Solution.cs deleted file mode 100755 index 56eb1186a..000000000 --- a/2017/Day10/Solution.cs +++ /dev/null @@ -1,45 +0,0 @@ -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; - } -} diff --git a/2017/Day10/input.in b/2017/Day10/input.in deleted file mode 100644 index 960b72aab..000000000 Binary files a/2017/Day10/input.in and /dev/null differ diff --git a/2017/Day10/input.refout b/2017/Day10/input.refout deleted file mode 100644 index f7d268b57..000000000 --- a/2017/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -826 -d067d3f14d07e09c2e7308c3926605c4 diff --git a/2017/Day11/README.md b/2017/Day11/README.md deleted file mode 100644 index 5e1c4b600..000000000 --- a/2017/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Hex Ed --- -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](https://adventofcode.com/2017/day/11). \ No newline at end of file diff --git a/2017/Day11/Solution.cs b/2017/Day11/Solution.cs deleted file mode 100755 index f0bb5d90f..000000000 --- a/2017/Day11/Solution.cs +++ /dev/null @@ -1,32 +0,0 @@ -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); - } - } -} diff --git a/2017/Day11/input.in b/2017/Day11/input.in deleted file mode 100644 index b630af35f..000000000 Binary files a/2017/Day11/input.in and /dev/null differ diff --git a/2017/Day11/input.refout b/2017/Day11/input.refout deleted file mode 100644 index ef522ce42..000000000 --- a/2017/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -687 -1483 diff --git a/2017/Day12/README.md b/2017/Day12/README.md deleted file mode 100644 index ac03ac73b..000000000 --- a/2017/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Digital Plumber --- -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](https://adventofcode.com/2017/day/12). \ No newline at end of file diff --git a/2017/Day12/Solution.cs b/2017/Day12/Solution.cs deleted file mode 100755 index 18bcaf829..000000000 --- a/2017/Day12/Solution.cs +++ /dev/null @@ -1,59 +0,0 @@ -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(); - } - -} diff --git a/2017/Day12/input.in b/2017/Day12/input.in deleted file mode 100644 index 0e252b630..000000000 Binary files a/2017/Day12/input.in and /dev/null differ diff --git a/2017/Day12/input.refout b/2017/Day12/input.refout deleted file mode 100644 index 5d4e8c6a9..000000000 --- a/2017/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -128 -209 diff --git a/2017/Day13/README.md b/2017/Day13/README.md deleted file mode 100644 index f3f247c6d..000000000 --- a/2017/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Packet Scanners --- -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](https://adventofcode.com/2017/day/13). \ No newline at end of file diff --git a/2017/Day13/Solution.cs b/2017/Day13/Solution.cs deleted file mode 100755 index e8d71e292..000000000 --- a/2017/Day13/Solution.cs +++ /dev/null @@ -1,42 +0,0 @@ -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; - } - } - } -} diff --git a/2017/Day13/input.in b/2017/Day13/input.in deleted file mode 100644 index 04007867a..000000000 Binary files a/2017/Day13/input.in and /dev/null differ diff --git a/2017/Day13/input.refout b/2017/Day13/input.refout deleted file mode 100644 index 0f6b43a45..000000000 --- a/2017/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -748 -3873662 diff --git a/2017/Day14/README.md b/2017/Day14/README.md deleted file mode 100644 index e57cab07d..000000000 --- a/2017/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Disk Defragmentation --- -Suddenly, a scheduled job activates the system's [disk defragmenter](https://en.wikipedia.org/wiki/Defragmentation). Were the situation different, you might [sit and watch it for a while](https://www.youtube.com/watch?v=kPv1gQ5Rs8A&t=37), 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](10). - -Read the [full puzzle](https://adventofcode.com/2017/day/14). \ No newline at end of file diff --git a/2017/Day14/Solution.cs b/2017/Day14/Solution.cs deleted file mode 100755 index b87f90a3f..000000000 --- a/2017/Day14/Solution.cs +++ /dev/null @@ -1,100 +0,0 @@ -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(); - } -} diff --git a/2017/Day14/input.in b/2017/Day14/input.in deleted file mode 100644 index eb4843fa4..000000000 Binary files a/2017/Day14/input.in and /dev/null differ diff --git a/2017/Day14/input.refout b/2017/Day14/input.refout deleted file mode 100644 index f0fc530ee..000000000 --- a/2017/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -8148 -1180 diff --git a/2017/Day15/README.md b/2017/Day15/README.md deleted file mode 100644 index caa4832bf..000000000 --- a/2017/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Dueling Generators --- -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](https://adventofcode.com/2017/day/15). \ No newline at end of file diff --git a/2017/Day15/Solution.cs b/2017/Day15/Solution.cs deleted file mode 100755 index 88d8a2546..000000000 --- a/2017/Day15/Solution.cs +++ /dev/null @@ -1,40 +0,0 @@ -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; - } - } -} diff --git a/2017/Day15/input.in b/2017/Day15/input.in deleted file mode 100644 index a5e775638..000000000 Binary files a/2017/Day15/input.in and /dev/null differ diff --git a/2017/Day15/input.refout b/2017/Day15/input.refout deleted file mode 100644 index 18c95fe29..000000000 --- a/2017/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -569 -298 \ No newline at end of file diff --git a/2017/Day16/README.md b/2017/Day16/README.md deleted file mode 100644 index 5fea82b4c..000000000 --- a/2017/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Permutation Promenade --- -You come upon a very unusual sight; a group of programs here appear to be [dancing](https://www.youtube.com/watch?v=lyZQPjUT5B4&t=53). - -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](https://adventofcode.com/2017/day/16). \ No newline at end of file diff --git a/2017/Day16/Solution.cs b/2017/Day16/Solution.cs deleted file mode 100755 index 63f61b27d..000000000 --- a/2017/Day16/Solution.cs +++ /dev/null @@ -1,85 +0,0 @@ -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; - } - } -} diff --git a/2017/Day16/input.in b/2017/Day16/input.in deleted file mode 100644 index bca792491..000000000 Binary files a/2017/Day16/input.in and /dev/null differ diff --git a/2017/Day16/input.refout b/2017/Day16/input.refout deleted file mode 100644 index 79267ff33..000000000 --- a/2017/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -kpfonjglcibaedhm -odiabmplhfgjcekn diff --git a/2017/Day17/README.md b/2017/Day17/README.md deleted file mode 100755 index 470b36a6a..000000000 --- a/2017/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Spinlock --- -Suddenly, whirling in the distance, you notice what looks like a massive, pixelated hurricane: a deadly [spinlock](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2017/day/17). \ No newline at end of file diff --git a/2017/Day17/Solution.cs b/2017/Day17/Solution.cs deleted file mode 100755 index c42b6b19e..000000000 --- a/2017/Day17/Solution.cs +++ /dev/null @@ -1,33 +0,0 @@ -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; - } -} diff --git a/2017/Day17/input.in b/2017/Day17/input.in deleted file mode 100755 index 680907958..000000000 Binary files a/2017/Day17/input.in and /dev/null differ diff --git a/2017/Day17/input.refout b/2017/Day17/input.refout deleted file mode 100644 index 12e438148..000000000 --- a/2017/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -180 -13326437 diff --git a/2017/Day18/README.md b/2017/Day18/README.md deleted file mode 100755 index 5dad72bb5..000000000 --- a/2017/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Duet --- -You discover a tablet containing some strange assembly code labeled simply "[Duet](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Integer). You suppose each register should start with a value of `0`. - -Read the [full puzzle](https://adventofcode.com/2017/day/18). \ No newline at end of file diff --git a/2017/Day18/Solution.cs b/2017/Day18/Solution.cs deleted file mode 100755 index 39ad1db6e..000000000 --- a/2017/Day18/Solution.cs +++ /dev/null @@ -1,151 +0,0 @@ -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; - } - } -} diff --git a/2017/Day18/input.in b/2017/Day18/input.in deleted file mode 100755 index d009c685d..000000000 Binary files a/2017/Day18/input.in and /dev/null differ diff --git a/2017/Day18/input.refout b/2017/Day18/input.refout deleted file mode 100644 index 40344ddc6..000000000 --- a/2017/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -9423 -7620 diff --git a/2017/Day19/README.md b/2017/Day19/README.md deleted file mode 100644 index 51bf41e1f..000000000 --- a/2017/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: A Series of Tubes --- -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](https://adventofcode.com/2017/day/19). \ No newline at end of file diff --git a/2017/Day19/Solution.cs b/2017/Day19/Solution.cs deleted file mode 100644 index e2a072db4..000000000 --- a/2017/Day19/Solution.cs +++ /dev/null @@ -1,47 +0,0 @@ -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); - } -} diff --git a/2017/Day19/input.in b/2017/Day19/input.in deleted file mode 100644 index 5dff2031d..000000000 Binary files a/2017/Day19/input.in and /dev/null differ diff --git a/2017/Day19/input.refout b/2017/Day19/input.refout deleted file mode 100644 index 93bf8246c..000000000 --- a/2017/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -RUEDAHWKSM -17264 diff --git a/2017/Day20/README.md b/2017/Day20/README.md deleted file mode 100644 index 5f187c427..000000000 --- a/2017/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Particle Swarm --- -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 ``. - -Read the [full puzzle](https://adventofcode.com/2017/day/20). \ No newline at end of file diff --git a/2017/Day20/Solution.cs b/2017/Day20/Solution.cs deleted file mode 100644 index 30382587f..000000000 --- a/2017/Day20/Solution.cs +++ /dev/null @@ -1,142 +0,0 @@ -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)); - } - - } - } - } -} diff --git a/2017/Day20/input.in b/2017/Day20/input.in deleted file mode 100644 index 7c61f4550..000000000 Binary files a/2017/Day20/input.in and /dev/null differ diff --git a/2017/Day20/input.refout b/2017/Day20/input.refout deleted file mode 100644 index ee3ee6635..000000000 --- a/2017/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -457 -448 diff --git a/2017/Day21/README.md b/2017/Day21/README.md deleted file mode 100644 index e949862b9..000000000 --- a/2017/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Fractal Art --- -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](https://adventofcode.com/2017/day/21). \ No newline at end of file diff --git a/2017/Day21/Solution.cs b/2017/Day21/Solution.cs deleted file mode 100644 index 7ae2b8378..000000000 --- a/2017/Day21/Solution.cs +++ /dev/null @@ -1,197 +0,0 @@ -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; - } - } -} diff --git a/2017/Day21/input.in b/2017/Day21/input.in deleted file mode 100644 index 8ef156364..000000000 Binary files a/2017/Day21/input.in and /dev/null differ diff --git a/2017/Day21/input.refout b/2017/Day21/input.refout deleted file mode 100644 index 2e78b4052..000000000 --- a/2017/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -147 -1936582 diff --git a/2017/Day22/README.md b/2017/Day22/README.md deleted file mode 100644 index 8355477fd..000000000 --- a/2017/Day22/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## --- Day 22: Sporifica Virus --- - -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](https://adventofcode.com/2017/day/22). \ No newline at end of file diff --git a/2017/Day22/Solution.cs b/2017/Day22/Solution.cs deleted file mode 100644 index 9494c0bf2..000000000 --- a/2017/Day22/Solution.cs +++ /dev/null @@ -1,71 +0,0 @@ -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; - } -} diff --git a/2017/Day22/input.in b/2017/Day22/input.in deleted file mode 100644 index 51ee69ad2..000000000 Binary files a/2017/Day22/input.in and /dev/null differ diff --git a/2017/Day22/input.refout b/2017/Day22/input.refout deleted file mode 100644 index 7bb50aedd..000000000 --- a/2017/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5406 -2511640 \ No newline at end of file diff --git a/2017/Day23/README.md b/2017/Day23/README.md deleted file mode 100644 index 67204d7f4..000000000 --- a/2017/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Coprocessor Conflagration --- -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](https://en.wikipedia.org/wiki/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](18). The general functionality seems *very similar*, but some of the instructions are different: - -Read the [full puzzle](https://adventofcode.com/2017/day/23). \ No newline at end of file diff --git a/2017/Day23/Solution.cs b/2017/Day23/Solution.cs deleted file mode 100644 index 248f520fc..000000000 --- a/2017/Day23/Solution.cs +++ /dev/null @@ -1,66 +0,0 @@ -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; - } - -} diff --git a/2017/Day23/input.in b/2017/Day23/input.in deleted file mode 100644 index cbf93a8de..000000000 Binary files a/2017/Day23/input.in and /dev/null differ diff --git a/2017/Day23/input.refout b/2017/Day23/input.refout deleted file mode 100644 index 3f1ac48b1..000000000 --- a/2017/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5929 -907 diff --git a/2017/Day24/README.md b/2017/Day24/README.md deleted file mode 100644 index 78618390a..000000000 --- a/2017/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Electromagnetic Moat --- -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](https://adventofcode.com/2017/day/24). \ No newline at end of file diff --git a/2017/Day24/Solution.cs b/2017/Day24/Solution.cs deleted file mode 100644 index d546441d2..000000000 --- a/2017/Day24/Solution.cs +++ /dev/null @@ -1,49 +0,0 @@ -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; -} diff --git a/2017/Day24/input.in b/2017/Day24/input.in deleted file mode 100644 index 1309fea11..000000000 Binary files a/2017/Day24/input.in and /dev/null differ diff --git a/2017/Day24/input.refout b/2017/Day24/input.refout deleted file mode 100644 index cf8455bc6..000000000 --- a/2017/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1859 -1799 diff --git a/2017/Day25/README.md b/2017/Day25/README.md deleted file mode 100644 index 301a86bc7..000000000 --- a/2017/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: The Halting Problem --- -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](https://adventofcode.com/2017/day/25). \ No newline at end of file diff --git a/2017/Day25/Solution.cs b/2017/Day25/Solution.cs deleted file mode 100644 index 4b001daeb..000000000 --- a/2017/Day25/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -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)>(); -} diff --git a/2017/Day25/input.in b/2017/Day25/input.in deleted file mode 100644 index b0a778b4a..000000000 Binary files a/2017/Day25/input.in and /dev/null differ diff --git a/2017/Day25/input.refout b/2017/Day25/input.refout deleted file mode 100644 index 2dcfbdc04..000000000 --- a/2017/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -2870 diff --git a/2017/README.md b/2017/README.md deleted file mode 100644 index 33861dcbc..000000000 --- a/2017/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2017) -Check out https://adventofcode.com/2017. - - diff --git a/2017/SplashScreen.cs b/2017/SplashScreen.cs deleted file mode 100644 index fb4ba3fb2..000000000 --- a/2017/SplashScreen.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System; - -namespace AdventOfCode.Y2017; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ {'year': 2017}\n "); - Write(0xcc00, false, " \n "); - Write(0x999999, false, "|O| "); - Write(0xcccccc, false, " Naughty | Nice "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "-------------------+------------------- "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "The Easter Bunny | encse "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "Martin Galese | Szabolcs Sipos "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "Balázs Dankó | wesen "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "Gábor Gyebnár | Daniel Willenson "); - Write(0x999999, false, "|O| \n |O| "); - Write(0xcccccc, false, "Woodrow Hedberg | gkatai "); - Write(0x999999, false, "|O| \n "); - Write(0xcccccc, false, ".-----------------------------------------------. \n | "); - Write(0x666666, false, "┌───────────────o┌"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "───────"); - Write(0xaaaaaa, false, "[─]"); - Write(0x666666, false, "────┐o─────────┐ "); - Write(0xcccccc, false, "| 25 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└──────"); - Write(0x9900, false, "oTo"); - Write(0x666666, false, "───────┘└────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "┌o┌────┐┌┘┌─────────┤ "); - Write(0xcccccc, false, "| 24 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xffff66, true, "*"); - Write(0x666666, false, "───────────────────"); - Write(0x66ff, false, "|("); - Write(0x666666, false, "─┘├─┘┌──o└┘┌┴──────┐o─┘ "); - Write(0xcccccc, false, "| 23 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└───"); - Write(0xff0000, false, "┤|├"); - Write(0x666666, false, "───┬┴┴┴┴┬────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "┌─o│o─┴─────┴──────o└──┐ "); - Write(0xcccccc, false, "| 22 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xffff66, true, "*"); - Write(0x666666, false, "─"); - Write(0xaaaaaa, false, "[─]"); - Write(0x666666, false, "─"); - Write(0xaaaaaa, false, "[─]"); - Write(0x666666, false, "─┤ DY├────┘└──┴────"); - Write(0xff9900, false, "∧∧∧"); - Write(0x666666, false, "────────────┤ "); - Write(0xcccccc, false, "| 21 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "├─────────┤ EP├─────┐┌──"); - Write(0xff9900, false, "∧∧∧"); - Write(0x666666, false, "──"); - Write(0x990099, false, "┤[]├"); - Write(0x666666, false, "───┐┌─"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "o──┘ "); - Write(0xcccccc, false, "| 20 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└─────────┤ CT├────┬┘│V┌────┬──────o└┴o└───"); - Write(0xffff66, true, "* "); - Write(0xcccccc, false, "| 19 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌─────────┤ RR├o───┘┌┘└┴──o┌┘"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "─────┬┴┴┴┬───┘ "); - Write(0xcccccc, false, "| 18 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "├─────────┤ ├─────┘o┬────┘┌┘┌────┤ 30├───"); - Write(0xffff66, true, "* "); - Write(0xcccccc, false, "| 17 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "│o┬─┐"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "────┼┬┬┬┬┴───"); - Write(0xff9900, false, "∧∧∧"); - Write(0x666666, false, "─┘┌───┐└─┴────┤ 29├┐┌─┘ "); - Write(0xcccccc, false, "| 16 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└─┘┌┘└───"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "└┬┴┴┴┴┬───────┘o──┴──────┐┤ 83├┘└─┐ "); - Write(0xcccccc, false, "| 15 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌──┘┌───o└─┤ ├──┐┌───────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "o─────┴┤ P6├───┘ "); - Write(0xcccccc, false, "| 14 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└┬──┘┌─"); - Write(0x9900, false, "oTo"); - Write(0x666666, false, "─┤ ├─o└┘┌─────o└───────┴┬┬┬┴───"); - Write(0xffff66, true, "* "); - Write(0xcccccc, false, "| 13 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "o┘┌──┘┌────┤ v17├────┴─┐"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "──"); - Write(0xaaaaaa, false, "[─]"); - Write(0x666666, false, "─────────┐┌───┤ "); - Write(0xcccccc, false, "| 12 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌─┘┌┴┴┴┴┴┬─┴┬┬┬┬┴──"); - Write(0x66ff, false, "|("); - Write(0x666666, false, "──┘└──────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "┌─o┌───┘└─┐V│ "); - Write(0xcccccc, false, "| 11 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└──┤ ├"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "──────"); - Write(0xff9900, false, "∧∧∧"); - Write(0x666666, false, "───────────┘└──┴──────┘└┘ "); - Write(0xcccccc, false, "| 10 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌──┤ ├┘┌─────"); - Write(0xff9900, false, "∧∧∧"); - Write(0x666666, false, "───────┐┌───────────────"); - Write(0xffff66, true, "* "); - Write(0xcccccc, false, "| 9 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└──┤ 5 ├─┴─────o"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "───────┐└┴o┌─────────"); - Write(0x66ff, false, "|("); - Write(0x666666, false, "──┤ "); - Write(0xcccccc, false, "| 8 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "─┤ 1P├────────┘o──"); - Write(0x66ff, false, "|("); - Write(0x666666, false, "──┴───┘o─────┬─o┌───┘ "); - Write(0xcccccc, false, "| 7 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "│└─┤ 2B├────────────────────────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "┌─┘┌─┘o──┐ "); - Write(0xcccccc, false, "| 6 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└──┴┬┬┬┬┬┴───┐┌──o┌──────┐"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "───────┘└──┴─────┘ "); - Write(0xcccccc, false, "| 5 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "V┌───────────┘└───┴───o┌─┘└──────┐┌────────"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "o "); - Write(0xcccccc, false, "| 4 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└┴───"); - Write(0xff0000, false, "┤|├"); - Write(0x666666, false, "──────────────┐└──┬───o┌─┘└┐"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "─┐┌──┐└┐ "); - Write(0xcccccc, false, "| 3 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "┌─────────────o┌──────┴───┘"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "──┐└───┘└┐│└─┐└─┤ "); - Write(0xcccccc, false, "| 2 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x666666, false, "└──────────────┴─────o"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "────┘o─┴──────┘└──┘o─┘ "); - Write(0xcccccc, false, "| 1 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "'-----------------------------------------------' \n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2017/calendar.svg b/2017/calendar.svg deleted file mode 100644 index 8c532d567..000000000 --- a/2017/calendar.svg +++ /dev/null @@ -1,55 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  {'year': 2017} -  -|O|        Naughty      |        Nice         |O|        -|O|  -------------------+-------------------  |O|        -|O|  The Easter Bunny   | encse               |O|        -|O|  Martin Galese      | Szabolcs Sipos      |O|        -|O|  Balázs Dankó       | wesen               |O|        -|O|  Gábor Gyebnár      | Daniel Willenson    |O|        -|O|  Woodrow Hedberg    | gkatai              |O|        -.-----------------------------------------------.        -| o*[]o |  25 ** -| oTo*o |  24 ** -| *|(oo |  23 ** -| |*ooo |  22 ** -| *[][]  DY |  21 ** -|   EP[]*o |  20 ** -|   CTVoo* |  19 ** -|   RRoo* |  18 ** -|     o 30* |  17 ** -| o* 29 |  16 ** -| *o 83 |  15 ** -| o    *o P6 |  14 ** -| oTo    oo* |  13 ** -| o v17*[] |  12 ** -| |(*oV |  11 ** -|      * |  10 ** -|      * |   9 ** -|    5 o*o|( |   8 ** -| *   1Po|(oo |   7 ** -|    2B*o |   6 ** -| o* |   5 ** -| Vo*o |   4 ** -| |o* |   3 ** -| o* |   2 ** -| o*oo |   1 ** -'-----------------------------------------------'        - - - - \ No newline at end of file diff --git a/2018/Day01/README.md b/2018/Day01/README.md deleted file mode 100644 index 8ccecebb9..000000000 --- a/2018/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Chronal Calibration --- -"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." - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2018/day/1) description._ diff --git a/2018/Day01/Solution.cs b/2018/Day01/Solution.cs deleted file mode 100644 index 92e411e5c..000000000 --- a/2018/Day01/Solution.cs +++ /dev/null @@ -1,34 +0,0 @@ -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; - } - } - } -} diff --git a/2018/Day01/input.in b/2018/Day01/input.in deleted file mode 100644 index 8103c3057..000000000 Binary files a/2018/Day01/input.in and /dev/null differ diff --git a/2018/Day01/input.refout b/2018/Day01/input.refout deleted file mode 100644 index 95dce70f7..000000000 --- a/2018/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -490 -70357 \ No newline at end of file diff --git a/2018/Day02/README.md b/2018/Day02/README.md deleted file mode 100644 index 920cce933..000000000 --- a/2018/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Inventory Management System --- -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](https://adventofcode.com/2018/day/2). \ No newline at end of file diff --git a/2018/Day02/Solution.cs b/2018/Day02/Solution.cs deleted file mode 100644 index c6aaff74c..000000000 --- a/2018/Day02/Solution.cs +++ /dev/null @@ -1,48 +0,0 @@ -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() : "")); - } -} diff --git a/2018/Day02/input.in b/2018/Day02/input.in deleted file mode 100644 index dc37cf34f..000000000 Binary files a/2018/Day02/input.in and /dev/null differ diff --git a/2018/Day02/input.refout b/2018/Day02/input.refout deleted file mode 100644 index a7398df9d..000000000 --- a/2018/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -7808 -efmyhuckqldtwjyvisipargno diff --git a/2018/Day03/README.md b/2018/Day03/README.md deleted file mode 100644 index cc4dad2c6..000000000 --- a/2018/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: No Matter How You Slice It --- -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](https://adventofcode.com/2018/day/3). \ No newline at end of file diff --git a/2018/Day03/Solution.cs b/2018/Day03/Solution.cs deleted file mode 100644 index dc9ed4e4c..000000000 --- a/2018/Day03/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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()); - } -} diff --git a/2018/Day03/input.in b/2018/Day03/input.in deleted file mode 100644 index ad9827ff8..000000000 Binary files a/2018/Day03/input.in and /dev/null differ diff --git a/2018/Day03/input.refout b/2018/Day03/input.refout deleted file mode 100644 index c43208a7d..000000000 --- a/2018/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -111266 -266 diff --git a/2018/Day04/README.md b/2018/Day04/README.md deleted file mode 100644 index 043e4e5a5..000000000 --- a/2018/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Repose Record --- -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](https://adventofcode.com/2018/day/4). \ No newline at end of file diff --git a/2018/Day04/Solution.cs b/2018/Day04/Solution.cs deleted file mode 100644 index a0e68416f..000000000 --- a/2018/Day04/Solution.cs +++ /dev/null @@ -1,97 +0,0 @@ -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(); -} diff --git a/2018/Day04/input.in b/2018/Day04/input.in deleted file mode 100644 index 3675066b8..000000000 Binary files a/2018/Day04/input.in and /dev/null differ diff --git a/2018/Day04/input.refout b/2018/Day04/input.refout deleted file mode 100644 index 569861772..000000000 --- a/2018/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -60438 -47989 diff --git a/2018/Day05/README.md b/2018/Day05/README.md deleted file mode 100644 index 09a32c2e7..000000000 --- a/2018/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Alchemical Reduction --- -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](https://en.wikipedia.org/wiki/Polymer) (one of which is available as your puzzle input). - -Read the [full puzzle](https://adventofcode.com/2018/day/5). \ No newline at end of file diff --git a/2018/Day05/Solution.cs b/2018/Day05/Solution.cs deleted file mode 100644 index 7d39ca053..000000000 --- a/2018/Day05/Solution.cs +++ /dev/null @@ -1,30 +0,0 @@ -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; - } -} diff --git a/2018/Day05/input.in b/2018/Day05/input.in deleted file mode 100644 index c23e0782e..000000000 Binary files a/2018/Day05/input.in and /dev/null differ diff --git a/2018/Day05/input.refout b/2018/Day05/input.refout deleted file mode 100644 index 43b30d0ec..000000000 --- a/2018/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -10804 -6650 diff --git a/2018/Day06/README.md b/2018/Day06/README.md deleted file mode 100644 index 47db579bb..000000000 --- a/2018/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Chronal Coordinates --- -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](https://adventofcode.com/2018/day/6). \ No newline at end of file diff --git a/2018/Day06/Solution.cs b/2018/Day06/Solution.cs deleted file mode 100644 index 5df21bc09..000000000 --- a/2018/Day06/Solution.cs +++ /dev/null @@ -1,75 +0,0 @@ -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(); -} diff --git a/2018/Day06/input.in b/2018/Day06/input.in deleted file mode 100644 index 54e5710fd..000000000 Binary files a/2018/Day06/input.in and /dev/null differ diff --git a/2018/Day06/input.refout b/2018/Day06/input.refout deleted file mode 100644 index 8b674ebad..000000000 --- a/2018/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3969 -42123 diff --git a/2018/Day07/README.md b/2018/Day07/README.md deleted file mode 100644 index 2dd1cc983..000000000 --- a/2018/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: The Sum of Its Parts --- -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](/2015/day/6). 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](https://adventofcode.com/2018/day/7). \ No newline at end of file diff --git a/2018/Day07/Solution.cs b/2018/Day07/Solution.cs deleted file mode 100644 index ed3ef7c8e..000000000 --- a/2018/Day07/Solution.cs +++ /dev/null @@ -1,101 +0,0 @@ -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; - } -} diff --git a/2018/Day07/input.in b/2018/Day07/input.in deleted file mode 100644 index 414e2d7a2..000000000 Binary files a/2018/Day07/input.in and /dev/null differ diff --git a/2018/Day07/input.refout b/2018/Day07/input.refout deleted file mode 100644 index b390f20a5..000000000 --- a/2018/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -ABGKCMVWYDEHFOPQUILSTNZRJX -898 diff --git a/2018/Day08/README.md b/2018/Day08/README.md deleted file mode 100644 index 8e314227d..000000000 --- a/2018/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Memory Maneuver --- -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](https://adventofcode.com/2018/day/8). \ No newline at end of file diff --git a/2018/Day08/Solution.cs b/2018/Day08/Solution.cs deleted file mode 100644 index 77d9fa112..000000000 --- a/2018/Day08/Solution.cs +++ /dev/null @@ -1,64 +0,0 @@ -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; - } -} diff --git a/2018/Day08/input.in b/2018/Day08/input.in deleted file mode 100644 index 01888be79..000000000 Binary files a/2018/Day08/input.in and /dev/null differ diff --git a/2018/Day08/input.refout b/2018/Day08/input.refout deleted file mode 100644 index 15920ddb9..000000000 --- a/2018/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -43825 -19276 diff --git a/2018/Day09/README.md b/2018/Day09/README.md deleted file mode 100644 index 750be53b5..000000000 --- a/2018/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Marble Mania --- -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](https://en.wikipedia.org/wiki/Marble_(toy)) 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](https://adventofcode.com/2018/day/9). \ No newline at end of file diff --git a/2018/Day09/Solution.cs b/2018/Day09/Solution.cs deleted file mode 100644 index ad54d968b..000000000 --- a/2018/Day09/Solution.cs +++ /dev/null @@ -1,60 +0,0 @@ -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; -} diff --git a/2018/Day09/input.in b/2018/Day09/input.in deleted file mode 100644 index ec6953af2..000000000 Binary files a/2018/Day09/input.in and /dev/null differ diff --git a/2018/Day09/input.refout b/2018/Day09/input.refout deleted file mode 100644 index 72d142c50..000000000 --- a/2018/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -400493 -3338341690 diff --git a/2018/Day10/README.md b/2018/Day10/README.md deleted file mode 100644 index 867a88d43..000000000 --- a/2018/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: The Stars Align --- -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](https://adventofcode.com/2018/day/10). \ No newline at end of file diff --git a/2018/Day10/Solution.cs b/2018/Day10/Solution.cs deleted file mode 100644 index b8694fe46..000000000 --- a/2018/Day10/Solution.cs +++ /dev/null @@ -1,76 +0,0 @@ -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; -} diff --git a/2018/Day10/input.in b/2018/Day10/input.in deleted file mode 100644 index e85ff3932..000000000 Binary files a/2018/Day10/input.in and /dev/null differ diff --git a/2018/Day10/input.refout b/2018/Day10/input.refout deleted file mode 100644 index de505dd72..000000000 --- a/2018/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -ZZCBGGCJ -10886 diff --git a/2018/Day11/README.md b/2018/Day11/README.md deleted file mode 100644 index 8f32d908b..000000000 --- a/2018/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Chronal Charge --- -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](https://adventofcode.com/2018/day/11). \ No newline at end of file diff --git a/2018/Day11/Solution.cs b/2018/Day11/Solution.cs deleted file mode 100644 index ed3750d90..000000000 --- a/2018/Day11/Solution.cs +++ /dev/null @@ -1,72 +0,0 @@ -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); - } - -} diff --git a/2018/Day11/input.in b/2018/Day11/input.in deleted file mode 100644 index 77e59ecee..000000000 Binary files a/2018/Day11/input.in and /dev/null differ diff --git a/2018/Day11/input.refout b/2018/Day11/input.refout deleted file mode 100644 index 673116044..000000000 --- a/2018/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -33,54 -232,289,8 diff --git a/2018/Day12/README.md b/2018/Day12/README.md deleted file mode 100644 index 267227936..000000000 --- a/2018/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Subterranean Sustainability --- -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](https://adventofcode.com/2018/day/12). \ No newline at end of file diff --git a/2018/Day12/Solution.cs b/2018/Day12/Solution.cs deleted file mode 100644 index 5a428cc7c..000000000 --- a/2018/Day12/Solution.cs +++ /dev/null @@ -1,61 +0,0 @@ -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; -} diff --git a/2018/Day12/input.in b/2018/Day12/input.in deleted file mode 100644 index f94e0da77..000000000 Binary files a/2018/Day12/input.in and /dev/null differ diff --git a/2018/Day12/input.refout b/2018/Day12/input.refout deleted file mode 100644 index 3b042617b..000000000 --- a/2018/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3903 -3450000002268 diff --git a/2018/Day13/README.md b/2018/Day13/README.md deleted file mode 100644 index 14747d94f..000000000 --- a/2018/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Mine Cart Madness --- -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](https://adventofcode.com/2018/day/13). \ No newline at end of file diff --git a/2018/Day13/Solution.cs b/2018/Day13/Solution.cs deleted file mode 100644 index b05ae51db..000000000 --- a/2018/Day13/Solution.cs +++ /dev/null @@ -1,119 +0,0 @@ -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); - } -} diff --git a/2018/Day13/input.in b/2018/Day13/input.in deleted file mode 100644 index 921dc501f..000000000 Binary files a/2018/Day13/input.in and /dev/null differ diff --git a/2018/Day13/input.refout b/2018/Day13/input.refout deleted file mode 100644 index 91799b64e..000000000 --- a/2018/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -8,3 -73,121 diff --git a/2018/Day14/README.md b/2018/Day14/README.md deleted file mode 100644 index 69452d3ed..000000000 --- a/2018/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Chocolate Charts --- -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](https://adventofcode.com/2018/day/14). \ No newline at end of file diff --git a/2018/Day14/Solution.cs b/2018/Day14/Solution.cs deleted file mode 100644 index ccd9377b1..000000000 --- a/2018/Day14/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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; - } - } -} diff --git a/2018/Day14/input.in b/2018/Day14/input.in deleted file mode 100644 index 342edb5ac..000000000 Binary files a/2018/Day14/input.in and /dev/null differ diff --git a/2018/Day14/input.refout b/2018/Day14/input.refout deleted file mode 100644 index 1db589e3b..000000000 --- a/2018/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1221283494 -20261485 diff --git a/2018/Day15/README.md b/2018/Day15/README.md deleted file mode 100644 index ffa44ddd5..000000000 --- a/2018/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Beverage Bandits --- -Having perfected their hot chocolate, the Elves have a new problem: the [Goblins](https://en.wikipedia.org/wiki/Goblin) 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](https://adventofcode.com/2018/day/15). \ No newline at end of file diff --git a/2018/Day15/Solution.cs b/2018/Day15/Solution.cs deleted file mode 100644 index 41aa93b9d..000000000 --- a/2018/Day15/Solution.cs +++ /dev/null @@ -1,251 +0,0 @@ -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; - } - -} diff --git a/2018/Day15/input.in b/2018/Day15/input.in deleted file mode 100644 index 0ea43d55c..000000000 Binary files a/2018/Day15/input.in and /dev/null differ diff --git a/2018/Day15/input.refout b/2018/Day15/input.refout deleted file mode 100644 index cc68bcea7..000000000 --- a/2018/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -319410 -63168 \ No newline at end of file diff --git a/2018/Day16/README.md b/2018/Day16/README.md deleted file mode 100644 index 0c41ed9df..000000000 --- a/2018/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Chronal Classification --- -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](https://adventofcode.com/2018/day/16). \ No newline at end of file diff --git a/2018/Day16/Solution.cs b/2018/Day16/Solution.cs deleted file mode 100644 index e268e8d30..000000000 --- a/2018/Day16/Solution.cs +++ /dev/null @@ -1,139 +0,0 @@ -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; -} diff --git a/2018/Day16/input.in b/2018/Day16/input.in deleted file mode 100644 index 75cac132a..000000000 Binary files a/2018/Day16/input.in and /dev/null differ diff --git a/2018/Day16/input.refout b/2018/Day16/input.refout deleted file mode 100644 index ce8897022..000000000 --- a/2018/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -567 -610 diff --git a/2018/Day17/README.md b/2018/Day17/README.md deleted file mode 100644 index 16a5873ac..000000000 --- a/2018/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Reservoir Research --- -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](https://adventofcode.com/2018/day/17). \ No newline at end of file diff --git a/2018/Day17/Solution.cs b/2018/Day17/Solution.cs deleted file mode 100644 index b225a8d30..000000000 --- a/2018/Day17/Solution.cs +++ /dev/null @@ -1,96 +0,0 @@ -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; - } -} diff --git a/2018/Day17/input.in b/2018/Day17/input.in deleted file mode 100644 index 47120cff7..000000000 Binary files a/2018/Day17/input.in and /dev/null differ diff --git a/2018/Day17/input.refout b/2018/Day17/input.refout deleted file mode 100644 index cd2b0b0da..000000000 --- a/2018/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -41027 -34214 diff --git a/2018/Day18/README.md b/2018/Day18/README.md deleted file mode 100644 index 10baaa900..000000000 --- a/2018/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Settlers of The North Pole --- -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](https://adventofcode.com/2018/day/18). \ No newline at end of file diff --git a/2018/Day18/Solution.cs b/2018/Day18/Solution.cs deleted file mode 100644 index 1cf6be00b..000000000 --- a/2018/Day18/Solution.cs +++ /dev/null @@ -1,68 +0,0 @@ -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(); - } -} diff --git a/2018/Day18/input.in b/2018/Day18/input.in deleted file mode 100644 index 5babc989e..000000000 Binary files a/2018/Day18/input.in and /dev/null differ diff --git a/2018/Day18/input.refout b/2018/Day18/input.refout deleted file mode 100644 index b196652ee..000000000 --- a/2018/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -594712 -203138 diff --git a/2018/Day19/README.md b/2018/Day19/README.md deleted file mode 100644 index b2070b233..000000000 --- a/2018/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Go With The Flow --- -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](16) don't contain any *flow control* like jump instructions. The device's [manual](16) goes on to explain: - -Read the [full puzzle](https://adventofcode.com/2018/day/19). \ No newline at end of file diff --git a/2018/Day19/Solution.cs b/2018/Day19/Solution.cs deleted file mode 100644 index ff0696dcb..000000000 --- a/2018/Day19/Solution.cs +++ /dev/null @@ -1,57 +0,0 @@ -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; - } -} diff --git a/2018/Day19/input.in b/2018/Day19/input.in deleted file mode 100644 index 07bc89717..000000000 Binary files a/2018/Day19/input.in and /dev/null differ diff --git a/2018/Day19/input.orig b/2018/Day19/input.orig deleted file mode 100644 index 986151d9b..000000000 --- a/2018/Day19/input.orig +++ /dev/null @@ -1,37 +0,0 @@ -#ip 2 -addi 2 16 2 -seti 1 8 5 -seti 1 0 3 -mulr 5 3 4 -eqrr 4 1 4 -addr 4 2 2 -addi 2 1 2 -addr 5 0 0 -addi 3 1 3 -gtrr 3 1 4 -addr 2 4 2 -seti 2 1 2 -addi 5 1 5 -gtrr 5 1 4 -addr 4 2 2 -seti 1 1 2 -mulr 2 2 2 -addi 1 2 1 -mulr 1 1 1 -mulr 2 1 1 -muli 1 11 1 -addi 4 2 4 -mulr 4 2 4 -addi 4 12 4 -addr 1 4 1 -addr 2 0 2 -seti 0 9 2 -setr 2 3 4 -mulr 4 2 4 -addr 2 4 4 -mulr 2 4 4 -muli 4 14 4 -mulr 4 2 4 -addr 1 4 1 -seti 0 1 0 -seti 0 4 2 \ No newline at end of file diff --git a/2018/Day19/input.refout b/2018/Day19/input.refout deleted file mode 100644 index 1d587a220..000000000 --- a/2018/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1568 -19030032 diff --git a/2018/Day20/README.md b/2018/Day20/README.md deleted file mode 100644 index 195e256fe..000000000 --- a/2018/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: A Regular Map --- -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](https://adventofcode.com/2018/day/20). \ No newline at end of file diff --git a/2018/Day20/Solution.cs b/2018/Day20/Solution.cs deleted file mode 100644 index 221cad07c..000000000 --- a/2018/Day20/Solution.cs +++ /dev/null @@ -1,65 +0,0 @@ -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); - } - } - } -} diff --git a/2018/Day20/input.in b/2018/Day20/input.in deleted file mode 100644 index 84ee2d7a1..000000000 Binary files a/2018/Day20/input.in and /dev/null differ diff --git a/2018/Day20/input.refout b/2018/Day20/input.refout deleted file mode 100644 index 19f571c46..000000000 --- a/2018/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -4186 -8466 diff --git a/2018/Day21/README.md b/2018/Day21/README.md deleted file mode 100644 index f7558e4d8..000000000 --- a/2018/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Chronal Conversion --- -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](https://adventofcode.com/2018/day/21). \ No newline at end of file diff --git a/2018/Day21/Solution.cs b/2018/Day21/Solution.cs deleted file mode 100644 index f7ed345ae..000000000 --- a/2018/Day21/Solution.cs +++ /dev/null @@ -1,65 +0,0 @@ -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() - }; - } -} diff --git a/2018/Day21/input.in b/2018/Day21/input.in deleted file mode 100644 index 157525118..000000000 Binary files a/2018/Day21/input.in and /dev/null differ diff --git a/2018/Day21/input.refout b/2018/Day21/input.refout deleted file mode 100644 index 10dd1ba29..000000000 --- a/2018/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -16311888 -1413889 diff --git a/2018/Day22/README.md b/2018/Day22/README.md deleted file mode 100644 index 37a01eb08..000000000 --- a/2018/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Mode Maze --- -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](https://adventofcode.com/2018/day/22). \ No newline at end of file diff --git a/2018/Day22/Solution.cs b/2018/Day22/Solution.cs deleted file mode 100644 index 4cbd7a6b5..000000000 --- a/2018/Day22/Solution.cs +++ /dev/null @@ -1,155 +0,0 @@ -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; - } -} diff --git a/2018/Day22/input.in b/2018/Day22/input.in deleted file mode 100644 index b30a77446..000000000 Binary files a/2018/Day22/input.in and /dev/null differ diff --git a/2018/Day22/input.refout b/2018/Day22/input.refout deleted file mode 100644 index 3f363443a..000000000 --- a/2018/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -11462 -1054 diff --git a/2018/Day23/README.md b/2018/Day23/README.md deleted file mode 100644 index 9557f08ef..000000000 --- a/2018/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Experimental Emergency Teleportation --- -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](https://adventofcode.com/2018/day/23). \ No newline at end of file diff --git a/2018/Day23/Solution.cs b/2018/Day23/Solution.cs deleted file mode 100644 index cdd5e0fda..000000000 --- a/2018/Day23/Solution.cs +++ /dev/null @@ -1,178 +0,0 @@ -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; - } -} diff --git a/2018/Day23/input.in b/2018/Day23/input.in deleted file mode 100644 index caf7024a6..000000000 Binary files a/2018/Day23/input.in and /dev/null differ diff --git a/2018/Day23/input.refout b/2018/Day23/input.refout deleted file mode 100644 index c19db2c2e..000000000 --- a/2018/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -219 -83779034 diff --git a/2018/Day24/README.md b/2018/Day24/README.md deleted file mode 100644 index 8b9e7ab6f..000000000 --- a/2018/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Immune System Simulator 20XX --- -After [a weird buzzing noise](https://www.youtube.com/watch?v=NDVjLt_QHL8&t=7), 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](https://adventofcode.com/2018/day/24). \ No newline at end of file diff --git a/2018/Day24/Solution.cs b/2018/Day24/Solution.cs deleted file mode 100644 index 8f00a5a55..000000000 --- a/2018/Day24/Solution.cs +++ /dev/null @@ -1,140 +0,0 @@ -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; - } - } -} diff --git a/2018/Day24/input.in b/2018/Day24/input.in deleted file mode 100644 index 211b05595..000000000 Binary files a/2018/Day24/input.in and /dev/null differ diff --git a/2018/Day24/input.refout b/2018/Day24/input.refout deleted file mode 100644 index 346246eb9..000000000 --- a/2018/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -33551 -760 diff --git a/2018/Day25/README.md b/2018/Day25/README.md deleted file mode 100644 index 9d1c5fc54..000000000 --- a/2018/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Four-Dimensional Adventure --- -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](https://adventofcode.com/2018/day/25). \ No newline at end of file diff --git a/2018/Day25/Solution.cs b/2018/Day25/Solution.cs deleted file mode 100644 index dc882125d..000000000 --- a/2018/Day25/Solution.cs +++ /dev/null @@ -1,44 +0,0 @@ -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(); - -} diff --git a/2018/Day25/input.in b/2018/Day25/input.in deleted file mode 100644 index 9f40980a4..000000000 Binary files a/2018/Day25/input.in and /dev/null differ diff --git a/2018/Day25/input.refout b/2018/Day25/input.refout deleted file mode 100644 index fae513888..000000000 --- a/2018/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -381 diff --git a/2018/README.md b/2018/README.md deleted file mode 100644 index 1d7ec08e1..000000000 --- a/2018/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2018) -Check out https://adventofcode.com/2018. - - diff --git a/2018/SplashScreen.cs b/2018/SplashScreen.cs deleted file mode 100644 index 56bcdf187..000000000 --- a/2018/SplashScreen.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; - -namespace AdventOfCode.Y2018; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ 0x0000 | 2018\n "); - Write(0xcc00, false, " \n "); - Write(0xcccccc, false, ". . . . . 25 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". . . . "); - Write(0x886655, false, "\\ / "); - Write(0xcccccc, false, ". 24 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". . "); - Write(0x886655, false, "\\_\\_\\|_/__/ "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". . . "); - Write(0xff0000, true, "o"); - Write(0x886655, false, "-_/"); - Write(0xcccccc, false, ".()"); - Write(0x886655, false, "__------- "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". . "); - Write(0xffff66, true, "* "); - Write(0x886655, false, "\\____ "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". "); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "\\| \\_"); - Write(0x886655, false, "\\_ "); - Write(0xcccccc, false, "___ / 20 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". |"); - Write(0xff0000, false, "\\| "); - Write(0x886655, false, "/ | || "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ". "); - Write(0x66ff, false, "_________"); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "\\|"); - Write(0x66ff, false, "_________ "); - Write(0x886655, false, "/ | || "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x66ff, false, "___----- "); - Write(0xcccccc, false, "########### ##### "); - Write(0x66ff, false, "-----___ "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x66ff, false, "___--- "); - Write(0xcccccc, false, "### ##### ######### ##### "); - Write(0x66ff, false, "---___ "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ") )) ) ) __"); - Write(0xff0000, false, "__ "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, ".-"); - Write(0xcccccc, false, "("); - Write(0xff0000, false, "-"); - Write(0xcccccc, false, "(("); - Write(0xff0000, false, "-. "); - Write(0x9900, false, ".--"); - Write(0xcccccc, false, "("); - Write(0x9900, false, "-"); - Write(0xcccccc, false, "("); - Write(0x9900, false, "-. "); - Write(0xff0000, false, "/ "); - Write(0xcccccc, false, "_"); - Write(0xff0000, false, "\\ "); - Write(0xcccccc, false, "\\ 14 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "'------'_ "); - Write(0x9900, false, "'------'_ "); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "/| |/"); - Write(0xff0000, false, "| "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "| | ) "); - Write(0x9900, false, "| | ) "); - Write(0xcccccc, false, "|_| "); - Write(0xff0000, false, "|/"); - Write(0xcccccc, false, "| 12 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "| |/ "); - Write(0x9900, false, "| |/ "); - Write(0xcccccc, false, "|/"); - Write(0xff0000, false, "| "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "'------' "); - Write(0x9900, false, "'------' "); - Write(0xff0000, false, "|/"); - Write(0xcccccc, false, "| 10 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "_ __ "); - Write(0xcccccc, false, "|/"); - Write(0xff0000, false, "| "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, ".---_ _ "); - Write(0x880000, false, "| "); - Write(0xff0000, false, "|\\__"); - Write(0x880000, false, "/"); - Write(0xff0000, false, "_/) |/"); - Write(0xcccccc, false, "| 8 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "/ "); - Write(0x880000, false, "/ "); - Write(0xff0000, false, "/\\| "); - Write(0x999999, false, "__ "); - Write(0x880000, false, ") "); - Write(0xff0000, false, ")__ "); - Write(0x880000, false, "_|"); - Write(0xff0000, false, "_| / "); - Write(0xcccccc, false, "|/"); - Write(0xff0000, false, "| "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "/ "); - Write(0x880000, false, "/ | "); - Write(0xff0000, false, "\\ "); - Write(0xffff66, true, "* "); - Write(0x999999, false, "/ / \\ "); - Write(0x880000, false, "( "); - Write(0xff0000, false, "( \\_"); - Write(0x880000, false, "/"); - Write(0xff0000, false, "_/ / |/"); - Write(0xcccccc, false, "| 6 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "/ "); - Write(0x880000, false, "/ \\ "); - Write(0xff0000, false, "\\ "); - Write(0x999999, false, "| | \\/ "); - Write(0x880000, false, "\\_"); - Write(0xff0000, false, "\\____________/ "); - Write(0xcccccc, false, "|_| 5 "); - Write(0xffff66, false, "**\n "); - Write(0xff0000, false, "/ "); - Write(0x880000, false, "/ / \\ "); - Write(0xff0000, false, "\\ "); - Write(0x999999, false, "\\_\\______X_____X_____X_, "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "./~~~~~~~~~~~\\. 3 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "( .\",^. -\". '.~ ) 2 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "_'~~~~~~~~~~~~~'_________ ___ __ _ _ _ _ 1 "); - Write(0xffff66, false, "**\n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2018/calendar.svg b/2018/calendar.svg deleted file mode 100644 index 341b34a67..000000000 --- a/2018/calendar.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  0x0000 | 2018 -  -     .         .         .        .        .       25 ** - .        .         .        .       \  /      .   24 ** -              .         .         \_\_\|_/__/      23 ** -       .         .            .  o-_/.()__-------  22 ** -   .       .            *         \____            21 ** -               .       |\|            \_\_ ___  /  20 ** -       .               |\|              / |   ||   19 ** -  .           _________|\|_________    /  |   ||   18 ** -      ___-----  ###########  ##### -----___        17 ** -___---  ###  #####    #########  #####     ---___  16 ** -      ) ))          ) )                    ____    15 ** -   .-(-((-.     .--(-(-.                  / _\ \   14 ** -   '------'_    '------'_                |/|  |/|  13 ** -   |      | )   |      | )               |_|  |/|  12 ** -   |      |/    |      |/                     |/|  11 ** -   '------'     '------'                      |/|  10 ** -                                   _     __   |/|   9 ** -        .---_             _       | |\__/_/)  |/|   8 ** -       / / /\|      __   ) )__   _|_|     /   |/|   7 ** -     / / | \ *    / / \ ( (   \_/_/      /    |/|   6 ** -    /  /  \ \    | | \/  \_\____________/     |_|   5 ** -   / /  / \  \    \_\______X_____X_____X_,          4 ** - ./~~~~~~~~~~~\.                                    3 ** -( .",^. -". '.~ )                                   2 ** -_'~~~~~~~~~~~~~'_________ ___ __ _  _   _    _      1 ** - - - - \ No newline at end of file diff --git a/2019/Day01/README.md b/2019/Day01/README.md deleted file mode 100644 index 0cca1558b..000000000 --- a/2019/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: The Tyranny of the Rocket Equation --- -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! - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2019/day/1) description._ diff --git a/2019/Day01/Solution.cs b/2019/Day01/Solution.cs deleted file mode 100644 index 9a68bfd44..000000000 --- a/2019/Day01/Solution.cs +++ /dev/null @@ -1,28 +0,0 @@ -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; - } -} diff --git a/2019/Day01/input.in b/2019/Day01/input.in deleted file mode 100644 index 2db97c2a8..000000000 Binary files a/2019/Day01/input.in and /dev/null differ diff --git a/2019/Day01/input.refout b/2019/Day01/input.refout deleted file mode 100644 index 5a56d38f4..000000000 --- a/2019/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3465154 -5194864 \ No newline at end of file diff --git a/2019/Day02/README.md b/2019/Day02/README.md deleted file mode 100644 index d7c41c9ef..000000000 --- a/2019/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: 1202 Program Alarm --- -On the way to your [gravity assist](https://en.wikipedia.org/wiki/Gravity_assist) around the Moon, your ship computer beeps angrily about a "[1202 program alarm](https://www.hq.nasa.gov/alsj/a11/a11.landing.html#1023832)". 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](https://en.wikipedia.org/wiki/Halt_and_Catch_Fire). - -You notify the Elves that the computer's [magic smoke](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2019/day/2). \ No newline at end of file diff --git a/2019/Day02/Solution.cs b/2019/Day02/Solution.cs deleted file mode 100644 index 0cae0cb68..000000000 --- a/2019/Day02/Solution.cs +++ /dev/null @@ -1,32 +0,0 @@ -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]; - } -} diff --git a/2019/Day02/input.in b/2019/Day02/input.in deleted file mode 100644 index 3cff00467..000000000 Binary files a/2019/Day02/input.in and /dev/null differ diff --git a/2019/Day02/input.refout b/2019/Day02/input.refout deleted file mode 100644 index b5d16152e..000000000 --- a/2019/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3850704 -6718 diff --git a/2019/Day03/README.md b/2019/Day03/README.md deleted file mode 100644 index a2d766739..000000000 --- a/2019/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Crossed Wires --- -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](https://adventofcode.com/2019/day/3). \ No newline at end of file diff --git a/2019/Day03/Solution.cs b/2019/Day03/Solution.cs deleted file mode 100644 index 86942e933..000000000 --- a/2019/Day03/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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; - } -} diff --git a/2019/Day03/input.in b/2019/Day03/input.in deleted file mode 100644 index e840a410a..000000000 Binary files a/2019/Day03/input.in and /dev/null differ diff --git a/2019/Day03/input.refout b/2019/Day03/input.refout deleted file mode 100644 index a89ad14a2..000000000 --- a/2019/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1519 -14358 diff --git a/2019/Day04/README.md b/2019/Day04/README.md deleted file mode 100644 index 1145b177d..000000000 --- a/2019/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Secure Container --- -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](https://adventofcode.com/2019/day/4). \ No newline at end of file diff --git a/2019/Day04/Solution.cs b/2019/Day04/Solution.cs deleted file mode 100644 index d32906c8c..000000000 --- a/2019/Day04/Solution.cs +++ /dev/null @@ -1,43 +0,0 @@ -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; - } - } -} diff --git a/2019/Day04/input.in b/2019/Day04/input.in deleted file mode 100644 index 079b7dd74..000000000 Binary files a/2019/Day04/input.in and /dev/null differ diff --git a/2019/Day04/input.refout b/2019/Day04/input.refout deleted file mode 100644 index 20393657f..000000000 --- a/2019/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -910 -598 diff --git a/2019/Day05/README.md b/2019/Day05/README.md deleted file mode 100644 index b3908d680..000000000 --- a/2019/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Sunny with a Chance of Asteroids --- -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](2) after a few modifications: - -Read the [full puzzle](https://adventofcode.com/2019/day/5). \ No newline at end of file diff --git a/2019/Day05/Solution.cs b/2019/Day05/Solution.cs deleted file mode 100644 index a1ef9d7bb..000000000 --- a/2019/Day05/Solution.cs +++ /dev/null @@ -1,12 +0,0 @@ -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(); - -} diff --git a/2019/Day05/input.in b/2019/Day05/input.in deleted file mode 100644 index 0d4db2def..000000000 Binary files a/2019/Day05/input.in and /dev/null differ diff --git a/2019/Day05/input.refout b/2019/Day05/input.refout deleted file mode 100644 index 813b792fa..000000000 --- a/2019/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -13294380 -11460760 diff --git a/2019/Day06/README.md b/2019/Day06/README.md deleted file mode 100644 index 44651a79a..000000000 --- a/2019/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Universal Orbit Map --- -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](https://en.wikipedia.org/wiki/Orbit) looks roughly like this: - -Read the [full puzzle](https://adventofcode.com/2019/day/6). \ No newline at end of file diff --git a/2019/Day06/Solution.cs b/2019/Day06/Solution.cs deleted file mode 100644 index 581199813..000000000 --- a/2019/Day06/Solution.cs +++ /dev/null @@ -1,48 +0,0 @@ -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; - } - - } -} diff --git a/2019/Day06/input.in b/2019/Day06/input.in deleted file mode 100644 index f2e87ab51..000000000 Binary files a/2019/Day06/input.in and /dev/null differ diff --git a/2019/Day06/input.refout b/2019/Day06/input.refout deleted file mode 100644 index bbdadbd31..000000000 --- a/2019/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -147807 -229 diff --git a/2019/Day07/README.md b/2019/Day07/README.md deleted file mode 100644 index d25f07a2a..000000000 --- a/2019/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: Amplification Circuit --- -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](https://en.wikipedia.org/wiki/Amplifier) 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](https://adventofcode.com/2019/day/7). \ No newline at end of file diff --git a/2019/Day07/Solution.cs b/2019/Day07/Solution.cs deleted file mode 100644 index d2454634a..000000000 --- a/2019/Day07/Solution.cs +++ /dev/null @@ -1,63 +0,0 @@ -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); - } -} diff --git a/2019/Day07/input.in b/2019/Day07/input.in deleted file mode 100644 index 85edf7132..000000000 Binary files a/2019/Day07/input.in and /dev/null differ diff --git a/2019/Day07/input.refout b/2019/Day07/input.refout deleted file mode 100644 index 7f3e0e4d4..000000000 --- a/2019/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -262086 -5371621 diff --git a/2019/Day08/README.md b/2019/Day08/README.md deleted file mode 100644 index 50bec7cf7..000000000 --- a/2019/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Space Image Format --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2019/day/8). \ No newline at end of file diff --git a/2019/Day08/Solution.cs b/2019/Day08/Solution.cs deleted file mode 100644 index a982c96e9..000000000 --- a/2019/Day08/Solution.cs +++ /dev/null @@ -1,44 +0,0 @@ -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(); -} diff --git a/2019/Day08/input.in b/2019/Day08/input.in deleted file mode 100644 index 546534d70..000000000 Binary files a/2019/Day08/input.in and /dev/null differ diff --git a/2019/Day08/input.refout b/2019/Day08/input.refout deleted file mode 100644 index 2aaf4ceb8..000000000 --- a/2019/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1620 -BCYEF diff --git a/2019/Day09/README.md b/2019/Day09/README.md deleted file mode 100644 index e063ad056..000000000 --- a/2019/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Sensor Boost --- -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](https://adventofcode.com/2019/day/9). \ No newline at end of file diff --git a/2019/Day09/Solution.cs b/2019/Day09/Solution.cs deleted file mode 100644 index 512a66f72..000000000 --- a/2019/Day09/Solution.cs +++ /dev/null @@ -1,10 +0,0 @@ -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(); -} diff --git a/2019/Day09/input.in b/2019/Day09/input.in deleted file mode 100644 index 53b584655..000000000 Binary files a/2019/Day09/input.in and /dev/null differ diff --git a/2019/Day09/input.refout b/2019/Day09/input.refout deleted file mode 100644 index 2ac7a16ec..000000000 --- a/2019/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3454977209 -50120 diff --git a/2019/Day10/README.md b/2019/Day10/README.md deleted file mode 100644 index 049647f0e..000000000 --- a/2019/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Monitoring Station --- -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](https://adventofcode.com/2019/day/10). \ No newline at end of file diff --git a/2019/Day10/Solution.cs b/2019/Day10/Solution.cs deleted file mode 100644 index 7466e0e9e..000000000 --- a/2019/Day10/Solution.cs +++ /dev/null @@ -1,90 +0,0 @@ -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); -} diff --git a/2019/Day10/input.in b/2019/Day10/input.in deleted file mode 100644 index 546434ef7..000000000 Binary files a/2019/Day10/input.in and /dev/null differ diff --git a/2019/Day10/input.refout b/2019/Day10/input.refout deleted file mode 100644 index 56ad1f634..000000000 --- a/2019/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -269 -612 diff --git a/2019/Day11/README.md b/2019/Day11/README.md deleted file mode 100644 index b9a2b021d..000000000 --- a/2019/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Space Police --- -On the way to Jupiter, you're [pulled over](https://www.youtube.com/watch?v=KwY28rpyKDE) 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](https://www.youtube.com/watch?v=BVn1oQL9sWg&t=5)!" - -Read the [full puzzle](https://adventofcode.com/2019/day/11). \ No newline at end of file diff --git a/2019/Day11/Solution.cs b/2019/Day11/Solution.cs deleted file mode 100644 index 87690b1dd..000000000 --- a/2019/Day11/Solution.cs +++ /dev/null @@ -1,53 +0,0 @@ -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); - } - } - - -} diff --git a/2019/Day11/input.in b/2019/Day11/input.in deleted file mode 100644 index bffe73d76..000000000 Binary files a/2019/Day11/input.in and /dev/null differ diff --git a/2019/Day11/input.refout b/2019/Day11/input.refout deleted file mode 100644 index 0c8e20614..000000000 --- a/2019/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1785 -HJALJZFH diff --git a/2019/Day12/README.md b/2019/Day12/README.md deleted file mode 100644 index 28ab5b8a6..000000000 --- a/2019/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: The N-Body Problem --- -The space near Jupiter is not a very safe place; you need to be careful of a [big distracting red spot](https://en.wikipedia.org/wiki/Great_Red_Spot), extreme [radiation](https://en.wikipedia.org/wiki/Magnetosphere_of_Jupiter), and a [whole lot of moons](https://en.wikipedia.org/wiki/Moons_of_Jupiter#List) 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](https://adventofcode.com/2019/day/12). \ No newline at end of file diff --git a/2019/Day12/Solution.cs b/2019/Day12/Solution.cs deleted file mode 100644 index 8466500f3..000000000 --- a/2019/Day12/Solution.cs +++ /dev/null @@ -1,66 +0,0 @@ -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; - } - } -} diff --git a/2019/Day12/input.in b/2019/Day12/input.in deleted file mode 100644 index 0e1994f1a..000000000 Binary files a/2019/Day12/input.in and /dev/null differ diff --git a/2019/Day12/input.refout b/2019/Day12/input.refout deleted file mode 100644 index add4bb6d5..000000000 --- a/2019/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5517 -303070460651184 diff --git a/2019/Day13/README.md b/2019/Day13/README.md deleted file mode 100644 index dfb52a5c1..000000000 --- a/2019/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Care Package --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2019/day/13). \ No newline at end of file diff --git a/2019/Day13/Solution.cs b/2019/Day13/Solution.cs deleted file mode 100644 index fd7dc2c81..000000000 --- a/2019/Day13/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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(); - } -} diff --git a/2019/Day13/input.in b/2019/Day13/input.in deleted file mode 100644 index 157e70a9d..000000000 Binary files a/2019/Day13/input.in and /dev/null differ diff --git a/2019/Day13/input.refout b/2019/Day13/input.refout deleted file mode 100644 index 71679c029..000000000 --- a/2019/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -363 -17159 diff --git a/2019/Day14/README.md b/2019/Day14/README.md deleted file mode 100644 index 49e4fe406..000000000 --- a/2019/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Space Stoichiometry --- -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](https://adventofcode.com/2019/day/14). \ No newline at end of file diff --git a/2019/Day14/Solution.cs b/2019/Day14/Solution.cs deleted file mode 100644 index d6585263c..000000000 --- a/2019/Day14/Solution.cs +++ /dev/null @@ -1,77 +0,0 @@ -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; - }; - } -} diff --git a/2019/Day14/input.in b/2019/Day14/input.in deleted file mode 100644 index 929a13c2c..000000000 Binary files a/2019/Day14/input.in and /dev/null differ diff --git a/2019/Day14/input.refout b/2019/Day14/input.refout deleted file mode 100644 index 05d75e2eb..000000000 --- a/2019/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -892207 -1935265 diff --git a/2019/Day15/README.md b/2019/Day15/README.md deleted file mode 100644 index 0f0aa0e4e..000000000 --- a/2019/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Oxygen System --- -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](https://adventofcode.com/2019/day/15). \ No newline at end of file diff --git a/2019/Day15/Solution.cs b/2019/Day15/Solution.cs deleted file mode 100644 index 10fc69062..000000000 --- a/2019/Day15/Solution.cs +++ /dev/null @@ -1,53 +0,0 @@ -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)); - } - } - } - } - } -} diff --git a/2019/Day15/input.in b/2019/Day15/input.in deleted file mode 100644 index 62aa67426..000000000 Binary files a/2019/Day15/input.in and /dev/null differ diff --git a/2019/Day15/input.refout b/2019/Day15/input.refout deleted file mode 100644 index bef97500d..000000000 --- a/2019/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -258 -372 \ No newline at end of file diff --git a/2019/Day16/README.md b/2019/Day16/README.md deleted file mode 100644 index 719505721..000000000 --- a/2019/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Flawed Frequency Transmission --- -You're 3/4ths of the way through the [gas giants](https://en.wikipedia.org/wiki/Gas_giant). 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](https://adventofcode.com/2019/day/16). \ No newline at end of file diff --git a/2019/Day16/Solution.cs b/2019/Day16/Solution.cs deleted file mode 100644 index 9fd68ea3a..000000000 --- a/2019/Day16/Solution.cs +++ /dev/null @@ -1,146 +0,0 @@ -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; - } - -} diff --git a/2019/Day16/input.in b/2019/Day16/input.in deleted file mode 100644 index 745b563e4..000000000 Binary files a/2019/Day16/input.in and /dev/null differ diff --git a/2019/Day16/input.refout b/2019/Day16/input.refout deleted file mode 100644 index ce012da97..000000000 --- a/2019/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -76795888 -84024125 diff --git a/2019/Day17/README.md b/2019/Day17/README.md deleted file mode 100644 index 4bd898a5d..000000000 --- a/2019/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Set and Forget --- -An early warning system detects an incoming [solar flare](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2019/day/17). \ No newline at end of file diff --git a/2019/Day17/Solution.cs b/2019/Day17/Solution.cs deleted file mode 100644 index 07dd75fb3..000000000 --- a/2019/Day17/Solution.cs +++ /dev/null @@ -1,160 +0,0 @@ -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(); -} diff --git a/2019/Day17/input.in b/2019/Day17/input.in deleted file mode 100644 index b98176f73..000000000 Binary files a/2019/Day17/input.in and /dev/null differ diff --git a/2019/Day17/input.refout b/2019/Day17/input.refout deleted file mode 100644 index 9927dccba..000000000 --- a/2019/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -8520 -926819 diff --git a/2019/Day18/README.md b/2019/Day18/README.md deleted file mode 100644 index 21878042c..000000000 --- a/2019/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Many-Worlds Interpretation --- -As you approach Neptune, a planetary security system detects you and activates a giant [tractor beam](https://en.wikipedia.org/wiki/Tractor_beam) on [Triton](https://en.wikipedia.org/wiki/Triton_(moon))! 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](https://adventofcode.com/2019/day/18). \ No newline at end of file diff --git a/2019/Day18/Solution.cs b/2019/Day18/Solution.cs deleted file mode 100644 index 3396fd994..000000000 --- a/2019/Day18/Solution.cs +++ /dev/null @@ -1,204 +0,0 @@ -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; - } -} diff --git a/2019/Day18/input.in b/2019/Day18/input.in deleted file mode 100644 index d736bce82..000000000 Binary files a/2019/Day18/input.in and /dev/null differ diff --git a/2019/Day18/input.refout b/2019/Day18/input.refout deleted file mode 100644 index a28dab88a..000000000 --- a/2019/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -7430 -1864 diff --git a/2019/Day19/README.md b/2019/Day19/README.md deleted file mode 100644 index a0a240e7a..000000000 --- a/2019/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Tractor Beam --- -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](9) program (your puzzle input) that gives you access to the drone system. - -Read the [full puzzle](https://adventofcode.com/2019/day/19). \ No newline at end of file diff --git a/2019/Day19/Solution.cs b/2019/Day19/Solution.cs deleted file mode 100644 index 54a729596..000000000 --- a/2019/Day19/Solution.cs +++ /dev/null @@ -1,45 +0,0 @@ -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++; - } - - } -} diff --git a/2019/Day19/input.in b/2019/Day19/input.in deleted file mode 100644 index bca68256b..000000000 Binary files a/2019/Day19/input.in and /dev/null differ diff --git a/2019/Day19/input.refout b/2019/Day19/input.refout deleted file mode 100644 index 70f0a3f56..000000000 --- a/2019/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -141 -15641348 diff --git a/2019/Day20/README.md b/2019/Day20/README.md deleted file mode 100644 index 3fe880d51..000000000 --- a/2019/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Donut Maze --- -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](https://adventofcode.com/2019/day/20). \ No newline at end of file diff --git a/2019/Day20/Solution.cs b/2019/Day20/Solution.cs deleted file mode 100644 index 4078545fc..000000000 --- a/2019/Day20/Solution.cs +++ /dev/null @@ -1,102 +0,0 @@ -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)); - } -} diff --git a/2019/Day20/input.in b/2019/Day20/input.in deleted file mode 100644 index 3ad350028..000000000 Binary files a/2019/Day20/input.in and /dev/null differ diff --git a/2019/Day20/input.refout b/2019/Day20/input.refout deleted file mode 100644 index ba3380b8f..000000000 --- a/2019/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -606 -7186 diff --git a/2019/Day21/README.md b/2019/Day21/README.md deleted file mode 100644 index 48998e112..000000000 --- a/2019/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Springdroid Adventure --- -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](https://adventofcode.com/2019/day/21). \ No newline at end of file diff --git a/2019/Day21/Solution.cs b/2019/Day21/Solution.cs deleted file mode 100644 index f293ab4a1..000000000 --- a/2019/Day21/Solution.cs +++ /dev/null @@ -1,39 +0,0 @@ -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(); - } -} diff --git a/2019/Day21/input.in b/2019/Day21/input.in deleted file mode 100644 index e71d327cc..000000000 Binary files a/2019/Day21/input.in and /dev/null differ diff --git a/2019/Day21/input.refout b/2019/Day21/input.refout deleted file mode 100644 index 09bc57f85..000000000 --- a/2019/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -19352864 -1142488337 diff --git a/2019/Day22/README.md b/2019/Day22/README.md deleted file mode 100644 index f72411e68..000000000 --- a/2019/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Slam Shuffle --- -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](https://en.wikipedia.org/wiki/Shuffling) 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](https://adventofcode.com/2019/day/22). \ No newline at end of file diff --git a/2019/Day22/Solution.cs b/2019/Day22/Solution.cs deleted file mode 100644 index 8f4919550..000000000 --- a/2019/Day22/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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); - } -} diff --git a/2019/Day22/input.in b/2019/Day22/input.in deleted file mode 100644 index 0eab6218e..000000000 Binary files a/2019/Day22/input.in and /dev/null differ diff --git a/2019/Day22/input.refout b/2019/Day22/input.refout deleted file mode 100644 index 63c62e8f4..000000000 --- a/2019/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2306 -12545532223512 diff --git a/2019/Day23/README.md b/2019/Day23/README.md deleted file mode 100644 index eeb65d376..000000000 --- a/2019/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Category Six --- -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](https://en.wikipedia.org/wiki/Category_6_cable) 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](https://adventofcode.com/2019/day/23). \ No newline at end of file diff --git a/2019/Day23/Solution.cs b/2019/Day23/Solution.cs deleted file mode 100644 index 21fc3a764..000000000 --- a/2019/Day23/Solution.cs +++ /dev/null @@ -1,85 +0,0 @@ -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; - }; - } -} diff --git a/2019/Day23/input.in b/2019/Day23/input.in deleted file mode 100644 index 088494653..000000000 Binary files a/2019/Day23/input.in and /dev/null differ diff --git a/2019/Day23/input.refout b/2019/Day23/input.refout deleted file mode 100644 index 5b3578f4b..000000000 --- a/2019/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -18604 -11880 diff --git a/2019/Day24/README.md b/2019/Day24/README.md deleted file mode 100644 index 0571ab9cb..000000000 --- a/2019/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Planet of Discord --- -You land on [Eris](https://en.wikipedia.org/wiki/Eris_(dwarf_planet)), 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](https://www.nationalgeographic.org/thisday/sep9/worlds-first-computer-bug/)! 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](https://adventofcode.com/2019/day/24). \ No newline at end of file diff --git a/2019/Day24/Solution.cs b/2019/Day24/Solution.cs deleted file mode 100644 index a4da89e79..000000000 --- a/2019/Day24/Solution.cs +++ /dev/null @@ -1,148 +0,0 @@ -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); - } - } - } - } -} diff --git a/2019/Day24/input.in b/2019/Day24/input.in deleted file mode 100644 index ce82b25d5..000000000 Binary files a/2019/Day24/input.in and /dev/null differ diff --git a/2019/Day24/input.refout b/2019/Day24/input.refout deleted file mode 100644 index bfe93534c..000000000 --- a/2019/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -12129040 -2109 diff --git a/2019/Day25/README.md b/2019/Day25/README.md deleted file mode 100644 index 09c087c2b..000000000 --- a/2019/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Cryostasis --- -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](https://adventofcode.com/2019/day/25). \ No newline at end of file diff --git a/2019/Day25/Solution.cs b/2019/Day25/Solution.cs deleted file mode 100644 index 1f9a089e2..000000000 --- a/2019/Day25/Solution.cs +++ /dev/null @@ -1,102 +0,0 @@ -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); -} diff --git a/2019/Day25/input.in b/2019/Day25/input.in deleted file mode 100644 index 379c826d2..000000000 Binary files a/2019/Day25/input.in and /dev/null differ diff --git a/2019/Day25/input.refout b/2019/Day25/input.refout deleted file mode 100644 index e60a15efe..000000000 --- a/2019/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -201327120 diff --git a/2019/IntCode/IntCodeMachine.cs b/2019/IntCode/IntCodeMachine.cs deleted file mode 100644 index 8cd590cc1..000000000 --- a/2019/IntCode/IntCodeMachine.cs +++ /dev/null @@ -1,400 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace AdventOfCode.Y2019; - -enum Mode { - Positional = 0, - Immediate = 1, - Relative = 2 -} - -enum Opcode { - Add = 1, - Mul = 2, - In = 3, - Out = 4, - Jnz = 5, - Jz = 6, - Lt = 7, - Eq = 8, - StR = 9, - Hlt = 99, -} - -class Memory { - public long[] initial; - Dictionary mem = new Dictionary(); - - public Memory(long[] initial) { - this.initial = initial; - } - - private Memory(long[] initial, Dictionary mem) { - this.initial = initial; - this.mem = mem; - } - - public long this[long addr] { - get { - return mem.ContainsKey(addr) ? mem[addr] : addr >= 0 && addr < initial.Length ? initial[addr] : 0; - } - set { - mem[addr] = value; - } - } - - public long Length { - get { - return Math.Max(this.initial.Length, this.mem.Keys.Any() ? this.mem.Keys.Max() : 0); - } - } - - public Memory Clone() { - return new Memory(initial, new Dictionary(mem)); - } - - public void Reset() { - mem.Clear(); - } -} - - -class ImmutableIntCodeMachine { - IntCodeMachine icm; - public ImmutableIntCodeMachine(string stPrg) : this(new IntCodeMachine(stPrg)) { - } - - private ImmutableIntCodeMachine(IntCodeMachine icm) { - this.icm = icm; - } - - public (ImmutableIntCodeMachine iicm, IntCodeOutput output) Run(params long[] input) { - var immutableIntCodeMachine = new ImmutableIntCodeMachine(this.icm.Clone()); - return (immutableIntCodeMachine, immutableIntCodeMachine.icm.Run(input)); - } - - public (ImmutableIntCodeMachine iicm, IntCodeOutput output) Run(params string[] input) { - var immutableIntCodeMachine = new ImmutableIntCodeMachine(this.icm.Clone()); - return (immutableIntCodeMachine, immutableIntCodeMachine.icm.Run(input)); - } - - public bool Halted() => this.icm.Halted(); -} - -class IntCodeOutput : IReadOnlyList { - long[] output; - - public IntCodeOutput(long[] output){ - this.output = output; - } - - public string ToAscii() => string.Join("", from item in output select (char)item); - - public long this[int index] => this.output[index]; - - public int Count => this.output.Length; - - public IEnumerator GetEnumerator() => (this.output as IEnumerable).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => this.output.GetEnumerator(); -} - -class IntCodeMachine { - - private static int[] modeMask = new int[] { 0, 100, 1000, 10000 }; - - public Memory memory; - public long ip; - public long bp; - public Queue input; - - public IntCodeMachine(string stPrg) : - this(new Memory(stPrg.Split(",").Select(long.Parse).ToArray()), - 0, - 0, - new Queue() - ) { - } - - private IntCodeMachine(Memory memory, long ip, long bp, Queue input) { - this.memory = memory; - this.ip = ip; - this.bp = bp; - this.input = input; - } - - public void Reset() { - memory.Reset(); - ip = 0; - bp = 0; - input.Clear(); - } - - public IntCodeMachine Clone() { - return new IntCodeMachine(memory.Clone(), ip, bp, new Queue(input)); - } - - public bool Halted() => GetOpcode(ip) == Opcode.Hlt; - - private Mode GetMode(long addr, int i) => (Mode)(memory[addr] / modeMask[i] % 10); - private Opcode GetOpcode(long addr) => (Opcode)(memory[addr] % 100); - - public void RunInteractive() { - var input = new long[0]; - while (true) { - var output = Run(input); - var c = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Green; - Console.Write(output.ToAscii()); - Console.ForegroundColor = c; - if (this.Halted()) { - break; - } - input = AsciiEncode(Console.ReadLine() + "\n"); - } - } - - - private long[] AsciiEncode(string st) { - return (from ch in st select (long)ch).ToArray(); - } - - bool Match(string stm, string pattern, out int[] m) { - var match = Regex.Match(stm, pattern); - m = null; - if (match.Success) { - m = match.Groups.Cast().Skip(1).Select(g => int.Parse(g.Value)).ToArray(); - return true; - } else { - return false; - } - } - - public IntCodeOutput Run() { - return Run(new long[0]); - } - - public IntCodeOutput Run(params string[] input) { - return Run(AsciiEncode(string.Join("", from line in input select line + "\n"))); - } - - public IntCodeOutput Run(params long[] input) { - - foreach (var i in input) { - this.input.Enqueue(i); - } - var output = new List(); - while (true) { - var opcode = GetOpcode(ip); - var oldIp = ip; - - long addr(int i) { - return GetMode(oldIp, i) switch - { - Mode.Positional => memory[oldIp + i], - Mode.Immediate => oldIp + i, - Mode.Relative => bp + memory[oldIp + i], - _ => throw new ArgumentException() - }; - } - - long arg(int i) => memory[addr(i)]; - switch (opcode) { - case Opcode.Add: memory[addr(3)] = arg(1) + arg(2); ip += 4; break; - case Opcode.Mul: memory[addr(3)] = arg(1) * arg(2); ip += 4; break; - case Opcode.In: { - if (this.input.Any()) { - memory[addr(1)] = this.input.Dequeue(); ip += 2; - } - break; - } - case Opcode.Out: output.Add(arg(1)); ip += 2; break; - case Opcode.Jnz: ip = arg(1) != 0 ? arg(2) : ip + 3; break; - case Opcode.Jz: ip = arg(1) == 0 ? arg(2) : ip + 3; break; - case Opcode.Lt: memory[addr(3)] = arg(1) < arg(2) ? 1 : 0; ip += 4; break; - case Opcode.Eq: memory[addr(3)] = arg(1) == arg(2) ? 1 : 0; ip += 4; break; - case Opcode.StR: bp += arg(1); ip += 2; break; - case Opcode.Hlt: break; - default: throw new ArgumentException("invalid opcode " + opcode); - } - - if (ip == oldIp) { - break; - } - } - - return new IntCodeOutput(output.ToArray()); - } - - public string Decompile(string st) { - var inLines = st.Split("\n").ToList(); - var outLines = new List(); - - // function start - for (var iline = 0; iline < inLines.Count; iline++) { - string line(int i) { - return iline + i >= 0 ? inLines[iline + i] : ""; - } - - if (Regex.Match(line(0), @"bp \+= \d+;").Success) { - outLines.Add("fn_" + line(0).Split(" ")[0] + ":"); - } - outLines.Add(line(0)); - } - - inLines = outLines.ToList(); - outLines.Clear(); - - // return from function - for (var iline = 0; iline < inLines.Count; iline++) { - string line(int i) { - return iline + i >= 0 ? inLines[iline + i] : ""; - } - outLines.Add(line(0)); - - if (Regex.Match(line(-1), @"bp -= \d+;").Success && Regex.Match(line(0), @"goto mem\[bp\]").Success) { - outLines.Add("return;"); - } - } - - return string.Join("\n", outLines); - } - - public string Disass(bool trace = false, int count = int.MaxValue, long ip = -1) { - if (ip == -1) { - ip = this.ip; - } - var sb = new StringBuilder(); - - string addr(int i) { - return GetMode(ip, i) switch - { - Mode.Positional => $"mem[{memory[ip + i]}]", - Mode.Immediate => $"{memory[ip + i]}", - Mode.Relative => - memory[ip + i] > 0 ? $"mem[bp + {memory[ip + i]}]" : - memory[ip + i] == 0 ? $"mem[bp]" : - memory[ip + i] < 0 ? $"mem[bp - {-memory[ip + i]}]" : - throw new ArgumentException(), - _ => throw new ArgumentException() - }; - } - - string arg(int i) { - var st = addr(i); - if (trace) { - var val = GetMode(ip, i) switch - { - Mode.Positional => memory[memory[ip + i]], - Mode.Immediate => memory[ip + i], - Mode.Relative => memory[bp + memory[ip + i]], - _ => throw new ArgumentException() - }; - - st += $" ({format(val)})"; - } - return st; - }; - - string format(long v) { - var st = v.ToString(); - if (v >= 32 && v < 128) { - st += $" '{(char)(v)}'"; - } - return st; - } - int a1, a2; - - for (var i = 0; i < count && ip < memory.Length; i++) { - try { - sb.Append(ip.ToString("0000 ")); - switch (GetOpcode(ip)) { - case Opcode.Add: { - if (int.TryParse(arg(1), out a1) && int.TryParse(arg(2), out a2)) { - sb.AppendLine($"{addr(3)} = {a1 + a2};"); - } else if (int.TryParse(arg(1), out a1) && a1 == 0) { - sb.AppendLine($"{addr(3)} = {arg(2)};"); - } else if (int.TryParse(arg(2), out a2) && a2 == 0) { - sb.AppendLine($"{addr(3)} = {arg(2)};"); - } else if (int.TryParse(arg(2), out a2) && a2 < 0) { - sb.AppendLine($"{addr(3)} = {arg(1)} - {-a2};"); - } else { - sb.AppendLine($"{addr(3)} = {arg(1)} + {arg(2)};"); - } - ip += 4; - break; - } - case Opcode.Mul: { - if (int.TryParse(arg(1), out a1) && int.TryParse(arg(2), out a2)) { - sb.AppendLine($"{addr(3)} = {a1 * a2};"); - } else if (int.TryParse(arg(1), out a1) && a1 == 0) { - sb.AppendLine($"{addr(3)} = 0;"); - } else if (int.TryParse(arg(1), out a1) && a1 == 1) { - sb.AppendLine($"{addr(3)} = {arg(2)};"); - } else if (int.TryParse(arg(2), out a2) && a2 == 0) { - sb.AppendLine($"{addr(3)} = 0;"); - } else if (int.TryParse(arg(2), out a2) && a2 == 1) { - sb.AppendLine($"{addr(3)} = {arg(1)};"); - } else { - sb.AppendLine($"{addr(3)} = {arg(1)} * {arg(2)};"); - } - ip += 4; - break; - } - case Opcode.In: sb.AppendLine($"{addr(1)} = input;"); ip += 2; break; - case Opcode.Out: { - sb.AppendLine($"output {arg(1)};"); ip += 2; break; - } - case Opcode.Jnz: { - if (int.TryParse(arg(1), out a1) && a1 != 0) { - sb.AppendLine($"goto {arg(2)};"); - } else if (int.TryParse(arg(1), out a1) && a1 == 0) { - sb.AppendLine($";"); - } else { - sb.AppendLine($"if ({arg(1)}) goto {arg(2)};"); - - } - ip += 3; - break; - } - case Opcode.Jz: { - if (int.TryParse(arg(1), out a1) && a1 == 0) { - sb.AppendLine($"goto {arg(2)};"); - } else if (int.TryParse(arg(1), out a1) && a1 != 0) { - sb.AppendLine($";"); - } else { - sb.AppendLine($"if (!{arg(1)}) goto {arg(2)};"); - } - ip += 3; - break; - } - case Opcode.Lt: sb.AppendLine($"{addr(3)} = {arg(1)} < {arg(2)};"); ip += 4; break; - case Opcode.Eq: sb.AppendLine($"{addr(3)} = {arg(1)} == {arg(2)};"); ip += 4; break; - case Opcode.StR: { - if (int.TryParse(arg(1), out a1) && a1 < 0) { - sb.AppendLine($"bp -= {-a1};"); - } else { - sb.AppendLine($"bp += {arg(1)};"); - } - ip += 2; break; - } - case Opcode.Hlt: sb.AppendLine($"halt;"); ip += 1; break; - default: { - sb.AppendLine(format(memory[ip])); - ip += 1; - break; - } - } - } catch { - sb.AppendLine($"{memory[ip]}"); ip += 2; - } - } - - return sb.ToString().TrimEnd(); - } -} diff --git a/2019/README.md b/2019/README.md deleted file mode 100644 index 27bdfaccb..000000000 --- a/2019/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2019) -Check out https://adventofcode.com/2019. - - diff --git a/2019/SplashScreen.cs b/2019/SplashScreen.cs deleted file mode 100644 index 9025b076f..000000000 --- a/2019/SplashScreen.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; - -namespace AdventOfCode.Y2019; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ sub y{2019}\n \n"); - Write(0xcc00, false, " "); - Write(0x666666, false, " ''.. ':. '. "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "....... "); - Write(0x333333, false, "."); - Write(0x666666, false, " ''. '. "); - Write(0xbebcbc, true, ". "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x333333, false, "."); - Write(0x666666, false, " '''''... ''. '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " ' "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ''.. '. '. "); - Write(0xffffff, true, ". "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "...... "); - Write(0x333333, false, "."); - Write(0x666666, false, " ''."); - Write(0x333333, false, ". ."); - Write(0x666666, false, " '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " '. "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ''''... "); - Write(0x333333, false, "."); - Write(0x666666, false, "'. "); - Write(0x333333, false, "."); - Write(0x666666, false, " '. : "); - Write(0xcdc1b2, true, ". "); - Write(0x333333, false, ". "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ''.. '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " '."); - Write(0x333333, false, "."); - Write(0x666666, false, " '. "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "..... ''. '. '. '"); - Write(0x456efe, true, "o "); - Write(0x333333, false, ". "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ''''... '. '. ': '."); - Write(0x333333, false, ". "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x333333, false, "."); - Write(0x666666, false, " '.. '. '. "); - Write(0xbee4e7, true, "o"); - Write(0x333333, false, "."); - Write(0x666666, false, " : "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0x333333, false, ". ."); - Write(0x666666, false, " '. '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " : : "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "'''''... '. "); - Write(0x333333, false, ". ."); - Write(0x666666, false, " '. "); - Write(0xebc982, true, "(O)"); - Write(0x666666, false, " : '. "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0x333333, false, "."); - Write(0x666666, false, " ''.. '. '. "); - Write(0x333333, false, ".."); - Write(0x666666, false, " '. '. : "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "''''... '. '. '"); - Write(0xd2beab, true, "O"); - Write(0x666666, false, " '. : :"); - Write(0x333333, false, ". "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ''. '."); - Write(0x333333, false, ". ."); - Write(0x666666, false, " : '. : '. : "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "'''''.. '. '. "); - Write(0x333333, false, ". . "); - Write(0xbabdb6, true, "."); - Write(0x666666, false, " : "); - Write(0x333333, false, "."); - Write(0x666666, false, " '. : '. "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " '. '. '. '. "); - Write(0x333333, false, "."); - Write(0x666666, false, " : : : : "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " : '."); - Write(0x333333, false, ". "); - Write(0xf7a859, true, ". "); - Write(0x333333, false, "."); - Write(0x666666, false, " : :"); - Write(0x333333, false, "."); - Write(0x666666, false, " : : : "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "'''. "); - Write(0x333333, false, "."); - Write(0x666666, false, ":"); - Write(0x333333, false, "."); - Write(0x666666, false, " : :"); - Write(0x333333, false, "."); - Write(0x666666, false, " : : : : : "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0xffff66, true, "* "); - Write(0xbebcbe, true, "."); - Write(0x666666, false, " : : : : : : "); - Write(0x333333, false, "."); - Write(0x666666, false, " : : "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, "...' "); - Write(0x333333, false, "."); - Write(0x666666, false, ": : : : "); - Write(0x333333, false, "."); - Write(0x666666, false, ": : "); - Write(0x333333, false, "."); - Write(0x666666, false, ": : "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x333333, false, ". "); - Write(0xe3e2e0, true, "."); - Write(0x333333, false, "."); - Write(0x666666, false, " .' : : : : : : "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " .' .' .' "); - Write(0x333333, false, "."); - Write(0x666666, false, " .' : : : : "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, ".....'' "); - Write(0x91a5bd, true, "."); - Write(0x666666, false, "' .' : : .' "); - Write(0x333333, false, "."); - Write(0x666666, false, " : .' "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0x666666, false, " ..' .' : "); - Write(0x333333, false, "."); - Write(0x666666, false, " .' : .'"); - Write(0x333333, false, "."); - Write(0x666666, false, " : "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2019/calendar.svg b/2019/calendar.svg deleted file mode 100644 index 171bad8d6..000000000 --- a/2019/calendar.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  sub y{2019} -  -                   ''..     ':.              '.    25 ** -.......    .           ''.     '.              .   24 ** -.      '''''...           ''.    '.  .          '  23 ** -               ''..          '.    '. .            22 ** -......      .      ''.. .      '. .  '.            21 ** -      ''''...        .'.       . '.    : .  .      20 ** -             ''..       '.    .    '..  '.         19 ** -.....            ''.      '.        '.   'o    .   18 ** -     ''''...        '.      '.       ':   '..      17 ** - .          '..       '.      '.       o.   :      16 ** -        .   .  '.       '.   . '.   .   :    :     15 ** -'''''...         '.  . . '.     (O)      :   '.    14 ** -    .   ''..       '.     '.  .. '.      '.   :    13 ** -''''...     '.      '.     'O     '.      :    :.  12 ** -       ''.    '.. .   :     '.     :      '.   :   11 ** -'''''..   '.   '. .  . .     :  .  '.      :   '.  10 ** -       '.  '.   '.     '.  .  :     :      :    :   9 ** -         :  '..  . .    :     :.    :       :   :   8 ** -'''.     .:. :   :.     :     :     :       :   :   7 ** - * .      :  :   :      :     :     :   .   :   :   6 ** -...'     .:  :   :      :    .:     :      .:   :   5 ** -       . .. .'   :      :     :     :       :   :   4 ** -       .'  .'   .'  .  .'     :     :      :    :   3 ** -.....''   .'   .'      :     :     .' .    :   .'   2 ** -       ..'    .'      :  .  .'     :      .'.  :    1 ** - - - - \ No newline at end of file diff --git a/2020/Day01/README.md b/2020/Day01/README.md deleted file mode 100644 index afa2c5f0e..000000000 --- a/2020/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Report Repair --- -After saving Christmas [five years in a row](/events), 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. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2020/day/1) description._ diff --git a/2020/Day01/Solution.cs b/2020/Day01/Solution.cs deleted file mode 100644 index f26bb8a66..000000000 --- a/2020/Day01/Solution.cs +++ /dev/null @@ -1,33 +0,0 @@ -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(); - } -} diff --git a/2020/Day01/input.in b/2020/Day01/input.in deleted file mode 100644 index 498aa0d3f..000000000 Binary files a/2020/Day01/input.in and /dev/null differ diff --git a/2020/Day01/input.refout b/2020/Day01/input.refout deleted file mode 100644 index afaacc055..000000000 --- a/2020/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -692916 -289270976 \ No newline at end of file diff --git a/2020/Day02/README.md b/2020/Day02/README.md deleted file mode 100644 index 0b731664f..000000000 --- a/2020/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Password Philosophy --- -Your flight departs in a few days from the coastal airport; the easiest way down to the coast from here is via [toboggan](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2020/day/2). \ No newline at end of file diff --git a/2020/Day02/Solution.cs b/2020/Day02/Solution.cs deleted file mode 100644 index 63edb3c2c..000000000 --- a/2020/Day02/Solution.cs +++ /dev/null @@ -1,30 +0,0 @@ -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); -} diff --git a/2020/Day02/input.in b/2020/Day02/input.in deleted file mode 100644 index b43c90dc0..000000000 Binary files a/2020/Day02/input.in and /dev/null differ diff --git a/2020/Day02/input.refout b/2020/Day02/input.refout deleted file mode 100644 index 9d8098c7b..000000000 --- a/2020/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -434 -509 \ No newline at end of file diff --git a/2020/Day03/README.md b/2020/Day03/README.md deleted file mode 100644 index 79e2a72a7..000000000 --- a/2020/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Toboggan Trajectory --- -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](https://adventofcode.com/2020/day/3). \ No newline at end of file diff --git a/2020/Day03/Solution.cs b/2020/Day03/Solution.cs deleted file mode 100644 index 0e369de9a..000000000 --- a/2020/Day03/Solution.cs +++ /dev/null @@ -1,27 +0,0 @@ -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; - } -} diff --git a/2020/Day03/input.in b/2020/Day03/input.in deleted file mode 100644 index 4eb1a39f2..000000000 Binary files a/2020/Day03/input.in and /dev/null differ diff --git a/2020/Day03/input.refout b/2020/Day03/input.refout deleted file mode 100644 index d939d4155..000000000 --- a/2020/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -278 -9709761600 \ No newline at end of file diff --git a/2020/Day04/README.md b/2020/Day04/README.md deleted file mode 100644 index cd23630f4..000000000 --- a/2020/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Passport Processing --- -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](https://adventofcode.com/2020/day/4). \ No newline at end of file diff --git a/2020/Day04/Solution.cs b/2020/Day04/Solution.cs deleted file mode 100644 index 99839dada..000000000 --- a/2020/Day04/Solution.cs +++ /dev/null @@ -1,39 +0,0 @@ -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); -} diff --git a/2020/Day04/input.in b/2020/Day04/input.in deleted file mode 100644 index f84e2c10e..000000000 Binary files a/2020/Day04/input.in and /dev/null differ diff --git a/2020/Day04/input.refout b/2020/Day04/input.refout deleted file mode 100644 index 99fabf17c..000000000 --- a/2020/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -237 -172 \ No newline at end of file diff --git a/2020/Day05/README.md b/2020/Day05/README.md deleted file mode 100644 index 79b2dec02..000000000 --- a/2020/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Binary Boarding --- -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](https://adventofcode.com/2020/day/5). \ No newline at end of file diff --git a/2020/Day05/Solution.cs b/2020/Day05/Solution.cs deleted file mode 100644 index 61d4458be..000000000 --- a/2020/Day05/Solution.cs +++ /dev/null @@ -1,27 +0,0 @@ -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(); -} diff --git a/2020/Day05/input.in b/2020/Day05/input.in deleted file mode 100644 index addba3135..000000000 Binary files a/2020/Day05/input.in and /dev/null differ diff --git a/2020/Day05/input.refout b/2020/Day05/input.refout deleted file mode 100644 index 2210e3df1..000000000 --- a/2020/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -871 -640 \ No newline at end of file diff --git a/2020/Day06/README.md b/2020/Day06/README.md deleted file mode 100644 index f1f605931..000000000 --- a/2020/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Custom Customs --- -As your flight approaches the regional airport where you'll switch to a much larger plane, [customs declaration forms](https://en.wikipedia.org/wiki/Customs_declaration) 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](https://adventofcode.com/2020/day/6). \ No newline at end of file diff --git a/2020/Day06/Solution.cs b/2020/Day06/Solution.cs deleted file mode 100644 index 40374e899..000000000 --- a/2020/Day06/Solution.cs +++ /dev/null @@ -1,20 +0,0 @@ -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(); - } -} diff --git a/2020/Day06/input.in b/2020/Day06/input.in deleted file mode 100644 index 62ced6e23..000000000 Binary files a/2020/Day06/input.in and /dev/null differ diff --git a/2020/Day06/input.refout b/2020/Day06/input.refout deleted file mode 100644 index 674ef5261..000000000 --- a/2020/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6534 -3402 \ No newline at end of file diff --git a/2020/Day07/README.md b/2020/Day07/README.md deleted file mode 100644 index a3323abd5..000000000 --- a/2020/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: Handy Haversacks --- -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](https://adventofcode.com/2020/day/7). \ No newline at end of file diff --git a/2020/Day07/Solution.cs b/2020/Day07/Solution.cs deleted file mode 100644 index fd3203069..000000000 --- a/2020/Day07/Solution.cs +++ /dev/null @@ -1,63 +0,0 @@ -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); - } - -} diff --git a/2020/Day07/input.in b/2020/Day07/input.in deleted file mode 100644 index 992861ef5..000000000 Binary files a/2020/Day07/input.in and /dev/null differ diff --git a/2020/Day07/input.refout b/2020/Day07/input.refout deleted file mode 100644 index bebaa292e..000000000 --- a/2020/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -229 -6683 \ No newline at end of file diff --git a/2020/Day08/README.md b/2020/Day08/README.md deleted file mode 100644 index d59bf37f6..000000000 --- a/2020/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Handheld Halting --- -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](https://en.wikipedia.org/wiki/Handheld_game_console) won't turn on! They ask if you can take a look. - -Read the [full puzzle](https://adventofcode.com/2020/day/8). \ No newline at end of file diff --git a/2020/Day08/Solution.cs b/2020/Day08/Solution.cs deleted file mode 100644 index 2d1aee811..000000000 --- a/2020/Day08/Solution.cs +++ /dev/null @@ -1,56 +0,0 @@ -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; - }; - } - } - } -} diff --git a/2020/Day08/input.in b/2020/Day08/input.in deleted file mode 100644 index f89763dda..000000000 Binary files a/2020/Day08/input.in and /dev/null differ diff --git a/2020/Day08/input.refout b/2020/Day08/input.refout deleted file mode 100644 index 57264ef31..000000000 --- a/2020/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2034 -672 \ No newline at end of file diff --git a/2020/Day09/README.md b/2020/Day09/README.md deleted file mode 100644 index 5a67e3bca..000000000 --- a/2020/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Encoding Error --- -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](https://adventofcode.com/2020/day/9). \ No newline at end of file diff --git a/2020/Day09/Solution.cs b/2020/Day09/Solution.cs deleted file mode 100644 index 7b91e5a65..000000000 --- a/2020/Day09/Solution.cs +++ /dev/null @@ -1,42 +0,0 @@ -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(); - } -} diff --git a/2020/Day09/input.in b/2020/Day09/input.in deleted file mode 100644 index 59a243f0a..000000000 Binary files a/2020/Day09/input.in and /dev/null differ diff --git a/2020/Day09/input.refout b/2020/Day09/input.refout deleted file mode 100644 index 9e8a7b02e..000000000 --- a/2020/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -57195069 -7409241 \ No newline at end of file diff --git a/2020/Day10/README.md b/2020/Day10/README.md deleted file mode 100644 index 9d44928ce..000000000 --- a/2020/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Adapter Array --- -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](https://adventofcode.com/2020/day/10). \ No newline at end of file diff --git a/2020/Day10/Solution.cs b/2020/Day10/Solution.cs deleted file mode 100644 index 9169acf0d..000000000 --- a/2020/Day10/Solution.cs +++ /dev/null @@ -1,40 +0,0 @@ -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); - } -} diff --git a/2020/Day10/input.in b/2020/Day10/input.in deleted file mode 100644 index 759c3b340..000000000 Binary files a/2020/Day10/input.in and /dev/null differ diff --git a/2020/Day10/input.refout b/2020/Day10/input.refout deleted file mode 100644 index ce80c6488..000000000 --- a/2020/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1904 -10578455953408 \ No newline at end of file diff --git a/2020/Day11/README.md b/2020/Day11/README.md deleted file mode 100644 index a63684e2a..000000000 --- a/2020/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Seating System --- -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](https://adventofcode.com/2020/day/11). \ No newline at end of file diff --git a/2020/Day11/Solution.cs b/2020/Day11/Solution.cs deleted file mode 100644 index b4c6aa169..000000000 --- a/2020/Day11/Solution.cs +++ /dev/null @@ -1,52 +0,0 @@ -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 == '#'); - } -} diff --git a/2020/Day11/input.in b/2020/Day11/input.in deleted file mode 100644 index e47a1f52c..000000000 Binary files a/2020/Day11/input.in and /dev/null differ diff --git a/2020/Day11/input.refout b/2020/Day11/input.refout deleted file mode 100644 index c2ccaf2a9..000000000 --- a/2020/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2164 -1974 \ No newline at end of file diff --git a/2020/Day12/README.md b/2020/Day12/README.md deleted file mode 100644 index 5a856ba51..000000000 --- a/2020/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Rain Risk --- -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](https://en.wikipedia.org/wiki/Public_address_system) to ask if anyone can help, you quickly volunteer. - -Read the [full puzzle](https://adventofcode.com/2020/day/12). \ No newline at end of file diff --git a/2020/Day12/Solution.cs b/2020/Day12/Solution.cs deleted file mode 100644 index a5ede3fa4..000000000 --- a/2020/Day12/Solution.cs +++ /dev/null @@ -1,38 +0,0 @@ -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)); -} diff --git a/2020/Day12/input.in b/2020/Day12/input.in deleted file mode 100644 index 87a53ff58..000000000 Binary files a/2020/Day12/input.in and /dev/null differ diff --git a/2020/Day12/input.refout b/2020/Day12/input.refout deleted file mode 100644 index 14708017e..000000000 --- a/2020/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -445 -42495 \ No newline at end of file diff --git a/2020/Day13/README.md b/2020/Day13/README.md deleted file mode 100644 index 358e65ddb..000000000 --- a/2020/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Shuttle Search --- -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](https://adventofcode.com/2020/day/13). \ No newline at end of file diff --git a/2020/Day13/Solution.cs b/2020/Day13/Solution.cs deleted file mode 100644 index 507c849ef..000000000 --- a/2020/Day13/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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); -} diff --git a/2020/Day13/input.in b/2020/Day13/input.in deleted file mode 100644 index d5be0d5c9..000000000 Binary files a/2020/Day13/input.in and /dev/null differ diff --git a/2020/Day13/input.refout b/2020/Day13/input.refout deleted file mode 100644 index 0ebe71fd8..000000000 --- a/2020/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2165 -534035653563227 \ No newline at end of file diff --git a/2020/Day14/README.md b/2020/Day14/README.md deleted file mode 100644 index c5e356207..000000000 --- a/2020/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Docking Data --- -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](https://en.wikipedia.org/wiki/Mask_(computing)) 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](https://adventofcode.com/2020/day/14). \ No newline at end of file diff --git a/2020/Day14/Solution.cs b/2020/Day14/Solution.cs deleted file mode 100644 index b61c86191..000000000 --- a/2020/Day14/Solution.cs +++ /dev/null @@ -1,62 +0,0 @@ -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; - } - } - } - } -} diff --git a/2020/Day14/input.in b/2020/Day14/input.in deleted file mode 100644 index 5ee6d12fb..000000000 Binary files a/2020/Day14/input.in and /dev/null differ diff --git a/2020/Day14/input.refout b/2020/Day14/input.refout deleted file mode 100644 index d2a96ded8..000000000 --- a/2020/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -7997531787333 -3564822193820 \ No newline at end of file diff --git a/2020/Day15/README.md b/2020/Day15/README.md deleted file mode 100644 index 5ac8db2cb..000000000 --- a/2020/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Rambunctious Recitation --- -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](https://adventofcode.com/2020/day/15). \ No newline at end of file diff --git a/2020/Day15/Solution.cs b/2020/Day15/Solution.cs deleted file mode 100644 index 3147a7ffb..000000000 --- a/2020/Day15/Solution.cs +++ /dev/null @@ -1,22 +0,0 @@ -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; - } -} diff --git a/2020/Day15/input.in b/2020/Day15/input.in deleted file mode 100644 index 1522fa3f9..000000000 Binary files a/2020/Day15/input.in and /dev/null differ diff --git a/2020/Day15/input.refout b/2020/Day15/input.refout deleted file mode 100644 index 64ced955d..000000000 --- a/2020/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -203 -9007186 \ No newline at end of file diff --git a/2020/Day16/README.md b/2020/Day16/README.md deleted file mode 100644 index 60aa6b76e..000000000 --- a/2020/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Ticket Translation --- -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](https://adventofcode.com/2020/day/16). \ No newline at end of file diff --git a/2020/Day16/Solution.cs b/2020/Day16/Solution.cs deleted file mode 100644 index d5632bcce..000000000 --- a/2020/Day16/Solution.cs +++ /dev/null @@ -1,95 +0,0 @@ -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); - } -} diff --git a/2020/Day16/input.in b/2020/Day16/input.in deleted file mode 100644 index a63ca86a8..000000000 Binary files a/2020/Day16/input.in and /dev/null differ diff --git a/2020/Day16/input.refout b/2020/Day16/input.refout deleted file mode 100644 index b4b4f7ed1..000000000 --- a/2020/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -26009 -589685618167 \ No newline at end of file diff --git a/2020/Day17/README.md b/2020/Day17/README.md deleted file mode 100644 index 77aab7398..000000000 --- a/2020/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Conway Cubes --- -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](https://adventofcode.com/2020/day/17). \ No newline at end of file diff --git a/2020/Day17/Solution.cs b/2020/Day17/Solution.cs deleted file mode 100644 index d97204c9e..000000000 --- a/2020/Day17/Solution.cs +++ /dev/null @@ -1,73 +0,0 @@ -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(); - } -} diff --git a/2020/Day17/input.in b/2020/Day17/input.in deleted file mode 100644 index 0ffd26405..000000000 Binary files a/2020/Day17/input.in and /dev/null differ diff --git a/2020/Day17/input.refout b/2020/Day17/input.refout deleted file mode 100644 index 1840a425f..000000000 --- a/2020/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -271 -2064 \ No newline at end of file diff --git a/2020/Day18/README.md b/2020/Day18/README.md deleted file mode 100644 index f6419792d..000000000 --- a/2020/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Operation Order --- -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](https://www.youtube.com/watch?v=3QtRK7Y2pPU&t=15) than you remember. - -Read the [full puzzle](https://adventofcode.com/2020/day/18). \ No newline at end of file diff --git a/2020/Day18/Solution.cs b/2020/Day18/Solution.cs deleted file mode 100644 index 80c40a294..000000000 --- a/2020/Day18/Solution.cs +++ /dev/null @@ -1,65 +0,0 @@ -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; - } -} diff --git a/2020/Day18/input.in b/2020/Day18/input.in deleted file mode 100644 index 13bc4762b..000000000 Binary files a/2020/Day18/input.in and /dev/null differ diff --git a/2020/Day18/input.refout b/2020/Day18/input.refout deleted file mode 100644 index 9a8c99a60..000000000 --- a/2020/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -75592527415659 -360029542265462 \ No newline at end of file diff --git a/2020/Day19/README.md b/2020/Day19/README.md deleted file mode 100644 index 84fc34e56..000000000 --- a/2020/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Monster Messages --- -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](https://adventofcode.com/2020/day/19). \ No newline at end of file diff --git a/2020/Day19/Solution.cs b/2020/Day19/Solution.cs deleted file mode 100644 index 2c7b706b4..000000000 --- a/2020/Day19/Solution.cs +++ /dev/null @@ -1,86 +0,0 @@ -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; - } -} diff --git a/2020/Day19/input.in b/2020/Day19/input.in deleted file mode 100644 index ee4e83cb5..000000000 Binary files a/2020/Day19/input.in and /dev/null differ diff --git a/2020/Day19/input.refout b/2020/Day19/input.refout deleted file mode 100644 index 0eb08e7cd..000000000 --- a/2020/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -147 -263 \ No newline at end of file diff --git a/2020/Day20/README.md b/2020/Day20/README.md deleted file mode 100644 index 61638dbef..000000000 --- a/2020/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Jurassic Jigsaw --- -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](https://adventofcode.com/2020/day/20). \ No newline at end of file diff --git a/2020/Day20/Solution.cs b/2020/Day20/Solution.cs deleted file mode 100644 index 08563cc4e..000000000 --- a/2020/Day20/Solution.cs +++ /dev/null @@ -1,214 +0,0 @@ -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; - } -} diff --git a/2020/Day20/input.in b/2020/Day20/input.in deleted file mode 100644 index 97e975f2f..000000000 Binary files a/2020/Day20/input.in and /dev/null differ diff --git a/2020/Day20/input.refout b/2020/Day20/input.refout deleted file mode 100644 index 11ce5934d..000000000 --- a/2020/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -60145080587029 -1901 \ No newline at end of file diff --git a/2020/Day21/README.md b/2020/Day21/README.md deleted file mode 100644 index 5eda168ce..000000000 --- a/2020/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Allergen Assessment --- -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](https://adventofcode.com/2020/day/21). \ No newline at end of file diff --git a/2020/Day21/Solution.cs b/2020/Day21/Solution.cs deleted file mode 100644 index ed41cb554..000000000 --- a/2020/Day21/Solution.cs +++ /dev/null @@ -1,68 +0,0 @@ -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()); -} diff --git a/2020/Day21/input.in b/2020/Day21/input.in deleted file mode 100644 index 069732cb8..000000000 Binary files a/2020/Day21/input.in and /dev/null differ diff --git a/2020/Day21/input.refout b/2020/Day21/input.refout deleted file mode 100644 index 86221c8bd..000000000 --- a/2020/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2584 -fqhpsl,zxncg,clzpsl,zbbnj,jkgbvlxh,dzqc,ppj,glzb \ No newline at end of file diff --git a/2020/Day22/README.md b/2020/Day22/README.md deleted file mode 100644 index 07b3f0bf0..000000000 --- a/2020/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Crab Combat --- -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](/2019/day/22)! 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](https://adventofcode.com/2020/day/22). \ No newline at end of file diff --git a/2020/Day22/Solution.cs b/2020/Day22/Solution.cs deleted file mode 100644 index da455ac6c..000000000 --- a/2020/Day22/Solution.cs +++ /dev/null @@ -1,79 +0,0 @@ -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)) - ); - } -} diff --git a/2020/Day22/input.in b/2020/Day22/input.in deleted file mode 100644 index 831915344..000000000 Binary files a/2020/Day22/input.in and /dev/null differ diff --git a/2020/Day22/input.refout b/2020/Day22/input.refout deleted file mode 100644 index e01a19919..000000000 --- a/2020/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -33098 -35055 \ No newline at end of file diff --git a/2020/Day23/README.md b/2020/Day23/README.md deleted file mode 100644 index 7f505c698..000000000 --- a/2020/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Crab Cups --- -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](https://adventofcode.com/2020/day/23). \ No newline at end of file diff --git a/2020/Day23/Solution.cs b/2020/Day23/Solution.cs deleted file mode 100644 index 6c9e9ef91..000000000 --- a/2020/Day23/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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]; - } - } -} diff --git a/2020/Day23/input.in b/2020/Day23/input.in deleted file mode 100644 index 32bcef7d0..000000000 Binary files a/2020/Day23/input.in and /dev/null differ diff --git a/2020/Day23/input.refout b/2020/Day23/input.refout deleted file mode 100644 index 9593f7691..000000000 --- a/2020/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -78569234 -565615814504 \ No newline at end of file diff --git a/2020/Day24/README.md b/2020/Day24/README.md deleted file mode 100644 index 614c04ba5..000000000 --- a/2020/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Lobby Layout --- -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](https://adventofcode.com/2020/day/24). \ No newline at end of file diff --git a/2020/Day24/Solution.cs b/2020/Day24/Solution.cs deleted file mode 100644 index cc4c2b2e6..000000000 --- a/2020/Day24/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -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); - } -} diff --git a/2020/Day24/input.in b/2020/Day24/input.in deleted file mode 100644 index 69fd51927..000000000 Binary files a/2020/Day24/input.in and /dev/null differ diff --git a/2020/Day24/input.refout b/2020/Day24/input.refout deleted file mode 100644 index 54f436ae5..000000000 --- a/2020/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -351 -3869 \ No newline at end of file diff --git a/2020/Day25/README.md b/2020/Day25/README.md deleted file mode 100644 index 1ee9fb87d..000000000 --- a/2020/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Combo Breaker --- -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](https://en.wikipedia.org/wiki/Radio-frequency_identification) 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](https://adventofcode.com/2020/day/25). \ No newline at end of file diff --git a/2020/Day25/Solution.cs b/2020/Day25/Solution.cs deleted file mode 100644 index 7acb7f880..000000000 --- a/2020/Day25/Solution.cs +++ /dev/null @@ -1,29 +0,0 @@ -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; - } - -} diff --git a/2020/Day25/input.in b/2020/Day25/input.in deleted file mode 100644 index 44406a1f4..000000000 Binary files a/2020/Day25/input.in and /dev/null differ diff --git a/2020/Day25/input.refout b/2020/Day25/input.refout deleted file mode 100644 index 360867062..000000000 --- a/2020/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -181800 \ No newline at end of file diff --git a/2020/README.md b/2020/README.md deleted file mode 100644 index 6e92a1b05..000000000 --- a/2020/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2020) -Check out https://adventofcode.com/2020. - - diff --git a/2020/SplashScreen.cs b/2020/SplashScreen.cs deleted file mode 100644 index 0152b71a8..000000000 --- a/2020/SplashScreen.cs +++ /dev/null @@ -1,238 +0,0 @@ -using System; - -namespace AdventOfCode.Y2020; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ /* 2020 */\n \n "); - Write(0xcc00, false, " "); - Write(0xccccff, false, ".........."); - Write(0xff0000, false, "|"); - Write(0xccccff, false, ".......... "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n "); - Write(0xccccff, false, ".....'''''' "); - Write(0xffffff, false, ".' - - "); - Write(0xcccccc, false, "\\"); - Write(0xffffff, false, "- .''"); - Write(0x333399, false, "~ ~ "); - Write(0xccccff, false, "''''''..... "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0xccccff, false, "''' "); - Write(0x333399, false, "~ ~ ~ ~ ~ "); - Write(0xffffff, false, "'.'. - - "); - Write(0xcccccc, false, "\\ "); - Write(0xffffff, false, "-'': "); - Write(0x333399, false, "~ ~ ~ ~ "); - Write(0xccccff, false, "''' "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ ~ ~ ~ ~ "); - Write(0xffffff, false, "''..'''"); - Write(0xcccccc, false, "_[]"); - Write(0xffffff, false, ".' "); - Write(0x333399, false, "~ ~ ~ ~ ~ "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcc00, false, ".'. "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcccccc, false, "____/ "); - Write(0xffffff, false, "'' "); - Write(0x333399, false, "~ ~ ~ ~ ~ ~ "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ "); - Write(0xcc00, false, "'' .."); - Write(0xcccccc, false, "_____/ "); - Write(0x333399, false, "~ ~ ~ ~ "); - Write(0x9900ff, false, "_ "); - Write(0x333399, false, "~ "); - Write(0x9900ff, false, "_ O> "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ ~ ~ "); - Write(0xcc00, false, ":"); - Write(0xcccccc, false, "[]"); - Write(0xcc00, false, "'. "); - Write(0x333399, false, "~ ~ ~ "); - Write(0x9900ff, false, "\\ / \\ / \\ / "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, "'."); - Write(0xcccccc, false, "\\ "); - Write(0x333399, false, "~ ~ ~ ~ ~ ~ ~ "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcccccc, false, "\\ "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "____ "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ "); - Write(0xcccccc, false, "\\____/ "); - Write(0xcc00, false, ".''"); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "'.. "); - Write(0x333399, false, "~ ~ "); - Write(0xcc00, false, ". "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ "); - Write(0xcccccc, false, "__/\\ "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, ".'"); - Write(0xffffff, false, "^ "); - Write(0xcccccc, false, "[]"); - Write(0xcc00, false, ".' "); - Write(0x333399, false, "~ ~ "); - Write(0xcc00, false, "..'' "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "... "); - Write(0x333399, false, "~"); - Write(0xcccccc, false, "_____/"); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "\\ "); - Write(0xcc00, false, ":"); - Write(0xffffff, false, "^ "); - Write(0xcc00, false, ", :"); - Write(0xcccccc, false, "\\ "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, ":'' , "); - Write(0xffffff, false, "^ "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "###: ..."); - Write(0xcccccc, false, "/ "); - Write(0x333399, false, "~ ~"); - Write(0xcccccc, false, "\\ "); - Write(0xcc00, false, "'..' "); - Write(0xcccccc, false, "\\_______"); - Write(0x333399, false, "~ "); - Write(0xcc00, false, "'. , "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, ".'' .'"); - Write(0xcccccc, false, "[]"); - Write(0xcc00, false, "'. "); - Write(0xcccccc, false, "\\ "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcccccc, false, "\\ "); - Write(0xcc00, false, ": , "); - Write(0xffffff, false, "^ "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "'...'##"); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "##'. "); - Write(0x333399, false, "~ ~ "); - Write(0xcccccc, false, "\\ "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, "."); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "' , "); - Write(0xffffff, false, "^ ^ "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "##### ,#"); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "#.' "); - Write(0xcccccc, false, "\\ "); - Write(0xcc00, false, ". "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, "'."); - Write(0xcccccc, false, "[] "); - Write(0xcc00, false, ", "); - Write(0xffffff, false, "^ "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "#, ,"); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "'. "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, "'',: "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "_/"); - Write(0xcc00, false, "'.. , "); - Write(0xffffff, false, "^ "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0xffcc99, false, "~ ~ "); - Write(0xcc00, false, ","); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, ",'. "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, ":"); - Write(0xcccccc, false, "[]"); - Write(0xcc00, false, "..' "); - Write(0xcccccc, false, "/ "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, "''... "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0xffcc99, false, "~ ~ ~ ~ "); - Write(0xcccccc, false, "\\"); - Write(0xcc00, false, ", : ''"); - Write(0xcccccc, false, "\\__ "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "/ 13 "); - Write(0xffff66, false, "**\n "); - Write(0xffcc99, false, "~ ~ ~ ~ ~ "); - Write(0xcc00, false, ","); - Write(0xcccccc, false, "[]"); - Write(0xcc00, false, ": "); - Write(0x333399, false, "~ ~ "); - Write(0xcccccc, false, "\\__ /"); - Write(0x333399, false, "~ ~ "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0xffcc99, false, "~ ~ ~ ~ ~ "); - Write(0xcc00, false, ", ."); - Write(0xcccccc, false, "\\______ \\__/ 12 "); - Write(0xffff66, false, "**\n "); - Write(0xffcc99, false, "~ ~ ~ "); - Write(0xcc00, false, "..' "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "\\______ "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, ".....''' "); - Write(0x333399, false, "~ ~"); - Write(0xcccccc, false, "\\____ 23 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, "'' "); - Write(0x333399, false, "~ "); - Write(0xcc00, false, ".'.."); - Write(0xcccccc, false, "\\___"); - Write(0xcc00, false, "''.. "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x333399, false, "~ ~ ~ "); - Write(0xcc00, false, "'.' : "); - Write(0xcccccc, false, "[] "); - Write(0xcc00, false, ".' "); - Write(0x333399, false, "~ "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2020/calendar.svg b/2020/calendar.svg deleted file mode 100644 index 645d8f67e..000000000 --- a/2020/calendar.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  /* 2020 */ -  -              ..........|..........                 1 ** -   .....'''''' .'  -  -  \- .''~ ~ ''''''.....      2 ** -''' ~ ~ ~ ~  ~ '.'. -   - \ -'':  ~ ~   ~  ~  '''   3 ** - ~   ~  ~   ~ ~  ~ ''..'''_[].'  ~    ~   ~ ~  ~    4 ** -~   ~ ~  .'. ~  ~  ~ ____/ ''  ~  ~  ~  ~  ~    ~   5 ** -  ~    ~ ''  .._____/ ~   ~  ~  ~    _ ~ _   O>     6 ** - ~  ~ ~   ~ :[]'.   ~   ~      ~  \ / \ / \ /  ~    7 ** -       ~     '.\ ~        ~  ~   ~  ~      ~    ~   8 ** - ~   ~      ~   \  ~   ____     ~      ~      ~    17 ** -       ~       ~ \____/ .''\'..    ~       ~    .   9 ** -    ~       ~  __/\ ~   .'^ [].'      ~  ~  ..''   16 ** -...     ~_____/~   \    :^ , :\  ~       :''  , ^  18 ** -###: .../   ~      ~\    '..'  \_______~ '. ,      15 ** -.'' .'[]'.           \ ~       ~   ~   \  :  , ^   19 ** -'...'##\##'.  ~    ~  \   ~            .\' ,  ^ ^  10 ** -##### ,#\#.'           \   .       ~   '.[]  , ^   14 ** -#,      ,\'.         ~  \'',:  ~       _/'..  , ^  20 ** -   ~ ~   ,\,'.   ~     :[]..'         / ~   ''...  11 ** -~ ~ ~ ~    \, :         ''\__  ~     /             13 ** - ~ ~ ~ ~ ~ ,[]:     ~     ~  \__    /~      ~      21 ** -~ ~ ~ ~ ~  , .\______           \__/               12 ** - ~ ~ ~    ..'   ~    \______    ~         ~    ~   22 ** -  .....'''           ~     ~\____                  23 ** -''         ~                 .'..\___''..       ~  24 ** -     ~          ~        ~    '.'  : [] .'  ~      25 ** - - - - \ No newline at end of file diff --git a/2021/Day01/README.md b/2021/Day01/README.md deleted file mode 100644 index a6d42749f..000000000 --- a/2021/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Sonar Sweep --- -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. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2021/day/1) description._ diff --git a/2021/Day01/Solution.cs b/2021/Day01/Solution.cs deleted file mode 100644 index e498523a4..000000000 --- a/2021/Day01/Solution.cs +++ /dev/null @@ -1,28 +0,0 @@ -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); -} diff --git a/2021/Day01/input.in b/2021/Day01/input.in deleted file mode 100644 index 15940121c..000000000 Binary files a/2021/Day01/input.in and /dev/null differ diff --git a/2021/Day01/input.refout b/2021/Day01/input.refout deleted file mode 100644 index de375c673..000000000 --- a/2021/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1655 -1683 \ No newline at end of file diff --git a/2021/Day02/README.md b/2021/Day02/README.md deleted file mode 100644 index c4ac01b53..000000000 --- a/2021/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Dive! --- -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](https://adventofcode.com/2021/day/2). \ No newline at end of file diff --git a/2021/Day02/Solution.cs b/2021/Day02/Solution.cs deleted file mode 100644 index 077f855d4..000000000 --- a/2021/Day02/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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); \ No newline at end of file diff --git a/2021/Day02/input.in b/2021/Day02/input.in deleted file mode 100644 index 0b939332d..000000000 Binary files a/2021/Day02/input.in and /dev/null differ diff --git a/2021/Day02/input.refout b/2021/Day02/input.refout deleted file mode 100644 index ecbed9659..000000000 --- a/2021/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1694130 -1698850445 \ No newline at end of file diff --git a/2021/Day03/README.md b/2021/Day03/README.md deleted file mode 100644 index 51e5a146b..000000000 --- a/2021/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Binary Diagnostic --- -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](https://adventofcode.com/2021/day/3). \ No newline at end of file diff --git a/2021/Day03/Solution.cs b/2021/Day03/Solution.cs deleted file mode 100644 index 0facfb174..000000000 --- a/2021/Day03/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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); - } -} diff --git a/2021/Day03/input.in b/2021/Day03/input.in deleted file mode 100644 index 46287174b..000000000 Binary files a/2021/Day03/input.in and /dev/null differ diff --git a/2021/Day03/input.refout b/2021/Day03/input.refout deleted file mode 100644 index e25281707..000000000 --- a/2021/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1307354 -482500 \ No newline at end of file diff --git a/2021/Day04/README.md b/2021/Day04/README.md deleted file mode 100644 index cd24ccd66..000000000 --- a/2021/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Giant Squid --- -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](https://en.wikipedia.org/wiki/Bingo_(American_version))? - -Read the [full puzzle](https://adventofcode.com/2021/day/4). \ No newline at end of file diff --git a/2021/Day04/Solution.cs b/2021/Day04/Solution.cs deleted file mode 100644 index 3e47a6fb8..000000000 --- a/2021/Day04/Solution.cs +++ /dev/null @@ -1,81 +0,0 @@ -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(); - } - } - } - } -} diff --git a/2021/Day04/input.in b/2021/Day04/input.in deleted file mode 100644 index f185fe414..000000000 Binary files a/2021/Day04/input.in and /dev/null differ diff --git a/2021/Day04/input.refout b/2021/Day04/input.refout deleted file mode 100644 index 513c1e048..000000000 --- a/2021/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -58838 -6256 \ No newline at end of file diff --git a/2021/Day05/README.md b/2021/Day05/README.md deleted file mode 100644 index a565ae1cb..000000000 --- a/2021/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Hydrothermal Venture --- -You come across a field of [hydrothermal vents](https://en.wikipedia.org/wiki/Hydrothermal_vent) 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](https://adventofcode.com/2021/day/5). \ No newline at end of file diff --git a/2021/Day05/Solution.cs b/2021/Day05/Solution.cs deleted file mode 100644 index 0358a02f3..000000000 --- a/2021/Day05/Solution.cs +++ /dev/null @@ -1,43 +0,0 @@ -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); diff --git a/2021/Day05/input.in b/2021/Day05/input.in deleted file mode 100644 index cc16d6461..000000000 Binary files a/2021/Day05/input.in and /dev/null differ diff --git a/2021/Day05/input.refout b/2021/Day05/input.refout deleted file mode 100644 index 228f9d8de..000000000 --- a/2021/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6548 -19663 \ No newline at end of file diff --git a/2021/Day06/README.md b/2021/Day06/README.md deleted file mode 100644 index 238ac092f..000000000 --- a/2021/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Lanternfish --- -The sea floor is getting steeper. Maybe the sleigh keys got carried this way? - -A massive school of glowing [lanternfish](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2021/day/6). \ No newline at end of file diff --git a/2021/Day06/Solution.cs b/2021/Day06/Solution.cs deleted file mode 100644 index 3654b91c0..000000000 --- a/2021/Day06/Solution.cs +++ /dev/null @@ -1,31 +0,0 @@ -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(); - } -} diff --git a/2021/Day06/input.in b/2021/Day06/input.in deleted file mode 100644 index 17a86be23..000000000 Binary files a/2021/Day06/input.in and /dev/null differ diff --git a/2021/Day06/input.refout b/2021/Day06/input.refout deleted file mode 100644 index b2ee5f8f7..000000000 --- a/2021/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -395627 -1767323539209 \ No newline at end of file diff --git a/2021/Day07/README.md b/2021/Day07/README.md deleted file mode 100644 index e8c136e7c..000000000 --- a/2021/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: The Treachery of Whales --- -A giant [whale](https://en.wikipedia.org/wiki/Sperm_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](https://adventofcode.com/2021/day/7). \ No newline at end of file diff --git a/2021/Day07/Solution.cs b/2021/Day07/Solution.cs deleted file mode 100644 index f0d9d96dd..000000000 --- a/2021/Day07/Solution.cs +++ /dev/null @@ -1,27 +0,0 @@ -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(); - } -} diff --git a/2021/Day07/input.in b/2021/Day07/input.in deleted file mode 100644 index 15a51df75..000000000 Binary files a/2021/Day07/input.in and /dev/null differ diff --git a/2021/Day07/input.refout b/2021/Day07/input.refout deleted file mode 100644 index c7c6616dc..000000000 --- a/2021/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -352997 -101571302 \ No newline at end of file diff --git a/2021/Day08/README.md b/2021/Day08/README.md deleted file mode 100644 index 526d9304a..000000000 --- a/2021/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Seven Segment Search --- -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](https://en.wikipedia.org/wiki/Seven-segment_display) 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](https://adventofcode.com/2021/day/8). \ No newline at end of file diff --git a/2021/Day08/Solution.cs b/2021/Day08/Solution.cs deleted file mode 100644 index c9060bf5f..000000000 --- a/2021/Day08/Solution.cs +++ /dev/null @@ -1,72 +0,0 @@ -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; - } -} diff --git a/2021/Day08/input.in b/2021/Day08/input.in deleted file mode 100644 index adba44a98..000000000 Binary files a/2021/Day08/input.in and /dev/null differ diff --git a/2021/Day08/input.refout b/2021/Day08/input.refout deleted file mode 100644 index 6a7debded..000000000 --- a/2021/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -445 -1043101 \ No newline at end of file diff --git a/2021/Day09/README.md b/2021/Day09/README.md deleted file mode 100644 index e7684e0c1..000000000 --- a/2021/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Smoke Basin --- -These caves seem to be [lava tubes](https://en.wikipedia.org/wiki/Lava_tube). 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](https://adventofcode.com/2021/day/9). \ No newline at end of file diff --git a/2021/Day09/Solution.cs b/2021/Day09/Solution.cs deleted file mode 100644 index 4310ef7e6..000000000 --- a/2021/Day09/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -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); diff --git a/2021/Day09/input.in b/2021/Day09/input.in deleted file mode 100644 index 606fffcb1..000000000 Binary files a/2021/Day09/input.in and /dev/null differ diff --git a/2021/Day09/input.refout b/2021/Day09/input.refout deleted file mode 100644 index 5741a9964..000000000 --- a/2021/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -560 -959136 \ No newline at end of file diff --git a/2021/Day10/README.md b/2021/Day10/README.md deleted file mode 100644 index b54a19720..000000000 --- a/2021/Day10/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## --- Day 10: Syntax Scoring --- -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](https://adventofcode.com/2021/day/10). \ No newline at end of file diff --git a/2021/Day10/Solution.cs b/2021/Day10/Solution.cs deleted file mode 100644 index b2a3aaebe..000000000 --- a/2021/Day10/Solution.cs +++ /dev/null @@ -1,47 +0,0 @@ -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 - } - } -} diff --git a/2021/Day10/input.in b/2021/Day10/input.in deleted file mode 100644 index dd0e3ff58..000000000 Binary files a/2021/Day10/input.in and /dev/null differ diff --git a/2021/Day10/input.refout b/2021/Day10/input.refout deleted file mode 100644 index 9b95ba3ea..000000000 --- a/2021/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -358737 -4329504793 \ No newline at end of file diff --git a/2021/Day11/README.md b/2021/Day11/README.md deleted file mode 100644 index f8375dbd7..000000000 --- a/2021/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Dumbo Octopus --- -You enter a large cavern full of rare bioluminescent [dumbo octopuses](https://www.youtube.com/watch?v=eih-VSaS2g0)! 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](https://adventofcode.com/2021/day/11). \ No newline at end of file diff --git a/2021/Day11/Solution.cs b/2021/Day11/Solution.cs deleted file mode 100644 index 752a5280c..000000000 --- a/2021/Day11/Solution.cs +++ /dev/null @@ -1,69 +0,0 @@ -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); \ No newline at end of file diff --git a/2021/Day11/input.in b/2021/Day11/input.in deleted file mode 100644 index 6cb93ba2c..000000000 Binary files a/2021/Day11/input.in and /dev/null differ diff --git a/2021/Day11/input.refout b/2021/Day11/input.refout deleted file mode 100644 index 7d5305851..000000000 --- a/2021/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1669 -351 \ No newline at end of file diff --git a/2021/Day12/README.md b/2021/Day12/README.md deleted file mode 100644 index 45761534a..000000000 --- a/2021/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Passage Pathing --- -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](https://adventofcode.com/2021/day/12). \ No newline at end of file diff --git a/2021/Day12/Solution.cs b/2021/Day12/Solution.cs deleted file mode 100644 index 9f3f2d6d5..000000000 --- a/2021/Day12/Solution.cs +++ /dev/null @@ -1,59 +0,0 @@ -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()); - } -} diff --git a/2021/Day12/input.in b/2021/Day12/input.in deleted file mode 100644 index 55154692f..000000000 Binary files a/2021/Day12/input.in and /dev/null differ diff --git a/2021/Day12/input.refout b/2021/Day12/input.refout deleted file mode 100644 index e4cdb262b..000000000 --- a/2021/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5958 -150426 \ No newline at end of file diff --git a/2021/Day13/README.md b/2021/Day13/README.md deleted file mode 100644 index 15367b70b..000000000 --- a/2021/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Transparent Origami --- -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](https://adventofcode.com/2021/day/13). \ No newline at end of file diff --git a/2021/Day13/Solution.cs b/2021/Day13/Solution.cs deleted file mode 100644 index d8c9a484c..000000000 --- a/2021/Day13/Solution.cs +++ /dev/null @@ -1,54 +0,0 @@ -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); diff --git a/2021/Day13/input.in b/2021/Day13/input.in deleted file mode 100644 index f942127fe..000000000 Binary files a/2021/Day13/input.in and /dev/null differ diff --git a/2021/Day13/input.refout b/2021/Day13/input.refout deleted file mode 100644 index a2781454a..000000000 --- a/2021/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -781 -PERCGJPB \ No newline at end of file diff --git a/2021/Day14/README.md b/2021/Day14/README.md deleted file mode 100644 index 8c52bcfe8..000000000 --- a/2021/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Extended Polymerization --- -The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has [polymerization](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2021/day/14). \ No newline at end of file diff --git a/2021/Day14/Solution.cs b/2021/Day14/Solution.cs deleted file mode 100644 index c48447dfe..000000000 --- a/2021/Day14/Solution.cs +++ /dev/null @@ -1,67 +0,0 @@ -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(); - } -} diff --git a/2021/Day14/input.in b/2021/Day14/input.in deleted file mode 100644 index 1998430c7..000000000 Binary files a/2021/Day14/input.in and /dev/null differ diff --git a/2021/Day14/input.refout b/2021/Day14/input.refout deleted file mode 100644 index 89ef62bc6..000000000 --- a/2021/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2937 -3390034818249 \ No newline at end of file diff --git a/2021/Day15/README.md b/2021/Day15/README.md deleted file mode 100644 index 6093959ce..000000000 --- a/2021/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Chiton --- -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](https://en.wikipedia.org/wiki/Chiton), 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](https://adventofcode.com/2021/day/15). \ No newline at end of file diff --git a/2021/Day15/Solution.cs b/2021/Day15/Solution.cs deleted file mode 100644 index 51c2c0f23..000000000 --- a/2021/Day15/Solution.cs +++ /dev/null @@ -1,94 +0,0 @@ -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); diff --git a/2021/Day15/input.in b/2021/Day15/input.in deleted file mode 100644 index f73b0e2ab..000000000 Binary files a/2021/Day15/input.in and /dev/null differ diff --git a/2021/Day15/input.refout b/2021/Day15/input.refout deleted file mode 100644 index 099b5c99e..000000000 --- a/2021/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -602 -2935 \ No newline at end of file diff --git a/2021/Day16/README.md b/2021/Day16/README.md deleted file mode 100644 index a3b16b0be..000000000 --- a/2021/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Packet Decoder --- -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](https://en.wikipedia.org/wiki/Hexadecimal) (your puzzle input). - -Read the [full puzzle](https://adventofcode.com/2021/day/16). \ No newline at end of file diff --git a/2021/Day16/Solution.cs b/2021/Day16/Solution.cs deleted file mode 100644 index 9bf73b3ef..000000000 --- a/2021/Day16/Solution.cs +++ /dev/null @@ -1,114 +0,0 @@ -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); diff --git a/2021/Day16/input.in b/2021/Day16/input.in deleted file mode 100644 index a243b333d..000000000 Binary files a/2021/Day16/input.in and /dev/null differ diff --git a/2021/Day16/input.refout b/2021/Day16/input.refout deleted file mode 100644 index 96f674b12..000000000 --- a/2021/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1002 -1673210814091 \ No newline at end of file diff --git a/2021/Day17/README.md b/2021/Day17/README.md deleted file mode 100644 index 52983df0e..000000000 --- a/2021/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Trick Shot --- -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](https://en.wikipedia.org/wiki/Oceanic_trench). Could the keys have fallen into it? You'd better send a probe to investigate. - -Read the [full puzzle](https://adventofcode.com/2021/day/17). \ No newline at end of file diff --git a/2021/Day17/Solution.cs b/2021/Day17/Solution.cs deleted file mode 100644 index 28e992833..000000000 --- a/2021/Day17/Solution.cs +++ /dev/null @@ -1,55 +0,0 @@ -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; - } - } - } - } - } -} diff --git a/2021/Day17/input.in b/2021/Day17/input.in deleted file mode 100644 index 430f4cb91..000000000 Binary files a/2021/Day17/input.in and /dev/null differ diff --git a/2021/Day17/input.refout b/2021/Day17/input.refout deleted file mode 100644 index d175b7427..000000000 --- a/2021/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5253 -1770 \ No newline at end of file diff --git a/2021/Day18/README.md b/2021/Day18/README.md deleted file mode 100644 index 4a42b45bb..000000000 --- a/2021/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Snailfish --- -You descend into the ocean trench and encounter some [snailfish](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2021/day/18). \ No newline at end of file diff --git a/2021/Day18/Solution.cs b/2021/Day18/Solution.cs deleted file mode 100644 index 78e98817a..000000000 --- a/2021/Day18/Solution.cs +++ /dev/null @@ -1,181 +0,0 @@ -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; - } -}; diff --git a/2021/Day18/input.in b/2021/Day18/input.in deleted file mode 100644 index 28b247a44..000000000 Binary files a/2021/Day18/input.in and /dev/null differ diff --git a/2021/Day18/input.refout b/2021/Day18/input.refout deleted file mode 100644 index bf15cc6a0..000000000 --- a/2021/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -4243 -4701 \ No newline at end of file diff --git a/2021/Day19/README.md b/2021/Day19/README.md deleted file mode 100644 index 5c4ee5380..000000000 --- a/2021/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Beacon Scanner --- -As your [probe](17) 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](https://adventofcode.com/2021/day/19). \ No newline at end of file diff --git a/2021/Day19/Solution.cs b/2021/Day19/Solution.cs deleted file mode 100644 index 5202479b1..000000000 --- a/2021/Day19/Solution.cs +++ /dev/null @@ -1,172 +0,0 @@ -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); - } -} diff --git a/2021/Day19/input.in b/2021/Day19/input.in deleted file mode 100644 index 3fec76663..000000000 Binary files a/2021/Day19/input.in and /dev/null differ diff --git a/2021/Day19/input.refout b/2021/Day19/input.refout deleted file mode 100644 index 5b544d427..000000000 --- a/2021/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -330 -9634 \ No newline at end of file diff --git a/2021/Day20/README.md b/2021/Day20/README.md deleted file mode 100644 index 0bf43a48c..000000000 --- a/2021/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Trench Map --- -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](https://adventofcode.com/2021/day/20). \ No newline at end of file diff --git a/2021/Day20/Solution.cs b/2021/Day20/Solution.cs deleted file mode 100644 index 9cb1b4668..000000000 --- a/2021/Day20/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -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); diff --git a/2021/Day20/input.in b/2021/Day20/input.in deleted file mode 100644 index d06c07c68..000000000 Binary files a/2021/Day20/input.in and /dev/null differ diff --git a/2021/Day20/input.refout b/2021/Day20/input.refout deleted file mode 100644 index 33e62ff39..000000000 --- a/2021/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5339 -18395 \ No newline at end of file diff --git a/2021/Day21/README.md b/2021/Day21/README.md deleted file mode 100644 index 017a374ff..000000000 --- a/2021/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Dirac Dice --- -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](https://en.wikipedia.org/wiki/Dice), two [pawns](https://en.wikipedia.org/wiki/Glossary_of_board_games#piece), 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](https://adventofcode.com/2021/day/21). \ No newline at end of file diff --git a/2021/Day21/Solution.cs b/2021/Day21/Solution.cs deleted file mode 100644 index 540947432..000000000 --- a/2021/Day21/Solution.cs +++ /dev/null @@ -1,86 +0,0 @@ -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); - } -} diff --git a/2021/Day21/input.in b/2021/Day21/input.in deleted file mode 100644 index 0b2fc3507..000000000 Binary files a/2021/Day21/input.in and /dev/null differ diff --git a/2021/Day21/input.refout b/2021/Day21/input.refout deleted file mode 100644 index ec2c83c81..000000000 --- a/2021/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -720750 -275067741811212 \ No newline at end of file diff --git a/2021/Day22/README.md b/2021/Day22/README.md deleted file mode 100644 index d28c86ec4..000000000 --- a/2021/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Reactor Reboot --- -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](/2020/day/17)?) - -Read the [full puzzle](https://adventofcode.com/2021/day/22). \ No newline at end of file diff --git a/2021/Day22/Solution.cs b/2021/Day22/Solution.cs deleted file mode 100644 index d7b039c22..000000000 --- a/2021/Day22/Solution.cs +++ /dev/null @@ -1,72 +0,0 @@ -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)); -} diff --git a/2021/Day22/input.in b/2021/Day22/input.in deleted file mode 100644 index b3fe3fb0a..000000000 Binary files a/2021/Day22/input.in and /dev/null differ diff --git a/2021/Day22/input.refout b/2021/Day22/input.refout deleted file mode 100644 index e44671d74..000000000 --- a/2021/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -545118 -1227298136842375 \ No newline at end of file diff --git a/2021/Day23/README.md b/2021/Day23/README.md deleted file mode 100644 index a3534977a..000000000 --- a/2021/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Amphipod --- -A group of [amphipods](https://en.wikipedia.org/wiki/Amphipoda) 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](https://adventofcode.com/2021/day/23). \ No newline at end of file diff --git a/2021/Day23/Solution.cs b/2021/Day23/Solution.cs deleted file mode 100644 index 2be99d7b2..000000000 --- a/2021/Day23/Solution.cs +++ /dev/null @@ -1,279 +0,0 @@ -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() - }; - } -} \ No newline at end of file diff --git a/2021/Day23/input.in b/2021/Day23/input.in deleted file mode 100644 index b5f7295a2..000000000 Binary files a/2021/Day23/input.in and /dev/null differ diff --git a/2021/Day23/input.refout b/2021/Day23/input.refout deleted file mode 100644 index e2520f876..000000000 --- a/2021/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -19160 -47232 \ No newline at end of file diff --git a/2021/Day24/README.md b/2021/Day24/README.md deleted file mode 100644 index fe492dc74..000000000 --- a/2021/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Arithmetic Logic Unit --- -[Magic smoke](https://en.wikipedia.org/wiki/Magic_smoke) starts leaking from the submarine's [arithmetic logic unit](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2021/day/24). \ No newline at end of file diff --git a/2021/Day24/Solution.cs b/2021/Day24/Solution.cs deleted file mode 100644 index 0deace6ad..000000000 --- a/2021/Day24/Solution.cs +++ /dev/null @@ -1,66 +0,0 @@ -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)); - } -} diff --git a/2021/Day24/input.in b/2021/Day24/input.in deleted file mode 100644 index b6a2cb888..000000000 Binary files a/2021/Day24/input.in and /dev/null differ diff --git a/2021/Day24/input.refout b/2021/Day24/input.refout deleted file mode 100644 index 8e1044118..000000000 --- a/2021/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -96979989692495 -51316214181141 \ No newline at end of file diff --git a/2021/Day25/README.md b/2021/Day25/README.md deleted file mode 100644 index 3ec000011..000000000 --- a/2021/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Sea Cucumber --- -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](https://en.wikipedia.org/wiki/Sea_cucumber), and there isn't an open space large enough for your submarine. - -Read the [full puzzle](https://adventofcode.com/2021/day/25). \ No newline at end of file diff --git a/2021/Day25/Solution.cs b/2021/Day25/Solution.cs deleted file mode 100644 index e329412a2..000000000 --- a/2021/Day25/Solution.cs +++ /dev/null @@ -1,62 +0,0 @@ -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; - } - } - } -} diff --git a/2021/Day25/input.in b/2021/Day25/input.in deleted file mode 100644 index 3cce93f11..000000000 Binary files a/2021/Day25/input.in and /dev/null differ diff --git a/2021/Day25/input.refout b/2021/Day25/input.refout deleted file mode 100644 index e41567feb..000000000 --- a/2021/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -384 \ No newline at end of file diff --git a/2021/README.md b/2021/README.md deleted file mode 100644 index c0b9cc240..000000000 --- a/2021/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2021) -Check out https://adventofcode.com/2021. - - diff --git a/2021/SplashScreen.cs b/2021/SplashScreen.cs deleted file mode 100644 index 525ef555c..000000000 --- a/2021/SplashScreen.cs +++ /dev/null @@ -1,189 +0,0 @@ -using System; - -namespace AdventOfCode.Y2021; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ int y = 2021;\n "); - Write(0xcc00, false, " \n "); - Write(0xc8ff, false, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n "); - Write(0xb5ed, false, " . . . . '.. . . ... "); - Write(0xffffff, false, ". "); - Write(0xb5ed, false, " ."); - Write(0x9933, true, ". "); - Write(0xa47a4d, false, "..'''' "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0xa2db, false, " . . . . ' "); - Write(0xffffff, false, ". "); - Write(0xa2db, false, " '"); - Write(0x66ff, true, ". "); - Write(0x9933, true, ". "); - Write(0xa47a4d, false, ": "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x91cc, false, " . . .. . . ."); - Write(0x9933, true, ". "); - Write(0xffffff, false, ".' "); - Write(0xff9900, true, ". "); - Write(0xa47a4d, false, "....' "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x85c0, false, " . . . ."); - Write(0xff00ff, true, ". "); - Write(0xc74c30, false, "."); - Write(0xff0000, false, "."); - Write(0xffffff, false, "|\\"); - Write(0xff0000, false, "."); - Write(0xc74c30, false, "."); - Write(0xa47a4d, false, "'' "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x79b5, false, ".'~ ' . . . "); - Write(0xff0000, true, ". "); - Write(0xa47a4d, false, ": "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x6daa, false, " ' . . ' . . . "); - Write(0xff0000, true, "."); - Write(0xa47a4d, false, ":' "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0x619f, false, "' . . .. .' .. "); - Write(0xff9900, true, "."); - Write(0xa47a4d, false, "'''''..... .."); - Write(0xc74c30, false, "."); - Write(0xff0000, false, ". "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x5a98, false, " ' . . . . "); - Write(0xa47a4d, false, ":'.."); - Write(0x9933, true, ". "); - Write(0xa47a4d, false, ".."); - Write(0x9933, true, ". "); - Write(0x66ff, true, "."); - Write(0xa47a4d, false, "''"); - Write(0x66ff, true, ". "); - Write(0xff0000, false, "': "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x5291, false, " . '. "); - Write(0xa47a4d, false, ": '' ''''.. "); - Write(0xff9900, true, ". "); - Write(0x66ff, true, "."); - Write(0xc74c30, false, "'"); - Write(0xa47a4d, false, ". "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0x4a8a, false, " . . ' . "); - Write(0xa47a4d, false, ": '..'."); - Write(0x9933, true, "."); - Write(0xa47a4d, false, ": "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0x4282, false, " ' . .. "); - Write(0xa47a4d, false, ": :'''.. ..'"); - Write(0x9933, true, "."); - Write(0xa47a4d, false, ": "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0x3b7b, false, "' ' . . . . "); - Write(0xa47a4d, false, ".' ..''"); - Write(0xff9900, true, ". "); - Write(0xff00ff, true, ". "); - Write(0xa47a4d, false, "'''"); - Write(0xff9900, true, "."); - Write(0xa47a4d, false, "...: "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0x3374, false, "' . .' . . ' "); - Write(0xa47a4d, false, ": ...''"); - Write(0xff9900, true, ". "); - Write(0xa47a4d, false, "..': "); - Write(0xff0000, false, "."); - Write(0xc74c30, false, "."); - Write(0xa47a4d, false, "..' "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0x2e6f, false, " ' . .. . "); - Write(0xff9900, true, "."); - Write(0x2e6f, false, ". "); - Write(0x66ff, true, ". "); - Write(0xa47a4d, false, ":'"); - Write(0xff0000, true, "."); - Write(0xa47a4d, false, "...''' "); - Write(0xc74c30, false, "'"); - Write(0xff0000, false, "'' "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0xa47a4d, false, "'.'. "); - Write(0x296b, false, " . "); - Write(0xff9900, true, "."); - Write(0xa47a4d, false, ":'. ....' "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0xa47a4d, false, ": "); - Write(0x2566, false, " . "); - Write(0x66ff, true, "."); - Write(0x2566, false, ". "); - Write(0xa47a4d, false, ": ' "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, ": "); - Write(0x2062, false, " . "); - Write(0xff9900, true, ". "); - Write(0x584338, false, "..' "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, "'. "); - Write(0x1b5e, false, " . "); - Write(0xff0000, true, ". "); - Write(0x584338, false, ": "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, "'. "); - Write(0x1759, false, ". . "); - Write(0x66ff, true, ". "); - Write(0x584338, false, ": "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, ": "); - Write(0x1255, false, ". "); - Write(0x66ff, true, ". "); - Write(0x584338, false, ": "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, "'. "); - Write(0xd51, false, "."); - Write(0xff9900, true, ". "); - Write(0x584338, false, ": "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, ": "); - Write(0xff9900, true, "."); - Write(0x584338, false, ".' "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, ": "); - Write(0xff9900, true, ". "); - Write(0x584338, false, ".' "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x584338, false, ":..: "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2021/calendar.svg b/2021/calendar.svg deleted file mode 100644 index 00500cbb7..000000000 --- a/2021/calendar.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  int y = 2021; -  -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   1 ** -         . .  . . '.. .  . ...   .     ..  ..''''   2 ** -      .     .     .  . '        .   '. .  :         3 ** - .    .        .. .      .   .. .' .  ....'         4 ** -    .     .      .         .. ..|\..''              5 ** -.'~    '  .  .     .       . :                      6 ** - '    . .  '    .  . .    .:'                       7 ** -' . .    ..    .'      ..  .'''''.....  ....        8 ** -    ' .     .   . .       :'... ...  .''.   ':      9 ** -                     . '. :   ''  ''''..  . .'.    10 ** - .      .         '    .  :             '..'..:    11 ** -      '  .     ..        :       :'''..   ..'.:    12 ** -'     '   .  .  .   .  .'    ..''.   . '''....:    13 ** -'    . .'   . .  '    : ...''. ..':   ....'        14 ** -  ' .      ..  . .. :'....'''    '''             15 ** -'.'.     .     .:'. ....'                          16 ** -   :  .      .. :  '                               17 ** -   :  .     . ..'                                  18 ** -   '.    . .  :                                    19 ** -    '. .  . . :                                    20 ** -      : .  . :                                     21 ** -      '. ..  :                                     22 ** -       :   ..'                                     23 ** -       : . .'                                      24 ** -       :..:                                        25 ** - - - - \ No newline at end of file diff --git a/2022/Day01/README.md b/2022/Day01/README.md deleted file mode 100644 index b0781b782..000000000 --- a/2022/Day01/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 1: Calorie Counting --- -Santa's reindeer typically eat regular reindeer food, but they need a lot of [magical energy](/2018/day/25) 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. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2022/day/1) description._ diff --git a/2022/Day01/Solution.cs b/2022/Day01/Solution.cs deleted file mode 100644 index 9d8903b67..000000000 --- a/2022/Day01/Solution.cs +++ /dev/null @@ -1,21 +0,0 @@ -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; -} diff --git a/2022/Day01/input.in b/2022/Day01/input.in deleted file mode 100644 index d53279bef..000000000 Binary files a/2022/Day01/input.in and /dev/null differ diff --git a/2022/Day01/input.refout b/2022/Day01/input.refout deleted file mode 100644 index 6a70f04e7..000000000 --- a/2022/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -72602 -207410 \ No newline at end of file diff --git a/2022/Day02/README.md b/2022/Day02/README.md deleted file mode 100644 index a25c2f63c..000000000 --- a/2022/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Rock Paper Scissors --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2022/day/2). \ No newline at end of file diff --git a/2022/Day02/Solution.cs b/2022/Day02/Solution.cs deleted file mode 100644 index eb6138c9e..000000000 --- a/2022/Day02/Solution.cs +++ /dev/null @@ -1,64 +0,0 @@ -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(); -} diff --git a/2022/Day02/input.in b/2022/Day02/input.in deleted file mode 100644 index d72a808b5..000000000 Binary files a/2022/Day02/input.in and /dev/null differ diff --git a/2022/Day02/input.refout b/2022/Day02/input.refout deleted file mode 100644 index d8861757f..000000000 --- a/2022/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -11449 -13187 \ No newline at end of file diff --git a/2022/Day03/README.md b/2022/Day03/README.md deleted file mode 100644 index a94f9ec2d..000000000 --- a/2022/Day03/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 3: Rucksack Reorganization --- -One Elf has the important job of loading all of the [rucksacks](https://en.wikipedia.org/wiki/Rucksack) 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](https://adventofcode.com/2022/day/3). \ No newline at end of file diff --git a/2022/Day03/Solution.cs b/2022/Day03/Solution.cs deleted file mode 100644 index 3817fc40b..000000000 --- a/2022/Day03/Solution.cs +++ /dev/null @@ -1,37 +0,0 @@ -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(); - -} diff --git a/2022/Day03/input.in b/2022/Day03/input.in deleted file mode 100644 index c05cdfe70..000000000 Binary files a/2022/Day03/input.in and /dev/null differ diff --git a/2022/Day03/input.refout b/2022/Day03/input.refout deleted file mode 100644 index 37436afd6..000000000 --- a/2022/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -8233 -2821 \ No newline at end of file diff --git a/2022/Day04/README.md b/2022/Day04/README.md deleted file mode 100644 index 12dcd50de..000000000 --- a/2022/Day04/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 4: Camp Cleanup --- -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](https://adventofcode.com/2022/day/4). \ No newline at end of file diff --git a/2022/Day04/Solution.cs b/2022/Day04/Solution.cs deleted file mode 100644 index b57b40cdc..000000000 --- a/2022/Day04/Solution.cs +++ /dev/null @@ -1,45 +0,0 @@ -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()) - ); - } -} diff --git a/2022/Day04/input.in b/2022/Day04/input.in deleted file mode 100644 index be3ffb735..000000000 Binary files a/2022/Day04/input.in and /dev/null differ diff --git a/2022/Day04/input.refout b/2022/Day04/input.refout deleted file mode 100644 index 41e98355e..000000000 --- a/2022/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -490 -921 \ No newline at end of file diff --git a/2022/Day05/README.md b/2022/Day05/README.md deleted file mode 100644 index 0ed9547fd..000000000 --- a/2022/Day05/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 5: Supply Stacks --- -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](https://adventofcode.com/2022/day/5). \ No newline at end of file diff --git a/2022/Day05/Solution.cs b/2022/Day05/Solution.cs deleted file mode 100644 index ebcf83ed7..000000000 --- a/2022/Day05/Solution.cs +++ /dev/null @@ -1,79 +0,0 @@ -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())); - } -} diff --git a/2022/Day05/input.in b/2022/Day05/input.in deleted file mode 100644 index fbba47b11..000000000 Binary files a/2022/Day05/input.in and /dev/null differ diff --git a/2022/Day05/input.refout b/2022/Day05/input.refout deleted file mode 100644 index 2345dbc00..000000000 --- a/2022/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -TDCHVHJTG -NGCMPJLHV \ No newline at end of file diff --git a/2022/Day06/README.md b/2022/Day06/README.md deleted file mode 100644 index e58f42a31..000000000 --- a/2022/Day06/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 6: Tuning Trouble --- -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](https://adventofcode.com/2022/day/6). \ No newline at end of file diff --git a/2022/Day06/Solution.cs b/2022/Day06/Solution.cs deleted file mode 100644 index 8b579a3b2..000000000 --- a/2022/Day06/Solution.cs +++ /dev/null @@ -1,17 +0,0 @@ -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); -} diff --git a/2022/Day06/input.in b/2022/Day06/input.in deleted file mode 100644 index 4addfad05..000000000 Binary files a/2022/Day06/input.in and /dev/null differ diff --git a/2022/Day06/input.refout b/2022/Day06/input.refout deleted file mode 100644 index 599bcdf7f..000000000 --- a/2022/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1987 -3059 \ No newline at end of file diff --git a/2022/Day07/README.md b/2022/Day07/README.md deleted file mode 100644 index dab501f18..000000000 --- a/2022/Day07/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 7: No Space Left On Device --- -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](https://adventofcode.com/2022/day/7). \ No newline at end of file diff --git a/2022/Day07/Solution.cs b/2022/Day07/Solution.cs deleted file mode 100644 index ec1e48c76..000000000 --- a/2022/Day07/Solution.cs +++ /dev/null @@ -1,37 +0,0 @@ -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(); - } -} diff --git a/2022/Day07/input.in b/2022/Day07/input.in deleted file mode 100644 index 4e7063aff..000000000 Binary files a/2022/Day07/input.in and /dev/null differ diff --git a/2022/Day07/input.refout b/2022/Day07/input.refout deleted file mode 100644 index 339c33d8e..000000000 --- a/2022/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1477771 -3579501 \ No newline at end of file diff --git a/2022/Day08/README.md b/2022/Day08/README.md deleted file mode 100644 index 95d1ac8d8..000000000 --- a/2022/Day08/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 8: Treetop Tree House --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2022/day/8). \ No newline at end of file diff --git a/2022/Day08/Solution.cs b/2022/Day08/Solution.cs deleted file mode 100644 index a8417d3b8..000000000 --- a/2022/Day08/Solution.cs +++ /dev/null @@ -1,67 +0,0 @@ -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); - } - } -} diff --git a/2022/Day08/input.in b/2022/Day08/input.in deleted file mode 100644 index a78bc6205..000000000 Binary files a/2022/Day08/input.in and /dev/null differ diff --git a/2022/Day08/input.refout b/2022/Day08/input.refout deleted file mode 100644 index f1ef5ceee..000000000 --- a/2022/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1763 -671160 \ No newline at end of file diff --git a/2022/Day09/README.md b/2022/Day09/README.md deleted file mode 100644 index 632053f96..000000000 --- a/2022/Day09/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 9: Rope Bridge --- -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](https://adventofcode.com/2022/day/9). \ No newline at end of file diff --git a/2022/Day09/Solution.cs b/2022/Day09/Solution.cs deleted file mode 100644 index 5dafcb4a8..000000000 --- a/2022/Day09/Solution.cs +++ /dev/null @@ -1,59 +0,0 @@ -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) - ); - } - } - } -} diff --git a/2022/Day09/input.in b/2022/Day09/input.in deleted file mode 100644 index 41d5b2cd2..000000000 Binary files a/2022/Day09/input.in and /dev/null differ diff --git a/2022/Day09/input.refout b/2022/Day09/input.refout deleted file mode 100644 index 3adcf13fb..000000000 --- a/2022/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6243 -2630 \ No newline at end of file diff --git a/2022/Day10/README.md b/2022/Day10/README.md deleted file mode 100644 index a779db6f6..000000000 --- a/2022/Day10/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 10: Cathode-Ray Tube --- -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](https://adventofcode.com/2022/day/10). \ No newline at end of file diff --git a/2022/Day10/Solution.cs b/2022/Day10/Solution.cs deleted file mode 100644 index f4f9feb3c..000000000 --- a/2022/Day10/Solution.cs +++ /dev/null @@ -1,48 +0,0 @@ -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]); - } - } - } -} \ No newline at end of file diff --git a/2022/Day10/input.in b/2022/Day10/input.in deleted file mode 100644 index a8df5acdf..000000000 Binary files a/2022/Day10/input.in and /dev/null differ diff --git a/2022/Day10/input.refout b/2022/Day10/input.refout deleted file mode 100644 index 6c5d9b53b..000000000 --- a/2022/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -14420 -RGLRBZAU \ No newline at end of file diff --git a/2022/Day11/README.md b/2022/Day11/README.md deleted file mode 100644 index 4af3f099e..000000000 --- a/2022/Day11/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 11: Monkey in the Middle --- -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](https://en.wikipedia.org/wiki/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](https://adventofcode.com/2022/day/11). \ No newline at end of file diff --git a/2022/Day11/Solution.cs b/2022/Day11/Solution.cs deleted file mode 100644 index b14695d12..000000000 --- a/2022/Day11/Solution.cs +++ /dev/null @@ -1,104 +0,0 @@ -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); -} diff --git a/2022/Day11/input.in b/2022/Day11/input.in deleted file mode 100644 index 45757b6fe..000000000 Binary files a/2022/Day11/input.in and /dev/null differ diff --git a/2022/Day11/input.refout b/2022/Day11/input.refout deleted file mode 100644 index 2d0fa87fe..000000000 --- a/2022/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -98280 -17673687232 \ No newline at end of file diff --git a/2022/Day12/README.md b/2022/Day12/README.md deleted file mode 100644 index e9b806206..000000000 --- a/2022/Day12/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 12: Hill Climbing Algorithm --- -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](https://adventofcode.com/2022/day/12). \ No newline at end of file diff --git a/2022/Day12/Solution.cs b/2022/Day12/Solution.cs deleted file mode 100644 index 5abad0c95..000000000 --- a/2022/Day12/Solution.cs +++ /dev/null @@ -1,106 +0,0 @@ -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}, - }; -} diff --git a/2022/Day12/input.in b/2022/Day12/input.in deleted file mode 100644 index 3d0235a30..000000000 Binary files a/2022/Day12/input.in and /dev/null differ diff --git a/2022/Day12/input.refout b/2022/Day12/input.refout deleted file mode 100644 index 1d199fe53..000000000 --- a/2022/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -517 -512 \ No newline at end of file diff --git a/2022/Day13/README.md b/2022/Day13/README.md deleted file mode 100644 index 9f7528ec9..000000000 --- a/2022/Day13/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 13: Distress Signal --- -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](https://adventofcode.com/2022/day/13). \ No newline at end of file diff --git a/2022/Day13/Solution.cs b/2022/Day13/Solution.cs deleted file mode 100644 index d9112895f..000000000 --- a/2022/Day13/Solution.cs +++ /dev/null @@ -1,56 +0,0 @@ -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); - } - } -} \ No newline at end of file diff --git a/2022/Day13/input.in b/2022/Day13/input.in deleted file mode 100644 index 6b9afc4f3..000000000 Binary files a/2022/Day13/input.in and /dev/null differ diff --git a/2022/Day13/input.refout b/2022/Day13/input.refout deleted file mode 100644 index c87e9bc48..000000000 --- a/2022/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -5340 -21276 \ No newline at end of file diff --git a/2022/Day14/README.md b/2022/Day14/README.md deleted file mode 100644 index 556d598a3..000000000 --- a/2022/Day14/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 14: Regolith Reservoir --- -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](https://adventofcode.com/2022/day/14). \ No newline at end of file diff --git a/2022/Day14/Solution.cs b/2022/Day14/Solution.cs deleted file mode 100644 index c291bd79d..000000000 --- a/2022/Day14/Solution.cs +++ /dev/null @@ -1,98 +0,0 @@ -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; - } -} diff --git a/2022/Day14/input.in b/2022/Day14/input.in deleted file mode 100644 index 63006eac6..000000000 Binary files a/2022/Day14/input.in and /dev/null differ diff --git a/2022/Day14/input.refout b/2022/Day14/input.refout deleted file mode 100644 index 3ca85d671..000000000 --- a/2022/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -719 -23390 \ No newline at end of file diff --git a/2022/Day15/README.md b/2022/Day15/README.md deleted file mode 100644 index 02671e443..000000000 --- a/2022/Day15/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 15: Beacon Exclusion Zone --- -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](https://adventofcode.com/2022/day/15). \ No newline at end of file diff --git a/2022/Day15/Solution.cs b/2022/Day15/Solution.cs deleted file mode 100644 index 2a9177aba..000000000 --- a/2022/Day15/Solution.cs +++ /dev/null @@ -1,132 +0,0 @@ -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); - } - } -} diff --git a/2022/Day15/input.in b/2022/Day15/input.in deleted file mode 100644 index 3eb58d8d4..000000000 Binary files a/2022/Day15/input.in and /dev/null differ diff --git a/2022/Day15/input.refout b/2022/Day15/input.refout deleted file mode 100644 index b2d8c6c5f..000000000 --- a/2022/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -4961647 -12274327017867 \ No newline at end of file diff --git a/2022/Day16/README.md b/2022/Day16/README.md deleted file mode 100644 index d6a429ff4..000000000 --- a/2022/Day16/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 16: Proboscidea Volcanium --- -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](https://adventofcode.com/2022/day/16). \ No newline at end of file diff --git a/2022/Day16/Solution.cs b/2022/Day16/Solution.cs deleted file mode 100644 index 9eed482cd..000000000 --- a/2022/Day16/Solution.cs +++ /dev/null @@ -1,142 +0,0 @@ -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; - } -} diff --git a/2022/Day16/input.in b/2022/Day16/input.in deleted file mode 100644 index f01ccf0c6..000000000 Binary files a/2022/Day16/input.in and /dev/null differ diff --git a/2022/Day16/input.refout b/2022/Day16/input.refout deleted file mode 100644 index 4f9328d24..000000000 --- a/2022/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1716 -2504 \ No newline at end of file diff --git a/2022/Day17/README.md b/2022/Day17/README.md deleted file mode 100644 index 01faa7ee4..000000000 --- a/2022/Day17/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 17: Pyroclastic Flow --- -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](https://adventofcode.com/2022/day/17). \ No newline at end of file diff --git a/2022/Day17/Solution.cs b/2022/Day17/Solution.cs deleted file mode 100644 index 07b91dc2b..000000000 --- a/2022/Day17/Solution.cs +++ /dev/null @@ -1,163 +0,0 @@ -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 }; - } -} diff --git a/2022/Day17/input.in b/2022/Day17/input.in deleted file mode 100644 index e90b84848..000000000 Binary files a/2022/Day17/input.in and /dev/null differ diff --git a/2022/Day17/input.refout b/2022/Day17/input.refout deleted file mode 100644 index 8ec213c77..000000000 --- a/2022/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3048 -1504093567249 \ No newline at end of file diff --git a/2022/Day18/README.md b/2022/Day18/README.md deleted file mode 100644 index 638baaf1f..000000000 --- a/2022/Day18/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 18: Boiling Boulders --- -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](https://adventofcode.com/2022/day/18). \ No newline at end of file diff --git a/2022/Day18/Solution.cs b/2022/Day18/Solution.cs deleted file mode 100644 index f6f3167e1..000000000 --- a/2022/Day18/Solution.cs +++ /dev/null @@ -1,81 +0,0 @@ -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 } - }; -} diff --git a/2022/Day18/input.in b/2022/Day18/input.in deleted file mode 100644 index ba1b7efca..000000000 Binary files a/2022/Day18/input.in and /dev/null differ diff --git a/2022/Day18/input.refout b/2022/Day18/input.refout deleted file mode 100644 index d5f15cd71..000000000 --- a/2022/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3496 -2064 \ No newline at end of file diff --git a/2022/Day19/README.md b/2022/Day19/README.md deleted file mode 100644 index a4de31aed..000000000 --- a/2022/Day19/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 19: Not Enough Minerals --- -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](https://en.wikipedia.org/wiki/Geode) around the pond. Perhaps you could use the obsidian to create some geode-cracking robots and break them open? - -Read the [full puzzle](https://adventofcode.com/2022/day/19). \ No newline at end of file diff --git a/2022/Day19/Solution.cs b/2022/Day19/Solution.cs deleted file mode 100644 index dd9aa2f47..000000000 --- a/2022/Day19/Solution.cs +++ /dev/null @@ -1,191 +0,0 @@ -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 - ); - } -} diff --git a/2022/Day19/input.in b/2022/Day19/input.in deleted file mode 100644 index e1861b7f3..000000000 Binary files a/2022/Day19/input.in and /dev/null differ diff --git a/2022/Day19/input.refout b/2022/Day19/input.refout deleted file mode 100644 index 6465eff2e..000000000 --- a/2022/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1565 -10672 \ No newline at end of file diff --git a/2022/Day20/README.md b/2022/Day20/README.md deleted file mode 100644 index 6a7c0a971..000000000 --- a/2022/Day20/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 20: Grove Positioning System --- -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](https://adventofcode.com/2022/day/20). \ No newline at end of file diff --git a/2022/Day20/Solution.cs b/2022/Day20/Solution.cs deleted file mode 100644 index 4d4020e8f..000000000 --- a/2022/Day20/Solution.cs +++ /dev/null @@ -1,53 +0,0 @@ -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 - ); - } -} diff --git a/2022/Day20/input.in b/2022/Day20/input.in deleted file mode 100644 index c78f4a139..000000000 Binary files a/2022/Day20/input.in and /dev/null differ diff --git a/2022/Day20/input.refout b/2022/Day20/input.refout deleted file mode 100644 index 616dba11d..000000000 --- a/2022/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3466 -9995532008348 \ No newline at end of file diff --git a/2022/Day21/README.md b/2022/Day21/README.md deleted file mode 100644 index cb5007081..000000000 --- a/2022/Day21/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 21: Monkey Math --- -The [monkeys](11) 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](https://adventofcode.com/2022/day/21). \ No newline at end of file diff --git a/2022/Day21/Solution.cs b/2022/Day21/Solution.cs deleted file mode 100644 index c2dd8c30c..000000000 --- a/2022/Day21/Solution.cs +++ /dev/null @@ -1,98 +0,0 @@ -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), - }; - } - } -} diff --git a/2022/Day21/input.in b/2022/Day21/input.in deleted file mode 100644 index 5bfa1ab05..000000000 Binary files a/2022/Day21/input.in and /dev/null differ diff --git a/2022/Day21/input.refout b/2022/Day21/input.refout deleted file mode 100644 index d73987de0..000000000 --- a/2022/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -282285213953670 -3699945358564 \ No newline at end of file diff --git a/2022/Day22/README.md b/2022/Day22/README.md deleted file mode 100644 index 5345553d8..000000000 --- a/2022/Day22/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 22: Monkey Map --- -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](https://adventofcode.com/2022/day/22). \ No newline at end of file diff --git a/2022/Day22/Solution.cs b/2022/Day22/Solution.cs deleted file mode 100644 index a5b6d2252..000000000 --- a/2022/Day22/Solution.cs +++ /dev/null @@ -1,190 +0,0 @@ -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; -} diff --git a/2022/Day22/input.in b/2022/Day22/input.in deleted file mode 100644 index 4f4bab86d..000000000 Binary files a/2022/Day22/input.in and /dev/null differ diff --git a/2022/Day22/input.refout b/2022/Day22/input.refout deleted file mode 100644 index 53417e24a..000000000 --- a/2022/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -47462 -137045 \ No newline at end of file diff --git a/2022/Day23/README.md b/2022/Day23/README.md deleted file mode 100644 index 1f35f8265..000000000 --- a/2022/Day23/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 23: Unstable Diffusion --- -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](https://adventofcode.com/2022/day/23). \ No newline at end of file diff --git a/2022/Day23/Solution.cs b/2022/Day23/Solution.cs deleted file mode 100644 index 0cf8656a3..000000000 --- a/2022/Day23/Solution.cs +++ /dev/null @@ -1,106 +0,0 @@ -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(); - -} diff --git a/2022/Day23/input.in b/2022/Day23/input.in deleted file mode 100644 index d3a51ed87..000000000 Binary files a/2022/Day23/input.in and /dev/null differ diff --git a/2022/Day23/input.refout b/2022/Day23/input.refout deleted file mode 100644 index 839729e7c..000000000 --- a/2022/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3923 -1019 \ No newline at end of file diff --git a/2022/Day24/README.md b/2022/Day24/README.md deleted file mode 100644 index 9f6df318c..000000000 --- a/2022/Day24/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 24: Blizzard Basin --- -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](https://adventofcode.com/2022/day/24). \ No newline at end of file diff --git a/2022/Day24/Solution.cs b/2022/Day24/Solution.cs deleted file mode 100644 index b946d4c4a..000000000 --- a/2022/Day24/Solution.cs +++ /dev/null @@ -1,130 +0,0 @@ -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] == '^' ? '^': - '.'; - } - } -} diff --git a/2022/Day24/input.in b/2022/Day24/input.in deleted file mode 100644 index def762768..000000000 Binary files a/2022/Day24/input.in and /dev/null differ diff --git a/2022/Day24/input.refout b/2022/Day24/input.refout deleted file mode 100644 index bcd70db75..000000000 --- a/2022/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -262 -785 \ No newline at end of file diff --git a/2022/Day25/README.md b/2022/Day25/README.md deleted file mode 100644 index 72f7a26e8..000000000 --- a/2022/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Full of Hot Air --- -As the expedition finally reaches the extraction point, several large [hot air balloons](https://en.wikipedia.org/wiki/Hot_air_balloon) 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](https://adventofcode.com/2022/day/25). \ No newline at end of file diff --git a/2022/Day25/Solution.cs b/2022/Day25/Solution.cs deleted file mode 100644 index dee3f9749..000000000 --- a/2022/Day25/Solution.cs +++ /dev/null @@ -1,54 +0,0 @@ -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; - } -} diff --git a/2022/Day25/input.in b/2022/Day25/input.in deleted file mode 100644 index 5aea1b822..000000000 Binary files a/2022/Day25/input.in and /dev/null differ diff --git a/2022/Day25/input.refout b/2022/Day25/input.refout deleted file mode 100644 index 1f574cb22..000000000 --- a/2022/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -2=--00--0220-0-21==1 \ No newline at end of file diff --git a/2022/README.md b/2022/README.md deleted file mode 100644 index d43fe552e..000000000 --- a/2022/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2022) -Check out https://adventofcode.com/2022. - - diff --git a/2022/SplashScreen.cs b/2022/SplashScreen.cs deleted file mode 100644 index 115bf10cc..000000000 --- a/2022/SplashScreen.cs +++ /dev/null @@ -1,838 +0,0 @@ -using System; - -namespace AdventOfCode.Y2022; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ $year = 2022\n "); - Write(0xcc00, false, "\n "); - Write(0x630031, false, " - "); - Write(0xffffff, false, "/\\"); - Write(0x630031, false, " - - - - - - - \n "); - Write(0xd64200, false, " - "); - Write(0xaaaaaa, false, "/ \\/\\"); - Write(0xd64200, false, " - - - - - - "); - Write(0xaaaaaa, false, "/\\ "); - Write(0xd64200, false, " - - \n "); - Write(0xaaaaaa, false, "/\\ \\ \\"); - Write(0xffc700, false, "- - - - - - - -"); - Write(0xaaaaaa, false, "/\\/ \\"); - Write(0xffc700, false, "- - - "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n "); - Write(0xaaaaaa, false, "/"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0xaaaaaa, false, "\\ /\\"); - Write(0x488813, false, "@"); - Write(0xaaaaaa, false, "\\"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@@##"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "@@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@#"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "#@"); - Write(0x488813, false, "##"); - Write(0x1461f, false, "@ "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "."); - Write(0x427322, false, "'"); - Write(0x7fbd39, false, " '."); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "##@"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "@@@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "##@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@ "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "'. "); - Write(0x4d8b03, false, ".'"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@@"); - Write(0xd0b376, false, "."); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "@@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@#"); - Write(0x4d8b03, false, "@@"); - Write(0xffffff, false, "()))"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@ "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "#"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0xd0b376, false, "."); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "#"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "##"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x685c46, false, "|"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "# "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0xd0b376, false, "."); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "#"); - Write(0x427322, false, "#@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0xd0b376, false, "."); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@"); - Write(0x5eabb4, false, "~~"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@#"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "#@#"); - Write(0x488813, false, "#"); - Write(0x1461f, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@# "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0x488813, false, "@@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x685c46, false, "|"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "#"); - Write(0x5eabb4, false, "."); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@@#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@@"); - Write(0x5eabb4, false, "~~~~ "); - Write(0xaaaaaa, false, ".~'"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#@"); - Write(0x4d8b03, false, "#@#"); - Write(0x488813, false, "@@"); - Write(0x1461f, false, "#"); - Write(0x427322, false, "@ "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "@@"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@@"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x5eabb4, false, "."); - Write(0x4d8b03, false, "@@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@#"); - Write(0x427322, false, "@@@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x5eabb4, false, "~~ "); - Write(0xaaaaaa, false, "/"); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, "\\ "); - Write(0x488813, false, "@@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#@@"); - Write(0x7fbd39, false, "@#"); - Write(0x427322, false, "@#@ "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0x7fbd39, false, "#@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0xd0b376, false, "."); - Write(0x1461f, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x5eabb4, false, ".."); - Write(0x4d8b03, false, "@@"); - Write(0x7fbd39, false, "#@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@ "); - Write(0xaaaaaa, false, "/ "); - Write(0xe6410b, false, "/ "); - Write(0xaaaaaa, false, "\\ "); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x1461f, false, "#@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@@# "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@@@@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x5eabb4, false, ".."); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "@@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@"); - Write(0xaaaaaa, false, "/ "); - Write(0xe6410b, false, "/ \\ "); - Write(0xaaaaaa, false, "\\"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@ "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "_"); - Write(0x5eabb4, false, ".~."); - Write(0x427322, false, "_"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@#"); - Write(0xaaaaaa, false, ".'"); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, ".'"); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, ". "); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@@# "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@@"); - Write(0x488813, false, "@"); - Write(0xd0b376, false, "."); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "#"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x1461f, false, "@ "); - Write(0xffffff, false, "||| "); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "#@"); - Write(0x488813, false, "@#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0xaaaaaa, false, "'."); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, ".'"); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, ". "); - Write(0xe6410b, false, "\\"); - Write(0xaaaaaa, false, "'."); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "# "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@#"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "#"); - Write(0xffffff, false, "~~~"); - Write(0x1461f, false, "#"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@#"); - Write(0x488813, false, "#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0xaaaaaa, false, "' ..'.'."); - Write(0xe6410b, false, "\\"); - Write(0xaaaaaa, false, ". . "); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@@ "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "#@"); - Write(0x4d8b03, false, "@@@@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x5eabb4, false, ".~~."); - Write(0x427322, false, "@"); - Write(0x488813, false, "#@"); - Write(0x1461f, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "#@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "##"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0xaaaaaa, false, " .'."); - Write(0xe6410b, false, "~~~"); - Write(0xaaaaaa, false, "' "); - Write(0x7fbd39, false, "@"); - Write(0xaaaaaa, false, "'"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "#@ "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "#"); - Write(0x1461f, false, "@"); - Write(0xd0b376, false, "."); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x5eabb4, false, ".~~."); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@@"); - Write(0x427322, false, "##"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "##"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@ "); - Write(0xe6410b, false, "~~~~~"); - Write(0xaaaaaa, false, ".."); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "##"); - Write(0x7fbd39, false, "#"); - Write(0x1461f, false, "# "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0x7fbd39, false, "##"); - Write(0x488813, false, "#"); - Write(0xd0b376, false, "."); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "#"); - Write(0x5eabb4, false, ".~~."); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@#"); - Write(0x427322, false, "#@"); - Write(0x488813, false, "##"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "#"); - Write(0x427322, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@@"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0xaaaaaa, false, ".'"); - Write(0xe6410b, false, "/ ~~~ \\"); - Write(0xaaaaaa, false, "' "); - Write(0x488813, false, "@#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@ "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "#"); - Write(0xd0b376, false, "."); - Write(0x488813, false, "@"); - Write(0x427322, false, "@ "); - Write(0xaaaaaa, false, "_"); - Write(0xd0b376, false, "|%%%=%%|"); - Write(0xaaaaaa, false, "_ "); - Write(0x488813, false, "@#"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "#@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@#"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0xaaaaaa, false, ". "); - Write(0xe6410b, false, "~ /"); - Write(0xaaaaaa, false, "' .'"); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, "."); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "# "); - Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "#@"); - Write(0x488813, false, "@@"); - Write(0x1461f, false, "#"); - Write(0xd0b376, false, ".."); - Write(0xaaaaaa, false, "/ \\"); - Write(0x5eabb4, false, ".~~."); - Write(0xaaaaaa, false, "/ \\"); - Write(0xd0b376, false, "....."); - Write(0x488813, false, "@@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@@"); - Write(0xaaaaaa, false, "' "); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, ".''"); - Write(0xe6410b, false, "/"); - Write(0xaaaaaa, false, "' "); - Write(0xe6410b, false, "\\"); - Write(0xaaaaaa, false, "' "); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x7fbd39, false, "# "); - Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0x1461f, false, "@"); - Write(0x488813, false, "@"); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@#@"); - Write(0x427322, false, "@@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0x5eabb4, false, ".~~."); - Write(0x4d8b03, false, "#"); - Write(0x427322, false, "#"); - Write(0x1461f, false, "#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0xd0b376, false, "."); - Write(0x4d8b03, false, "@@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0xaaaaaa, false, "'."); - Write(0xe6410b, false, "/"); - Write(0xaaaaaa, false, "."); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, " ."); - Write(0xe6410b, false, "\\"); - Write(0xaaaaaa, false, "'."); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, " '. "); - Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "#"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "#"); - Write(0x488813, false, "@#"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "#"); - Write(0x7fbd39, false, "@@"); - Write(0x5eabb4, false, ".~~."); - Write(0x7fbd39, false, "@@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0xd0b376, false, ".."); - Write(0x4d8b03, false, "@"); - Write(0x685c46, false, "|"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "#"); - Write(0xaaaaaa, false, "' "); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, ". "); - Write(0xe6410b, false, "\\"); - Write(0xaaaaaa, false, "."); - Write(0xe6410b, false, "\\ \\ \\"); - Write(0xaaaaaa, false, "."); - Write(0xe6410b, false, "~~~"); - Write(0xaaaaaa, false, ". "); - Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0x488813, false, "#"); - Write(0x4d8b03, false, "#"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "##"); - Write(0x4d8b03, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x1461f, false, "@"); - Write(0x427322, false, "@@"); - Write(0x5eabb4, false, ".~~."); - Write(0x7fbd39, false, "#"); - Write(0x427322, false, "@"); - Write(0xd0b376, false, "."); - Write(0xeeeeee, false, "/\\"); - Write(0xd0b376, false, ".'"); - Write(0x427322, false, "@@"); - Write(0x1461f, false, "#"); - Write(0x488813, false, "##"); - Write(0x4d8b03, false, "@"); - Write(0x488813, false, "@"); - Write(0x1461f, false, "@"); - Write(0xaaaaaa, false, "'.' .'"); - Write(0xe6410b, false, "/"); - Write(0xaaaaaa, false, "."); - Write(0x488813, false, "@"); - Write(0xaaaaaa, false, ". "); - Write(0xe6410b, false, "/"); - Write(0xaaaaaa, false, "'."); - Write(0xe6410b, false, "~~~ "); - Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0x7fbd39, false, "#"); - Write(0x685c46, false, "|"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x1461f, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "@@"); - Write(0x488813, false, "#"); - Write(0x7fbd39, false, "@"); - Write(0xd0b376, false, ".'"); - Write(0x5eabb4, false, " ~ "); - Write(0xd0b376, false, "'."); - Write(0xeeeeee, false, "/\\"); - Write(0xd0b376, false, "'."); - Write(0xeeeeee, false, "/\\"); - Write(0xd0b376, false, "' ."); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "#@"); - Write(0x427322, false, "@@"); - Write(0x7fbd39, false, "@@"); - Write(0xaaaaaa, false, "' "); - Write(0xe6410b, false, "/\\"); - Write(0xaaaaaa, false, " . "); - Write(0xe6410b, false, "/"); - Write(0xaaaaaa, false, "'. ..' "); - Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x427322, false, "@"); - Write(0x4d8b03, false, "@"); - Write(0x7fbd39, false, "#@@"); - Write(0xd0b376, false, "_/"); - Write(0x5eabb4, false, " ~ ~ "); - Write(0xd0b376, false, "\\ ' '. '.'."); - Write(0x1461f, false, "#"); - Write(0x4d8b03, false, "@@@ "); - Write(0xe6410b, false, "/ \\ \\ "); - Write(0x427322, false, "@"); - Write(0x488813, false, "@"); - Write(0x7fbd39, false, "@"); - Write(0x427322, false, "@ "); - Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0xd0b376, false, "-~------'"); - Write(0x5eabb4, false, " ~ ~ "); - Write(0xd0b376, false, "'--~-----~-~----___________-- "); - Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); - Write(0x5eabb4, false, " ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "); - Write(0xcccccc, false, " 1 "); - Write(0xffff66, false, "**\n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2022/calendar.svg b/2022/calendar.svg deleted file mode 100644 index 7b4b0c60b..000000000 --- a/2022/calendar.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  $year = 2022 -  -  - /\ -  -        -       -     -      -    -           - - /  \/\  -    -     -  -    -   -  /\   -     -        - /\    \ \-  - -   -   -    - -  -/\/  \-   -  -   25 ** -/@#\   /\@\@@@#@@@###@#@@@###@####@@#@@@@#@@#@##@  24 ** -@@@.' '.@@#@@@@##@@@#@#@@@#@@#@@@@@#@#@@@@###@@#@  23 ** -@@@'. .'@@@@.@@@@@@@@#@###@@@@@@@#@@#@#@@()))@@#@  22 ** -@@@@@@#@@#@#@@@#@@.@####@@#@@#@#@#@##@@#@@###@|@#  21 ** -@#@##.@@@@#@###@@@@#@##@.##@~~@@#@@@##@###@@#@@@#  20 ** -@@@#|@@#@@#@#.@@#@@@@#@@@@@~~~~ .~'##@@@#@#@#@@#@  19 ** -@#@@#@@@@@##@@.@@@#@@@#@@@@@~~ /~\ @@@@#@#@@@#@#@  18 ** -#@@#.#@@@@#@@@@..@@#@###@@#@@ / / \ ##@@@##@@@@@#  17 ** -@##@@#@@@@@#@@@@..#@#@@@@@@#@/ / \ \@@@@@@###@@@@  16 ** -###@#@@@@@###@@_.~._@#@@##@#.'/\.'~. @@@@@@@@@@@#  15 ** -@@@.@@@@@@@###@ ||| @#@@#@@'.~.'~\'.@@##@@#@@##  14 ** -@@@@@@@#@#@@@@@#~~~#@@@##@#@' ..'.'.\. . #@@###@@  13 ** -@@@@@#@@@@@@@@.~~.@#@##@#@####@@@ .'.~~~@'@#@#@  12 ** -##@.@#@@@@@@.~~.@@@@#@@@##@@####@@  ~~~~~..@@####  11 ** -###.#@@@@@#.~~.@@##@##@@##@#@@#@@.'/ ~~~ \@#@@@  10 ** -@@##.@@ _|%%%=%%|_ @#@#@@@#@@@@#~ /' .'/\.@@@@#   9 ** -#@@@#../  \.~~./  \.....@@#@##@@@/\.''/\@@#   8 ** -@@@@@#@@@@@.~~.###@@#@@@.@@@@@@@'././\ .\'./\ '.    7 ** -@@@#@#@#@#@@.~~.@@@@@@@..@|@@@#~\.\  \ \.~~~.   6 ** -@@##@###@@@@@.~~.#@./\.'@@###@@@'.' .'/.@/'.~~~   5 ** -#|@@@@@@@#@.' ~  './\'./\' .@#@@@@@/\ . /'. ..'   4 ** -@#@@@@#@@_/ ~   ~  \ ' '. '.'.#@@@  /  \  \  @@@@   3 ** --~------'    ~    ~ '--~-----~-~----___________--   2 ** -  ~    ~  ~      ~     ~ ~   ~     ~  ~  ~   ~      1 ** - - - - \ No newline at end of file diff --git a/2023/Day01/README.md b/2023/Day01/README.md index 3c9e69343..1b3b3e6a0 100644 --- a/2023/Day01/README.md +++ b/2023/Day01/README.md @@ -1,6 +1,50 @@ +original source: [https://adventofcode.com/2023/day/1](https://adventofcode.com/2023/day/1) ## --- Day 1: Trebuchet?! --- Something is wrong with global snow production, and you've been selected to take a look. The Elves have even given you a map; on it, they've used stars to mark the top fifty locations that are likely to be having problems. You've been doing this long enough to know that to restore snow operations, you need to check all fifty stars by December 25th. -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2023/day/1) description._ +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! + +You try to ask why they can't just use a [weather machine](/2015/day/1) ("not powerful enough") and where they're even sending you ("the sky") and why your map looks mostly blank ("you sure ask a lot of questions") and hang on did you just say the sky ("of course, where do you think snow comes from") when you realize that the Elves are already loading you into a [trebuchet](https://en.wikipedia.org/wiki/Trebuchet) ("please hold still, we need to strap you in"). + +As they're making the final adjustments, they discover that their calibration document (your puzzle input) has been amended by a very young Elf who was apparently just excited to show off her art skills. Consequently, the Elves are having trouble reading the values on the document. + +The newly-improved calibration document consists of lines of text; each line originally contained a specific calibration value that the Elves now need to recover. On each line, the calibration value can be found by combining the first digit and the last digit (in that order) to form a single two-digit number. + +For example: + +
+1abc2
+pqr3stu8vwx
+a1b2c3d4e5f
+treb7uchet
+
+
+ +In this example, the calibration values of these four lines are 12, 38, 15, and 77. Adding these together produces 142. + +Consider your entire calibration document. What is the sum of all of the calibration values? + + +## --- Part Two --- +Your calculation isn't quite right. It looks like some of the digits are actually spelled out with letters: one, two, three, four, five, six, seven, eight, and nine also count as valid "digits". + +Equipped with this new information, you now need to find the real first and last digit on each line. For example: + +
+two1nine
+eightwothree
+abcone2threexyz
+xtwone3four
+4nineeightseven2
+zoneight234
+7pqrstsixteen
+
+
+ +In this example, the calibration values are 29, 83, 13, 24, 42, 14, and 76. Adding these together produces 281. + +What is the sum of all of the calibration values? + + diff --git a/2023/Day01/Solution.cs b/2023/Day01/Solution.cs index f2757dd57..5f03d966a 100644 --- a/2023/Day01/Solution.cs +++ b/2023/Day01/Solution.cs @@ -1,34 +1,172 @@ 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) - }; +class Solution : Solver +{ + public object PartOne(string[] input) + { + int sum = 0; + + foreach (string line in input) + { + string firstNumber = ""; + string lastNumber = ""; + + for (int i = 0; i < line.Length; i++) + { + if (firstNumber == "" && char.IsNumber(line[i])) + { + firstNumber = line[i].ToString(); + } + int reverseIndex = line.Length - 1 - i; + if (lastNumber == "" && char.IsNumber(line[reverseIndex])) + { + lastNumber = line[reverseIndex].ToString(); + } + } + + sum += int.TryParse(firstNumber + lastNumber, out int number) ? number : 0; + } + + return sum; + } + + public object PartTwo(string[] input) + { + int sum = 0; + + foreach (string line in input) + { + string firstNumber = ""; + string lastNumber = ""; + + for (int i = 0; i < line.Length; i++) + { + if (firstNumber == "") + { + TryParseWrittenNumber(line, i, false, out firstNumber); + + if (char.IsNumber(line[i])) + { + firstNumber = line[i].ToString(); + } + else + { + TryParseWrittenNumber(line, i, false, out firstNumber); + } + } + int reverseIndex = line.Length - 1 - i; + if (lastNumber == "") + { + if (char.IsNumber(line[reverseIndex])) + { + lastNumber = line[reverseIndex].ToString(); + } + else + { + TryParseWrittenNumber(line, reverseIndex, true, out lastNumber); + } + } + } + + sum += int.TryParse(firstNumber + lastNumber, out int number) ? number : 0; + } + + return sum; + } + + private bool TryParseWrittenNumber(string line, int startIndex, bool reversed, out string number) + { + number = ""; + bool hasRoomFor3 = line.Length >= startIndex + 3; + bool hasReversedRoomFor3 = reversed && startIndex - 3 >= -1; + bool hasRoomFor4 = line.Length >= startIndex + 4; + bool hasReversedRoomFor4 = reversed && startIndex - 4 >= -1; + bool hasRoomFor5 = line.Length >= startIndex + 5; + bool hasReversedRoomFor5 = reversed && startIndex - 5 >= -1; + + if (hasRoomFor3) + { + number = ParseWritten3LetterNumber(line.Substring(startIndex, 3)); + if (number != "") + { + return true; + } + } + if (hasReversedRoomFor3) + { + number = ParseWritten3LetterNumber(line.Substring(startIndex - (3 - 1), 3)); + if (number != "") + { + return true; + } + } + if (hasRoomFor4) + { + number = ParseWritten4LetterNumber(line.Substring(startIndex, 4)); + if (number != "") + { + return true; + } + } + if (hasReversedRoomFor4) + { + number = ParseWritten4LetterNumber(line.Substring(startIndex - (4 - 1), 4)); + if (number != "") + { + return true; + } + } + if (hasRoomFor5) + { + number = ParseWritten5LetterNumber(line.Substring(startIndex, 5)); + if (number != "") + { + return true; + } + } + if (hasReversedRoomFor5) + { + number = ParseWritten5LetterNumber(line.Substring(startIndex - (5 - 1), 5)); + if (number != "") + { + return true; + } + } + + return false; + } + + private string ParseWritten3LetterNumber(string line) + { + return line switch + { + "one" => "1", + "two" => "2", + "six" => "6", + _ => "" + }; + } + + private string ParseWritten4LetterNumber(string line) + { + return line switch + { + "four" => "4", + "five" => "5", + "nine" => "9", + _ => "" + }; + } + + private string ParseWritten5LetterNumber(string line) + { + return line switch + { + "three" => "3", + "seven" => "7", + "eight" => "8", + _ => "" + }; + } } diff --git a/2023/Day01/illustration.jpeg b/2023/Day01/illustration.jpeg deleted file mode 100644 index 2764a9495..000000000 Binary files a/2023/Day01/illustration.jpeg and /dev/null differ diff --git a/2023/Day01/input.in b/2023/Day01/input.in index 39a4d9fd9..07f31a491 100644 Binary files a/2023/Day01/input.in and b/2023/Day01/input.in differ diff --git a/2023/Day01/input.refout b/2023/Day01/input.refout index 1ba50a3f0..57fba15bc 100644 --- a/2023/Day01/input.refout +++ b/2023/Day01/input.refout @@ -1,2 +1,2 @@ -55447 -54706 \ No newline at end of file +55029 +55686 \ No newline at end of file diff --git a/2023/Day01/input.refouts b/2023/Day01/input.refouts new file mode 100644 index 000000000..352e80f60 --- /dev/null +++ b/2023/Day01/input.refouts @@ -0,0 +1 @@ +55029 \ No newline at end of file diff --git a/2023/Day02/README.md b/2023/Day02/README.md deleted file mode 100644 index 38fee8d3d..000000000 --- a/2023/Day02/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 2: Cube Conundrum --- -The task description is copyrighted, but it's available [here](https://adventofcode.com/2023/day/2). - -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. diff --git a/2023/Day02/Solution.cs b/2023/Day02/Solution.cs deleted file mode 100644 index a6f6a541e..000000000 --- a/2023/Day02/Solution.cs +++ /dev/null @@ -1,39 +0,0 @@ -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); -} diff --git a/2023/Day02/illustration.jpeg b/2023/Day02/illustration.jpeg deleted file mode 100644 index 78bdd14ad..000000000 Binary files a/2023/Day02/illustration.jpeg and /dev/null differ diff --git a/2023/Day02/input.in b/2023/Day02/input.in deleted file mode 100644 index b84b045ef..000000000 Binary files a/2023/Day02/input.in and /dev/null differ diff --git a/2023/Day02/input.refout b/2023/Day02/input.refout deleted file mode 100644 index 8b837a188..000000000 --- a/2023/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2076 -70950 \ No newline at end of file diff --git a/2023/Day03/README.md b/2023/Day03/README.md deleted file mode 100644 index ad0fcf171..000000000 --- a/2023/Day03/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 3: Gear Ratios --- -Let's revisit the problem description [here](https://adventofcode.com/2023/day/3). - -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. diff --git a/2023/Day03/Solution.cs b/2023/Day03/Solution.cs deleted file mode 100644 index 4d216e2d1..000000000 --- a/2023/Day03/Solution.cs +++ /dev/null @@ -1,56 +0,0 @@ -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); -} diff --git a/2023/Day03/illustration.jpeg b/2023/Day03/illustration.jpeg deleted file mode 100644 index c31a3973a..000000000 Binary files a/2023/Day03/illustration.jpeg and /dev/null differ diff --git a/2023/Day03/input.in b/2023/Day03/input.in deleted file mode 100644 index bc09e2783..000000000 Binary files a/2023/Day03/input.in and /dev/null differ diff --git a/2023/Day03/input.refout b/2023/Day03/input.refout deleted file mode 100644 index 7b8c558ce..000000000 --- a/2023/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -520019 -75519888 \ No newline at end of file diff --git a/2023/Day04/README.md b/2023/Day04/README.md deleted file mode 100644 index 74724c9ce..000000000 --- a/2023/Day04/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 4: Scratchcards --- -The original problem description is available [here](https://adventofcode.com/2023/day/4). - -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. diff --git a/2023/Day04/Solution.cs b/2023/Day04/Solution.cs deleted file mode 100644 index ddffbb15f..000000000 --- a/2023/Day04/Solution.cs +++ /dev/null @@ -1,40 +0,0 @@ -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()); - } -} diff --git a/2023/Day04/illustration.jpeg b/2023/Day04/illustration.jpeg deleted file mode 100644 index 04e0b6e6d..000000000 Binary files a/2023/Day04/illustration.jpeg and /dev/null differ diff --git a/2023/Day04/input.in b/2023/Day04/input.in deleted file mode 100644 index b51722da4..000000000 Binary files a/2023/Day04/input.in and /dev/null differ diff --git a/2023/Day04/input.refout b/2023/Day04/input.refout deleted file mode 100644 index 47ee47a63..000000000 --- a/2023/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -21558 -10425665 \ No newline at end of file diff --git a/2023/Day05/README.md b/2023/Day05/README.md deleted file mode 100644 index f46ab5529..000000000 --- a/2023/Day05/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## --- Day 5: If You Give A Seed A Fertilizer --- -Visit the Advent of Code website for the problem statement [here](https://adventofcode.com/2023/day/5). - -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. diff --git a/2023/Day05/Solution.cs b/2023/Day05/Solution.cs deleted file mode 100644 index a4e79f69a..000000000 --- a/2023/Day05/Solution.cs +++ /dev/null @@ -1,78 +0,0 @@ -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(); -} - diff --git a/2023/Day05/illustration.jpeg b/2023/Day05/illustration.jpeg deleted file mode 100644 index 228173ece..000000000 Binary files a/2023/Day05/illustration.jpeg and /dev/null differ diff --git a/2023/Day05/input.in b/2023/Day05/input.in deleted file mode 100644 index 750c9fa34..000000000 Binary files a/2023/Day05/input.in and /dev/null differ diff --git a/2023/Day05/input.refout b/2023/Day05/input.refout deleted file mode 100644 index 5948e332e..000000000 --- a/2023/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -806029445 -59370572 \ No newline at end of file diff --git a/2023/Day06/README.md b/2023/Day06/README.md deleted file mode 100644 index 474ec2d20..000000000 --- a/2023/Day06/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## --- Day 6: Wait For It --- -If you are not familiar with the problem, you can read it [here](https://adventofcode.com/2023/day/6). - -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. diff --git a/2023/Day06/Solution.cs b/2023/Day06/Solution.cs deleted file mode 100644 index 2527f5238..000000000 --- a/2023/Day06/Solution.cs +++ /dev/null @@ -1,51 +0,0 @@ -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(); -} diff --git a/2023/Day06/illustration.jpeg b/2023/Day06/illustration.jpeg deleted file mode 100644 index 04ff19cd6..000000000 Binary files a/2023/Day06/illustration.jpeg and /dev/null differ diff --git a/2023/Day06/input.in b/2023/Day06/input.in deleted file mode 100644 index 0b9bbe9b0..000000000 Binary files a/2023/Day06/input.in and /dev/null differ diff --git a/2023/Day06/input.refout b/2023/Day06/input.refout deleted file mode 100644 index 578621b2f..000000000 --- a/2023/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1710720 -35349468 \ No newline at end of file diff --git a/2023/Day07/README.md b/2023/Day07/README.md deleted file mode 100644 index 284290c62..000000000 --- a/2023/Day07/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 7: Camel Cards --- -Those who need a refresh can read the problem [here](https://adventofcode.com/2023/day/7). - -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. diff --git a/2023/Day07/Solution.cs b/2023/Day07/Solution.cs deleted file mode 100644 index ed51ade2b..000000000 --- a/2023/Day07/Solution.cs +++ /dev/null @@ -1,50 +0,0 @@ -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(); - } -} diff --git a/2023/Day07/illustration.jpeg b/2023/Day07/illustration.jpeg deleted file mode 100644 index beb93d335..000000000 Binary files a/2023/Day07/illustration.jpeg and /dev/null differ diff --git a/2023/Day07/input.in b/2023/Day07/input.in deleted file mode 100644 index 9eb0cdbec..000000000 Binary files a/2023/Day07/input.in and /dev/null differ diff --git a/2023/Day07/input.refout b/2023/Day07/input.refout deleted file mode 100644 index 4c8a6a1f8..000000000 --- a/2023/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -251806792 -252113488 \ No newline at end of file diff --git a/2023/Day08/README.md b/2023/Day08/README.md deleted file mode 100644 index b460559c3..000000000 --- a/2023/Day08/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## --- Day 8: Haunted Wasteland --- -The task description is copyrighted, but it's available [here](https://adventofcode.com/2023/day/8). - -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. diff --git a/2023/Day08/Solution.cs b/2023/Day08/Solution.cs deleted file mode 100644 index bcbaa1b62..000000000 --- a/2023/Day08/Solution.cs +++ /dev/null @@ -1,46 +0,0 @@ -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)); -} diff --git a/2023/Day08/illustration.jpeg b/2023/Day08/illustration.jpeg deleted file mode 100644 index f4243ea87..000000000 Binary files a/2023/Day08/illustration.jpeg and /dev/null differ diff --git a/2023/Day08/input.in b/2023/Day08/input.in deleted file mode 100644 index 5957b65fa..000000000 Binary files a/2023/Day08/input.in and /dev/null differ diff --git a/2023/Day08/input.refout b/2023/Day08/input.refout deleted file mode 100644 index 0b408f523..000000000 --- a/2023/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -14893 -10241191004509 \ No newline at end of file diff --git a/2023/Day09/README.md b/2023/Day09/README.md deleted file mode 100644 index c7e7b925b..000000000 --- a/2023/Day09/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## --- Day 9: Mirage Maintenance --- -Let's revisit the problem description [here](https://adventofcode.com/2023/day/9). - -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. diff --git a/2023/Day09/Solution.cs b/2023/Day09/Solution.cs deleted file mode 100644 index ccdd7e07d..000000000 --- a/2023/Day09/Solution.cs +++ /dev/null @@ -1,29 +0,0 @@ -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()); -} diff --git a/2023/Day09/illustration.jpeg b/2023/Day09/illustration.jpeg deleted file mode 100644 index aa73a2304..000000000 Binary files a/2023/Day09/illustration.jpeg and /dev/null differ diff --git a/2023/Day09/input.in b/2023/Day09/input.in deleted file mode 100644 index f1eab021d..000000000 Binary files a/2023/Day09/input.in and /dev/null differ diff --git a/2023/Day09/input.refout b/2023/Day09/input.refout deleted file mode 100644 index 3722f18b4..000000000 --- a/2023/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2101499000 -1089 \ No newline at end of file diff --git a/2023/Day10/README.md b/2023/Day10/README.md deleted file mode 100644 index 258eb534c..000000000 --- a/2023/Day10/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## --- Day 10: Pipe Maze --- -The original problem description is available [here](https://adventofcode.com/2023/day/10). - -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. diff --git a/2023/Day10/Solution.cs b/2023/Day10/Solution.cs deleted file mode 100644 index 5a5574182..000000000 --- a/2023/Day10/Solution.cs +++ /dev/null @@ -1,91 +0,0 @@ -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(); - } -} diff --git a/2023/Day10/illustration.jpeg b/2023/Day10/illustration.jpeg deleted file mode 100644 index 032b77df4..000000000 Binary files a/2023/Day10/illustration.jpeg and /dev/null differ diff --git a/2023/Day10/input.in b/2023/Day10/input.in deleted file mode 100644 index c14d4cdbf..000000000 Binary files a/2023/Day10/input.in and /dev/null differ diff --git a/2023/Day10/input.refout b/2023/Day10/input.refout deleted file mode 100644 index 021280b74..000000000 --- a/2023/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6613 -511 \ No newline at end of file diff --git a/2023/Day11/README.md b/2023/Day11/README.md deleted file mode 100644 index 25ac9d866..000000000 --- a/2023/Day11/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 11: Cosmic Expansion --- -Visit the Advent of Code website for the problem statement[here](https://adventofcode.com/2023/day/11). - -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. - diff --git a/2023/Day11/Solution.cs b/2023/Day11/Solution.cs deleted file mode 100644 index f7ea4403b..000000000 --- a/2023/Day11/Solution.cs +++ /dev/null @@ -1,52 +0,0 @@ -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); -} diff --git a/2023/Day11/illustration.jpeg b/2023/Day11/illustration.jpeg deleted file mode 100644 index 542eb6e96..000000000 Binary files a/2023/Day11/illustration.jpeg and /dev/null differ diff --git a/2023/Day11/input.in b/2023/Day11/input.in deleted file mode 100644 index 8ed93ddcc..000000000 Binary files a/2023/Day11/input.in and /dev/null differ diff --git a/2023/Day11/input.refout b/2023/Day11/input.refout deleted file mode 100644 index 3afa29a0c..000000000 --- a/2023/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -9795148 -650672493820 \ No newline at end of file diff --git a/2023/Day12/README.md b/2023/Day12/README.md deleted file mode 100644 index c5e3c6722..000000000 --- a/2023/Day12/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 12: Hot Springs --- -If you are not familiar with the problem, you can read i [here](https://adventofcode.com/2023/day/12). - -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. - diff --git a/2023/Day12/Solution.cs b/2023/Day12/Solution.cs deleted file mode 100644 index 4207d0786..000000000 --- a/2023/Day12/Solution.cs +++ /dev/null @@ -1,95 +0,0 @@ -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); - } - } -} diff --git a/2023/Day12/illustration.jpeg b/2023/Day12/illustration.jpeg deleted file mode 100644 index 21c6ccdb3..000000000 Binary files a/2023/Day12/illustration.jpeg and /dev/null differ diff --git a/2023/Day12/input.in b/2023/Day12/input.in deleted file mode 100644 index c3211f2b3..000000000 Binary files a/2023/Day12/input.in and /dev/null differ diff --git a/2023/Day12/input.refout b/2023/Day12/input.refout deleted file mode 100644 index 0bf985d39..000000000 --- a/2023/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -7307 -3415570893842 \ No newline at end of file diff --git a/2023/Day13/README.md b/2023/Day13/README.md deleted file mode 100644 index 5ed6b2d66..000000000 --- a/2023/Day13/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 13: Point of Incidence --- -Those who need a refresh can read the problem [here](https://adventofcode.com/2023/day/13). - -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. - diff --git a/2023/Day13/Solution.cs b/2023/Day13/Solution.cs deleted file mode 100644 index 075485fcc..000000000 --- a/2023/Day13/Solution.cs +++ /dev/null @@ -1,58 +0,0 @@ -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(); - } -} diff --git a/2023/Day13/illustration.jpeg b/2023/Day13/illustration.jpeg deleted file mode 100644 index 034cf2d83..000000000 Binary files a/2023/Day13/illustration.jpeg and /dev/null differ diff --git a/2023/Day13/input.in b/2023/Day13/input.in deleted file mode 100644 index 689e6f0fc..000000000 Binary files a/2023/Day13/input.in and /dev/null differ diff --git a/2023/Day13/input.refout b/2023/Day13/input.refout deleted file mode 100644 index 54d5efd6d..000000000 --- a/2023/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -33356 -28475 \ No newline at end of file diff --git a/2023/Day14/README.md b/2023/Day14/README.md deleted file mode 100644 index fc7f2eb7b..000000000 --- a/2023/Day14/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 14: Parabolic Reflector Dish --- -The task description is copyrighted, but it's available [here](https://adventofcode.com/2023/day/14). - -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. - - diff --git a/2023/Day14/Solution.cs b/2023/Day14/Solution.cs deleted file mode 100644 index 7bc97947b..000000000 --- a/2023/Day14/Solution.cs +++ /dev/null @@ -1,86 +0,0 @@ -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(); -} \ No newline at end of file diff --git a/2023/Day14/illustration.jpeg b/2023/Day14/illustration.jpeg deleted file mode 100644 index 3d5dbea0f..000000000 Binary files a/2023/Day14/illustration.jpeg and /dev/null differ diff --git a/2023/Day14/input.in b/2023/Day14/input.in deleted file mode 100644 index 56cc8b19b..000000000 Binary files a/2023/Day14/input.in and /dev/null differ diff --git a/2023/Day14/input.refout b/2023/Day14/input.refout deleted file mode 100644 index 6e343562a..000000000 --- a/2023/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -109596 -96105 \ No newline at end of file diff --git a/2023/Day15/README.md b/2023/Day15/README.md deleted file mode 100644 index a714668cb..000000000 --- a/2023/Day15/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## --- Day 15: Lens Library --- -Let's revisit the problem description [here](https://adventofcode.com/2023/day/15). - -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. diff --git a/2023/Day15/Solution.cs b/2023/Day15/Solution.cs deleted file mode 100644 index 6c5b4d1e9..000000000 --- a/2023/Day15/Solution.cs +++ /dev/null @@ -1,48 +0,0 @@ -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); -} diff --git a/2023/Day15/illustration.jpeg b/2023/Day15/illustration.jpeg deleted file mode 100644 index a338e9416..000000000 Binary files a/2023/Day15/illustration.jpeg and /dev/null differ diff --git a/2023/Day15/input.in b/2023/Day15/input.in deleted file mode 100644 index e433a2052..000000000 Binary files a/2023/Day15/input.in and /dev/null differ diff --git a/2023/Day15/input.refout b/2023/Day15/input.refout deleted file mode 100644 index 6ec9969c6..000000000 --- a/2023/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -519603 -244342 \ No newline at end of file diff --git a/2023/Day16/README.md b/2023/Day16/README.md deleted file mode 100644 index 52e619a8b..000000000 --- a/2023/Day16/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## --- Day 16: The Floor Will Be Lava --- -The original problem description is available [here](https://adventofcode.com/2023/day/16). - -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. - diff --git a/2023/Day16/Solution.cs b/2023/Day16/Solution.cs deleted file mode 100644 index 4341bda5a..000000000 --- a/2023/Day16/Solution.cs +++ /dev/null @@ -1,78 +0,0 @@ -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] - }; -} \ No newline at end of file diff --git a/2023/Day16/illustration.jpeg b/2023/Day16/illustration.jpeg deleted file mode 100644 index bd921cad4..000000000 Binary files a/2023/Day16/illustration.jpeg and /dev/null differ diff --git a/2023/Day16/input.in b/2023/Day16/input.in deleted file mode 100644 index 54c266772..000000000 Binary files a/2023/Day16/input.in and /dev/null differ diff --git a/2023/Day16/input.refout b/2023/Day16/input.refout deleted file mode 100644 index be1b44a9f..000000000 --- a/2023/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -7623 -8244 \ No newline at end of file diff --git a/2023/Day17/README.md b/2023/Day17/README.md deleted file mode 100644 index ec0988c79..000000000 --- a/2023/Day17/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 17: Clumsy Crucible --- -Visit the Advent of Code website for the problem statement [here](https://adventofcode.com/2023/day/17). - -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. diff --git a/2023/Day17/Solution.cs b/2023/Day17/Solution.cs deleted file mode 100644 index 08db1b1d4..000000000 --- a/2023/Day17/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/2023/Day17/illustration.jpeg b/2023/Day17/illustration.jpeg deleted file mode 100644 index 8c04f08d7..000000000 Binary files a/2023/Day17/illustration.jpeg and /dev/null differ diff --git a/2023/Day17/input.in b/2023/Day17/input.in deleted file mode 100644 index 706ddbce2..000000000 Binary files a/2023/Day17/input.in and /dev/null differ diff --git a/2023/Day17/input.refout b/2023/Day17/input.refout deleted file mode 100644 index 702b1c1fe..000000000 --- a/2023/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -767 -904 \ No newline at end of file diff --git a/2023/Day18/README.md b/2023/Day18/README.md deleted file mode 100644 index ba58b5b0c..000000000 --- a/2023/Day18/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## --- Day 18: Lavaduct Lagoon --- -If you are not familiar with the problem, you can read it [here](https://adventofcode.com/2023/day/18). - -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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Pick%27s_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. diff --git a/2023/Day18/Solution.cs b/2023/Day18/Solution.cs deleted file mode 100644 index 95547af27..000000000 --- a/2023/Day18/Solution.cs +++ /dev/null @@ -1,68 +0,0 @@ -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; - } - } -} \ No newline at end of file diff --git a/2023/Day18/illustration.jpeg b/2023/Day18/illustration.jpeg deleted file mode 100644 index 2d45b35ee..000000000 Binary files a/2023/Day18/illustration.jpeg and /dev/null differ diff --git a/2023/Day18/input.in b/2023/Day18/input.in deleted file mode 100644 index 265d68ef7..000000000 Binary files a/2023/Day18/input.in and /dev/null differ diff --git a/2023/Day18/input.refout b/2023/Day18/input.refout deleted file mode 100644 index 1cd59a4b6..000000000 --- a/2023/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -42317 -83605563360288 \ No newline at end of file diff --git a/2023/Day19/README.md b/2023/Day19/README.md deleted file mode 100644 index 87fc6516b..000000000 --- a/2023/Day19/README.md +++ /dev/null @@ -1,26 +0,0 @@ -## --- Day 19: Aplenty --- -Those who need a refresh can read the problem [here](https://adventofcode.com/2023/day/19). - -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. - diff --git a/2023/Day19/Solution.cs b/2023/Day19/Solution.cs deleted file mode 100644 index c6841d723..000000000 --- a/2023/Day19/Solution.cs +++ /dev/null @@ -1,109 +0,0 @@ -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(); -} \ No newline at end of file diff --git a/2023/Day19/illustration.jpeg b/2023/Day19/illustration.jpeg deleted file mode 100644 index bc8956993..000000000 Binary files a/2023/Day19/illustration.jpeg and /dev/null differ diff --git a/2023/Day19/input.in b/2023/Day19/input.in deleted file mode 100644 index b5033d617..000000000 Binary files a/2023/Day19/input.in and /dev/null differ diff --git a/2023/Day19/input.refout b/2023/Day19/input.refout deleted file mode 100644 index 438c2f996..000000000 --- a/2023/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -346230 -124693661917133 \ No newline at end of file diff --git a/2023/Day20/README.md b/2023/Day20/README.md deleted file mode 100644 index 607ee92ad..000000000 --- a/2023/Day20/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## --- Day 20: Pulse Propagation --- -The task description is copyrighted, but it's available [here](https://adventofcode.com/2023/day/20). - -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. - diff --git a/2023/Day20/Solution.cs b/2023/Day20/Solution.cs deleted file mode 100644 index 7840377b2..000000000 --- a/2023/Day20/Solution.cs +++ /dev/null @@ -1,112 +0,0 @@ -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) - ); - } -} \ No newline at end of file diff --git a/2023/Day20/illustration.jpeg b/2023/Day20/illustration.jpeg deleted file mode 100644 index 772a67c58..000000000 Binary files a/2023/Day20/illustration.jpeg and /dev/null differ diff --git a/2023/Day20/input.in b/2023/Day20/input.in deleted file mode 100644 index 9c8a997b9..000000000 Binary files a/2023/Day20/input.in and /dev/null differ diff --git a/2023/Day20/input.refout b/2023/Day20/input.refout deleted file mode 100644 index 92c71f358..000000000 --- a/2023/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -949764474 -243221023462303 \ No newline at end of file diff --git a/2023/Day21/README.md b/2023/Day21/README.md deleted file mode 100644 index e92e3fc0b..000000000 --- a/2023/Day21/README.md +++ /dev/null @@ -1,46 +0,0 @@ -## --- Day 21: Step Counter --- -Let's revisit the problem description [here](https://adventofcode.com/2023/day/21). - -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. diff --git a/2023/Day21/Solution.cs b/2023/Day21/Solution.cs deleted file mode 100644 index 57702b2a9..000000000 --- a/2023/Day21/Solution.cs +++ /dev/null @@ -1,68 +0,0 @@ -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(); - } -} diff --git a/2023/Day21/illustration.jpeg b/2023/Day21/illustration.jpeg deleted file mode 100644 index 843c9e1ce..000000000 Binary files a/2023/Day21/illustration.jpeg and /dev/null differ diff --git a/2023/Day21/input.in b/2023/Day21/input.in deleted file mode 100644 index 85de8fe42..000000000 Binary files a/2023/Day21/input.in and /dev/null differ diff --git a/2023/Day21/input.refout b/2023/Day21/input.refout deleted file mode 100644 index 3904a7379..000000000 --- a/2023/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -3751 -619407349431167 \ No newline at end of file diff --git a/2023/Day22/README.md b/2023/Day22/README.md deleted file mode 100644 index 074a83e8e..000000000 --- a/2023/Day22/README.md +++ /dev/null @@ -1,19 +0,0 @@ -## --- Day 22: Sand Slabs --- -The original problem description is available -[here](https://adventofcode.com/2023/day/22). - -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. diff --git a/2023/Day22/Solution.cs b/2023/Day22/Solution.cs deleted file mode 100644 index af46562ca..000000000 --- a/2023/Day22/Solution.cs +++ /dev/null @@ -1,102 +0,0 @@ -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(); -} \ No newline at end of file diff --git a/2023/Day22/illustration.jpeg b/2023/Day22/illustration.jpeg deleted file mode 100644 index 135992b9f..000000000 Binary files a/2023/Day22/illustration.jpeg and /dev/null differ diff --git a/2023/Day22/input.in b/2023/Day22/input.in deleted file mode 100644 index 004f71c7a..000000000 Binary files a/2023/Day22/input.in and /dev/null differ diff --git a/2023/Day22/input.refout b/2023/Day22/input.refout deleted file mode 100644 index 6edcd6304..000000000 --- a/2023/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -503 -98431 \ No newline at end of file diff --git a/2023/Day23/README.md b/2023/Day23/README.md deleted file mode 100644 index 43bc27740..000000000 --- a/2023/Day23/README.md +++ /dev/null @@ -1,26 +0,0 @@ -## --- Day 23: A Long Walk --- -Visit the Advent of Code website for the problem statement [here](https://adventofcode.com/2023/day/23). - -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_. - diff --git a/2023/Day23/Solution.cs b/2023/Day23/Solution.cs deleted file mode 100644 index 6a21dfd27..000000000 --- a/2023/Day23/Solution.cs +++ /dev/null @@ -1,129 +0,0 @@ -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(); - } -} diff --git a/2023/Day23/illustration.jpeg b/2023/Day23/illustration.jpeg deleted file mode 100644 index cdd403505..000000000 Binary files a/2023/Day23/illustration.jpeg and /dev/null differ diff --git a/2023/Day23/input.in b/2023/Day23/input.in deleted file mode 100644 index 223573511..000000000 Binary files a/2023/Day23/input.in and /dev/null differ diff --git a/2023/Day23/input.refout b/2023/Day23/input.refout deleted file mode 100644 index 26a431634..000000000 --- a/2023/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2238 -6398 \ No newline at end of file diff --git a/2023/Day24/README.md b/2023/Day24/README.md deleted file mode 100644 index 2fdc0380b..000000000 --- a/2023/Day24/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## --- Day 24: Never Tell Me The Odds --- -If you are not familiar with the problem, you can read it [here](https://adventofcode.com/2023/day/24). - -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. diff --git a/2023/Day24/Solution.cs b/2023/Day24/Solution.cs deleted file mode 100644 index f9f8e1fb4..000000000 --- a/2023/Day24/Solution.cs +++ /dev/null @@ -1,117 +0,0 @@ -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) - ) - ]; -} diff --git a/2023/Day24/illustration.jpeg b/2023/Day24/illustration.jpeg deleted file mode 100644 index 77f5b727e..000000000 Binary files a/2023/Day24/illustration.jpeg and /dev/null differ diff --git a/2023/Day24/input.in b/2023/Day24/input.in deleted file mode 100644 index c624e433f..000000000 Binary files a/2023/Day24/input.in and /dev/null differ diff --git a/2023/Day24/input.refout b/2023/Day24/input.refout deleted file mode 100644 index 0c308e399..000000000 --- a/2023/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -27732 -641619849766168 \ No newline at end of file diff --git a/2023/Day25/README.md b/2023/Day25/README.md deleted file mode 100644 index b74bd4b54..000000000 --- a/2023/Day25/README.md +++ /dev/null @@ -1,30 +0,0 @@ -## --- Day 25: Snowverload --- -Those who need a refresh can read the problem [here](https://adventofcode.com/2023/day/25). - -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](https://en.wikipedia.org/wiki/Karger%27s_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](https://github.com/encse) or -[Twitter](https://twitter.com/encse). - -Psst! There is game [hidden](game) in this site. - diff --git a/2023/Day25/Solution.cs b/2023/Day25/Solution.cs deleted file mode 100644 index fe67e85d4..000000000 --- a/2023/Day25/Solution.cs +++ /dev/null @@ -1,94 +0,0 @@ -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; - } -} diff --git a/2023/Day25/illustration.jpeg b/2023/Day25/illustration.jpeg deleted file mode 100644 index 42399f317..000000000 Binary files a/2023/Day25/illustration.jpeg and /dev/null differ diff --git a/2023/Day25/input.in b/2023/Day25/input.in deleted file mode 100644 index 5dd3aa864..000000000 Binary files a/2023/Day25/input.in and /dev/null differ diff --git a/2023/Day25/input.refout b/2023/Day25/input.refout deleted file mode 100644 index f80cbd205..000000000 --- a/2023/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -514786 \ No newline at end of file diff --git a/2023/README.md b/2023/README.md index 4fd5bc286..e499c3192 100644 --- a/2023/README.md +++ b/2023/README.md @@ -1,4 +1,6 @@ + # Advent of Code (2023) Check out https://adventofcode.com/2023. + diff --git a/2023/SplashScreen.cs b/2023/SplashScreen.cs index d5f9a011a..683bc42fd 100644 --- a/2023/SplashScreen.cs +++ b/2023/SplashScreen.cs @@ -1,3 +1,4 @@ + using System; namespace AdventOfCode.Y2023; @@ -8,225 +9,38 @@ public void Show() { var color = Console.ForegroundColor; Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ $year = 2023\n "); - Write(0xcc00, false, "\n "); - Write(0xa25151, false, "...'''''''''... \n .'' "); - Write(0xdf2308, true, "~"); - Write(0xa5a8af, false, "/\\"); - Write(0xffff66, true, "* "); - Write(0xdf2308, true, "~~~~ "); - Write(0xa5a8af, false, "/\\ "); - Write(0xa25151, false, "''. "); - Write(0xcccccc, false, "14 "); - Write(0xffff66, false, "**\n "); - Write(0xa25151, false, ".' "); - Write(0xa5a8af, false, "/\\/\\ "); - Write(0xdf2308, true, "~~~~~~~~ "); - Write(0xffff66, true, "* "); - Write(0xa5a8af, false, "/"); - Write(0xdf2308, true, "~"); - Write(0xa5a8af, false, "\\ "); - Write(0xa25151, false, "'. "); - Write(0xcccccc, false, "15 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, "... "); - Write(0xa25151, false, ":"); - Write(0xdf2308, true, "~~~~~~~~~ "); - Write(0xa5a8af, false, "/\\ "); - Write(0xdf2308, true, "~~~~"); - Write(0xa5a8af, false, "/ "); - Write(0xffff66, true, "* "); - Write(0xa5a8af, false, "\\ "); - Write(0xa25151, false, ": "); - Write(0xcccccc, false, "16 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, ".''....' '.."); - Write(0xa25151, false, "'."); - Write(0xdf2308, true, "~~~~"); - Write(0xa5a8af, false, "/\\"); - Write(0xffff66, true, "*"); - Write(0xa5a8af, false, "/\\ "); - Write(0xdf2308, true, "~ "); - Write(0xa5a8af, false, "/\\ /\\ "); - Write(0xa25151, false, ".' "); - Write(0xcccccc, false, "13 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, "'.ZZ"); - Write(0xdf2308, true, "~ ~ "); - Write(0xffff66, true, "* "); - Write(0xdf2308, true, "~~~~"); - Write(0xa25151, false, ". "); - Write(0xa5a8af, false, "/\\ /\\ /\\ "); - Write(0xa25151, false, "..' "); - Write(0xcccccc, false, "17 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, ".'''' ZZ"); - Write(0xffff66, true, "* "); - Write(0xd4dde4, false, ".'''.[]"); - Write(0xdf2308, true, "~~~"); - Write(0xd4dde4, false, "'"); - Write(0xa25151, false, "'''.........''' "); - Write(0xcccccc, false, "12 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, "'.... "); - Write(0xdf2308, true, "~ "); - Write(0xd4dde4, false, "'...' "); - Write(0xffff66, true, "*"); - Write(0xd4dde4, false, "[]....' "); - Write(0xcccccc, false, "18 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, ".'"); - Write(0xffff66, true, "* "); - Write(0xdf2308, true, "~ "); - Write(0xd4dde4, false, "[^^^] '. "); - Write(0xcccccc, false, "11 "); - Write(0xffff66, false, "**\n "); - Write(0xd4dde4, false, "'..''''."); - Write(0xffff66, true, "*"); - Write(0xd4dde4, false, ".''''..'"); - Write(0xe3b585, false, "' ''... "); - Write(0xcccccc, false, "10 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, "."); - Write(0xd4dde4, false, "'''"); - Write(0xe3b585, false, "~ ~ ~ "); - Write(0xd4dde4, false, ". "); - Write(0xffff66, true, "* "); - Write(0x6b4d3b, false, "### "); - Write(0xe3b585, false, "''. "); - Write(0xcccccc, false, "19 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, ".' ~ "); - Write(0xcc00, false, ","); - Write(0xffff66, true, "* "); - Write(0xe3b585, false, "~ "); - Write(0xd4dde4, false, "'\", "); - Write(0xe3b585, false, "~ "); - Write(0x6b4d3b, false, "##### "); - Write(0xe3b585, false, "'. "); + Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ {:year 2023}\n "); + Write(0xcc00, false, "\n \n "); + Write(0xcc00, false, " \n \n "); + Write(0xcc00, false, " \n "); + Write(0xcc00, false, " \n \n "); + Write(0xcc00, false, " \n \n "); + Write(0x333333, false, " * "); + Write(0x666666, false, "10\n \n * "); + Write(0x666666, false, " "); Write(0xcccccc, false, " 9 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, ": ~ "); - Write(0xcc00, false, "'"); - Write(0x5555bb, false, "(~)"); - Write(0xcc00, false, ", "); - Write(0xe3b585, false, "~ "); - Write(0xffff66, true, "* "); - Write(0xe3b585, false, "~ ~ ~ "); - Write(0x6b4d3b, false, "### "); - Write(0xe3b585, false, ": "); + Write(0x666666, false, "**\n * "); Write(0xcccccc, false, " 8 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, "'. ~ "); - Write(0xcc00, false, "\" ' "); - Write(0xe3b585, false, "~ ~ ~ "); - Write(0xffff66, true, "* "); - Write(0xe3b585, false, "~~~"); - Write(0x6b4d3b, false, "## "); - Write(0xe3b585, false, ".' "); - Write(0xcccccc, false, "20 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, "'.. ~ ~ "); - Write(0xffff66, true, "* "); - Write(0xe3b585, false, "~ "); - Write(0x6b4d3b, false, "####"); - Write(0xe3b585, false, "~~~~'"); - Write(0xcc00, false, ".'''''''''... "); + Write(0x666666, false, "**\n \n * "); + Write(0x666666, false, " "); Write(0xcccccc, false, " 7 "); - Write(0xffff66, false, "**\n "); - Write(0xe3b585, false, "'''.........'''"); - Write(0xcc00, false, "' "); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, ".'"); - Write(0xffff66, true, "*"); - Write(0xcc00, false, ". "); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, ".. ''. "); + Write(0x666666, false, "**\n * "); Write(0xcccccc, false, " 6 "); - Write(0xffff66, false, "**\n "); - Write(0xcc00, false, ".' "); - Write(0x5555bb, false, "~ "); - Write(0xe3b585, false, ".. "); - Write(0xcc00, false, "'...' "); - Write(0x5555bb, false, "~"); - Write(0xcc00, false, "'"); - Write(0xffff66, true, "* "); - Write(0xcc00, false, "'."); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "'. "); - Write(0xcccccc, false, "21 "); - Write(0xffff66, false, "**\n "); - Write(0x5555bb, false, "~~ "); - Write(0xe3b585, false, ".~~~'. "); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "'. "); - Write(0xffff66, true, "*"); - Write(0xcc00, false, "'."); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, ": "); + Write(0x666666, false, "**\n \n "); + Write(0x666666, false, " * "); Write(0xcccccc, false, " 5 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, "...''''"); - Write(0x5555bb, false, "~~~"); - Write(0xe3b585, false, "'"); - Write(0xffff66, true, "*"); - Write(0xe3b585, false, "~~.' "); - Write(0xcc00, false, ".''."); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "'..' .' "); - Write(0xcccccc, false, "22 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, ".'' "); - Write(0xccccff, false, "- - "); - Write(0xcc00, false, "'.. "); - Write(0x5555bb, false, "~"); - Write(0xcc00, false, "..'"); - Write(0xffff66, true, "* "); - Write(0xcc00, false, "'. "); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "..' "); + Write(0x666666, false, "**\n \n "); + Write(0x666666, false, " * "); Write(0xcccccc, false, " 4 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, ".' "); - Write(0xffff66, true, "* "); - Write(0xccccff, false, "- "); - Write(0xffffff, false, "/\\ "); - Write(0xccccff, false, "- "); - Write(0xcc00, false, "'''.."); - Write(0xd4dde4, false, "/"); - Write(0xcc00, false, "......''' "); - Write(0xcccccc, false, "23 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, ": "); - Write(0xccccff, false, "- - - "); - Write(0xffff66, true, "* "); - Write(0xffffff, false, "/\\ "); - Write(0xccccff, false, "-"); - Write(0xd4dde4, false, "/ "); - Write(0xffffff, false, ": "); - Write(0xcccccc, false, "25 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, "'. "); - Write(0xccccff, false, "- "); - Write(0xffff66, true, "* "); - Write(0xffffff, false, "/\\ "); - Write(0xccccff, false, "- - "); - Write(0xd4dde4, false, "/ "); - Write(0xffffff, false, ".' "); - Write(0xcccccc, false, "24 "); - Write(0xffff66, false, "**\n "); - Write(0xffffff, false, "'.. "); - Write(0xccccff, false, "- - "); - Write(0xffff66, true, "*"); - Write(0xffffff, false, "..' "); + Write(0x666666, false, "**\n \n "); + Write(0x666666, false, " \n \n "); + Write(0x666666, false, " * "); Write(0xcccccc, false, " 3 "); - Write(0xffff66, false, "**\n "); - Write(0x9b715b, false, "----@ "); - Write(0xffffff, false, "'''.."); - Write(0xffff66, true, "*"); - Write(0xffffff, false, "......''' "); + Write(0x666666, false, "**\n "); + Write(0x9b715b, false, "----@"); + Write(0x666666, false, " * "); Write(0xcccccc, false, " 2 "); - Write(0xffff66, false, "**\n "); + Write(0x666666, false, "**\n "); Write(0xffff66, true, "* "); Write(0x9b715b, false, "! /^\\ "); Write(0xcccccc, false, " 1 "); @@ -236,7 +50,7 @@ public void Show() { Console.WriteLine(); } - private static void Write(int rgb, bool bold, string text){ + private static void Write(int rgb, bool bold, string text){ Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file + } +} diff --git a/2023/calendar.svg b/2023/calendar.svg index e515150c5..7d19e5bac 100644 --- a/2023/calendar.svg +++ b/2023/calendar.svg @@ -1,4 +1,4 @@ - + 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. - -As each location is checked, they will mark it on their list with a star. They figure the Chief Historian must be in one of the first fifty places they'll look, so in order to save Christmas, you need to help them get fifty stars on their list before Santa takes off on December 25th. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/1) description._ diff --git a/2024/Day01/Solution.cs b/2024/Day01/Solution.cs deleted file mode 100644 index 3b440af39..000000000 --- a/2024/Day01/Solution.cs +++ /dev/null @@ -1,29 +0,0 @@ -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]; -} diff --git a/2024/Day01/illustration.jpeg b/2024/Day01/illustration.jpeg deleted file mode 100644 index c5dbd40d7..000000000 Binary files a/2024/Day01/illustration.jpeg and /dev/null differ diff --git a/2024/Day01/input.in b/2024/Day01/input.in deleted file mode 100644 index 8eba02d04..000000000 Binary files a/2024/Day01/input.in and /dev/null differ diff --git a/2024/Day01/input.refout b/2024/Day01/input.refout deleted file mode 100644 index 85ba5a423..000000000 --- a/2024/Day01/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2904518 -18650129 \ No newline at end of file diff --git a/2024/Day02/README.md b/2024/Day02/README.md deleted file mode 100644 index ba6e3516b..000000000 --- a/2024/Day02/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## --- Day 2: Red-Nosed Reports --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/2) description._ - -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. \ No newline at end of file diff --git a/2024/Day02/Solution.cs b/2024/Day02/Solution.cs deleted file mode 100644 index 8f07d7144..000000000 --- a/2024/Day02/Solution.cs +++ /dev/null @@ -1,36 +0,0 @@ -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); - } -} diff --git a/2024/Day02/illustration.jpeg b/2024/Day02/illustration.jpeg deleted file mode 100644 index cebc32454..000000000 Binary files a/2024/Day02/illustration.jpeg and /dev/null differ diff --git a/2024/Day02/input.in b/2024/Day02/input.in deleted file mode 100644 index 2ceeb0950..000000000 Binary files a/2024/Day02/input.in and /dev/null differ diff --git a/2024/Day02/input.refout b/2024/Day02/input.refout deleted file mode 100644 index 2e38115b0..000000000 --- a/2024/Day02/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -202 -271 \ No newline at end of file diff --git a/2024/Day03/README.md b/2024/Day03/README.md deleted file mode 100644 index c437cf887..000000000 --- a/2024/Day03/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## --- Day 3: Mull It Over --- -"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](/2020/day/2). 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?" - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/3) description._ - -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. diff --git a/2024/Day03/Solution.cs b/2024/Day03/Solution.cs deleted file mode 100644 index 292cf926f..000000000 --- a/2024/Day03/Solution.cs +++ /dev/null @@ -1,29 +0,0 @@ -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 - ); - } -} \ No newline at end of file diff --git a/2024/Day03/illustration.jpeg b/2024/Day03/illustration.jpeg deleted file mode 100644 index e19c0a13b..000000000 Binary files a/2024/Day03/illustration.jpeg and /dev/null differ diff --git a/2024/Day03/input.in b/2024/Day03/input.in deleted file mode 100644 index 46d2a13b9..000000000 Binary files a/2024/Day03/input.in and /dev/null differ diff --git a/2024/Day03/input.refout b/2024/Day03/input.refout deleted file mode 100644 index b4d21cde1..000000000 --- a/2024/Day03/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -165225049 -108830766 \ No newline at end of file diff --git a/2024/Day04/README.md b/2024/Day04/README.md deleted file mode 100644 index 830b6cf4e..000000000 --- a/2024/Day04/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 4: Ceres Search --- -"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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/4) description._ - -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. diff --git a/2024/Day04/Solution.cs b/2024/Day04/Solution.cs deleted file mode 100644 index b5cfcc9fd..000000000 --- a/2024/Day04/Solution.cs +++ /dev/null @@ -1,61 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/2024/Day04/illustration.jpeg b/2024/Day04/illustration.jpeg deleted file mode 100644 index a5fdc0918..000000000 Binary files a/2024/Day04/illustration.jpeg and /dev/null differ diff --git a/2024/Day04/input.in b/2024/Day04/input.in deleted file mode 100644 index 9f76d332e..000000000 Binary files a/2024/Day04/input.in and /dev/null differ diff --git a/2024/Day04/input.refout b/2024/Day04/input.refout deleted file mode 100644 index 947b78a71..000000000 --- a/2024/Day04/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -2414 -1871 \ No newline at end of file diff --git a/2024/Day05/README.md b/2024/Day05/README.md deleted file mode 100644 index 6f40cba61..000000000 --- a/2024/Day05/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 5: Print Queue --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/5) description._ - -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. diff --git a/2024/Day05/Solution.cs b/2024/Day05/Solution.cs deleted file mode 100644 index e25ef7a09..000000000 --- a/2024/Day05/Solution.cs +++ /dev/null @@ -1,40 +0,0 @@ -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)); - -} diff --git a/2024/Day05/illustration.jpeg b/2024/Day05/illustration.jpeg deleted file mode 100644 index d270b7fa4..000000000 Binary files a/2024/Day05/illustration.jpeg and /dev/null differ diff --git a/2024/Day05/input.in b/2024/Day05/input.in deleted file mode 100644 index 258e15c8b..000000000 Binary files a/2024/Day05/input.in and /dev/null differ diff --git a/2024/Day05/input.refout b/2024/Day05/input.refout deleted file mode 100644 index 4d6180ed3..000000000 --- a/2024/Day05/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -4790 -6319 \ No newline at end of file diff --git a/2024/Day06/README.md b/2024/Day06/README.md deleted file mode 100644 index 2a908234f..000000000 --- a/2024/Day06/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## --- Day 6: Guard Gallivant --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/6) description._ - -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. diff --git a/2024/Day06/Solution.cs b/2024/Day06/Solution.cs deleted file mode 100644 index 9b493893e..000000000 --- a/2024/Day06/Solution.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace AdventOfCode.Y2024.Day06; - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Numerics; -using Map = System.Collections.Immutable.ImmutableDictionary; - -[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); - // try a blocker in each locations visited by the guard counting the loops - return Walk(map, start).positions - .AsParallel() - .Count(pos => Walk(map.SetItem(pos, '#'), start).isLoop); - - } - - // 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]) - ).ToImmutableDictionary(); - - var start = map.First(x => x.Value == '^').Key; - - return (map, start); - } -} \ No newline at end of file diff --git a/2024/Day06/illustration.jpeg b/2024/Day06/illustration.jpeg deleted file mode 100644 index 62e5e4349..000000000 Binary files a/2024/Day06/illustration.jpeg and /dev/null differ diff --git a/2024/Day06/input.in b/2024/Day06/input.in deleted file mode 100644 index 6d740e90a..000000000 Binary files a/2024/Day06/input.in and /dev/null differ diff --git a/2024/Day06/input.refout b/2024/Day06/input.refout deleted file mode 100644 index cd63e0fc5..000000000 --- a/2024/Day06/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -4789 -1304 \ No newline at end of file diff --git a/2024/Day07/README.md b/2024/Day07/README.md deleted file mode 100644 index 902b0774d..000000000 --- a/2024/Day07/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 7: Bridge Repair --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/7) description._ - -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. diff --git a/2024/Day07/Solution.cs b/2024/Day07/Solution.cs deleted file mode 100644 index 2cb0af10a..000000000 --- a/2024/Day07/Solution.cs +++ /dev/null @@ -1,41 +0,0 @@ -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..]) - }; -} diff --git a/2024/Day07/illustration.jpeg b/2024/Day07/illustration.jpeg deleted file mode 100644 index f08fd6f20..000000000 Binary files a/2024/Day07/illustration.jpeg and /dev/null differ diff --git a/2024/Day07/input.in b/2024/Day07/input.in deleted file mode 100644 index 723bf50a4..000000000 Binary files a/2024/Day07/input.in and /dev/null differ diff --git a/2024/Day07/input.refout b/2024/Day07/input.refout deleted file mode 100644 index 7a69a12ba..000000000 --- a/2024/Day07/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6231007345478 -333027885676693 \ No newline at end of file diff --git a/2024/Day08/README.md b/2024/Day08/README.md deleted file mode 100644 index fcfa0971a..000000000 --- a/2024/Day08/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## --- Day 8: Resonant Collinearity --- -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! - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/8) description._ - -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. diff --git a/2024/Day08/Solution.cs b/2024/Day08/Solution.cs deleted file mode 100644 index e3c4c4695..000000000 --- a/2024/Day08/Solution.cs +++ /dev/null @@ -1,66 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/2024/Day08/illustration.jpeg b/2024/Day08/illustration.jpeg deleted file mode 100644 index c15028cbf..000000000 Binary files a/2024/Day08/illustration.jpeg and /dev/null differ diff --git a/2024/Day08/input.in b/2024/Day08/input.in deleted file mode 100644 index 8b2c34647..000000000 Binary files a/2024/Day08/input.in and /dev/null differ diff --git a/2024/Day08/input.refout b/2024/Day08/input.refout deleted file mode 100644 index fb3dee4bd..000000000 --- a/2024/Day08/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -247 -861 \ No newline at end of file diff --git a/2024/Day09/README.md b/2024/Day09/README.md deleted file mode 100644 index be72beecb..000000000 --- a/2024/Day09/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## --- Day 9: Disk Fragmenter --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/9) description._ - -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... diff --git a/2024/Day09/Solution.cs b/2024/Day09/Solution.cs deleted file mode 100644 index 0622a6368..000000000 --- a/2024/Day09/Solution.cs +++ /dev/null @@ -1,78 +0,0 @@ -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'))); - } -} diff --git a/2024/Day09/illustration.jpeg b/2024/Day09/illustration.jpeg deleted file mode 100644 index 7e5c69dd3..000000000 Binary files a/2024/Day09/illustration.jpeg and /dev/null differ diff --git a/2024/Day09/input.in b/2024/Day09/input.in deleted file mode 100644 index 8e4220afb..000000000 Binary files a/2024/Day09/input.in and /dev/null differ diff --git a/2024/Day09/input.refout b/2024/Day09/input.refout deleted file mode 100644 index 59f6af771..000000000 --- a/2024/Day09/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -6448989155953 -6476642796832 \ No newline at end of file diff --git a/2024/Day10/README.md b/2024/Day10/README.md deleted file mode 100644 index e0d8711b7..000000000 --- a/2024/Day10/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## --- Day 10: Hoof It --- -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](https://en.wikipedia.org/wiki/Topographic_map) of the surrounding area (your puzzle input) and looks up at you excitedly. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/10) description._ - -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! diff --git a/2024/Day10/Solution.cs b/2024/Day10/Solution.cs deleted file mode 100644 index 1b882279f..000000000 --- a/2024/Day10/Solution.cs +++ /dev/null @@ -1,59 +0,0 @@ -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(); - } -} diff --git a/2024/Day10/illustration.jpeg b/2024/Day10/illustration.jpeg deleted file mode 100644 index 4c66aecd0..000000000 Binary files a/2024/Day10/illustration.jpeg and /dev/null differ diff --git a/2024/Day10/input.in b/2024/Day10/input.in deleted file mode 100644 index c5e8a9c7c..000000000 Binary files a/2024/Day10/input.in and /dev/null differ diff --git a/2024/Day10/input.refout b/2024/Day10/input.refout deleted file mode 100644 index 2f0670b4a..000000000 --- a/2024/Day10/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -674 -1372 \ No newline at end of file diff --git a/2024/Day11/README.md b/2024/Day11/README.md deleted file mode 100644 index 4d9b8030a..000000000 --- a/2024/Day11/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## --- Day 11: Plutonian Pebbles --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/11) description._ - -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. \ No newline at end of file diff --git a/2024/Day11/Solution.cs b/2024/Day11/Solution.cs deleted file mode 100644 index f5bb4786b..000000000 --- a/2024/Day11/Solution.cs +++ /dev/null @@ -1,38 +0,0 @@ -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) - } - ); -} \ No newline at end of file diff --git a/2024/Day11/illustration.jpeg b/2024/Day11/illustration.jpeg deleted file mode 100644 index 04d52a2c8..000000000 Binary files a/2024/Day11/illustration.jpeg and /dev/null differ diff --git a/2024/Day11/input.in b/2024/Day11/input.in deleted file mode 100644 index 5a4dfc848..000000000 Binary files a/2024/Day11/input.in and /dev/null differ diff --git a/2024/Day11/input.refout b/2024/Day11/input.refout deleted file mode 100644 index 75b88057d..000000000 --- a/2024/Day11/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -189547 -224577979481346 \ No newline at end of file diff --git a/2024/Day12/README.md b/2024/Day12/README.md deleted file mode 100644 index d8fdb2ff0..000000000 --- a/2024/Day12/README.md +++ /dev/null @@ -1,31 +0,0 @@ -## --- Day 12: Garden Groups --- -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. - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/12) description._ - -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. diff --git a/2024/Day12/Solution.cs b/2024/Day12/Solution.cs deleted file mode 100644 index f169d9a40..000000000 --- a/2024/Day12/Solution.cs +++ /dev/null @@ -1,113 +0,0 @@ -namespace AdventOfCode.Y2024.Day12; - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Numerics; - -using Region = System.Collections.Generic.HashSet; - -[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]; - - // check the 4 corner types - foreach (var (du, dv) in new[] { (Up, Right), (Right, Down), (Down, Left), (Left, Up) }) { - // .. - // x. convex corner - if (map.GetValueOrDefault(pt + du) != region && - map.GetValueOrDefault(pt + dv) != region - ) { - res++; - } - - // x. - // xx concave corner - 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; - } - -} diff --git a/2024/Day12/illustration.jpeg b/2024/Day12/illustration.jpeg deleted file mode 100644 index 62c1d43f1..000000000 Binary files a/2024/Day12/illustration.jpeg and /dev/null differ diff --git a/2024/Day12/input.in b/2024/Day12/input.in deleted file mode 100644 index 87382f822..000000000 Binary files a/2024/Day12/input.in and /dev/null differ diff --git a/2024/Day12/input.refout b/2024/Day12/input.refout deleted file mode 100644 index 03255f67a..000000000 --- a/2024/Day12/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1374934 -841078 \ No newline at end of file diff --git a/2024/Day13/README.md b/2024/Day13/README.md deleted file mode 100644 index 12fb1f33f..000000000 --- a/2024/Day13/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## --- Day 13: Claw Contraption --- -Next up: the [lobby](/2020/day/24) of a resort on a tropical island. The Historians take a moment to admire the hexagonal floor tiles before spreading out. - -Fortunately, it looks like the resort has a new [arcade](https://en.wikipedia.org/wiki/Amusement_arcade)! Maybe you can win some prizes from the [claw machines](https://en.wikipedia.org/wiki/Claw_machine)? - -_Visit the website for the full story and [puzzle](https://adventofcode.com/2024/day/13) description._ - -We got a math problem today. The movements triggered by buttons A, B and the target position P form a linear equation that we can solve for the two unknowns: the number of button presses. Using math terms, if _i_ and _j_ marks the number of button presses, we are to solve `A * i + B * j = P`. This is simple enough to do using [Cramer's rule](https://en.wikipedia.org/wiki/Cramer%27s_rule), especially with two dimensional vectors. In this case the determinats can be computed with a simple cross product. We should not forget about the special cases: A and B can be parallel (didn't occur in my input), and the solution needs to be non negative integer for _i_ and _j_. \ No newline at end of file diff --git a/2024/Day13/Solution.cs b/2024/Day13/Solution.cs deleted file mode 100644 index a37e1f094..000000000 --- a/2024/Day13/Solution.cs +++ /dev/null @@ -1,46 +0,0 @@ -namespace AdventOfCode.Y2024.Day13; - -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Machine = (Vec2 a, Vec2 b, Vec2 p); - -record struct Vec2(long x, long y); - -[ProblemName("Claw Contraption")] -class Solution : Solver { - - public object PartOne(string input) => Parse(input).Sum(GetPrize); - public object PartTwo(string input) => Parse(input, shift: 10000000000000).Sum(GetPrize); - - long GetPrize(Machine m) { - var (a, b, p) = m; - - // solve a * i + b * j = p for i and j using Cramer's rule - var i = Det(p, b) / Det(a, b); - var j = Det(a, p) / Det(a, b); - - // return the prize when a non negative _integer_ solution is found - if (i >= 0 && j >= 0 && a.x * i + b.x * j == p.x && a.y * i + b.y * j == p.y) { - return 3 * i + j; - } else { - return 0; - } - } - - long Det(Vec2 a, Vec2 b) => a.x * b.y - a.y * b.x; - - IEnumerable Parse(string input, long shift=0) { - var blocks = input.Split("\n\n"); - foreach (var block in blocks) { - var nums = - Regex.Matches(block, @"\d+", RegexOptions.Multiline) - .Select(m => int.Parse(m.Value)) - .Chunk(2).Select(p => new Vec2(p[0], p[1])) - .ToArray(); - - nums[2] = new Vec2(nums[2].x + shift, nums[2].y + shift); - yield return (nums[0], nums[1], nums[2]); - } - } -} \ No newline at end of file diff --git a/2024/Day13/illustration.jpeg b/2024/Day13/illustration.jpeg deleted file mode 100644 index a62957630..000000000 Binary files a/2024/Day13/illustration.jpeg and /dev/null differ diff --git a/2024/Day13/input.in b/2024/Day13/input.in deleted file mode 100644 index 10f78d949..000000000 Binary files a/2024/Day13/input.in and /dev/null differ diff --git a/2024/Day13/input.refout b/2024/Day13/input.refout deleted file mode 100644 index 78a92a9e3..000000000 --- a/2024/Day13/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -32041 -95843948914827 \ No newline at end of file diff --git a/2024/Day14/README.md b/2024/Day14/README.md deleted file mode 100644 index 9c226b17a..000000000 --- a/2024/Day14/README.md +++ /dev/null @@ -1,50 +0,0 @@ -## --- Day 14: Restroom Redoubt --- -One of The Historians needs to use the bathroom; fortunately, you know there's a bathroom near an unvisited location on their list, and so you're all quickly teleported directly to the lobby of Easter Bunny Headquarters. - -Unfortunately, EBHQ seems to have "improved" bathroom security again after your last [visit](/2016/day/2). The area outside the bathroom is swarming with robots! - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/14) description._ - -A nice simulation challenge for today. `Part 1` was straightforward: iterate 100 times and count the robots in the different quadrants. - -I’d bet many of us anticipated some `least common multiple` or `Chinese Remainder Theorem` magic for `Part 2`, but Eric threw us a curveball by making us search for a Christmas tree pattern in the robot’s movement. - -The expected output wasn’t clearly specified — other than the fact that it should resemble a Christmas tree. I wrote a plot function to display the robot’s locations on the screen, dumped everything into a long file, and manually inspected it in my editor. - -Later, to automate this process, decided to search for a longer horizontal '####' pattern in the output: - -``` - ############################### - # # # # - # # # - # # # - # # # # - # # # - # ### # # - # ##### # - # # ####### # - # # ######### # # - # ##### # - # # ####### # - # ######### # - # ########### # - # ############# # # # - # ######### # - # # ########### # # - # # ############# # - # ############### # # # - # ################# # # - # ############# # - # ############### # - # ################# # - # ################### # - # # ##################### # - # ### # - # ### # # - # # ### # # - # # # - # # # - # # # - # # # # - # ############################### -``` \ No newline at end of file diff --git a/2024/Day14/Solution.cs b/2024/Day14/Solution.cs deleted file mode 100644 index 72850bf90..000000000 --- a/2024/Day14/Solution.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace AdventOfCode.Y2024.Day14; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -record struct Vec2(int x, int y); -record struct Robot(Vec2 pos, Vec2 vel); - -[ProblemName("Restroom Redoubt")] -class Solution : Solver { - const int width = 101; - const int height = 103; - - // run the simulation for 100 steps and count the robots in the different quadrants. - public object PartOne(string input) => - Simulate(input) - .ElementAt(100) - .CountBy(GetQuadrant) - .Where(group => group.Key.x != 0 && group.Key.y != 0) - .Aggregate(1, (acc, group) => acc * group.Value); - - // I figured that the xmas tree pattern has a long horizontal ### pattern in it - public object PartTwo(string input) => - Simulate(input) - .TakeWhile(robots => !Plot(robots).Contains("#################")) - .Count(); - - // an infinite simulation of robot movement - IEnumerable Simulate(string input) { - var robots = Parse(input).ToArray(); - while (true) { - yield return robots; - robots = robots.Select(Step).ToArray(); - } - } - - // advance a robot by its velocity taking care of the 'teleportation' - Robot Step(Robot robot) => robot with {pos = AddWithWrapAround(robot.pos, robot.vel) }; - - // returns the direction (-1/0/1) of the robot to the center of the room - Vec2 GetQuadrant(Robot robot) => - new Vec2(Math.Sign(robot.pos.x - width / 2), Math.Sign(robot.pos.y - height / 2)); - - Vec2 AddWithWrapAround(Vec2 a, Vec2 b) => - new Vec2((a.x + b.x + width) % width, (a.y + b.y + height) % height); - - // shows the robot locations in the room - string Plot(IEnumerable robots) { - var res = new char[height, width]; - foreach (var robot in robots) { - res[robot.pos.y, robot.pos.x] = '#'; - } - var sb = new StringBuilder(); - for (var y = 0; y < height; y++) { - for (var x = 0; x < width; x++) { - sb.Append(res[y, x] == '#' ? "#" : " "); - } - sb.AppendLine(); - } - return sb.ToString(); - } - - IEnumerable Parse(string input) => - from line in input.Split("\n") - let nums = Regex.Matches(line, @"-?\d+").Select(m => int.Parse(m.Value)).ToArray() - select new Robot(new Vec2(nums[0], nums[1]), new Vec2(nums[2], nums[3])); -} \ No newline at end of file diff --git a/2024/Day14/illustration.jpeg b/2024/Day14/illustration.jpeg deleted file mode 100644 index 1fdaa3615..000000000 Binary files a/2024/Day14/illustration.jpeg and /dev/null differ diff --git a/2024/Day14/input.in b/2024/Day14/input.in deleted file mode 100644 index 28019ec95..000000000 Binary files a/2024/Day14/input.in and /dev/null differ diff --git a/2024/Day14/input.refout b/2024/Day14/input.refout deleted file mode 100644 index 34259b6fe..000000000 --- a/2024/Day14/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -231019008 -8280 \ No newline at end of file diff --git a/2024/Day15/README.md b/2024/Day15/README.md deleted file mode 100644 index 0e8fd4eb6..000000000 --- a/2024/Day15/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## --- Day 15: Warehouse Woes --- -You appear back inside your own mini submarine! Each Historian drives their mini submarine in a different direction; maybe the Chief has his own submarine down here somewhere as well? - -You look up to see a vast school of [lanternfish](/2021/day/6) swimming past you. On closer inspection, they seem quite anxious, so you drive your mini submarine over to see if you can help. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/15) description._ - -A nice Sokoban-style puzzle for the weekend! The main difference is that in the original Sokoban, the robot could push only a single box, not multiple boxes. This adds complexity to both parts of the puzzle. However, it’s not that difficult to handle... I moved the hard parts into the `TryToStep` function that takes the map, a position, and a direction, then attempts to make a move in that direction. - -If the position corresponds to the robot or a box, the function checks whether the neighboring cell is free or can be made free by pushing boxes in the given direction. The .NET API sometimes uses the `TryToDoX` pattern, where a function returns a boolean result and provides an `out` parameter. I reused this pattern here. On success, the updated map is returned via the `ref` parameter. If the move fails, the map remains unchanged. - -The real challenge lies in `part 2`, where recursion needs to branch whenever the robot pushes more than one box at a time. In such cases, we must invoke `TryToStep` for each box. Due to the recursive nature of the algorithm, it’s possible for one branch to succeed while the other fails. When this happens, the entire map must be reset to its original state before we pop from the recursion. This could be quite tricky to manage unless you make copies of the dictionary that holds the state — or, as I did, use an immutable dictionary instead. - -I’m not entirely satisfied with the "if-ladder" structure of the `TryToStep` function, but for now, I don’t have a better idea to handle all the cases in a more readable way. diff --git a/2024/Day15/Solution.cs b/2024/Day15/Solution.cs deleted file mode 100644 index 35261aa50..000000000 --- a/2024/Day15/Solution.cs +++ /dev/null @@ -1,110 +0,0 @@ -namespace AdventOfCode.Y2024.Day15; - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Numerics; - -using Map = System.Collections.Immutable.IImmutableDictionary; - -[ProblemName("Warehouse Woes")] -class Solution : Solver { - - static Complex Up = -Complex.ImaginaryOne; - static Complex Down = Complex.ImaginaryOne; - static Complex Left = -1; - static Complex Right = 1; - - public object PartOne(string input) => Solve(input); - public object PartTwo(string input) => Solve(ScaleUp(input)); - - public double Solve(string input) { - var (map, steps) = Parse(input); - - var robot = map.Keys.Single(k => map[k] == '@'); - foreach (var dir in steps) { - if (TryToStep(ref map, robot, dir)) { - robot += dir; - } - } - - return map.Keys - .Where(k => map[k] == '[' || map[k] == 'O') - .Sum(box => box.Real + 100 * box.Imaginary); - } - - // Attempts to move the robot in the given direction on the map, pushing boxes as necessary. - // If the move is successful, the map is updated to reflect the new positions and the function returns true. - // Otherwise, the map remains unchanged and the function returns false. - bool TryToStep(ref Map map, Complex pos, Complex dir) { - var mapOrig = map; - - if (map[pos] == '.') { - return true; - } else if (map[pos] == 'O' || map[pos] == '@') { - if (TryToStep(ref map, pos + dir, dir)) { - map = map - .SetItem(pos + dir, map[pos]) - .SetItem(pos, '.'); - return true; - } - } else if (map[pos] == ']') { - return TryToStep(ref map, pos + Left, dir); - } else if (map[pos] == '[') { - if (dir == Left) { - if (TryToStep(ref map, pos + Left, dir)) { - map = map - .SetItem(pos + Left, '[') - .SetItem(pos, ']') - .SetItem(pos + Right, '.'); - return true; - } - } else if (dir == Right) { - if (TryToStep(ref map, pos + 2 * Right, dir)) { - map = map - .SetItem(pos, '.') - .SetItem(pos + Right, '[') - .SetItem(pos + 2 * Right, ']'); - return true; - } - } else { - if (TryToStep(ref map, pos + dir, dir) && TryToStep(ref map, pos + Right + dir, dir)) { - map = map - .SetItem(pos, '.') - .SetItem(pos + Right, '.') - .SetItem(pos + dir, '[') - .SetItem(pos + dir + Right, ']'); - return true; - } - } - } - - map = mapOrig; - return false; - } - - string ScaleUp(string input) => - input.Replace("#", "##").Replace(".", "..").Replace("O", "[]").Replace("@", "@."); - - (Map, Complex[]) Parse(string input) { - var blocks = input.Split("\n\n"); - var lines = blocks[0].Split("\n"); - var map = ( - 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]) - ).ToImmutableDictionary(); - - var steps = blocks[1].ReplaceLineEndings("").Select(ch => - ch switch { - '^' => Up, - '<' => Left, - '>' => Right, - 'v' => Down, - _ => throw new Exception() - }); - - return (map, steps.ToArray()); - } -} diff --git a/2024/Day15/illustration.jpeg b/2024/Day15/illustration.jpeg deleted file mode 100644 index 75f133b4a..000000000 Binary files a/2024/Day15/illustration.jpeg and /dev/null differ diff --git a/2024/Day15/input.in b/2024/Day15/input.in deleted file mode 100644 index 4641e0ca4..000000000 Binary files a/2024/Day15/input.in and /dev/null differ diff --git a/2024/Day15/input.refout b/2024/Day15/input.refout deleted file mode 100644 index 2c35fe07a..000000000 --- a/2024/Day15/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1476771 -1468005 \ No newline at end of file diff --git a/2024/Day16/README.md b/2024/Day16/README.md deleted file mode 100644 index 160ab57ff..000000000 --- a/2024/Day16/README.md +++ /dev/null @@ -1,12 +0,0 @@ -## --- Day 16: Reindeer Maze --- -It's time again for the _Reindeer Olympics_! This year, the big event is the Reindeer Maze, where the Reindeer compete for the lowest score. - -You and The Historians arrive to search for the Chief right as the event is about to start. It wouldn't hurt to watch a little, right? - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/16) description._ - -I spent hell a lot of time on this one. I’m not sure why, because I had a good understanding of what to do for both parts. `Part 1` went reasonably well: I quickly used a priority queue based approach to find the shortest path from the `start` state to the `goal`. - -For `Part 2`, I tried a few dead ends, because I overcomplicate things as usual. But I found the right direction after about half an hour. The idea is to split the problem into two halves. First, we compute the optimal distances from every tile and direction to the goal node. This can be found using _Dijskstra's algorithm_. - -Once I have the distances, I can start an other round, now working forward from the start position and using a flood-fill-like algorithm to discover the positions on the shortest path. This is easy to do with the distance map as a guide. I maintain the 'remaining score' along the path, and just need to check if the distance from a potential next state equals to the score I still have to use. This logic can be found in the `FindBestSpots` function. diff --git a/2024/Day16/Solution.cs b/2024/Day16/Solution.cs deleted file mode 100644 index 89f5bd78e..000000000 --- a/2024/Day16/Solution.cs +++ /dev/null @@ -1,98 +0,0 @@ -namespace AdventOfCode.Y2024.Day16; - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Numerics; -using AngleSharp.Common; -using Map = System.Collections.Generic.Dictionary; -using State = (System.Numerics.Complex pos, System.Numerics.Complex dir); - -[ProblemName("Reindeer Maze")] -class Solution : Solver { - - static readonly Complex North = -Complex.ImaginaryOne; - static readonly Complex South = Complex.ImaginaryOne; - static readonly Complex West = -1; - static readonly Complex East = 1; - - public object PartOne(string input) => FindBestScore(GetMap(input)); - public object PartTwo(string input) => FindBestSpots(GetMap(input)); - - int FindBestScore(Map map) => Dijkstra(map, Goal(map))[Start(map)]; - - int FindBestSpots(Map map) { - var dist = Dijkstra(map, Goal(map)); - var start = Start(map); - - // track the shortest paths using the distance map as guideline. - var q = new PriorityQueue(); - q.Enqueue(start, dist[start]); - - var bestSpots = new HashSet { start }; - while (q.TryDequeue(out var state, out var remainingScore)) { - foreach (var (next, score) in Steps(map, state, forward: true)) { - var nextRemainingScore = remainingScore - score; - if (!bestSpots.Contains(next) && dist[next] == nextRemainingScore) { - bestSpots.Add(next); - q.Enqueue(next, nextRemainingScore); - } - } - } - return bestSpots.DistinctBy(state => state.pos).Count(); - } - - Dictionary Dijkstra(Map map, Complex goal) { - // Dijkstra algorithm; works backwards from the goal, returns the - // distances to _all_ tiles and directions. - var dist = new Dictionary(); - - var q = new PriorityQueue(); - foreach (var dir in new[]{North, East, West, South}) { - q.Enqueue((goal, dir), 0); - dist[(goal, dir)] = 0; - } - - while (q.TryDequeue(out var cur, out var totalDistance)) { - foreach (var (next, score) in Steps(map, cur, forward: false)) { - var nextCost = totalDistance + score; - if (nextCost < dist.GetOrDefault(next, int.MaxValue)) { - q.Remove(next, out _, out _, null); - dist[next] = nextCost; - q.Enqueue(next, nextCost); - } - } - } - return dist; - } - - // returns the possible next or previous states and the associated costs for a given state. - // in forward mode we scan the possible states from the start state towards the goal. - // in backward mode we are working backwards from the goal to the start. - IEnumerable<(State, int cost)> Steps(Map map, State state, bool forward) { - foreach (var dir in new[]{North, East, West, South}) { - if (dir == state.dir) { - var pos = forward ? state.pos + dir : state.pos - dir; - if (map.GetValueOrDefault(pos) != '#') { - yield return ((pos, dir), 1); - } - } else if (dir != -state.dir) { - yield return ((state.pos, dir), 1000); - } - } - } - - // 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 * South, map[y][x]) - ).ToDictionary(); - } - Complex Goal(Map map) => map.Keys.Single(k => map[k] == 'E'); - State Start(Map map) => (map.Keys.Single(k => map[k] == 'S'), East); -} \ No newline at end of file diff --git a/2024/Day16/illustration.jpeg b/2024/Day16/illustration.jpeg deleted file mode 100644 index 2e27f1e4b..000000000 Binary files a/2024/Day16/illustration.jpeg and /dev/null differ diff --git a/2024/Day16/input.in b/2024/Day16/input.in deleted file mode 100644 index 44464bc38..000000000 Binary files a/2024/Day16/input.in and /dev/null differ diff --git a/2024/Day16/input.refout b/2024/Day16/input.refout deleted file mode 100644 index 6d050d07f..000000000 --- a/2024/Day16/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -130536 -1024 \ No newline at end of file diff --git a/2024/Day17/README.md b/2024/Day17/README.md deleted file mode 100644 index dcddf5cf2..000000000 --- a/2024/Day17/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## --- Day 17: Chronospatial Computer --- -The Historians push the button on their strange device, but this time, you all just feel like you're _falling_. - -"Situation critical", the device announces in a familiar voice. "Bootstrapping process failed. Initializing debugger...." - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/17) description._ - -I'm not a big fan of _disassembly_ tasks, but they come up almost every year. The first part of the problem, which -I _actually_ liked, was to write an interpreter for an elvish computer (i.e. one with a weird instruction set). This -is really easy to do with a simple for loop and switching on the different opcodes. - -The second half was a bit harder, as I had to understand what's going on in the program. We had to generate inputs that -would force the program to print out its own source. Well, a _quine_ is a computer program that takes no input and -produces a copy of its own source code as its only output. Although our program was not a real quine, I couldn't help -but smile when I read the problem description in the morning. - -Fortunately, the algorithm was not that complicated once I realized that the _next output number_ depends only on the -_lowest few bits_ of the input. Then the input gets shifted by a small amount, and this continues until the end. - -There is _some interconnection_ between the consecutive numbers, so one cannot just calculate the result independently -for each. But I was able to come up with a _recursive solution_ that generates the input _backwards_. Once we know the -higher bits, we can try all combinations for the next 3 bits, and so on down to the first bit. - -As an added bonus I implemented (part of) the emulator in [VIC-20 BASIC](https://hu.wikipedia.org/wiki/Commodore_VIC-20). -This is how it runs the second sample that prints out its own source code. - -![vic20.gif](vic20.gif) \ No newline at end of file diff --git a/2024/Day17/Solution.cs b/2024/Day17/Solution.cs deleted file mode 100644 index b5e44d86e..000000000 --- a/2024/Day17/Solution.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace AdventOfCode.Y2024.Day17; - -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -[ProblemName("Chronospatial Computer")] -class Solution : Solver { - - enum Opcode { - Adv, Bxl, Bst, Jnz, Bxc, Out, Bdv, Cdv - } - - public object PartOne(string input) { - var (state, program) = Parse(input); - return string.Join(",", Run(state, program)); - } - public object PartTwo(string input) { - var (_, program) = Parse(input); - return GenerateA(program, program).Min(); - } - - List Run(List state, List program) { - var combo = (int op) => op < 4 ? op : state[op - 4]; - var res = new List(); - for (var ip = 0; ip < program.Count; ip += 2) { - switch ((Opcode)program[ip], (int)program[ip + 1]) { - case (Opcode.Adv, var op): state[0] = state[0] >> (int)combo(op); break; - case (Opcode.Bdv, var op): state[1] = state[0] >> (int)combo(op); break; - case (Opcode.Cdv, var op): state[2] = state[0] >> (int)combo(op); break; - case (Opcode.Bxl, var op): state[1] = state[1] ^ op; break; - case (Opcode.Bst, var op): state[1] = combo(op) % 8; break; - case (Opcode.Jnz, var op): ip = state[0] == 0 ? ip : op - 2; break; - case (Opcode.Bxc, var op): state[1] = state[1] ^ state[2]; break; - case (Opcode.Out, var op): res.Add(combo(op) % 8); break; - } - } - return res; - } - - /* - Determines register A for the given output. The search works recursively and in - reverse order, starting from the last number to be printed and ending with the first. - */ - IEnumerable GenerateA(List program, List output) { - if (!output.Any()) { - yield return 0; - yield break; - } - - foreach (var ah in GenerateA(program, output[1..])) { - for (var al = 0; al < 8; al++) { - var a = ah * 8 + al; - if (Run([a, 0, 0], program).SequenceEqual(output)) { - yield return a; - } - } - } - } - - (List state, List program) Parse(string input) { - var blocks = input.Split("\n\n").Select(ParseNums).ToArray(); - return (blocks[0], blocks[1]); - } - - List ParseNums(string st) => - Regex.Matches(st, @"\d+", RegexOptions.Multiline) - .Select(m => long.Parse(m.Value)) - .ToList(); -} \ No newline at end of file diff --git a/2024/Day17/illustration.jpeg b/2024/Day17/illustration.jpeg deleted file mode 100644 index 001875746..000000000 Binary files a/2024/Day17/illustration.jpeg and /dev/null differ diff --git a/2024/Day17/input.in b/2024/Day17/input.in deleted file mode 100644 index 593be0de4..000000000 Binary files a/2024/Day17/input.in and /dev/null differ diff --git a/2024/Day17/input.refout b/2024/Day17/input.refout deleted file mode 100644 index fa0a5d5c9..000000000 --- a/2024/Day17/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1,5,0,5,2,0,1,3,5 -236581108670061 \ No newline at end of file diff --git a/2024/Day17/vic20.gif b/2024/Day17/vic20.gif deleted file mode 100644 index ab0829883..000000000 Binary files a/2024/Day17/vic20.gif and /dev/null differ diff --git a/2024/Day18/README.md b/2024/Day18/README.md deleted file mode 100644 index 3f8903f0a..000000000 --- a/2024/Day18/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## --- Day 18: RAM Run --- -You and The Historians look a lot more pixelated than you remember. You're _inside a computer_ at the North Pole! - -Just as you're about to check out your surroundings, a program runs up to you. "This region of memory isn't safe! The User misunderstood what a [pushdown automaton](https://en.wikipedia.org/wiki/Pushdown_automaton) is and their algorithm is pushing whole bytes down on top of us! Run!" - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/18) description._ - -We got a simple path finding problem for today. I implemented a _binary search_ for the second part. \ No newline at end of file diff --git a/2024/Day18/Solution.cs b/2024/Day18/Solution.cs deleted file mode 100644 index bc9747461..000000000 --- a/2024/Day18/Solution.cs +++ /dev/null @@ -1,64 +0,0 @@ -namespace AdventOfCode.Y2024.Day18; - -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Numerics; -using AngleSharp.Common; - -[ProblemName("RAM Run")] -class Solution : Solver { - - public object PartOne(string input) => Distance(GetBlocks(input).Take(1024)); - - public object PartTwo(string input) { - // find the first block position that will cut off the goal position - // we can use a binary search for this - - var blocks = GetBlocks(input); - var (lo, hi) = (0, blocks.Length); - while (hi - lo > 1) { - var m = (lo + hi) / 2; - if (Distance(blocks.Take(m)) == null) { - hi = m; - } else { - lo = m; - } - } - return $"{blocks[lo].Real},{blocks[lo].Imaginary}"; - } - - int? Distance(IEnumerable blocks) { - // our standard priority queue based path finding - - var size = 70; - var (start, goal) = (0, size + size * Complex.ImaginaryOne); - var blocked = blocks.Concat(start).ToHashSet(); - - var q = new PriorityQueue(); - q.Enqueue(start, 0); - while (q.TryDequeue(out var pos, out var dist)) { - if (pos == goal) { - return dist; - } - - foreach (var dir in new[] { 1, -1, Complex.ImaginaryOne, -Complex.ImaginaryOne }) { - var posT = pos + dir; - if (!blocked.Contains(posT) && - 0 <= posT.Imaginary && posT.Imaginary <= size && - 0 <= posT.Real && posT.Real <= size - ) { - q.Enqueue(posT, dist + 1); - blocked.Add(posT); - } - } - } - return null; - } - - Complex[] GetBlocks(string input) => ( - from line in input.Split("\n") - let nums = Regex.Matches(line, @"\d+").Select(m => int.Parse(m.Value)).ToArray() - select nums[0] + nums[1] * Complex.ImaginaryOne - ).ToArray(); -} \ No newline at end of file diff --git a/2024/Day18/illustration.jpeg b/2024/Day18/illustration.jpeg deleted file mode 100644 index 12a134ec2..000000000 Binary files a/2024/Day18/illustration.jpeg and /dev/null differ diff --git a/2024/Day18/input.in b/2024/Day18/input.in deleted file mode 100644 index bc02b11cd..000000000 Binary files a/2024/Day18/input.in and /dev/null differ diff --git a/2024/Day18/input.refout b/2024/Day18/input.refout deleted file mode 100644 index db6793b1f..000000000 --- a/2024/Day18/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -338 -20,44 \ No newline at end of file diff --git a/2024/Day19/README.md b/2024/Day19/README.md deleted file mode 100644 index 91ef262a7..000000000 --- a/2024/Day19/README.md +++ /dev/null @@ -1,15 +0,0 @@ -## --- Day 19: Linen Layout --- -Today, The Historians take you up to the _hot springs_ on Gear Island! Very [suspiciously](https://www.youtube.com/watch?v=ekL881PJMjI), absolutely nothing goes wrong as they begin their careful search of the vast field of helixes. - -Could this finally be your chance to visit the [onsen](https://en.wikipedia.org/wiki/Onsen) next door? Only one way to find out. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/19) description._ - -I initially thought that I would be able to entirely solve today's problem using regular expressions. This worked for Part 1, but unfortunately, the regex library can only determine whether a pattern matches a string — it cannot return the number of ways the match can occur. Not that it’s its job anyway... - -I had to implement the search function myself. It’s a simple recursive function that iterates through all towels and tries to match them to the beginning of the pattern. If a match is found, it continues recursively with the remaining pattern until the entire pattern becomes an empty string, which signifies a complete match. - -Of course, this approach would never terminate as-is, it needs to be converted into a cached function. Thankfully, this is straightforward to do using a _ConcurrentDictionary_, which I discovered earlier this year. By utilizing the _GetOrAdd_ method of -the _ConcurrentDictionary_ class, one can simply wrap the uncached logic inside a lambda and call it a day. - -It’s very similar to Python’s cached function decorators, albeit with the caveat of having to pass an additional 'cache' argument at the end of the parameter list. But since we’re in the world of C#, we have to work with what it offers. diff --git a/2024/Day19/Solution.cs b/2024/Day19/Solution.cs deleted file mode 100644 index 952efada5..000000000 --- a/2024/Day19/Solution.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace AdventOfCode.Y2024.Day19; - -using System; -using System.Collections.Generic; -using System.Linq; - -using Cache = System.Collections.Concurrent.ConcurrentDictionary; - -[ProblemName("Linen Layout")] -class Solution : Solver { - - public object PartOne(string input) => MatchCounts(input).Count(c => c != 0); - - public object PartTwo(string input) => MatchCounts(input).Sum(); - - IEnumerable MatchCounts(string input) { - var blocks = input.Split("\n\n"); - var towels = blocks[0].Split(", "); - return - from pattern in blocks[1].Split("\n") - select MatchCount(towels, pattern, new Cache()); - } - - // computes the number of ways the pattern can be build up from the towels. - // works recursively by matching the prefix of the pattern with each towel. - // a full match is found when the pattern becomes empty. the cache is applied - // to _drammatically_ speed up execution - long MatchCount(string[] towels, string pattern, Cache cache) => - cache.GetOrAdd(pattern, (pattern) => - pattern switch { - "" => 1, - _ => towels - .Where(pattern.StartsWith) - .Sum(towel => MatchCount(towels, pattern[towel.Length ..], cache)) - } - ); -} \ No newline at end of file diff --git a/2024/Day19/illustration.jpeg b/2024/Day19/illustration.jpeg deleted file mode 100644 index 6a4aa3f54..000000000 Binary files a/2024/Day19/illustration.jpeg and /dev/null differ diff --git a/2024/Day19/input.in b/2024/Day19/input.in deleted file mode 100644 index c718fe1b3..000000000 Binary files a/2024/Day19/input.in and /dev/null differ diff --git a/2024/Day19/input.refout b/2024/Day19/input.refout deleted file mode 100644 index 92770631d..000000000 --- a/2024/Day19/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -333 -678536865274732 \ No newline at end of file diff --git a/2024/Day20/README.md b/2024/Day20/README.md deleted file mode 100644 index 76d9ad9bb..000000000 --- a/2024/Day20/README.md +++ /dev/null @@ -1,22 +0,0 @@ -## --- Day 20: Race Condition --- -The Historians are quite pixelated again. This time, a massive, black building looms over you - you're _right outside_ the CPU! - -While The Historians get to work, a nearby program sees that you're idle and challenges you to a race. Apparently, you've arrived just in time for the frequently-held race condition festival! - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/20) description._ - -The problem included a small but crucial hint: _there is only a single path from the start to the end_. Moreover, there are no dead ends in the input; it's just a single, continuous trace. - -The definition of _cheating_ was super hard to understand. I have to admit that instead, I used my intuition and used a more simple definition: in cheat mode you can step to any cell within the distance of 2 (or 20 for the second part). This really worked. - -I created a function that returns the points of the track in finish to start order. This way, the _index_ of an item in the array corresponds to its distance to the finish line. - -Then, I go over the path. For each position, the number of possible cheats is calculated by checking what happens if we are trying to make a shortcut to any other positions around. - -There are a number of cases to consider: -- the target position is too far away. This happens when its Manhattan distance is greater than the allowed _cheat_ limit -- the target is within range, but actually further away from the finish than we are (the saving is negative). -- the target is within range, closer to the finish, but the saving is still less than 100 -- the target is within range, and the saving is at least 100 - -We need to determine the number of good cheats for each position _add_ them up. I used Parallel LINQ here, as the regular sequential one took significantly more time. diff --git a/2024/Day20/Solution.cs b/2024/Day20/Solution.cs deleted file mode 100644 index d56acd386..000000000 --- a/2024/Day20/Solution.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace AdventOfCode.Y2024.Day20; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; - -[ProblemName("Race Condition")] -class Solution : Solver { - - public object PartOne(string input) => Solve(input, 2); - public object PartTwo(string input) => Solve(input, 20); - - int Solve(string input, int cheat) { - var path = GetPath(input); - var indices = Enumerable.Range(0, path.Length).ToArray(); - - // sum up the worthy cheats for each index along the path - var cheatsFromI = (int i) => ( - from j in indices[0..i] - let dist = Manhattan(path[i], path[j]) - let saving = i - (j + dist) - where dist <= cheat && saving >= 100 - select 1 - ).Sum(); - - // parallel is gold today, it gives us an 3-4x boost - return indices.AsParallel().Select(cheatsFromI).Sum(); - } - - int Manhattan(Complex a, Complex b) => - (int)(Math.Abs(a.Imaginary - b.Imaginary) + Math.Abs(a.Real - b.Real)); - - // Follow the path from finish to start, supposed that there is a single track in the input. - // The index of a position in the returned array equals to its distance from the finish - Complex[] GetPath(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(x + y * Complex.ImaginaryOne, lines[y][x]) - ).ToDictionary(); - - Complex[] dirs = [-1, 1, Complex.ImaginaryOne, -Complex.ImaginaryOne]; - - var start = map.Keys.Single(k => map[k] == 'S'); - var goal = map.Keys.Single(k => map[k] == 'E'); - - var (prev, cur) = ((Complex?)null, goal); - var res = new List { cur }; - - while (cur != start) { - var dir = dirs.Single(dir => map[cur + dir] != '#' && cur + dir != prev); - (prev, cur) = (cur, cur + dir); - res.Add(cur); - } - return res.ToArray(); - } -} \ No newline at end of file diff --git a/2024/Day20/illustration.jpeg b/2024/Day20/illustration.jpeg deleted file mode 100644 index dc1389f34..000000000 Binary files a/2024/Day20/illustration.jpeg and /dev/null differ diff --git a/2024/Day20/input.in b/2024/Day20/input.in deleted file mode 100644 index 3a67ed17b..000000000 Binary files a/2024/Day20/input.in and /dev/null differ diff --git a/2024/Day20/input.refout b/2024/Day20/input.refout deleted file mode 100644 index a7c19236d..000000000 --- a/2024/Day20/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1384 -1008542 \ No newline at end of file diff --git a/2024/Day21/README.md b/2024/Day21/README.md deleted file mode 100644 index a10d58bb1..000000000 --- a/2024/Day21/README.md +++ /dev/null @@ -1,23 +0,0 @@ -## --- Day 21: Keypad Conundrum --- -As you teleport onto Santa's _Reindeer-class starship_, The Historians begin to panic: someone from their search party is missing. A quick life-form scan by the ship's computer reveals that when the missing Historian teleported, he arrived in another part of the ship. - -The door to that area is locked, but the computer can't open it; it can only be opened by physically typing the door codes (your puzzle input) on the numeric keypad on the door. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/21) description._ - -This is the problem that sets casual players apart competitors. I had a hard time solving it. I think I was on track, but -I just couldn't visualize the whole idea of robots controlling robots controlling robots. I love recursion, but just -cannot mentally follow multiple layers of indirection. Anyway. I could solve it in the evening hours, so I'm still on track with _Advent of Code 2024_. - -It was clear from the exponential growth demonstrated by _part 1_ that I wont be able to generate the final string to -be entered. Luckily the problem asked only for the length of it. (Which makes it really artifical: how would the elves enter -such a long key?) - -I created a function called `EncodeKeys` which takes a sequence of keys to be pressed and an array of keypads, and returns the length of the shortest sequence needed to enter the given keys. An empty keypad array means that the sequence is simply entered by a human and no further encoding is needed. Otherwise, the sequence is entered by a robot that needs to be programmed using its keypad. In this case the keys are encoded using the first keypad in the array (the robot's keypad), character by character using _EncodeKey_ which will recursively call back to `EncodeKeys` with the rest of the keypads. - -The `_EncodeKey_` helper function is used to move the robot from position _A_ to position _B_ on the keypad and press the button. Usually, _A_ and _B_ are not in the same row and column, so the movement has both a horizontal and a vertical part. We could go both ways: horizontal first then vertical, or the other way around, and we need to check which movement results in fewer key presses. Lastly, we should not forget that the robot's hand should never move over the empty space `' '`. - -Since every key sequence we need to enter ends with a button press `'A'`, we can always be sure that the robot will stay over the `'A'` button at the end. Since it initially starts over the `'A'` key as well, we have an invariant: at the beginning and the end of `EncodeKeys`, the robot is over the `'A'` key. It can move around while entering the keys, but the invariant holds when it finishes. - -This is great because we don't have to keep track of it! The `Cache` used by `EncodeKey` doesn't need to care about the robot's position recursively. All it depends on is the current robot's position, the position of the next key to be entered, and the number of keypads left in the recursion. This reduces the problem space quite a bit and gives us a well-performing algorithm. - diff --git a/2024/Day21/Solution.cs b/2024/Day21/Solution.cs deleted file mode 100644 index 99cf4d96f..000000000 --- a/2024/Day21/Solution.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace AdventOfCode.Y2024.Day21; - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; - -using Cache = System.Collections.Concurrent.ConcurrentDictionary<(char currentKey, char nextKey, int depth), long>; -using Keypad = System.Collections.Generic.Dictionary; -record struct Vec2(int x, int y); - -[ProblemName("Keypad Conundrum")] -class Solution : Solver { - - public object PartOne(string input) => Solve(input, 2); - - public object PartTwo(string input) => Solve(input, 25); - - long Solve(string input, int depth) { - var keypad1 = ParseKeypad("789\n456\n123\n 0A"); - var keypad2 = ParseKeypad(" ^A\n"); - var keypads = Enumerable.Repeat(keypad2, depth).Prepend(keypad1).ToArray(); - - var cache = new Cache(); - var res = 0L; - - foreach (var line in input.Split("\n")) { - var num = int.Parse(line[..^1]); - res += num * EncodeKeys(line, keypads, cache); - } - return res; - } - - // Determines the length of the shortest sequence that is needed to enter the given - // keys. An empty keypad array means that the sequence is simply entered by a human - // and no further encoding is needed. Otherwise the sequence is entered by a robot - // which needs to be programmed. In practice this means that the keys are encoded - // using the robots keypad (the first keypad), generating an other sequence of keys. - // This other sequence is then recursively encoded using the rest of the keypads. - long EncodeKeys(string keys, Keypad[] keypads, Cache cache) { - if (keypads.Length == 0) { - return keys.Length; - } else { - // invariant: the robot starts and finishes by pointing at the 'A' key - var currentKey = 'A'; - var length = 0L; - - foreach (var nextKey in keys) { - length += EncodeKey(currentKey, nextKey, keypads, cache); - // while the sequence is entered the current key changes accordingly - currentKey = nextKey; - } - - // at the end the current key should be reset to 'A' - Debug.Assert(currentKey == 'A', "The robot should point at the 'A' key"); - return length; - } - } - long EncodeKey(char currentKey, char nextKey, Keypad[] keypads, Cache cache) => - cache.GetOrAdd((currentKey, nextKey, keypads.Length), _ => { - var keypad = keypads[0]; - - var currentPos = keypad.Single(kvp => kvp.Value == currentKey).Key; - var nextPos = keypad.Single(kvp => kvp.Value == nextKey).Key; - - var dy = nextPos.y - currentPos.y; - var vert = new string(dy < 0 ? 'v' : '^', Math.Abs(dy)); - - var dx = nextPos.x - currentPos.x; - var horiz = new string(dx < 0 ? '<' : '>', Math.Abs(dx)); - - var cost = long.MaxValue; - // we can usually go vertical first then horizontal or vica versa, - // but we should check for the extra condition and don't position - // the robot over the ' ' key: - if (keypad[new Vec2(currentPos.x, nextPos.y)] != ' ') { - cost = Math.Min(cost, EncodeKeys($"{vert}{horiz}A", keypads[1..], cache)); - } - - if (keypad[new Vec2(nextPos.x, currentPos.y)] != ' ') { - cost = Math.Min(cost, EncodeKeys($"{horiz}{vert}A", keypads[1..], cache)); - } - return cost; - }); - - Keypad ParseKeypad(string keypad) { - var lines = keypad.Split("\n"); - return ( - from y in Enumerable.Range(0, lines.Length) - from x in Enumerable.Range(0, lines[0].Length) - select new KeyValuePair(new Vec2(x, -y), lines[y][x]) - ).ToDictionary(); - } -} \ No newline at end of file diff --git a/2024/Day21/illustration.jpeg b/2024/Day21/illustration.jpeg deleted file mode 100644 index 00430c919..000000000 Binary files a/2024/Day21/illustration.jpeg and /dev/null differ diff --git a/2024/Day21/input.in b/2024/Day21/input.in deleted file mode 100644 index a7fdffcf2..000000000 Binary files a/2024/Day21/input.in and /dev/null differ diff --git a/2024/Day21/input.refout b/2024/Day21/input.refout deleted file mode 100644 index 5aa4febc5..000000000 --- a/2024/Day21/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -176650 -217698355426872 \ No newline at end of file diff --git a/2024/Day22/README.md b/2024/Day22/README.md deleted file mode 100644 index 4358da5ea..000000000 --- a/2024/Day22/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## --- Day 22: Monkey Market --- -As you're all teleported deep into the jungle, a _monkey_ steals The Historians' device! You'll need get it back while The Historians are looking for the Chief. - -The monkey that stole the device seems willing to trade it, but only in exchange for an absurd number of bananas. Your only option is to buy bananas on the Monkey Exchange Market. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/22) description._ - -A refreshing challenge after yesterday's hard one. I created a secret number generator function that returns the 2001 numbers for each seller (the initial one and the 2000 additional). This is enough for _Part 1_. - -For _Part 2_ I maintain the dictionary of buying options for each potential sequence the monkey can recognize with the -combined amount of bananas this would generate from all sellers. \ No newline at end of file diff --git a/2024/Day22/Solution.cs b/2024/Day22/Solution.cs deleted file mode 100644 index 6a81e92de..000000000 --- a/2024/Day22/Solution.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace AdventOfCode.Y2024.Day22; - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -[ProblemName("Monkey Market")] -class Solution : Solver { - - public object PartOne(string input) { - return GetNums(input).Select(x => (long)SecretNumbers(x).Last()).Sum(); - } - - public object PartTwo(string input) { - // create a dictionary of all buying options then select the one with the most banana: - - var buyingOptions = new Dictionary<(int,int,int,int), int>(); - - foreach (var num in GetNums(input)) { - var optionsBySeller = BuyingOptions(num); - foreach (var seq in optionsBySeller.Keys) { - buyingOptions[seq] = buyingOptions.GetValueOrDefault(seq) + optionsBySeller[seq]; - } - } - return buyingOptions.Values.Max(); - } - - Dictionary<(int,int,int,int), int> BuyingOptions(int seed) { - var bananasSold = Bananas(seed).ToArray(); - var buyingOptions = new Dictionary<(int,int,int,int), int>(); - - // a sliding window of 5 elements over the sold bananas defines the sequence the monkey - // will recognize. add the first occurrence of each sequence to the buyingOptions dictionary - // with the corresponding banana count - var diff = Diff(bananasSold); - for (var i = 0; i < bananasSold.Length - 4; i++) { - var seq = (diff[i], diff[i+1], diff[i+2], diff[i+3]); - if (!buyingOptions.ContainsKey(seq)) { - buyingOptions[seq] = bananasSold[i+4]; - } - } - return buyingOptions; - } - int[] Bananas(int seed) => SecretNumbers(seed).Select(n => n % 10).ToArray(); - - int[] Diff(IEnumerable x) => x.Zip(x.Skip(1)).Select(p => p.Second - p.First).ToArray(); - - IEnumerable SecretNumbers(int seed) { - var mixAndPrune = (int a, int b) => (a ^ b) & 0xffffff; - - yield return seed; - for (var i = 0; i < 2000; i++) { - seed = mixAndPrune(seed, seed << 6); - seed = mixAndPrune(seed, seed >> 5); - seed = mixAndPrune(seed, seed << 11); - yield return seed; - } - } - IEnumerable GetNums(string input) => input.Split("\n").Select(int.Parse); -} \ No newline at end of file diff --git a/2024/Day22/illustration.jpeg b/2024/Day22/illustration.jpeg deleted file mode 100644 index d0ba24944..000000000 Binary files a/2024/Day22/illustration.jpeg and /dev/null differ diff --git a/2024/Day22/input.in b/2024/Day22/input.in deleted file mode 100644 index c00da3dae..000000000 Binary files a/2024/Day22/input.in and /dev/null differ diff --git a/2024/Day22/input.refout b/2024/Day22/input.refout deleted file mode 100644 index 895648653..000000000 --- a/2024/Day22/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -18525593556 -2089 \ No newline at end of file diff --git a/2024/Day23/README.md b/2024/Day23/README.md deleted file mode 100644 index 1bc05ba21..000000000 --- a/2024/Day23/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## --- Day 23: LAN Party --- -As The Historians wander around a secure area at Easter Bunny HQ, you come across posters for a [LAN party](https://en.wikipedia.org/wiki/LAN_party) scheduled for today! Maybe you can find it; you connect to a nearby _datalink port_ and download a map of the local network (your puzzle input). - -The network map provides a list of every connection between two computers. For example: - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/23) description._ - -We tackled a graph algorithm problem today, where we had to find maximal cliques in an undirected graph. The literature provides [efficient algorithms](https://en.wikipedia.org/wiki/Bron%E2%80%93Kerbosch_algorithm) for this problem, but our graph is not too large, so we can use a straightforward "poor man's" strategy as well. - -I started with the _seed_ components, that is single element components for each node. Then, I proceeded to _grow_ these components by adding a single node to them in all possible ways. I can put this in a loop, to get components with size 2, 3, 4, etc. _Part 1_ asks for the number of components that have 3 nodes and have at least one node starting with 't'. _Part 2_ asks for the biggest component that cannot be grown anymore. \ No newline at end of file diff --git a/2024/Day23/Solution.cs b/2024/Day23/Solution.cs deleted file mode 100644 index e43da8f65..000000000 --- a/2024/Day23/Solution.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace AdventOfCode.Y2024.Day23; - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Graph = System.Collections.Generic.Dictionary>; -using Component = string; - -[ProblemName("LAN Party")] -class Solution : Solver { - public object PartOne(string input) { - var g = GetGraph(input); - var components = g.Keys.ToHashSet(); - components = Grow(g, components); - components = Grow(g, components); - return components.Count(c => Members(c).Any(m => m.StartsWith("t"))); - } - - public object PartTwo(string input) { - var g = GetGraph(input); - var components = g.Keys.ToHashSet(); - while (components.Count > 1) { - components = Grow(g, components); - } - return components.Single(); - } - - HashSet Grow(Graph g, HashSet components) => ( - from c in components.AsParallel() - let members = Members(c) - from neighbour in members.SelectMany(m => g[m]).Distinct() - where !members.Contains(neighbour) - where members.All(m => g[neighbour].Contains(m)) - select Extend(c, neighbour) - ).ToHashSet(); - - IEnumerable Members(Component c) => - c.Split(","); - Component Extend(Component c, string item) => - string.Join(",", Members(c).Append(item).OrderBy(x=>x)); - - Graph GetGraph(string input) { - var edges = - from line in input.Split("\n") - let nodes = line.Split("-") - from edge in new []{(nodes[0], nodes[1]), (nodes[1], nodes[0])} - select (From: edge.Item1, To: edge.Item2); - - return ( - from e in edges - group e by e.From into g - select (g.Key, g.Select(e => e.To).ToHashSet()) - ).ToDictionary(); - } -} \ No newline at end of file diff --git a/2024/Day23/illustration.jpeg b/2024/Day23/illustration.jpeg deleted file mode 100644 index 1a3da9908..000000000 Binary files a/2024/Day23/illustration.jpeg and /dev/null differ diff --git a/2024/Day23/input.in b/2024/Day23/input.in deleted file mode 100644 index 2233d6e98..000000000 Binary files a/2024/Day23/input.in and /dev/null differ diff --git a/2024/Day23/input.refout b/2024/Day23/input.refout deleted file mode 100644 index 18bc5052a..000000000 --- a/2024/Day23/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -1368 -dd,ig,il,im,kb,kr,pe,ti,tv,vr,we,xu,zi \ No newline at end of file diff --git a/2024/Day24/README.md b/2024/Day24/README.md deleted file mode 100644 index 5c708fc50..000000000 --- a/2024/Day24/README.md +++ /dev/null @@ -1,21 +0,0 @@ -## --- Day 24: Crossed Wires --- -You and The Historians arrive at the edge of a _large grove_ somewhere in the jungle. After the last incident, the Elves installed a small device that monitors the fruit. While The Historians search the grove, one of them asks if you can take a look at the monitoring device; apparently, it's been malfunctioning recently. - -The device seems to be trying to produce a number through some boolean logic gates. Each gate has two inputs and one output. The gates all operate on values that are either true (1) or false (0). - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/24) description._ - -The first half of the problem was a familiar logic circuit evaluator, we have done this before. I really liked the second part, although I don't have a super generic solution for it. I generated a graph from my input using Graphviz, then realized that the circuit tries to implement a Ripple-carry adder. - -A single full adder consists of two half adders: - -![half adder](halfadder.png) - -Which are chained one after the other like this to get a Ripple-carry adder: - -![full adder](adder.png) - -I took the images from [build-electronic-circuits.com](https://www.build-electronic-circuits.com/full-adder/). - -I implemented this logic in my 'fix' method. I start with the inputs x01 and y01 and try to identify the gates for the individual steps. Where I found an error, I manually checked my input to figure out what went wrong. I had just two different -kind of errors which can be corrected by the fixer. \ No newline at end of file diff --git a/2024/Day24/Solution.cs b/2024/Day24/Solution.cs deleted file mode 100644 index 0eed31740..000000000 --- a/2024/Day24/Solution.cs +++ /dev/null @@ -1,101 +0,0 @@ -namespace AdventOfCode.Y2024.Day24; - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Circuit = System.Collections.Generic.Dictionary; - -record struct Gate(string in1, string kind, string in2); - -[ProblemName("Crossed Wires")] -class Solution : Solver { - - public object PartOne(string input) { - var (inputs, circuit) = Parse(input); - - var outputs = from label in circuit.Keys where label.StartsWith("z") select label; - - var res = 0L; - foreach (var label in outputs.OrderByDescending(label=>label)) { - res = res * 2 + Eval(label, circuit, inputs); - } - return res; - } - - int Eval(string label, Circuit circuit, Dictionary inputs) { - if (inputs.TryGetValue(label, out var res)) { - return res; - } else { - return circuit[label] switch { - Gate(var in1, "AND", var in2) => Eval(in1, circuit, inputs) & Eval(in2, circuit, inputs), - Gate(var in1, "OR", var in2) => Eval(in1, circuit, inputs) | Eval(in2, circuit, inputs), - Gate(var in1, "XOR", var in2) => Eval(in1, circuit, inputs) ^ Eval(in2, circuit, inputs), - _ => throw new Exception(circuit[label].ToString()), - }; - } - } - - public object PartTwo(string input) { - var circuit = Parse(input).circuit; - return string.Join(",", Fix(circuit).OrderBy(label => label)); - } - - // the circuit should define a full adder for two 44 bit numbers - // this fixer is specific to my input. - IEnumerable Fix(Circuit circuit) { - var cin = Output(circuit, "x00", "AND", "y00"); - for (var i = 1; i < 45; i++) { - var x = $"x{i:D2}"; - var y = $"y{i:D2}"; - var z = $"z{i:D2}"; - - var xor1 = Output(circuit, x, "XOR", y); - var and1 = Output(circuit, x, "AND", y); - var xor2 = Output(circuit, cin, "XOR", xor1); - var and2 = Output(circuit, cin, "AND", xor1); - - if (xor2 == null && and2 == null) { - return SwapAndFix(circuit, xor1, and1); - } - - var carry = Output(circuit, and1, "OR", and2); - if (xor2 != z) { - return SwapAndFix(circuit, z, xor2); - } else { - cin = carry; - } - } - return []; - } - - IEnumerable SwapAndFix(Circuit circuit, string out1, string out2) { - (circuit[out1], circuit[out2]) = (circuit[out2], circuit[out1]); - return Fix(circuit).Concat([out1, out2]); - } - - string Output(Circuit circuit, string x, string kind, string y) => - circuit.SingleOrDefault(pair => - (pair.Value.in1 == x && pair.Value.kind == kind && pair.Value.in2 == y) || - (pair.Value.in1 == y && pair.Value.kind == kind && pair.Value.in2 == x) - ).Key; - - (Dictionary inputs, Circuit circuit) Parse(string input) { - var inputs = new Dictionary(); - var circuit = new Circuit(); - - var blocks = input.Split("\n\n"); - - foreach (var line in blocks[0].Split("\n")) { - var parts = line.Split(": "); - inputs.Add(parts[0], int.Parse(parts[1])); - } - - foreach (var line in blocks[1].Split("\n")) { - var parts = Regex.Matches(line, "[a-zA-z0-9]+").Select(m => m.Value).ToArray(); - circuit.Add(parts[3], new Gate(in1: parts[0], kind: parts[1], in2: parts[2])); - } - return (inputs, circuit); - } - -} \ No newline at end of file diff --git a/2024/Day24/adder.png b/2024/Day24/adder.png deleted file mode 100644 index 9b21c1063..000000000 Binary files a/2024/Day24/adder.png and /dev/null differ diff --git a/2024/Day24/halfadder.png b/2024/Day24/halfadder.png deleted file mode 100644 index 76cdb3d92..000000000 Binary files a/2024/Day24/halfadder.png and /dev/null differ diff --git a/2024/Day24/illustration.jpeg b/2024/Day24/illustration.jpeg deleted file mode 100644 index 322a5b212..000000000 Binary files a/2024/Day24/illustration.jpeg and /dev/null differ diff --git a/2024/Day24/input.in b/2024/Day24/input.in deleted file mode 100644 index 2df3714a9..000000000 Binary files a/2024/Day24/input.in and /dev/null differ diff --git a/2024/Day24/input.refout b/2024/Day24/input.refout deleted file mode 100644 index bf2c0f14a..000000000 --- a/2024/Day24/input.refout +++ /dev/null @@ -1,2 +0,0 @@ -61495910098126 -css,cwt,gdd,jmv,pqt,z05,z09,z37 \ No newline at end of file diff --git a/2024/Day25/README.md b/2024/Day25/README.md deleted file mode 100644 index a4042b8c3..000000000 --- a/2024/Day25/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## --- Day 25: Code Chronicle --- -Out of ideas and time, The Historians agree that they should go back to check the Chief Historian's office one last time, just in case he went back there without you noticing. - -When you get there, you are surprised to discover that the door to his office is locked! You can hear someone inside, but knocking yields no response. The locks on this floor are all fancy, expensive, virtual versions of [five-pin tumbler locks](https://en.wikipedia.org/wiki/Pin_tumbler_lock), so you contact North Pole security to see if they can help open the door. - -_Visit the website for the full story and [full puzzle](https://adventofcode.com/2024/day/25) description._ diff --git a/2024/Day25/Solution.cs b/2024/Day25/Solution.cs deleted file mode 100644 index 16046d22f..000000000 --- a/2024/Day25/Solution.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace AdventOfCode.Y2024.Day25; - -using System; -using System.Linq; - -[ProblemName("Code Chronicle")] -class Solution : Solver { - - public object PartOne(string input) { - int[] parsePattern(string[] lines) => - Enumerable.Range(0, lines[0].Length).Select(x => - Enumerable.Range(0, lines.Length).Count(y => lines[y][x] == '#') - ).ToArray(); - - bool match(int[] k, int[] l) => - Enumerable.Range(0, k.Length).All(i => k[i] + l[i] <= 7); - - var patterns = input.Split("\n\n").Select(b => b.Split("\n")); - var keys = patterns.Where(p => p[0][0] == '.').Select(parsePattern).ToList(); - var locks = patterns.Where(p => p[0][0] == '#').Select(parsePattern).ToList(); - - return keys.Sum(k => locks.Count(l => match(l, k))); - } -} \ No newline at end of file diff --git a/2024/Day25/illustration.jpeg b/2024/Day25/illustration.jpeg deleted file mode 100644 index a7665d28e..000000000 Binary files a/2024/Day25/illustration.jpeg and /dev/null differ diff --git a/2024/Day25/input.in b/2024/Day25/input.in deleted file mode 100644 index 9c008e4e5..000000000 Binary files a/2024/Day25/input.in and /dev/null differ diff --git a/2024/Day25/input.refout b/2024/Day25/input.refout deleted file mode 100644 index ddc2c2009..000000000 --- a/2024/Day25/input.refout +++ /dev/null @@ -1 +0,0 @@ -3242 \ No newline at end of file diff --git a/2024/README.md b/2024/README.md deleted file mode 100644 index e4d82c85c..000000000 --- a/2024/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Advent of Code (2024) -Check out https://adventofcode.com/2024. - - diff --git a/2024/SplashScreen.cs b/2024/SplashScreen.cs deleted file mode 100644 index e29c3095b..000000000 --- a/2024/SplashScreen.cs +++ /dev/null @@ -1,370 +0,0 @@ -using System; - -namespace AdventOfCode.Y2024; - -class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ "); - Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ /* 2024 */\n \n "); - Write(0xcc00, false, " "); - Write(0x888888, false, " .-----. .------------------. \n "); - Write(0xcccccc, false, ".--'"); - Write(0xe3b585, false, "~ ~ ~"); - Write(0xcccccc, false, "| .-' "); - Write(0xffff66, true, "* "); - Write(0x886655, false, "\\ / "); - Write(0xcccccc, false, "'-. 1 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ".--'"); - Write(0xe3b585, false, "~ "); - Write(0xcc00, false, ","); - Write(0xffff66, true, "* "); - Write(0xe3b585, false, "~ "); - Write(0xcccccc, false, "| | "); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "< "); - Write(0x886655, false, "\\_\\_\\|_/__/ "); - Write(0xcccccc, false, "| 2 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ".---'"); - Write(0xe3b585, false, ": ~ "); - Write(0xcc00, false, "'"); - Write(0x5555bb, false, "(~)"); - Write(0xcc00, false, ", "); - Write(0xe3b585, false, "~"); - Write(0xcccccc, false, "| | "); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, "< "); - Write(0xff0000, true, "o"); - Write(0x886655, false, "-_/"); - Write(0xcccccc, false, ".()"); - Write(0x886655, false, "__------"); - Write(0xcccccc, false, "| 3 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x4d8b03, false, "@"); - Write(0x5eabb4, false, ".."); - Write(0x4d8b03, false, "@"); - Write(0xe3b585, false, "'. ~ "); - Write(0xcc00, false, "\" ' "); - Write(0xe3b585, false, "~ "); - Write(0xcccccc, false, "| |"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "< "); - Write(0x886655, false, "\\____ "); - Write(0xcc00, false, ".'"); - Write(0xcccccc, false, "| 4 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x488813, false, "_"); - Write(0x5eabb4, false, ".~."); - Write(0x488813, false, "_"); - Write(0x7fbd39, false, "@"); - Write(0xe3b585, false, "'.. ~ ~ "); - Write(0xffff66, true, "*"); - Write(0xcccccc, false, "| | "); - Write(0xaaaaaa, false, "_| |_ "); - Write(0xcccccc, false, "..\\_"); - Write(0x886655, false, "\\_ "); - Write(0xcc00, false, "..'"); - Write(0xffff66, true, "* "); - Write(0xcccccc, false, "| 5 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xffffff, false, "||| "); - Write(0x427322, false, "@ "); - Write(0xe3b585, false, "'''..."); - Write(0xcccccc, false, "| |"); - Write(0xa25151, false, "... "); - Write(0xcccccc, false, ".' '."); - Write(0xcc00, false, "'''.."); - Write(0xd4dde4, false, "/"); - Write(0xcc00, false, ".."); - Write(0xcccccc, false, "| 6 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x1461f, false, "@"); - Write(0xffffff, false, "~~~"); - Write(0x488813, false, "@"); - Write(0x4d8b03, false, "@##"); - Write(0x7fbd39, false, "@"); - Write(0x4d8b03, false, "# "); - Write(0x427322, false, "@# "); - Write(0xcccccc, false, "| |"); - Write(0xa5a8af, false, "/\\ "); - Write(0xa25151, false, "''. "); - Write(0xcccccc, false, "| | "); - Write(0xccccff, false, "-"); - Write(0xd4dde4, false, "/ "); - Write(0xffffff, false, ":"); - Write(0xcccccc, false, "| 7 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x5eabb4, false, "~~."); - Write(0xcccccc, false, ".--."); - Write(0x666666, false, " _____ "); - Write(0xcccccc, false, "| |"); - Write(0xffff66, true, "* "); - Write(0xa5a8af, false, "/"); - Write(0xdf2308, true, "~"); - Write(0xa5a8af, false, "\\ "); - Write(0xa25151, false, "'."); - Write(0xcccccc, false, "| | "); - Write(0xccccff, false, "- "); - Write(0xd4dde4, false, "/ "); - Write(0xffffff, false, ".'"); - Write(0xcccccc, false, "| 8 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "'---' |"); - Write(0x666666, false, "|[][]_\\-"); - Write(0xcccccc, false, "| |"); - Write(0xdf2308, true, "~"); - Write(0xa5a8af, false, "/ "); - Write(0xffff66, true, "* "); - Write(0xa5a8af, false, "\\ "); - Write(0xa25151, false, ":"); - Write(0xcccccc, false, "| | "); - Write(0xffff66, true, "*"); - Write(0xffffff, false, "..' "); - Write(0xcccccc, false, "| 9 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x666666, false, "------- "); - Write(0xcccccc, false, "| | "); - Write(0xa5a8af, false, "/\\ "); - Write(0xa25151, false, ".'"); - Write(0xcccccc, false, "| |"); - Write(0xffffff, false, "'''"); - Write(0xc8ff, false, "~~~~~"); - Write(0xcccccc, false, "| 10 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xccccff, false, "......."); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "| |"); - Write(0xa5a8af, false, "/\\ "); - Write(0xa25151, false, "..' "); - Write(0xcccccc, false, "| | "); - Write(0xb5ed, false, ". "); - Write(0xffffff, false, ". "); - Write(0xb5ed, false, "."); - Write(0xcccccc, false, "| 11 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xffffff, false, "- - "); - Write(0xcccccc, false, "| |"); - Write(0xa25151, false, "'''"); - Write(0x333333, false, "::"); - Write(0xffff66, true, ":"); - Write(0x333333, false, "::"); - Write(0xcccccc, false, "| | "); - Write(0xffffff, false, ". "); - Write(0xa2db, false, ". ."); - Write(0xff0000, true, "."); - Write(0xcccccc, false, "| 12 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xffffff, false, "'. - -"); - Write(0xcccccc, false, "| | "); - Write(0x333333, false, "::"); - Write(0x9900, true, ":"); - Write(0x333333, false, "::"); - Write(0xcccccc, false, "| |"); - Write(0x66ff, true, ". "); - Write(0xffffff, false, ".' "); - Write(0x9933, true, ". "); - Write(0x91cc, false, "."); - Write(0xcccccc, false, "| 13 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xcc00, false, "..."); - Write(0xffffff, false, "'..''"); - Write(0xcccccc, false, "| |"); - Write(0xffffff, true, ". "); - Write(0x333333, false, ".:"); - Write(0x9900, true, ":::"); - Write(0x333333, false, ":"); - Write(0xcccccc, false, "| |"); - Write(0xc74c30, false, "."); - Write(0xff0000, false, "."); - Write(0xffffff, false, "|\\"); - Write(0xff0000, false, "."); - Write(0xc74c30, false, "."); - Write(0xa47a4d, false, "''"); - Write(0xcccccc, false, "| 14 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xcc00, false, ". ''. "); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, ". "); - Write(0x9900, true, ":::::"); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, "──┬┴┴┴┬─"); - Write(0xcccccc, false, "| 15 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xcc00, false, "'."); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "'."); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, " : "); - Write(0x333333, false, "::"); - Write(0x553322, true, ":"); - Write(0x333333, false, "::"); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, "──┤AoC├o"); - Write(0xcccccc, false, "| 16 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xcc00, false, ". "); - Write(0xffff66, true, "*"); - Write(0xcc00, false, "'."); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, ":"); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, " '. "); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, "┬o┤ten├─"); - Write(0xcccccc, false, "| 17 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xcc00, false, "'..' .'"); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, " '"); - Write(0x456efe, true, "o "); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, "┘"); - Write(0xffff66, true, "*"); - Write(0x666666, false, "┤yrs├─"); - Write(0xcccccc, false, "| 18 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0x5555bb, false, "~ "); - Write(0xcc00, false, "..' "); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, ": '."); - Write(0x333333, false, ".."); - Write(0xcccccc, false, "| |"); - Write(0x666666, false, "─┘├┬┬┬┴─"); - Write(0xcccccc, false, "| 19 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xcc00, false, "'''"); - Write(0xcccccc, false, ")) | | "); - Write(0xbee4e7, true, "o "); - Write(0xffff66, true, "*"); - Write(0x666666, false, " : "); - Write(0xcccccc, false, "'. .'"); - Write(0x666666, false, "──┘"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<<"); - Write(0xcccccc, false, "| 20 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, ".------'"); - Write(0x66ff, false, ".-"); - Write(0xcccccc, false, "(("); - Write(0x66ff, false, "---."); - Write(0xcccccc, false, "'------. |"); - Write(0x666666, false, " :"); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "\\| "); - Write(0x333399, false, "~ "); - Write(0x9900ff, false, "_"); - Write(0xcccccc, false, "'' "); - Write(0x9900ff, false, "O> "); - Write(0x9900, false, ">>"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<"); - Write(0xff9900, true, "o"); - Write(0x9900, false, "<"); - Write(0xcccccc, false, "| 21 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "| "); - Write(0xff0000, false, ".---_ "); - Write(0x66ff, false, "'------'_ "); - Write(0xaaaaaa, false, ".~' "); - Write(0xcccccc, false, "| | |"); - Write(0xff0000, false, "\\|"); - Write(0x9900ff, false, "\\ / \\ /"); - Write(0x333399, false, "~ "); - Write(0x9900, false, ">"); - Write(0xff0000, true, "@"); - Write(0x9900, false, "<<"); - Write(0xffff66, true, "*"); - Write(0x9900, false, "<"); - Write(0x66ff, true, "O"); - Write(0xcccccc, false, "| 22 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0xff0000, false, "/ "); - Write(0x880000, false, "/ "); - Write(0xff0000, false, "/\\|"); - Write(0x66ff, false, "| | )"); - Write(0xaaaaaa, false, "/"); - Write(0xe6410b, false, "~"); - Write(0xaaaaaa, false, "\\ "); - Write(0xcccccc, false, "| |"); - Write(0x66ff, false, "___"); - Write(0xff0000, false, "|"); - Write(0xcccccc, false, "\\|"); - Write(0x66ff, false, "________"); - Write(0x9900, false, ">"); - Write(0x66ff, true, "O"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0x9900, false, ">>"); - Write(0xff9900, true, "o"); - Write(0xcccccc, false, "| 23 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x880000, false, "/ | "); - Write(0xff0000, false, "\\ "); - Write(0xffff66, true, "*"); - Write(0x66ff, false, "| |/"); - Write(0xaaaaaa, false, "/ "); - Write(0xe6410b, false, "/ "); - Write(0xaaaaaa, false, "\\ "); - Write(0xcccccc, false, "| | "); - Write(0x9b715b, false, "----@ "); - Write(0xaaaaaa, false, "_"); - Write(0xd0b376, false, "|%%%=%%|"); - Write(0xaaaaaa, false, "_ "); - Write(0xcccccc, false, "| 24 "); - Write(0xffff66, false, "**\n "); - Write(0xcccccc, false, "|"); - Write(0x880000, false, "/ \\ "); - Write(0xff0000, false, "\\ "); - Write(0x66ff, false, "'------'"); - Write(0xaaaaaa, false, "/ "); - Write(0xe6410b, false, "/ \\ "); - Write(0xaaaaaa, false, "\\"); - Write(0xcccccc, false, "| '-."); - Write(0x9b715b, false, "! /^\\ "); - Write(0xaaaaaa, false, "/ \\"); - Write(0x5eabb4, false, ".~~."); - Write(0xaaaaaa, false, "/ \\"); - Write(0xcccccc, false, ".-' 25 "); - Write(0xffff66, false, "**\n "); - Write(0x888888, false, "'----------------------' '------------------' \n \n"); - - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } -} \ No newline at end of file diff --git a/2024/calendar.svg b/2024/calendar.svg deleted file mode 100644 index 576f4919f..000000000 --- a/2024/calendar.svg +++ /dev/null @@ -1,48 +0,0 @@ - - - - -▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄  ▄▄▄ ▄█  ▄▄ ▄▄▄ ▄▄█ ▄▄▄ -█▄█ █ █ █ █ █▄█ █ █ █   █ █ █▄  █  █ █ █ █ █▄█ -█ █ █▄█ ▀▄▀ █▄▄ █ █ █▄  █▄█ █   █▄ █▄█ █▄█ █▄▄  /* 2024 */ -  -          .-----.          .------------------.          -       .--'~ ~ ~|        .-' *       \  /     '-.   1 ** -    .--'~  ,* ~ |        |  >o<   \_\_\|_/__/   |   2 ** -.---': ~ '(~), ~|        | >@>O< o-_/.()__------|   3 ** -|@..@'. ~ " ' ~ |        |>O>o<@< \____       .'|   4 ** -|_.~._@'.. ~ ~ *|        | _| |_    ..\_\_ ..'* |   5 ** -| ||| @   '''...|        |...     .'  '.'''../..|   6 ** -|@~~~@@##@# @#  |        |/\ ''.  |    |   -/  :|   7 ** -|~~..--. _____  |        |* /~\ '.|    | - /  .'|   8 ** -'---'  ||[][]_\-|        |~/ * \ :|    |  *..'  |   9 ** -       |------- |        |   /\ .'|    |'''~~~~~|  10 ** -       |.......||        |/\ ..'  |    | . .   .|  11 ** -       |  -  -  |        |''':::::|    |  . . ..|  12 ** -       |'. -   -|        |   :::::|    |. .' . .|  13 ** -       |...'..''|        |. .:::::|    |..|\..''|  14 ** -       |.  ''.  |        |.  :::::|    ||  15 ** -       | '.~  '.|        | : :::::|    |AoCo|  16 ** -       |. *'.~ :|        |  '.    |    |oten|  17 ** -       | '..' .'|        |   'o   |    |*yrs|  18 ** -       | ~ ..'  |        |:   '...|    ||  19 ** -       |'''))   |        | o  * : '.  .'>>o<<|  20 ** -.------'.-((---.'------. |  :|\| ~ _'' O> >>@<o<|  21 ** -| .---_ '------'_  .~' | |   |\|\ / \ /~ >@<<*<O|  22 ** -|/ / /\||      | )/~\  | |___|\|________>O>>o>>o|  23 ** -|/ | \ *|      |// / \ | |  ----@  _|%%%=%%|_   |  24 ** -|/  \ \ '------'/ / \ \| '-.! /^\ /  \.~~./  \.-'  25 ** -'----------------------'   '------------------'          - - - - \ No newline at end of file diff --git a/App.cs b/App.cs index 75d69d14d..0bb181a21 100644 --- a/App.cs +++ b/App.cs @@ -56,22 +56,22 @@ var tsolversSelected = tsolvers.First(tsolver => SolverExtensions.Year(tsolver) == year && SolverExtensions.Day(tsolver) == day); - return () => Runner.RunAll(true, true, true, GetSolvers(tsolversSelected)); + return () => Runner.RunAll(GetSolvers(tsolversSelected)); }) ?? Command(args, Args("[0-9]+"), m => { var year = int.Parse(m[0]); var tsolversSelected = tsolvers.Where(tsolver => SolverExtensions.Year(tsolver) == year); - return () => Runner.RunAll(true, true, true, GetSolvers(tsolversSelected.ToArray())); + return () => Runner.RunAll(GetSolvers(tsolversSelected.ToArray())); }) ?? Command(args, Args("([0-9]+)/all"), m => { var year = int.Parse(m[0]); var tsolversSelected = tsolvers.Where(tsolver => SolverExtensions.Year(tsolver) == year); - return () => Runner.RunAll(true, true, true, GetSolvers(tsolversSelected.ToArray())); + return () => Runner.RunAll(GetSolvers(tsolversSelected.ToArray())); }) ?? Command(args, Args("all"), m => { - return () => Runner.RunAll(true, true, true, GetSolvers(tsolvers)); + return () => Runner.RunAll(GetSolvers(tsolvers)); }) ?? Command(args, Args("today"), m => { var dt = DateTime.UtcNow.AddHours(-5); @@ -82,17 +82,26 @@ SolverExtensions.Day(tsolver) == dt.Day); return () => - Runner.RunAll(true, true, true, GetSolvers(tsolversSelected)); + Runner.RunAll(GetSolvers(tsolversSelected)); } else { throw new AocCommuncationError("Event is not active. This option works in Dec 1-25 only)"); } }) ?? Command(args, Args("calendars"), _ => { - return () => Runner.RunAll(false, true, false, GetSolvers(tsolvers)); - }) ?? - Command(args, Args("loc"), _ => { - return () => Runner.RunAll(false, false, true, GetSolvers(tsolvers)); + return () => { + var tsolversSelected = ( + from tsolver in tsolvers + group tsolver by SolverExtensions.Year(tsolver) into g + orderby SolverExtensions.Year(g.First()) descending + select g.First() + ).ToArray(); + + var solvers = GetSolvers(tsolversSelected); + foreach (var solver in solvers) { + solver.SplashScreen().Show(); + } + }; }) ?? new Action(() => { Console.WriteLine(Usage.Get()); @@ -100,8 +109,8 @@ try { action(); -} catch (AggregateException a) { - if (a.InnerExceptions.Count == 1 && a.InnerException is AocCommuncationError) { +} catch (AggregateException a){ + if (a.InnerExceptions.Count == 1 && a.InnerException is AocCommuncationError){ Console.WriteLine(a.InnerException.Message); } else { throw; @@ -122,8 +131,8 @@ Action Command(string[] args, string[] regexes, Func parse) { } try { - return parse(matches.SelectMany(m => - m.Groups.Count > 1 ? m.Groups.Cast().Skip(1).Select(g => g.Value) + return parse(matches.SelectMany(m => + m.Groups.Count > 1 ? m.Groups.Cast().Skip(1).Select(g => g.Value) : new[] { m.Value } ).ToArray()); } catch { @@ -137,37 +146,37 @@ string[] Args(params string[] regex) { class Usage { public static string Get() { - return $""" - Usage: dotnet run [arguments] - 1) To run the solutions and admire your advent calendar: + return $@" + > Usage: dotnet run [arguments] + > 1) To run the solutions and admire your advent calendar: + + > [year]/[day|all] Solve the specified problems + > today Shortcut to the above + > [year] Solve the whole year + > all Solve everything - [year]/[day|all] Solve the specified problems - today Shortcut to the above - [year] Solve the whole year - all Solve everything + > calendars Show the calendars - calendars Show the calendars - loc Show the line of code charts + > 2) To start working on new problems: + > login to https://adventofcode.com, then copy your session cookie, and export + > it in your console like this - 2) To start working on new problems: - login to https://adventofcode.com, then copy your session cookie, and export - it in your console like this + > export SESSION=73a37e9a72a... - export SESSION=73a37e9a72a... + > or in a session.txt file in the root of the project. - then run the app with + > then run the app with - update [year]/[day] Prepares a folder for the given day, updates the input, - the readme and creates a solution template. - update today Shortcut to the above. + > update [year]/[day] Prepares a folder for the given day, updates the input, + > the readme and creates a solution template. + > update today Shortcut to the above. - 3) To upload your answer: - set up your SESSION variable as above. + > 3) To upload your answer: + > set up your SESSION variable as above. - upload [year]/[day] Upload the answer for the selected year and day. - upload today Shortcut to the above. + > upload [year]/[day] Upload the answer for the selected year and day. + > upload today Shortcut to the above. - 4) Don't forget to tip the maintainer https://github.com/sponsors/encse. - """; + > ".StripMargin("> "); } } diff --git a/LICENSE.txt b/LICENSE.txt index e381440e0..d9cdf0629 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,20 +1,24 @@ Copyright (c) 2019 David Nemeth Cs. -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 license applies to all source code and configuration incluced in +the repository. It doesn't apply to advent of code problem statements +and input files. For the license conditions of those please contact the +original author at https://adventofcode.com. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +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 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. \ No newline at end of file +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. diff --git a/Lib/CheckGitCrypt.cs b/Lib/CheckGitCrypt.cs deleted file mode 100644 index 9b7c76d5d..000000000 --- a/Lib/CheckGitCrypt.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; - -class GitCrypt { - public static void Check() { - if (!File.Exists(".git/git-crypt/keys/default")) { - Console.WriteLine( - """ - Repository is not unlocked. You need to install and configure git-crypt. - Check out the README file. - """); - Environment.Exit(1); - } - } - - public static void CheckFile(string file) { - using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) { - fileStream.Seek(1, SeekOrigin.Begin); - byte[] buffer = new byte[8]; - int bytesRead = fileStream.Read(buffer, 0, buffer.Length); - - // If the file is smaller than the requested byte count, resize the array - if (bytesRead < buffer.Length) { - return; - } - - if (Encoding.ASCII.GetBytes("GITCRYPT").SequenceEqual(buffer)) { - Console.WriteLine( - $""" - File '{file}' is encrypted. You need to install and configure git-crypt. - Check out the README file. - """); - Environment.Exit(1); - } - } - } -} \ No newline at end of file diff --git a/Lib/Generator/ReadmeGenerator.cs b/Lib/Generator/ReadmeGenerator.cs index 5b88fe66a..c7191008e 100644 --- a/Lib/Generator/ReadmeGenerator.cs +++ b/Lib/Generator/ReadmeGenerator.cs @@ -1,15 +1,78 @@ +using System.Linq; using AdventOfCode.Model; namespace AdventOfCode.Generator; +class ProjectReadmeGenerator { + public string Generate(int firstYear, int lastYear) { + + return $@" + > # Advent of Code ({firstYear}-{lastYear}) + > C# solutions to the Advent of Code problems. + > Check out https://adventofcode.com. + > + > + > + > The goal is to keep my C# knowledge fresh and to follow the latest changes of the language. + > + > Everything is self contained. I don't use any libraries to make things short or predefined algorithms + > to parameterize. Just stick to what .Net provides. Each problem is solved by plain C# classes without any 'base' to derive from. + > The solvers have different entry points for part 1 and 2. There is no local state, part 2 starts from scratch, + > but code sharing between part 1 and 2 is important to me. (Unless it makes things hard to read.) + > + > I prefer to use functional style, local or anonymous functions, immutability and linq over the state manipulation + > style of oop, but I'm not very strict about this. Whatever I see fit for the problem. + > + > One thing that you will not see much in C# projects is K&R indentation. Sorry about that... + > + > The way I solve the puzzles should be pretty consistent during an event but there are small changes over + > the years as I find something new or forget about stuff I learned last year. + > + > I try to keep things tight and golf the solution to a certain level, but don't want to overgolf it. (Sometimes I fail.) + > + > There aren't many comments, but if I find that the solution is not straightforward, the algorithm has a name, or it is + > using some special property of the input I might explain it in a line or two. + > + > You can browse my solutions as they are or fork the repo, remove everything and use just the lib part to + > start working on your own. The framework part is pretty stable and you get testing, scaffolding etc for free. + > + > ## Dependencies + + > - This project is based on `.NET 8` and `C# 12`. It should work on Windows, Linux and OS-X. + > - `AngleSharp` is used for problem download. + + > ## Running + + > To run the project: + + > 1. Install .NET Core + > 2. Clone the repo + > 3. Get help with `dotnet run` + > ``` + > {Usage.Get()} + > ``` + + > ## Working in Visual Studio Code + > If you prefer, you can work directly in VSCode as well. + + > Open the command Palette (⇧ ⌘ P), select `Tasks: Run Task` then e.g. `update today`. + > + > Work on part 1. Check the solution with the `upload today` task. Continue with part 2. + > + > **Note:** this feature relies on the ""Memento Inputs"" extension to store your session cookie, you need + > to set it up in advance from the Command Palette with `Install Extensions`. + > ".StripMargin("> "); + } +} + class ReadmeGeneratorForYear { public string Generate(Calendar calendar) { - return $""" - # Advent of Code ({calendar.Year}) - Check out https://adventofcode.com/{calendar.Year}. + return $@" + > # Advent of Code ({calendar.Year}) + > Check out https://adventofcode.com/{calendar.Year}. - + > - """; + > ".StripMargin("> "); } } diff --git a/Lib/Generator/SolutionTemplateGenerator.cs b/Lib/Generator/SolutionTemplateGenerator.cs index 8b67a4ed3..0629bc04e 100644 --- a/Lib/Generator/SolutionTemplateGenerator.cs +++ b/Lib/Generator/SolutionTemplateGenerator.cs @@ -4,28 +4,23 @@ namespace AdventOfCode.Generator; class SolutionTemplateGenerator { public string Generate(Problem problem) { - return $$""" - namespace AdventOfCode.Y{{problem.Year}}.Day{{problem.Day:00}}; - - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - using System.Linq; - using System.Text.RegularExpressions; - using System.Text; - using System.Numerics; - - [ProblemName("{{problem.Title}}")] - class Solution : Solver { - - public object PartOne(string input) { - return 0; - } - - public object PartTwo(string input) { - return 0; - } - } - """; + return $@"using System; + |namespace AdventOfCode.Y{problem.Year}.Day{problem.Day.ToString("00")}; + | + |[ProblemName(""{problem.Title}"")] + |class Solution : Solver + |{{ + | + | public object PartOne(string input) + | {{ + | return 0; + | }} + | + | public object PartTwo(string input) + | {{ + | return 0; + | }} + |}} + |".StripMargin(); } } diff --git a/Lib/Generator/SplashScreenGenerator.cs b/Lib/Generator/SplashScreenGenerator.cs index 050b2c8ee..2479376eb 100644 --- a/Lib/Generator/SplashScreenGenerator.cs +++ b/Lib/Generator/SplashScreenGenerator.cs @@ -8,26 +8,26 @@ namespace AdventOfCode.Generator; class SplashScreenGenerator { public string Generate(Calendar calendar) { string calendarPrinter = CalendarPrinter(calendar); - return $$""" - using System; - - namespace AdventOfCode.Y{{calendar.Year}}; - - class SplashScreenImpl : SplashScreen { - - public void Show() { - - var color = Console.ForegroundColor; - {{calendarPrinter.Indent(12)}} - Console.ForegroundColor = color; - Console.WriteLine(); - } - - private static void Write(int rgb, bool bold, string text){ - Console.Write($"\u001b[38;2;{(rgb>>16)&255};{(rgb>>8)&255};{rgb&255}{(bold ? ";1" : "")}m{text}"); - } - } - """; + return $@" + |using System; + | + |namespace AdventOfCode.Y{calendar.Year}; + | + |class SplashScreenImpl : SplashScreen {{ + | + | public void Show() {{ + | + | var color = Console.ForegroundColor; + | {calendarPrinter.Indent(12)} + | Console.ForegroundColor = color; + | Console.WriteLine(); + | }} + | + | private static void Write(int rgb, bool bold, string text){{ + | Console.Write($""\u001b[38;2;{{(rgb>>16)&255}};{{(rgb>>8)&255}};{{rgb&255}}{{(bold ? "";1"" : """")}}m{{text}}""); + | }} + |}} + |".StripMargin(); } private string CalendarPrinter(Calendar calendar) { diff --git a/Lib/Model/Calendar.cs b/Lib/Model/Calendar.cs index 2d6fcc714..119fd5d68 100644 --- a/Lib/Model/Calendar.cs +++ b/Lib/Model/Calendar.cs @@ -5,7 +5,6 @@ using System.Text.RegularExpressions; using System.Text; using AngleSharp.Dom; -using System.Globalization; namespace AdventOfCode.Model; @@ -98,7 +97,7 @@ public static Calendar Parse(int year, IDocument document) { foreach (var textNode in GetText(calendar)) { var text = textNode.Text(); var style = textNode.ParentElement.ComputeCurrentStyle(); - var rgbaColor = !string.IsNullOrEmpty(style["color"]) ? style["color"]: "rgba(204,204,204,1)"; + var rgbaColor = style["color"]; var bold = !string.IsNullOrEmpty(style["text-shadow"]); if (style["position"] == "absolute" || @@ -112,7 +111,7 @@ public static Calendar Parse(int year, IDocument document) { var m = Regex.Match(widthSpec, "[.0-9]+"); if (m.Success) { - var width = double.Parse(m.Value, CultureInfo.InvariantCulture) * 1.7; + var width = double.Parse(m.Value) * 1.7; var c = (int)Math.Round(width - text.Length, MidpointRounding.AwayFromZero); if (c > 0) { text += new string(' ', c); diff --git a/Lib/Model/Problem.cs b/Lib/Model/Problem.cs index b1ae3a94f..e4a279106 100644 --- a/Lib/Model/Problem.cs +++ b/Lib/Model/Problem.cs @@ -16,36 +16,11 @@ class Problem { public static Problem Parse(int year, int day, string url, IDocument document, string input) { - var md = ParseMdIntro(document, 2, url); - - var answers = ParseAnswers(document); - var title = document.QuerySelector("h2").TextContent; - - var match = Regex.Match(title, ".*: (.*) ---"); - if (match.Success) { - title = match.Groups[1].Value; - } - return new Problem {Year = year, Day = day, Title = title, ContentMd = md, Input = input, Answers = answers.ToArray() }; - } - - static string ParseMdIntro(IDocument document, int paragraphs, string url) { - var article = ParseMd(document).Split("\n\n").ToList(); - article = article.Take(Math.Min(paragraphs, article.Count)).ToList(); - article.Add($"_Visit the website for the full story and [full puzzle]({url}) description._\n"); - return string.Join("\n\n", article); - } - - static string ParseMd(IDocument document) { - var md = ""; + var md = $"original source: [{url}]({url})\n"; + var answers = new List(); foreach (var article in document.QuerySelectorAll("article")) { md += UnparseList("", article) + "\n"; - } - return md; - } - static List ParseAnswers(IDocument document) { - var answers = new List(); - foreach (var article in document.QuerySelectorAll("article")) { var answerNode = article.NextSibling; while (answerNode != null && !( answerNode.NodeName == "P" @@ -60,7 +35,13 @@ static List ParseAnswers(IDocument document) { answers.Add(code.TextContent); } } - return answers; + var title = document.QuerySelector("h2").TextContent; + + var match = Regex.Match(title, ".*: (.*) ---"); + if (match.Success) { + title = match.Groups[1].Value; + } + return new Problem {Year = year, Day = day, Title = title, ContentMd = md, Input = input, Answers = answers.ToArray() }; } static string UnparseList(string sep, INode element) { diff --git a/Lib/Ocr.cs b/Lib/Ocr.cs index 21511c9aa..fa6dcad04 100644 --- a/Lib/Ocr.cs +++ b/Lib/Ocr.cs @@ -28,29 +28,29 @@ public override string ToString() { var width = lines[0].Length; var height = lines.Length; - var smallAlphabet = """ - A B C E F G H I J K L O P R S U Y Z - ## ### ## #### #### ## # # ### ## # # # ## ### ### ### # # # ##### - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # # ### # ### ### # #### # # ## # # # # # # # # # # # # # - #### # # # # # # ## # # # # # # # # # ### ### ## # # # # - # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # # ### ## #### # ### # # ### ## # # #### ## # # # ### ## # #### - """.Split('\n'); - - var largeAlphabet = """ - A B C E F G H J K L N P R X Z - ## ##### #### ###### ###### #### # # ### # # # # # ##### ##### # # ###### - # # # # # # # # # # # # # # # # ## # # # # # # # # - # # # # # # # # # # # # # # ## # # # # # # # # - # # # # # # # # # # # # # # # # # # # # # # # # - # # ##### # ##### ##### # ###### # ## # # # # ##### ##### ## # - ###### # # # # # # ### # # # ## # # # # # # # ## # - # # # # # # # # # # # # # # # # # # # # # # # # - # # # # # # # # # # # # # # # # # ## # # # # # # - # # # # # # # # # ## # # # # # # # # ## # # # # # # - # # ##### #### ###### # ### # # # ### # # ###### # # # # # # # ###### - """.Split('\n'); + var smallAlphabet = StripMargin(@" + | A B C E F G H I J K L O P R S U Y Z + | ## ### ## #### #### ## # # ### ## # # # ## ### ### ### # # # ##### + | # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + | # # ### # ### ### # #### # # ## # # # # # # # # # # # # # + | #### # # # # # # ## # # # # # # # # # ### ### ## # # # # + | # # # # # # # # # # # # # # # # # # # # # # # # # # # # + | # # ### ## #### # ### # # ### ## # # #### ## # # # ### ## # #### + "); + + var largeAlphabet = StripMargin(@" + | A B C E F G H J K L N P R X Z + | ## ##### #### ###### ###### #### # # ### # # # # # ##### ##### # # ###### + | # # # # # # # # # # # # # # # # ## # # # # # # # # + | # # # # # # # # # # # # # # ## # # # # # # # # + | # # # # # # # # # # # # # # # # # # # # # # # # + | # # ##### # ##### ##### # ###### # ## # # # # ##### ##### ## # + | ###### # # # # # # ### # # # ## # # # # # # # ## # + | # # # # # # # # # # # # # # # # # # # # # # # # + | # # # # # # # # # # # # # # # # # ## # # # # # # + | # # # # # # # # # ## # # # # # # # # ## # # # # # # + | # # ##### #### ###### # ### # # # ### # # ###### # # # # # # # ###### + "); var charMap = lines.Length == smallAlphabet.Length - 1 ? smallAlphabet : @@ -66,6 +66,12 @@ A B C E F G H J K L return res; } + string[] StripMargin(string st) => ( + from line in Regex.Split(st, "\r?\n") + where Regex.IsMatch(line, @"^\s*\| ") + select Regex.Replace(line, @"^\s* \| ", "") + ).ToArray(); + public string Detect(string[] text, int icolLetter, int charWidth, int charHeight, string[] charMap) { var textRect = GetRect(text, icolLetter, 0, charWidth, charHeight); diff --git a/Lib/Runner.cs b/Lib/Runner.cs index 4ae3e3792..9a6136ef7 100644 --- a/Lib/Runner.cs +++ b/Lib/Runner.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Reflection; using System.Diagnostics; -using System.Text.RegularExpressions; namespace AdventOfCode; @@ -16,13 +15,13 @@ public ProblemName(string name) { } interface Solver { - object PartOne(string input); - object PartTwo(string input) => null; + object PartOne(string[] input); + object PartTwo(string[] input) => null; } static class SolverExtensions { - public static IEnumerable Solve(this Solver solver, string input) { + public static IEnumerable Solve(this Solver solver, string[] input) { yield return solver.PartOne(input); var res = solver.PartTwo(input); if (res != null) { @@ -75,23 +74,13 @@ public static SplashScreen SplashScreen(this Solver solver) { .Single(t => Year(t) == solver.Year()); return (SplashScreen)Activator.CreateInstance(tsplashScreen); } - - public static int Sloc(this Solver solver) { - var file = solver.WorkingDir() + "/Solution.cs"; - if (File.Exists(file)) { - var solution = File.ReadAllText(file); - return Regex.Matches(solution, @"\n").Count; - } - return -1; - } } record SolverResult(string[] answers, string[] errors); class Runner { - private static string GetNormalizedInput(string file) { - GitCrypt.CheckFile(file); + private static string[] GetNormalizedInput(string file) { var input = File.ReadAllText(file); // on Windows we have "\r\n", not sure if this causes more harm or not @@ -100,7 +89,7 @@ private static string GetNormalizedInput(string file) { if (input.EndsWith("\n")) { input = input.Substring(0, input.Length - 1); } - return input; + return input.Split("\n"); } public static SolverResult RunSolver(Solver solver) { @@ -150,50 +139,35 @@ public static SolverResult RunSolver(Solver solver) { return new SolverResult(answers.ToArray(), errors.ToArray()); } - public static void RunAll(bool executeSolvers, bool showSplashScreen, bool showLocChart, params Solver[] solvers) { - + public static void RunAll(params Solver[] solvers) { var errors = new List(); var lastYear = -1; - List<(int day, int sloc)> slocs = new (); foreach (var solver in solvers) { - if (lastYear != solver.Year()) { - if (showLocChart){ - SlocChart.Show(lastYear, slocs); - } - slocs.Clear(); - - if (showSplashScreen){ - solver.SplashScreen().Show(); - } + solver.SplashScreen().Show(); lastYear = solver.Year(); } - slocs.Add((solver.Day(), solver.Sloc())); - if (executeSolvers){ - var result = RunSolver(solver); - WriteLine(); - errors.AddRange(result.errors); - } - } - if (showLocChart){ - SlocChart.Show(lastYear, slocs); + + var result = RunSolver(solver); WriteLine(); + errors.AddRange(result.errors); } + WriteLine(); + if (errors.Any()) { WriteLine(ConsoleColor.Red, "Errors:\n" + string.Join("\n", errors)); } - - WriteLine(ConsoleColor.Yellow, "Please support the maintainer: https://github.com/sponsors/encse"); - WriteLine(); } private static void WriteLine(ConsoleColor color = ConsoleColor.Gray, string text = "") { - Terminal.WriteLine(color, text); + Write(color, text + "\n"); } private static void Write(ConsoleColor color = ConsoleColor.Gray, string text = "") { - Terminal.Write(color, text); + var c = Console.ForegroundColor; + Console.ForegroundColor = color; + Console.Write(text); + Console.ForegroundColor = c; } - } diff --git a/Lib/SlocChart.cs b/Lib/SlocChart.cs deleted file mode 100644 index f4a667a77..000000000 --- a/Lib/SlocChart.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualBasic; - -namespace AdventOfCode; - - -class SlocChart { - public static void Show(int year, List<(int day, int sloc)> slocs) { - if (slocs.Count < 2) { - return; - } - - - var chars = "█▁▂▃▄▅▆▇"; - var max = slocs.Max(sloc => sloc.sloc); - var min = slocs.Min(sloc => sloc.sloc); - var total = slocs.Sum(sloc => sloc.sloc); - - Console.WriteLine($" {year } in code lines total: {total} max: {max} min: {min}"); - Console.WriteLine(""); - - - var columns = new List>(); - - var icol = 0; - var prevSloc = -1; - foreach (var sloc in slocs) { - icol++; - var col = new List(); - var h = sloc.sloc; - - var color = - h > 200 ? ConsoleColor.Red : - h > 100 ? ConsoleColor.Yellow : - ConsoleColor.DarkGray; - h /= 2; - - if (Math.Abs(prevSloc - sloc.sloc) > 20 || prevSloc < 100 && sloc.sloc < 100) { - var slocSt = sloc.sloc.ToString(); - col.Add(slocSt.WithColor(ConsoleColor.White)); - } - prevSloc = sloc.sloc; - if (h % chars.Length != 0) { - var ch = chars[h % chars.Length]; - col.Add($"{ch}{ch}".WithColor(color)); - h -= h % chars.Length; - } - while (h >= 0) { - var ch = chars[0]; - col.Add($"{ch}{ch}".WithColor(color)); - h -= chars.Length; - } - col.Add(sloc.day.ToString().PadLeft(2, ' ').WithColor(ConsoleColor.White)); - var w = 3; - col = col.Select(r => r.st.PadLeft(w).WithColor(r.c)).ToList(); - columns.Add(col); - } - - var rows = new List>(); - var height = columns.Select(col => col.Count).Max(); - for (var irow = 0; irow < height; irow++) { - var row = new List(); - foreach (var col in columns) { - var color = col.Count > irow ? col[col.Count - irow - 1].c : ConsoleColor.Gray; - var st = col.Count > irow ? col[col.Count - irow - 1].st : ""; - var w = col.Select(r => r.st.Length).Max(); - st = st.PadLeft(w); - row.Add(st.WithColor(color)); - } - rows.Insert(0, row); - } - - foreach (var row in rows) { - foreach (var item in row) { - Terminal.Write(item.c, item.st); - } - Console.WriteLine(); - } - Console.WriteLine(""); - } -} \ No newline at end of file diff --git a/Lib/StringExtensions.cs b/Lib/StringExtensions.cs index 86a7248c0..a0509e206 100644 --- a/Lib/StringExtensions.cs +++ b/Lib/StringExtensions.cs @@ -1,10 +1,16 @@ -using System; using System.Linq; using System.Text.RegularExpressions; namespace AdventOfCode; public static class StringExtensions { + public static string StripMargin(this string st, string margin = "|") { + return string.Join("\n", + from line in Regex.Split(st, "\r?\n") + select Regex.Replace(line, @"^\s*"+Regex.Escape(margin), "") + ); + } + public static string Indent(this string st, int l, bool firstLine = false) { var indent = new string(' ', l); var res = string.Join("\n" + new string(' ', l), @@ -13,9 +19,4 @@ select Regex.Replace(line, @"^\s*\|", "") ); return firstLine ? indent + res : res; } - public static ColoredString WithColor(this string st, ConsoleColor c) { - return new ColoredString(c, st); - } } - -public record ColoredString(ConsoleColor c, string st); diff --git a/Lib/Terminal.cs b/Lib/Terminal.cs deleted file mode 100644 index 6f9a3d1d9..000000000 --- a/Lib/Terminal.cs +++ /dev/null @@ -1,36 +0,0 @@ - -using System; - -class Terminal { - public static void WriteLine(ConsoleColor color = ConsoleColor.Gray, string text = "") { - Write(color, text + "\n"); - } - public static void Write(ConsoleColor color = ConsoleColor.Gray, string text = "") { - - Console.Write($"\u001b[{ToAnsiColorCode(color)}"); - Console.Write(text); - Console.Write("\u001b[0m"); - } - - private static string ToAnsiColorCode(ConsoleColor color) { - switch(color) { - case ConsoleColor.Black: return "30m"; - case ConsoleColor.DarkRed: return "31m"; - case ConsoleColor.DarkGreen: return "32m"; - case ConsoleColor.DarkYellow: return "33m"; - case ConsoleColor.DarkBlue: return "34m"; - case ConsoleColor.DarkMagenta: return "35m"; - case ConsoleColor.DarkCyan: return "36m"; - case ConsoleColor.DarkGray: return "37m"; - case ConsoleColor.Gray: return "90m"; - case ConsoleColor.Red: return "91m"; - case ConsoleColor.Green: return "92m"; - case ConsoleColor.Yellow: return "93m"; - case ConsoleColor.Blue: return "94m"; - case ConsoleColor.Magenta: return "95m"; - case ConsoleColor.Cyan: return "96m"; - case ConsoleColor.White: return "97m"; - } - throw new Exception($"unhandled color code {color}"); - } -} \ No newline at end of file diff --git a/Lib/Updater.cs b/Lib/Updater.cs index 62d2dde2a..e4615a70b 100644 --- a/Lib/Updater.cs +++ b/Lib/Updater.cs @@ -12,13 +12,13 @@ using AdventOfCode.Model; using AngleSharp; using AngleSharp.Io; +using Microsoft.CodeAnalysis.Text; namespace AdventOfCode; class Updater { public async Task Update(int year, int day) { - GitCrypt.Check(); var session = GetSession(); var baseAddress = new Uri("https://adventofcode.com/"); @@ -49,6 +49,7 @@ public async Task Update(int year, int day) { years = new int[] { year }; } + UpdateProjectReadme(years.Min(), years.Max()); UpdateReadmeForYear(calendar); UpdateSplashScreen(calendar); UpdateReadmeForDay(problem); @@ -63,10 +64,18 @@ private Uri GetBaseAddress() { private string GetSession() { if (!Environment.GetEnvironmentVariables().Contains("SESSION")) { - throw new AocCommuncationError("Specify SESSION environment variable", null); + string session = File.ReadAllText("./session.txt"); + + if (session == "") + { + throw new AocCommuncationError("Specify SESSION environment variable", null); + } + + return session; } return Environment.GetEnvironmentVariable("SESSION"); } + private IBrowsingContext GetContext() { var context = BrowsingContext.New(Configuration.Default @@ -204,6 +213,11 @@ void UpdateSolutionTemplate(Problem problem) { } } + void UpdateProjectReadme(int firstYear, int lastYear) { + var file = Path.Combine("README.md"); + WriteFile(file, new ProjectReadmeGenerator().Generate(firstYear, lastYear)); + } + void UpdateReadmeForYear(Calendar calendar) { var file = Path.Combine(SolverExtensions.WorkingDir(calendar.Year), "README.md"); WriteFile(file, new ReadmeGeneratorForYear().Generate(calendar)); diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json new file mode 100644 index 000000000..7248dd30f --- /dev/null +++ b/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "adventofcode": { + "commandName": "Project", + "commandLineArgs": "2023/01", + "workingDirectory": "C:\\projects\\Private\\adventofcode" + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 8b616b4f6..a23852aa9 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,86 @@ - # Advent of Code (2015-2024) - C# solutions to the [Advent of Code](https://adventofcode.com) problems. - +# Advent of Code (2023-2023) +C# solutions to the Advent of Code problems. +Check out https://adventofcode.com. - I'm making a [website](https://aoc.csokavar.hu) out of this. - - A lot of effort goes into my solutions to present things in an easy to understand and elegant way. Clarity first also means less emphasis on speed, but I try to balance it until each puzzle's runtime fits into a second. - - The framework I'm using is freely available and it's pretty streamlined by now. You can start with the - https://github.com/encse/adventofcode-template repository. + - Like what you see? Consider [sponsoring](https://github.com/sponsors/encse) me. +The goal is to keep my C# knowledge fresh and to follow the latest changes of the language. - ## Dependencies - - Based on `.NET 9` and `C# 13`. - - `AngleSharp` is used for problem download. - - git-crypt to store the input files in an encrypted form +Everything is self contained. I don't use any libraries to make things short or predefined algorithms +to parameterize. Just stick to what .Net provides. Each problem is solved by plain C# classes without any 'base' to derive from. +The solvers have different entry points for part 1 and 2. There is no local state, part 2 starts from scratch, +but code sharing between part 1 and 2 is important to me. (Unless it makes things hard to read.) + +I prefer to use functional style, local or anonymous functions, immutability and linq over the state manipulation +style of oop, but I'm not very strict about this. Whatever I see fit for the problem. + +One thing that you will not see much in C# projects is K&R indentation. Sorry about that... + +The way I solve the puzzles should be pretty consistent during an event but there are small changes over +the years as I find something new or forget about stuff I learned last year. + +I try to keep things tight and golf the solution to a certain level, but don't want to overgolf it. (Sometimes I fail.) + +There aren't many comments, but if I find that the solution is not straightforward, the algorithm has a name, or it is +using some special property of the input I might explain it in a line or two. + +You can browse my solutions as they are or fork the repo, remove everything and use just the lib part to +start working on your own. The framework part is pretty stable and you get testing, scaffolding etc for free. + +## Dependencies + +- This project is based on `.NET 8` and `C# 12`. It should work on Windows, Linux and OS-X. +- `AngleSharp` is used for problem download. + +## Running + +To run the project: + +1. Install .NET Core +2. Clone the repo +3. Get help with `dotnet run` +``` + +Usage: dotnet run [arguments] +1) To run the solutions and admire your advent calendar: + + [year]/[day|all] Solve the specified problems + today Shortcut to the above + [year] Solve the whole year + all Solve everything + + calendars Show the calendars + +2) To start working on new problems: +login to https://adventofcode.com, then copy your session cookie, and export +it in your console like this + + export SESSION=73a37e9a72a... + +or in a session.txt file in the root of the project. + +then run the app with + + update [year]/[day] Prepares a folder for the given day, updates the input, + the readme and creates a solution template. + update today Shortcut to the above. + +3) To upload your answer: +set up your SESSION variable as above. + + upload [year]/[day] Upload the answer for the selected year and day. + upload today Shortcut to the above. + + +``` + +## Working in Visual Studio Code +If you prefer, you can work directly in VSCode as well. + + Open the command Palette (⇧ ⌘ P), select `Tasks: Run Task` then e.g. `update today`. + + Work on part 1. Check the solution with the `upload today` task. Continue with part 2. + + **Note:** this feature relies on the "Memento Inputs" extension to store your session cookie, you need + to set it up in advance from the Command Palette with `Install Extensions`. diff --git a/adventofcode.csproj b/adventofcode.csproj index 426add6a1..f20ae3225 100755 --- a/adventofcode.csproj +++ b/adventofcode.csproj @@ -1,13 +1,13 @@ Exe - net9.0 - 13 + net8.0 + 12 true - false + \ No newline at end of file diff --git a/docs/build.js b/docs/build.js deleted file mode 100644 index 4a0efdc78..000000000 --- a/docs/build.js +++ /dev/null @@ -1,185 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const marked = require('marked'); - - -function media(dir){ - const files = fs.readdirSync(dir); - return files.filter(file => - path.extname(file).toLowerCase() === '.gif' || - path.extname(file).toLowerCase() === '.png' - ).map(file => path.join(dir, file)); -} - -function* findReadmes(dir) { - const entries = fs.readdirSync(dir, { withFileTypes: true }); - - for (const entry of entries) { - const fullPath = path.join(dir, entry.name); - - if (entry.isDirectory()) { - const match = fullPath.match(/(\d{4})\/Day(\d{1,2})/i); - if (match) { - const year = parseInt(match[1], 10); - const day = parseInt(match[2], 10); - - // Check the directory for a readme.md file - const readmePath = path.join(fullPath, 'README.md'); - const solutionPath = path.join(fullPath, 'Solution.cs'); - const illustrationPath = path.join(fullPath, 'illustration.jpeg'); - if (fs.existsSync(readmePath) && fs.existsSync(solutionPath)) { - - const rawContent = fs.readFileSync(readmePath, 'utf8'); - - let name = ''; - const match = rawContent.match(/^## --- Day \d+: (.+?) ---/); - if (match) { - name = match[1]; - } - - let lines = rawContent.split('\n'); - while (lines.length > 0) { - let line = lines.shift(); - if (line.match(/^## --- Day \d+: (.+?) ---/)) { - break; - } - } - - - yield { - year, - day, - path: readmePath, - name: name, - notes: marked.parse(lines.join('\n')), - code: fs.readFileSync(solutionPath, 'utf8'), - illustration: fs.existsSync(illustrationPath) ? illustrationPath : 'docs/elf.jpeg', - media: media(fullPath) - }; - } - } - - // Recursively search within this directory - yield* findReadmes(fullPath); - } - } -} - - -function copyDirectory(src, dest) { - if (!fs.existsSync(src)) { - throw new Error(`Source directory does not exist: ${src}`); - } - - if (!fs.existsSync(dest)) { - fs.mkdirSync(dest, { recursive: true }); - } - - const items = fs.readdirSync(src); - - items.forEach(item => { - const srcPath = path.join(src, item); - const destPath = path.join(dest, item); - - if (fs.statSync(srcPath).isDirectory()) { - copyDirectory(srcPath, destPath); - } else { - fs.copyFileSync(srcPath, destPath); - } - }); - }; - - -function loadTemplate(templatePath) { - return fs.readFileSync(templatePath, 'utf8'); -} - - -function fillTemplate(template, replacements) { - return template.replace(/{{\s*([\w-]+)\s*}}/g, (_, key) => replacements[key] || ''); -} - -function generateYearPicker(year, day, yearToDays) { - let options = ''; - for (let y of Object.keys(yearToDays).sort()){ - let lastDay = yearToDays[y][yearToDays[y].length-1]; - let target = `/${y}/${lastDay}/` - options += `${y}` - } - - return ` - `; -} - -function generateDayPicker(year, day, yearToDays) { - let res = ''; - for (i = 1; i <= yearToDays[year].length; i++) { - const link = `${i.toString().padStart(2, '0')}`; - res += i == day ? `${link}` : `${link}`; - } - return res; -} - -function escapeHtml(st) { - const map = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - return st.replace(/[&<>"']/g, (char) => map[char]); -} - -const template = loadTemplate('docs/template.html'); -const redirectTemplate = loadTemplate('docs/redirect_template.html') - -const yearToDays = {}; -for (const { year, day } of findReadmes('.')) { - if (!yearToDays[year]) { - yearToDays[year] = []; - } - yearToDays[year].push(day); -} - -for(const year of Object.keys(yearToDays)){ - yearToDays[year] = yearToDays[year].sort((a,b) => a-b); -} - -const lastYear = Math.max(...Object.keys(yearToDays)) -const lastDay = Math.max(...yearToDays[lastYear]); - -copyDirectory('docs/static', 'build'); - -const filledRedirectTemplate = fillTemplate(redirectTemplate, { - 'default-page': `/${lastYear}/${lastDay}/`, -}); - -fs.writeFileSync(path.join('build', 'index.html'), filledRedirectTemplate); - -const currentYear = new Date().getFullYear(); -// Iterate over readme.md files and print filled templates -for (const { year, day, name, notes, code, illustration, media } of findReadmes('.')) { - const filledHtml = fillTemplate(template, { - url: `https://aoc.csokavar.hu/${year}/${day}/`, - 'problem-id': `${year}/${day}`, - 'problem-name': `${name}`, - 'year-picker': generateYearPicker(year,day, yearToDays), - 'day-picker': generateDayPicker(year, day, yearToDays), - 'current-year': `${currentYear}`, - notes, - code: escapeHtml(code), - }); - const dst = `build/${year}/${day}`; - fs.mkdirSync(dst, { recursive: true }); - fs.writeFileSync(path.join(dst, 'index.html'), filledHtml); - fs.copyFileSync(illustration, path.join(dst, 'illustration.jpeg')); - for(let file of media) { - fs.copyFileSync(file, path.join(dst, path.basename(file))); - } -} - diff --git a/docs/elf.jpeg b/docs/elf.jpeg deleted file mode 100644 index d61c3abb0..000000000 Binary files a/docs/elf.jpeg and /dev/null differ diff --git a/docs/package-lock.json b/docs/package-lock.json deleted file mode 100644 index a398ad371..000000000 --- a/docs/package-lock.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "docs", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "marked": "^15.0.3" - } - }, - "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/package.json b/docs/package.json deleted file mode 100644 index d90559306..000000000 --- a/docs/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "docs", - "version": "1.0.0", - "main": "build.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "description": "", - "dependencies": { - "marked": "^15.0.3" - } -} diff --git a/docs/redirect_template.html b/docs/redirect_template.html deleted file mode 100644 index cc99add5e..000000000 --- a/docs/redirect_template.html +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/docs/static/404.html b/docs/static/404.html deleted file mode 100644 index 9c931b102..000000000 --- a/docs/static/404.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/docs/static/CNAME b/docs/static/CNAME deleted file mode 100644 index dfac70bb5..000000000 --- a/docs/static/CNAME +++ /dev/null @@ -1 +0,0 @@ -aoc.csokavar.hu \ No newline at end of file diff --git a/docs/static/android-chrome-192x192.png b/docs/static/android-chrome-192x192.png deleted file mode 100644 index 00444eee3..000000000 Binary files a/docs/static/android-chrome-192x192.png and /dev/null differ diff --git a/docs/static/android-chrome-512x512.png b/docs/static/android-chrome-512x512.png deleted file mode 100644 index ac878c39a..000000000 Binary files a/docs/static/android-chrome-512x512.png and /dev/null differ diff --git a/docs/static/apple-touch-icon.png b/docs/static/apple-touch-icon.png deleted file mode 100644 index bf6729c6a..000000000 Binary files a/docs/static/apple-touch-icon.png and /dev/null differ diff --git a/docs/static/browserconfig.xml b/docs/static/browserconfig.xml deleted file mode 100644 index b3930d0f0..000000000 --- a/docs/static/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #da532c - - - diff --git a/docs/static/favicon-16x16.png b/docs/static/favicon-16x16.png deleted file mode 100644 index ca6fbddd6..000000000 Binary files a/docs/static/favicon-16x16.png and /dev/null differ diff --git a/docs/static/favicon-32x32.png b/docs/static/favicon-32x32.png deleted file mode 100644 index d4fac82eb..000000000 Binary files a/docs/static/favicon-32x32.png and /dev/null differ diff --git a/docs/static/favicon.ico b/docs/static/favicon.ico deleted file mode 100644 index 70d3d947b..000000000 Binary files a/docs/static/favicon.ico and /dev/null differ diff --git a/docs/static/mstile-150x150.png b/docs/static/mstile-150x150.png deleted file mode 100644 index f1d02c0d4..000000000 Binary files a/docs/static/mstile-150x150.png and /dev/null differ diff --git a/docs/static/safari-pinned-tab.svg b/docs/static/safari-pinned-tab.svg deleted file mode 100644 index 46cebff23..000000000 --- a/docs/static/safari-pinned-tab.svg +++ /dev/null @@ -1,110 +0,0 @@ - - - - -Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - - - - - - - - diff --git a/docs/static/site.webmanifest b/docs/static/site.webmanifest deleted file mode 100644 index b20abb7cb..000000000 --- a/docs/static/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "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" -} diff --git a/docs/template.html b/docs/template.html deleted file mode 100644 index a512a3981..000000000 --- a/docs/template.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - - - - - - - - - - - - - - - Advent of Code {{problem-id}} '{{problem-name}}'' in C# by encse - - - - - - - - - - - - - - -
-
{{year-picker}}
-
{{day-picker}}
-
-
-
-
- -
- -
-

Advent of Code

-

{{problem-id}}

-

{{problem-name}}

-

in C#

-

-

by encse

-
- -
- -
-
{{notes}}
-
{{code}}
-

Please ☆ my repo if you like it!

-
- -
-
- © {{current-year}} - 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/omnisharp.json b/omnisharp.json new file mode 100644 index 000000000..bbf2d9c5f --- /dev/null +++ b/omnisharp.json @@ -0,0 +1,23 @@ +{ + "FormattingOptions": { + "UseTabs": false, + "TabSize": 4, + "IndentationSize": 4, + "EnableEditorConfigSupport": false, + "NewLineForCatch": false, + "NewLineForClausesInQuery": false, + "NewLineForElse": false, + "NewLineForFinally": false, + "NewLineForMembersInAnonymousTypes": false, + "NewLineForMembersInObjectInit": false, + "NewLinesForBracesInAccessors": false, + "NewLinesForBracesInAnonymousMethods": false, + "NewLinesForBracesInAnonymousTypes": false, + "NewLinesForBracesInControlBlocks": false, + "NewLinesForBracesInLambdaExpressionBody": false, + "NewLinesForBracesInMethods": false, + "NewLinesForBracesInObjectCollectionArrayInitializers": false, + "NewLinesForBracesInProperties": false, + "NewLinesForBracesInTypes": false + } +} \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy