Compare commits

...

12 Commits

Author SHA1 Message Date
625a9e5ad5 Aoc 2025 day 1 2025-12-01 21:21:14 -05:00
ef959284a5 misc 2025-04-21 09:58:20 -04:00
bba775fd4e wip day 12 2025-02-09 14:21:48 -05:00
f16899ff3c wip day 12 part 2 2025-02-08 17:22:39 -05:00
6606f40df9 day 12 part 1 2024-12-23 21:10:08 -05:00
199b940ff9 misc 2024-12-18 23:14:11 -05:00
63eb4d01b0 day 11 part 2 2024-12-18 23:13:40 -05:00
a33843ae1b Day 11 part 1 2024-12-18 21:59:43 -05:00
e08a60614a Merge branch 'master' of https://github.com/Amatsugu/AdventOfCode 2024-12-17 19:44:33 -05:00
6a9c813d08 day 10 2024-12-17 19:44:30 -05:00
ba7e6d4be0 Update DiskFragmenter.cs 2024-12-17 09:40:42 -05:00
a4cb169566 fix part 2 2024-12-17 09:40:15 -05:00
79 changed files with 7244 additions and 6631 deletions

View File

@@ -76,6 +76,8 @@
<ItemGroup>
<PackageReference Include="Superpower" Version="3.0.0" />
<PackageReference Include="MaybeError" Version="1.2.0" />
<PackageReference Include="Superpower" Version="3.1.1-dev-00257" />
<PackageReference Include="ZLinq" Version="1.5.4" />
</ItemGroup>
</Project>

View File

@@ -1,25 +1,102 @@
using System;
using AdventOfCode.Utils.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2024.Day10;
//[ProblemInfo(2024, 10, "Hoof It")]
internal class HoofIt : Problem
[ProblemInfo(2024, 10, "Hoof It")]
internal class HoofIt : Problem<int, int>
{
private int[][] _data = [];
public static Vec2<int>[] DIRS = [
new(0, -1),
new(1, 0),
new(0, 1),
new(-1, 0),
];
public override void CalculatePart1()
{
throw new NotImplementedException();
for (int y = 0; y < _data.Length; y++)
{
var row = _data[y];
for (int x = 0; x < row.Length; x++)
{
var h = row[x];
if (h != 0)
continue;
var (s,_) = GetScore(new(x, y));
Part1 += s;
}
}
}
public override void CalculatePart2()
{
throw new NotImplementedException();
for (int y = 0; y < _data.Length; y++)
{
var row = _data[y];
for (int x = 0; x < row.Length; x++)
{
var h = row[x];
if (h != 0)
continue;
var (_, s) = GetScore(new(x, y));
Part2 += s;
}
}
}
public (int score, int scoreDistinct) GetScore(Vec2<int> pos)
{
return GetScore(pos, []);
}
public (int score, int scoreDistinct) GetScore(Vec2<int> pos, HashSet<Vec2<int>> visited)
{
var curHeight = _data[pos.Y][pos.X];
if (curHeight == 9)
{
if(visited.Contains(pos))
return (0, 1);
visited.Add(pos);
return (1, 1);
}
var score = 0;
var scoreDistinct = 0;
foreach (var dir in DIRS)
{
var n = pos + dir;
if (!IsInBounds(n))
continue;
var h = _data[n.Y][n.X];
if (h - curHeight != 1)
continue;
var (s, d)= GetScore(n, visited);
score += s;
scoreDistinct += d;
}
return (score, scoreDistinct);
}
public bool IsInBounds(Vec2<int> pos)
{
if (pos.X < 0 || pos.Y < 0)
return false;
if(pos.X >= _data.Length || pos.Y >= _data[0].Length)
return false;
return true;
}
public override void LoadInput()
{
throw new NotImplementedException();
_data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
}
}

View File

