Aoc 2025 day 1

This commit is contained in:
2025-12-01 21:19:43 -05:00
parent ef959284a5
commit 625a9e5ad5
78 changed files with 7224 additions and 7152 deletions

126
.gitattributes vendored
View File

@@ -1,63 +1,63 @@
############################################################################### ###############################################################################
# Set default behavior to automatically normalize line endings. # Set default behavior to automatically normalize line endings.
############################################################################### ###############################################################################
* text=auto * text=auto
############################################################################### ###############################################################################
# Set default behavior for command prompt diff. # Set default behavior for command prompt diff.
# #
# This is need for earlier builds of msysgit that does not have it on by # This is need for earlier builds of msysgit that does not have it on by
# default for csharp files. # default for csharp files.
# Note: This is only used by command line # Note: This is only used by command line
############################################################################### ###############################################################################
#*.cs diff=csharp #*.cs diff=csharp
############################################################################### ###############################################################################
# Set the merge driver for project and solution files # Set the merge driver for project and solution files
# #
# Merging from the command prompt will add diff markers to the files if there # Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS # are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following # the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat # file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user # these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below # intervention with every merge. To do so, just uncomment the entries below
############################################################################### ###############################################################################
#*.sln merge=binary #*.sln merge=binary
#*.csproj merge=binary #*.csproj merge=binary
#*.vbproj merge=binary #*.vbproj merge=binary
#*.vcxproj merge=binary #*.vcxproj merge=binary
#*.vcproj merge=binary #*.vcproj merge=binary
#*.dbproj merge=binary #*.dbproj merge=binary
#*.fsproj merge=binary #*.fsproj merge=binary
#*.lsproj merge=binary #*.lsproj merge=binary
#*.wixproj merge=binary #*.wixproj merge=binary
#*.modelproj merge=binary #*.modelproj merge=binary
#*.sqlproj merge=binary #*.sqlproj merge=binary
#*.wwaproj merge=binary #*.wwaproj merge=binary
############################################################################### ###############################################################################
# behavior for image files # behavior for image files
# #
# image files are treated as binary by default. # image files are treated as binary by default.
############################################################################### ###############################################################################
#*.jpg binary #*.jpg binary
#*.png binary #*.png binary
#*.gif binary #*.gif binary
############################################################################### ###############################################################################
# diff behavior for common document formats # diff behavior for common document formats
# #
# Convert binary document formats to text before diffing them. This feature # Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the # is only available from the command line. Turn it on by uncommenting the
# entries below. # entries below.
############################################################################### ###############################################################################
#*.doc diff=astextplain #*.doc diff=astextplain
#*.DOC diff=astextplain #*.DOC diff=astextplain
#*.docx diff=astextplain #*.docx diff=astextplain
#*.DOCX diff=astextplain #*.DOCX diff=astextplain
#*.dot diff=astextplain #*.dot diff=astextplain
#*.DOT diff=astextplain #*.DOT diff=astextplain
#*.pdf diff=astextplain #*.pdf diff=astextplain
#*.PDF diff=astextplain #*.PDF diff=astextplain
#*.rtf diff=astextplain #*.rtf diff=astextplain
#*.RTF diff=astextplain #*.RTF diff=astextplain

726
.gitignore vendored
View File

