Compare commits

..

19 Commits

Author SHA1 Message Date
5f45853889 misc 2025-12-06 21:29:45 -05:00
55a8ea0281 day 6 2025-12-06 21:13:53 -05:00
e56befa18b day 5 2025-12-05 20:00:59 -05:00
9f1a2d2300 day 4 pt 1 2025-12-04 12:58:34 -05:00
a0c97e4b75 day 2 pt 1; day 3 2025-12-03 20:29:39 -05:00
629b13abef wip day 2 2025-12-02 19:58:33 -05:00
4f4ccf7117 optimized day 1 2025-12-02 18:05:45 -05:00
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
85 changed files with 7682 additions and 6631 deletions

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
@@ -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,69 @@
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 const int LOCK_SIZE = 100;
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(LOCK_SIZE);
if (v == 0)
c++;
}
Part1 = c;
}
public override void CalculatePart2()
{
var c = 0;
var v = 50;
foreach (var item in Input)
{
var vStart = v;
v += item;
if (item > 0)
c += (int)Math.Floor(v / (float)LOCK_SIZE);
else
{
var d = v / (float)LOCK_SIZE;
var fl = Math.Floor(d);
c += (int)Math.Abs(fl) - (vStart == 0 ? 1 : 0);
if (fl == d)
c += 1;
}
v = v.Mod(LOCK_SIZE);
}
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

@@ -0,0 +1,8 @@
[-100]: 1 | start: 50 v: 50
[100]: 1 | start: 50 v: 50
[-150]: 2 | start: 50 v: 0
[150]: 1 | start: 0 v: 50
[-500]: 5 | start: 50 v: 50
[500]: 5 | start: 50 v: 50
[-550]: 6 | start: 50 v: 0
[550]: 5 | start: 0 v: 5

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;
using ZLinq;
namespace AdventOfCode.Problems.AOC2025.Day2;
[ProblemInfo(2025, 2, "Gift Shop")]
internal class GiftShop : Problem<long, long>
{
private IdRange[] _ranges = [];
public override void CalculatePart1()
{
var v = _ranges.SelectMany(GetDoubleSequences);
//Console.WriteLine(v.AsJoinedString());
Part1 = v.Sum();
}
public static long[] GetDoubleSequences(IdRange range)
{
range = range.Snap();
var minDigits = range.Min.DigitCount() / 2;
var maxDigits = range.Max.DigitCount() / 2;
var min = GetMinValue((int)minDigits, range.Min);
var max = GetMaxValue((int)maxDigits, range.Max);
//Console.WriteLine($"{min}-{max}");
if (max < min)
return [];
var n = (max - min) + 1;
var result = new long[n];
for (long i = min; i <= max; i++)
{
result[i - min] = (i * QuickMath.FastPow10(minDigits)) + i;
}
return result;
}
public static long SnapToUpNearestValidRange(long value)
{
var dc = value.DigitCount();
if (dc.IsEven())
return value;
return QuickMath.FastPow10(dc);
}
public static long SnapToDownNearestValidRange(long value)
{
var dc = value.DigitCount();
if (dc.IsEven())
return value;
return QuickMath.FastPow10(dc - 1) - 1;
}
public static long GetMinValue(int digits, long value)
{
var val = long.Parse(value.ToString()[..^digits]);
while ((val * QuickMath.FastPow10(digits)) + val < value)
{
val++;
}
return val;
}
public static long GetMaxValue(int digits, long value)
{
var val = long.Parse(value.ToString()[..^digits]);
while ((val * QuickMath.FastPow10(digits)) + val > value)
{
val--;
}
return val;
}
public override void CalculatePart2()
{
throw new NotImplementedException();
}
public override void LoadInput()
{
var text = ReadInputText("input.txt");
_ranges = text.Split(',')
.AsValueEnumerable()
.Select(r => r.Split('-').Select(long.Parse))
.Select(r => new IdRange(r.First(), r.Last()))
.ToArray();
}
public record IdRange(long Min, long Max)
{
public IdRange Snap()
{
return new IdRange(SnapToUpNearestValidRange(Min), SnapToDownNearestValidRange(Max));
}
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Text;
using ZLinq;
namespace AdventOfCode.Problems.AOC2025.Day3;
[ProblemInfo(2025, 3, "Lobby")]
internal class Lobby : Problem<long, long>
{
private (int val, int idx)[][] _batteryBanks = [];
public override void CalculatePart1()
{
Part1 = _batteryBanks.AsValueEnumerable().Select(bank =>
{
var batteries = GetViableBatteries(bank);
return GetPower(batteries);
}).Sum();
}
public override void CalculatePart2()
{
Console.WriteLine();
var b = _batteryBanks.AsValueEnumerable().Select(bank =>
{
var batteries = GetViableBatteries(bank, 12);
return GetPower(batteries);
});
Part2 = b.Sum();
}
public static long GetPower(int[] values)
{
return values.Select((v, idx) =>
{
var mag = (long)Math.Pow(10, values.Length - idx - 1);
return v * mag;
}).Sum();
}
public static int[] GetViableBatteries((int val, int idx)[] source, int count = 2)
{
var batteries = new int[count];
var offset = 0;
for (int i = count; i > 0; i--)
{
var tgt = i - 1;
var (val, idx) = source[offset..^tgt].MaxBy(v => v.val);
offset = idx + 1;
batteries[count - i] = val;
}
return batteries;
}
public override void LoadInput()
{
_batteryBanks = ReadInputLines("input.txt")
.AsValueEnumerable()
.Select(l => l.AsValueEnumerable().Select((v, idx) => (v - '0', idx)).ToArray())
.ToArray();
}
}

View File

@@ -0,0 +1,62 @@
using AdventOfCode.Utils.Models;
using System;
using System.Collections.Generic;
using System.Text;
namespace AdventOfCode.Problems.AOC2025.Day4;
[ProblemInfo(2025, 4, "Printing Department")]
internal class PrintingDeparment: Problem<int, int>
{
private string[] _data = [];
private Vec2<int> _size;
public override void CalculatePart1()
{
var c = 0;
for (int y = 0; y < _size.Y; y++)
{
for (int x = 0; x < _size.X; x++)
{
var pos = new Vec2<int>(x, y);
if (_data[pos.Y][pos.X] != '@')
continue;
var n = CountNeighbors(pos);
if (n < 4)
c++;
}
}
Part1 = c;
}
public int CountNeighbors(Vec2<int> pos)
{
var c = 0;
for (int y = pos.Y-1; y <= pos.Y + 1; y++)
{
if (y < 0 || y >= _size.Y)
continue;
for (int x = pos.X - 1; x <= pos.X + 1; x++)
{
if (x < 0 || x >= _size.X)
continue;
if (pos.X == x && pos.Y == y)
continue;
if (_data[y][x] == '@')
c++;
}
}
return c;
}
public override void CalculatePart2()
{
throw new NotImplementedException();
}
public override void LoadInput()
{
_data = ReadInputLines("input.txt");
_size = new Vec2<int>(_data[0].Length, _data.Length);
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Text;
using ZLinq;
namespace AdventOfCode.Problems.AOC2025.Day5;
[ProblemInfo(2025, 5, "Cafeteria")]
internal class Cafeteria : Problem<long, long>
{
private (long start, long end)[] _ranges = [];
private long[] _values = [];
public override void CalculatePart1()
{
Part1 = _values.AsValueEnumerable().Count(v => _ranges.AsValueEnumerable().Any(r => IsInRange(r, v)));
}
public static bool IsInRange((long start, long end) range, long value)
{
return (range.start <= value && range.end >= value);
}
public override void CalculatePart2()
{
var merged = MergeRanges(_ranges);
merged.Print();
Console.WriteLine("----");
MergeRanges(merged.ToArray()).Print();
//merged.Print();
Part2 = merged.Select(r => r.end - r.start + 1).Sum();
}
public static List<(long start, long end)> MergeRanges((long start, long end)[] ranges)
{
var result = new List<(long start, long end)>(ranges.Length);
var used = new HashSet<int>();
for (int i = 0; i < ranges.Length; i++)
{
if (used.Contains(i))
continue;
var range = ranges[i];
for (int j = (i + 1); j < ranges.Length; j++)
{
if (used.Contains(j))
continue;
var range2 = ranges[j];
if(IsOverlapping(range, range2))
{
range = Merge(range, range2);
used.Add(j);
j = i;
}
}
result.Add(range);
}
return result;
}
public static bool IsOverlapping((long start, long end) a, (long start, long end) b)
{
return IsInRange(a, b.start) || IsInRange(a, b.end) || IsInRange(b, a.start) || IsInRange(b, a.end);
}
public static (long start, long end) Merge((long start, long end) a, (long start, long end) b)
{
return (a.start.Min(b.start), a.end.Max(b.end));
}
public override void LoadInput()
{
var lines = ReadInputLines("input.txt");
_ranges = lines
.TakeWhile(l => !string.IsNullOrWhiteSpace(l))
.Select(l => l.Split('-').Select(long.Parse))
.Select(v => (start: v.First(), end: v.Last()))
.ToArray();
_values = lines[(_ranges.Length + 1)..]
.Select(long.Parse)
.ToArray();
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace AdventOfCode.Problems.AOC2025.Day6;
[ProblemInfo(2025, 6, "Trash Compactor")]
public partial class TrashCompactor : Problem<long, long>
{
private long[][] _values = [];
private string[] _operators = [];
private IEnumerable<(char op, long[] values)> _part2Data = [];
public override void CalculatePart1()
{
for (int i = 0; i < _operators.Length; i++)
{
var op = _operators[i];
var col = _values.Select(r => r[i]).ToArray();
Part1 += op switch
{
"+" => col.Aggregate((a, b) => a + b),
"*" => col.Aggregate((a, b) => a * b),
_ => throw new InvalidOperationException()
};
}
}
public override void CalculatePart2()
{
foreach (var (op, values) in _part2Data)
{
Part2 += op switch
{
'+' => values.Aggregate((a, b) => a + b),
'*' => values.Aggregate((a, b) => a * b),
_ => throw new InvalidOperationException()
};
}
}
public override void LoadInput()
{
var lines = ReadInputLines("input.txt");
ParsePart1(lines);
ParsePart2(lines);
}
private void ParsePart1(string[] lines)
{
_values = lines[..^1].Select(l => LineMatch().Matches(l).Select(v => long.Parse(v.Value)).ToArray()).ToArray();
_operators = LineMatch().Matches(lines[^1]).Select(v => v.Value).ToArray();
}
private void ParsePart2(string[] lines)
{
var valueLines = lines[..^1];
var opLines = lines[^1];
var opPos = 0;
var len = 1;
var data = new List<(char op, string[] values)>();
for (int i = 1; i < opLines.Length; i++)
{
var curChar = opLines[i];
if (curChar != ' ' || i == opLines.Length - 1)
{
if (i == opLines.Length - 1)
len = opLines.Length - opPos + 1;
var op = opLines[opPos];
var values = valueLines.Select(v => v[opPos..(opPos + len - 1)]).ToArray();
data.Add((op, values));
len = 1;
opPos = i;
}
else
len++;
}
_part2Data = data.Select(v => (v.op, v.values.Transpose().Select(long.Parse).ToArray()));
}
[GeneratedRegex(@"(\S+)")]
private static partial Regex LineMatch();
}

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>
@@ -19,8 +20,38 @@ public static class ExtraMath
return a;
}
public static T LCM<T>(this T a, T b) where T: INumber<T>
public static T LCM<T>(this T a, T b) where T : INumber<T>
{
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);
}
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;
}
public static bool IsEven<T>(this T value) where T : INumber<T>
{
return T.IsEvenInteger(value);
}
public static bool IsOdd<T>(this T value) where T : INumber<T>
{
return T.IsOddInteger(value);
}
}

View File

@@ -1,16 +1,17 @@
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);
}
}

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);
@@ -17,10 +24,18 @@ public record struct Vec2<T>(T X, T Y) where T : INumber<T>
var b = other.Y - this.Y;
return (a * a) + (b * b);
}
public override string ToString()
{
return $"({X}, {Y})";
}
}
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);
@@ -35,4 +50,9 @@ public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
var c = other.Z - this.Z;
return (a * a) + (b * b) + (c * c);
}
public override string ToString()
{
return $"({X}, {Y}, {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;
}
}