@@ -1,25 +1,115 @@
using System;
using Superpower.Model;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace AdventOfCode.Problems.AOC2024.Day11;
//[ProblemInfo(2024, 11, "Plutonian Pebbles")]
internal class PlutonianPebbles : Problem
[ProblemInfo(2024, 11, "Plutonian Pebbles")]
public class PlutonianPebbles : Problem<long, long>
{
private List<long> _data = [];
private readonly Dictionary<(long, long), long> _depthLookup = [];
public override void CalculatePart1()
{
throw new NotImplementedException();
Part1 = _data.Sum(v => ProcessStoneRecursive(v, 25));
}
public override void CalculatePart2()
{
throw new NotImplementedException();
Part2 = _data.Sum(v => ProcessStoneRecursive(v, 75));
}
public long ProcessStoneRecursive(long stone, long target, long curDepth = 0)
{
if (curDepth == target)
return 1;
var d = target - curDepth;
if(_depthLookup.TryGetValue((stone, d), out var c))
return c;
long result;
if (stone == 0)
result = ProcessStoneRecursive(1, target, curDepth + 1);
else if (FastSplit(stone, out var left, out var right))
result = ProcessStoneRecursive(left, target, curDepth + 1) + ProcessStoneRecursive(right, target, curDepth + 1);
else
result = ProcessStoneRecursive(stone * 2024, target, curDepth + 1);
_depthLookup.Add((stone, d), result);
return result;
}
public long Run(long count)
{
var a = _data.ToList();
var b = new List<long>(a.Count);
for (long i = 0; i < count; i++)
{
foreach (var stone in a)
ProcessStone(stone, b);
(a, b) = (b, a);
b.Clear();
}
return a.Count;
}
public void ProcessStone(long stone, List<long> data)
{
if (stone == 0)
{
data.Add(1);
return;
}
if (FastSplit(stone, out var left, out var right))
{
data.Add(left);
data.Add(right);
return;
}
data.Add(stone * 2024);
}
private static IEnumerable<long> Split(long stone, int len)
{
var v = stone.ToString();
return [long.Parse(v[..(len / 2)]), long.Parse(v[(len / 2)..])];
}
private static bool FastSplit(long stone, out long left, out long right)
{
var len = stone.DigitCount();
if (len % 2 != 0)
{
left = 0;
right = 0;
return false;
}
var l = QuickMath.FastPow10(len / 2);
var a = stone / l;
(left, right) = (a, stone - (a * l));
return true;
}
private static bool IsEvenDigits(long value, out int len)
{
var v = len = value.ToString().Length;
return v % 2 == 0;
}
public override void LoadInput()
{
throw new NotImplementedException();
_data = ReadInputText("input.txt").Split(' ').Select(long.Parse).ToList();
}
}

View File