@@ -1,363 +1,363 @@
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files # User-specific files
*.rsuser *.rsuser
*.suo *.suo
*.user *.user
*.userosscache *.userosscache
*.sln.docstates *.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
# Mono auto generated files # Mono auto generated files
mono_crash.* mono_crash.*
# Build results # Build results
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
[Rr]elease/ [Rr]elease/
[Rr]eleases/ [Rr]eleases/
x64/ x64/
x86/ x86/
[Ww][Ii][Nn]32/ [Ww][Ii][Nn]32/
[Aa][Rr][Mm]/ [Aa][Rr][Mm]/
[Aa][Rr][Mm]64/ [Aa][Rr][Mm]64/
bld/ bld/
[Bb]in/ [Bb]in/
[Oo]bj/ [Oo]bj/
[Oo]ut/ [Oo]ut/
[Ll]og/ [Ll]og/
[Ll]ogs/ [Ll]ogs/
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/
# Uncomment if you have tasks that create the project's static files in wwwroot # Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/ #wwwroot/
# Visual Studio 2017 auto generated files # Visual Studio 2017 auto generated files
Generated\ Files/ Generated\ Files/
# MSTest test Results # MSTest test Results
[Tt]est[Rr]esult*/ [Tt]est[Rr]esult*/
[Bb]uild[Ll]og.* [Bb]uild[Ll]og.*
# NUnit # NUnit
*.VisualState.xml *.VisualState.xml
TestResult.xml TestResult.xml
nunit-*.xml nunit-*.xml
# Build Results of an ATL Project # Build Results of an ATL Project
[Dd]ebugPS/ [Dd]ebugPS/
[Rr]eleasePS/ [Rr]eleasePS/
dlldata.c dlldata.c
# Benchmark Results # Benchmark Results
BenchmarkDotNet.Artifacts/ BenchmarkDotNet.Artifacts/
# .NET Core # .NET Core
project.lock.json project.lock.json
project.fragment.lock.json project.fragment.lock.json
artifacts/ artifacts/
# ASP.NET Scaffolding # ASP.NET Scaffolding
ScaffoldingReadMe.txt ScaffoldingReadMe.txt
# StyleCop # StyleCop
StyleCopReport.xml StyleCopReport.xml
# Files built by Visual Studio # Files built by Visual Studio
*_i.c *_i.c
*_p.c *_p.c
*_h.h *_h.h
*.ilk *.ilk
*.meta *.meta
*.obj *.obj
*.iobj *.iobj
*.pch *.pch
*.pdb *.pdb
*.ipdb *.ipdb
*.pgc *.pgc
*.pgd *.pgd
*.rsp *.rsp
*.sbr *.sbr
*.tlb *.tlb
*.tli *.tli
*.tlh *.tlh
*.tmp *.tmp
*.tmp_proj *.tmp_proj
*_wpftmp.csproj *_wpftmp.csproj
*.log *.log
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
*.pidb *.pidb
*.svclog *.svclog
*.scc *.scc
# Chutzpah Test files # Chutzpah Test files
_Chutzpah* _Chutzpah*
# Visual C++ cache files # Visual C++ cache files
ipch/ ipch/
*.aps *.aps
*.ncb *.ncb
*.opendb *.opendb
*.opensdf *.opensdf
*.sdf *.sdf
*.cachefile *.cachefile
*.VC.db *.VC.db
*.VC.VC.opendb *.VC.VC.opendb
# Visual Studio profiler # Visual Studio profiler
*.psess *.psess
*.vsp *.vsp
*.vspx *.vspx
*.sap *.sap
# Visual Studio Trace Files # Visual Studio Trace Files
*.e2e *.e2e
# TFS 2012 Local Workspace # TFS 2012 Local Workspace
$tf/ $tf/
# Guidance Automation Toolkit # Guidance Automation Toolkit
*.gpState *.gpState
# ReSharper is a .NET coding add-in # ReSharper is a .NET coding add-in
_ReSharper*/ _ReSharper*/
*.[Rr]e[Ss]harper *.[Rr]e[Ss]harper
*.DotSettings.user *.DotSettings.user
# TeamCity is a build add-in # TeamCity is a build add-in
_TeamCity* _TeamCity*
# DotCover is a Code Coverage Tool # DotCover is a Code Coverage Tool
*.dotCover *.dotCover
# AxoCover is a Code Coverage Tool # AxoCover is a Code Coverage Tool
.axoCover/* .axoCover/*
!.axoCover/settings.json !.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool # Coverlet is a free, cross platform Code Coverage Tool
coverage*.json coverage*.json
coverage*.xml coverage*.xml
coverage*.info coverage*.info
# Visual Studio code coverage results # Visual Studio code coverage results
*.coverage *.coverage
*.coveragexml *.coveragexml
# NCrunch # NCrunch
_NCrunch_* _NCrunch_*
.*crunch*.local.xml .*crunch*.local.xml
nCrunchTemp_* nCrunchTemp_*
# MightyMoose # MightyMoose
*.mm.* *.mm.*
AutoTest.Net/ AutoTest.Net/
# Web workbench (sass) # Web workbench (sass)
.sass-cache/ .sass-cache/
# Installshield output folder # Installshield output folder
[Ee]xpress/ [Ee]xpress/
# DocProject is a documentation generator add-in # DocProject is a documentation generator add-in
DocProject/buildhelp/ DocProject/buildhelp/
DocProject/Help/*.HxT DocProject/Help/*.HxT
DocProject/Help/*.HxC DocProject/Help/*.HxC
DocProject/Help/*.hhc DocProject/Help/*.hhc
DocProject/Help/*.hhk DocProject/Help/*.hhk
DocProject/Help/*.hhp DocProject/Help/*.hhp
DocProject/Help/Html2 DocProject/Help/Html2
DocProject/Help/html DocProject/Help/html
# Click-Once directory # Click-Once directory
publish/ publish/
# Publish Web Output # Publish Web Output
*.[Pp]ublish.xml *.[Pp]ublish.xml
*.azurePubxml *.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings, # Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted # but database connection strings (with potential passwords) will be unencrypted
*.pubxml *.pubxml
*.publishproj *.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to # Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained # checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted # in these scripts will be unencrypted
PublishScripts/ PublishScripts/
# NuGet Packages # NuGet Packages
*.nupkg *.nupkg
# NuGet Symbol Packages # NuGet Symbol Packages
*.snupkg *.snupkg
# The packages folder can be ignored because of Package Restore # The packages folder can be ignored because of Package Restore
**/[Pp]ackages/* **/[Pp]ackages/*
# except build/, which is used as an MSBuild target. # except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/ !**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed # Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config #!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files # NuGet v3's project.json files produces more ignorable files
*.nuget.props *.nuget.props
*.nuget.targets *.nuget.targets
# Microsoft Azure Build Output # Microsoft Azure Build Output
csx/ csx/
*.build.csdef *.build.csdef
# Microsoft Azure Emulator # Microsoft Azure Emulator
ecf/ ecf/
rcf/ rcf/
# Windows Store app package directories and files # Windows Store app package directories and files
AppPackages/ AppPackages/
BundleArtifacts/ BundleArtifacts/
Package.StoreAssociation.xml Package.StoreAssociation.xml
_pkginfo.txt _pkginfo.txt
*.appx *.appx
*.appxbundle *.appxbundle
*.appxupload *.appxupload
# Visual Studio cache files # Visual Studio cache files
# files ending in .cache can be ignored # files ending in .cache can be ignored
*.[Cc]ache *.[Cc]ache
# but keep track of directories ending in .cache # but keep track of directories ending in .cache
!?*.[Cc]ache/ !?*.[Cc]ache/
# Others # Others
ClientBin/ ClientBin/
~$* ~$*
*~ *~
*.dbmdl *.dbmdl
*.dbproj.schemaview *.dbproj.schemaview
*.jfm *.jfm
*.pfx *.pfx
*.publishsettings *.publishsettings
orleans.codegen.cs orleans.codegen.cs
# Including strong name files can present a security risk # Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424) # (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk #*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components # Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/ #bower_components/
# RIA/Silverlight projects # RIA/Silverlight projects
Generated_Code/ Generated_Code/
# Backup & report files from converting an old project file # Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed, # to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-) # because we have git ;-)
_UpgradeReport_Files/ _UpgradeReport_Files/
Backup*/ Backup*/
UpgradeLog*.XML UpgradeLog*.XML
UpgradeLog*.htm UpgradeLog*.htm
ServiceFabricBackup/ ServiceFabricBackup/
*.rptproj.bak *.rptproj.bak
# SQL Server files # SQL Server files
*.mdf *.mdf
*.ldf *.ldf
*.ndf *.ndf
# Business Intelligence projects # Business Intelligence projects
*.rdl.data *.rdl.data
*.bim.layout *.bim.layout
*.bim_*.settings *.bim_*.settings
*.rptproj.rsuser *.rptproj.rsuser
*- [Bb]ackup.rdl *- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl *- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl *- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes # Microsoft Fakes
FakesAssemblies/ FakesAssemblies/
# GhostDoc plugin setting file # GhostDoc plugin setting file
*.GhostDoc.xml *.GhostDoc.xml
# Node.js Tools for Visual Studio # Node.js Tools for Visual Studio
.ntvs_analysis.dat .ntvs_analysis.dat
node_modules/ node_modules/
# Visual Studio 6 build log # Visual Studio 6 build log
*.plg *.plg
# Visual Studio 6 workspace options file # Visual Studio 6 workspace options file
*.opt *.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw *.vbw
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml **/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts **/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml **/*.Server/ModelManifest.xml
_Pvt_Extensions _Pvt_Extensions
# Paket dependency manager # Paket dependency manager
.paket/paket.exe .paket/paket.exe
paket-files/ paket-files/
# FAKE - F# Make # FAKE - F# Make
.fake/ .fake/
# CodeRush personal settings # CodeRush personal settings
.cr/personal .cr/personal
# Python Tools for Visual Studio (PTVS) # Python Tools for Visual Studio (PTVS)
__pycache__/ __pycache__/
*.pyc *.pyc
# Cake - Uncomment if you are using it # Cake - Uncomment if you are using it
# tools/** # tools/**
# !tools/packages.config # !tools/packages.config
# Tabs Studio # Tabs Studio
*.tss *.tss
# Telerik's JustMock configuration file # Telerik's JustMock configuration file
*.jmconfig *.jmconfig
# BizTalk build output # BizTalk build output
*.btp.cs *.btp.cs
*.btm.cs *.btm.cs
*.odx.cs *.odx.cs
*.xsd.cs *.xsd.cs
# OpenCover UI analysis results # OpenCover UI analysis results
OpenCover/ OpenCover/
# Azure Stream Analytics local run output # Azure Stream Analytics local run output
ASALocalRun/ ASALocalRun/
# MSBuild Binary and Structured Log # MSBuild Binary and Structured Log
*.binlog *.binlog
# NVidia Nsight GPU debugger configuration file # NVidia Nsight GPU debugger configuration file
*.nvuser *.nvuser
# MFractors (Xamarin productivity tool) working folder # MFractors (Xamarin productivity tool) working folder
.mfractor/ .mfractor/
# Local History for Visual Studio # Local History for Visual Studio
.localhistory/ .localhistory/
# BeatPulse healthcheck temp database # BeatPulse healthcheck temp database
healthchecksdb healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017 # Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder # Ionide (cross platform F# VS Code tools) working folder
.ionide/ .ionide/
# Fody - auto-generated XML schema # Fody - auto-generated XML schema
FodyWeavers.xsd FodyWeavers.xsd

View File

@@ -1,25 +1,25 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.4.33110.190 VisualStudioVersion = 17.4.33110.190
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B} SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -1,81 +1,83 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Problems\*\*\*.txt"> <EmbeddedResource Include="Problems\*\*\*.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Problems\*\*\*.csv"> <EmbeddedResource Include="Problems\*\*\*.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Remove="Problems\AOC2022\Day10\input.txt" /> <None Remove="Problems\AOC2022\Day10\input.txt" />
<None Remove="Problems\AOC2022\Day10\sara.txt" /> <None Remove="Problems\AOC2022\Day10\sara.txt" />
<None Remove="Problems\AOC2022\Day10\simple.txt" /> <None Remove="Problems\AOC2022\Day10\simple.txt" />
<None Remove="Problems\AOC2022\Day10\test.txt" /> <None Remove="Problems\AOC2022\Day10\test.txt" />
<None Remove="Problems\AOC2022\Day11\input.txt" /> <None Remove="Problems\AOC2022\Day11\input.txt" />
<None Remove="Problems\AOC2022\Day11\test.txt" /> <None Remove="Problems\AOC2022\Day11\test.txt" />
<None Remove="Problems\AOC2022\Day3\input.txt" /> <None Remove="Problems\AOC2022\Day3\input.txt" />
<None Remove="Problems\AOC2022\Day3\test.txt" /> <None Remove="Problems\AOC2022\Day3\test.txt" />
<None Remove="Problems\AOC2022\Day4\input.txt" /> <None Remove="Problems\AOC2022\Day4\input.txt" />
<None Remove="Problems\AOC2022\Day4\test.txt" /> <None Remove="Problems\AOC2022\Day4\test.txt" />
<None Remove="Problems\AOC2022\Day5\input.txt" /> <None Remove="Problems\AOC2022\Day5\input.txt" />
<None Remove="Problems\AOC2022\Day5\test.txt" /> <None Remove="Problems\AOC2022\Day5\test.txt" />
<None Remove="Problems\AOC2022\Day6\input.txt" /> <None Remove="Problems\AOC2022\Day6\input.txt" />
<None Remove="Problems\AOC2022\Day6\test.txt" /> <None Remove="Problems\AOC2022\Day6\test.txt" />
<None Remove="Problems\AOC2022\Day8\input.txt" /> <None Remove="Problems\AOC2022\Day8\input.txt" />
<None Remove="Problems\AOC2022\Day8\test.txt" /> <None Remove="Problems\AOC2022\Day8\test.txt" />
<None Remove="Problems\AOC2022\Day9\input.txt" /> <None Remove="Problems\AOC2022\Day9\input.txt" />
<None Remove="Problems\AOC2022\Day9\test.txt" /> <None Remove="Problems\AOC2022\Day9\test.txt" />
<None Remove="Problems\AOC2022\Day9\test2.txt" /> <None Remove="Problems\AOC2022\Day9\test2.txt" />
<None Remove="problems\aoc2023\day10\input.txt" /> <None Remove="problems\aoc2023\day10\input.txt" />
<None Remove="problems\aoc2023\day10\sample.txt" /> <None Remove="problems\aoc2023\day10\sample.txt" />
<None Remove="problems\aoc2023\day11\input.txt" /> <None Remove="problems\aoc2023\day11\input.txt" />
<None Remove="problems\aoc2023\day11\sample.txt" /> <None Remove="problems\aoc2023\day11\sample.txt" />
<None Remove="problems\aoc2023\day12\input.txt" /> <None Remove="problems\aoc2023\day12\input.txt" />
<None Remove="problems\aoc2023\day12\sample.txt" /> <None Remove="problems\aoc2023\day12\sample.txt" />
<None Remove="problems\aoc2023\day1\input.txt" /> <None Remove="problems\aoc2023\day1\input.txt" />
<None Remove="problems\aoc2023\day2\input.txt" /> <None Remove="problems\aoc2023\day2\input.txt" />
<None Remove="problems\aoc2023\day3\input.txt" /> <None Remove="problems\aoc2023\day3\input.txt" />
<None Remove="problems\aoc2023\day3\sample.txt" /> <None Remove="problems\aoc2023\day3\sample.txt" />
<None Remove="problems\aoc2023\day3\sara.txt" /> <None Remove="problems\aoc2023\day3\sara.txt" />
<None Remove="problems\aoc2023\day4\input.txt" /> <None Remove="problems\aoc2023\day4\input.txt" />
<None Remove="problems\aoc2023\day4\sample.txt" /> <None Remove="problems\aoc2023\day4\sample.txt" />
<None Remove="problems\aoc2023\day5\input.txt" /> <None Remove="problems\aoc2023\day5\input.txt" />
<None Remove="problems\aoc2023\day5\sample.txt" /> <None Remove="problems\aoc2023\day5\sample.txt" />
<None Remove="problems\aoc2023\day6\input.txt" /> <None Remove="problems\aoc2023\day6\input.txt" />
<None Remove="problems\aoc2023\day6\sample.txt" /> <None Remove="problems\aoc2023\day6\sample.txt" />
<None Remove="problems\aoc2023\day7\input.txt" /> <None Remove="problems\aoc2023\day7\input.txt" />
<None Remove="problems\aoc2023\day7\sample.txt" /> <None Remove="problems\aoc2023\day7\sample.txt" />
<None Remove="problems\aoc2023\day7\sara.txt" /> <None Remove="problems\aoc2023\day7\sara.txt" />
<None Remove="problems\aoc2023\day8\input.txt" /> <None Remove="problems\aoc2023\day8\input.txt" />
<None Remove="problems\aoc2023\day8\sample.txt" /> <None Remove="problems\aoc2023\day8\sample.txt" />
<None Remove="problems\aoc2023\day9\input.txt" /> <None Remove="problems\aoc2023\day9\input.txt" />
<None Remove="problems\aoc2023\day9\sample.txt" /> <None Remove="problems\aoc2023\day9\sample.txt" />
<None Remove="problems\aoc2023\day9\sara.txt" /> <None Remove="problems\aoc2023\day9\sara.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Problems\AOC2015\" /> <Folder Include="Problems\AOC2015\" />
<Folder Include="Problems\AOC2021\" /> <Folder Include="Problems\AOC2021\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Superpower" Version="3.0.0" /> <PackageReference Include="MaybeError" Version="1.2.0" />
</ItemGroup> <PackageReference Include="Superpower" Version="3.1.1-dev-00257" />
</Project> <PackageReference Include="ZLinq" Version="1.5.4" />
</ItemGroup>
</Project>

View File

@@ -1,2 +1,2 @@
*/*/*.txt */*/*.txt
*/*/*.csv */*/*.csv

View File

@@ -1,58 +1,58 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System.Text; using System.Text;
namespace AdventOfCode.Problems.AOC2015.Day10; namespace AdventOfCode.Problems.AOC2015.Day10;
[ProblemInfo(2015, 10, "Evles Look, Elves Say")] [ProblemInfo(2015, 10, "Evles Look, Elves Say")]
internal class LookAndSay : Problem<int, int> internal class LookAndSay : Problem<int, int>
{ {
private string _input = string.Empty; private string _input = string.Empty;
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = Run(40); Part1 = Run(40);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = Run(50); Part2 = Run(50);
} }
public override void LoadInput() public override void LoadInput()
{ {
_input = "3113322113"; _input = "3113322113";
} }
public int Run(int iter) public int Run(int iter)
{ {
var value = new StringBuilder(_input); var value = new StringBuilder(_input);
for (int i = 0; i < iter; i++) for (int i = 0; i < iter; i++)
CalculateNext(ref value); CalculateNext(ref value);
return value.Length; return value.Length;
} }
private static void CalculateNext(ref StringBuilder input) private static void CalculateNext(ref StringBuilder input)
{ {
var next = new StringBuilder(); var next = new StringBuilder();
var len = input.Length; var len = input.Length;
var curCount = 1; var curCount = 1;
var curChar = input[0]; var curChar = input[0];
for (int i = 1; i < len; i++) for (int i = 1; i < len; i++)
{ {
var c = input[i]; var c = input[i];
if (c != curChar) if (c != curChar)
{ {
next.Append(curCount).Append(curChar); next.Append(curCount).Append(curChar);
curChar = c; curChar = c;
curCount = 1; curCount = 1;
continue; continue;
} }
curCount++; curCount++;
} }
next.Append(curCount).Append(curChar); next.Append(curCount).Append(curChar);
input = next; input = next;
} }
} }

View File

@@ -1,110 +1,110 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2015.Day5; namespace AdventOfCode.Problems.AOC2015.Day5;
[ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")] [ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")]
public class NiceList : Problem<int, int> public class NiceList : Problem<int, int>
{ {
private string[] _inputData = Array.Empty<string>(); private string[] _inputData = Array.Empty<string>();
public override void LoadInput() public override void LoadInput()
{ {
_inputData = ReadInputLines(); _inputData = ReadInputLines();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
for (int i = 0; i < _inputData.Length; i++) for (int i = 0; i < _inputData.Length; i++)
{ {
if (IsNice(_inputData[i])) if (IsNice(_inputData[i]))
Part1++; Part1++;
} }
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
for (int i = 0; i < _inputData.Length; i++) for (int i = 0; i < _inputData.Length; i++)
{ {
if (IsNice2(_inputData[i])) if (IsNice2(_inputData[i]))
{ {
Part2++; Part2++;
} }
} }
} }
private static bool IsNice2(string value) private static bool IsNice2(string value)
{ {
var pairs = new Dictionary<string, List<int>>(); var pairs = new Dictionary<string, List<int>>();
var separatedPair = false; var separatedPair = false;
for (int i = 1; i < value.Length; i++) for (int i = 1; i < value.Length; i++)
{ {
var c = value[i]; var c = value[i];
var curIndex = i - 1; var curIndex = i - 1;
var pair = value[curIndex..(i + 1)]; var pair = value[curIndex..(i + 1)];
if (pairs.ContainsKey(pair)) if (pairs.ContainsKey(pair))
{ {
if (pairs[pair].Contains(curIndex - 1)) if (pairs[pair].Contains(curIndex - 1))
continue; continue;
pairs[pair].Add(curIndex); pairs[pair].Add(curIndex);
} }
else else
{ {
pairs.Add(pair, new List<int>() { curIndex }); pairs.Add(pair, new List<int>() { curIndex });
} }
if (i == 1) if (i == 1)
continue; continue;
if (value[i - 2] == c) if (value[i - 2] == c)
separatedPair = true; separatedPair = true;
} }
return separatedPair && pairs.Any(p => p.Value.Count >= 2); return separatedPair && pairs.Any(p => p.Value.Count >= 2);
} }
private static bool IsNice(string value) private static bool IsNice(string value)
{ {
var vowelCount = 0; var vowelCount = 0;
var doubleLetters = false; var doubleLetters = false;
for (int i = 0; i < value.Length; i++) for (int i = 0; i < value.Length; i++)
{ {
char c = value[i]; char c = value[i];
if (IsVowel(c)) if (IsVowel(c))
vowelCount++; vowelCount++;
if (i == 0) if (i == 0)
continue; continue;
var lastChar = value[i - 1]; var lastChar = value[i - 1];
if (IsIllegal(c, lastChar)) if (IsIllegal(c, lastChar))
return false; return false;
if (IsDouble(c, lastChar)) if (IsDouble(c, lastChar))
doubleLetters = true; doubleLetters = true;
} }
return doubleLetters && vowelCount >= 3; return doubleLetters && vowelCount >= 3;
} }
private static bool IsVowel(char c) private static bool IsVowel(char c)
{ {
return c switch return c switch
{ {
'a' or 'e' or 'i' or 'o' or 'u' => true, 'a' or 'e' or 'i' or 'o' or 'u' => true,
_ => false _ => false
}; };
} }
private static bool IsDouble(char c, char lastChar) private static bool IsDouble(char c, char lastChar)
{ {
return c == lastChar; return c == lastChar;
} }
private static bool IsIllegal(char c, char lastChar) private static bool IsIllegal(char c, char lastChar)
{ {
return (lastChar, c) switch return (lastChar, c) switch
{ {
('a', 'b') => true, ('a', 'b') => true,
('c', 'd') => true, ('c', 'd') => true,
('p', 'q') => true, ('p', 'q') => true,
('x', 'y') => true, ('x', 'y') => true,
_ => false _ => false
}; };
} }
} }

View File

@@ -1,41 +1,41 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day1 namespace AdventOfCode.Problems.AOC2019.Day1
{ {
[ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")] [ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")]
public class FuelCaluclation : Problem<int, int> public class FuelCaluclation : Problem<int, int>
{ {
private int[] _input = Array.Empty<int>(); private int[] _input = Array.Empty<int>();
public static int GetFuelRequirement(int[] input) public static int GetFuelRequirement(int[] input)
{ {
var curFuel = input.Sum(i => GetFuelCost(i)); var curFuel = input.Sum(i => GetFuelCost(i));
return curFuel; return curFuel;
} }
public static int GetFuelCost(int mass) public static int GetFuelCost(int mass)
{ {
var curCost = mass / 3 - 2; var curCost = mass / 3 - 2;
if (curCost <= 0) if (curCost <= 0)
return 0; return 0;
return curCost + GetFuelCost(curCost); return curCost + GetFuelCost(curCost);
} }
public static int GetCost(int mass) => mass / 3 - 2; public static int GetCost(int mass) => mass / 3 - 2;
public override void LoadInput() public override void LoadInput()
{ {
_input = InputParsing.ParseIntArray(GetInputFile()); _input = InputParsing.ParseIntArray(GetInputFile());
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = _input.Sum(i => GetCost(i)); Part1 = _input.Sum(i => GetCost(i));
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = GetFuelRequirement(_input); Part2 = GetFuelRequirement(_input);
} }
} }
} }

View File

@@ -1,72 +1,72 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day2 namespace AdventOfCode.Problems.AOC2019.Day2
{ {
[ProblemInfo(2019, 2, "Program Alarm")] [ProblemInfo(2019, 2, "Program Alarm")]
public class IntCode : Problem<int, int> public class IntCode : Problem<int, int>
{ {
private int[] _inputPart1 = Array.Empty<int>(); private int[] _inputPart1 = Array.Empty<int>();
private int[] _inputPart2 = Array.Empty<int>(); private int[] _inputPart2 = Array.Empty<int>();
public static int ExecuteCode(int[] code, int noun, int verb) public static int ExecuteCode(int[] code, int noun, int verb)
{ {
int[] memory = code; int[] memory = code;
memory[1] = noun; memory[1] = noun;
memory[2] = verb; memory[2] = verb;
var curAddr = 0; var curAddr = 0;
while (true) while (true)
{ {
var opCode = memory[curAddr]; var opCode = memory[curAddr];
if (opCode == 99) //Halt if (opCode == 99) //Halt
return memory[0]; return memory[0];
//Working Adresses //Working Adresses
int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3]; int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3];
if (a > memory.Length || b > memory.Length || c > memory.Length) if (a > memory.Length || b > memory.Length || c > memory.Length)
{ {
Console.WriteLine("ERROR: Out of Bounds"); Console.WriteLine("ERROR: Out of Bounds");
return 0; return 0;
} }
if (opCode == 1) //Add if (opCode == 1) //Add
memory[c] = memory[a] + memory[b]; memory[c] = memory[a] + memory[b];
if (opCode == 2) //Multiply if (opCode == 2) //Multiply
memory[c] = memory[a] * memory[b]; memory[c] = memory[a] * memory[b];
curAddr += 4; curAddr += 4;
} }
} }
public override void LoadInput() public override void LoadInput()
{ {
_inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv")); _inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
_inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv")); _inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = ExecuteCode(_inputPart1, 12, 2); Part1 = ExecuteCode(_inputPart1, 12, 2);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
int targetOutput = 19690720; int targetOutput = 19690720;
for (int n = 0; n < 100; n++) for (int n = 0; n < 100; n++)
{ {
for (int v = 0; v < 100; v++) for (int v = 0; v < 100; v++)
{ {
var curInput = new int[_inputPart2.Length]; var curInput = new int[_inputPart2.Length];
Array.Copy(_inputPart2, curInput, _inputPart2.Length); Array.Copy(_inputPart2, curInput, _inputPart2.Length);
if (ExecuteCode(curInput, n, v) == targetOutput) if (ExecuteCode(curInput, n, v) == targetOutput)
{ {
Part2 = 100 * n + v; Part2 = 100 * n + v;
return; return;
} }
} }
} }
} }
} }
} }

View File

@@ -1,319 +1,319 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System.Drawing; using System.Drawing;
namespace AdventOfCode.Problems.AOC2019.Day3 namespace AdventOfCode.Problems.AOC2019.Day3
{ {
[ProblemInfo(2019, 3, "Crossed Wires")] [ProblemInfo(2019, 3, "Crossed Wires")]
public class CrossedWires : Problem<int, int> public class CrossedWires : Problem<int, int>
{ {
private string[] _inputLines = Array.Empty<string>(); private string[] _inputLines = Array.Empty<string>();
public struct WireSegment public struct WireSegment
{ {
public Point min, max; public Point min, max;
public Point start, end; public Point start, end;
public int Length; public int Length;
public bool Vertical => min.X == max.X; public bool Vertical => min.X == max.X;
public WireSegment(Point a, Point b) public WireSegment(Point a, Point b)
{ {
start = a; start = a;
end = b; end = b;
if (a.X == b.X) //Vertical if (a.X == b.X) //Vertical
{ {
if (a.Y < b.Y) if (a.Y < b.Y)
{ {
min = a; min = a;
max = b; max = b;
} }
else else
{ {
min = b; min = b;
max = a; max = a;
} }
Length = Math.Abs(b.Y - a.Y); Length = Math.Abs(b.Y - a.Y);
} }
else else
{ {
if (a.X < b.X) if (a.X < b.X)
{ {
min = a; min = a;
max = b; max = b;
} }
else else
{ {
min = b; min = b;
max = a; max = a;
} }
Length = Math.Abs(b.X - a.X); Length = Math.Abs(b.X - a.X);
} }
} }
public WireSegment CreateRelative(Point offset) public WireSegment CreateRelative(Point offset)
{ {
return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y)); return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y));
} }
public bool ContainsPoint(Point point) public bool ContainsPoint(Point point)
{ {
if (Vertical) if (Vertical)
{ {
if (min.X == point.X) if (min.X == point.X)
{ {
return min.Y <= point.Y && max.Y >= point.Y; return min.Y <= point.Y && max.Y >= point.Y;
} }
else else
return false; return false;
} }
else else
{ {
if (min.Y == point.Y) if (min.Y == point.Y)
{ {
return min.X <= point.X && max.X >= point.X; return min.X <= point.X && max.X >= point.X;
} }
else else
return false; return false;
} }
} }
public bool Contains(WireSegment other) public bool Contains(WireSegment other)
{ {
if (Vertical != other.Vertical) if (Vertical != other.Vertical)
return false; return false;
if (Vertical) if (Vertical)
{ {
return min.Y <= other.min.Y && max.Y >= other.max.Y; return min.Y <= other.min.Y && max.Y >= other.max.Y;
} }
else else
{ {
return min.X <= other.min.X && max.X >= other.max.X; return min.X <= other.min.X && max.X >= other.max.X;
} }
} }
public WireSegment GetOverlap(WireSegment other) public WireSegment GetOverlap(WireSegment other)
{ {
if (Vertical) if (Vertical)
{ {
if (other.Contains(this)) if (other.Contains(this))
return this; return this;
else if (Contains(other)) else if (Contains(other))
return other; return other;
if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y) if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y)
{ {
return new WireSegment(other.min, max); return new WireSegment(other.min, max);
} }
else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y) else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y)
return new WireSegment(min, other.max); return new WireSegment(min, other.max);
else else
throw new Exception("No Overlap"); throw new Exception("No Overlap");
} }
else else
{ {
if (other.Contains(this)) if (other.Contains(this))
return this; return this;
else if (Contains(other)) else if (Contains(other))
return other; return other;
if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X) if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X)
{ {
return new WireSegment(other.min, max); return new WireSegment(other.min, max);
} }
else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X) else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X)
return new WireSegment(min, other.max); return new WireSegment(min, other.max);
else else
throw new Exception("No Overlap"); throw new Exception("No Overlap");
} }
} }
public bool Intersect(WireSegment other, out Point intersection) public bool Intersect(WireSegment other, out Point intersection)
{ {
if (Vertical) if (Vertical)
{ {
if (!other.Vertical)//Other Horizontal if (!other.Vertical)//Other Horizontal
{ {
var potInt = new Point(min.X, other.min.Y); var potInt = new Point(min.X, other.min.Y);
if (potInt == default) if (potInt == default)
{ {
intersection = default; intersection = default;
return false; return false;
} }
if (ContainsPoint(potInt) && other.ContainsPoint(potInt)) if (ContainsPoint(potInt) && other.ContainsPoint(potInt))
{ {
intersection = potInt; intersection = potInt;
return true; return true;
} }
else else
{ {
intersection = default; intersection = default;
return false; return false;
} }
} }
else //Both else //Both
{ {
if (min.X != other.min.X) if (min.X != other.min.X)
{ {
intersection = default; intersection = default;
return false; return false;
} }
else else
{ {
var overlap = GetOverlap(other); var overlap = GetOverlap(other);
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max)) if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
intersection = overlap.min == default ? overlap.max : overlap.min; intersection = overlap.min == default ? overlap.max : overlap.min;
else else
intersection = overlap.max == default ? overlap.min : overlap.max; intersection = overlap.max == default ? overlap.min : overlap.max;
if (intersection == default) if (intersection == default)
return false; return false;
return true; return true;
} }
} }
} }
else else
{ {
if (!other.Vertical) //Other Horizontal if (!other.Vertical) //Other Horizontal
{ {
if (min.Y != other.min.Y) if (min.Y != other.min.Y)
{ {
intersection = default; intersection = default;
return false; return false;
} }
var overlap = GetOverlap(other); var overlap = GetOverlap(other);
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max)) if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
intersection = overlap.min == default ? overlap.max : overlap.min; intersection = overlap.min == default ? overlap.max : overlap.min;
else else
intersection = overlap.max == default ? overlap.min : overlap.max; intersection = overlap.max == default ? overlap.min : overlap.max;
if (intersection == default) if (intersection == default)
return false; return false;
return true; return true;
} }
else else
return other.Intersect(this, out intersection); return other.Intersect(this, out intersection);
} }
} }
public override string ToString() public override string ToString()
{ {
return $"{start} > {end}"; return $"{start} > {end}";
} }
} }
public static int StepsToPoint(List<WireSegment> wires, Point p) public static int StepsToPoint(List<WireSegment> wires, Point p)
{ {
var steps = 0; var steps = 0;
for (int i = 0; i < wires.Count; i++) for (int i = 0; i < wires.Count; i++)
{ {
if (wires[i].ContainsPoint(p)) if (wires[i].ContainsPoint(p))
{ {
if (wires[i].Vertical) if (wires[i].Vertical)
steps += Math.Abs(wires[i].start.Y - p.Y); steps += Math.Abs(wires[i].start.Y - p.Y);
else else
steps += Math.Abs(wires[i].start.X - p.X); steps += Math.Abs(wires[i].start.X - p.X);
break; break;
} }
else else
steps += wires[i].Length; steps += wires[i].Length;
} }
return steps; return steps;
} }
public static int SolveWires(string[] wires) public static int SolveWires(string[] wires)
{ {
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires); var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
int shortestWire = int.MaxValue; int shortestWire = int.MaxValue;
for (int i = 0; i < wireSegmentsA.Count; i++) for (int i = 0; i < wireSegmentsA.Count; i++)
{ {
for (int j = 0; j < wireSegmentsB.Count; j++) for (int j = 0; j < wireSegmentsB.Count; j++)
{ {
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection)) if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
{ {
var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection); var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection);
if (len < shortestWire) if (len < shortestWire)
shortestWire = len; shortestWire = len;
} }
} }
} }
return shortestWire; return shortestWire;
} }
public static int SolveClosestDistane(string[] wires) public static int SolveClosestDistane(string[] wires)
{ {
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires); var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
int lastIntersection = int.MaxValue; int lastIntersection = int.MaxValue;
for (int i = 0; i < wireSegmentsA.Count; i++) for (int i = 0; i < wireSegmentsA.Count; i++)
{ {
for (int j = 0; j < wireSegmentsB.Count; j++) for (int j = 0; j < wireSegmentsB.Count; j++)
{ {
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection)) if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
{ {
var dist = ManhattanMagnitude(intersection); var dist = ManhattanMagnitude(intersection);
if (dist < lastIntersection) if (dist < lastIntersection)
lastIntersection = dist; lastIntersection = dist;
} }
} }
} }
return lastIntersection; return lastIntersection;
} }
private static (List<WireSegment> A, List<WireSegment> B) CreateWirePair(string[] wires) private static (List<WireSegment> A, List<WireSegment> B) CreateWirePair(string[] wires)
{ {
var wireA = wires[0].Split(','); var wireA = wires[0].Split(',');
var wireSegmentsA = CreateWire(wireA); var wireSegmentsA = CreateWire(wireA);
var wireB = wires[1].Split(','); var wireB = wires[1].Split(',');
var wireSegmentsB = CreateWire(wireB); var wireSegmentsB = CreateWire(wireB);
return (wireSegmentsA, wireSegmentsB); return (wireSegmentsA, wireSegmentsB);
} }
private static List<WireSegment> CreateWire(string[] wires) private static List<WireSegment> CreateWire(string[] wires)
{ {
var wireSegments = new List<WireSegment>(); var wireSegments = new List<WireSegment>();
for (int i = 0; i < wires.Length; i++) for (int i = 0; i < wires.Length; i++)
{ {
var curSegment = wires[i]; var curSegment = wires[i];
var offset = GetOffset(curSegment); var offset = GetOffset(curSegment);
if (i == 0) if (i == 0)
wireSegments.Add(new WireSegment(new Point(0, 0), offset)); wireSegments.Add(new WireSegment(new Point(0, 0), offset));
else else
wireSegments.Add(wireSegments.Last().CreateRelative(offset)); wireSegments.Add(wireSegments.Last().CreateRelative(offset));
} }
return wireSegments; return wireSegments;
} }
public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y); public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y);
public static Point GetOffset(string move) public static Point GetOffset(string move)
{ {
int x = 0, y = 0; int x = 0, y = 0;
if (move[0] == 'R') if (move[0] == 'R')
x = int.Parse(move.Remove(0, 1)); x = int.Parse(move.Remove(0, 1));
else if (move[0] == 'L') else if (move[0] == 'L')
x = -int.Parse(move.Remove(0, 1)); x = -int.Parse(move.Remove(0, 1));
else if (move[0] == 'U') else if (move[0] == 'U')
y = int.Parse(move.Remove(0, 1)); y = int.Parse(move.Remove(0, 1));
else if (move[0] == 'D') else if (move[0] == 'D')
y = -int.Parse(move.Remove(0, 1)); y = -int.Parse(move.Remove(0, 1));
return new Point(x, y); return new Point(x, y);
} }
public override void LoadInput() public override void LoadInput()
{ {
_inputLines = ReadInputLines(); _inputLines = ReadInputLines();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = SolveClosestDistane(_inputLines); Part1 = SolveClosestDistane(_inputLines);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = SolveWires(_inputLines); Part2 = SolveWires(_inputLines);
} }
} }
} }

View File

@@ -1,147 +1,147 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day4 namespace AdventOfCode.Problems.AOC2019.Day4
{ {
[ProblemInfo(2019, 4, "Secure Container")] [ProblemInfo(2019, 4, "Secure Container")]
public class SecureContainer : Problem<int, int> public class SecureContainer : Problem<int, int>
{ {
public static bool IsValidPassword(int[] password) public static bool IsValidPassword(int[] password)
{ {
if (password.Length != 6) if (password.Length != 6)
return false; return false;
return HasRepeating(password) && IsAssending(password); return HasRepeating(password) && IsAssending(password);
} }
public static bool HasRepeating(int[] password) public static bool HasRepeating(int[] password)
{ {
for (int i = 0; i < password.Length - 1; i++) for (int i = 0; i < password.Length - 1; i++)
{ {
if (password[i] == password[i + 1]) if (password[i] == password[i + 1])
return true; return true;
} }
return false; return false;
} }
public static bool HasDoubles(int[] password) public static bool HasDoubles(int[] password)
{ {
bool foundDouble = false; bool foundDouble = false;
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
int c = 0; int c = 0;
for (int j = 0; j < 6; j++) for (int j = 0; j < 6; j++)
{ {
if (password[j] == password[i]) if (password[j] == password[i])
c++; c++;
else else
{ {
if (c != 0) if (c != 0)
{ {
if (c == 2) if (c == 2)
foundDouble = true; foundDouble = true;
c = 0; c = 0;
} }
} }
} }
if (c == 2) if (c == 2)
foundDouble = true; foundDouble = true;
} }
return foundDouble; return foundDouble;
} }
public static bool IsAssending(int[] password) public static bool IsAssending(int[] password)
{ {
for (int i = 1; i < 6; i++) for (int i = 1; i < 6; i++)
{ {
if (password[i] < password[i - 1]) if (password[i] < password[i - 1])
{ {
return false; return false;
} }
} }
return true; return true;
} }
public static int CountPasswordsPart1(int lower, int upper) public static int CountPasswordsPart1(int lower, int upper)
{ {
int passwordCount = 0; int passwordCount = 0;
int[] curPassword = lower.ToIntArray(); int[] curPassword = lower.ToIntArray();
CleanPassword(ref curPassword); CleanPassword(ref curPassword);
while (curPassword.ToInt() <= upper) while (curPassword.ToInt() <= upper)
{ {
if (IsValidPassword(curPassword)) if (IsValidPassword(curPassword))
{ {
passwordCount++; passwordCount++;
} }
curPassword[^1]++; curPassword[^1]++;
Propagate(ref curPassword, curPassword.Length - 1); Propagate(ref curPassword, curPassword.Length - 1);
CleanPassword(ref curPassword); CleanPassword(ref curPassword);
} }
return passwordCount; return passwordCount;
} }
public static int CountPasswordsPart2(int lower, int upper) public static int CountPasswordsPart2(int lower, int upper)
{ {
int passwordCount = 0; int passwordCount = 0;
int[] curPassword = lower.ToIntArray(); int[] curPassword = lower.ToIntArray();
CleanPassword(ref curPassword); CleanPassword(ref curPassword);
while (curPassword.ToInt() <= upper) while (curPassword.ToInt() <= upper)
{ {
if (HasDoubles(curPassword)) if (HasDoubles(curPassword))
{ {
passwordCount++; passwordCount++;
} }
curPassword[^1]++; curPassword[^1]++;
Propagate(ref curPassword, curPassword.Length - 1); Propagate(ref curPassword, curPassword.Length - 1);
CleanPassword(ref curPassword); CleanPassword(ref curPassword);
} }
return passwordCount; return passwordCount;
} }
public static void CleanPassword(ref int[] password) public static void CleanPassword(ref int[] password)
{ {
for (int i = 1; i < 6; i++) for (int i = 1; i < 6; i++)
{ {
if (password[i] < password[i - 1]) if (password[i] < password[i - 1])
{ {
password[i] += password[i - 1] - password[i]; password[i] += password[i - 1] - password[i];
if (password[i] == 10) if (password[i] == 10)
{ {
Propagate(ref password, i); Propagate(ref password, i);
password[i] = password[i - 1]; password[i] = password[i - 1];
} }
} }
} }
} }
public static void Propagate(ref int[] password, int digit) public static void Propagate(ref int[] password, int digit)
{ {
for (int i = digit; i >= 0; i--) for (int i = digit; i >= 0; i--)
{ {
if (i == 0 && password[i] == 10) if (i == 0 && password[i] == 10)
{ {
password[i] = 9; password[i] = 9;
break; break;
} }
if (password[i] == 10) if (password[i] == 10)
{ {
password[i] = 0; password[i] = 0;
password[i - 1]++; password[i - 1]++;
} }
} }
} }
public override void LoadInput() public override void LoadInput()
{ {
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = CountPasswordsPart1(147981, 691423); Part1 = CountPasswordsPart1(147981, 691423);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = CountPasswordsPart2(147981, 691423); Part2 = CountPasswordsPart2(147981, 691423);
} }
} }
} }

View File

@@ -1,30 +1,30 @@
using AdventOfCode.Day_5; using AdventOfCode.Day_5;
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day5; namespace AdventOfCode.Problems.AOC2019.Day5;
[ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")] [ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")]
internal class ChanceOfAsteroids : Problem<int, int> internal class ChanceOfAsteroids : Problem<int, int>
{ {
private IntCodeV2 _cpu = new IntCodeV2(); private IntCodeV2 _cpu = new IntCodeV2();
private int[] _baseInput = Array.Empty<int>(); private int[] _baseInput = Array.Empty<int>();
public override void CalculatePart1() public override void CalculatePart1()
{ {
var output = new int[1]; var output = new int[1];
_cpu.ExecuteCode(_baseInput, new int[] { 1 }, output); _cpu.ExecuteCode(_baseInput, new int[] { 1 }, output);
Part1 = output[0]; Part1 = output[0];
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var output = new int[1]; var output = new int[1];
_cpu.ExecuteCode(_baseInput, new int[] { 5 }, output); _cpu.ExecuteCode(_baseInput, new int[] { 5 }, output);
Part2 = output[0]; Part2 = output[0];
} }
public override void LoadInput() public override void LoadInput()
{ {
_baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv")); _baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
} }
} }

View File

@@ -1,233 +1,233 @@
namespace AdventOfCode.Day_5 namespace AdventOfCode.Day_5
{ {
public class IntCodeV2 public class IntCodeV2
{ {
public struct Instruction public struct Instruction
{ {
public int opcode; public int opcode;
public int paramCount; public int paramCount;
public Func<int[], int[], int, int, int, bool> action; public Func<int[], int[], int, int, int, bool> action;
public Instruction(int opcode, int paramCount, Func<int[], int[], int, int, int, bool> action) public Instruction(int opcode, int paramCount, Func<int[], int[], int, int, int, bool> action)
{ {
this.opcode = opcode; this.opcode = opcode;
this.paramCount = paramCount; this.paramCount = paramCount;
this.action = action; this.action = action;
} }
} }
public bool IsHalted { get; private set; } public bool IsHalted { get; private set; }
public bool IsRunning { get; private set; } public bool IsRunning { get; private set; }
public bool PersistentMode { get; private set; } public bool PersistentMode { get; private set; }
public bool SuspendOnWrite { get; private set; } public bool SuspendOnWrite { get; private set; }
private Dictionary<int, Instruction> _instructions; private Dictionary<int, Instruction> _instructions;
private int _instructionPointer; private int _instructionPointer;
private int[]? _inputBuffer; private int[]? _inputBuffer;
private int _inputCounter = 0; private int _inputCounter = 0;
private int[]? _outputBuffer; private int[]? _outputBuffer;
private int _outputCounter = 0; private int _outputCounter = 0;
private int[] memory = Array.Empty<int>(); private int[] memory = Array.Empty<int>();
public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false) public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false)
{ {
_instructions = new Dictionary<int, Instruction>(); _instructions = new Dictionary<int, Instruction>();
PersistentMode = persistentMode; PersistentMode = persistentMode;
SuspendOnWrite = suspendOnOutput; SuspendOnWrite = suspendOnOutput;
IsHalted = false; IsHalted = false;
//Add //Add
_instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) => _instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
var v3 = mode[0] == 1 ? mem[p3] : p3; var v3 = mode[0] == 1 ? mem[p3] : p3;
mem[v3] = v1 + v2; mem[v3] = v1 + v2;
return true; return true;
})); }));
//Multiply //Multiply
_instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) => _instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
var v3 = mode[0] == 1 ? mem[p3] : p3; var v3 = mode[0] == 1 ? mem[p3] : p3;
mem[v3] = v1 * v2; mem[v3] = v1 * v2;
return true; return true;
})); }));
//Halt //Halt
_instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) => _instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) =>
{ {
IsHalted = true; IsHalted = true;
IsRunning = false; IsRunning = false;
return false; return false;
})); }));
//Read Input //Read Input
_instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) => _instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? mem[p1] : p1; var v1 = mode[2] == 1 ? mem[p1] : p1;
mem[v1] = ReadInput(); mem[v1] = ReadInput();
//Console.WriteLine($"Input Read: {mem[v1]}"); //Console.WriteLine($"Input Read: {mem[v1]}");
return true; return true;
})); }));
//Write Output //Write Output
_instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) => _instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
WriteOutput(v1); WriteOutput(v1);
if (SuspendOnWrite) if (SuspendOnWrite)
IsRunning = false; IsRunning = false;
return true; return true;
})); }));
//Jump if True //Jump if True
_instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) => _instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
if (v1 != 0) if (v1 != 0)
{ {
_instructionPointer = v2; _instructionPointer = v2;
return false; return false;
} }
return true; return true;
})); }));
//Jump if False //Jump if False
_instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) => _instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
if (v1 == 0) if (v1 == 0)
{ {
_instructionPointer = v2; _instructionPointer = v2;
return false; return false;
} }
return true; return true;
})); }));
//Less than //Less than
_instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) => _instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
var v3 = mode[0] == 1 ? mem[p3] : p3; var v3 = mode[0] == 1 ? mem[p3] : p3;
if (v1 < v2) if (v1 < v2)
mem[v3] = 1; mem[v3] = 1;
else else
mem[v3] = 0; mem[v3] = 0;
return true; return true;
})); }));
//Equals //Equals
_instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) => _instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) =>
{ {
var v1 = mode[2] == 1 ? p1 : mem[p1]; var v1 = mode[2] == 1 ? p1 : mem[p1];
var v2 = mode[1] == 1 ? p2 : mem[p2]; var v2 = mode[1] == 1 ? p2 : mem[p2];
var v3 = mode[0] == 1 ? mem[p3] : p3; var v3 = mode[0] == 1 ? mem[p3] : p3;
if (v1 == v2) if (v1 == v2)
mem[v3] = 1; mem[v3] = 1;
else else
mem[v3] = 0; mem[v3] = 0;
return true; return true;
})); }));
} }
private int ReadInput() private int ReadInput()
{ {
_inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1); _inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1);
if (_inputBuffer != null && _inputCounter < _inputBuffer.Length) if (_inputBuffer != null && _inputCounter < _inputBuffer.Length)
return _inputBuffer[_inputCounter++]; return _inputBuffer[_inputCounter++];
else else
{ {
Console.Write("Input: "); Console.Write("Input: ");
return int.Parse(Console.ReadLine()!); return int.Parse(Console.ReadLine()!);
} }
} }
private void WriteOutput(int output) private void WriteOutput(int output)
{ {
_outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1); _outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1);
if (_outputBuffer != null && _outputCounter < _outputBuffer.Length) if (_outputBuffer != null && _outputCounter < _outputBuffer.Length)
_outputBuffer[_outputCounter++] = output; _outputBuffer[_outputCounter++] = output;
else else
Console.WriteLine(output); Console.WriteLine(output);
} }
public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null) public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null)
{ {
LoadCode(code); LoadCode(code);
SetIO(input, output); SetIO(input, output);
IsHalted = false; IsHalted = false;
Run(); Run();
} }
public static (int[] opModes, int opcode) ParseInstruction(int instruction) public static (int[] opModes, int opcode) ParseInstruction(int instruction)
{ {
var opModes = new int[3]; var opModes = new int[3];
var arr = instruction.ToIntArray(); var arr = instruction.ToIntArray();
switch (arr.Length) switch (arr.Length)
{ {
case 1: case 1:
return (opModes, arr[0]); return (opModes, arr[0]);
case 2: case 2:
return (opModes, (arr[^2] * 10) + arr[^1]); return (opModes, (arr[^2] * 10) + arr[^1]);
} }
var opcode = (arr[^2] * 10) + arr[^1]; var opcode = (arr[^2] * 10) + arr[^1];
for (int i = 1; i <= 3; i++) for (int i = 1; i <= 3; i++)
{ {
if (arr.Length < i + 2) if (arr.Length < i + 2)
opModes[^i] = 0; opModes[^i] = 0;
else else
opModes[^i] = arr[^(i + 2)]; opModes[^i] = arr[^(i + 2)];
} }
return (opModes, opcode); return (opModes, opcode);
} }
public void ResetIO() public void ResetIO()
{ {
_inputCounter = _outputCounter = 0; _inputCounter = _outputCounter = 0;
} }
public void SetInputIndex(int index) public void SetInputIndex(int index)
{ {
_inputCounter = index; _inputCounter = index;
} }
public void SetIO(int[]? inputBuffer, int[]? outputBuffer) public void SetIO(int[]? inputBuffer, int[]? outputBuffer)
{ {
ResetIO(); ResetIO();
_inputBuffer = inputBuffer ?? Array.Empty<int>(); _inputBuffer = inputBuffer ?? Array.Empty<int>();
_outputBuffer = outputBuffer ?? Array.Empty<int>(); _outputBuffer = outputBuffer ?? Array.Empty<int>();
} }
public void Run() public void Run()
{ {
IsRunning = true; IsRunning = true;
while (IsRunning) while (IsRunning)
{ {
var (modes, opcode) = ParseInstruction(memory[_instructionPointer]); var (modes, opcode) = ParseInstruction(memory[_instructionPointer]);
var curInstruction = _instructions[opcode]; var curInstruction = _instructions[opcode];
int[] parameters = new int[3]; int[] parameters = new int[3];
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (i >= curInstruction.paramCount) if (i >= curInstruction.paramCount)
parameters[i] = 0; parameters[i] = 0;
else else
parameters[i] = memory[_instructionPointer + i + 1]; parameters[i] = memory[_instructionPointer + i + 1];
} }
if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2])) if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2]))
_instructionPointer += curInstruction.paramCount + 1; _instructionPointer += curInstruction.paramCount + 1;
if (IsHalted) if (IsHalted)
IsRunning = false; IsRunning = false;
} }
} }
public IntCodeV2 LoadCode(int[] code) public IntCodeV2 LoadCode(int[] code)
{ {
memory = new int[code.Length]; memory = new int[code.Length];
code.CopyTo(memory, 0); code.CopyTo(memory, 0);
_instructionPointer = 0; _instructionPointer = 0;
return this; return this;
} }
} }
} }

View File

@@ -1,119 +1,119 @@
namespace AdventOfCode.Problems.AOC2019.Day6 namespace AdventOfCode.Problems.AOC2019.Day6
{ {
public class OrbitMap public class OrbitMap
{ {
public CelestialObject root; public CelestialObject root;
public Dictionary<string, CelestialObject> objectMap; public Dictionary<string, CelestialObject> objectMap;
public OrbitMap(string[] orbits) public OrbitMap(string[] orbits)
{ {
objectMap = new Dictionary<string, CelestialObject>(); objectMap = new Dictionary<string, CelestialObject>();
GenerateOrbits(orbits); GenerateOrbits(orbits);
} }
public void GenerateOrbits(string[] orbits) public void GenerateOrbits(string[] orbits)
{ {
for (int i = 0; i < orbits.Length; i++) for (int i = 0; i < orbits.Length; i++)
{ {
var bodies = orbits[i].Split(')'); var bodies = orbits[i].Split(')');
if (bodies[0] == "COM") if (bodies[0] == "COM")
root = CreateObject("COM"); root = CreateObject("COM");
var parent = GetOrCreateObject(bodies[0]); var parent = GetOrCreateObject(bodies[0]);
var child = GetOrCreateObject(bodies[1]); var child = GetOrCreateObject(bodies[1]);
parent.AddChild(child); parent.AddChild(child);
} }
} }
public CelestialObject GetOrCreateObject(string name) public CelestialObject GetOrCreateObject(string name)
{ {
if (objectMap.ContainsKey(name)) if (objectMap.ContainsKey(name))
return objectMap[name]; return objectMap[name];
else else
return CreateObject(name); return CreateObject(name);
} }
public CelestialObject CreateObject(string name) public CelestialObject CreateObject(string name)
{ {
var o = new CelestialObject(name); var o = new CelestialObject(name);
objectMap.Add(name, o); objectMap.Add(name, o);
return o; return o;
} }
public int CalculateOrbits() public int CalculateOrbits()
{ {
return root.GetOrbitCount(); return root.GetOrbitCount();
} }
public List<CelestialObject> FindPathTo(string name) public List<CelestialObject> FindPathTo(string name)
{ {
var path = new List<CelestialObject>(); var path = new List<CelestialObject>();
root.FindPathTo(name, path); root.FindPathTo(name, path);
return path; return path;
} }
public int GetDepthOf(string name) => root.GetDepth(name); public int GetDepthOf(string name) => root.GetDepth(name);
public class CelestialObject public class CelestialObject
{ {
public string Name { get; set; } public string Name { get; set; }
public int ChildCount => children.Count; public int ChildCount => children.Count;
public List<CelestialObject> children; public List<CelestialObject> children;
public CelestialObject(string name) public CelestialObject(string name)
{ {
children = new List<CelestialObject>(); children = new List<CelestialObject>();
Name = name; Name = name;
} }
public void AddChild(CelestialObject child) public void AddChild(CelestialObject child)
{ {
children.Add(child); children.Add(child);
} }
public int GetOrbitCount(int depth = 0) public int GetOrbitCount(int depth = 0)
{ {
var count = 0; var count = 0;
for (int i = 0; i < children.Count; i++) for (int i = 0; i < children.Count; i++)
{ {
count += children[i].GetOrbitCount(depth + 1); count += children[i].GetOrbitCount(depth + 1);
} }
return depth + count; return depth + count;
} }
public bool FindPathTo(string name, List<CelestialObject> path) public bool FindPathTo(string name, List<CelestialObject> path)
{ {
if (name == Name) if (name == Name)
return true; return true;
for (int i = 0; i < ChildCount; i++) for (int i = 0; i < ChildCount; i++)
{ {
if (children[i].FindPathTo(name, path)) if (children[i].FindPathTo(name, path))
{ {
path.Add(children[i]); path.Add(children[i]);
return true; return true;
} }
} }
return false; return false;
} }
public int GetDepth(string name, int depth = 0) public int GetDepth(string name, int depth = 0)
{ {
if (name == Name) if (name == Name)
return depth; return depth;
var d = 0; var d = 0;
for (int i = 0; i < ChildCount; i++) for (int i = 0; i < ChildCount; i++)
{ {
d += children[i].GetDepth(name, depth + 1); d += children[i].GetDepth(name, depth + 1);
} }
return d; return d;
} }
public override string ToString() public override string ToString()
{ {
return Name; return Name;
} }
} }
} }
} }

View File

@@ -1,53 +1,53 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day6; namespace AdventOfCode.Problems.AOC2019.Day6;
[ProblemInfo(2019, 6, "Universal Orbit Map")] [ProblemInfo(2019, 6, "Universal Orbit Map")]
internal class UniversalOrbits : Problem<int, int> internal class UniversalOrbits : Problem<int, int>
{ {
private OrbitMap? _map; private OrbitMap? _map;
public override void CalculatePart1() public override void CalculatePart1()
{ {
if (_map == null) if (_map == null)
return; return;
Part1 = _map.CalculateOrbits(); Part1 = _map.CalculateOrbits();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
if (_map == null) if (_map == null)
return; return;
var pathToYOU = _map.FindPathTo("YOU"); var pathToYOU = _map.FindPathTo("YOU");
var pathToSAN = _map.FindPathTo("SAN"); var pathToSAN = _map.FindPathTo("SAN");
string pivot = ""; string pivot = "";
int dist = 0; int dist = 0;
HashSet<string> pathYOU = new(pathToYOU.Select(o => o.Name)); HashSet<string> pathYOU = new(pathToYOU.Select(o => o.Name));
for (int i = 0; i < pathToSAN.Count; i++) for (int i = 0; i < pathToSAN.Count; i++)
{ {
if (pathYOU.Contains(pathToSAN[i].Name)) if (pathYOU.Contains(pathToSAN[i].Name))
{ {
pivot = pathToSAN[i].Name; pivot = pathToSAN[i].Name;
dist = i; dist = i;
break; break;
} }
} }
for (int i = 0; i < pathToYOU.Count; i++) for (int i = 0; i < pathToYOU.Count; i++)
{ {
if (pathToYOU[i].Name == pivot) if (pathToYOU[i].Name == pivot)
{ {
dist += i; dist += i;
break; break;
} }
} }
Part2 = dist - 2; Part2 = dist - 2;
} }
public override void LoadInput() public override void LoadInput()
{ {
_map = new OrbitMap(ReadInputLines()); _map = new OrbitMap(ReadInputLines());
} }
} }

View File

@@ -1,161 +1,161 @@
using AdventOfCode.Day_5; using AdventOfCode.Day_5;
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day7 namespace AdventOfCode.Problems.AOC2019.Day7
{ {
[ProblemInfo(2019, 7, "Amplification Circuit")] [ProblemInfo(2019, 7, "Amplification Circuit")]
public class AmplificationCircuit : Problem<int, int> public class AmplificationCircuit : Problem<int, int>
{ {
private int[] _code = Array.Empty<int>(); private int[] _code = Array.Empty<int>();
public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings) public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings)
{ {
if (HasDuplicateValues(phaseSettings)) if (HasDuplicateValues(phaseSettings))
return int.MinValue; return int.MinValue;
int[] outputBuffer = { 0 }; int[] outputBuffer = { 0 };
int[] inputBuffer; int[] inputBuffer;
//Amp A //Amp A
inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] }; inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] };
cpu.ExecuteCode(code, inputBuffer, outputBuffer); cpu.ExecuteCode(code, inputBuffer, outputBuffer);
//Amp B //Amp B
inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] }; inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] };
cpu.ExecuteCode(code, inputBuffer, outputBuffer); cpu.ExecuteCode(code, inputBuffer, outputBuffer);
//Amp C //Amp C
inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] }; inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] };
cpu.ExecuteCode(code, inputBuffer, outputBuffer); cpu.ExecuteCode(code, inputBuffer, outputBuffer);
//Amp D //Amp D
inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] }; inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] };
cpu.ExecuteCode(code, inputBuffer, outputBuffer); cpu.ExecuteCode(code, inputBuffer, outputBuffer);
//Amp E //Amp E
inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] }; inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] };
cpu.ExecuteCode(code, inputBuffer, outputBuffer); cpu.ExecuteCode(code, inputBuffer, outputBuffer);
return outputBuffer[0]; return outputBuffer[0];
} }
public static int RunFeedback(int[] code, int[] phaseSettings) public static int RunFeedback(int[] code, int[] phaseSettings)
{ {
if (HasDuplicateValues(phaseSettings)) if (HasDuplicateValues(phaseSettings))
return int.MinValue; return int.MinValue;
var ampA = new IntCodeV2(true, true).LoadCode(code); var ampA = new IntCodeV2(true, true).LoadCode(code);
var ampB = new IntCodeV2(true, true).LoadCode(code); var ampB = new IntCodeV2(true, true).LoadCode(code);
var ampC = new IntCodeV2(true, true).LoadCode(code); var ampC = new IntCodeV2(true, true).LoadCode(code);
var ampD = new IntCodeV2(true, true).LoadCode(code); var ampD = new IntCodeV2(true, true).LoadCode(code);
var ampE = new IntCodeV2(true, true).LoadCode(code); var ampE = new IntCodeV2(true, true).LoadCode(code);
var outputA = new int[] { 273 }; var outputA = new int[] { 273 };
var outputB = new int[] { 0 }; var outputB = new int[] { 0 };
var outputC = new int[] { 0 }; var outputC = new int[] { 0 };
var outputD = new int[] { 0 }; var outputD = new int[] { 0 };
var outputE = new int[] { 0 }; var outputE = new int[] { 0 };
var inputA = new int[] { phaseSettings[0], outputE[0] }; var inputA = new int[] { phaseSettings[0], outputE[0] };
var inputB = new int[] { phaseSettings[1], outputA[0] }; var inputB = new int[] { phaseSettings[1], outputA[0] };
var inputC = new int[] { phaseSettings[2], outputB[0] }; var inputC = new int[] { phaseSettings[2], outputB[0] };
var inputD = new int[] { phaseSettings[3], outputC[0] }; var inputD = new int[] { phaseSettings[3], outputC[0] };
var inputE = new int[] { phaseSettings[4], outputD[0] }; var inputE = new int[] { phaseSettings[4], outputD[0] };
ampA.SetIO(inputA, outputA); ampA.SetIO(inputA, outputA);
ampB.SetIO(inputB, outputB); ampB.SetIO(inputB, outputB);
ampC.SetIO(inputC, outputC); ampC.SetIO(inputC, outputC);
ampD.SetIO(inputD, outputD); ampD.SetIO(inputD, outputD);
ampE.SetIO(inputE, outputE); ampE.SetIO(inputE, outputE);
int iter = 0; int iter = 0;
while (!ampE.IsHalted) while (!ampE.IsHalted)
{ {
//Console.WriteLine($"Iteration {iter}"); //Console.WriteLine($"Iteration {iter}");
inputA[1] = outputE[0]; inputA[1] = outputE[0];
ampA.Run(); ampA.Run();
inputB[1] = outputA[0]; inputB[1] = outputA[0];
ampB.Run(); ampB.Run();
inputC[1] = outputB[0]; inputC[1] = outputB[0];
ampC.Run(); ampC.Run();
inputD[1] = outputC[0]; inputD[1] = outputC[0];
ampD.Run(); ampD.Run();
inputE[1] = outputD[0]; inputE[1] = outputD[0];
ampE.Run(); ampE.Run();
//Console.WriteLine($"Output {outputE[0]}"); //Console.WriteLine($"Output {outputE[0]}");
iter++; iter++;
} }
return outputE[0]; return outputE[0];
} }
public static bool HasDuplicateValues(int[] arr) public static bool HasDuplicateValues(int[] arr)
{ {
for (int i = 0; i < arr.Length; i++) for (int i = 0; i < arr.Length; i++)
{ {
for (int j = 0; j < arr.Length; j++) for (int j = 0; j < arr.Length; j++)
{ {
if (i == j) if (i == j)
continue; continue;
if (arr[i] == arr[j]) if (arr[i] == arr[j])
return true; return true;
} }
} }
return false; return false;
} }
public override void LoadInput() public override void LoadInput()
{ {
_code = InputParsing.ParseIntCsv(GetInputFile("input.csv")); _code = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
int output = int.MinValue; int output = int.MinValue;
int min = 0; int min = 0;
int max = 5; int max = 5;
var cpu = new IntCodeV2(); var cpu = new IntCodeV2();
for (int i = min; i < max; i++) for (int i = min; i < max; i++)
{ {
for (int j = min; j < max; j++) for (int j = min; j < max; j++)
{ {
for (int k = min; k < max; k++) for (int k = min; k < max; k++)
{ {
for (int l = min; l < max; l++) for (int l = min; l < max; l++)
{ {
for (int m = min; m < max; m++) for (int m = min; m < max; m++)
{ {
var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m }); var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m });
if (output < result) if (output < result)
{ {
output = result; output = result;
} }
} }
} }
} }
} }
} }
Part1 = output; Part1 = output;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
int output = int.MinValue; int output = int.MinValue;
int min = 5; int min = 5;
int max = 10; int max = 10;
for (int i = min; i < max; i++) for (int i = min; i < max; i++)
{ {
for (int j = min; j < max; j++) for (int j = min; j < max; j++)
{ {
for (int k = min; k < max; k++) for (int k = min; k < max; k++)
{ {
for (int l = min; l < max; l++) for (int l = min; l < max; l++)
{ {
for (int m = min; m < max; m++) for (int m = min; m < max; m++)
{ {
var result = RunFeedback(_code, new int[] { i, j, k, l, m }); var result = RunFeedback(_code, new int[] { i, j, k, l, m });
if (output < result) if (output < result)
{ {
output = result; output = result;
} }
} }
} }
} }
} }
} }
Part2 = output; Part2 = output;
} }
} }
} }

View File

@@ -1,83 +1,83 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2019.Day8 namespace AdventOfCode.Problems.AOC2019.Day8
{ {
[ProblemInfo(2019, 8, "Space Image Format")] [ProblemInfo(2019, 8, "Space Image Format")]
public class SpaceImageFormat : Problem<int, string> public class SpaceImageFormat : Problem<int, string>
{ {
private int[] _imageData = Array.Empty<int>(); private int[] _imageData = Array.Empty<int>();
public static void Execute() public static void Execute()
{ {
var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray(); var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
Console.WriteLine(Checksum(imageData, 25, 6)); Console.WriteLine(Checksum(imageData, 25, 6));
} }
public static void RenderImage(int[] data, int h, int w) public static void RenderImage(int[] data, int h, int w)
{ {
var imgSize = h * w; var imgSize = h * w;
var layerCount = data.Length / imgSize; var layerCount = data.Length / imgSize;
for (int l = 0; l < layerCount; l++) for (int l = 0; l < layerCount; l++)
{ {
} }
} }
public static int Checksum(int[] data, int h, int w) public static int Checksum(int[] data, int h, int w)
{ {
var imgSize = h * w; var imgSize = h * w;
var layerCount = data.Length / imgSize; var layerCount = data.Length / imgSize;
int[] zeroCount = new int[layerCount]; int[] zeroCount = new int[layerCount];
int[] oneCount = new int[layerCount]; int[] oneCount = new int[layerCount];
int[] twoCount = new int[layerCount]; int[] twoCount = new int[layerCount];
int smallestLayer = -1; int smallestLayer = -1;
int smallestLayerCount = int.MaxValue; int smallestLayerCount = int.MaxValue;
for (int l = 0; l < layerCount; l++) for (int l = 0; l < layerCount; l++)
{ {
for (int i = imgSize * l; i < imgSize * (l + 1); i++) for (int i = imgSize * l; i < imgSize * (l + 1); i++)
{ {
switch (data[i]) switch (data[i])
{ {
case 0: case 0:
zeroCount[l]++; zeroCount[l]++;
break; break;
case 1: case 1:
oneCount[l]++; oneCount[l]++;
break; break;
case 2: case 2:
twoCount[l]++; twoCount[l]++;
break; break;
} }
} }
if (zeroCount[l] <= smallestLayerCount) if (zeroCount[l] <= smallestLayerCount)
{ {
smallestLayer = l; smallestLayer = l;
smallestLayerCount = zeroCount[l]; smallestLayerCount = zeroCount[l];
} }
} }
return oneCount[smallestLayer] * twoCount[smallestLayer]; return oneCount[smallestLayer] * twoCount[smallestLayer];
} }
public override void LoadInput() public override void LoadInput()
{ {
_imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray(); _imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = Checksum(_imageData, 25, 6); Part1 = Checksum(_imageData, 25, 6);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = null; Part2 = null;
} }
} }
} }

View File

@@ -1,31 +1,31 @@
namespace AdventOfCode namespace AdventOfCode
{ {
public static class InputParsing public static class InputParsing
{ {
public static int[] ParseIntArray(string file) public static int[] ParseIntArray(string file)
{ {
return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray(); return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray();
} }
public static int[] ParseIntCsv(string file) public static int[] ParseIntCsv(string file)
{ {
return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray(); return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray();
} }
public static int ToInt(this int[] intArr) public static int ToInt(this int[] intArr)
{ {
int value = 0; int value = 0;
for (int i = 0; i < intArr.Length; i++) for (int i = 0; i < intArr.Length; i++)
{ {
value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i]; value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i];
} }
return value; return value;
} }
public static int[] ToIntArray(this int number) public static int[] ToIntArray(this int number)
{ {
int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray(); int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray();
return intArr; return intArr;
} }
} }
} }

View File

@@ -1,196 +1,196 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System.Collections; using System.Collections;
namespace AdventOfCode.Problems.AOC2021.Day11; namespace AdventOfCode.Problems.AOC2021.Day11;
[ProblemInfo(2021, 11, "Dumbo Octopus")] [ProblemInfo(2021, 11, "Dumbo Octopus")]
public class DumboOctopus : Problem<int, int>, IEnumerable<byte> public class DumboOctopus : Problem<int, int>, IEnumerable<byte>
{ {
public byte[] dataPart1 = Array.Empty<byte>(); public byte[] dataPart1 = Array.Empty<byte>();
public byte[] dataPart2 = Array.Empty<byte>(); public byte[] dataPart2 = Array.Empty<byte>();
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputLines(); var data = ReadInputLines();
dataPart1 = new byte[10 * 10]; dataPart1 = new byte[10 * 10];
if (data.Length != 10) if (data.Length != 10)
throw new ArgumentException("Data must contain 10 elements", nameof(data)); throw new ArgumentException("Data must contain 10 elements", nameof(data));
for (int y = 0; y < data.Length; y++) for (int y = 0; y < data.Length; y++)
{ {
var line = data[y]; var line = data[y];
if (line.Length != 10) if (line.Length != 10)
throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data)); throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data));
for (int x = 0; x < line.Length; x++) for (int x = 0; x < line.Length; x++)
{ {
dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1)); dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1));
} }
} }
dataPart2 = new byte[10 * 10]; dataPart2 = new byte[10 * 10];
Array.Copy(dataPart1, dataPart2, dataPart1.Length); Array.Copy(dataPart1, dataPart2, dataPart1.Length);
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = Run(ref dataPart1, 100, out _); Part1 = Run(ref dataPart1, 100, out _);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Run(ref dataPart2, 210, out var fullFlash); Run(ref dataPart2, 210, out var fullFlash);
Part2 = fullFlash; Part2 = fullFlash;
} }
public IEnumerator<byte> GetEnumerator() public IEnumerator<byte> GetEnumerator()
{ {
return ((IEnumerable<byte>)dataPart1).GetEnumerator(); return ((IEnumerable<byte>)dataPart1).GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return dataPart1.GetEnumerator(); return dataPart1.GetEnumerator();
} }
public int Run(ref byte[] data, int count, out int fullFlash) public int Run(ref byte[] data, int count, out int fullFlash)
{ {
var flashes = 0; var flashes = 0;
fullFlash = 0; fullFlash = 0;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
var start = flashes; var start = flashes;
Run(ref data, ref flashes); Run(ref data, ref flashes);
if (flashes - start == 100) if (flashes - start == 100)
{ {
fullFlash = i + 1; fullFlash = i + 1;
break; break;
} }
} }
return flashes; return flashes;
} }
public void Run(ref byte[] data, ref int flashes) public void Run(ref byte[] data, ref int flashes)
{ {
Increment(ref data); Increment(ref data);
Flash(ref data, ref flashes); Flash(ref data, ref flashes);
} }
private static void Increment(ref byte[] data) private static void Increment(ref byte[] data)
{ {
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
data[i]++; data[i]++;
} }
private void Flash(ref byte[] data, ref int flashes) private void Flash(ref byte[] data, ref int flashes)
{ {
int diff; int diff;
do do
{ {
var startFlash = flashes; var startFlash = flashes;
for (int i = 0; i < data.Length; i++) for (int i = 0; i < data.Length; i++)
{ {
if (data[i] > 9) if (data[i] > 9)
PerformFlash(ref data, i, ref flashes); PerformFlash(ref data, i, ref flashes);
} }
diff = flashes - startFlash; diff = flashes - startFlash;
} while (diff != 0); } while (diff != 0);
} }
private void PerformFlash(ref byte[] data, int index, ref int flashes) private void PerformFlash(ref byte[] data, int index, ref int flashes)
{ {
flashes++; flashes++;
var y = index / 10; var y = index / 10;
var x = index % 10; var x = index % 10;
data[index] = 0; data[index] = 0;
if (x > 0) if (x > 0)
{ {
//Left //Left
index = x - 1 + y * 10; index = x - 1 + y * 10;
if (index >= 0 && data[index] != 0) if (index >= 0 && data[index] != 0)
data[index]++; data[index]++;
} }
if (x < 9) if (x < 9)
{ {
//Right //Right
index = x + 1 + y * 10; index = x + 1 + y * 10;
if (index < data.Length && data[index] != 0) if (index < data.Length && data[index] != 0)
data[index]++; data[index]++;
} }
if (y > 0) if (y > 0)
{ {
//Up //Up
index = x + 0 + (y - 1) * 10; index = x + 0 + (y - 1) * 10;
if (index >= 0 && data[index] != 0) if (index >= 0 && data[index] != 0)
data[index]++; data[index]++;
if (x > 0) if (x > 0)
{ {
//Up Left //Up Left
index = x - 1 + (y - 1) * 10; index = x - 1 + (y - 1) * 10;
if (index >= 0 && data[index] != 0) if (index >= 0 && data[index] != 0)
data[index]++; data[index]++;
} }
if (x < 9) if (x < 9)
{ {
//Up Right //Up Right
index = x + 1 + (y - 1) * 10; index = x + 1 + (y - 1) * 10;
if (index < data.Length && data[index] != 0) if (index < data.Length && data[index] != 0)
data[index]++; data[index]++;
} }
} }
if (y < 9) if (y < 9)
{ {
//Bottom //Bottom
index = x + 0 + (y + 1) * 10; index = x + 0 + (y + 1) * 10;
if (index < data.Length && data[index] != 0) if (index < data.Length && data[index] != 0)
data[index]++; data[index]++;
if (x > 0) if (x > 0)
{ {
//Bottom Left //Bottom Left
index = x - 1 + (y + 1) * 10; index = x - 1 + (y + 1) * 10;
if (index < data.Length && data[index] != 0) if (index < data.Length && data[index] != 0)
data[index]++; data[index]++;
} }
if (x < 9) if (x < 9)
{ {
//Bottom Right //Bottom Right
index = x + 1 + (y + 1) * 10; index = x + 1 + (y + 1) * 10;
if (index < data.Length && data[index] != 0) if (index < data.Length && data[index] != 0)
data[index]++; data[index]++;
} }
} }
} }
//public override string ToString() //public override string ToString()
//{ //{
// var output = new StringBuilder(); // var output = new StringBuilder();
// for (int y = 0; y < 10; y++) // for (int y = 0; y < 10; y++)
// { // {
// for (int x = 0; x < 10; x++) // for (int x = 0; x < 10; x++)
// { // {
// output.Append(DataPart1[x + y * 10]); // output.Append(DataPart1[x + y * 10]);
// } // }
// output.AppendLine(); // output.AppendLine();
// } // }
// return output.ToString(); // return output.ToString();
//} //}
//public void Render() //public void Render()
//{ //{
// for (int y = 0; y < 10; y++) // for (int y = 0; y < 10; y++)
// { // {
// for (int x = 0; x < 10; x++) // for (int x = 0; x < 10; x++)
// { // {
// var index = x + y * 10; // var index = x + y * 10;
// if (DataPart1[index] == 0) // if (DataPart1[index] == 0)
// Console.ForegroundColor = ConsoleColor.Magenta; // Console.ForegroundColor = ConsoleColor.Magenta;
// else // else
// Console.ForegroundColor = ConsoleColor.White; // Console.ForegroundColor = ConsoleColor.White;
// Console.Write(DataPart1[index]); // Console.Write(DataPart1[index]);
// } // }
// Console.WriteLine(); // Console.WriteLine();
// } // }
//} //}
} }

View File

@@ -1,71 +1,71 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2021.Day3; namespace AdventOfCode.Problems.AOC2021.Day3;
[ProblemInfo(2021, 3, "Binary Diagnostic")] [ProblemInfo(2021, 3, "Binary Diagnostic")]
public class BinaryDiagnostic : Problem<int, int> public class BinaryDiagnostic : Problem<int, int>
{ {
public int[][] Data { get; set; } = Array.Empty<int[]>(); public int[][] Data { get; set; } = Array.Empty<int[]>();
private static int ToDecimal(int[] value) private static int ToDecimal(int[] value)
{ {
return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum(); return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum();
} }
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputLines(); var data = ReadInputLines();
Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray(); Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var width = Data[0].Length; var width = Data[0].Length;
var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx])); var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx]));
var transposed2 = new int[width][]; var transposed2 = new int[width][];
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {
transposed2[i] = Data.Select(row => row[i]).ToArray(); transposed2[i] = Data.Select(row => row[i]).ToArray();
} }
var mid = Data.Length / 2; var mid = Data.Length / 2;
var gamma = transposed.Select(col => col.Count(c => c == 1) > mid ? 1 : 0).ToArray(); var gamma = transposed.Select(col => col.Count(c => c == 1) > mid ? 1 : 0).ToArray();
var epsilon = gamma.Select(b => b == 0 ? 1 : 0).ToArray(); var epsilon = gamma.Select(b => b == 0 ? 1 : 0).ToArray();
var gammaDec = ToDecimal(gamma); var gammaDec = ToDecimal(gamma);
var epsilongDec = ToDecimal(epsilon); var epsilongDec = ToDecimal(epsilon);
Part1 = gammaDec * epsilongDec; Part1 = gammaDec * epsilongDec;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var oxygen = Data; var oxygen = Data;
var index = 0; var index = 0;
while (oxygen.Length > 1) while (oxygen.Length > 1)
{ {
var t = oxygen.Select(row => row[index]); var t = oxygen.Select(row => row[index]);
var m = oxygen.Length / 2f; var m = oxygen.Length / 2f;
var g = t.Count(c => c == 1) >= m ? 1 : 0; var g = t.Count(c => c == 1) >= m ? 1 : 0;
oxygen = oxygen.Where(row => row[index] == g).ToArray(); oxygen = oxygen.Where(row => row[index] == g).ToArray();
index++; index++;
} }
var carbon = Data; var carbon = Data;
index = 0; index = 0;
while (carbon.Length > 1) while (carbon.Length > 1)
{ {
var t = carbon.Select(row => row[index]); var t = carbon.Select(row => row[index]);
var m = carbon.Length / 2f; var m = carbon.Length / 2f;
var e = t.Count(c => c == 1) < m ? 1 : 0; var e = t.Count(c => c == 1) < m ? 1 : 0;
carbon = carbon.Where(row => row[index] == e).ToArray(); carbon = carbon.Where(row => row[index] == e).ToArray();
index++; index++;
} }
var oxygenLevel = ToDecimal(oxygen.First()); var oxygenLevel = ToDecimal(oxygen.First());
var carbonLevel = ToDecimal(carbon.First()); var carbonLevel = ToDecimal(carbon.First());
Part2 = oxygenLevel * carbonLevel; Part2 = oxygenLevel * carbonLevel;
} }
} }

View File

@@ -1,50 +1,50 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2021.Day6; namespace AdventOfCode.Problems.AOC2021.Day6;
[ProblemInfo(2021, 6, "Lanternfish")] [ProblemInfo(2021, 6, "Lanternfish")]
internal class LanternFish : Problem<long, long> internal class LanternFish : Problem<long, long>
{ {
public int[] Data { get; private set; } = Array.Empty<int>(); public int[] Data { get; private set; } = Array.Empty<int>();
public override void LoadInput() public override void LoadInput()
{ {
var input = ReadInputLines(); var input = ReadInputLines();
Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray(); Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var lifetimes = PrepareLifetimes(); var lifetimes = PrepareLifetimes();
Part1 = Simulate(lifetimes, 80); Part1 = Simulate(lifetimes, 80);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var lifetimes = PrepareLifetimes(); var lifetimes = PrepareLifetimes();
Part2 = Simulate(lifetimes, 256); Part2 = Simulate(lifetimes, 256);
} }
private long[] PrepareLifetimes() private long[] PrepareLifetimes()
{ {
var lifetimes = new long[9]; var lifetimes = new long[9];
foreach (var life in Data) foreach (var life in Data)
lifetimes[life] += 1; lifetimes[life] += 1;
return lifetimes; return lifetimes;
} }
private static long Simulate(long[] lifetimes, int days) private static long Simulate(long[] lifetimes, int days)
{ {
for (int i = 0; i < days; i++) for (int i = 0; i < days; i++)
{ {
var day0Count = lifetimes[0]; var day0Count = lifetimes[0];
for (int j = 1; j < lifetimes.Length; j++) for (int j = 1; j < lifetimes.Length; j++)
lifetimes[j - 1] = lifetimes[j]; lifetimes[j - 1] = lifetimes[j];
lifetimes[6] += day0Count; lifetimes[6] += day0Count;
lifetimes[^1] = day0Count; lifetimes[^1] = day0Count;
} }
return lifetimes.Sum(); return lifetimes.Sum();
} }
} }

View File

@@ -1,32 +1,32 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day0; namespace AdventOfCode.Problems.AOC2022.Day0;
[ProblemInfo(2022, 0, "Fancy Test")] [ProblemInfo(2022, 0, "Fancy Test")]
public class TestProblem : Problem public class TestProblem : Problem
{ {
public override void LoadInput() public override void LoadInput()
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
} }
public override void PrintPart1() public override void PrintPart1()
{ {
Console.WriteLine("Result"); Console.WriteLine("Result");
} }
public override void PrintPart2() public override void PrintPart2()
{ {
Console.WriteLine("Result 2"); Console.WriteLine("Result 2");
} }
} }

View File

@@ -1,54 +1,54 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day1; namespace AdventOfCode.Problems.AOC2022.Day1;
[ProblemInfo(2022, 1, "Calorie Counting")] [ProblemInfo(2022, 1, "Calorie Counting")]
internal class CalorieCounting : Problem internal class CalorieCounting : Problem
{ {
public List<List<int>> FlaresFood { get; set; } public List<List<int>> FlaresFood { get; set; }
private (int calories, int elf)? _mostestElf; private (int calories, int elf)? _mostestElf;
private IEnumerable<(int sum, int idx)>? _mostestElves; private IEnumerable<(int sum, int idx)>? _mostestElves;
public CalorieCounting() public CalorieCounting()
{ {
FlaresFood = new List<List<int>> FlaresFood = new List<List<int>>
{ {
new List<int>() new List<int>()
}; };
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = File.ReadAllLines(GetInputFile("input.txt")); var lines = File.ReadAllLines(GetInputFile("input.txt"));
var c = 0; var c = 0;
foreach (var calorie in lines) foreach (var calorie in lines)
{ {
if (string.IsNullOrWhiteSpace(calorie)) if (string.IsNullOrWhiteSpace(calorie))
{ {
FlaresFood.Add(new List<int>()); FlaresFood.Add(new List<int>());
c++; c++;
continue; continue;
} }
FlaresFood[c].Add(int.Parse(calorie)); FlaresFood[c].Add(int.Parse(calorie));
} }
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
_mostestElf = FlaresFood _mostestElf = FlaresFood
.Select((x, idx) => (sum: x.Sum(), idx)) .Select((x, idx) => (sum: x.Sum(), idx))
.MaxBy(x => x.sum); .MaxBy(x => x.sum);
Part1 = _mostestElf.Value.ToString(); Part1 = _mostestElf.Value.ToString();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
_mostestElves = FlaresFood _mostestElves = FlaresFood
.Select((x, idx) => (sum: x.Sum(), idx)) .Select((x, idx) => (sum: x.Sum(), idx))
.OrderByDescending(e => e.sum) .OrderByDescending(e => e.sum)
.Take(3); .Take(3);
Part2 = _mostestElves.Sum(e => e.sum).ToString(); Part2 = _mostestElves.Sum(e => e.sum).ToString();
} }
} }

View File

@@ -1,66 +1,66 @@
namespace AdventOfCode.Problems.AOC2022.Day10; namespace AdventOfCode.Problems.AOC2022.Day10;
internal class CathodeCPU internal class CathodeCPU
{ {
public enum Instruction public enum Instruction
{ {
NoOp, NoOp,
AddX AddX
} }
public int X { get; private set; } = 1; public int X { get; private set; } = 1;
private int _cycleNumber = 1; private int _cycleNumber = 1;
private int _programCounter; private int _programCounter;
private int _pending = -1; private int _pending = -1;
public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func<int, int, int>? processor = null) public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func<int, int, int>? processor = null)
{ {
var result = new int[outputCycles.Length]; var result = new int[outputCycles.Length];
var ridx = 0; var ridx = 0;
if (processor == null) if (processor == null)
processor = (c, x) => c * x; processor = (c, x) => c * x;
ExecuteCode(code, (c, x) => ExecuteCode(code, (c, x) =>
{ {
if (ridx < outputCycles.Length && c == outputCycles[ridx]) if (ridx < outputCycles.Length && c == outputCycles[ridx])
{ {
result[ridx] = processor(c, x); result[ridx] = processor(c, x);
ridx++; ridx++;
} }
}); });
return result; return result;
} }
public void ExecuteCode((Instruction ins, int value)[] code, Action<int, int> processor) public void ExecuteCode((Instruction ins, int value)[] code, Action<int, int> processor)
{ {
while (_programCounter < code.Length) while (_programCounter < code.Length)
{ {
var (ins, value) = code[_programCounter]; var (ins, value) = code[_programCounter];
processor(_cycleNumber, X); processor(_cycleNumber, X);
switch ((ins, _pending)) switch ((ins, _pending))
{ {
case { ins: Instruction.NoOp }: case { ins: Instruction.NoOp }:
_programCounter++; _programCounter++;
break; break;
case { ins: Instruction.AddX, _pending: -1 }: case { ins: Instruction.AddX, _pending: -1 }:
_pending = 1; _pending = 1;
break; break;
case { ins: Instruction.AddX, _pending: 0 }: case { ins: Instruction.AddX, _pending: 0 }:
X += value; X += value;
_programCounter++; _programCounter++;
break; break;
} }
if (_pending >= 0) if (_pending >= 0)
_pending--; _pending--;
_cycleNumber++; _cycleNumber++;
} }
} }
} }

View File

@@ -1,55 +1,55 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day10; namespace AdventOfCode.Problems.AOC2022.Day10;
[ProblemInfo(2022, 10, "Cathode-Ray Tube")] [ProblemInfo(2022, 10, "Cathode-Ray Tube")]
internal class CathodeRayTube : Problem<int, string> internal class CathodeRayTube : Problem<int, string>
{ {
private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>(); private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>();
public override void CalculatePart1() public override void CalculatePart1()
{ {
var cpu = new CathodeCPU(); var cpu = new CathodeCPU();
var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 }); var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 });
Part1 = result.Sum(); Part1 = result.Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var output = Enumerable.Repeat(' ', 6 * 40).ToArray(); var output = Enumerable.Repeat(' ', 6 * 40).ToArray();
var cpu = new CathodeCPU(); var cpu = new CathodeCPU();
cpu.ExecuteCode(_code, (cycle, signal) => cpu.ExecuteCode(_code, (cycle, signal) =>
{ {
cycle -= 1; cycle -= 1;
if (cycle > output.Length) if (cycle > output.Length)
return; return;
var pos = signal % 40; var pos = signal % 40;
var head = (cycle % 40); var head = (cycle % 40);
var sprite = Math.Abs(pos - head); var sprite = Math.Abs(pos - head);
if (sprite <= 1) if (sprite <= 1)
output[cycle] = '█'; output[cycle] = '█';
}); });
var lines = output.Chunk(40).Select(r => new string(r)); var lines = output.Chunk(40).Select(r => new string(r));
Part2 = $"\n{string.Join("\n", lines)}"; Part2 = $"\n{string.Join("\n", lines)}";
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
_code = new (CathodeCPU.Instruction ins, int value)[lines.Length]; _code = new (CathodeCPU.Instruction ins, int value)[lines.Length];
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
var ln = lines[i]; var ln = lines[i];
if (ln == "noop") if (ln == "noop")
_code[i] = (CathodeCPU.Instruction.NoOp, 0); _code[i] = (CathodeCPU.Instruction.NoOp, 0);
else else
{ {
var instruction = ln.Split(' '); var instruction = ln.Split(' ');
_code[i] = (Enum.Parse<CathodeCPU.Instruction>(instruction[0], true), int.Parse(instruction[1])); _code[i] = (Enum.Parse<CathodeCPU.Instruction>(instruction[0], true), int.Parse(instruction[1]));
} }
} }
} }
} }

View File

@@ -1,73 +1,73 @@
using System.Numerics; using System.Numerics;
namespace AdventOfCode.Problems.AOC2022.Day11; namespace AdventOfCode.Problems.AOC2022.Day11;
internal class Monkey internal class Monkey
{ {
public int MonkeyNumber { get; set; } public int MonkeyNumber { get; set; }
public int InspectionCount { get; private set; } public int InspectionCount { get; private set; }
public List<BigInteger> Items { get; set; } public List<BigInteger> Items { get; set; }
private MonkeyOperator _operator; private MonkeyOperator _operator;
private uint _operand; private uint _operand;
private uint _divisor; private uint _divisor;
private int _trueTarget; private int _trueTarget;
private int _falseTarget; private int _falseTarget;
public Monkey(string[] lines) public Monkey(string[] lines)
{ {
Items = new List<BigInteger>(); Items = new List<BigInteger>();
MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]); MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]);
Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList(); Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList();
var operation = lines[2].Split("= old ")[^1]; var operation = lines[2].Split("= old ")[^1];
_operator = operation[0] switch _operator = operation[0] switch
{ {
'*' => MonkeyOperator.Multiply, '*' => MonkeyOperator.Multiply,
'+' => MonkeyOperator.Add, '+' => MonkeyOperator.Add,
_ => MonkeyOperator.Add _ => MonkeyOperator.Add
}; };
if (!uint.TryParse(operation[1..], out _operand)) if (!uint.TryParse(operation[1..], out _operand))
_operator = MonkeyOperator.Power; _operator = MonkeyOperator.Power;
_divisor = uint.Parse(lines[3].Split(' ')[^1]); _divisor = uint.Parse(lines[3].Split(' ')[^1]);
_trueTarget = int.Parse(lines[4].Split(' ')[^1]); _trueTarget = int.Parse(lines[4].Split(' ')[^1]);
_falseTarget = int.Parse(lines[5].Split(' ')[^1]); _falseTarget = int.Parse(lines[5].Split(' ')[^1]);
} }
public BigInteger Inspect(BigInteger value, uint worryOffset = 3) public BigInteger Inspect(BigInteger value, uint worryOffset = 3)
{ {
InspectionCount++; InspectionCount++;
value = Operate(value); value = Operate(value);
if (worryOffset != 0) if (worryOffset != 0)
value /= worryOffset; value /= worryOffset;
return value; return value;
} }
public int GetThrowTarget(BigInteger value) public int GetThrowTarget(BigInteger value)
{ {
return value % _divisor == 0 ? _trueTarget : _falseTarget; return value % _divisor == 0 ? _trueTarget : _falseTarget;
} }
private BigInteger Operate(BigInteger value) private BigInteger Operate(BigInteger value)
{ {
return _operator switch return _operator switch
{ {
MonkeyOperator.Multiply => value * _operand, MonkeyOperator.Multiply => value * _operand,
MonkeyOperator.Add => value + _operand, MonkeyOperator.Add => value + _operand,
MonkeyOperator.Power => value * value, MonkeyOperator.Power => value * value,
_ => value _ => value
}; };
} }
private enum MonkeyOperator private enum MonkeyOperator
{ {
Multiply, Multiply,
Add, Add,
Power Power
} }
public override string ToString() public override string ToString()
{ {
return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]"; return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]";
} }
} }

View File

@@ -1,60 +1,60 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day11; namespace AdventOfCode.Problems.AOC2022.Day11;
[ProblemInfo(2022, 11, "Monkey in the Middle")] [ProblemInfo(2022, 11, "Monkey in the Middle")]
internal class MonkeyInTheMiddle : Problem<int, int> internal class MonkeyInTheMiddle : Problem<int, int>
{ {
private Monkey[] _monkeysPart1 = Array.Empty<Monkey>(); private Monkey[] _monkeysPart1 = Array.Empty<Monkey>();
private Monkey[] _monkeysPart2 = Array.Empty<Monkey>(); private Monkey[] _monkeysPart2 = Array.Empty<Monkey>();
public override void CalculatePart1() public override void CalculatePart1()
{ {
Simulate(_monkeysPart1, 20); Simulate(_monkeysPart1, 20);
Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount) Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount)
.Take(2) .Take(2)
.Select(m => m.InspectionCount) .Select(m => m.InspectionCount)
.Aggregate((a, b) => a * b); .Aggregate((a, b) => a * b);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Simulate(_monkeysPart2, 10000, 0); Simulate(_monkeysPart2, 10000, 0);
Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount) Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount)
.Take(2) .Take(2)
.Select(m => m.InspectionCount) .Select(m => m.InspectionCount)
.Aggregate((a, b) => a * b); .Aggregate((a, b) => a * b);
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("test.txt").Chunk(7); var lines = ReadInputLines("test.txt").Chunk(7);
_monkeysPart1 = lines.Select(ln => new Monkey(ln)).ToArray(); _monkeysPart1 = lines.Select(ln => new Monkey(ln)).ToArray();
_monkeysPart2 = lines.Select(ln => new Monkey(ln)).ToArray(); _monkeysPart2 = lines.Select(ln => new Monkey(ln)).ToArray();
} }
private static void Simulate(Monkey[] monkeys, int rounds, uint worry = 3) private static void Simulate(Monkey[] monkeys, int rounds, uint worry = 3)
{ {
for (int i = 0; i < rounds; i++) for (int i = 0; i < rounds; i++)
{ {
SimulateRound(monkeys, worry); SimulateRound(monkeys, worry);
} }
} }
private static void SimulateRound(Monkey[] monkeys, uint worry = 3) private static void SimulateRound(Monkey[] monkeys, uint worry = 3)
{ {
foreach (var monkey in monkeys) foreach (var monkey in monkeys)
SimulateTurn(monkey, monkeys, worry); SimulateTurn(monkey, monkeys, worry);
} }
private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3) private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3)
{ {
for (int i = 0; i < monkey.Items.Count; i++) for (int i = 0; i < monkey.Items.Count; i++)
{ {
var item = monkey.Inspect(monkey.Items[i], worry); var item = monkey.Inspect(monkey.Items[i], worry);
var target = monkey.GetThrowTarget(item); var target = monkey.GetThrowTarget(item);
monkeys[target].Items.Add(item); monkeys[target].Items.Add(item);
} }
monkey.Items.Clear(); monkey.Items.Clear();
} }
} }

View File

@@ -1,22 +1,22 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day12; namespace AdventOfCode.Problems.AOC2022.Day12;
[ProblemInfo(2022, 12, "Hill Climbing Algorithm")] [ProblemInfo(2022, 12, "Hill Climbing Algorithm")]
internal class HillClimbing : Problem internal class HillClimbing : Problem
{ {
public override void CalculatePart1() public override void CalculatePart1()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void LoadInput() public override void LoadInput()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@@ -1,22 +1,22 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day13; namespace AdventOfCode.Problems.AOC2022.Day13;
[ProblemInfo(2022, 13, "Distress Signal")] [ProblemInfo(2022, 13, "Distress Signal")]
internal class DistressSignal : Problem internal class DistressSignal : Problem
{ {
public override void CalculatePart1() public override void CalculatePart1()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void LoadInput() public override void LoadInput()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@@ -1,22 +1,22 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day14; namespace AdventOfCode.Problems.AOC2022.Day14;
[ProblemInfo(2022, 14, "Regolith Reservoir")] [ProblemInfo(2022, 14, "Regolith Reservoir")]
internal class RegolithReservoir : Problem internal class RegolithReservoir : Problem
{ {
public override void CalculatePart1() public override void CalculatePart1()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void LoadInput() public override void LoadInput()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@@ -1,100 +1,100 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day2; namespace AdventOfCode.Problems.AOC2022.Day2;
[ProblemInfo(2022, 2, "Rock Paper Scissors")] [ProblemInfo(2022, 2, "Rock Paper Scissors")]
internal class RockPaperScissors : Problem internal class RockPaperScissors : Problem
{ {
private string[] _lines; private string[] _lines;
public RockPaperScissors() public RockPaperScissors()
{ {
_lines = Array.Empty<string>(); _lines = Array.Empty<string>();
} }
public override void LoadInput() public override void LoadInput()
{ {
_lines = File.ReadAllLines(GetInputFile("input.txt")); _lines = File.ReadAllLines(GetInputFile("input.txt"));
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var totalScore = 0; var totalScore = 0;
foreach (var line in _lines) foreach (var line in _lines)
{ {
var move = line[0]; var move = line[0];
var response = line[^1]; var response = line[^1];
totalScore += GetMoveValue(response); totalScore += GetMoveValue(response);
totalScore += GetResult(move, response); totalScore += GetResult(move, response);
} }
Part1 = totalScore.ToString(); Part1 = totalScore.ToString();
} }
private static int GetMoveValue(char move) private static int GetMoveValue(char move)
{ {
return move switch return move switch
{ {
'A' => 1, 'A' => 1,
'B' => 2, 'B' => 2,
'C' => 3, 'C' => 3,
'X' => 1, 'X' => 1,
'Y' => 2, 'Y' => 2,
'Z' => 3, 'Z' => 3,
_ => 0, _ => 0,
}; };
} }
private static int GetResult(char move, char response) private static int GetResult(char move, char response)
{ {
return (move, response) switch return (move, response) switch
{ {
('A', 'X') => 3, ('A', 'X') => 3,
('B', 'X') => 0, ('B', 'X') => 0,
('C', 'X') => 6, ('C', 'X') => 6,
('A', 'Y') => 6, ('A', 'Y') => 6,
('B', 'Y') => 3, ('B', 'Y') => 3,
('C', 'Y') => 0, ('C', 'Y') => 0,
('A', 'Z') => 0, ('A', 'Z') => 0,
('B', 'Z') => 6, ('B', 'Z') => 6,
('C', 'Z') => 3, ('C', 'Z') => 3,
_ => 0, _ => 0,
}; };
} }
private static int GetResultValue(char result) private static int GetResultValue(char result)
{ {
return result switch return result switch
{ {
'X' => 0, 'X' => 0,
'Y' => 3, 'Y' => 3,
'Z' => 6, 'Z' => 6,
_ => 0, _ => 0,
}; };
} }
private static int GetResponseValue(char move, char result) private static int GetResponseValue(char move, char result)
{ {
var p = result switch var p = result switch
{ {
'X' => (GetMoveValue(move) + 2) % 3, //Lose 'X' => (GetMoveValue(move) + 2) % 3, //Lose
'Y' => GetMoveValue(move), //Tie 'Y' => GetMoveValue(move), //Tie
'Z' => (GetMoveValue(move) + 1) % 3, //Win 'Z' => (GetMoveValue(move) + 1) % 3, //Win
_ => 0 _ => 0
}; };
return p == 0 ? 3 : p; return p == 0 ? 3 : p;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var score = 0; var score = 0;
foreach (var line in _lines) foreach (var line in _lines)
{ {
var move = line[0]; var move = line[0];
var result = line[^1]; var result = line[^1];
score += GetResponseValue(move, result); score += GetResponseValue(move, result);
score += GetResultValue(result); score += GetResultValue(result);
} }
Part2 = score.ToString(); Part2 = score.ToString();
} }
} }

View File

@@ -1,54 +1,54 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day3; namespace AdventOfCode.Problems.AOC2022.Day3;
[ProblemInfo(2022, 3, "Rucksack Reorganization")] [ProblemInfo(2022, 3, "Rucksack Reorganization")]
internal class RucksackReorganization : Problem internal class RucksackReorganization : Problem
{ {
private string[] _sacks; private string[] _sacks;
public RucksackReorganization() public RucksackReorganization()
{ {
_sacks = Array.Empty<string>(); _sacks = Array.Empty<string>();
} }
public override void LoadInput() public override void LoadInput()
{ {
_sacks = ReadInputLines("input.txt"); _sacks = ReadInputLines("input.txt");
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var total = 0; var total = 0;
foreach (var sack in _sacks) foreach (var sack in _sacks)
{ {
var mid = sack.Length / 2; var mid = sack.Length / 2;
var left = sack[..mid]; var left = sack[..mid];
var right = sack[mid..]; var right = sack[mid..];
var common = right.First(itm => left.Contains(itm)); var common = right.First(itm => left.Contains(itm));
total += GetValue(common); total += GetValue(common);
} }
Part1 = total.ToString(); Part1 = total.ToString();
} }
public static int GetValue(char c) public static int GetValue(char c)
{ {
return c switch return c switch
{ {
<= 'Z' => c - 'A' + 27, <= 'Z' => c - 'A' + 27,
_ => c - 'a' + 1 _ => c - 'a' + 1
}; };
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var groups = _sacks.Chunk(3); var groups = _sacks.Chunk(3);
var total = 0; var total = 0;
foreach (var group in groups) foreach (var group in groups)
{ {
var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge))); var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge)));
total += GetValue(badgeType); total += GetValue(badgeType);
} }
Part2 = total.ToString(); Part2 = total.ToString();
} }
} }

View File

@@ -1,63 +1,63 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day4; namespace AdventOfCode.Problems.AOC2022.Day4;
[ProblemInfo(2022, 4, "Camp Cleanup")] [ProblemInfo(2022, 4, "Camp Cleanup")]
internal class CampCleanup : Problem<int, int> internal class CampCleanup : Problem<int, int>
{ {
private List<(Range a, Range b)> _pairs = new(500); private List<(Range a, Range b)> _pairs = new(500);
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
foreach (var line in lines) foreach (var line in lines)
{ {
var (a, b) = line.Split(',') var (a, b) = line.Split(',')
.Select(range => .Select(range =>
range.Split('-') range.Split('-')
.Select(v => int.Parse(v)) .Select(v => int.Parse(v))
.Chunk(2) .Chunk(2)
.Select(r => new Range(r.First(), r.Last())) .Select(r => new Range(r.First(), r.Last()))
.First() .First()
).Chunk(2) ).Chunk(2)
.Select(pair => (pair.First(), pair.Last())) .Select(pair => (pair.First(), pair.Last()))
.First(); .First();
_pairs.Add((a, b)); _pairs.Add((a, b));
} }
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var total = 0; var total = 0;
foreach (var (a, b) in _pairs) foreach (var (a, b) in _pairs)
{ {
if (a.Contains(b) || b.Contains(a)) if (a.Contains(b) || b.Contains(a))
total++; total++;
} }
Part1 = total; Part1 = total;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
foreach (var (a, b) in _pairs) foreach (var (a, b) in _pairs)
{ {
if (a.OverlapsWith(b)) if (a.OverlapsWith(b))
Part2++; Part2++;
} }
} }
record Range(int A, int B) record Range(int A, int B)
{ {
public bool Contains(Range other) public bool Contains(Range other)
{ {
return (A <= other.A && B >= other.B); return (A <= other.A && B >= other.B);
} }
public bool OverlapsWith(Range other) public bool OverlapsWith(Range other)
{ {
return (B >= other.A && A <= other.A) || (A <= other.B && B >= other.B) || (A >= other.A && B <= other.B); return (B >= other.A && A <= other.A) || (A <= other.B && B >= other.B) || (A >= other.A && B <= other.B);
} }
public static implicit operator Range((int a, int b) value) => new(value.a, value.b); public static implicit operator Range((int a, int b) value) => new(value.a, value.b);
} }
} }

View File

@@ -1,131 +1,131 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using Superpower; using Superpower;
using Superpower.Parsers; using Superpower.Parsers;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace AdventOfCode.Problems.AOC2022.Day5; namespace AdventOfCode.Problems.AOC2022.Day5;
[ProblemInfo(2022, 5, "Supply Stacks")] [ProblemInfo(2022, 5, "Supply Stacks")]
internal partial class SupplyStacks : Problem internal partial class SupplyStacks : Problem
{ {
private List<char>[] _stacksPart1 = Array.Empty<List<char>>(); private List<char>[] _stacksPart1 = Array.Empty<List<char>>();
private List<char>[] _stacksPart2 = Array.Empty<List<char>>(); private List<char>[] _stacksPart2 = Array.Empty<List<char>>();
private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many() private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
from stack in Character.Digit.Many() from stack in Character.Digit.Many()
from frm in Character.Letter.Or(Character.WhiteSpace).Many() from frm in Character.Letter.Or(Character.WhiteSpace).Many()
from source in Character.Digit.Many() from source in Character.Digit.Many()
from to in Character.Letter.Or(Character.WhiteSpace).Many() from to in Character.Letter.Or(Character.WhiteSpace).Many()
from dst in Character.Digit.Many() from dst in Character.Digit.Many()
select (int.Parse(stack), int.Parse(source), int.Parse(dst)); select (int.Parse(stack), int.Parse(source), int.Parse(dst));
private List<(int stack, int from, int to)> _moves = new(); private List<(int stack, int from, int to)> _moves = new();
public override void CalculatePart1() public override void CalculatePart1()
{ {
foreach (var move in _moves) foreach (var move in _moves)
{ {
PerformBasicMove(_stacksPart1, move); PerformBasicMove(_stacksPart1, move);
} }
Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray()); Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
} }
private static void PerformBasicMove(List<char>[] data, (int stack, int from, int to) move) private static void PerformBasicMove(List<char>[] data, (int stack, int from, int to) move)
{ {
var from = data[move.from - 1]; var from = data[move.from - 1];
var to = data[move.to - 1]; var to = data[move.to - 1];
for (int i = 0; i < move.stack; i++) for (int i = 0; i < move.stack; i++)
{ {
var item = from[^1]; var item = from[^1];
from.RemoveAt(from.Count - 1); from.RemoveAt(from.Count - 1);
to.Add(item); to.Add(item);
} }
} }
private static void PerformMove(List<char>[] data, (int stack, int from, int to) move) private static void PerformMove(List<char>[] data, (int stack, int from, int to) move)
{ {
var from = data[move.from - 1]; var from = data[move.from - 1];
var to = data[move.to - 1]; var to = data[move.to - 1];
var items = from.Skip(from.Count - move.stack); var items = from.Skip(from.Count - move.stack);
to.AddRange(items); to.AddRange(items);
from.RemoveRange(from.Count - move.stack, move.stack); from.RemoveRange(from.Count - move.stack, move.stack);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
foreach (var move in _moves) foreach (var move in _moves)
{ {
PerformMove(_stacksPart2, move); PerformMove(_stacksPart2, move);
} }
Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray()); Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
var readMoves = false; var readMoves = false;
var buffers = new List<List<char>>(); var buffers = new List<List<char>>();
var moves = new List<(int stack, int from, int to)>(); var moves = new List<(int stack, int from, int to)>();
foreach (var line in lines) foreach (var line in lines)
{ {
if (string.IsNullOrWhiteSpace(line)) if (string.IsNullOrWhiteSpace(line))
{ {
readMoves = true; readMoves = true;
continue; continue;
} }
if (readMoves) if (readMoves)
{ {
moves.Add(ParseMoveLineRegex(line)); moves.Add(ParseMoveLineRegex(line));
} }
else else
{ {
var crates = ParseCrateLine(line); var crates = ParseCrateLine(line);
for (int i = 0; i < crates.Count; i++) for (int i = 0; i < crates.Count; i++)
{ {
var crate = crates[i]; var crate = crates[i];
if (buffers.Count == i) if (buffers.Count == i)
buffers.Add(crate == ' ' ? new() : new List<char>() { crate }); buffers.Add(crate == ' ' ? new() : new List<char>() { crate });
else if (crate != ' ') else if (crate != ' ')
buffers[i].Add(crate); buffers[i].Add(crate);
} }
} }
} }
_stacksPart1 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray(); _stacksPart1 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
_stacksPart2 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray(); _stacksPart2 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
_moves = moves; _moves = moves;
} }
//Way slower //Way slower
private (int stack, int from, int to) ParseMoveLine(string line) private (int stack, int from, int to) ParseMoveLine(string line)
{ {
return _moveParser.Parse(line); return _moveParser.Parse(line);
} }
private static (int stack, int from, int to) ParseMoveLineRegex(string line) private static (int stack, int from, int to) ParseMoveLineRegex(string line)
{ {
var r = MoveParser().Matches(line); var r = MoveParser().Matches(line);
var items = r.First() var items = r.First()
.Groups.Values.Skip(1) .Groups.Values.Skip(1)
.Select(v => int.Parse(v.ValueSpan)) .Select(v => int.Parse(v.ValueSpan))
.ToArray(); .ToArray();
return (items[0], items[1], items[2]); return (items[0], items[1], items[2]);
} }
private static List<char> ParseCrateLine(string line) private static List<char> ParseCrateLine(string line)
{ {
var result = new List<char>(line.Length / 4); var result = new List<char>(line.Length / 4);
for (int i = 1; i < line.Length; i += 4) for (int i = 1; i < line.Length; i += 4)
{ {
var c = line[i]; var c = line[i];
result.Add(c); result.Add(c);
} }
return result; return result;
} }
[GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")] [GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
private static partial Regex MoveParser(); private static partial Regex MoveParser();
} }

View File

@@ -1,35 +1,35 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day6; namespace AdventOfCode.Problems.AOC2022.Day6;
[ProblemInfo(2022, 6, "Tuning Trouble")] [ProblemInfo(2022, 6, "Tuning Trouble")]
internal class TuningTrouble : Problem<int, int> internal class TuningTrouble : Problem<int, int>
{ {
private string _input = string.Empty; private string _input = string.Empty;
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = FindMarker(4); Part1 = FindMarker(4);
} }
private int FindMarker(int size = 4) private int FindMarker(int size = 4)
{ {
for (int i = size; i < _input.Length; i++) for (int i = size; i < _input.Length; i++)
{ {
var group = _input[(i - size)..i]; var group = _input[(i - size)..i];
if (group.All(c => group.Count(gc => gc == c) == 1)) if (group.All(c => group.Count(gc => gc == c) == 1))
return i; return i;
} }
return -1; return -1;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = FindMarker(14); Part2 = FindMarker(14);
} }
public override void LoadInput() public override void LoadInput()
{ {
_input = ReadInputText(); _input = ReadInputText();
} }
} }

View File

@@ -1,121 +1,121 @@
namespace AdventOfCode.Problems.AOC2022.Day7; namespace AdventOfCode.Problems.AOC2022.Day7;
internal class DirectoryNode internal class DirectoryNode
{ {
public DirectoryNode Parent { get; set; } public DirectoryNode Parent { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string FullPath => GetFullPath(); public string FullPath => GetFullPath();
public List<DirectoryNode> Children { get; set; } public List<DirectoryNode> Children { get; set; }
public List<(string name, int size)> Files { get; set; } public List<(string name, int size)> Files { get; set; }
public int Size => Files.Sum(f => f.size) + Children.Sum(c => c.Size); public int Size => Files.Sum(f => f.size) + Children.Sum(c => c.Size);
public int LocalSize => Files.Sum(f => f.size); public int LocalSize => Files.Sum(f => f.size);
public DirectoryNode(string name) public DirectoryNode(string name)
{ {
Name = name; Name = name;
Files = new(); Files = new();
Children = new(); Children = new();
Parent = this; Parent = this;
} }
public DirectoryNode(string name, DirectoryNode parent) public DirectoryNode(string name, DirectoryNode parent)
{ {
Name = name; Name = name;
Files = new(); Files = new();
Children = new(); Children = new();
Parent = parent; Parent = parent;
} }
public DirectoryNode(string name, List<(string name, int size)> files) public DirectoryNode(string name, List<(string name, int size)> files)
{ {
Name = name; Name = name;
Files = files; Files = files;
Children = new(); Children = new();
Parent = this; Parent = this;
} }
public DirectoryNode AddDirectory(string path) public DirectoryNode AddDirectory(string path)
{ {
if (path == "/") if (path == "/")
return this; return this;
if (string.IsNullOrWhiteSpace(path)) if (string.IsNullOrWhiteSpace(path))
return this; return this;
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
if (segments.Length == 0) if (segments.Length == 0)
throw new Exception("Invalid Path?"); throw new Exception("Invalid Path?");
return AddDirectory(segments); return AddDirectory(segments);
} }
private DirectoryNode AddDirectory(string[] segments) private DirectoryNode AddDirectory(string[] segments)
{ {
var curSegment = segments[0]; var curSegment = segments[0];
var child = Children.FirstOrDefault(c => c.Name == curSegment); var child = Children.FirstOrDefault(c => c.Name == curSegment);
if (child == null) if (child == null)
{ {
var node = new DirectoryNode(curSegment, this); var node = new DirectoryNode(curSegment, this);
Children.Add(node); Children.Add(node);
if (segments.Length == 1) if (segments.Length == 1)
return node; return node;
else else
return node.AddDirectory(segments[1..]); return node.AddDirectory(segments[1..]);
} }
else else
{ {
if (segments.Length == 1) if (segments.Length == 1)
return child; return child;
return child.AddDirectory(segments[1..]); return child.AddDirectory(segments[1..]);
} }
} }
public void AddFile(string name, int size) public void AddFile(string name, int size)
{ {
Files.Add((name, size)); Files.Add((name, size));
} }
public DirectoryNode? GetDirectory(string path) public DirectoryNode? GetDirectory(string path)
{ {
if (path == "/") if (path == "/")
return this; return this;
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray(); var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
if (segments.Length == 0) if (segments.Length == 0)
throw new Exception("Invalid Path?"); throw new Exception("Invalid Path?");
return GetDirectory(segments); return GetDirectory(segments);
} }
private DirectoryNode? GetDirectory(string[] segments) private DirectoryNode? GetDirectory(string[] segments)
{ {
if (Children.Count == 0) if (Children.Count == 0)
return null; return null;
var child = Children.FirstOrDefault(c => c.Name == segments[0]); var child = Children.FirstOrDefault(c => c.Name == segments[0]);
if (child == null) if (child == null)
return null; return null;
else else
if (segments.Length == 1) if (segments.Length == 1)
return child; return child;
else else
return child.GetDirectory(segments[1..]); return child.GetDirectory(segments[1..]);
} }
public List<DirectoryNode> Where(Func<DirectoryNode, bool> filter) public List<DirectoryNode> Where(Func<DirectoryNode, bool> filter)
{ {
var result = new List<DirectoryNode>(); var result = new List<DirectoryNode>();
if (filter(this)) if (filter(this))
result.Add(this); result.Add(this);
result.AddRange(Children.SelectMany(c => c.Where(filter))); result.AddRange(Children.SelectMany(c => c.Where(filter)));
return result; return result;
} }
public string GetFullPath() public string GetFullPath()
{ {
if (Parent == this) if (Parent == this)
return ""; return "";
return $"{Parent.GetFullPath()}/{Name}"; return $"{Parent.GetFullPath()}/{Name}";
} }
public override string ToString() public override string ToString()
{ {
return $"{Name} - {Children.Count}"; return $"{Name} - {Children.Count}";
} }
} }

View File

@@ -1,75 +1,75 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day7; namespace AdventOfCode.Problems.AOC2022.Day7;
[ProblemInfo(2022, 7, "No Space Left On Device")] [ProblemInfo(2022, 7, "No Space Left On Device")]
internal class NoSpace : Problem<int, int> internal class NoSpace : Problem<int, int>
{ {
private DirectoryNode _dirTree = new DirectoryNode("/"); private DirectoryNode _dirTree = new DirectoryNode("/");
public override void CalculatePart1() public override void CalculatePart1()
{ {
var dirs = _dirTree.Where(d => d.Size <= 100000); var dirs = _dirTree.Where(d => d.Size <= 100000);
Part1 = dirs.Sum(d => d.Size); Part1 = dirs.Sum(d => d.Size);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var neededPace = 30000000; var neededPace = 30000000;
var totalSize = 70000000; var totalSize = 70000000;
var unusedSpace = totalSize - _dirTree.Size; var unusedSpace = totalSize - _dirTree.Size;
var targetSize = neededPace - unusedSpace; var targetSize = neededPace - unusedSpace;
var bigEnough = _dirTree.Where(d => d.Size >= targetSize); var bigEnough = _dirTree.Where(d => d.Size >= targetSize);
Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0; Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0;
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
var curDir = new Stack<string>(); var curDir = new Stack<string>();
var dir = "/"; var dir = "/";
foreach (var line in lines) foreach (var line in lines)
{ {
if (line[0] == '$') if (line[0] == '$')
{ {
ParseCommand(line[2..], ref curDir); ParseCommand(line[2..], ref curDir);
dir = $"/{string.Join("/", curDir.Reverse())}"; dir = $"/{string.Join("/", curDir.Reverse())}";
_dirTree.AddDirectory(dir); _dirTree.AddDirectory(dir);
} }
else else
ReadDirectory(line, _dirTree.GetDirectory(dir)!); ReadDirectory(line, _dirTree.GetDirectory(dir)!);
} }
} }
private static void ReadDirectory(string line, DirectoryNode curDir) private static void ReadDirectory(string line, DirectoryNode curDir)
{ {
if (line.StartsWith("dir")) if (line.StartsWith("dir"))
return; return;
var split = line.Split(' '); var split = line.Split(' ');
var name = split[1]; var name = split[1];
var size = int.Parse(split[0]); var size = int.Parse(split[0]);
curDir.AddFile(name, size); curDir.AddFile(name, size);
} }
private static void ParseCommand(string command, ref Stack<string> curDir) private static void ParseCommand(string command, ref Stack<string> curDir)
{ {
var split = command.Split(' '); var split = command.Split(' ');
var keyword = split.First(); var keyword = split.First();
var param = split.Last(); var param = split.Last();
switch (keyword) switch (keyword)
{ {
case "cd": case "cd":
if (param == "..") if (param == "..")
curDir.Pop(); curDir.Pop();
else if (param == "/") else if (param == "/")
curDir.Clear(); curDir.Clear();
else else
curDir.Push(param); curDir.Push(param);
break; break;
} }
} }
} }

View File

@@ -1,99 +1,99 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day8; namespace AdventOfCode.Problems.AOC2022.Day8;
[ProblemInfo(2022, 8, "Treetop Tree House")] [ProblemInfo(2022, 8, "Treetop Tree House")]
internal class TreetopTreeHouse : Problem<int, int> internal class TreetopTreeHouse : Problem<int, int>
{ {
private int[][] _input = Array.Empty<int[]>(); private int[][] _input = Array.Empty<int[]>();
private int _height; private int _height;
private int _width; private int _width;
public override void CalculatePart1() public override void CalculatePart1()
{ {
for (int y = 1; y < _height - 1; y++) for (int y = 1; y < _height - 1; y++)
{ {
for (int x = 1; x < _width - 1; x++) for (int x = 1; x < _width - 1; x++)
{ {
Part1 += IsVisible(x, y) ? 1 : 0; Part1 += IsVisible(x, y) ? 1 : 0;
} }
} }
Part1 += _height * 2 + _width * 2 - 4; Part1 += _height * 2 + _width * 2 - 4;
} }
private bool IsVisible(int x, int y) private bool IsVisible(int x, int y)
{ {
return IsVisibleColumn(x, y) || IsVisibleRow(x, y); return IsVisibleColumn(x, y) || IsVisibleRow(x, y);
} }
private bool IsVisibleColumn(int col, int row) private bool IsVisibleColumn(int col, int row)
{ {
var tree = _input[row][col]; var tree = _input[row][col];
var columnOfTrees = _input.Select(r => r[col]); var columnOfTrees = _input.Select(r => r[col]);
var above = columnOfTrees.Take(row); var above = columnOfTrees.Take(row);
var below = columnOfTrees.Skip(row + 1); var below = columnOfTrees.Skip(row + 1);
return above.All(t => t < tree) || below.All(t => t < tree); return above.All(t => t < tree) || below.All(t => t < tree);
} }
private bool IsVisibleRow(int col, int row) private bool IsVisibleRow(int col, int row)
{ {
var tree = _input[row][col]; var tree = _input[row][col];
var rowOfTrees = _input[row]; var rowOfTrees = _input[row];
var left = rowOfTrees.Take(col); var left = rowOfTrees.Take(col);
var right = rowOfTrees.Skip(col + 1); var right = rowOfTrees.Skip(col + 1);
return left.All(t => t < tree) || right.All(t => t < tree); return left.All(t => t < tree) || right.All(t => t < tree);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = int.MinValue; Part2 = int.MinValue;
for (int y = 1; y < _height - 1; y++) for (int y = 1; y < _height - 1; y++)
{ {
for (int x = 1; x < _width - 1; x++) for (int x = 1; x < _width - 1; x++)
{ {
var v = GetScenicScore(x, y); var v = GetScenicScore(x, y);
if (Part2 < v) if (Part2 < v)
Part2 = v; Part2 = v;
} }
} }
} }
public int GetScenicScore(int row, int col) public int GetScenicScore(int row, int col)
{ {
var tree = _input[row][col]; var tree = _input[row][col];
var columnOfTrees = _input.Select(r => r[col]); var columnOfTrees = _input.Select(r => r[col]);
var rowOfTrees = _input[row]; var rowOfTrees = _input[row];
var above = columnOfTrees.Take(row).Reverse(); var above = columnOfTrees.Take(row).Reverse();
var below = columnOfTrees.Skip(row + 1); var below = columnOfTrees.Skip(row + 1);
var left = rowOfTrees.Take(col).Reverse(); var left = rowOfTrees.Take(col).Reverse();
var right = rowOfTrees.Skip(col + 1); var right = rowOfTrees.Skip(col + 1);
var score = above.Select((t, idx) => (t, idx)) var score = above.Select((t, idx) => (t, idx))
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1; .FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1;
score *= below.Select((t, idx) => (t, idx)) score *= below.Select((t, idx) => (t, idx))
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1; .FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1;
score *= left.Select((t, idx) => (t, idx)) score *= left.Select((t, idx) => (t, idx))
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1; .FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1;
score *= right.Select((t, idx) => (t, idx)) score *= right.Select((t, idx) => (t, idx))
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1; .FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1;
return score; return score;
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
_input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray(); _input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray();
_height = _input.Length; _height = _input.Length;
_width = _input[0].Length; _width = _input[0].Length;
} }
} }

View File

@@ -1,31 +1,31 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2022.Day9; namespace AdventOfCode.Problems.AOC2022.Day9;
[ProblemInfo(2022, 9, "Rope Bridge")] [ProblemInfo(2022, 9, "Rope Bridge")]
internal class RopeBridge : Problem<int, int> internal class RopeBridge : Problem<int, int>
{ {
private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>(); private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>();
public override void CalculatePart1() public override void CalculatePart1()
{ {
var sim = new RopeSimulator(_moves); var sim = new RopeSimulator(_moves);
sim.Simulate(); sim.Simulate();
Part1 = sim.Visited; Part1 = sim.Visited;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var sim = new RopeSimulator(_moves, 9); var sim = new RopeSimulator(_moves, 9);
sim.Simulate(); sim.Simulate();
Part2 = sim.Visited; Part2 = sim.Visited;
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
_moves = lines.Select(ln => ln.Split(' ')) _moves = lines.Select(ln => ln.Split(' '))
.Select(move => (Enum.Parse<RopeSimulator.Direction>(move.First()), int.Parse(move.Last()))) .Select(move => (Enum.Parse<RopeSimulator.Direction>(move.First()), int.Parse(move.Last())))
.ToArray(); .ToArray();
} }
} }

View File

@@ -1,146 +1,146 @@
namespace AdventOfCode.Problems.AOC2022.Day9; namespace AdventOfCode.Problems.AOC2022.Day9;
public class RopeSimulator public class RopeSimulator
{ {
public int Visited => _visited.Count; public int Visited => _visited.Count;
private readonly (Direction dir, int ammount)[] _movement; private readonly (Direction dir, int ammount)[] _movement;
private readonly bool _render; private readonly bool _render;
public enum Direction public enum Direction
{ {
L, L,
R, R,
U, U,
D D
} }
private (int x, int y) _head; private (int x, int y) _head;
private (int x, int y)[] _segments; private (int x, int y)[] _segments;
private Dictionary<(int x, int y), int> _visited; private Dictionary<(int x, int y), int> _visited;
public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false) public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false)
{ {
_movement = movement; _movement = movement;
_render = render; _render = render;
_visited = new Dictionary<(int x, int y), int>() _visited = new Dictionary<(int x, int y), int>()
{ {
{ (0,0), 1 } { (0,0), 1 }
}; };
_head = (0, 0); _head = (0, 0);
_segments = Enumerable.Repeat((0, 0), segments).ToArray(); _segments = Enumerable.Repeat((0, 0), segments).ToArray();
} }
public void Simulate() public void Simulate()
{ {
foreach (var (dir, ammount) in _movement) foreach (var (dir, ammount) in _movement)
{ {
ProcessStep(dir, ammount); ProcessStep(dir, ammount);
} }
} }
private void ProcessStep(Direction dir, int ammount) private void ProcessStep(Direction dir, int ammount)
{ {
for (int i = 0; i < ammount; i++) for (int i = 0; i < ammount; i++)
{ {
switch (dir) switch (dir)
{ {
case Direction.L: case Direction.L:
_head.x--; _head.x--;
break; break;
case Direction.R: case Direction.R:
_head.x++; _head.x++;
break; break;
case Direction.U: case Direction.U:
_head.y++; _head.y++;
break; break;
case Direction.D: case Direction.D:
_head.y--; _head.y--;
break; break;
} }
FollowHead(); FollowHead();
var tail = _segments.Last(); var tail = _segments.Last();
if (_visited.ContainsKey(tail)) if (_visited.ContainsKey(tail))
_visited[tail]++; _visited[tail]++;
else else
_visited.Add(tail, 1); _visited.Add(tail, 1);
} }
} }
private void FollowHead() private void FollowHead()
{ {
var curHead = _head; var curHead = _head;
for (int i = 0; i < _segments.Length; i++) for (int i = 0; i < _segments.Length; i++)
{ {
var tail = _segments[i]; var tail = _segments[i];
curHead = _segments[i] = FollowSegment(curHead, tail); curHead = _segments[i] = FollowSegment(curHead, tail);
} }
if (_render) if (_render)
{ {
DrawScene(); DrawScene();
Console.ReadKey(); Console.ReadKey();
} }
} }
private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail) private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail)
{ {
var xDist = head.x - tail.x; var xDist = head.x - tail.x;
var yDist = head.y - tail.y; var yDist = head.y - tail.y;
if (xDist * xDist + yDist * yDist < 4) if (xDist * xDist + yDist * yDist < 4)
return tail; return tail;
if (xDist > 1) if (xDist > 1)
head.x -= 1; head.x -= 1;
if (xDist < -1) if (xDist < -1)
head.x += 1; head.x += 1;
if (yDist > 1) if (yDist > 1)
head.y -= 1; head.y -= 1;
if (yDist < -1) if (yDist < -1)
head.y += 1; head.y += 1;
return head; return head;
} }
private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail) private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail)
{ {
var xDist = Math.Abs(head.x - tail.x); var xDist = Math.Abs(head.x - tail.x);
var yDist = Math.Abs(head.y - tail.y); var yDist = Math.Abs(head.y - tail.y);
return (xDist > 1 || yDist > 1); return (xDist > 1 || yDist > 1);
} }
private void DrawScene(int segment = -1) private void DrawScene(int segment = -1)
{ {
var upperX = Math.Max(_head.x, _segments.MaxBy(s => s.x).x); var upperX = Math.Max(_head.x, _segments.MaxBy(s => s.x).x);
var upperY = Math.Max(_head.y, _segments.MaxBy(s => s.y).y); var upperY = Math.Max(_head.y, _segments.MaxBy(s => s.y).y);
var lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y); var lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y);
var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y); var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y);
var width = upperX - lowerX; var width = upperX - lowerX;
var height = upperY - lowerY; var height = upperY - lowerY;
Console.Clear(); Console.Clear();
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Draw('s', (0, 0), lowerX, upperY); Draw('s', (0, 0), lowerX, upperY);
Draw('H', _head, lowerX, upperY); Draw('H', _head, lowerX, upperY);
for (int i = _segments.Length - 1; i >= 0; i--) for (int i = _segments.Length - 1; i >= 0; i--)
{ {
if (segment == i) if (segment == i)
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
else else
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY); Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY);
} }
} }
private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY) private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY)
{ {
Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY); Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY);
Console.WriteLine(c); Console.WriteLine(c);
} }
} }

View File

@@ -1,97 +1,97 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2023.Day1; namespace AdventOfCode.Problems.AOC2023.Day1;
[ProblemInfo(2023, 1, "Trebuchet!?")] [ProblemInfo(2023, 1, "Trebuchet!?")]
public partial class Trebuchet : Problem<int, int> public partial class Trebuchet : Problem<int, int>
{ {
private string[] _inputData = []; private string[] _inputData = [];
public override void LoadInput() public override void LoadInput()
{ {
_inputData = ReadInputLines(); _inputData = ReadInputLines();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = _inputData.Select(GetCalibrationValues) Part1 = _inputData.Select(GetCalibrationValues)
.Select(cv => cv.left * 10 + cv.right) .Select(cv => cv.left * 10 + cv.right)
.Sum(); .Sum();
} }
private (int left, int right) GetCalibrationValues(string line) private (int left, int right) GetCalibrationValues(string line)
{ {
var (left, right) = (0, 0); var (left, right) = (0, 0);
for (int i = 0; i < line.Length; i++) for (int i = 0; i < line.Length; i++)
{ {
if (line[i] - '0' >= 10) if (line[i] - '0' >= 10)
continue; continue;
left = line[i] - '0'; left = line[i] - '0';
break; break;
} }
for (int i = line.Length - 1; i >= 0; i--) for (int i = line.Length - 1; i >= 0; i--)
{ {
if (line[i] - '0' >= 10) if (line[i] - '0' >= 10)
continue; continue;
right = line[i] - '0'; right = line[i] - '0';
break; break;
} }
return (left, right); return (left, right);
} }
private readonly (string word, int value)[] _numberWords = new[] private readonly (string word, int value)[] _numberWords = new[]
{ {
("one", 1), ("one", 1),
("two", 2), ("two", 2),
("three", 3), ("three", 3),
("four", 4), ("four", 4),
("five", 5), ("five", 5),
("six", 6), ("six", 6),
("seven", 7), ("seven", 7),
("eight", 8), ("eight", 8),
("nine", 9) ("nine", 9)
}; };
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = _inputData.Select(GetNamedCalibrationValues) Part2 = _inputData.Select(GetNamedCalibrationValues)
.Select(cv => cv.left * 10 + cv.right) .Select(cv => cv.left * 10 + cv.right)
.Sum(); .Sum();
} }
private (int left, int right) GetNamedCalibrationValues(string line) private (int left, int right) GetNamedCalibrationValues(string line)
{ {
var (left, right) = (0, 0); var (left, right) = (0, 0);
for (int i = 0; i < line.Length; i++) for (int i = 0; i < line.Length; i++)
{ {
var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value; var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
if (word != -1) if (word != -1)
{ {
left = word; left = word;
break; break;
} }
else if (line[i] - '0' >= 10) else if (line[i] - '0' >= 10)
continue; continue;
left = line[i] - '0'; left = line[i] - '0';
break; break;
} }
for (int i = line.Length - 1; i >= 0; i--) for (int i = line.Length - 1; i >= 0; i--)
{ {
var word = _numberWords.FirstOrDefault(v => line[..(i + 1)].EndsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value; var word = _numberWords.FirstOrDefault(v => line[..(i + 1)].EndsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
if (word != -1) if (word != -1)
{ {
right = word; right = word;
break; break;
} }
else if (line[i] - '0' >= 10) else if (line[i] - '0' >= 10)
continue; continue;
right = line[i] - '0'; right = line[i] - '0';
break; break;
} }
return (left, right); return (left, right);
} }
} }

View File

@@ -1,106 +1,106 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day10; namespace AdventOfCode.Problems.AOC2023.Day10;
[ProblemInfo(2023, 10, "Pipe Maze")] [ProblemInfo(2023, 10, "Pipe Maze")]
internal class PipeMaze : Problem<int, int> internal class PipeMaze : Problem<int, int>
{ {
private string[] _maze = []; private string[] _maze = [];
public override void LoadInput() public override void LoadInput()
{ {
_maze = ReadInputLines(); _maze = ReadInputLines();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var start = GetStartPointPos(); var start = GetStartPointPos();
var nPoints = GetStartConnections(start); var nPoints = GetStartConnections(start);
var seen = new Dictionary<(int, int), int>(); var seen = new Dictionary<(int, int), int>();
foreach (var point in nPoints) foreach (var point in nPoints)
{ {
var curPoint = start; var curPoint = start;
var prevPoint = point; var prevPoint = point;
var dist = 0; var dist = 0;
while (true) while (true)
{ {
dist++; dist++;
var next = GetNextPoint(curPoint, prevPoint); var next = GetNextPoint(curPoint, prevPoint);
prevPoint = curPoint; prevPoint = curPoint;
curPoint = next; curPoint = next;
if (next == start) if (next == start)
break; break;
if (seen.TryGetValue(next, out var d)) if (seen.TryGetValue(next, out var d))
{ {
if (d > dist) if (d > dist)
seen[next] = dist; seen[next] = dist;
else else
break; break;
} }
else else
seen.Add(next, dist); seen.Add(next, dist);
} }
} }
Part1 = seen.Values.Max(); Part1 = seen.Values.Max();
} }
private (int x, int y) GetStartPointPos() private (int x, int y) GetStartPointPos()
{ {
for (int y = 0; y < _maze.Length; y++) for (int y = 0; y < _maze.Length; y++)
{ {
var x = _maze[y].IndexOf('S'); var x = _maze[y].IndexOf('S');
if (x >= 0) if (x >= 0)
return (x, y); return (x, y);
} }
throw new Exception("Start point not found"); throw new Exception("Start point not found");
} }
private List<(int x, int y)> GetStartConnections((int x, int y) pos) private List<(int x, int y)> GetStartConnections((int x, int y) pos)
{ {
var points = new List<(int x, int y)>(); var points = new List<(int x, int y)>();
if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L') if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L')
points.Add((pos.x + 1, pos.y)); points.Add((pos.x + 1, pos.y));
if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7') if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7')
points.Add((pos.x - 1, pos.y)); points.Add((pos.x - 1, pos.y));
if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7') if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7')
points.Add((pos.x, pos.y + 1)); points.Add((pos.x, pos.y + 1));
if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L') if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L')
points.Add((pos.x, pos.y - 1)); points.Add((pos.x, pos.y - 1));
return points; return points;
} }
private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev) private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev)
{ {
var curPipe = _maze[pos.y][pos.x]; var curPipe = _maze[pos.y][pos.x];
(int x, int y) = (pos.x - prev.x, pos.y - prev.y); (int x, int y) = (pos.x - prev.x, pos.y - prev.y);
if (curPipe == 'S') if (curPipe == 'S')
return GetStartConnections(pos).First(p => p != prev); return GetStartConnections(pos).First(p => p != prev);
return curPipe switch return curPipe switch
{ {
'|' => (pos.x, pos.y + y), '|' => (pos.x, pos.y + y),
'-' => (pos.x + x, pos.y), '-' => (pos.x + x, pos.y),
'L' => (pos.x + y, pos.y + x), 'L' => (pos.x + y, pos.y + x),
'F' => (pos.x - y, pos.y - x), 'F' => (pos.x - y, pos.y - x),
'J' => (pos.x - y, pos.y - x), 'J' => (pos.x - y, pos.y - x),
'7' => (pos.x + y, pos.y + x), '7' => (pos.x + y, pos.y + x),
_ => throw new Exception() _ => throw new Exception()
}; };
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@@ -1,89 +1,89 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day11; namespace AdventOfCode.Problems.AOC2023.Day11;
[ProblemInfo(2023, 11, "Cosmic Expansion")] [ProblemInfo(2023, 11, "Cosmic Expansion")]
internal class CosmicExpansion : Problem<int, long> internal class CosmicExpansion : Problem<int, long>
{ {
private string[] _data = []; private string[] _data = [];
private int[] _yGaps = []; private int[] _yGaps = [];
private int[] _xGaps = []; private int[] _xGaps = [];
public override void CalculatePart1() public override void CalculatePart1()
{ {
var points = GetPoints().Select(p => Inflate(p, 2)).ToList(); var points = GetPoints().Select(p => Inflate(p, 2)).ToList();
for (int i = 0; i < points.Count - 1; i++) for (int i = 0; i < points.Count - 1; i++)
{ {
for (int j = i + 1; j < points.Count; j++) for (int j = i + 1; j < points.Count; j++)
{ {
var a = points[i]; var a = points[i];
var b = points[j]; var b = points[j];
Part1 += GetDistance(a, b); Part1 += GetDistance(a, b);
} }
} }
} }
public List<(int x, int y)> GetPoints() public List<(int x, int y)> GetPoints()
{ {
var result = new List<(int x, int y)>(); var result = new List<(int x, int y)>();
for (int y = 0; y < _data.Length; y++) for (int y = 0; y < _data.Length; y++)
{ {
for (int x = 0; x < _data[0].Length; x++) for (int x = 0; x < _data[0].Length; x++)
{ {
if (_data[y][x] == '#') if (_data[y][x] == '#')
result.Add((x, y)); result.Add((x, y));
} }
} }
return result; return result;
} }
public int GetDistance((int x, int y) a, (int x, int y) b) public int GetDistance((int x, int y) a, (int x, int y) b)
{ {
var xDist = Math.Abs(a.x - b.x); var xDist = Math.Abs(a.x - b.x);
var yDist = Math.Abs(a.y - b.y); var yDist = Math.Abs(a.y - b.y);
return xDist + yDist; return xDist + yDist;
} }
public (int x, int y) Inflate((int x, int y) point, int factor) public (int x, int y) Inflate((int x, int y) point, int factor)
{ {
factor -= 1; factor -= 1;
var cX = _xGaps.Count(x => point.x >= x); var cX = _xGaps.Count(x => point.x >= x);
var cY = _yGaps.Count(y => point.y >= y); var cY = _yGaps.Count(y => point.y >= y);
return (point.x + cX * factor, point.y + cY * factor); return (point.x + cX * factor, point.y + cY * factor);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList(); var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList();
for (int i = 0; i < points.Count - 1; i++) for (int i = 0; i < points.Count - 1; i++)
{ {
for (int j = i + 1; j < points.Count; j++) for (int j = i + 1; j < points.Count; j++)
{ {
var a = points[i]; var a = points[i];
var b = points[j]; var b = points[j];
Part2 += GetDistance(a, b); Part2 += GetDistance(a, b);
} }
} }
} }
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputLines(); _data = ReadInputLines();
_yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i)) _yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i))
.Where(v => v.c == _data[0].Length) .Where(v => v.c == _data[0].Length)
.Select(v => v.i) .Select(v => v.i)
.ToArray(); .ToArray();
_xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i)) _xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i))
.Where(v => v.c == _data[0].Length) .Where(v => v.c == _data[0].Length)
.Select(v => v.i) .Select(v => v.i)
.ToArray(); .ToArray();
} }
} }

View File

@@ -1,111 +1,111 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day12; namespace AdventOfCode.Problems.AOC2023.Day12;
[ProblemInfo(2023, 12, "Hot Springs")] [ProblemInfo(2023, 12, "Hot Springs")]
internal class HotSprings : Problem<int, int> internal class HotSprings : Problem<int, int>
{ {
private Record[] _data = []; private Record[] _data = [];
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = _data.Select(r => CountPossiblilites(r)).Sum(); Part1 = _data.Select(r => CountPossiblilites(r)).Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var unfolded = _data.Select(r => var unfolded = _data.Select(r =>
{ {
var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5)); var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5));
var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray(); var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray();
return new Record(unfoldData, unfoldPattern); return new Record(unfoldData, unfoldPattern);
}).ToArray(); }).ToArray();
Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum(); Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum();
} }
public static int CountPossiblilites(Record record, int pos = 0) public static int CountPossiblilites(Record record, int pos = 0)
{ {
if (pos == -1 || pos >= record.Data.Length) if (pos == -1 || pos >= record.Data.Length)
return record.IsValid ? 1 : 0; return record.IsValid ? 1 : 0;
if (!record.IsValid) if (!record.IsValid)
return 0; return 0;
if (record.Data[pos] != '?') if (record.Data[pos] != '?')
return CountPossiblilites(record, record.Data.IndexOf('?')); return CountPossiblilites(record, record.Data.IndexOf('?'));
var front = record.Data[..pos]; var front = record.Data[..pos];
var back = record.Data[(pos + 1)..]; var back = record.Data[(pos + 1)..];
var r1 = record with { Data = $"{front}.{back}" }; var r1 = record with { Data = $"{front}.{back}" };
var r2 = record with { Data = $"{front}#{back}" }; var r2 = record with { Data = $"{front}#{back}" };
return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1); return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1);
} }
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputLines(); var data = ReadInputLines();
_data = data.Select(x => x.Split(' ')) _data = data.Select(x => x.Split(' '))
.Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray())) .Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray()))
.ToArray(); .ToArray();
} }
public record Record(string Data, int[] Pattern) public record Record(string Data, int[] Pattern)
{ {
public bool IsValid => CheckValidity(this); public bool IsValid => CheckValidity(this);
public static bool CheckValidity(Record record) public static bool CheckValidity(Record record)
{ {
var section = 0; var section = 0;
var start = 0; var start = 0;
var inSection = false; var inSection = false;
for (int i = 0; i < record.Data.Length; i++) for (int i = 0; i < record.Data.Length; i++)
{ {
var c = record.Data[i]; var c = record.Data[i];
if (section >= record.Pattern.Length) if (section >= record.Pattern.Length)
return !record.Data[i..].Contains('#'); return !record.Data[i..].Contains('#');
var len = record.Pattern[section]; var len = record.Pattern[section];
switch (c) switch (c)
{ {
case '?': case '?':
if (inSection && i - start > len) if (inSection && i - start > len)
return false; return false;
return true; return true;
case '.': case '.':
if (inSection) if (inSection)
{ {
if (i - start != len) if (i - start != len)
return false; return false;
inSection = false; inSection = false;
start = 0; start = 0;
section++; section++;
} }
continue; continue;
case '#': case '#':
if (!inSection) if (!inSection)
{ {
inSection = true; inSection = true;
start = i; start = i;
} }
break; break;
} }
} }
if (inSection) if (inSection)
{ {
if (record.Pattern[section] != (record.Data[start..].Length)) if (record.Pattern[section] != (record.Data[start..].Length))
return false; return false;
else else
section++; section++;
} }
if (section != record.Pattern.Length) if (section != record.Pattern.Length)
return false; return false;
return true; return true;
} }
}; };
} }

View File

@@ -1,31 +1,31 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2023.Day2; namespace AdventOfCode.Problems.AOC2023.Day2;
[ProblemInfo(2023, 2, "Cube Conundrum")] [ProblemInfo(2023, 2, "Cube Conundrum")]
internal class CubeConundrum : Problem<int, int> internal class CubeConundrum : Problem<int, int>
{ {
private CubeGame[] _gameInfo = []; private CubeGame[] _gameInfo = [];
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines(); var lines = ReadInputLines();
_gameInfo = lines.Select(l => new CubeGame(l)).ToArray(); _gameInfo = lines.Select(l => new CubeGame(l)).ToArray();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum(); Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum(); Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum();
} }
public IEnumerable<int> FindPossibleGames(CubeRound constraints) public IEnumerable<int> FindPossibleGames(CubeRound constraints)
{ {
return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints))) return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints)))
.Select(r => r.Id); .Select(r => r.Id);
} }
} }

View File

@@ -1,81 +1,81 @@
namespace AdventOfCode.Problems.AOC2023.Day2; namespace AdventOfCode.Problems.AOC2023.Day2;
internal class CubeGame internal class CubeGame
{ {
public CubeRound[] Rounds { get; } public CubeRound[] Rounds { get; }
public int Id { get; } public int Id { get; }
public CubeGame(string line) public CubeGame(string line)
{ {
var info = line.Split(':'); var info = line.Split(':');
Id = int.Parse(info[0].Split(' ')[^1]); Id = int.Parse(info[0].Split(' ')[^1]);
var roundsData = info[1].Split(';'); var roundsData = info[1].Split(';');
Rounds = new CubeRound[roundsData.Length]; Rounds = new CubeRound[roundsData.Length];
for (int i = 0; i < roundsData.Length; i++) for (int i = 0; i < roundsData.Length; i++)
Rounds[i] = CubeRound.ParseRound(roundsData[i]); Rounds[i] = CubeRound.ParseRound(roundsData[i]);
} }
public CubeRound GetMinimalConstraints() public CubeRound GetMinimalConstraints()
{ {
var (r, g, b) = (0, 0, 0); var (r, g, b) = (0, 0, 0);
foreach (var round in Rounds) foreach (var round in Rounds)
{ {
if (round.Red > r) if (round.Red > r)
r = round.Red; r = round.Red;
if (round.Green > g) if (round.Green > g)
g = round.Green; g = round.Green;
if (round.Blue > b) if (round.Blue > b)
b = round.Blue; b = round.Blue;
} }
return new CubeRound(r, g, b); return new CubeRound(r, g, b);
} }
} }
internal record struct CubeRound(int Red, int Green, int Blue) internal record struct CubeRound(int Red, int Green, int Blue)
{ {
public static CubeRound ParseRound(string round) public static CubeRound ParseRound(string round)
{ {
var cubes = round.Split(','); var cubes = round.Split(',');
var (r, g, b) = (0, 0, 0); var (r, g, b) = (0, 0, 0);
foreach (var cube in cubes) foreach (var cube in cubes)
{ {
var info = cube.TrimStart().Split(' '); var info = cube.TrimStart().Split(' ');
var count = int.Parse(info[0]); var count = int.Parse(info[0]);
switch (info[1]) switch (info[1])
{ {
case ['r', ..]: case ['r', ..]:
r = count; r = count;
break; break;
case ['g', ..]: case ['g', ..]:
g = count; g = count;
break; break;
case ['b', ..]: case ['b', ..]:
b = count; b = count;
break; break;
} }
} }
return new CubeRound(r, g, b); return new CubeRound(r, g, b);
} }
public readonly bool IsPossible(CubeRound constraints) public readonly bool IsPossible(CubeRound constraints)
{ {
if (Red > constraints.Red) if (Red > constraints.Red)
return false; return false;
if (Green > constraints.Green) if (Green > constraints.Green)
return false; return false;
if (Blue > constraints.Blue) if (Blue > constraints.Blue)
return false; return false;
return true; return true;
} }
public readonly int Power() public readonly int Power()
{ {
return Red * Green * Blue; return Red * Green * Blue;
} }
}; };

View File

@@ -1,136 +1,136 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
namespace AdventOfCode.Problems.AOC2023.Day3; namespace AdventOfCode.Problems.AOC2023.Day3;
[ProblemInfo(2023, 3, "Gear Ratios")] [ProblemInfo(2023, 3, "Gear Ratios")]
internal class GearRatios : Problem<int, int> internal class GearRatios : Problem<int, int>
{ {
private string[] _data = []; private string[] _data = [];
private int _width; private int _width;
private int _height; private int _height;
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputLines(); _data = ReadInputLines();
_width = _data[0].Length - 1; _width = _data[0].Length - 1;
_height = _data.Length - 1; _height = _data.Length - 1;
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var partNumbers = new List<int>(); var partNumbers = new List<int>();
for (int y = 0; y < _height; y++) for (int y = 0; y < _height; y++)
{ {
for (int x = 0; x <= _width; x++) for (int x = 0; x <= _width; x++)
{ {
var cell = _data[y][x]; var cell = _data[y][x];
switch (cell) switch (cell)
{ {
case '.': case '.':
continue; continue;
case < '0' or > '9': case < '0' or > '9':
FindNumbers(x, y, ref partNumbers); FindNumbers(x, y, ref partNumbers);
break; break;
} }
} }
} }
Part1 = partNumbers.Sum(); Part1 = partNumbers.Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var ratios = new List<int>(); var ratios = new List<int>();
var curNums = new List<int>(); var curNums = new List<int>();
for (int y = 0; y < _height; y++) for (int y = 0; y < _height; y++)
{ {
for (int x = 0; x <= _width; x++) for (int x = 0; x <= _width; x++)
{ {
var cell = _data[y][x]; var cell = _data[y][x];
switch (cell) switch (cell)
{ {
case '*': case '*':
curNums.Clear(); curNums.Clear();
FindNumbers(x, y, ref curNums); FindNumbers(x, y, ref curNums);
if (curNums.Count == 2) if (curNums.Count == 2)
ratios.Add(curNums[0] * curNums[1]); ratios.Add(curNums[0] * curNums[1]);
break; break;
} }
} }
} }
Part2 = ratios.Sum(); Part2 = ratios.Sum();
} }
public void FindNumbers(int x, int y, ref List<int> results) public void FindNumbers(int x, int y, ref List<int> results)
{ {
var seen = new HashSet<(int x, int y)>(); var seen = new HashSet<(int x, int y)>();
var n = GetNeighborPoints(x, y); var n = GetNeighborPoints(x, y);
foreach (var (xN, yN) in n) foreach (var (xN, yN) in n)
{ {
var c = _data[yN][xN] - '0'; var c = _data[yN][xN] - '0';
if (c >= 0) //A bug exists here, I wont fix it if (c >= 0) //A bug exists here, I wont fix it
{ {
var num = GetNumber(xN, yN, out var idx); var num = GetNumber(xN, yN, out var idx);
if (seen.Contains(idx)) if (seen.Contains(idx))
continue; continue;
seen.Add(idx); seen.Add(idx);
results.Add(num); results.Add(num);
} }
} }
} }
public List<(int x, int y)> GetNeighborPoints(int x, int y) public List<(int x, int y)> GetNeighborPoints(int x, int y)
{ {
var points = new List<(int x, int y)>(); var points = new List<(int x, int y)>();
if (x > 0) if (x > 0)
points.Add((x - 1, y)); points.Add((x - 1, y));
if (x < _width) if (x < _width)
points.Add((x + 1, y)); points.Add((x + 1, y));
if (y > 0) if (y > 0)
points.Add((x, y - 1)); points.Add((x, y - 1));
if (y < _height) if (y < _height)
points.Add((x, y + 1)); points.Add((x, y + 1));
if (x > 0 && y > 0) if (x > 0 && y > 0)
points.Add((x - 1, y - 1)); points.Add((x - 1, y - 1));
if (x > 0 && y < _height) if (x > 0 && y < _height)
points.Add((x - 1, y + 1)); points.Add((x - 1, y + 1));
if (x < _width && y < _height) if (x < _width && y < _height)
points.Add((x + 1, y + 1)); points.Add((x + 1, y + 1));
if (x < _width && y > 0) if (x < _width && y > 0)
points.Add((x + 1, y - 1)); points.Add((x + 1, y - 1));
return points; return points;
} }
public int GetNumber(int x, int y, out (int iX, int iY) index) public int GetNumber(int x, int y, out (int iX, int iY) index)
{ {
var row = _data[y]; var row = _data[y];
var numStart = 0; var numStart = 0;
var numEnd = _width + 1; var numEnd = _width + 1;
for (int i = x; i >= 0; i--) for (int i = x; i >= 0; i--)
{ {
switch (row[i]) switch (row[i])
{ {
case < '0' or > '9': case < '0' or > '9':
numStart = i + 1; numStart = i + 1;
goto leftDone; goto leftDone;
} }
} }
leftDone: leftDone:
for (int i = x; i <= _width; i++) for (int i = x; i <= _width; i++)
{ {
switch (row[i]) switch (row[i])
{ {
case < '0' or > '9': case < '0' or > '9':
numEnd = i; numEnd = i;
goto done; goto done;
} }
} }
done: done:
index = (numStart, y); index = (numStart, y);
return int.Parse(row[numStart..numEnd]); return int.Parse(row[numStart..numEnd]);
} }
} }

View File

@@ -1,66 +1,66 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day4; namespace AdventOfCode.Problems.AOC2023.Day4;
[ProblemInfo(2023, 4, "Scratchcards")] [ProblemInfo(2023, 4, "Scratchcards")]
internal class Scratchcards : Problem<double, int> internal class Scratchcards : Problem<double, int>
{ {
private (int card, int[] win, int[] have)[] _cards = []; private (int card, int[] win, int[] have)[] _cards = [];
private readonly Dictionary<int, int> _cardCount = []; private readonly Dictionary<int, int> _cardCount = [];
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = _cards Part1 = _cards
.Select(c => c.have.Intersect(c.win).Count()) .Select(c => c.have.Intersect(c.win).Count())
.Select(c => c == 0 ? 0 : Math.Pow(2, c - 1)) .Select(c => c == 0 ? 0 : Math.Pow(2, c - 1))
.Sum(); .Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = _cards.Length; Part2 = _cards.Length;
for (int i = 0; i < _cards.Length; i++) for (int i = 0; i < _cards.Length; i++)
{ {
var card = _cards[i]; var card = _cards[i];
var wins = card.have.Intersect(card.win).Count(); var wins = card.have.Intersect(card.win).Count();
var cCount = GetCardCount(card.card); var cCount = GetCardCount(card.card);
for (int j = 1; j <= wins; j++) for (int j = 1; j <= wins; j++)
AddCards(card.card + j, cCount); AddCards(card.card + j, cCount);
Part2 += wins * cCount; Part2 += wins * cCount;
} }
} }
private int GetCardCount(int card) private int GetCardCount(int card)
{ {
if(_cardCount.TryGetValue(card, out var count)) if(_cardCount.TryGetValue(card, out var count))
return count; return count;
return 1; return 1;
} }
private void AddCards(int card, int count) private void AddCards(int card, int count)
{ {
if(_cardCount.ContainsKey(card)) if(_cardCount.ContainsKey(card))
_cardCount[card] += count; _cardCount[card] += count;
else else
_cardCount.Add(card, count + 1); _cardCount.Add(card, count + 1);
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines(); var lines = ReadInputLines();
_cards = new (int card, int[] win, int[] have)[lines.Length]; _cards = new (int card, int[] win, int[] have)[lines.Length];
for (int i = 0; i < lines.Length; i++) for (int i = 0; i < lines.Length; i++)
{ {
var card = lines[i].Split(':'); var card = lines[i].Split(':');
var cardNum = int.Parse(card[0].Split(' ').Last()); var cardNum = int.Parse(card[0].Split(' ').Last());
var numbers = card[1].Split('|') var numbers = card[1].Split('|')
.Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse)); .Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse));
_cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray()); _cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray());
} }
} }
} }

View File

@@ -1,73 +1,73 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day5; namespace AdventOfCode.Problems.AOC2023.Day5;
internal class CategoryEvaluator internal class CategoryEvaluator
{ {
public Dictionary<Category, CategoryMapper> destinations = []; public Dictionary<Category, CategoryMapper> destinations = [];
public CategoryEvaluator(CategoryMapper[] mappers) public CategoryEvaluator(CategoryMapper[] mappers)
{ {
destinations = mappers.ToDictionary(m => m.Destination); destinations = mappers.ToDictionary(m => m.Destination);
} }
public long Evaluate(Category source, long sourceValue, Category destination) public long Evaluate(Category source, long sourceValue, Category destination)
{ {
var mappers = new List<CategoryMapper>(); var mappers = new List<CategoryMapper>();
var curMapper = destinations[destination]; var curMapper = destinations[destination];
do do
{ {
mappers.Add(curMapper); mappers.Add(curMapper);
curMapper = destinations[curMapper.Source]; curMapper = destinations[curMapper.Source];
} while (curMapper.Source != source); } while (curMapper.Source != source);
mappers.Add(destinations[mappers.Last().Source]); mappers.Add(destinations[mappers.Last().Source]);
mappers.Reverse(); mappers.Reverse();
var result = sourceValue; var result = sourceValue;
foreach (var mapper in mappers) foreach (var mapper in mappers)
{ {
result = mapper.Evaluate(result); result = mapper.Evaluate(result);
} }
return result; return result;
} }
public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination) public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination)
{ {
var mappers = new List<CategoryMapper>(); var mappers = new List<CategoryMapper>();
var curMapper = destinations[destination]; var curMapper = destinations[destination];
do do
{ {
mappers.Add(curMapper); mappers.Add(curMapper);
curMapper = destinations[curMapper.Source]; curMapper = destinations[curMapper.Source];
} while (curMapper.Source != source); } while (curMapper.Source != source);
mappers.Add(destinations[mappers.Last().Source]); mappers.Add(destinations[mappers.Last().Source]);
mappers.Reverse(); mappers.Reverse();
var result = seeds; var result = seeds;
foreach (var mapper in mappers) foreach (var mapper in mappers)
{ {
result = mapper.Evaluate(result); result = mapper.Evaluate(result);
} }
return result.Distinct().ToArray(); return result.Distinct().ToArray();
} }
public CategoryMapper GetCategoryMapper(Category destination) public CategoryMapper GetCategoryMapper(Category destination)
{ {
return destinations[destination]; return destinations[destination];
} }
public enum Category public enum Category
{ {
Seed, Seed,
Soil, Soil,
Fertilizer, Fertilizer,
Water, Water,
Light, Light,
Temperature, Temperature,
Humidity, Humidity,
Location Location
} }
} }

View File

@@ -1,88 +1,88 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day5; namespace AdventOfCode.Problems.AOC2023.Day5;
internal class CategoryMapper internal class CategoryMapper
{ {
public CategoryEvaluator.Category Source { get; } public CategoryEvaluator.Category Source { get; }
public CategoryEvaluator.Category Destination { get; } public CategoryEvaluator.Category Destination { get; }
public long[] DestinationStart { get; } public long[] DestinationStart { get; }
public long[] DestinationEnd { get; } public long[] DestinationEnd { get; }
public long[] SourceStart { get; } public long[] SourceStart { get; }
public long[] SourceEnd { get; } public long[] SourceEnd { get; }
public long[] RangeLength { get; } public long[] RangeLength { get; }
public long[] Gap { get; } public long[] Gap { get; }
public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length) public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length)
{ {
Source = source; Source = source;
Destination = destination; Destination = destination;
DestinationStart = destinationStart; DestinationStart = destinationStart;
DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray(); DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray();
SourceStart = sourceStart; SourceStart = sourceStart;
SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray(); SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray();
RangeLength = length; RangeLength = length;
Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray(); Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray();
} }
public static CategoryMapper Parse(string categoryData) public static CategoryMapper Parse(string categoryData)
{ {
var lines = categoryData.Split("\r\n"); var lines = categoryData.Split("\r\n");
var names = lines[0].Split(' ')[0].Split('-'); var names = lines[0].Split(' ')[0].Split('-');
var source = Enum.Parse<CategoryEvaluator.Category>(names[0], true); var source = Enum.Parse<CategoryEvaluator.Category>(names[0], true);
var dst = Enum.Parse<CategoryEvaluator.Category>(names[^1], true); var dst = Enum.Parse<CategoryEvaluator.Category>(names[^1], true);
var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray()); var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray());
var dStart = mappingData.Select(d => d[0]).ToArray(); var dStart = mappingData.Select(d => d[0]).ToArray();
var sStart = mappingData.Select(d => d[1]).ToArray(); var sStart = mappingData.Select(d => d[1]).ToArray();
var len = mappingData.Select(d => d[2]).ToArray(); var len = mappingData.Select(d => d[2]).ToArray();
return new CategoryMapper(source, dst, dStart, sStart, len); return new CategoryMapper(source, dst, dStart, sStart, len);
} }
public long Evaluate(long value) public long Evaluate(long value)
{ {
for (int i = 0; i < DestinationStart.Length; i++) for (int i = 0; i < DestinationStart.Length; i++)
{ {
if (SourceStart[i] > value) if (SourceStart[i] > value)
continue; continue;
if (SourceEnd[i] < value) if (SourceEnd[i] < value)
continue; continue;
return value + Gap[i]; return value + Gap[i];
} }
return value; return value;
} }
public (long start, long end)[] Evaluate((long start, long end)[] ranges) public (long start, long end)[] Evaluate((long start, long end)[] ranges)
{ {
var result = new List<(long start, long end)>(); var result = new List<(long start, long end)>();
for (int i = 0; i < DestinationStart.Length; i++) for (int i = 0; i < DestinationStart.Length; i++)
{ {
result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i])))); result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i]))));
} }
return result.Distinct().Select(v => (Evaluate(v.start), Evaluate(v.end))).ToArray(); return result.Distinct().Select(v => (Evaluate(v.start), Evaluate(v.end))).ToArray();
} }
public static (long start, long end)[] SubdivideRange((long start, long end) source, (long start, long end) dst) public static (long start, long end)[] SubdivideRange((long start, long end) source, (long start, long end) dst)
{ {
if (source.start >= dst.start && source.end <= dst.end) if (source.start >= dst.start && source.end <= dst.end)
return [source]; return [source];
if(source.end < dst.end) if(source.end < dst.end)
return [source]; return [source];
if(source.start > dst.start) if(source.start > dst.start)
return [source]; return [source];
if(source.start < dst.start) if(source.start < dst.start)
return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)]; return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)];
else else
return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)]; return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)];
} }
public override string ToString() public override string ToString()
{ {
return $"{Source} -> {Destination}"; return $"{Source} -> {Destination}";
} }
} }

View File

@@ -1,38 +1,38 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day5; namespace AdventOfCode.Problems.AOC2023.Day5;
[ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")] [ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")]
internal class SeedFertilizer : Problem<long, long> internal class SeedFertilizer : Problem<long, long>
{ {
private long[] _seeds = []; private long[] _seeds = [];
private CategoryEvaluator _evaluator = new ([]); private CategoryEvaluator _evaluator = new ([]);
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputText("sample.txt"); var data = ReadInputText("sample.txt");
var sections = data.Split("\r\n\r\n"); var sections = data.Split("\r\n\r\n");
_seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray(); _seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray();
var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray(); var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray();
_evaluator = new CategoryEvaluator(mappers); _evaluator = new CategoryEvaluator(mappers);
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location)); var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location));
Part1 = evaludated.Min(); Part1 = evaludated.Min();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var splitRanges = _evaluator.Evaluate(CategoryEvaluator.Category.Seed, _seeds.Chunk(2).Select(s => (s[0], s[0] + s[1])).ToArray(), CategoryEvaluator.Category.Location); var splitRanges = _evaluator.Evaluate(CategoryEvaluator.Category.Seed, _seeds.Chunk(2).Select(s => (s[0], s[0] + s[1])).ToArray(), CategoryEvaluator.Category.Location);
} }
} }

View File

@@ -1,65 +1,65 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day6; namespace AdventOfCode.Problems.AOC2023.Day6;
[ProblemInfo(2023, 6, "Wait For It")] [ProblemInfo(2023, 6, "Wait For It")]
internal class WaitForIt : Problem<int, long> internal class WaitForIt : Problem<int, long>
{ {
private int[] _times = []; private int[] _times = [];
private int[] _distances = []; private int[] _distances = [];
private int _realTime; private int _realTime;
private long _realDistance; private long _realDistance;
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
_times = lines[0].Split(':')[1] _times = lines[0].Split(':')[1]
.Split(' ') .Split(' ')
.Where(e => e.Length > 0) .Where(e => e.Length > 0)
.Select(int.Parse) .Select(int.Parse)
.ToArray(); .ToArray();
_distances = lines[1].Split(':')[1] _distances = lines[1].Split(':')[1]
.Split(' ') .Split(' ')
.Where(e => e.Length > 0) .Where(e => e.Length > 0)
.Select(int.Parse) .Select(int.Parse)
.ToArray(); .ToArray();
_realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", "")); _realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", ""));
_realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", "")); _realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", ""));
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var winList = new List<int>(); var winList = new List<int>();
for (int i = 0; i < _times.Length; i++) for (int i = 0; i < _times.Length; i++)
{ {
var time = _times[i]; var time = _times[i];
var distance = _distances[i]; var distance = _distances[i];
var minTime = (int)Math.Floor((float)distance / time); var minTime = (int)Math.Floor((float)distance / time);
var possibleHeldTimes = Enumerable.Range(minTime, time - minTime); var possibleHeldTimes = Enumerable.Range(minTime, time - minTime);
var races = possibleHeldTimes.Select(t => (time - t) * t); var races = possibleHeldTimes.Select(t => (time - t) * t);
winList.Add(races.Count(d => d > distance)); winList.Add(races.Count(d => d > distance));
} }
Part1 = winList.Aggregate((a, b) => a * b); Part1 = winList.Aggregate((a, b) => a * b);
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var minTime = (long)Math.Floor((float)_realDistance/ _realTime); var minTime = (long)Math.Floor((float)_realDistance/ _realTime);
var maxTime = _realTime - minTime; var maxTime = _realTime - minTime;
for (long i = minTime; i <= maxTime; i++) for (long i = minTime; i <= maxTime; i++)
{ {
var dist = (_realTime - i) * i; var dist = (_realTime - i) * i;
if(dist > _realDistance) if(dist > _realDistance)
Part2++; Part2++;
} }
} }
} }

View File

@@ -1,36 +1,36 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day7; namespace AdventOfCode.Problems.AOC2023.Day7;
[ProblemInfo(2023, 7, "Camel Cards")] [ProblemInfo(2023, 7, "Camel Cards")]
internal class CamelCards : Problem<int, int> internal class CamelCards : Problem<int, int>
{ {
private CamelHand[] _hands = []; private CamelHand[] _hands = [];
private CamelHand[] _jokerHands = []; private CamelHand[] _jokerHands = [];
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputLines("input.txt"); var data = ReadInputLines("input.txt");
_hands = data.Select(d => new CamelHand(d)).ToArray(); _hands = data.Select(d => new CamelHand(d)).ToArray();
_jokerHands = data.Select(d => new CamelHand(d, true)).ToArray(); _jokerHands = data.Select(d => new CamelHand(d, true)).ToArray();
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var x = _hands.Order(); var x = _hands.Order();
Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum(); Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var x = _jokerHands.Order().Print(); var x = _jokerHands.Order().Print();
//x.Where(x => x.Hand.Contains('J')).Print(); //x.Where(x => x.Hand.Contains('J')).Print();
Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum(); Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
} }
} }

View File

@@ -1,106 +1,106 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day7; namespace AdventOfCode.Problems.AOC2023.Day7;
internal class CamelHand : IComparable<CamelHand> internal class CamelHand : IComparable<CamelHand>
{ {
public static readonly List<char> CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ]; public static readonly List<char> CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
public static readonly List<char> CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ]; public static readonly List<char> CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ];
public string Hand { get; set; } public string Hand { get; set; }
public int Bid { get; set; } public int Bid { get; set; }
public int Value { get; set; } public int Value { get; set; }
public HandType Type { get; set; } public HandType Type { get; set; }
public CamelHand(string data, bool useJoker = false) public CamelHand(string data, bool useJoker = false)
{ {
var split = data.Split(' '); var split = data.Split(' ');
Hand = split[0]; Hand = split[0];
Bid = int.Parse(split[1]); Bid = int.Parse(split[1]);
Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand); Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand);
Value = CalculateValue(Hand, useJoker); Value = CalculateValue(Hand, useJoker);
} }
public static int CalculateValue(string hand, bool useJoker) public static int CalculateValue(string hand, bool useJoker)
{ {
var total = 0; var total = 0;
for (int i = 0; i < hand.Length; i++) for (int i = 0; i < hand.Length; i++)
{ {
var p = (hand.Length - i - 1); var p = (hand.Length - i - 1);
var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]); var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]);
total += (v + 1) * (int)Math.Pow(13, p); total += (v + 1) * (int)Math.Pow(13, p);
} }
return total; return total;
} }
public bool IsStrongerThan(CamelHand card) public bool IsStrongerThan(CamelHand card)
{ {
if (Type > card.Type) if (Type > card.Type)
return true; return true;
if(Type < card.Type) if(Type < card.Type)
return false; return false;
return Value >= card.Value; return Value >= card.Value;
} }
private static HandType GetJokerHandType(string hand) private static HandType GetJokerHandType(string hand)
{ {
var type = GetHandType(hand); var type = GetHandType(hand);
if (type == HandType.FiveOfKind) if (type == HandType.FiveOfKind)
return type; return type;
if (!hand.Contains('J')) if (!hand.Contains('J'))
return type; return type;
var bestCard = hand.GroupBy(c => c) var bestCard = hand.GroupBy(c => c)
.OrderByDescending(c => c.Count()) .OrderByDescending(c => c.Count())
.First(c => c.Key != 'J').Key; .First(c => c.Key != 'J').Key;
var newHand = hand.Replace('J', bestCard); var newHand = hand.Replace('J', bestCard);
return GetHandType(newHand); return GetHandType(newHand);
} }
private static HandType GetHandType(string hand) private static HandType GetHandType(string hand)
{ {
var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray(); var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray();
if (cardGroups.Length == 1) if (cardGroups.Length == 1)
return HandType.FiveOfKind; return HandType.FiveOfKind;
if(cardGroups.Contains(4)) if(cardGroups.Contains(4))
return HandType.FourOfKind; return HandType.FourOfKind;
if (cardGroups.Contains(3) && cardGroups.Contains(2)) if (cardGroups.Contains(3) && cardGroups.Contains(2))
return HandType.FullHouse; return HandType.FullHouse;
if(cardGroups.Contains(3)) if(cardGroups.Contains(3))
return HandType.ThreeOfKind; return HandType.ThreeOfKind;
var pairs = cardGroups.Count(c => c == 2); var pairs = cardGroups.Count(c => c == 2);
if (pairs == 2) if (pairs == 2)
return HandType.TwoPair; return HandType.TwoPair;
if (pairs == 1) if (pairs == 1)
return HandType.OnePair; return HandType.OnePair;
return HandType.HighCard; return HandType.HighCard;
} }
public int CompareTo(CamelHand? other) public int CompareTo(CamelHand? other)
{ {
if(other == null) return 1; if(other == null) return 1;
return IsStrongerThan(other) ? 1 : -1; return IsStrongerThan(other) ? 1 : -1;
} }
public override string ToString() public override string ToString()
{ {
return $"[{Value}] {Hand}: {Type} | {Bid}"; return $"[{Value}] {Hand}: {Type} | {Bid}";
} }
public enum HandType public enum HandType
{ {
HighCard, HighCard,
OnePair, OnePair,
TwoPair, TwoPair,
ThreeOfKind, ThreeOfKind,
FullHouse, FullHouse,
FourOfKind, FourOfKind,
FiveOfKind FiveOfKind
} }
} }

View File

@@ -1,74 +1,74 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day8; namespace AdventOfCode.Problems.AOC2023.Day8;
[ProblemInfo(2023, 8, "Haunted Wasteland")] [ProblemInfo(2023, 8, "Haunted Wasteland")]
internal class HauntedWasteland : Problem<int, long> internal class HauntedWasteland : Problem<int, long>
{ {
private string _path = string.Empty; private string _path = string.Empty;
private Dictionary<string, (string left, string right)> _nodes = []; private Dictionary<string, (string left, string right)> _nodes = [];
public override void LoadInput() public override void LoadInput()
{ {
var data = ReadInputLines(); var data = ReadInputLines();
_path = data[0]; _path = data[0];
for (int i = 2; i < data.Length; i++) for (int i = 2; i < data.Length; i++)
{ {
var curLine = data[i].Split('='); var curLine = data[i].Split('=');
var node = curLine[0].TrimEnd(); var node = curLine[0].TrimEnd();
var branches = curLine[1][2..^1].Split(", "); var branches = curLine[1][2..^1].Split(", ");
_nodes.Add(node, (branches[0], branches[1])); _nodes.Add(node, (branches[0], branches[1]));
} }
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
var curPos = "AAA"; var curPos = "AAA";
var i = 0; var i = 0;
var steps = 0; var steps = 0;
do do
{ {
curPos = _path[i] switch curPos = _path[i] switch
{ {
'L' => _nodes[curPos].left, 'L' => _nodes[curPos].left,
'R' => _nodes[curPos].right, 'R' => _nodes[curPos].right,
_ => throw new Exception("Something went horribly wrong") _ => throw new Exception("Something went horribly wrong")
}; };
i = (i + 1) % _path.Length; i = (i + 1) % _path.Length;
steps++; steps++;
} while (curPos != "ZZZ"); } while (curPos != "ZZZ");
Part1 = steps; Part1 = steps;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray(); var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray();
var len = new long[curPos.Length]; var len = new long[curPos.Length];
var i = 0; var i = 0;
do do
{ {
for (int j = 0; j < curPos.Length; j++) for (int j = 0; j < curPos.Length; j++)
{ {
if (curPos[j][^1] == 'Z') if (curPos[j][^1] == 'Z')
continue; continue;
len[j]++; len[j]++;
curPos[j] = _path[i] switch curPos[j] = _path[i] switch
{ {
'L' => _nodes[curPos[j]].left, 'L' => _nodes[curPos[j]].left,
'R' => _nodes[curPos[j]].right, 'R' => _nodes[curPos[j]].right,
_ => throw new Exception("Something went horribly wrong") _ => throw new Exception("Something went horribly wrong")
}; };
} }
i = (i + 1) % _path.Length; i = (i + 1) % _path.Length;
} while (curPos.Any(n => n[^1] != 'Z')); } while (curPos.Any(n => n[^1] != 'Z'));
Part2 = len.LCM(); Part2 = len.LCM();
} }
} }

View File

@@ -1,85 +1,85 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2023.Day9; namespace AdventOfCode.Problems.AOC2023.Day9;
[ProblemInfo(2023, 9, "Mirage Maintenance")] [ProblemInfo(2023, 9, "Mirage Maintenance")]
internal class MirageMaintenance : Problem<long, long> internal class MirageMaintenance : Problem<long, long>
{ {
private long[][] _history = []; private long[][] _history = [];
public override void LoadInput() public override void LoadInput()
{ {
_history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray(); _history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray();
} }
public long CalculateNumber(long[] values, bool last = true) public long CalculateNumber(long[] values, bool last = true)
{ {
var diffs = new long[values.Length - 1]; var diffs = new long[values.Length - 1];
for (int i = 0; i < values.Length - 1; i++) for (int i = 0; i < values.Length - 1; i++)
diffs[i] = values[i + 1] - values[i]; diffs[i] = values[i + 1] - values[i];
if (diffs.Any(d => d != 0)) if (diffs.Any(d => d != 0))
return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last)); return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last));
else else
return last ? values.Last() : values.First(); return last ? values.Last() : values.First();
} }
[Obsolete("Optimize too soon garbage")] [Obsolete("Optimize too soon garbage")]
public long GetNextNumber(long[] history) public long GetNextNumber(long[] history)
{ {
var data = new List<List<long>> var data = new List<List<long>>
{ {
new(history.Reverse()) new(history.Reverse())
}; };
CalculateLayer(data, 1, 1); CalculateLayer(data, 1, 1);
var sum = data.Select(d => d.First()).Sum(); var sum = data.Select(d => d.First()).Sum();
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(string.Join(',', history)); Console.WriteLine(string.Join(',', history));
Console.WriteLine(); Console.WriteLine();
foreach (var item in data) foreach (var item in data)
Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString()))); Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString())));
return sum; return sum;
} }
[Obsolete("Optimize too soon garbage")] [Obsolete("Optimize too soon garbage")]
public void CalculateLayer(List<List<long>> data, int layer, int pos) public void CalculateLayer(List<List<long>> data, int layer, int pos)
{ {
while (data.Count <= layer) while (data.Count <= layer)
data.Add([]); data.Add([]);
var lastLayer = layer - 1; var lastLayer = layer - 1;
if (layer != 0 && data[lastLayer].Count <= pos) if (layer != 0 && data[lastLayer].Count <= pos)
CalculateLayer(data, lastLayer, pos + 1); CalculateLayer(data, lastLayer, pos + 1);
var right = data[lastLayer][pos - 1]; var right = data[lastLayer][pos - 1];
var left = data[lastLayer][pos]; var left = data[lastLayer][pos];
var diff = right - left; var diff = right - left;
data[layer].Add(diff); data[layer].Add(diff);
if (diff != 0 && pos == 1) if (diff != 0 && pos == 1)
CalculateLayer(data, layer + 1, 1); CalculateLayer(data, layer + 1, 1);
} }
public enum State public enum State
{ {
Diff, Diff,
Expand, Expand,
Predict Predict
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
//GetNextNumber(_history[2]); //GetNextNumber(_history[2]);
Part1 = _history.Select(c => CalculateNumber(c)).Sum(); Part1 = _history.Select(c => CalculateNumber(c)).Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = _history.Select(c => CalculateNumber(c, false)).Sum(); Part2 = _history.Select(c => CalculateNumber(c, false)).Sum();
} }
} }

View File

@@ -1,40 +1,40 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Frozen; using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2024.Day1; namespace AdventOfCode.Problems.AOC2024.Day1;
[ProblemInfo(2024, 1, "Historian Hysteria")] [ProblemInfo(2024, 1, "Historian Hysteria")]
internal class HistorianHysteria : Problem<int, int> internal class HistorianHysteria : Problem<int, int>
{ {
private int[] _left = []; private int[] _left = [];
private int[] _right = []; private int[] _right = [];
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = _left.Order() Part1 = _left.Order()
.Zip(_right.Order()) .Zip(_right.Order())
.Select(a => Math.Abs(a.First - a.Second)) .Select(a => Math.Abs(a.First - a.Second))
.Sum(); .Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var rightFeq = _right.GroupBy(x => x) var rightFeq = _right.GroupBy(x => x)
.ToFrozenDictionary(g => g.Key, g => g.Count()); .ToFrozenDictionary(g => g.Key, g => g.Count());
Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0) Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0)
.Sum(); .Sum();
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines(); var lines = ReadInputLines();
var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList(); var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList();
_left = data.Select(l => l.First()).ToArray(); _left = data.Select(l => l.First()).ToArray();
_right = data.Select(l => l.Last()).ToArray(); _right = data.Select(l => l.Last()).ToArray();
} }
} }

View File

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

View File

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

View File

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

View File

@@ -1,107 +1,107 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2024.Day2; namespace AdventOfCode.Problems.AOC2024.Day2;
[ProblemInfo(2024, 2, "Red-Nosed Reports")] [ProblemInfo(2024, 2, "Red-Nosed Reports")]
internal class RedNosedReports : Problem<int, int> internal class RedNosedReports : Problem<int, int>
{ {
private int[][] _data = []; private int[][] _data = [];
private static bool CheckIncrease(int l) => l >= 1 && l <= 3; private static bool CheckIncrease(int l) => l >= 1 && l <= 3;
private static bool CheckDecrease(int l) => l <= -1 && l >= -3; private static bool CheckDecrease(int l) => l <= -1 && l >= -3;
public override void CalculatePart1() public override void CalculatePart1()
{ {
var reportAnalysis = Analyze(); var reportAnalysis = Analyze();
var increasing = reportAnalysis.Count(r => r.All(CheckIncrease)); var increasing = reportAnalysis.Count(r => r.All(CheckIncrease));
var decreasing = reportAnalysis.Count(r => r.All(CheckDecrease)); var decreasing = reportAnalysis.Count(r => r.All(CheckDecrease));
Part1 = increasing + decreasing; Part1 = increasing + decreasing;
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Console.WriteLine(); Console.WriteLine();
foreach (var report in _data) foreach (var report in _data)
{ {
if (CheckSafety(report, out _)) if (CheckSafety(report, out _))
Part2++; Part2++;
} }
} }
private static bool CheckSafety(int[] report, out bool increase) private static bool CheckSafety(int[] report, out bool increase)
{ {
increase = false; increase = false;
var inFail = Check(report, CheckIncrease); var inFail = Check(report, CheckIncrease);
var deFail = Check(report, CheckDecrease); var deFail = Check(report, CheckDecrease);
if(inFail.Count == 0) if(inFail.Count == 0)
{ {
increase = true; increase = true;
return true; return true;
} }
else else
{ {
if (inFail.Count < report.Length && RemoveFails(report, inFail).Any(g => Check(g, CheckIncrease).Count == 0)) if (inFail.Count < report.Length && RemoveFails(report, inFail).Any(g => Check(g, CheckIncrease).Count == 0))
{ {
increase = true; increase = true;
return true; return true;
} }
} }
if(deFail.Count == 0) if(deFail.Count == 0)
return true; return true;
else else
{ {
if (deFail.Count < report.Length && RemoveFails(report, deFail).Any(g => Check(g, CheckDecrease).Count == 0)) if (deFail.Count < report.Length && RemoveFails(report, deFail).Any(g => Check(g, CheckDecrease).Count == 0))
return true; return true;
} }
return false; return false;
} }
static int[][] RemoveFails(int[] report, List<int> fails) static int[][] RemoveFails(int[] report, List<int> fails)
{ {
var results = new int[fails.Count][]; var results = new int[fails.Count][];
for (int i = 0; i < fails.Count; i++) for (int i = 0; i < fails.Count; i++)
{ {
var f = fails[i]; var f = fails[i];
results[i] = f == 0 ? report[1..] : f == report.Length-1 ? report[..^1] : [.. report[..f], .. report[(f+1)..]]; results[i] = f == 0 ? report[1..] : f == report.Length-1 ? report[..^1] : [.. report[..f], .. report[(f+1)..]];
} }
return results; return results;
} }
static List<int> Check(int[] report, Func<int, bool> check) static List<int> Check(int[] report, Func<int, bool> check)
{ {
var fails = new List<int>(); var fails = new List<int>();
for (int i = 1; i < report.Length; i++) for (int i = 1; i < report.Length; i++)
{ {
var d = report[i] - report[i-1]; var d = report[i] - report[i-1];
if (!check(d)) if (!check(d))
fails.AddRange([i, i-1]); fails.AddRange([i, i-1]);
} }
return fails.Distinct().ToList(); return fails.Distinct().ToList();
} }
private int[][] Analyze() private int[][] Analyze()
{ {
var reportAnalysis = new int[_data.Length][]; var reportAnalysis = new int[_data.Length][];
for (int ridx = 0; ridx < _data.Length; ridx++) for (int ridx = 0; ridx < _data.Length; ridx++)
{ {
int[]? report = _data[ridx]; int[]? report = _data[ridx];
var safety = new int[report.Length - 1]; var safety = new int[report.Length - 1];
for (int i = 1; i < report.Length; i++) for (int i = 1; i < report.Length; i++)
safety[i - 1] = report[i] - report[i - 1]; safety[i - 1] = report[i] - report[i - 1];
reportAnalysis[ridx] = safety; reportAnalysis[ridx] = safety;
} }
return reportAnalysis; return reportAnalysis;
} }
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputLines("input.txt").Select(l => l.Split(' ').Select(int.Parse).ToArray()).ToArray(); _data = ReadInputLines("input.txt").Select(l => l.Split(' ').Select(int.Parse).ToArray()).ToArray();
} }
} }

View File

@@ -1,54 +1,54 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Problems.AOC2024.Day3; namespace AdventOfCode.Problems.AOC2024.Day3;
[ProblemInfo(2024, 3, "Mull It Over")] [ProblemInfo(2024, 3, "Mull It Over")]
internal partial class MullItOver : Problem<int, int> internal partial class MullItOver : Problem<int, int>
{ {
private string _data = string.Empty; private string _data = string.Empty;
public override void CalculatePart1() public override void CalculatePart1()
{ {
var matches = Mul().Matches(_data); var matches = Mul().Matches(_data);
Part1 = matches.Select(m => (int.Parse(m.Groups["a"].ValueSpan), int.Parse(m.Groups["b"].ValueSpan))).Select(v => v.Item1 * v.Item2).Sum(); Part1 = matches.Select(m => (int.Parse(m.Groups["a"].ValueSpan), int.Parse(m.Groups["b"].ValueSpan))).Select(v => v.Item1 * v.Item2).Sum();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var doing = true; var doing = true;
var muls = DosAndDonts().Matches(_data); var muls = DosAndDonts().Matches(_data);
foreach (Match match in muls) foreach (Match match in muls)
{ {
switch (match.ValueSpan) switch (match.ValueSpan)
{ {
case ['d', 'o', 'n', ..]: case ['d', 'o', 'n', ..]:
doing = false; doing = false;
break; break;
case ['d', 'o', ..]: case ['d', 'o', ..]:
doing = true; doing = true;
break; break;
default: default:
if (!doing) if (!doing)
continue; continue;
Part2 += int.Parse(match.Groups["a"].ValueSpan) * int.Parse(match.Groups["b"].ValueSpan); Part2 += int.Parse(match.Groups["a"].ValueSpan) * int.Parse(match.Groups["b"].ValueSpan);
break; break;
} }
} }
} }
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputText("input.txt"); _data = ReadInputText("input.txt");
} }
[GeneratedRegex("(mul\\((?<a>\\d+)\\,(?<b>\\d+)\\))|(do\\(\\))|(don't\\(\\))")] [GeneratedRegex("(mul\\((?<a>\\d+)\\,(?<b>\\d+)\\))|(do\\(\\))|(don't\\(\\))")]
private static partial Regex DosAndDonts(); private static partial Regex DosAndDonts();
[GeneratedRegex("mul\\((?<a>\\d+)\\,(?<b>\\d+)\\)")] [GeneratedRegex("mul\\((?<a>\\d+)\\,(?<b>\\d+)\\)")]
private static partial Regex Mul(); private static partial Regex Mul();
} }

View File

@@ -1,127 +1,127 @@
 
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Pos = (int x, int y); using Pos = (int x, int y);
namespace AdventOfCode.Problems.AOC2024.Day4; namespace AdventOfCode.Problems.AOC2024.Day4;
[ProblemInfo(2024, 4, "Ceres Search")] [ProblemInfo(2024, 4, "Ceres Search")]
internal class CeresSearch : Problem<int, int> internal class CeresSearch : Problem<int, int>
{ {
private string[] _data = []; private string[] _data = [];
private static readonly Pos[] dirs = [ private static readonly Pos[] dirs = [
(-1, 0), //Left (-1, 0), //Left
(-1, -1), //Top Left (-1, -1), //Top Left
(0, -1), //Top (0, -1), //Top
(1, -1), //Top Right (1, -1), //Top Right
(1, 0), //Right (1, 0), //Right
(1, 1), //Bottom Right (1, 1), //Bottom Right
(0, 1), //Bottom (0, 1), //Bottom
(-1, 1), //Bottom Left (-1, 1), //Bottom Left
]; ];
private static readonly Pos[] xdirs = [ private static readonly Pos[] xdirs = [
(-1, -1), //Top Left (-1, -1), //Top Left
(1, -1), //Top Right (1, -1), //Top Right
(1, 1), //Bottom Right (1, 1), //Bottom Right
(-1, 1), //Bottom Left (-1, 1), //Bottom Left
]; ];
public override void CalculatePart1() public override void CalculatePart1()
{ {
Part1 = FindWord(_data, "XMAS"); Part1 = FindWord(_data, "XMAS");
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
Part2 = FindXWord(_data, "MAS"); Part2 = FindXWord(_data, "MAS");
} }
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputLines("input.txt"); _data = ReadInputLines("input.txt");
} }
private static int FindXWord(string[] data, string target) private static int FindXWord(string[] data, string target)
{ {
var matches = 0; var matches = 0;
var pivot = target.Length / 2; var pivot = target.Length / 2;
var tgt = target[pivot]; var tgt = target[pivot];
var branchA = string.Join("", target[..(pivot+1)].Reverse()); var branchA = string.Join("", target[..(pivot+1)].Reverse());
var branchB = target[pivot..]; var branchB = target[pivot..];
for (int y = 1; y < data.Length-1; y++) for (int y = 1; y < data.Length-1; y++)
{ {
var row = data[y]; var row = data[y];
for (int x = 1; x < row.Length-1; x++) for (int x = 1; x < row.Length-1; x++)
{ {
var c = row[x]; var c = row[x];
if (c == tgt) if (c == tgt)
{ {
for (int i = 0; i < xdirs.Length; i++) for (int i = 0; i < xdirs.Length; i++)
{ {
Pos dir = xdirs[i]; Pos dir = xdirs[i];
Pos opposingDir = xdirs[(i + 2) % xdirs.Length]; Pos opposingDir = xdirs[(i + 2) % xdirs.Length];
if (CheckWord(data, (x, y), dir, branchA, 1) && CheckWord(data, (x,y), opposingDir, branchB, 1)) if (CheckWord(data, (x, y), dir, branchA, 1) && CheckWord(data, (x,y), opposingDir, branchB, 1))
{ {
Pos dir2 = xdirs[(i+1) % xdirs.Length]; Pos dir2 = xdirs[(i+1) % xdirs.Length];
Pos opposingDir2 = xdirs[(i + 3) % xdirs.Length]; Pos opposingDir2 = xdirs[(i + 3) % xdirs.Length];
if (CheckWord(data, (x, y), dir2, branchA, 1) && CheckWord(data, (x, y), opposingDir2, branchB, 1)) if (CheckWord(data, (x, y), dir2, branchA, 1) && CheckWord(data, (x, y), opposingDir2, branchB, 1))
matches++; matches++;
} }
} }
} }
} }
} }
return matches; return matches;
} }
private static int FindWord(string[] data, string target) private static int FindWord(string[] data, string target)
{ {
var matches = 0; var matches = 0;
var tgt = target[0]; var tgt = target[0];
for (int y = 0; y < data.Length; y++) for (int y = 0; y < data.Length; y++)
{ {
var row = data[y]; var row = data[y];
for (int x = 0; x < row.Length; x++) for (int x = 0; x < row.Length; x++)
{ {
var c = row[x]; var c = row[x];
if(c == tgt) if(c == tgt)
{ {
foreach (var dir in dirs) foreach (var dir in dirs)
{ {
if(CheckWord(data, (x, y), dir, target, 1)) if(CheckWord(data, (x, y), dir, target, 1))
matches++; matches++;
} }
} }
} }
} }
return matches; return matches;
} }
private static bool CheckWord(string[] data, Pos pos, Pos dir, string target, int targetPos) private static bool CheckWord(string[] data, Pos pos, Pos dir, string target, int targetPos)
{ {
Pos curPos = (pos.x + dir.x, pos.y + dir.y); Pos curPos = (pos.x + dir.x, pos.y + dir.y);
if(curPos.y < 0 || curPos.y >= data.Length) if(curPos.y < 0 || curPos.y >= data.Length)
return false; return false;
if (curPos.x < 0 || curPos.x >= data[0].Length) if (curPos.x < 0 || curPos.x >= data[0].Length)
return false; return false;
var c = data[curPos.y][curPos.x]; var c = data[curPos.y][curPos.x];
if(c == target[targetPos]) if(c == target[targetPos])
{ {
if (targetPos == target.Length - 1) if (targetPos == target.Length - 1)
return true; return true;
return CheckWord(data, curPos, dir, target, targetPos + 1); return CheckWord(data, curPos, dir, target, targetPos + 1);
} }
return false; return false;
} }
} }

View File

@@ -1,96 +1,96 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Rule = (int after, int before); using Rule = (int after, int before);
namespace AdventOfCode.Problems.AOC2024.Day5; namespace AdventOfCode.Problems.AOC2024.Day5;
internal class PageList internal class PageList
{ {
private readonly List<Rule> _rules; private readonly List<Rule> _rules;
private PageNode _root; private PageNode _root;
public PageList(int[] pages, List<Rule> rules) public PageList(int[] pages, List<Rule> rules)
{ {
_rules = rules.Where(r => pages.Contains(r.before)).ToList(); _rules = rules.Where(r => pages.Contains(r.before)).ToList();
_root = new PageNode(pages[0], GetRulesForPage(pages[0])); _root = new PageNode(pages[0], GetRulesForPage(pages[0]));
for (int i = 1; i < pages.Length; i++) for (int i = 1; i < pages.Length; i++)
AddPage(pages[i]); AddPage(pages[i]);
} }
public void AddPage(int page) public void AddPage(int page)
{ {
var node = new PageNode(page, GetRulesForPage(page)); var node = new PageNode(page, GetRulesForPage(page));
if(node.IsBefore(_root)) if(node.IsBefore(_root))
{ {
node.NextNode = _root; node.NextNode = _root;
_root = node; _root = node;
return; return;
} }
var curNode = _root; var curNode = _root;
while(curNode != null) while(curNode != null)
{ {
if(curNode.IsBefore(node)) if(curNode.IsBefore(node))
{ {
if(curNode.NextNode == null) if(curNode.NextNode == null)
{ {
curNode.NextNode = node; curNode.NextNode = node;
break; break;
} }
else if(node.IsBefore(curNode.NextNode)) else if(node.IsBefore(curNode.NextNode))
{ {
node.NextNode = curNode.NextNode; node.NextNode = curNode.NextNode;
curNode.NextNode = node; curNode.NextNode = node;
break; break;
} }
} }
curNode = curNode.NextNode; curNode = curNode.NextNode;
} }
} }
public List<Rule> GetRulesForPage(int page) public List<Rule> GetRulesForPage(int page)
{ {
return _rules.Where(r => r.after == page).ToList(); return _rules.Where(r => r.after == page).ToList();
} }
public List<int> Traverse() public List<int> Traverse()
{ {
var list = new List<int>(); var list = new List<int>();
var curNode = _root; var curNode = _root;
while(curNode != null) while(curNode != null)
{ {
list.Add(curNode.Page); list.Add(curNode.Page);
curNode = curNode.NextNode; curNode = curNode.NextNode;
} }
return list; return list;
} }
} }
internal class PageNode internal class PageNode
{ {
public int Page { get; set; } public int Page { get; set; }
public int[] Before { get; set; } public int[] Before { get; set; }
public PageNode? NextNode { get; set; } public PageNode? NextNode { get; set; }
public PageNode(int page, List<Rule> rules) public PageNode(int page, List<Rule> rules)
{ {
Page = page; Page = page;
Before = rules.Count == 0 ? [int.MinValue] : rules.Select(r => r.before).ToArray(); Before = rules.Count == 0 ? [int.MinValue] : rules.Select(r => r.before).ToArray();
} }
public override string ToString() public override string ToString()
{ {
return $"{Page} << {Before}"; return $"{Page} << {Before}";
} }
public bool IsBefore(PageNode other) public bool IsBefore(PageNode other)
{ {
if(Before.Any(b => b == other.Page)) if(Before.Any(b => b == other.Page))
return true; return true;
return false; return false;
} }
} }

View File

@@ -1,77 +1,77 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Rule = (int after, int before); using Rule = (int after, int before);
namespace AdventOfCode.Problems.AOC2024.Day5; namespace AdventOfCode.Problems.AOC2024.Day5;
[ProblemInfo(2024, 5, "Print Queue")] [ProblemInfo(2024, 5, "Print Queue")]
internal class PrintQueue : Problem<int, int> internal class PrintQueue : Problem<int, int>
{ {
private List<Rule> _rules = []; private List<Rule> _rules = [];
private List<int[]> updates = []; private List<int[]> updates = [];
public override void CalculatePart1() public override void CalculatePart1()
{ {
foreach (var update in updates) foreach (var update in updates)
{ {
if (IsOrdered(update, out _)) if (IsOrdered(update, out _))
{ {
var mid = update[update.Length / 2]; var mid = update[update.Length / 2];
Part1 += mid; Part1 += mid;
} }
} }
} }
public bool IsOrdered(int[] update, out List<int> orderd) public bool IsOrdered(int[] update, out List<int> orderd)
{ {
var list = new PageList(update, _rules); var list = new PageList(update, _rules);
orderd = list.Traverse(); orderd = list.Traverse();
return orderd.Zip(update).All(e => e.First== e.Second); return orderd.Zip(update).All(e => e.First== e.Second);
} }
public int[] SortUpdates(int[] updates) public int[] SortUpdates(int[] updates)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
foreach (var update in updates) foreach (var update in updates)
{ {
if (!IsOrdered(update, out var ordered)) if (!IsOrdered(update, out var ordered))
{ {
var mid = ordered[update.Length / 2]; var mid = ordered[update.Length / 2];
Part2 += mid; Part2 += mid;
} }
} }
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
var parsingPages = false; var parsingPages = false;
foreach (var line in lines) foreach (var line in lines)
{ {
if (string.IsNullOrWhiteSpace(line)) if (string.IsNullOrWhiteSpace(line))
{ {
parsingPages = true; parsingPages = true;
continue; continue;
} }
if (parsingPages) if (parsingPages)
{ {
updates.Add(line.Split(',').Select(int.Parse).ToArray()); updates.Add(line.Split(',').Select(int.Parse).ToArray());
} }
else{ else{
var d = line.Split('|').Select(int.Parse); var d = line.Split('|').Select(int.Parse);
_rules.Add((d.First(), d.Last())); _rules.Add((d.First(), d.Last()));
} }
} }
} }
} }

View File

@@ -1,392 +1,392 @@
using AdventOfCode.Utils.Models; using AdventOfCode.Utils.Models;
using System; using System;
using System.Collections.Frozen; using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Turn = (AdventOfCode.Utils.Models.Vec2<int> pos, int dir, int step); using Turn = (AdventOfCode.Utils.Models.Vec2<int> pos, int dir, int step);
namespace AdventOfCode.Problems.AOC2024.Day6; namespace AdventOfCode.Problems.AOC2024.Day6;
[ProblemInfo(2024, 6, "Guard Gallivant")] [ProblemInfo(2024, 6, "Guard Gallivant")]
internal class GuardGallivant : Problem<int, int> internal class GuardGallivant : Problem<int, int>
{ {
private char[][] _data = []; private char[][] _data = [];
private int _height; private int _height;
private int _width; private int _width;
public static readonly Vec2<int>[] DIRS = [ public static readonly Vec2<int>[] DIRS = [
new (0, -1), new (0, -1),
new (1, 0), new (1, 0),
new (0, 1), new (0, 1),
new (-1, 0), new (-1, 0),
]; ];
public override void CalculatePart1() public override void CalculatePart1()
{ {
var map = new GuardMap(_data, GetStartPos()); var map = new GuardMap(_data, GetStartPos());
Part1 = map.GetPath().DistinctBy(p => p.pos).Count(); Part1 = map.GetPath().DistinctBy(p => p.pos).Count();
} }
//this does not work //this does not work
public override void CalculatePart2() public override void CalculatePart2()
{ {
var start = GetStartPos(); var start = GetStartPos();
var map = new GuardMap(_data, start); var map = new GuardMap(_data, start);
var path = map.GetPath(); var path = map.GetPath();
var visited = path.Select(p => p.pos).ToFrozenSet(); var visited = path.Select(p => p.pos).ToFrozenSet();
var nodes = new List<GuardNode>(); var nodes = new List<GuardNode>();
var found = new HashSet<Vec2<int>>(); var found = new HashSet<Vec2<int>>();
foreach (var (pos, node) in path) foreach (var (pos, node) in path)
{ {
var turn = (node.Direction + 1) % 4; var turn = (node.Direction + 1) % 4;
if (pos == start) if (pos == start)
continue; continue;
if (map.GetNextObstacle(pos, turn, out var next)) if (map.GetNextObstacle(pos, turn, out var next))
{ {
var obstacleNode = new GuardNode(pos, turn, 0); var obstacleNode = new GuardNode(pos, turn, 0);
var obstaclePos = pos + DIRS[node.Direction]; var obstaclePos = pos + DIRS[node.Direction];
if (!IsInBounds(obstaclePos)) if (!IsInBounds(obstaclePos))
continue; continue;
if (map.SolveNewPath(obstacleNode, pos + DIRS[node.Direction], nodes)) if (map.SolveNewPath(obstacleNode, pos + DIRS[node.Direction], nodes))
{ {
if (!found.Contains(obstaclePos)) if (!found.Contains(obstaclePos))
{ {
Part2++; Part2++;
//map.PrintBoard(nodes, pos, obstaclePos); //map.PrintBoard(nodes, pos, obstaclePos);
//Console.ReadLine(); //Console.ReadLine();
} }
found.Add(obstaclePos); found.Add(obstaclePos);
} }
} }
} }
} }
private Vec2<int> GetStartPos() private Vec2<int> GetStartPos()
{ {
for (int y = 0; y < _data.Length; y++) for (int y = 0; y < _data.Length; y++)
{ {
var row = _data[y]; var row = _data[y];
for (int x = 0; x < row.Length; x++) for (int x = 0; x < row.Length; x++)
{ {
if (row[x] == '^') if (row[x] == '^')
return new(x, y); return new(x, y);
} }
} }
throw new Exception("Start Position not found"); throw new Exception("Start Position not found");
} }
private bool IsInBounds(Vec2<int> pos) private bool IsInBounds(Vec2<int> pos)
{ {
if (pos.X < 0 || pos.Y < 0) if (pos.X < 0 || pos.Y < 0)
return false; return false;
if (pos.X >= _width || pos.Y >= _height) if (pos.X >= _width || pos.Y >= _height)
return false; return false;
return true; return true;
} }
public override void LoadInput() public override void LoadInput()
{ {
_data = ReadInputLines("input.txt").Select(r => r.ToCharArray()).ToArray(); _data = ReadInputLines("input.txt").Select(r => r.ToCharArray()).ToArray();
_height = _data.Length; _height = _data.Length;
_width = _data[0].Length; _width = _data[0].Length;
} }
} }
file class GuardMap file class GuardMap
{ {
public List<GuardNode> Nodes { get; set; } public List<GuardNode> Nodes { get; set; }
private readonly bool[][] _map; private readonly bool[][] _map;
private readonly int _height; private readonly int _height;
private readonly int _width; private readonly int _width;
public GuardMap(char[][] map, Vec2<int> start) public GuardMap(char[][] map, Vec2<int> start)
{ {
_map = map.Select(r => r.Select(c => c == '#' ? true : false).ToArray()).ToArray(); _map = map.Select(r => r.Select(c => c == '#' ? true : false).ToArray()).ToArray();
_height = map.Length; _height = map.Length;
_width = map[0].Length; _width = map[0].Length;
var startNode = new GuardNode(start, 0, 0); var startNode = new GuardNode(start, 0, 0);
Nodes = [startNode]; Nodes = [startNode];
Solve(); Solve();
} }
public List<(Vec2<int> pos, GuardNode node)> GetPath() public List<(Vec2<int> pos, GuardNode node)> GetPath()
{ {
return GetPath(Nodes); return GetPath(Nodes);
} }
public FrozenSet<Vec2<int>> GetPathSet(List<GuardNode> nodes) public FrozenSet<Vec2<int>> GetPathSet(List<GuardNode> nodes)
{ {
var path = GetPath(nodes); var path = GetPath(nodes);
return path.Select(p => p.pos).ToFrozenSet(); return path.Select(p => p.pos).ToFrozenSet();
} }
public List<(Vec2<int> pos, GuardNode node)> GetPath(List<GuardNode> nodes) public List<(Vec2<int> pos, GuardNode node)> GetPath(List<GuardNode> nodes)
{ {
var path = new List<(Vec2<int>, GuardNode)>(); var path = new List<(Vec2<int>, GuardNode)>();
var curNode = nodes[0]; var curNode = nodes[0];
while (true) while (true)
{ {
if (curNode.Next is int nextId && nextId >= 0) if (curNode.Next is int nextId && nextId >= 0)
{ {
var next = nodes[nextId]; var next = nodes[nextId];
path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode))); path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode)));
curNode = next; curNode = next;
} }
else if (curNode.Next == -1) else if (curNode.Next == -1)
{ {
var end = curNode.Direction switch var end = curNode.Direction switch
{ {
0 => new Vec2<int>(curNode.Pos.X, -1), 0 => new Vec2<int>(curNode.Pos.X, -1),
1 => new Vec2<int>(_width, curNode.Pos.Y), 1 => new Vec2<int>(_width, curNode.Pos.Y),
2 => new Vec2<int>(curNode.Pos.X, _height), 2 => new Vec2<int>(curNode.Pos.X, _height),
3 => new Vec2<int>(-1, curNode.Pos.Y), 3 => new Vec2<int>(-1, curNode.Pos.Y),
_ => throw new InvalidOperationException() _ => throw new InvalidOperationException()
}; };
path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode))); path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode)));
break; break;
} }
else else
break; break;
} }
return path; return path;
} }
private List<Vec2<int>> GetPointsBetween(Vec2<int> start, Vec2<int> end, int dir) private List<Vec2<int>> GetPointsBetween(Vec2<int> start, Vec2<int> end, int dir)
{ {
var result = new List<Vec2<int>>(); var result = new List<Vec2<int>>();
switch (dir) switch (dir)
{ {
case 0: case 0:
for (int i = start.Y; i > end.Y; i--) for (int i = start.Y; i > end.Y; i--)
result.Add(new Vec2<int>(start.X, i)); result.Add(new Vec2<int>(start.X, i));
break; break;
case 1: case 1:
for (int i = start.X; i < end.X; i++) for (int i = start.X; i < end.X; i++)
result.Add(new Vec2<int>(i, start.Y)); result.Add(new Vec2<int>(i, start.Y));
break; break;
case 2: case 2:
for (int i = start.Y; i < end.Y; i++) for (int i = start.Y; i < end.Y; i++)
result.Add(new Vec2<int>(start.X, i)); result.Add(new Vec2<int>(start.X, i));
break; break;
case 3: case 3:
for (int i = start.X; i > end.X; i--) for (int i = start.X; i > end.X; i--)
result.Add(new Vec2<int>(i, start.Y)); result.Add(new Vec2<int>(i, start.Y));
break; break;
} }
return result; return result;
} }
private void Solve() private void Solve()
{ {
var curNode = Nodes[0]; var curNode = Nodes[0];
while (true) while (true)
{ {
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next)) if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next))
{ {
curNode.Next = -1; curNode.Next = -1;
Nodes[curNode.Id] = curNode; Nodes[curNode.Id] = curNode;
break; break;
} }
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count); var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count);
curNode.Next = newNode.Id; curNode.Next = newNode.Id;
Nodes[curNode.Id] = curNode; Nodes[curNode.Id] = curNode;
Nodes.Add(newNode); Nodes.Add(newNode);
curNode = newNode; curNode = newNode;
} }
} }
public bool SolveNewPath(GuardNode start, Vec2<int> extraObsticle, List<GuardNode> nodes) public bool SolveNewPath(GuardNode start, Vec2<int> extraObsticle, List<GuardNode> nodes)
{ {
var curNode = start; var curNode = start;
nodes.Clear(); nodes.Clear();
nodes.Add(start); nodes.Add(start);
while (true) while (true)
{ {
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next, extraObsticle)) if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next, extraObsticle))
return false; return false;
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, nodes.Count); var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, nodes.Count);
if (nodes.Any(n => n.Pos == newNode.Pos && n.Direction == newNode.Direction)) if (nodes.Any(n => n.Pos == newNode.Pos && n.Direction == newNode.Direction))
{ {
return true; return true;
} }
curNode.Next = newNode.Id; curNode.Next = newNode.Id;
nodes[curNode.Id] = curNode; nodes[curNode.Id] = curNode;
curNode = newNode; curNode = newNode;
nodes.Add(newNode); nodes.Add(newNode);
} }
} }
public bool GetNextObstacle(Vec2<int> start, int dir, out Vec2<int> pos, Vec2<int>? extraObsticle = null) public bool GetNextObstacle(Vec2<int> start, int dir, out Vec2<int> pos, Vec2<int>? extraObsticle = null)
{ {
if (extraObsticle is Vec2<int> ex) if (extraObsticle is Vec2<int> ex)
_map[ex.Y][ex.X] = true; _map[ex.Y][ex.X] = true;
pos = default; pos = default;
var (sX, sY) = start; var (sX, sY) = start;
switch (dir) switch (dir)
{ {
case 0: case 0:
for (int y = sY; y >= 0; y--) for (int y = sY; y >= 0; y--)
{ {
if (_map[y][sX]) if (_map[y][sX])
{ {
pos = new(sX, y); pos = new(sX, y);
ResetExtraObsticle(); ResetExtraObsticle();
return true; return true;
} }
} }
break; break;
case 1: case 1:
var rowRight = _map[sY]; var rowRight = _map[sY];
for (int x = sX; x < _width; x++) for (int x = sX; x < _width; x++)
{ {
if (rowRight[x]) if (rowRight[x])
{ {
pos = new(x, sY); pos = new(x, sY);
ResetExtraObsticle(); ResetExtraObsticle();
return true; return true;
} }
} }
break; break;
case 2: case 2:
for (int y = sY; y < _height; y++) for (int y = sY; y < _height; y++)
{ {
if (_map[y][sX]) if (_map[y][sX])
{ {
pos = new(sX, y); pos = new(sX, y);
ResetExtraObsticle(); ResetExtraObsticle();
return true; return true;
} }
} }
break; break;
case 3: case 3:
var rowLeft = _map[sY]; var rowLeft = _map[sY];
for (int x = sX; x >= 0; x--) for (int x = sX; x >= 0; x--)
{ {
if (rowLeft[x]) if (rowLeft[x])
{ {
pos = new(x, sY); pos = new(x, sY);
ResetExtraObsticle(); ResetExtraObsticle();
return true; return true;
} }
} }
break; break;
} }
void ResetExtraObsticle() void ResetExtraObsticle()
{ {
if (extraObsticle is Vec2<int> ex) if (extraObsticle is Vec2<int> ex)
_map[ex.Y][ex.X] = false; _map[ex.Y][ex.X] = false;
} }
ResetExtraObsticle(); ResetExtraObsticle();
return false; return false;
} }
public void PrintBoard(List<GuardNode> nodes, Vec2<int> start, Vec2<int>? extraObsticle = null) public void PrintBoard(List<GuardNode> nodes, Vec2<int> start, Vec2<int>? extraObsticle = null)
{ {
var path = GetPathSet(nodes); var path = GetPathSet(nodes);
for (int y = 0; y < _height; y++) for (int y = 0; y < _height; y++)
{ {
for (int x = 0; x < _width; x++) for (int x = 0; x < _width; x++)
{ {
Console.ResetColor(); Console.ResetColor();
var p = new Vec2<int>(x, y); var p = new Vec2<int>(x, y);
var node = nodes.FirstOrDefault(n => n.Pos == p, new GuardNode(p, 0, -1)); var node = nodes.FirstOrDefault(n => n.Pos == p, new GuardNode(p, 0, -1));
if (node.Id != -1) if (node.Id != -1)
{ {
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
if (node.Id == 0) if (node.Id == 0)
Console.ForegroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Yellow;
else if (node.Id == nodes.Count - 1) else if (node.Id == nodes.Count - 1)
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
switch (node.Direction) switch (node.Direction)
{ {
case 0: case 0:
Console.Write('^'); Console.Write('^');
break; break;
case 1: case 1:
Console.Write('>'); Console.Write('>');
break; break;
case 2: case 2:
Console.Write('v'); Console.Write('v');
break; break;
case 3: case 3:
Console.Write('<'); Console.Write('<');
break; break;
} }
continue; continue;
} }
if (p == start) if (p == start)
{ {
Console.ForegroundColor = ConsoleColor.Magenta; Console.ForegroundColor = ConsoleColor.Magenta;
Console.Write('S'); Console.Write('S');
} }
if (_map[y][x]) if (_map[y][x])
Console.Write('#'); Console.Write('#');
else if (p == extraObsticle) else if (p == extraObsticle)
{ {
Console.ForegroundColor = ConsoleColor.DarkBlue; Console.ForegroundColor = ConsoleColor.DarkBlue;
Console.Write('$'); Console.Write('$');
} }
else if (path.Contains(p)) else if (path.Contains(p))
{ {
Console.ForegroundColor = ConsoleColor.DarkGray; Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Write('.'); Console.Write('.');
} }
else else
Console.Write(' '); Console.Write(' ');
} }
Console.WriteLine(); Console.WriteLine();
} }
} }
} }
file struct GuardNode file struct GuardNode
{ {
public int Id { get; private set; } public int Id { get; private set; }
public Vec2<int> Pos { get; } public Vec2<int> Pos { get; }
public int Direction { get; } public int Direction { get; }
public int? Next { get; set; } public int? Next { get; set; }
public GuardNode(Vec2<int> pos, int dir, int id) public GuardNode(Vec2<int> pos, int dir, int id)
{ {
Pos = pos; Pos = pos;
Direction = dir; Direction = dir;
Id = id; Id = id;
} }
public bool IsLoop(List<GuardNode> nodes) public bool IsLoop(List<GuardNode> nodes)
{ {
return NodeExists(Id, nodes); return NodeExists(Id, nodes);
} }
public bool NodeExists(int target, List<GuardNode> nodes) public bool NodeExists(int target, List<GuardNode> nodes)
{ {
if (Next == target) if (Next == target)
return true; return true;
if (Next is int id) if (Next is int id)
return nodes[id].NodeExists(target, nodes); return nodes[id].NodeExists(target, nodes);
return false; return false;
} }
public override string ToString() public override string ToString()
{ {
return $"{Pos}: {Direction}"; return $"{Pos}: {Direction}";
} }
} }

View File

@@ -1,70 +1,70 @@
namespace AdventOfCode.Problems.AOC2024.Day7; namespace AdventOfCode.Problems.AOC2024.Day7;
[ProblemInfo(2024, 7, "Bridge Repair")] [ProblemInfo(2024, 7, "Bridge Repair")]
internal class BridgeRepair : Problem<ulong, ulong> internal class BridgeRepair : Problem<ulong, ulong>
{ {
private List<(ulong total, ulong[] nums)> _data = []; private List<(ulong total, ulong[] nums)> _data = [];
private enum Operator private enum Operator
{ {
Mul, Mul,
Add, Add,
Concat Concat
} }
public override void CalculatePart1() public override void CalculatePart1()
{ {
foreach (var (target, nums) in _data) foreach (var (target, nums) in _data)
{ {
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add])) if (IsSolvable(target, nums, [Operator.Mul, Operator.Add]))
Part1 += target; Part1 += target;
} }
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
foreach (var (target, nums) in _data) foreach (var (target, nums) in _data)
{ {
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add, Operator.Concat])) if (IsSolvable(target, nums, [Operator.Mul, Operator.Add, Operator.Concat]))
Part2 += target; Part2 += target;
} }
} }
private static bool IsSolvable(ulong target, ulong[] nums, Operator[] ops) private static bool IsSolvable(ulong target, ulong[] nums, Operator[] ops)
{ {
return ops.Any(o => IsSolvable(target, nums, o, nums[0], ops)); return ops.Any(o => IsSolvable(target, nums, o, nums[0], ops));
} }
private static bool IsSolvable(ulong target, ulong[] nums, Operator curOperator, ulong curTotal, Operator[] ops, int idx = 1) private static bool IsSolvable(ulong target, ulong[] nums, Operator curOperator, ulong curTotal, Operator[] ops, int idx = 1)
{ {
if (target == curTotal && idx == nums.Length) if (target == curTotal && idx == nums.Length)
return true; return true;
if (curTotal > target) if (curTotal > target)
return false; return false;
if (idx >= nums.Length) if (idx >= nums.Length)
return false; return false;
curTotal = curOperator switch curTotal = curOperator switch
{ {
Operator.Mul => curTotal * nums[idx], Operator.Mul => curTotal * nums[idx],
Operator.Add => curTotal + nums[idx], Operator.Add => curTotal + nums[idx],
Operator.Concat => ulong.Parse($"{curTotal}{nums[idx]}"), Operator.Concat => ulong.Parse($"{curTotal}{nums[idx]}"),
_ => throw new InvalidOperationException(), _ => throw new InvalidOperationException(),
}; };
return ops.Any(o => IsSolvable(target, nums, o, curTotal, ops, idx + 1)); return ops.Any(o => IsSolvable(target, nums, o, curTotal, ops, idx + 1));
} }
public override void LoadInput() public override void LoadInput()
{ {
var lines = ReadInputLines("input.txt"); var lines = ReadInputLines("input.txt");
_data = new List<(ulong total, ulong[] nums)>(lines.Length); _data = new List<(ulong total, ulong[] nums)>(lines.Length);
foreach (var line in lines) foreach (var line in lines)
{ {
var s = line.Split(':'); var s = line.Split(':');
var sum = ulong.Parse(s[0].Trim()); var sum = ulong.Parse(s[0].Trim());
var nums = s[1].Trim().Split(' ').Select(ulong.Parse).ToArray(); var nums = s[1].Trim().Split(' ').Select(ulong.Parse).ToArray();
_data.Add((sum, nums)); _data.Add((sum, nums));
} }
} }
} }

View File

@@ -1,139 +1,139 @@
using AdventOfCode.Utils.Models; using AdventOfCode.Utils.Models;
using System.Collections.Frozen; using System.Collections.Frozen;
namespace AdventOfCode.Problems.AOC2024.Day8; namespace AdventOfCode.Problems.AOC2024.Day8;
[ProblemInfo(2024, 8, "Resonant Collinearity")] [ProblemInfo(2024, 8, "Resonant Collinearity")]
internal class ResonantCollinearity : Problem<int, int> internal class ResonantCollinearity : Problem<int, int>
{ {
private string[] _map = []; private string[] _map = [];
private int _width; private int _width;
private int _height; private int _height;
private FrozenDictionary<char, List<Vec2<int>>> _nodes = FrozenDictionary<char, List<Vec2<int>>>.Empty; private FrozenDictionary<char, List<Vec2<int>>> _nodes = FrozenDictionary<char, List<Vec2<int>>>.Empty;
public override void CalculatePart1() public override void CalculatePart1()
{ {
var antiNodes = new List<Vec2<int>>(); var antiNodes = new List<Vec2<int>>();
foreach (var (nodeType, nodes) in _nodes) foreach (var (nodeType, nodes) in _nodes)
{ {
foreach (var a in nodes) foreach (var a in nodes)
{ {
foreach (var b in nodes) foreach (var b in nodes)
{ {
if (a == b) if (a == b)
continue; continue;
antiNodes.AddRange(GetAntiNodes(a, b)); antiNodes.AddRange(GetAntiNodes(a, b));
} }
} }
} }
//PrintBoard(antiNodes); //PrintBoard(antiNodes);
Part1 = antiNodes.Where(IsInBounds).Distinct().Count(); Part1 = antiNodes.Where(IsInBounds).Distinct().Count();
} }
public void PrintBoard(List<Vec2<int>> antinodes) public void PrintBoard(List<Vec2<int>> antinodes)
{ {
Console.WriteLine(); Console.WriteLine();
for (int y = 0; y < _height; y++) for (int y = 0; y < _height; y++)
{ {
for (int x = 0; x < _width; x++) for (int x = 0; x < _width; x++)
{ {
Console.ResetColor(); Console.ResetColor();
var p = new Vec2<int>(x, y); var p = new Vec2<int>(x, y);
if (antinodes.Contains(p)) if (antinodes.Contains(p))
Console.BackgroundColor = ConsoleColor.DarkGreen; Console.BackgroundColor = ConsoleColor.DarkGreen;
Console.Write(_map[y][x]); Console.Write(_map[y][x]);
} }
Console.ResetColor(); Console.ResetColor();
Console.WriteLine(); Console.WriteLine();
} }
Console.ResetColor(); Console.ResetColor();
} }
public bool IsInBounds(Vec2<int> pos) public bool IsInBounds(Vec2<int> pos)
{ {
if (pos.X < 0 || pos.Y < 0) if (pos.X < 0 || pos.Y < 0)
return false; return false;
if (pos.X >= _width || pos.Y >= _height) if (pos.X >= _width || pos.Y >= _height)
return false; return false;
return true; return true;
} }
private Vec2<int>[] GetAntiNodes(Vec2<int> a, Vec2<int> b) private Vec2<int>[] GetAntiNodes(Vec2<int> a, Vec2<int> b)
{ {
var dir = a - b; var dir = a - b;
var aNode1 = dir + a; var aNode1 = dir + a;
var aNode2 = -dir + b; var aNode2 = -dir + b;
return [aNode1, aNode2]; return [aNode1, aNode2];
} }
private Vec2<int>[] GetHarmonicAntiNodes(Vec2<int> a, Vec2<int> b) private Vec2<int>[] GetHarmonicAntiNodes(Vec2<int> a, Vec2<int> b)
{ {
var dir = a - b; var dir = a - b;
List<Vec2<int>> GetNodes(Vec2<int> start, Vec2<int> dir) List<Vec2<int>> GetNodes(Vec2<int> start, Vec2<int> dir)
{ {
var results = new List<Vec2<int>>(); var results = new List<Vec2<int>>();
while (true) while (true)
{ {
var p = dir + start; var p = dir + start;
if(!IsInBounds(p)) if(!IsInBounds(p))
break; break;
results.Add(p); results.Add(p);
start = p; start = p;
} }
return results; return results;
} }
return [.. GetNodes(a, dir), .. GetNodes(b, -dir)]; return [.. GetNodes(a, dir), .. GetNodes(b, -dir)];
} }
public override void CalculatePart2() public override void CalculatePart2()
{ {
var antiNodes = new List<Vec2<int>>(); var antiNodes = new List<Vec2<int>>();
foreach (var (nodeType, nodes) in _nodes) foreach (var (nodeType, nodes) in _nodes)
{ {
foreach (var a in nodes) foreach (var a in nodes)
{ {
foreach (var b in nodes) foreach (var b in nodes)
{ {
if (a == b) if (a == b)
continue; continue;
antiNodes.AddRange(GetHarmonicAntiNodes(a, b)); antiNodes.AddRange(GetHarmonicAntiNodes(a, b));
} }
} }
} }
//PrintBoard(antiNodes); //PrintBoard(antiNodes);
antiNodes.AddRange(_nodes.Values.Where(v => v.Count > 1).SelectMany(v => v)); antiNodes.AddRange(_nodes.Values.Where(v => v.Count > 1).SelectMany(v => v));
Part2 = antiNodes.Distinct().Count(); Part2 = antiNodes.Distinct().Count();
} }
public override void LoadInput() public override void LoadInput()
{ {
_map = ReadInputLines("input.txt"); _map = ReadInputLines("input.txt");
var nodes = new Dictionary<char, List<Vec2<int>>>(); var nodes = new Dictionary<char, List<Vec2<int>>>();
_width = _map[0].Length; _width = _map[0].Length;
_height = _map.Length; _height = _map.Length;
for (int y = 0; y < _map.Length; y++) for (int y = 0; y < _map.Length; y++)
{ {
var row = _map[y]; var row = _map[y];
for (int x = 0; x < row.Length; x++) for (int x = 0; x < row.Length; x++)
{ {
switch (row[x]) switch (row[x])
{ {
case '.': case '.':
continue; continue;
default: default:
var p = new Vec2<int>(x, y); var p = new Vec2<int>(x, y);
if (!nodes.TryAdd(row[x], [p])) if (!nodes.TryAdd(row[x], [p]))
nodes[row[x]].Add(p); nodes[row[x]].Add(p);
continue; continue;
} }
} }
} }
_nodes = nodes.ToFrozenDictionary(); _nodes = nodes.ToFrozenDictionary();
} }
} }

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

@@ -1,7 +1,7 @@
global using AdventOfCode.Runner; global using AdventOfCode.Runner;
global using AdventOfCode.Runner.Attributes; global using AdventOfCode.Runner.Attributes;
global using AdventOfCode.Utils; global using AdventOfCode.Utils;
var runner = new AOCRunner(); var runner = new AOCRunner();
runner.RenderInteractiveMenu(); runner.RenderInteractiveMenu();

View File

@@ -1,424 +1,424 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
namespace AdventOfCode.Runner; namespace AdventOfCode.Runner;
public class AOCRunner public class AOCRunner
{ {
private Dictionary<int, List<(ProblemInfoAttribute info, Type type)>> _loadedProblems; private Dictionary<int, List<(ProblemInfoAttribute info, Type type)>> _loadedProblems;
private List<int> _years; private List<int> _years;
private int _selectedYear; private int _selectedYear;
private int _selectedDay; private int _selectedDay;
private int _scollOffset = 0; private int _scollOffset = 0;
private int _maxProblemCount; private int _maxProblemCount;
private bool _isQuiting; private bool _isQuiting;
private bool _isProblemMode = false; private bool _isProblemMode = false;
public AOCRunner() public AOCRunner()
{ {
Console.OutputEncoding = Encoding.UTF8; Console.OutputEncoding = Encoding.UTF8;
_loadedProblems = new(); _loadedProblems = new();
_years = new List<int>(); _years = new List<int>();
_selectedYear = DateTime.Now.Year; _selectedYear = DateTime.Now.Year;
FindProblemClasses(); FindProblemClasses();
if (!_loadedProblems.ContainsKey(_selectedYear)) if (!_loadedProblems.ContainsKey(_selectedYear))
_selectedYear = _loadedProblems.Keys.First(); _selectedYear = _loadedProblems.Keys.First();
InitSizing(); InitSizing();
if (_years.Count > 0) if (_years.Count > 0)
{ {
_selectedDay = _loadedProblems[_selectedYear].Count - 1; _selectedDay = _loadedProblems[_selectedYear].Count - 1;
ConstrainListScroll(); ConstrainListScroll();
} }
} }
public AOCRunner WithDay(int day) public AOCRunner WithDay(int day)
{ {
var problem = _loadedProblems[_selectedYear].FirstOrDefault(d => d.info.Day == day); var problem = _loadedProblems[_selectedYear].FirstOrDefault(d => d.info.Day == day);
if (problem == default) if (problem == default)
throw new ArgumentException($"There are no problems have been loaded for the day '{day}' of year '{_selectedYear}'", nameof(day)); throw new ArgumentException($"There are no problems have been loaded for the day '{day}' of year '{_selectedYear}'", nameof(day));
_selectedDay = _loadedProblems[_selectedYear].IndexOf(problem); _selectedDay = _loadedProblems[_selectedYear].IndexOf(problem);
return this; return this;
} }
public AOCRunner WithYear(int year) public AOCRunner WithYear(int year)
{ {
if (!_loadedProblems.ContainsKey(year)) if (!_loadedProblems.ContainsKey(year))
throw new ArgumentException($"There are no problems have been loaded for the year '{year}'", nameof(year)); throw new ArgumentException($"There are no problems have been loaded for the year '{year}'", nameof(year));
_selectedYear = year; _selectedYear = year;
return this; return this;
} }
private void InitSizing() private void InitSizing()
{ {
_maxProblemCount = Console.WindowHeight - 9; _maxProblemCount = Console.WindowHeight - 9;
} }
private void ConstrainListScroll() private void ConstrainListScroll()
{ {
if (_selectedDay >= _maxProblemCount) if (_selectedDay >= _maxProblemCount)
{ {
_scollOffset = _loadedProblems[_selectedYear].Count - _maxProblemCount; _scollOffset = _loadedProblems[_selectedYear].Count - _maxProblemCount;
} }
if (_selectedDay < _scollOffset) if (_selectedDay < _scollOffset)
{ {
_scollOffset = _selectedDay; _scollOffset = _selectedDay;
} }
} }
private void FindProblemClasses() private void FindProblemClasses()
{ {
var types = Assembly.GetExecutingAssembly().DefinedTypes.Where(t => !t.IsAbstract); var types = Assembly.GetExecutingAssembly().DefinedTypes.Where(t => !t.IsAbstract);
if (types == null) if (types == null)
return; return;
foreach (var type in types) foreach (var type in types)
{ {
var info = type.GetCustomAttribute<ProblemInfoAttribute>(); var info = type.GetCustomAttribute<ProblemInfoAttribute>();
if (info == null) if (info == null)
continue; continue;
if (_loadedProblems.TryGetValue(info.Year, out var list)) if (_loadedProblems.TryGetValue(info.Year, out var list))
list.Add((info, type)); list.Add((info, type));
else else
_loadedProblems.Add(info.Year, new() { (info, type) }); _loadedProblems.Add(info.Year, new() { (info, type) });
} }
foreach (var (year, list) in _loadedProblems) foreach (var (year, list) in _loadedProblems)
_loadedProblems[year] = list.OrderBy(l => l.info.Day).ToList(); _loadedProblems[year] = list.OrderBy(l => l.info.Day).ToList();
_years = _loadedProblems.Keys.OrderDescending().ToList(); _years = _loadedProblems.Keys.OrderDescending().ToList();
} }
private void RunDay(int year, int dayIndex) private void RunDay(int year, int dayIndex)
{ {
var yearList = _loadedProblems[year]; var yearList = _loadedProblems[year];
if (yearList.Count <= dayIndex || dayIndex < 0) if (yearList.Count <= dayIndex || dayIndex < 0)
Console.WriteLine($"No problem exists for day index {dayIndex}"); Console.WriteLine($"No problem exists for day index {dayIndex}");
Console.Clear(); Console.Clear();
var (info, problemType) = yearList[dayIndex]; var (info, problemType) = yearList[dayIndex];
Console.Write("Problem: "); Console.Write("Problem: ");
Console.ForegroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"\t{info.Name}"); Console.WriteLine($"\t{info.Name}");
Console.ForegroundColor = ConsoleColor.DarkRed; Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"\t\t{info.Year} - Day {info.Day}"); Console.WriteLine($"\t\t{info.Year} - Day {info.Day}");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
if (Activator.CreateInstance(problemType) is not IProblem problem) if (Activator.CreateInstance(problemType) is not IProblem problem)
{ {
Console.WriteLine("Failed to create problem isntance"); Console.WriteLine("Failed to create problem isntance");
return; return;
} }
var time = ReadInput(problem); var time = ReadInput(problem);
time += RunPart("Calculating Part 1", problem.CalculatePart1); time += RunPart("Calculating Part 1", problem.CalculatePart1);
time += RunPart("Calculating Part 2", problem.CalculatePart2); time += RunPart("Calculating Part 2", problem.CalculatePart2);
Console.WriteLine(); Console.WriteLine();
Console.Write($"Total Elapsed Time: "); Console.Write($"Total Elapsed Time: ");
Console.ForegroundColor = ConsoleColor.Cyan; Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"{time.TotalMilliseconds}ms"); Console.WriteLine($"{time.TotalMilliseconds}ms");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Printing Results:"); Console.WriteLine("Printing Results:");
Console.WriteLine("---- Part 1 ----"); Console.WriteLine("---- Part 1 ----");
problem.PrintPart1(); problem.PrintPart1();
Console.Write("\n\n"); Console.Write("\n\n");
Console.WriteLine("---- Part 2 ----"); Console.WriteLine("---- Part 2 ----");
problem.PrintPart2(); problem.PrintPart2();
Console.Write("\n\n"); Console.Write("\n\n");
} }
private static TimeSpan ReadInput(IProblem problem) private static TimeSpan ReadInput(IProblem problem)
{ {
var sw = new Stopwatch(); var sw = new Stopwatch();
Console.WriteLine(); Console.WriteLine();
Console.Write("Loading Input data... "); Console.Write("Loading Input data... ");
sw.Start(); sw.Start();
problem.LoadInput(); problem.LoadInput();
sw.Stop(); sw.Stop();
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
Console.Write("Done in "); Console.Write("Done in ");
Console.ForegroundColor = ConsoleColor.Cyan; Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms"); Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
return sw.Elapsed; return sw.Elapsed;
} }
private static TimeSpan RunPart(string name, Action action) private static TimeSpan RunPart(string name, Action action)
{ {
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
var sw = new Stopwatch(); var sw = new Stopwatch();
Console.Write($"{name}... "); Console.Write($"{name}... ");
try try
{ {
sw.Start(); sw.Start();
action(); action();
sw.Stop(); sw.Stop();
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
Console.Write("Done in "); Console.Write("Done in ");
Console.ForegroundColor = ConsoleColor.Cyan; Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms"); Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
} }
catch (NotImplementedException) catch (NotImplementedException)
{ {
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Not Implemented"); Console.WriteLine("Not Implemented");
} }
//catch (Exception e) //catch (Exception e)
//{ //{
// Console.ForegroundColor = ConsoleColor.Red; // Console.ForegroundColor = ConsoleColor.Red;
// Console.WriteLine("Failed"); // Console.WriteLine("Failed");
// Console.WriteLine(e); // Console.WriteLine(e);
//} //}
finally finally
{ {
sw.Stop(); sw.Stop();
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
} }
return sw.Elapsed; return sw.Elapsed;
} }
public void RenderInteractiveMenu() public void RenderInteractiveMenu()
{ {
Console.BackgroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Console.CursorVisible = false; Console.CursorVisible = false;
Console.Clear(); Console.Clear();
while (!_isQuiting) while (!_isQuiting)
{ {
InitSizing(); InitSizing();
RenderTopBar(); RenderTopBar();
RenderContentView(); RenderContentView();
ReadInput(); ReadInput();
} }
} }
private void ReadInput() private void ReadInput()
{ {
var input = Console.ReadKey(true); var input = Console.ReadKey(true);
if (_isProblemMode) if (_isProblemMode)
{ {
if (input.Key is ConsoleKey.Enter or ConsoleKey.Escape) if (input.Key is ConsoleKey.Enter or ConsoleKey.Escape)
{ {
_isProblemMode = false; _isProblemMode = false;
Console.Clear(); Console.Clear();
} }
return; return;
} }
var yearIndex = _years.IndexOf(_selectedYear); var yearIndex = _years.IndexOf(_selectedYear);
var dayMax = _loadedProblems[_selectedYear].Count - 1; var dayMax = _loadedProblems[_selectedYear].Count - 1;
switch (input.Key) switch (input.Key)
{ {
case ConsoleKey.LeftArrow: case ConsoleKey.LeftArrow:
_scollOffset = 0; _scollOffset = 0;
_selectedDay = 0; _selectedDay = 0;
if (yearIndex == 0) if (yearIndex == 0)
{ {
_selectedYear = _years.Last(); _selectedYear = _years.Last();
break; break;
} }
_selectedYear = _years[--yearIndex]; _selectedYear = _years[--yearIndex];
break; break;
case ConsoleKey.RightArrow: case ConsoleKey.RightArrow:
_scollOffset = 0; _scollOffset = 0;
_selectedDay = 0; _selectedDay = 0;
if (yearIndex == _years.Count - 1) if (yearIndex == _years.Count - 1)
{ {
_selectedYear = _years.First(); _selectedYear = _years.First();
break; break;
} }
_selectedYear = _years[++yearIndex]; _selectedYear = _years[++yearIndex];
break; break;
case ConsoleKey.UpArrow: case ConsoleKey.UpArrow:
if (_selectedDay == 0) if (_selectedDay == 0)
{ {
_selectedDay = dayMax; _selectedDay = dayMax;
break; break;
} }
_selectedDay--; _selectedDay--;
break; break;
case ConsoleKey.DownArrow: case ConsoleKey.DownArrow:
if (_selectedDay == dayMax) if (_selectedDay == dayMax)
{ {
_selectedDay = 0; _selectedDay = 0;
break; break;
} }
_selectedDay++; _selectedDay++;
break; break;
case ConsoleKey.Enter: case ConsoleKey.Enter:
_isProblemMode = true; _isProblemMode = true;
break; break;
case ConsoleKey.Escape: case ConsoleKey.Escape:
_isQuiting = true; _isQuiting = true;
break; break;
} }
ConstrainListScroll(); ConstrainListScroll();
} }
private void RenderTopBar() private void RenderTopBar()
{ {
if (_isProblemMode) if (_isProblemMode)
return; return;
//Render Border //Render Border
DrawBorder(1, 0, Console.WindowWidth, 3); DrawBorder(1, 0, Console.WindowWidth, 3);
Console.SetCursorPosition(Console.WindowWidth / 2 - 4, 1); Console.SetCursorPosition(Console.WindowWidth / 2 - 4, 1);
Console.ForegroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(" Years "); Console.Write(" Years ");
//Render Tabs //Render Tabs
RenderTabList(); RenderTabList();
} }
private void RenderTabList() private void RenderTabList()
{ {
var buttonWidth = 6; var buttonWidth = 6;
var tabMaxPos = Console.WindowWidth - 3; var tabMaxPos = Console.WindowWidth - 3;
for (int i = 0; i < _years.Count; i++) for (int i = 0; i < _years.Count; i++)
{ {
var year = _years[i]; var year = _years[i];
var col = (i * 7) + 2; var col = (i * 7) + 2;
var end = col + buttonWidth; var end = col + buttonWidth;
if (end >= tabMaxPos) if (end >= tabMaxPos)
break; break;
if (year == _selectedYear) if (year == _selectedYear)
DrawSelectedButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Red, ConsoleColor.Blue); DrawSelectedButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Red, ConsoleColor.Blue);
else else
DrawButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Gray, Console.BackgroundColor); DrawButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Gray, Console.BackgroundColor);
} }
} }
private void RenderContentView() private void RenderContentView()
{ {
if (!_isProblemMode) if (!_isProblemMode)
{ {
DrawBorder(5, 0, Console.WindowWidth, Console.WindowHeight - 5); DrawBorder(5, 0, Console.WindowWidth, Console.WindowHeight - 5);
Console.SetCursorPosition(Console.WindowWidth / 2 - 5, 5); Console.SetCursorPosition(Console.WindowWidth / 2 - 5, 5);
Console.ForegroundColor = ConsoleColor.Blue; Console.ForegroundColor = ConsoleColor.Blue;
Console.Write(" Problems "); Console.Write(" Problems ");
RenderProblemList(); RenderProblemList();
} }
else else
RenderProblemResults(); RenderProblemResults();
} }
private void RenderProblemList() private void RenderProblemList()
{ {
if (_loadedProblems.Count == 0) if (_loadedProblems.Count == 0)
{ {
DrawButton("There are no problems...", 6, 2, Console.WindowWidth - 2, Console.WindowHeight - 7); DrawButton("There are no problems...", 6, 2, Console.WindowWidth - 2, Console.WindowHeight - 7);
return; return;
} }
var problems = _loadedProblems[_selectedYear]; var problems = _loadedProblems[_selectedYear];
var listEnd = Math.Min(_maxProblemCount, problems.Count); var listEnd = Math.Min(_maxProblemCount, problems.Count);
for (int i = 0; i < listEnd; i++) for (int i = 0; i < listEnd; i++)
{ {
var (info, _) = problems[i + _scollOffset]; var (info, _) = problems[i + _scollOffset];
var buttonText = $"{i + _scollOffset}.\t[Day {info.Day}] {info.Name}"; var buttonText = $"{i + _scollOffset}.\t[Day {info.Day}] {info.Name}";
var row = i + 7; var row = i + 7;
if (i + _scollOffset == _selectedDay) if (i + _scollOffset == _selectedDay)
DrawSelectedButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.DarkMagenta, ConsoleColor.DarkGray, false, 2); DrawSelectedButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.DarkMagenta, ConsoleColor.DarkGray, false, 2);
else else
DrawButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.Cyan, Console.BackgroundColor, false, 2); DrawButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.Cyan, Console.BackgroundColor, false, 2);
} }
for (int i = problems.Count + 7; i < Console.WindowHeight - 2; i++) for (int i = problems.Count + 7; i < Console.WindowHeight - 2; i++)
{ {
Console.SetCursorPosition(2, i); Console.SetCursorPosition(2, i);
Console.Write(new string(' ', Console.WindowWidth - 4)); Console.Write(new string(' ', Console.WindowWidth - 4));
} }
} }
private void RenderProblemResults() private void RenderProblemResults()
{ {
Console.SetCursorPosition(2, 7); Console.SetCursorPosition(2, 7);
RunDay(_selectedYear, _selectedDay); RunDay(_selectedYear, _selectedDay);
} }
private void DrawSelectedButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0) private void DrawSelectedButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
{ {
//text = $"\ue0c7{text}\ue0c6"; //text = $"\ue0c7{text}\ue0c6";
var origBg = Console.BackgroundColor; var origBg = Console.BackgroundColor;
Console.BackgroundColor = background; Console.BackgroundColor = background;
for (int y = row; y < row + height; y++) for (int y = row; y < row + height; y++)
{ {
Console.SetCursorPosition(col, y); Console.SetCursorPosition(col, y);
Console.Write(new string(' ', width)); Console.Write(new string(' ', width));
} }
Console.ForegroundColor = color; Console.ForegroundColor = color;
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding; var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
var yOffset = centered ? height / 2 : padding; var yOffset = centered ? height / 2 : padding;
if (height == 1) if (height == 1)
yOffset = 0; yOffset = 0;
Console.SetCursorPosition(col + xOffset, row + yOffset); Console.SetCursorPosition(col + xOffset, row + yOffset);
Console.Write(text); Console.Write(text);
Console.BackgroundColor = origBg; Console.BackgroundColor = origBg;
Console.ForegroundColor = background; Console.ForegroundColor = background;
Console.SetCursorPosition(col, row + height / 2); Console.SetCursorPosition(col, row + height / 2);
Console.Write('\ue0c7'); Console.Write('\ue0c7');
Console.SetCursorPosition(col + width - 1, row + height / 2); Console.SetCursorPosition(col + width - 1, row + height / 2);
Console.Write('\ue0c6'); Console.Write('\ue0c6');
Console.BackgroundColor = origBg; Console.BackgroundColor = origBg;
} }
private void DrawButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0) private void DrawButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
{ {
var origBg = Console.BackgroundColor; var origBg = Console.BackgroundColor;
Console.BackgroundColor = background; Console.BackgroundColor = background;
for (int y = row; y < row + height; y++) for (int y = row; y < row + height; y++)
{ {
Console.SetCursorPosition(col, y); Console.SetCursorPosition(col, y);
Console.Write(new string(' ', width)); Console.Write(new string(' ', width));
} }
Console.ForegroundColor = color; Console.ForegroundColor = color;
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding; var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
var yOffset = centered ? height / 2 : padding; var yOffset = centered ? height / 2 : padding;
if (height == 1) if (height == 1)
yOffset = 0; yOffset = 0;
Console.SetCursorPosition(col + xOffset, row + yOffset); Console.SetCursorPosition(col + xOffset, row + yOffset);
Console.Write(text); Console.Write(text);
Console.BackgroundColor = origBg; Console.BackgroundColor = origBg;
} }
private void DrawBorder(int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, bool drawFill = false) private void DrawBorder(int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, bool drawFill = false)
{ {
//║═╔╗╝╚ //║═╔╗╝╚
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
var w = col + width - 1; var w = col + width - 1;
var h = row + height - 1; var h = row + height - 1;
for (int x = col; x <= w; x++) for (int x = col; x <= w; x++)
{ {
for (int y = row; y <= h; y++) for (int y = row; y <= h; y++)
{ {
Console.SetCursorPosition(x, y); Console.SetCursorPosition(x, y);
if (x == col && y == row) if (x == col && y == row)
Console.Write('╔'); Console.Write('╔');
else if (x == col && y == h) else if (x == col && y == h)
Console.Write('╚'); Console.Write('╚');
else if (x == w && y == row) else if (x == w && y == row)
Console.Write('╗'); Console.Write('╗');
else if (x == w && y == h) else if (x == w && y == h)
Console.Write('╝'); Console.Write('╝');
else if (x == col || x == w) else if (x == col || x == w)
Console.Write('║'); Console.Write('║');
else if (y == row || y == h) else if (y == row || y == h)
Console.Write('═'); Console.Write('═');
else if (drawFill) else if (drawFill)
Console.Write(' '); Console.Write(' ');
} }
} }
} }
} }

View File

@@ -1,15 +1,15 @@
namespace AdventOfCode.Runner.Attributes; namespace AdventOfCode.Runner.Attributes;
public class ProblemInfoAttribute : Attribute public class ProblemInfoAttribute : Attribute
{ {
public int Day { get; init; } public int Day { get; init; }
public int Year { get; init; } public int Year { get; init; }
public string Name { get; init; } public string Name { get; init; }
public ProblemInfoAttribute(int year, int day, string name) public ProblemInfoAttribute(int year, int day, string name)
{ {
Year = year; Year = year;
Day = day; Day = day;
Name = name; Name = name;
} }
} }

View File

@@ -1,63 +1,63 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace AdventOfCode.Runner; namespace AdventOfCode.Runner;
public static class Extensions public static class Extensions
{ {
public static IEnumerable<T> Print<T>(this IEnumerable<T> values) public static IEnumerable<T> Print<T>(this IEnumerable<T> values)
{ {
foreach (var item in values) foreach (var item in values)
{ {
Console.WriteLine(item); Console.WriteLine(item);
} }
return values; return values;
} }
public static T LCM<T>(this IEnumerable<T> values) where T : INumber<T> public static T LCM<T>(this IEnumerable<T> values) where T : INumber<T>
{ {
var a = values.First(); var a = values.First();
values = values.Skip(1); values = values.Skip(1);
foreach (var item in values) foreach (var item in values)
{ {
a = a.LCM(item); a = a.LCM(item);
} }
return a; return a;
} }
public static IEnumerable<IEnumerable<T2>> Transpose<T, T2>(this IEnumerable<T> data) where T: IEnumerable<T2> public static IEnumerable<IEnumerable<T2>> Transpose<T, T2>(this IEnumerable<T> data) where T: IEnumerable<T2>
{ {
var range = Enumerable.Range(0, data.First().Count()); var range = Enumerable.Range(0, data.First().Count());
return range.Select(i => data.Select(l => l.Skip(i).First())); return range.Select(i => data.Select(l => l.Skip(i).First()));
} }
public static IEnumerable<T> Transpose<T, T2>(this IEnumerable<T> data, Func<IEnumerable<T2>, T> formatter) where T : IEnumerable<T2> public static IEnumerable<T> Transpose<T, T2>(this IEnumerable<T> data, Func<IEnumerable<T2>, T> formatter) where T : IEnumerable<T2>
{ {
var range = Enumerable.Range(0, data.First().Count()); var range = Enumerable.Range(0, data.First().Count());
return range.Select(i => formatter(data.Select(l => l.Skip(i).First()))); return range.Select(i => formatter(data.Select(l => l.Skip(i).First())));
} }
public static IEnumerable<string> Transpose(this IEnumerable<string> data) public static IEnumerable<string> Transpose(this IEnumerable<string> data)
{ {
return Transpose<string, char>(data, a => string.Join("", a)); return Transpose<string, char>(data, a => string.Join("", a));
} }
public static IEnumerable<List<T>> Permute<T>(this IEnumerable<T> values) public static IEnumerable<List<T>> Permute<T>(this IEnumerable<T> values)
{ {
IEnumerable<List<T>> permutate(IEnumerable<T> reminder, IEnumerable<T> prefix) IEnumerable<List<T>> permutate(IEnumerable<T> reminder, IEnumerable<T> prefix)
{ {
return !reminder.Any() return !reminder.Any()
? new List<List<T>> { prefix.ToList() } ? new List<List<T>> { prefix.ToList() }
: reminder.SelectMany((c, i) => permutate( : reminder.SelectMany((c, i) => permutate(
reminder.Take(i).Concat(reminder.Skip(i + 1)).ToList(), reminder.Take(i).Concat(reminder.Skip(i + 1)).ToList(),
prefix.Append(c))); prefix.Append(c)));
} }
return permutate(values, Enumerable.Empty<T>()); return permutate(values, Enumerable.Empty<T>());
} }
} }

View File

@@ -1,37 +1,37 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text; 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>
{ {
while (!b.Equals(T.Zero)) while (!b.Equals(T.Zero))
{ {
var t = b; var t = b;
b = a % b; b = a % b;
a = t; a = t;
} }
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> public static T Max<T>(this T a, T b) where T : INumber<T>
{ {
return T.Max(a, b); return T.Max(a, b);
} }
public static T Min<T>(this T a, T b) where T : INumber<T> public static T Min<T>(this T a, T b) where T : INumber<T>
{ {
return T.Min(a, b); return T.Min(a, b);
} }
} }

View File

@@ -1,89 +1,89 @@
using AdventOfCode.Runner.Attributes; using AdventOfCode.Runner.Attributes;
using System.Reflection; using System.Reflection;
namespace AdventOfCode.Runner; namespace AdventOfCode.Runner;
public interface IProblem public interface IProblem
{ {
void LoadInput(); void LoadInput();
void CalculatePart1(); void CalculatePart1();
void PrintPart1(); void PrintPart1();
void CalculatePart2(); void CalculatePart2();
void PrintPart2(); void PrintPart2();
} }
public abstract class Problem : Problem<string, string> public abstract class Problem : Problem<string, string>
{ {
} }
public abstract class Problem<TPart1, TPart2> : IProblem public abstract class Problem<TPart1, TPart2> : IProblem
{ {
protected TPart1? Part1 { get; set; } protected TPart1? Part1 { get; set; }
protected TPart2? Part2 { get; set; } protected TPart2? Part2 { get; set; }
public abstract void LoadInput(); public abstract void LoadInput();
public abstract void CalculatePart1(); public abstract void CalculatePart1();
public virtual void PrintPart1() public virtual void PrintPart1()
{ {
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
if (Part1 == null) if (Part1 == null)
{ {
Console.Write("Part 1: "); Console.Write("Part 1: ");
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("No Solution"); Console.WriteLine("No Solution");
} }
else else
{ {
Console.Write("Part 1: "); Console.Write("Part 1: ");
Console.ForegroundColor = ConsoleColor.DarkYellow; Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"{Part1}"); Console.WriteLine($"{Part1}");
} }
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
} }
public abstract void CalculatePart2(); public abstract void CalculatePart2();
public virtual void PrintPart2() public virtual void PrintPart2()
{ {
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
if (Part2 == null) if (Part2 == null)
{ {
Console.Write("Part 2: "); Console.Write("Part 2: ");
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("No Solution"); Console.WriteLine("No Solution");
} }
else else
{ {
Console.Write("Part 2: "); Console.Write("Part 2: ");
Console.ForegroundColor = ConsoleColor.DarkYellow; Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine($"{Part2}"); Console.WriteLine($"{Part2}");
} }
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
} }
protected string GetInputFile(string filename = "input.txt") protected string GetInputFile(string filename = "input.txt")
{ {
var info = this.GetType().GetCustomAttribute<ProblemInfoAttribute>(); var info = this.GetType().GetCustomAttribute<ProblemInfoAttribute>();
if (info == null) if (info == null)
return filename; return filename;
return Path.Combine($"Problems/AOC{info.Year}/Day{info.Day}", filename); return Path.Combine($"Problems/AOC{info.Year}/Day{info.Day}", filename);
} }
protected string[] ReadInputLines(string filename = "input.txt") protected string[] ReadInputLines(string filename = "input.txt")
{ {
return File.ReadAllLines(GetInputFile(filename)); return File.ReadAllLines(GetInputFile(filename));
} }
protected string ReadInputText(string filename = "input.txt") protected string ReadInputText(string filename = "input.txt")
{ {
return File.ReadAllText(GetInputFile(filename)); return File.ReadAllText(GetInputFile(filename));
} }
} }

View File

@@ -1,16 +1,25 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Numerics;
using System.Threading.Tasks; using System.Text;
using System.Threading.Tasks;
namespace AdventOfCode.Utils;
public static class Extensions namespace AdventOfCode.Utils;
{ 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;
}
}

View File

@@ -1,48 +1,48 @@
using System.Numerics; using System.Numerics;
namespace AdventOfCode.Utils.Models; 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> Zero => new (T.Zero, T.Zero);
public static Vec2<T> One => new (T.One, T.One); public static Vec2<T> One => new (T.One, T.One);
public readonly Vec2<T> YX => new(Y, X); public readonly Vec2<T> YX => new(Y, X);
public readonly Vec2<T> YY => new(Y, Y); public readonly Vec2<T> YY => new(Y, Y);
public readonly Vec2<T> XX => new(X, X); public readonly Vec2<T> XX => new(X, X);
public static Vec2<T> Splat(T v) => new(v, v); 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);
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 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 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 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> Zero => new(T.Zero, T.Zero, T.Zero);
public static Vec3<T> One => new(T.One, T.One, T.One); 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> 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);
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 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 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);
} }
} }

View File

@@ -1,37 +1,37 @@
namespace AdventOfCode.Utils; namespace AdventOfCode.Utils;
public static class QuickMath 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 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]; private static readonly int[] pow10int = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
public static long FastPow10(long exp) public static long FastPow10(long exp)
{ {
return pow10Long[exp]; return pow10Long[exp];
} }
public static int FastPow10(int exp) public static int FastPow10(int exp)
{ {
return pow10int[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 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]; private static readonly int[] intCorrectionTable = [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999];
public static long DigitCount(this long value) public static long DigitCount(this long value)
{ {
var l2 = 63 - long.LeadingZeroCount(value | 1); var l2 = 63 - long.LeadingZeroCount(value | 1);
var ans = ((9 * l2) >> 5); var ans = ((9 * l2) >> 5);
if (value > longCorrectionTable[ans]) if (value > longCorrectionTable[ans])
ans += 1; ans += 1;
return ans + 1; return ans + 1;
} }
public static int DigitCount(this int value) public static int DigitCount(this int value)
{ {
var l2 = 31 - int.LeadingZeroCount(value | 1); var l2 = 31 - int.LeadingZeroCount(value | 1);
var ans = ((9 * l2) >> 5); var ans = ((9 * l2) >> 5);
if (value > intCorrectionTable[ans]) if (value > intCorrectionTable[ans])
ans += 1; ans += 1;
return ans + 1; return ans + 1;
} }
} }