Skip to content

Commit ec24efb

Browse files
committed
day14: finally something non trivial
1 parent 409ac6f commit ec24efb

File tree

6 files changed

+310
-46
lines changed

6 files changed

+310
-46
lines changed

2021/Day14/README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
original source: [https://adventofcode.com/2021/day/14](https://adventofcode.com/2021/day/14)
2+
## --- Day 14: Extended Polymerization ---
3+
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.
4+
5+
The submarine manual contains instructions for finding the optimal polymer formula; specifically, it offers a <em>polymer template</em> and a list of <em>pair insertion</em> rules (your puzzle input). You just need to work out what polymer would result after repeating the pair insertion process a few times.
6+
7+
For example:
8+
9+
<pre>
10+
<code>NNCB
11+
12+
CH -> B
13+
HH -> N
14+
CB -> H
15+
NH -> C
16+
HB -> C
17+
HC -> B
18+
HN -> C
19+
NN -> C
20+
BH -> H
21+
NC -> B
22+
NB -> B
23+
BN -> B
24+
BB -> N
25+
BC -> B
26+
CC -> N
27+
CN -> C
28+
</code>
29+
</pre>
30+
31+
The first line is the <em>polymer template</em> - this is the starting point of the process.
32+
33+
The following section defines the <em>pair insertion</em> rules. A rule like <code>AB -> C</code> means that when elements <code>A</code> and <code>B</code> are immediately adjacent, element <code>C</code> should be inserted between them. These insertions all happen simultaneously.
34+
35+
So, starting with the polymer template <code>NNCB</code>, the first step simultaneously considers all three pairs:
36+
37+
38+
- The first pair (<code>NN</code>) matches the rule <code>NN -> C</code>, so element <code><em>C</em></code> is inserted between the first <code>N</code> and the second <code>N</code>.
39+
- The second pair (<code>NC</code>) matches the rule <code>NC -> B</code>, so element <code><em>B</em></code> is inserted between the <code>N</code> and the <code>C</code>.
40+
- The third pair (<code>CB</code>) matches the rule <code>CB -> H</code>, so element <code><em>H</em></code> is inserted between the <code>C</code> and the <code>B</code>.
41+
42+
Note that these pairs overlap: the second element of one pair is the first element of the next pair. Also, because all pairs are considered simultaneously, inserted elements are not considered to be part of a pair until the next step.
43+
44+
After the first step of this process, the polymer becomes <code>N<em>C</em>N<em>B</em>C<em>H</em>B</code>.
45+
46+
Here are the results of a few steps using the above rules:
47+
48+
<pre>
49+
<code>Template: NNCB
50+
After step 1: NCNBCHB
51+
After step 2: NBCCNBBBCBHCB
52+
After step 3: NBBBCNCCNBBNBNBBCHBHHBCHB
53+
After step 4: NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB
54+
</code>
55+
</pre>
56+
57+
This polymer grows quickly. After step 5, it has length 97; After step 10, it has length 3073. After step 10, <code>B</code> occurs 1749 times, <code>C</code> occurs 298 times, <code>H</code> occurs 161 times, and <code>N</code> occurs 865 times; taking the quantity of the most common element (<code>B</code>, 1749) and subtracting the quantity of the least common element (<code>H</code>, 161) produces <code>1749 - 161 = <em>1588</em></code>.
58+
59+
Apply 10 steps of pair insertion to the polymer template and find the most and least common elements in the result. <em>What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?</em>
60+
61+
62+
## --- Part Two ---
63+
The resulting polymer isn't nearly strong enough to reinforce the submarine. You'll need to run more steps of the pair insertion process; a total of <em>40 steps</em> should do it.
64+
65+
In the above example, the most common element is <code>B</code> (occurring <code>2192039569602</code> times) and the least common element is <code>H</code> (occurring <code>3849876073</code> times); subtracting these produces <code><em>2188189693529</em></code>.
66+
67+
Apply <em>40</em> steps of pair insertion to the polymer template and find the most and least common elements in the result. <em>What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?</em>
68+
69+

2021/Day14/Solution.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
4+
namespace AdventOfCode.Y2021.Day14;
5+
6+
[ProblemName("Extended Polymerization")]
7+
class Solution : Solver {
8+
9+
public object PartOne(string input) => Solve(input, 10);
10+
public object PartTwo(string input) => Solve(input, 40);
11+
12+
long Solve(string input, int steps) {
13+
var (polymer, elements, polymerFromMolecule) = Parse(input);
14+
15+
var cache = new Dictionary<(string, int, char), long>();
16+
17+
// getElementCountAfterNSteps: Determines how many atoms of the element
18+
// are present after N steps, if we are starting from the given polymer.
19+
20+
// This function needs to be cached or it will never terminate.
21+
22+
long getElementCountAfterNSteps(string polymer, int steps, char element) {
23+
var key = (polymer, steps, element);
24+
if (!cache.ContainsKey(key)) {
25+
long res = 0L;
26+
if (steps == 0) {
27+
// no more steps to do, just count the element in the polymer:
28+
res = polymer.Count(ch => ch == element);
29+
} else {
30+
31+
// The idea is that we can go over the molecules in the polymer,
32+
// and deal with them one by one. Do one replacement, recurse and
33+
// sum the element counts:
34+
35+
for (var j = 0; j < polymer.Length - 1; j++) {
36+
var molecule = polymer.Substring(j, 2);
37+
38+
var count = getElementCountAfterNSteps(
39+
polymerFromMolecule[molecule],
40+
steps - 1,
41+
element
42+
);
43+
44+
// if the molecule ends with the searched element, the next one will include it as well,
45+
// we shouldn't count it twice:
46+
if (element == molecule[1] && j < polymer.Length - 2) {
47+
count--;
48+
}
49+
50+
res += count;
51+
}
52+
}
53+
cache[key] = res;
54+
}
55+
return cache[key];
56+
}
57+
58+
// using the above helper, we can just ask for the count of each element, and quickly compute the answer
59+
var elementCountsAtTheEnd = (
60+
from element in elements
61+
select getElementCountAfterNSteps(polymer, steps, element)
62+
).ToArray();
63+
64+
return elementCountsAtTheEnd.Max() - elementCountsAtTheEnd.Min();
65+
}
66+
67+
(string polymer, HashSet<char> elements, Dictionary<string, string> polymerFromMolecule) Parse(string input) {
68+
var blocks = input.Split("\n\n");
69+
70+
// we will start from this polymer
71+
var polymer = blocks[0];
72+
73+
// the map contains the resulted polymer after the replacement, not just the inserted element:
74+
var polymerFromMolecule = (
75+
from line in blocks[1].Split("\n")
76+
let parts = line.Split(" -> ")
77+
select (molecule: parts[0], element: parts[1])
78+
).ToDictionary(p => p.molecule, p => p.molecule[0] + p.element + p.molecule[1]);
79+
80+
// set of all elements for convenience:
81+
var elements = polymerFromMolecule.Keys.Select(molecule => molecule[0]).ToHashSet();
82+
83+
return (polymer, elements, polymerFromMolecule);
84+
}
85+
}

2021/Day14/input.in

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
PFVKOBSHPSPOOOCOOHBP
2+
3+
FV -> C
4+
CP -> K
5+
FS -> K
6+
VF -> N
7+
HN -> F
8+
FF -> N
9+
SS -> K
10+
VS -> V
11+
BV -> F
12+
HC -> K
13+
BP -> F
14+
OV -> N
15+
BF -> V
16+
VH -> V
17+
PF -> N
18+
FC -> S
19+
CS -> B
20+
FK -> N
21+
VK -> H
22+
FN -> P
23+
SH -> V
24+
CV -> K
25+
HP -> K
26+
HO -> C
27+
NO -> V
28+
CK -> C
29+
VB -> S
30+
OC -> N
31+
NS -> C
32+
NF -> H
33+
SF -> N
34+
NK -> S
35+
NP -> P
36+
OO -> S
37+
NH -> C
38+
BC -> H
39+
KS -> H
40+
PV -> O
41+
KO -> K
42+
OK -> H
43+
OH -> H
44+
BH -> F
45+
NB -> B
46+
FH -> N
47+
HV -> F
48+
BN -> S
49+
ON -> V
50+
CB -> V
51+
CF -> H
52+
FB -> S
53+
KF -> S
54+
PS -> P
55+
OB -> C
56+
NN -> K
57+
KV -> C
58+
BK -> H
59+
SN -> S
60+
NC -> H
61+
PK -> B
62+
PC -> H
63+
KN -> S
64+
VO -> V
65+
FO -> K
66+
CH -> B
67+
PH -> N
68+
SO -> C
69+
KH -> S
70+
HB -> V
71+
HH -> B
72+
BB -> H
73+
SC -> V
74+
HS -> K
75+
SP -> V
76+
KB -> N
77+
VN -> H
78+
HK -> H
79+
KP -> K
80+
OP -> F
81+
CO -> B
82+
VP -> H
83+
OS -> N
84+
OF -> H
85+
KK -> N
86+
CC -> K
87+
BS -> C
88+
VV -> O
89+
CN -> H
90+
PB -> P
91+
BO -> N
92+
SB -> H
93+
FP -> F
94+
SK -> F
95+
PO -> S
96+
KC -> H
97+
VC -> H
98+
NV -> N
99+
HF -> B
100+
PN -> F
101+
SV -> K
102+
PP -> K

2021/Day14/input.refout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2937
2+
3390034818249

2021/SplashScreen.cs

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,30 @@ public void Show() {
99

1010
var color = Console.ForegroundColor;
1111
Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ ");
12-
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ λy.2021\n \n ");
13-
Write(0xcc00, false, " ");
12+
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ int y = 2021;\n ");
13+
Write(0xcc00, false, " \n ");
1414
Write(0xc8ff, false, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ");
1515
Write(0xcccccc, false, " 1 ");
1616
Write(0xffff66, false, "**\n ");
17-
Write(0xb5ed, false, " . . . .~. . ' . ");
17+
Write(0xb5ed, false, " .. . ' . ~. .. ");
1818
Write(0xffffff, false, ". ");
19-
Write(0xb5ed, false, ". . . ");
19+
Write(0xb5ed, false, " . ");
2020
Write(0xa47a4d, false, "..'''' ");
2121
Write(0xcccccc, false, " 2 ");
2222
Write(0xffff66, false, "**\n ");
23-
Write(0xa2db, false, " . ...' . . . ");
23+
Write(0xa2db, false, " . ~ ' . . . ' ");
2424
Write(0xffffff, false, ". ");
25-
Write(0xa2db, false, " .. ");
25+
Write(0xa2db, false, " .. ");
2626
Write(0xa47a4d, false, ": ");
2727
Write(0xcccccc, false, " 3 ");
2828
Write(0xffff66, false, "**\n ");
29-
Write(0x91cc, false, " .' ' ~ . . ");
30-
Write(0xffffff, false, ".' ");
29+
Write(0x91cc, false, " . . . .'. ' . . ' ");
30+
Write(0xffffff, false, ".' ");
31+
Write(0x91cc, false, ".. ");
3132
Write(0xa47a4d, false, "....' ");
3233
Write(0xcccccc, false, " 4 ");
3334
Write(0xffff66, false, "**\n ");
34-
Write(0x85c0, false, " . . ");
35+
Write(0x85c0, false, "~ . . . ~ . . ");
3536
Write(0xc74c30, false, ".");
3637
Write(0xff0000, false, ".");
3738
Write(0xffffff, false, "|\\");
@@ -40,58 +41,63 @@ public void Show() {
4041
Write(0xa47a4d, false, "'' ");
4142
Write(0xcccccc, false, " 5 ");
4243
Write(0xffff66, false, "**\n ");
43-
Write(0x79b5, false, " . . . ");
44+
Write(0x79b5, false, ". . . . . ");
4445
Write(0xa47a4d, false, ": ");
4546
Write(0xcccccc, false, " 6 ");
4647
Write(0xffff66, false, "**\n ");
47-
Write(0x6daa, false, " ' ' . ' ");
48+
Write(0x6daa, false, " . . .' . ");
4849
Write(0xa47a4d, false, ":' ");
4950
Write(0xcccccc, false, " 7 ");
5051
Write(0xffff66, false, "**\n ");
51-
Write(0x619f, false, " . . .. ");
52+
Write(0x619f, false, " . . . ' . '' ");
5253
Write(0xa47a4d, false, "'''''..... ..");
5354
Write(0xc74c30, false, ".");
5455
Write(0xff0000, false, ". ");
5556
Write(0xcccccc, false, " 8 ");
5657
Write(0xffff66, false, "**\n ");
57-
Write(0x5a98, false, " . . . ");
58+
Write(0x5a98, false, " .' . . . . ");
5859
Write(0xa47a4d, false, ":'.. .. '' ");
5960
Write(0xff0000, false, "': ");
6061
Write(0xcccccc, false, " 9 ");
6162
Write(0xffff66, false, "**\n ");
62-
Write(0x5291, false, " . . . ");
63+
Write(0x5291, false, " . . . . ");
6364
Write(0xa47a4d, false, ": '' ''''.. ");
6465
Write(0xc74c30, false, "'");
6566
Write(0xa47a4d, false, ". ");
6667
Write(0xcccccc, false, "10 ");
6768
Write(0xffff66, false, "**\n ");
68-
Write(0x4a8a, false, " ''. ");
69+
Write(0x4a8a, false, " . . ' ' ");
6970
Write(0xa47a4d, false, ": '..'. : ");
7071
Write(0xcccccc, false, "11 ");
7172
Write(0xffff66, false, "**\n ");
72-
Write(0x4282, false, " .. . . . .' ");
73+
Write(0x4282, false, " . ... . ");
7374
Write(0xa47a4d, false, ":'''.. ..' : ");
7475
Write(0xcccccc, false, "12 ");
7576
Write(0xffff66, false, "**\n ");
76-
Write(0x3b7b, false, " ... ");
77-
Write(0x666666, false, " ..'' ");
78-
Write(0xa47a4d, false, "''' ...: ");
77+
Write(0x3b7b, false, ".. ~ .' ");
78+
Write(0xa47a4d, false, "..'' ''' ...: ");
7979
Write(0xcccccc, false, "13 ");
8080
Write(0xffff66, false, "**\n ");
81-
Write(0x333333, false, " . . . ' ..': ");
81+
Write(0x3374, false, " . '. .. .");
82+
Write(0x666666, false, " ...'");
83+
Write(0xa47a4d, false, "' ..': ");
8284
Write(0xff0000, false, ".");
8385
Write(0xc74c30, false, ".");
8486
Write(0xa47a4d, false, "..' ");
85-
Write(0x666666, false, "14\n ");
86-
Write(0x333333, false, " ' '");
87+
Write(0xcccccc, false, "14 ");
88+
Write(0xffff66, false, "**\n ");
89+
Write(0x333333, false, ". . .~ ' ' ...''");
90+
Write(0xa47a4d, false, "' ");
91+
Write(0xc74c30, false, "'");
8792
Write(0xff0000, false, "'' ");
88-
Write(0x666666, false, "15\n 16\n ");
89-
Write(0x666666, false, " 17\n 18\n ");
90-
Write(0x666666, false, " 19\n ");
91-
Write(0x666666, false, " 20\n 21\n ");
92-
Write(0x666666, false, " 22\n ");
93-
Write(0x666666, false, " 23\n 24\n ");
94-
Write(0x666666, false, " 25\n \n");
93+
Write(0x666666, false, "15\n ");
94+
Write(0x333333, false, " ' ");
95+
Write(0x666666, false, "16\n 17\n ");
96+
Write(0x666666, false, " 18\n 19\n ");
97+
Write(0x666666, false, " 20\n ");
98+
Write(0x666666, false, " 21\n 22\n ");
99+
Write(0x666666, false, " 23\n ");
100+
Write(0x666666, false, " 24\n 25\n \n");
95101

96102
Console.ForegroundColor = color;
97103
Console.WriteLine();

0 commit comments

Comments
 (0)
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