Day 15-18

Day 18 one time with trees and once with string operations
This commit is contained in:
Stefan Forstenlechner 2021-12-20 13:02:03 +01:00
parent ee2d1f4bda
commit 2378be4dd5
8 changed files with 658 additions and 1 deletions

View File

@ -1,4 +1,4 @@
#define Day15
// #define Day15
#if Day15
using System.Collections.Immutable;
using System.Diagnostics;

88
Day16.cs Normal file
View File

@ -0,0 +1,88 @@
// #define Day16
#if Day16
var line = File.ReadAllText("day16/input");
Console.WriteLine(line);
// line = "8A004A801A8002F478";
string binarystring = String.Join(String.Empty,
line.Where(c => !Char.IsWhiteSpace(c)).Select(
c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0')
)
);
Console.WriteLine(binarystring);
int pos = 0;
long versionSum = 0;
Console.WriteLine(ParsePackage(ref pos, binarystring));
Console.WriteLine(versionSum);
long ParsePackage(ref int pos, string binary) {
var version = ParseTypeOrVersionId(ref pos, binary);
versionSum += version;
var type = ParseTypeOrVersionId(ref pos, binary);
if (type == 4) {
return ParseLiteral(ref pos, binary);
} else {
var lengthTypeId = ParseLength(ref pos, binary, 1);
if (lengthTypeId == 1) {
return ParseOperatorType1(ref pos, binary, type);
} else {
return ParseOperatorType0(ref pos, binary, type);
}
}
}
long ParseTypeOrVersionId(ref int pos, string binary) {
return ParseLength(ref pos, binary, 3);
}
long ParseLiteral(ref int pos, string binary) {
string res = String.Empty;
while (binary[pos] == '1') {
res += binary.Substring(pos + 1, 4);
pos += 5;
}
res += binary.Substring(pos + 1, 4);
pos += 5;
return Convert.ToInt64(res, 2);
}
long ParseLength(ref int pos, string binary, int length) {
var id = binary.Substring(pos, length);
pos += length;
return Convert.ToInt64(id, 2);
}
long ParseOperatorType0(ref int pos, string binary, long type) {
long length = ParseLength(ref pos, binary, 15);
long originalPos = pos;
List<long> values = new List<long>();
while (originalPos+length > pos) {
values.Add(ParsePackage(ref pos, binary));
}
return Calculate(type, values);
}
long ParseOperatorType1(ref int pos, string binary, long type) {
long numberOfSubPackages = ParseLength(ref pos, binary, 11);
List<long> values = new List<long>();
for (int i = 0; i < numberOfSubPackages; i++) {
values.Add(ParsePackage(ref pos, binary));
}
return Calculate(type, values);
}
long Calculate(long type, List<long> values) => (type) switch {
0 => values.Sum(),
1 => values.Aggregate(1L, (acc, val) => acc * val),
2 => values.Min(),
3 => values.Max(),
5 => values[0] > values[1] ? 1 : 0,
6 => values[0] < values[1] ? 1 : 0,
7 => values[0] == values[1] ? 1 : 0,
_ => throw new ArgumentException("not defined")
};
#endif

55
Day17.cs Normal file
View File

@ -0,0 +1,55 @@
// #define Day17
#if Day17
using System.Text.RegularExpressions;
var line = File.ReadAllText("day17/input");
var regex = new Regex(@"target area: x=(?<x1>-?\d+)\.\.(?<x2>-?\d+), y=(?<y1>-?\d+)\.\.(?<y2>-?\d+)");
var m = regex.Match(line);
var xTarget = new Distance(int.Parse(m.Groups["x1"].Value), int.Parse(m.Groups["x2"].Value));
var yTarget = new Distance(int.Parse(m.Groups["y1"].Value), int.Parse(m.Groups["y2"].Value));
var maxYVelocity = yTarget.start * -1 - 1;
Console.WriteLine(SumFormulae(maxYVelocity));
var count = Check(1, xTarget.end, yTarget.start, maxYVelocity);
Console.WriteLine(count); // 1440 too low
long Check(int minX, int maxX, int minY, int maxY) {
long count = 0;
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
if (LandsInTarget(x, y, new Position(0, 0))) {
count += 1;
Console.WriteLine($"{x}, {y}");
}
}
}
return count;
}
bool LandsInTarget(int x, int y, Position cur) {
while (cur.x <= xTarget.end && cur.y >= yTarget.start) {
if (InTarget(cur)) {
return true;
}
cur = new Position(cur.x + x, cur.y + y);
x += x > 0 ? -1 : 0;
y += -1;
}
return false;
}
bool InTarget(Position cur) {
return cur.x >= xTarget.start && cur.x <= xTarget.end
&& cur.y >= yTarget.start && cur.y <= yTarget.end;
}
long SumFormulae(long v) => (v * (v + 1)) / 2;
record Distance(int start, int end);
record Position(int x, int y);
#endif