@@ -0,0 +1,301 @@
using AdventOfCode.Utils.Models;
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace AdventOfCode.Problems.AOC2024.Day12;
[ProblemInfo(2024, 12, "Garden Groups")]
internal class GardenGroups : Problem<int, int>
{
private char[][] _data = [];
public static readonly Vec2<int>[] DIRS = [
new(0,1),
new(1,0),
new(0,-1),
new(-1,0),
];
public override void CalculatePart1()
{
var r = FindPlots(_data);
Part1 = r.Sum(plot => plot.area.Count * plot.perimeter);
}
public override void CalculatePart2()
{
var plots = FindPlots(_data);
var r = plots.Select(plot => (plot.plant, area: plot.area.Count, sides: CountSides(GroupSides(plot.outline, plot.area), plot.area)));
foreach (var (plant, area, perimeter, outline) in plots)
{
Console.WriteLine();
var groups = GroupSides(outline, area);
Console.WriteLine($"{plant}: {CountSides(groups, area)}, {groups.Count}");
DrawPlot(area, groups, plant);
}
Part2 = r.Sum(v => v.area * v.sides);
}
public static List<List<Vec2<int>>> GroupSides(List<Vec2<int>> outline, List<Vec2<int>> area)
{
var result = new List<List<Vec2<int>>>();
var visited = new HashSet<Vec2<int>>();
var open = new HashSet<Vec2<int>>(outline);
while (open.Count > 0)
{
var p = open.First();
open.Remove(p);
if(visited.Contains(p))
continue;
visited.Add(p);
var group = new List<Vec2<int>>() { p };
GetGroup(p, group);
result.Add(group);
}
void GetGroup(Vec2<int> point, List<Vec2<int>> group)
{
var up = DIRS[0];
var right = DIRS[1];
if(outline.Contains(point + up) || outline.Contains(point - up))
{
ProcessDirection(point, up, group);
ProcessDirection(point, -up, group);
}
else if(outline.Contains(point + right) || outline.Contains(point - right))
{
ProcessDirection(point, right, group);
ProcessDirection(point, -right, group);
}
}
void ProcessDirection(Vec2<int> point, Vec2<int> dir, List<Vec2<int>> group)
{
var n = point + dir;
if (!outline.Contains(n) || visited.Contains(n))
return;
//if (!area.Contains(n + dir.YX) && !area.Contains(n - dir.YX))
// return;
visited.Add(n);
group.Add(n);
ProcessDirection(n, dir, group);
}
return result;
}
public static void DrawPlot(List<Vec2<int>> area, List<List<Vec2<int>>> outline, char plant)
{
var (min, max) = GetBounds(outline.SelectMany(v => v).ToList());
int Sides(Vec2<int> point, List<Vec2<int>> group)
{
var s = 0;
foreach (var dir in DIRS)
{
var n = point + dir;
if (area.Contains(n))
s++;
if(group.Count > 1 && outline.Any(g => group != g && g.Contains(n)))
s--;
}
return s;
}
ConsoleColor[] colors = [
ConsoleColor.Red,
ConsoleColor.DarkGreen,
ConsoleColor.Blue,
ConsoleColor.DarkRed,
ConsoleColor.Magenta,
ConsoleColor.DarkCyan,
ConsoleColor.DarkBlue,
ConsoleColor.DarkMagenta,
ConsoleColor.DarkYellow
];
for (int y = min.Y; y <= max.Y; y++)
{
for (int x = min.X; x <= max.X; x++)
{
Console.ResetColor();
var p = new Vec2<int>(x,y);
if (area.Contains(p))
{
Console.BackgroundColor = ConsoleColor.Black;
Console.Write(plant);
}
else
{
var curSideGroup = outline.FirstOrDefault(v => v.Contains(p));
if (curSideGroup != null)
{
var idx = outline.IndexOf(curSideGroup);
Console.BackgroundColor = colors[idx % colors.Length];
var s = Sides(p, curSideGroup);
if(curSideGroup.Count > 1 && IsInclosed(curSideGroup, outline, area))
Console.Write('&');
else
Console.Write(s);
}else
Console.Write(' ');
}
Console.ResetColor();
}
Console.ResetColor();
Console.WriteLine();
}
Console.ResetColor();
}
public static void DrawPoints(List<Vec2<int>> data, char display)
{
var (min, max) = GetBounds(data);
var output = new StringBuilder();
for (int y = min.Y; y <= max.Y; y++)
{
for (int x = min.X; x <= max.X; x++)
{
var p = new Vec2<int>(x,y);
if (data.Contains(p))
output.Append(display);
else
output.Append(' ');
}
output.AppendLine();
}
Console.WriteLine(output);
}
public static (Vec2<int> min, Vec2<int> max) GetBounds(List<Vec2<int>> points)
{
var min = Vec2<int>.Splat(int.MaxValue);
var max = Vec2<int>.Splat(int.MinValue);
foreach (var pos in points)
{
if (pos.X < min.X)
min.X = pos.X;
if (pos.Y < min.Y)
min.Y = pos.Y;
if (pos.X > max.X)
max.X = pos.X;
if (pos.Y > max.Y)
max.Y = pos.Y;
}
return (min, max);
}
public static bool IsInclosed(List<Vec2<int>> side, List<List<Vec2<int>>> sides, List<Vec2<int>> area)
{
var otherSides = sides.Where(g => g != side).SelectMany(s => s).ToFrozenSet();
foreach (var point in side)
{
foreach (var dir in DIRS)
{
var n = point + dir;
if (side.Contains(n))
continue;
if (!area.Contains(n))
return false;
if (otherSides.Contains(n))
return false;
}
}
return true;
}
public static int CountSides(List<List<Vec2<int>>> groups, List<Vec2<int>> area)
{
int Sides(Vec2<int> point, List<Vec2<int>> group)
{
var s = 0;
foreach (var dir in DIRS)
{
var n = point + dir;
if(area.Contains(n))
s++;
if (group.Count > 1 && groups.Any(g => group != g && g.Contains(n)))
s--;
}
return s;
}
return groups.Sum(s => s.Select(p => Sides(p, s)).Max() + (s.Count > 1 && IsInclosed(s, groups, area) ? 1 : 0));
}
private static List<(char plant, List<Vec2<int>> area, int perimeter, List<Vec2<int>> outline)> FindPlots(char[][] data)
{
var visited = new HashSet<Vec2<int>>(data.Length * data[0].Length);
var results = new List<(char plant, List<Vec2<int>>, int perimeter, List<Vec2<int>> outline)>();
for (int y = 0; y < data.Length; y++)
{
var row = data[y];
for (int x = 0; x < row.Length; x++)
{
var p = new Vec2<int>(x, y);
if (visited.Contains(p))
continue;
var members = new List<Vec2<int>>();
var plant = data[y][x];
var perimeter = 0;
var outline = new List<Vec2<int>>();
GetMembers(data, plant, p, visited, members, ref perimeter, outline);
results.Add((plant, members, perimeter, outline));
}
}
return results;
}
private static void GetMembers(char[][] data, char plant, Vec2<int> point, HashSet<Vec2<int>> visited, List<Vec2<int>> members, ref int perimeter, List<Vec2<int>> outline)
{
if (visited.Contains(point))
return;
visited.Add(point);
members.Add(point);
foreach (var dir in DIRS)
{
var n = dir + point;
if (!IsInBounds(n, data))
{
perimeter += 1;
outline.Add(n);
continue;
}
if (data[n.Y][n.X] != plant)
{
perimeter += 1;
outline.Add(n);
continue;
}
GetMembers(data, plant, n, visited, members, ref perimeter, outline);
}
}
public static bool IsInBounds(Vec2<int> pos, char[][] data)
{
if (pos.X < 0 || pos.Y < 0)
return false;
if (pos.X >= data.Length || pos.Y >= data[0].Length)
return false;
return true;
}
public override void LoadInput()
{
_data = ReadInputLines("sample3.txt").Select(ln => ln.ToCharArray()).ToArray();
}
}

