Compare commits
10 Commits
625a9e5ad5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c8cf1ebfd | |||
| 7056c1516e | |||
| 07510227e9 | |||
| 5f45853889 | |||
| 55a8ea0281 | |||
| e56befa18b | |||
| 9f1a2d2300 | |||
| a0c97e4b75 | |||
| 629b13abef | |||
| 4f4ccf7117 |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace AdventOfCode.Problems.AOC2025.Day1;
|
|||||||
[ProblemInfo(2025, 1, "Secret Entrance")]
|
[ProblemInfo(2025, 1, "Secret Entrance")]
|
||||||
internal class SecretEntrance : Problem<int, int>
|
internal class SecretEntrance : Problem<int, int>
|
||||||
{
|
{
|
||||||
|
public const int LOCK_SIZE = 100;
|
||||||
|
|
||||||
public int[] Input { get; set; } = [];
|
public int[] Input { get; set; } = [];
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
@@ -19,7 +21,7 @@ internal class SecretEntrance : Problem<int, int>
|
|||||||
foreach (var item in Input)
|
foreach (var item in Input)
|
||||||
{
|
{
|
||||||
v += item;
|
v += item;
|
||||||
v = v.Mod(100);
|
v = v.Mod(LOCK_SIZE);
|
||||||
if (v == 0)
|
if (v == 0)
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
@@ -32,14 +34,20 @@ internal class SecretEntrance : Problem<int, int>
|
|||||||
var v = 50;
|
var v = 50;
|
||||||
foreach (var item in Input)
|
foreach (var item in Input)
|
||||||
{
|
{
|
||||||
var sign = int.Sign(item);
|
var vStart = v;
|
||||||
for (int i = 0; i < Math.Abs(item); i++)
|
|
||||||
|
v += item;
|
||||||
|
if (item > 0)
|
||||||
|
c += (int)Math.Floor(v / (float)LOCK_SIZE);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
v += sign;
|
var d = v / (float)LOCK_SIZE;
|
||||||
v = v.Mod(100);
|
var fl = Math.Floor(d);
|
||||||
if (v == 0)
|
c += (int)Math.Abs(fl) - (vStart == 0 ? 1 : 0);
|
||||||
c++;
|
if (fl == d)
|
||||||
|
c += 1;
|
||||||
}
|
}
|
||||||
|
v = v.Mod(LOCK_SIZE);
|
||||||
}
|
}
|
||||||
Part2 = c;
|
Part2 = c;
|
||||||
}
|
}
|
||||||
|
|||||||
8
AdventOfCode/Problems/AOC2025/Day1/test.out
Normal file
8
AdventOfCode/Problems/AOC2025/Day1/test.out
Normal 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
|
||||||
100
AdventOfCode/Problems/AOC2025/Day2/GiftShop.cs
Normal file
100
AdventOfCode/Problems/AOC2025/Day2/GiftShop.cs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
AdventOfCode/Problems/AOC2025/Day3/Lobby.cs
Normal file
65
AdventOfCode/Problems/AOC2025/Day3/Lobby.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
62
AdventOfCode/Problems/AOC2025/Day4/PrintingDeparment.cs
Normal file
62
AdventOfCode/Problems/AOC2025/Day4/PrintingDeparment.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
85
AdventOfCode/Problems/AOC2025/Day5/Cafeteria.cs
Normal file
85
AdventOfCode/Problems/AOC2025/Day5/Cafeteria.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
88
AdventOfCode/Problems/AOC2025/Day6/TrashCompactor.cs
Normal file
88
AdventOfCode/Problems/AOC2025/Day6/TrashCompactor.cs
Normal 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();
|
||||||
|
}
|
||||||
111
AdventOfCode/Problems/AOC2025/Day7/Laboratories.cs
Normal file
111
AdventOfCode/Problems/AOC2025/Day7/Laboratories.cs
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
|
using MaybeError;
|
||||||
|
using MaybeError.Errors;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AdventOfCode.Problems.AOC2025.Day7;
|
||||||
|
[ProblemInfo(2025, 7, "Laboratories")]
|
||||||
|
internal class Laboratories : Problem<long, long>
|
||||||
|
{
|
||||||
|
private string[] _grid = [];
|
||||||
|
private Vec2<int> _size;
|
||||||
|
|
||||||
|
public override void CalculatePart1()
|
||||||
|
{
|
||||||
|
var start = GetStart(_grid).Value;
|
||||||
|
Part1 = TraceBeam(start, _grid, _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalculatePart2()
|
||||||
|
{
|
||||||
|
var start = GetStart(_grid).Value;
|
||||||
|
Part2 = QuantumTraceBeam(start, _grid, _size, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Maybe<Vec2<int>> GetStart(string[] data)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < data.Length; y++)
|
||||||
|
{
|
||||||
|
var ln = data[y];
|
||||||
|
for (int x = 0; x < ln.Length; x++)
|
||||||
|
{
|
||||||
|
if (ln[x] == 'S')
|
||||||
|
return new Vec2<int>(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Error("There is no start position");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long TraceBeam(Vec2<int> pos, string[] data, Vec2<int> size)
|
||||||
|
{
|
||||||
|
return TraceBeam(pos, data, size, []);
|
||||||
|
}
|
||||||
|
private static long TraceBeam(Vec2<int> pos, string[] data, Vec2<int> size, HashSet<Vec2<int>> visited)
|
||||||
|
{
|
||||||
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
|
return 0;
|
||||||
|
if (pos.X >= size.X || pos.Y >= size.Y)
|
||||||
|
return 0;
|
||||||
|
var curPos = data[pos.Y][pos.X];
|
||||||
|
|
||||||
|
if (curPos == '^')
|
||||||
|
{
|
||||||
|
var left = new Vec2<int>(pos.X - 1, pos.Y);
|
||||||
|
var right = new Vec2<int>(pos.X + 1, pos.Y);
|
||||||
|
var leftCount = visited.Add(left) ? TraceBeam(left, data, size, visited) : 0;
|
||||||
|
var rightCount = visited.Add(right) ? TraceBeam(right, data, size, visited) : 0;
|
||||||
|
return 1 + leftCount + rightCount;
|
||||||
|
}
|
||||||
|
var next = new Vec2<int>(pos.X, pos.Y + 1);
|
||||||
|
if (visited.Contains(next))
|
||||||
|
return 0;
|
||||||
|
visited.Add(next);
|
||||||
|
return TraceBeam(next, data, size, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long QuantumTraceBeam(Vec2<int> pos, string[] data, Vec2<int> size, Dictionary<Vec2<int>, long> trace)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
|
return 1;
|
||||||
|
if (pos.X >= size.X || pos.Y >= size.Y)
|
||||||
|
return 1;
|
||||||
|
if (trace.TryGetValue(pos, out var c))
|
||||||
|
return c;
|
||||||
|
var curPos = data[pos.Y][pos.X];
|
||||||
|
|
||||||
|
if (curPos == '^')
|
||||||
|
{
|
||||||
|
var left = new Vec2<int>(pos.X - 1, pos.Y);
|
||||||
|
var right = new Vec2<int>(pos.X + 1, pos.Y);
|
||||||
|
|
||||||
|
if (!trace.TryGetValue(left, out long leftCount))
|
||||||
|
{
|
||||||
|
leftCount = QuantumTraceBeam(left, data, size, trace);
|
||||||
|
trace.Add(left, leftCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trace.TryGetValue(right, out long rightCount))
|
||||||
|
{
|
||||||
|
rightCount = QuantumTraceBeam(right, data, size, trace);
|
||||||
|
trace.Add(right, rightCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftCount + rightCount;
|
||||||
|
}
|
||||||
|
return QuantumTraceBeam(new(pos.X, pos.Y + 1), data, size, trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public override void LoadInput()
|
||||||
|
{
|
||||||
|
_grid = ReadInputLines("input.txt");
|
||||||
|
_size = new Vec2<int>(_grid[0].Length, _grid.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
48
AdventOfCode/Problems/AOC2025/Day9/MovieTheater.cs
Normal file
48
AdventOfCode/Problems/AOC2025/Day9/MovieTheater.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AdventOfCode.Problems.AOC2025.Day9;
|
||||||
|
|
||||||
|
[ProblemInfo(2025, 9, "Movie Theater")]
|
||||||
|
internal class MovieTheater : Problem<long, long>
|
||||||
|
{
|
||||||
|
private Vec2<long>[] _input = [];
|
||||||
|
|
||||||
|
public override void CalculatePart1()
|
||||||
|
{
|
||||||
|
for (long i = 0; i < _input.Length; i++)
|
||||||
|
{
|
||||||
|
var a = _input[i];
|
||||||
|
for (long j = (i + 1); j < _input.Length; j++)
|
||||||
|
{
|
||||||
|
var b = _input[j];
|
||||||
|
var area = CalculateArea(a, b);
|
||||||
|
if (area > Part1)
|
||||||
|
{
|
||||||
|
Part1 = area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long CalculateArea(Vec2<long> a, Vec2<long> b)
|
||||||
|
{
|
||||||
|
var rect = (a - b).Abs() + 1;
|
||||||
|
var area = Math.Abs(rect.X * rect.Y);
|
||||||
|
//Console.WriteLine($"{a} -> {b} : {rect} = {area}");
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalculatePart2()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadInput()
|
||||||
|
{
|
||||||
|
_input = ReadInputLines("input.txt").Select(l => l.Split(',').Select(long.Parse)).Select(v => new Vec2<long>(v.First(), v.Last())).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,4 +4,4 @@ global using AdventOfCode.Utils;
|
|||||||
|
|
||||||
|
|
||||||
var runner = new AOCRunner();
|
var runner = new AOCRunner();
|
||||||
runner.RenderInteractiveMenu();
|
runner.WithDay(7).RenderInteractiveMenu();
|
||||||
|
|||||||
@@ -34,4 +34,24 @@ public static class ExtraMath
|
|||||||
{
|
{
|
||||||
return T.Min(a, b);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,13 +13,5 @@ public static class Extensions
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,29 @@ public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
|||||||
public static Vec2<T> operator *(T left, Vec2<T> right) => new Vec2<T>(right.X * left, right.Y * left);
|
public static Vec2<T> operator *(T left, Vec2<T> right) => new Vec2<T>(right.X * left, right.Y * left);
|
||||||
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
||||||
|
|
||||||
public T DistanceSq(Vec2<T> other)
|
public static implicit operator Vec2<T>(T value)
|
||||||
|
{
|
||||||
|
return new(value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly T DistanceSq(Vec2<T> other)
|
||||||
{
|
{
|
||||||
var a = other.X - this.X;
|
var a = other.X - this.X;
|
||||||
var b = other.Y - this.Y;
|
var b = other.Y - this.Y;
|
||||||
return (a * a) + (b * b);
|
return (a * a) + (b * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly Vec2<T> Min(Vec2<T> other) => new(T.Min(X, other.X), T.Min(Y, other.Y));
|
||||||
|
|
||||||
|
public readonly Vec2<T> Max(Vec2<T> other) => new(T.Max(X, other.X), T.Max(Y, other.Y));
|
||||||
|
|
||||||
|
public readonly Vec2<T> Abs() => new(T.Abs(X), T.Abs(Y));
|
||||||
|
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return $"({X}, {Y})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
||||||
@@ -38,11 +55,26 @@ public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
|||||||
public static Vec3<T> operator *(T left, Vec3<T> right) => new Vec3<T>(right.X * left, right.Y * left, right.Z * left);
|
public static Vec3<T> operator *(T left, Vec3<T> right) => new Vec3<T>(right.X * left, right.Y * left, right.Z * left);
|
||||||
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
||||||
|
|
||||||
public T DistanceSq(Vec3<T> other)
|
public static implicit operator Vec3<T>(T value)
|
||||||
|
{
|
||||||
|
return new(value, value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly T DistanceSq(Vec3<T> other)
|
||||||
{
|
{
|
||||||
var a = other.X - this.X;
|
var a = other.X - this.X;
|
||||||
var b = other.Y - this.Y;
|
var b = other.Y - this.Y;
|
||||||
var c = other.Z - this.Z;
|
var c = other.Z - this.Z;
|
||||||
return (a * a) + (b * b) + (c * c);
|
return (a * a) + (b * b) + (c * c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly Vec3<T> Min(Vec3<T> other) => new(T.Min(X, other.X), T.Min(Y, other.Y), T.Min(Z, other.Z));
|
||||||
|
|
||||||
|
public readonly Vec3<T> Max(Vec3<T> other) => new(T.Max(X, other.X), T.Max(Y, other.Y), T.Max(Z, other.Z));
|
||||||
|
public readonly Vec3<T> Abs() => new(T.Abs(X), T.Abs(Y), T.Abs(Z));
|
||||||
|
|
||||||
|
public override readonly string ToString()
|
||||||
|
{
|
||||||
|
return $"({X}, {Y}, {Z})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user