227
Day18.cs Normal file
View File

@ -0,0 +1,227 @@
// #define Day18
#if Day18
var lines = File.ReadAllLines("day18/input");
var numbers = lines.Select(Node.Parse).ToList();
var cur = numbers.First();
foreach (var toAdd in numbers.Skip(1)) {
cur = Node.Add(cur,toAdd);
ExplodeAndSplit(cur);
}
Console.WriteLine(cur);
Console.WriteLine(cur.Magnitude());
List<long> magnitudes = new List<long>();
for (int i = 0; i < lines.Length; i++) {
for (int j = 0; j < lines.Length; j++) {
if (i == j) {
continue;
}
var test = Node.Add(Node.Parse(lines[i]), Node.Parse(lines[j]));
ExplodeAndSplit(test);
magnitudes.Add(test.Magnitude());
var testReverse = Node.Add(Node.Parse(lines[j]), Node.Parse(lines[i]));
ExplodeAndSplit(testReverse);
magnitudes.Add(testReverse.Magnitude());
}
}
Console.WriteLine(magnitudes.Max());
sw.Stop();
Console.WriteLine(sw.Elapsed);
void ExplodeAndSplit(Node number) {
bool changed = false;
do {
changed = number.Explode(1);
if (!changed) {
changed = number.Split();
}
} while (changed);
}
class Node {
public Node? Parent { get; set; }
public Node? Left { get; set; }
public Node? Right { get; set; }
public int? Leaf { get; set; }
public string Print() {
if (Leaf != null) {
return $"{Leaf}";
} else {
return $"[{Left.Print()},{Right.Print()}]";
}
}
public long Magnitude() {
if (Leaf != null) {
return Leaf ?? -9999;
}
return 3 * Left.Magnitude() + 2 * Right.Magnitude();
}
public static Node Add(Node left, Node right) {
var top = new Node() {Left = left, Right = right};
left.Parent = top;
right.Parent = top;
return top;
}
public bool Explode(int depth) {
if (depth >= 4 && Leaf == null && (Left.Leaf == null || Right.Leaf == null)) {
if (Left.Leaf == null) {
var oldLeft = Left;
Left = new Node() {Leaf = 0, Parent = this};
if (oldLeft.Left.Leaf == null || oldLeft.Right.Leaf == null) {
throw new ArgumentException("left or right was null");
} else {
Parent?.AddValueLeftParent(oldLeft.Left.Leaf ?? -9999, this);
Right.AddValueLeftChild(oldLeft.Right.Leaf ?? -9999);
}
return true;
}
if (Right.Leaf == null) {
var oldRight = Right;
Right = new Node() {Leaf = 0, Parent = this};
if (oldRight.Left.Leaf == null || oldRight.Right.Leaf == null) {
throw new ArgumentException("left or right was null");
} else {
Left.AddValueRightChild(oldRight.Left.Leaf ?? -9999);
Parent?.AddValueRightParent(oldRight.Right.Leaf ?? -9999, this);
}
return true;
}
} else if (Leaf == null) {
if (Left.Explode(depth + 1)) {
return true;
} else if (Right.Explode(depth + 1)) {
return true;
}
}
return false;
}
public bool AddValueLeftParent(int value, Node from) {
if (Leaf != null) {
Leaf += value;
return true;
}
if (Left == from) {
if (Parent == null) {
return false;
}
return Parent.AddValueLeftParent(value, this);
}
if (Right == from) {
return Left.AddValueRightChild(value);
}
return AddValueRightChild(value);
}
public bool AddValueRightParent(int value, Node from) {
if (Leaf != null) {
Leaf += value;
return true;
}
if (Right == from) {
if (Parent == null) {
return false;
}
return Parent.AddValueRightParent(value, this);
}
if (Left == from) {
return Right.AddValueLeftChild(value);
}
return AddValueLeftChild(value);
}
public bool AddValueLeftChild(int value) {
if (Leaf != null) {
Leaf += value;
return true;
}
return Left.AddValueLeftChild(value);
}
public bool AddValueRightChild(int value) {
if (Leaf != null) {
Leaf += value;
return true;
}
return Right.AddValueRightChild(value);
}
public bool Split() {
if (Leaf == null) {
if (Left.Split()) {
return true;
}
if (Right.Split()) {
return true;
}
return false;
} else if (Leaf > 9){
var leftValue = Leaf / 2;
var rightValue = Leaf - leftValue;
Leaf = null;
Left = new Node() {Leaf = leftValue, Parent = this};
Right = new Node() {Leaf = rightValue, Parent = this};
return true;
}
return false;
}
public static Node Parse(string number) {
int pos = 0;
return Parse(ref pos, number, null);
}
public static Node Parse(ref int pos, string number, Node parent) {
var cur = new Node() {Parent = parent};
if (number[pos] == '[') {
pos++;
cur.Left = Node.Parse(ref pos, number, cur);
pos++; // ignore comma
cur.Right = Node.Parse(ref pos, number, cur);
pos++; // ignore closing bracket
} else {
// for debugging
int i = 0;
while ("1234567890".Contains(number[pos + i])) {
i++;
}
cur.Leaf = int.Parse(number.Substring(pos, i));
pos += i;
}
return cur;
}
public override string ToString() {
return Print();
}
}
#endif