View File

@@ -22,7 +22,16 @@ internal class DiskFragmenter : Problem<long, long>
public override void CalculatePart2()
{
var blocks = ExpandBlocks(_data);
var empty = blocks.Where(b => b.isEmpty).Sum(b => b.length);
var files = blocks.Where(b => !b.isEmpty).Sum(b => b.length);
CompactV2(blocks);
var empty2 = blocks.Where(b => b.isEmpty).Sum(b => b.length);
var files2 = blocks.Where(b => !b.isEmpty).Sum(b => b.length);
if (empty != empty2)
Console.WriteLine("Empty space does not match");
if (files != files2)
Console.WriteLine($"Files space does not match Befor: {files} -> {files2}");
//Print(blocks);
// Too High: 8838426222802
Part2 = ComputeHashV2(blocks);
@@ -174,10 +183,16 @@ internal class DiskFragmenter : Problem<long, long>
}
//Extend Right Block
else if (idx + 1 < blocks.Count && blocks[idx + 1].isEmpty)
{
blocks[idx + 1].length += block.length;
blocks.RemoveAt(idx);
}
//Extend Left Block
else if (idx - 1 > 0 && blocks[idx - 1].isEmpty)
{
blocks[idx - 1].length += block.length;
blocks.RemoveAt(idx);
}
//Insert new Empty Block
else
blocks[idx] = new Block(block.length);

