Compare commits
12 Commits
a92c9b4478
...
625a9e5ad5
| Author | SHA1 | Date | |
|---|---|---|---|
| 625a9e5ad5 | |||
| ef959284a5 | |||
| bba775fd4e | |||
| f16899ff3c | |||
| 6606f40df9 | |||
| 199b940ff9 | |||
| 63eb4d01b0 | |||
| a33843ae1b | |||
| e08a60614a | |||
| 6a9c813d08 | |||
| ba7e6d4be0 | |||
| a4cb169566 |
@@ -76,6 +76,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<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>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,25 +1,102 @@
|
|||||||
using System;
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day10;
|
namespace AdventOfCode.Problems.AOC2024.Day10;
|
||||||
//[ProblemInfo(2024, 10, "Hoof It")]
|
[ProblemInfo(2024, 10, "Hoof It")]
|
||||||
internal class HoofIt : Problem
|
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()
|
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()
|
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()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,115 @@
|
|||||||
using System;
|
using Superpower.Model;
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day11;
|
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()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
Part1 = _data.Sum(v => ProcessStoneRecursive(v, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
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()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_data = ReadInputText("input.txt").Split(' ').Select(long.Parse).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
301
AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs
Normal file
301
AdventOfCode/Problems/AOC2024/Day12/GardenGroups.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,16 @@ internal class DiskFragmenter : Problem<long, long>
|
|||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var blocks = ExpandBlocks(_data);
|
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);
|
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);
|
//Print(blocks);
|
||||||
// Too High: 8838426222802
|
// Too High: 8838426222802
|
||||||
Part2 = ComputeHashV2(blocks);
|
Part2 = ComputeHashV2(blocks);
|
||||||
@@ -174,10 +183,16 @@ internal class DiskFragmenter : Problem<long, long>
|
|||||||
}
|
}
|
||||||
//Extend Right Block
|
//Extend Right Block
|
||||||
else if (idx + 1 < blocks.Count && blocks[idx + 1].isEmpty)
|
else if (idx + 1 < blocks.Count && blocks[idx + 1].isEmpty)
|
||||||
|
{
|
||||||
blocks[idx + 1].length += block.length;
|
blocks[idx + 1].length += block.length;
|
||||||
|
blocks.RemoveAt(idx);
|
||||||
|
}
|
||||||
//Extend Left Block
|
//Extend Left Block
|
||||||
else if (idx - 1 > 0 && blocks[idx - 1].isEmpty)
|
else if (idx - 1 > 0 && blocks[idx - 1].isEmpty)
|
||||||
|
{
|
||||||
blocks[idx - 1].length += block.length;
|
blocks[idx - 1].length += block.length;
|
||||||
|
blocks.RemoveAt(idx);
|
||||||
|
}
|
||||||
//Insert new Empty Block
|
//Insert new Empty Block
|
||||||
else
|
else
|
||||||
blocks[idx] = new Block(block.length);
|
blocks[idx] = new Block(block.length);
|
||||||
|
|||||||
61
AdventOfCode/Problems/AOC2025/Day1/SecretEntrance.cs
Normal file
61
AdventOfCode/Problems/AOC2025/Day1/SecretEntrance.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
|
|
||||||
public static class ExtraMath
|
public static class ExtraMath
|
||||||
{
|
{
|
||||||
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
||||||
@@ -19,8 +20,18 @@ public static class ExtraMath
|
|||||||
return a;
|
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;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Utils;
|
namespace AdventOfCode.Utils;
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
|
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
|
||||||
{
|
{
|
||||||
return string.Join(delim, data);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ namespace AdventOfCode.Utils.Models;
|
|||||||
|
|
||||||
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
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> 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);
|
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 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> 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);
|
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
||||||
|
|||||||
37
AdventOfCode/Utils/QuickMath.cs
Normal file
37
AdventOfCode/Utils/QuickMath.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user