View File

@ -0,0 +1,185 @@
// #define Day18_2
#if Day18_2
using System.Text.RegularExpressions;
var lines = File.ReadAllLines("day18/input");
var numberToSplit = new Regex(@"\d{2,}");
var numbersToMatch = new Regex(@"\d+");
var cur = lines.First();
foreach (var l in lines.Skip(1)) {
cur = Add(cur, l);
cur = Reduce(cur);
}
var bla = Node.Parse(cur);
Console.WriteLine(bla);
Console.WriteLine(bla.Magnitude());
List<long> magnitudes = new List<long>();
for (int i = 0; i < lines.Length; i++) {
for (int j = 0; j < lines.Length; j++) {
if (i == j) {continue;}
var test = Add(lines[i], lines[j]);
var reducedTest = Reduce(test);
magnitudes.Add(Node.Parse(reducedTest).Magnitude());
var testReverse = Add(lines[j], lines[i]);
var reducedTestReverse = Reduce(testReverse);
magnitudes.Add(Node.Parse(reducedTestReverse).Magnitude());
}
}
Console.WriteLine(magnitudes.Max());
string Reduce(string number) {
bool changed = false;
do {
(changed, number) = Explode(number);
if (!changed) {
(changed, number) = Split(number);
}
} while (changed);
return number;
}
Changed Explode(string number) {
int depth = 0;
int pos = 0;
while (depth < 5 && pos < number.Length) {
if (number[pos] == '[') {
depth++;
} else if (number[pos] == ']'){
depth--;
}
pos++;
}
if (depth < 5) {
return new Changed(false, number);
}
int startOfExplode = pos;
while (number[pos] != ']') {
pos++;
}
int endOfExplode = pos;
var exploded = number.Substring(startOfExplode, endOfExplode - startOfExplode);
var explodedNumbers = exploded.Split(",").Select(int.Parse).ToList();
var matches = numbersToMatch.Matches(number);
var leftAddMatch = matches.Where(m => m.Index < startOfExplode).MaxBy(m => m.Index);
var rightAddMatch = matches.Where(m => m.Index > endOfExplode).MinBy(m => m.Index);
if (leftAddMatch != null && rightAddMatch != null) {
var before = number.Substring(0, leftAddMatch.Index);
var after = number.Substring(rightAddMatch.Index + rightAddMatch.Length,
number.Length - rightAddMatch.Index - rightAddMatch.Length);
var beforeExplosion = number.Substring(leftAddMatch.Index + leftAddMatch.Length,
startOfExplode - leftAddMatch.Index - leftAddMatch.Length - 1);
var afterExplosion = number.Substring(endOfExplode + 1, rightAddMatch.Index - endOfExplode - 1);
var leftAdded = int.Parse(leftAddMatch.Value) + explodedNumbers[0];
var rightAdded = int.Parse(rightAddMatch.Value) + explodedNumbers[1];
return new Changed(true, $"{before}{leftAdded}{beforeExplosion}0{afterExplosion}{rightAdded}{after}");
} else if (leftAddMatch == null) {
var before = number.Substring(0, startOfExplode - 1);
var after = number.Substring(rightAddMatch.Index + rightAddMatch.Length,
number.Length - rightAddMatch.Index - rightAddMatch.Length);
var afterExplosion = number.Substring(endOfExplode + 1, rightAddMatch.Index - endOfExplode - 1);
var rightAdded = int.Parse(rightAddMatch.Value) + explodedNumbers[1];
return new Changed(true, $"{before}0{afterExplosion}{rightAdded}{after}");
} else if (rightAddMatch == null) {
var before = number.Substring(0, leftAddMatch.Index);
var after = number.Substring(endOfExplode + 1,
number.Length - endOfExplode - 1);
var beforeExplosion = number.Substring(leftAddMatch.Index + leftAddMatch.Length,
startOfExplode - leftAddMatch.Index - leftAddMatch.Length - 1);
var leftAdded = int.Parse(leftAddMatch.Value) + explodedNumbers[0];
return new Changed(true, $"{before}{leftAdded}{beforeExplosion}0{after}");
}
throw new ArgumentException();
}
Changed Split(string number) {
var m = numberToSplit.Match(number);
if (!m.Success) {
return new Changed(false, number);
}
var before = number.Substring(0, m.Index);
var after = number.Substring(m.Index + m.Length, number.Length - m.Index - m.Length);
var value = int.Parse(m.Value);
int first = value / 2;
int second = value - first;
return new Changed(true, $"{before}[{first},{second}]{after}");
}
string Add(string first, string second) {
return $"[{first},{second}]";
}
record Changed(bool changed, string number);
class Node {
public Node? Parent { get; set; }
public Node? Left { get; set; }
public Node? Right { get; set; }
public int? Leaf { get; set; }
public string Print() {
if (Leaf != null) {
return $"{Leaf}";
} else {
return $"[{Left.Print()},{Right.Print()}]";
}
}
public long Magnitude() {
if (Leaf != null) {
return Leaf ?? -9999;
}
return 3 * Left.Magnitude() + 2 * Right.Magnitude();
}
public static Node Parse(string number) {
int pos = 0;
return Parse(ref pos, number, null);
}
public static Node Parse(ref int pos, string number, Node parent) {
var cur = new Node() {Parent = parent};
if (number[pos] == '[') {
pos++;
cur.Left = Node.Parse(ref pos, number, cur);
pos++; // ignore comma
cur.Right = Node.Parse(ref pos, number, cur);
pos++; // ignore closing bracket
} else {
// for debugging
int i = 0;
while ("1234567890".Contains(number[pos + i])) {
i++;
}
cur.Leaf = int.Parse(number.Substring(pos, i));
pos += i;
}
return cur;
}
public override string ToString() {
return Print();
}
}
#endif