View File

@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZLinq;
namespace AdventOfCode.Problems.AOC2025.Day1;
[ProblemInfo(2025, 1, "Secret Entrance")]
internal class SecretEntrance : Problem<int, int>
{
public int[] Input { get; set; } = [];
public override void CalculatePart1()
{
var c = 0;
var v = 50;
foreach (var item in Input)
{
v += item;
v = v.Mod(100);
if (v == 0)
c++;
}
Part1 = c;
}
public override void CalculatePart2()
{
var c = 0;
var v = 50;
foreach (var item in Input)
{
var sign = int.Sign(item);
for (int i = 0; i < Math.Abs(item); i++)
{
v += sign;
v = v.Mod(100);
if (v == 0)
c++;
}
}
Part2 = c;
}
public override void LoadInput()
{
Input = ReadInputLines("input.txt")
.AsValueEnumerable()
.Select(l =>
{
return l[0] switch
{
'L' => -int.Parse(l[1..]),
'R' => int.Parse(l[1..]),
_ => throw new NotImplementedException()
};
}).ToArray();
}
}

View File

@@ -6,6 +6,7 @@ using System.Text;
using System.Threading.Tasks;
namespace AdventOfCode.Runner;
public static class ExtraMath
{
public static T GCF<T>(this T a, T b) where T : INumber<T>
@@ -23,4 +24,14 @@ public static class ExtraMath
{
return (a / GCF(a, b)) * b;
}
public static T Max<T>(this T a, T b) where T : INumber<T>
{
return T.Max(a, b);
}
public static T Min<T>(this T a, T b) where T : INumber<T>
{
return T.Min(a, b);
}
}

View File

@@ -1,16 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
namespace AdventOfCode.Utils;
public static class Extensions
{
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
{
return string.Join(delim, data);
}
public static T Mod<T>(this T value, T divisor) where T : INumber<T>
{
T remainder = value % divisor;
if (remainder < T.Zero)
return remainder + divisor;
else
return remainder;
}
}

View File

@@ -4,6 +4,13 @@ namespace AdventOfCode.Utils.Models;
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
{
public static Vec2<T> Zero => new (T.Zero, T.Zero);
public static Vec2<T> One => new (T.One, T.One);
public readonly Vec2<T> YX => new(Y, X);
public readonly Vec2<T> YY => new(Y, Y);
public readonly Vec2<T> XX => new(X, X);
public static Vec2<T> Splat(T v) => new(v, v);
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
@@ -21,6 +28,9 @@ public record struct Vec2<T>(T X, T Y) where T : INumber<T>
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
{
public static Vec3<T> Zero => new(T.Zero, T.Zero, T.Zero);
public static Vec3<T> One => new(T.One, T.One, T.One);
public static Vec3<T> Splat(T v) => new(v, v, v);
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);

View File

@@ -0,0 +1,37 @@
namespace AdventOfCode.Utils;
public static class QuickMath
{
private static readonly long[] pow10Long = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000];
private static readonly int[] pow10int = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
public static long FastPow10(long exp)
{
return pow10Long[exp];
}
public static int FastPow10(int exp)
{
return pow10int[exp];
}
private static readonly long[] longCorrectionTable= [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 9999999999, 99999999999, 999999999999, 9999999999999, 99999999999999, 999999999999999, 9999999999999999, 99999999999999999, 999999999999999999];
private static readonly int[] intCorrectionTable = [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999];
public static long DigitCount(this long value)
{
var l2 = 63 - long.LeadingZeroCount(value | 1);
var ans = ((9 * l2) >> 5);
if (value > longCorrectionTable[ans])
ans += 1;
return ans + 1;
}
public static int DigitCount(this int value)
{
var l2 = 31 - int.LeadingZeroCount(value | 1);
var ans = ((9 * l2) >> 5);
if (value > intCorrectionTable[ans])
ans += 1;
return ans + 1;
}
}