1
day16/input Normal file
View File

@ -0,0 +1 @@
4054460802532B12FEE8B180213B19FA5AA77601C010E4EC2571A9EDFE356C7008E7B141898C1F4E50DA7438C011D005E4F6E727B738FC40180CB3ED802323A8C3FED8C4E8844297D88C578C26008E004373BCA6B1C1C99945423798025800D0CFF7DC199C9094E35980253FB50A00D4C401B87104A0C8002171CE31C41201062C01393AE2F5BCF7B6E969F3C553F2F0A10091F2D719C00CD0401A8FB1C6340803308A0947B30056803361006615C468E4200E47E8411D26697FC3F91740094E164DFA0453F46899015002A6E39F3B9802B800D04A24CC763EDBB4AFF923A96ED4BDC01F87329FA491E08180253A4DE0084C5B7F5B978CC410012F9CFA84C93900A5135BD739835F00540010F8BF1D22A0803706E0A47B3009A587E7D5E4D3A59B4C00E9567300AE791E0DCA3C4A32CDBDC4830056639D57C00D4C401C8791162380021108E26C6D991D10082549218CDC671479A97233D43993D70056663FAC630CB44D2E380592FB93C4F40CA7D1A60FE64348039CE0069E5F565697D59424B92AF246AC065DB01812805AD901552004FDB801E200738016403CC000DD2E0053801E600700091A801ED20065E60071801A800AEB00151316450014388010B86105E13980350423F447200436164688A4001E0488AC90FCDF31074929452E7612B151803A200EC398670E8401B82D04E31880390463446520040A44AA71C25653B6F2FE80124C9FF18EDFCA109275A140289CDF7B3AEEB0C954F4B5FC7CD2623E859726FB6E57DA499EA77B6B68E0401D996D9C4292A881803926FB26232A133598A118023400FA4ADADD5A97CEEC0D37696FC0E6009D002A937B459BDA3CC7FFD65200F2E531581AD80230326E11F52DFAEAAA11DCC01091D8BE0039B296AB9CE5B576130053001529BE38CDF1D22C100509298B9950020B309B3098C002F419100226DC

1
day17/input Normal file
View File

@ -0,0 +1 @@
target area: x=144..178, y=-100..-76

100
day18/input Normal file
View File

@ -0,0 +1,100 @@
[6,[[5,[7,7]],[[8,2],2]]]
[[8,[0,0]],[[[1,4],[2,0]],[[2,3],[8,2]]]]
[[[7,[6,1]],[9,[7,9]]],[[6,6],2]]
[[5,[2,0]],[[[9,4],[6,8]],[3,9]]]
[[[3,[0,3]],[5,[9,8]]],[[5,[8,1]],[1,2]]]
[[[5,[8,5]],[[6,3],3]],[[1,[0,9]],[[3,0],[7,3]]]]
[[[[1,2],0],[8,[6,6]]],[6,[7,5]]]
[[[[0,9],[5,3]],[[9,7],8]],[9,[[1,9],1]]]
[[4,[6,[0,8]]],[[2,9],1]]
[[[5,1],[6,[9,5]]],8]
[[[4,[7,0]],1],[3,3]]
[2,[[3,4],6]]
[[[[0,5],[7,1]],[[7,0],[1,7]]],2]
[[3,[7,8]],[[1,0],[[1,7],6]]]
[[[7,[6,3]],1],[4,[1,[6,8]]]]
[[[[5,5],[3,5]],[5,[2,6]]],[3,[1,[3,2]]]]
[[8,2],9]
[[8,[[1,9],2]],[[8,[8,4]],3]]
[[[[8,7],9],5],[[[0,6],5],[6,5]]]
[[2,6],[0,[[9,8],6]]]
[[[[7,9],0],[[1,5],9]],[[[2,2],1],[3,1]]]
[[8,[1,[9,1]]],[0,[0,[2,4]]]]
[[[[0,2],3],[[9,4],9]],[[3,2],[[5,7],[4,8]]]]
[[[[8,0],3],[9,[5,9]]],[4,3]]
[2,[7,[[3,3],[7,9]]]]
[3,[[[6,4],0],5]]
[[1,[[9,9],9]],[[[0,3],[0,6]],0]]
[[7,[[2,3],4]],[6,[9,9]]]
[3,5]
[[[[2,3],2],[1,[9,9]]],[[8,2],[1,[2,0]]]]
[[[[7,2],[3,6]],[[9,7],[8,9]]],[[[5,3],[5,1]],6]]
[8,[[7,0],[[8,2],5]]]
[[[1,[1,0]],[[3,7],[4,5]]],[[[6,5],2],1]]
[8,[[5,0],3]]
[[[4,1],9],[1,5]]
[[9,[5,[3,7]]],[[0,4],4]]
[[[[9,6],4],[8,[7,5]]],[[6,9],5]]
[[[7,[2,5]],0],[8,[0,7]]]
[8,[[4,[1,8]],[[8,9],3]]]
[[[[3,7],[7,3]],[[5,3],1]],[[[6,7],[2,7]],[[2,6],[9,0]]]]
[[[9,[5,4]],[[1,7],2]],[[1,0],[[2,6],0]]]
[[[[3,2],[5,3]],[9,[2,0]]],[[7,6],[[8,2],[0,7]]]]
[[[4,0],0],[9,0]]
[[[[9,4],[0,9]],[2,3]],8]
[[2,[8,[6,7]]],[[[6,1],[5,1]],[3,[1,1]]]]
[[6,[[8,2],7]],5]
[[[[7,3],[9,7]],5],[[[0,9],4],[3,[0,3]]]]
[[2,[6,7]],[[[9,0],[6,7]],4]]
[[[[3,1],5],[7,[5,1]]],[[[8,4],9],[[2,7],[4,6]]]]
[[8,8],[[[1,4],[7,3]],[[9,6],5]]]
[[[[3,0],8],[[5,1],[7,8]]],[[[5,0],[2,2]],[[9,0],[0,7]]]]
[[1,1],7]
[[4,3],[[9,[7,3]],[2,3]]]
[[[5,[3,5]],3],7]
[[[5,[3,2]],1],[[[3,2],8],[8,5]]]
[[7,[6,5]],[[[9,8],7],6]]
[[[7,9],0],[3,4]]
[[[[5,6],[7,4]],[4,[1,7]]],[[[8,2],7],[6,[4,5]]]]
[[[[8,5],1],[[7,0],[9,7]]],[[[5,2],3],2]]
[[[[7,3],9],7],[[[8,1],9],3]]
[[[6,5],[4,[6,1]]],7]
[[[[4,0],1],[4,4]],[[1,7],[3,0]]]
[9,[[2,[9,0]],6]]
[[[[0,0],9],2],[9,3]]
[5,[5,[[6,6],[2,6]]]]
[[[[8,2],[8,9]],[[8,4],[8,0]]],[[[9,5],6],4]]
[[[3,[6,1]],[3,[6,9]]],[3,4]]
[[[7,[6,3]],[[6,7],1]],[[1,1],2]]
[[[[1,2],[7,1]],[[7,7],4]],3]
[[[[7,2],4],[[4,7],[2,4]]],[1,[[6,2],4]]]
[4,[[0,4],5]]
[[[4,6],[0,[8,2]]],[[4,[8,7]],[[7,9],0]]]
[[[9,2],[5,2]],7]
[[9,[2,2]],4]
[[[6,2],[[4,3],[3,9]]],[[4,1],[[9,4],4]]]
[[[7,[4,2]],4],[[8,[9,3]],[[9,0],[5,4]]]]
[[[[4,1],[4,6]],[2,[4,5]]],[[1,[1,5]],9]]
[[[[5,2],8],6],[1,[[8,9],4]]]
[[[6,[4,2]],[6,[5,5]]],[0,3]]
[[7,[5,[7,0]]],[[[7,2],0],[[7,3],8]]]
[[3,[[2,3],[2,8]]],[5,7]]
[[[[8,0],[6,4]],[[3,7],3]],[[[7,3],[9,8]],[[8,0],8]]]
[[2,[5,2]],[[[0,9],[4,1]],[[8,8],4]]]
[[[[4,1],[6,5]],[[2,7],[5,8]]],[[[7,1],[2,3]],2]]
[[3,5],2]
[[9,2],[[6,[1,9]],[9,5]]]
[[4,[3,8]],[[4,[0,3]],[1,1]]]
[[[6,[0,7]],[[0,4],[6,1]]],[[8,5],[[5,2],[7,2]]]]
[[[[8,8],[6,3]],[[0,2],[6,5]]],[[[7,6],[5,4]],[4,[7,1]]]]
[[[[7,6],[5,8]],[6,1]],[0,[[0,8],9]]]
[[[6,[2,2]],[5,2]],6]
[[[7,9],[[1,5],8]],2]
[[[3,3],[5,6]],[[3,[3,6]],[2,[5,9]]]]
[[[[0,8],[0,1]],[[8,6],4]],[[0,[1,3]],4]]
[[6,[4,4]],[4,[0,4]]]
[[[3,4],[4,1]],8]
[[0,[[4,6],[5,1]]],[[0,[4,3]],[6,9]]]
[[[0,7],2],[[4,9],[1,6]]]
[[1,0],[[[4,9],9],[[5,4],9]]]
[8,[[[1,4],[5,5]],[1,[0,9]]]]