diff --git a/.gitattributes b/.gitattributes
index 1ff0c42..b7d4ef6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,63 +1,63 @@
-###############################################################################
-# Set default behavior to automatically normalize line endings.
-###############################################################################
-* text=auto
-
-###############################################################################
-# Set default behavior for command prompt diff.
-#
-# This is need for earlier builds of msysgit that does not have it on by
-# default for csharp files.
-# Note: This is only used by command line
-###############################################################################
-#*.cs diff=csharp
-
-###############################################################################
-# Set the merge driver for project and solution files
-#
-# 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
-# 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
-# these files as binary and thus will always conflict and require user
-# intervention with every merge. To do so, just uncomment the entries below
-###############################################################################
-#*.sln merge=binary
-#*.csproj merge=binary
-#*.vbproj merge=binary
-#*.vcxproj merge=binary
-#*.vcproj merge=binary
-#*.dbproj merge=binary
-#*.fsproj merge=binary
-#*.lsproj merge=binary
-#*.wixproj merge=binary
-#*.modelproj merge=binary
-#*.sqlproj merge=binary
-#*.wwaproj merge=binary
-
-###############################################################################
-# behavior for image files
-#
-# image files are treated as binary by default.
-###############################################################################
-#*.jpg binary
-#*.png binary
-#*.gif binary
-
-###############################################################################
-# diff behavior for common document formats
-#
-# Convert binary document formats to text before diffing them. This feature
-# is only available from the command line. Turn it on by uncommenting the
-# entries below.
-###############################################################################
-#*.doc diff=astextplain
-#*.DOC diff=astextplain
-#*.docx diff=astextplain
-#*.DOCX diff=astextplain
-#*.dot diff=astextplain
-#*.DOT diff=astextplain
-#*.pdf diff=astextplain
-#*.PDF diff=astextplain
-#*.rtf diff=astextplain
-#*.RTF diff=astextplain
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# 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
+# 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
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
index eaa9902..43d9deb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,363 +1,363 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Oo]ut/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# 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
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-
-# Fody - auto-generated XML schema
-FodyWeavers.xsd
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# 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
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
diff --git a/AdventOfCode.sln b/AdventOfCode.sln
index a6ac603..e1a6b57 100644
--- a/AdventOfCode.sln
+++ b/AdventOfCode.sln
@@ -1,25 +1,25 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.4.33110.190
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {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}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33110.190
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {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}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
+ EndGlobalSection
+EndGlobal
diff --git a/AdventOfCode/AdventOfCode.csproj b/AdventOfCode/AdventOfCode.csproj
index 3d8672d..4f8869c 100644
--- a/AdventOfCode/AdventOfCode.csproj
+++ b/AdventOfCode/AdventOfCode.csproj
@@ -1,81 +1,83 @@
-
-
-
- Exe
- net9.0
- enable
- enable
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
- PreserveNewest
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AdventOfCode/Problems/.gitignore b/AdventOfCode/Problems/.gitignore
index 0b956fc..6735430 100644
--- a/AdventOfCode/Problems/.gitignore
+++ b/AdventOfCode/Problems/.gitignore
@@ -1,2 +1,2 @@
-*/*/*.txt
+*/*/*.txt
*/*/*.csv
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2015/Day10/LookAndSay.cs b/AdventOfCode/Problems/AOC2015/Day10/LookAndSay.cs
index 3eef30e..8ba9adf 100644
--- a/AdventOfCode/Problems/AOC2015/Day10/LookAndSay.cs
+++ b/AdventOfCode/Problems/AOC2015/Day10/LookAndSay.cs
@@ -1,58 +1,58 @@
-using AdventOfCode.Runner.Attributes;
-
-using System.Text;
-
-namespace AdventOfCode.Problems.AOC2015.Day10;
-
-[ProblemInfo(2015, 10, "Evles Look, Elves Say")]
-internal class LookAndSay : Problem
-{
- private string _input = string.Empty;
-
- public override void CalculatePart1()
- {
- Part1 = Run(40);
- }
-
- public override void CalculatePart2()
- {
- Part2 = Run(50);
- }
-
- public override void LoadInput()
- {
- _input = "3113322113";
- }
-
- public int Run(int iter)
- {
- var value = new StringBuilder(_input);
- for (int i = 0; i < iter; i++)
- CalculateNext(ref value);
-
- return value.Length;
- }
-
- private static void CalculateNext(ref StringBuilder input)
- {
- var next = new StringBuilder();
- var len = input.Length;
- var curCount = 1;
- var curChar = input[0];
- for (int i = 1; i < len; i++)
- {
- var c = input[i];
- if (c != curChar)
- {
- next.Append(curCount).Append(curChar);
- curChar = c;
- curCount = 1;
- continue;
- }
- curCount++;
- }
- next.Append(curCount).Append(curChar);
-
- input = next;
- }
+using AdventOfCode.Runner.Attributes;
+
+using System.Text;
+
+namespace AdventOfCode.Problems.AOC2015.Day10;
+
+[ProblemInfo(2015, 10, "Evles Look, Elves Say")]
+internal class LookAndSay : Problem
+{
+ private string _input = string.Empty;
+
+ public override void CalculatePart1()
+ {
+ Part1 = Run(40);
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = Run(50);
+ }
+
+ public override void LoadInput()
+ {
+ _input = "3113322113";
+ }
+
+ public int Run(int iter)
+ {
+ var value = new StringBuilder(_input);
+ for (int i = 0; i < iter; i++)
+ CalculateNext(ref value);
+
+ return value.Length;
+ }
+
+ private static void CalculateNext(ref StringBuilder input)
+ {
+ var next = new StringBuilder();
+ var len = input.Length;
+ var curCount = 1;
+ var curChar = input[0];
+ for (int i = 1; i < len; i++)
+ {
+ var c = input[i];
+ if (c != curChar)
+ {
+ next.Append(curCount).Append(curChar);
+ curChar = c;
+ curCount = 1;
+ continue;
+ }
+ curCount++;
+ }
+ next.Append(curCount).Append(curChar);
+
+ input = next;
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2015/Day5/NiceList.cs b/AdventOfCode/Problems/AOC2015/Day5/NiceList.cs
index 65b8782..44a6ff2 100644
--- a/AdventOfCode/Problems/AOC2015/Day5/NiceList.cs
+++ b/AdventOfCode/Problems/AOC2015/Day5/NiceList.cs
@@ -1,110 +1,110 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2015.Day5;
-
-[ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")]
-public class NiceList : Problem
-{
- private string[] _inputData = Array.Empty();
-
- public override void LoadInput()
- {
- _inputData = ReadInputLines();
- }
-
- public override void CalculatePart1()
- {
- for (int i = 0; i < _inputData.Length; i++)
- {
- if (IsNice(_inputData[i]))
- Part1++;
- }
- }
-
- public override void CalculatePart2()
- {
- for (int i = 0; i < _inputData.Length; i++)
- {
- if (IsNice2(_inputData[i]))
- {
- Part2++;
- }
- }
- }
-
- private static bool IsNice2(string value)
- {
- var pairs = new Dictionary>();
- var separatedPair = false;
-
- for (int i = 1; i < value.Length; i++)
- {
- var c = value[i];
- var curIndex = i - 1;
- var pair = value[curIndex..(i + 1)];
- if (pairs.ContainsKey(pair))
- {
- if (pairs[pair].Contains(curIndex - 1))
- continue;
- pairs[pair].Add(curIndex);
- }
- else
- {
- pairs.Add(pair, new List() { curIndex });
- }
-
- if (i == 1)
- continue;
- if (value[i - 2] == c)
- separatedPair = true;
- }
-
- return separatedPair && pairs.Any(p => p.Value.Count >= 2);
- }
-
- private static bool IsNice(string value)
- {
- var vowelCount = 0;
- var doubleLetters = false;
- for (int i = 0; i < value.Length; i++)
- {
- char c = value[i];
- if (IsVowel(c))
- vowelCount++;
- if (i == 0)
- continue;
- var lastChar = value[i - 1];
- if (IsIllegal(c, lastChar))
- return false;
- if (IsDouble(c, lastChar))
- doubleLetters = true;
- }
- return doubleLetters && vowelCount >= 3;
- }
-
- private static bool IsVowel(char c)
- {
- return c switch
- {
- 'a' or 'e' or 'i' or 'o' or 'u' => true,
- _ => false
- };
- }
-
- private static bool IsDouble(char c, char lastChar)
- {
- return c == lastChar;
- }
-
- private static bool IsIllegal(char c, char lastChar)
- {
- return (lastChar, c) switch
- {
- ('a', 'b') => true,
- ('c', 'd') => true,
- ('p', 'q') => true,
- ('x', 'y') => true,
- _ => false
- };
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2015.Day5;
+
+[ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")]
+public class NiceList : Problem
+{
+ private string[] _inputData = Array.Empty();
+
+ public override void LoadInput()
+ {
+ _inputData = ReadInputLines();
+ }
+
+ public override void CalculatePart1()
+ {
+ for (int i = 0; i < _inputData.Length; i++)
+ {
+ if (IsNice(_inputData[i]))
+ Part1++;
+ }
+ }
+
+ public override void CalculatePart2()
+ {
+ for (int i = 0; i < _inputData.Length; i++)
+ {
+ if (IsNice2(_inputData[i]))
+ {
+ Part2++;
+ }
+ }
+ }
+
+ private static bool IsNice2(string value)
+ {
+ var pairs = new Dictionary>();
+ var separatedPair = false;
+
+ for (int i = 1; i < value.Length; i++)
+ {
+ var c = value[i];
+ var curIndex = i - 1;
+ var pair = value[curIndex..(i + 1)];
+ if (pairs.ContainsKey(pair))
+ {
+ if (pairs[pair].Contains(curIndex - 1))
+ continue;
+ pairs[pair].Add(curIndex);
+ }
+ else
+ {
+ pairs.Add(pair, new List() { curIndex });
+ }
+
+ if (i == 1)
+ continue;
+ if (value[i - 2] == c)
+ separatedPair = true;
+ }
+
+ return separatedPair && pairs.Any(p => p.Value.Count >= 2);
+ }
+
+ private static bool IsNice(string value)
+ {
+ var vowelCount = 0;
+ var doubleLetters = false;
+ for (int i = 0; i < value.Length; i++)
+ {
+ char c = value[i];
+ if (IsVowel(c))
+ vowelCount++;
+ if (i == 0)
+ continue;
+ var lastChar = value[i - 1];
+ if (IsIllegal(c, lastChar))
+ return false;
+ if (IsDouble(c, lastChar))
+ doubleLetters = true;
+ }
+ return doubleLetters && vowelCount >= 3;
+ }
+
+ private static bool IsVowel(char c)
+ {
+ return c switch
+ {
+ 'a' or 'e' or 'i' or 'o' or 'u' => true,
+ _ => false
+ };
+ }
+
+ private static bool IsDouble(char c, char lastChar)
+ {
+ return c == lastChar;
+ }
+
+ private static bool IsIllegal(char c, char lastChar)
+ {
+ return (lastChar, c) switch
+ {
+ ('a', 'b') => true,
+ ('c', 'd') => true,
+ ('p', 'q') => true,
+ ('x', 'y') => true,
+ _ => false
+ };
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day1/FuelCaluclation.cs b/AdventOfCode/Problems/AOC2019/Day1/FuelCaluclation.cs
index 2a10c32..aa505d2 100644
--- a/AdventOfCode/Problems/AOC2019/Day1/FuelCaluclation.cs
+++ b/AdventOfCode/Problems/AOC2019/Day1/FuelCaluclation.cs
@@ -1,41 +1,41 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day1
-{
- [ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")]
- public class FuelCaluclation : Problem
- {
- private int[] _input = Array.Empty();
-
- public static int GetFuelRequirement(int[] input)
- {
- var curFuel = input.Sum(i => GetFuelCost(i));
- return curFuel;
- }
-
- public static int GetFuelCost(int mass)
- {
- var curCost = mass / 3 - 2;
- if (curCost <= 0)
- return 0;
- return curCost + GetFuelCost(curCost);
- }
-
- public static int GetCost(int mass) => mass / 3 - 2;
-
- public override void LoadInput()
- {
- _input = InputParsing.ParseIntArray(GetInputFile());
- }
-
- public override void CalculatePart1()
- {
- Part1 = _input.Sum(i => GetCost(i));
- }
-
- public override void CalculatePart2()
- {
- Part2 = GetFuelRequirement(_input);
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day1
+{
+ [ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")]
+ public class FuelCaluclation : Problem
+ {
+ private int[] _input = Array.Empty();
+
+ public static int GetFuelRequirement(int[] input)
+ {
+ var curFuel = input.Sum(i => GetFuelCost(i));
+ return curFuel;
+ }
+
+ public static int GetFuelCost(int mass)
+ {
+ var curCost = mass / 3 - 2;
+ if (curCost <= 0)
+ return 0;
+ return curCost + GetFuelCost(curCost);
+ }
+
+ public static int GetCost(int mass) => mass / 3 - 2;
+
+ public override void LoadInput()
+ {
+ _input = InputParsing.ParseIntArray(GetInputFile());
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = _input.Sum(i => GetCost(i));
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = GetFuelRequirement(_input);
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day2/IntCode.cs b/AdventOfCode/Problems/AOC2019/Day2/IntCode.cs
index 6722026..d37e366 100644
--- a/AdventOfCode/Problems/AOC2019/Day2/IntCode.cs
+++ b/AdventOfCode/Problems/AOC2019/Day2/IntCode.cs
@@ -1,72 +1,72 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day2
-{
- [ProblemInfo(2019, 2, "Program Alarm")]
- public class IntCode : Problem
- {
- private int[] _inputPart1 = Array.Empty();
- private int[] _inputPart2 = Array.Empty();
-
- public static int ExecuteCode(int[] code, int noun, int verb)
- {
- int[] memory = code;
- memory[1] = noun;
- memory[2] = verb;
- var curAddr = 0;
-
- while (true)
- {
- var opCode = memory[curAddr];
-
- if (opCode == 99) //Halt
- return memory[0];
-
- //Working Adresses
- int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3];
-
- if (a > memory.Length || b > memory.Length || c > memory.Length)
- {
- Console.WriteLine("ERROR: Out of Bounds");
- return 0;
- }
-
- if (opCode == 1) //Add
- memory[c] = memory[a] + memory[b];
- if (opCode == 2) //Multiply
- memory[c] = memory[a] * memory[b];
-
- curAddr += 4;
- }
- }
-
- public override void LoadInput()
- {
- _inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
- _inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
- }
-
- public override void CalculatePart1()
- {
- Part1 = ExecuteCode(_inputPart1, 12, 2);
- }
-
- public override void CalculatePart2()
- {
- int targetOutput = 19690720;
- for (int n = 0; n < 100; n++)
- {
- for (int v = 0; v < 100; v++)
- {
- var curInput = new int[_inputPart2.Length];
- Array.Copy(_inputPart2, curInput, _inputPart2.Length);
- if (ExecuteCode(curInput, n, v) == targetOutput)
- {
- Part2 = 100 * n + v;
- return;
- }
- }
- }
- }
- }
-}
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day2
+{
+ [ProblemInfo(2019, 2, "Program Alarm")]
+ public class IntCode : Problem
+ {
+ private int[] _inputPart1 = Array.Empty();
+ private int[] _inputPart2 = Array.Empty();
+
+ public static int ExecuteCode(int[] code, int noun, int verb)
+ {
+ int[] memory = code;
+ memory[1] = noun;
+ memory[2] = verb;
+ var curAddr = 0;
+
+ while (true)
+ {
+ var opCode = memory[curAddr];
+
+ if (opCode == 99) //Halt
+ return memory[0];
+
+ //Working Adresses
+ int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3];
+
+ if (a > memory.Length || b > memory.Length || c > memory.Length)
+ {
+ Console.WriteLine("ERROR: Out of Bounds");
+ return 0;
+ }
+
+ if (opCode == 1) //Add
+ memory[c] = memory[a] + memory[b];
+ if (opCode == 2) //Multiply
+ memory[c] = memory[a] * memory[b];
+
+ curAddr += 4;
+ }
+ }
+
+ public override void LoadInput()
+ {
+ _inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
+ _inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = ExecuteCode(_inputPart1, 12, 2);
+ }
+
+ public override void CalculatePart2()
+ {
+ int targetOutput = 19690720;
+ for (int n = 0; n < 100; n++)
+ {
+ for (int v = 0; v < 100; v++)
+ {
+ var curInput = new int[_inputPart2.Length];
+ Array.Copy(_inputPart2, curInput, _inputPart2.Length);
+ if (ExecuteCode(curInput, n, v) == targetOutput)
+ {
+ Part2 = 100 * n + v;
+ return;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2019/Day3/CrossedWires.cs b/AdventOfCode/Problems/AOC2019/Day3/CrossedWires.cs
index b232fc9..c1a6133 100644
--- a/AdventOfCode/Problems/AOC2019/Day3/CrossedWires.cs
+++ b/AdventOfCode/Problems/AOC2019/Day3/CrossedWires.cs
@@ -1,319 +1,319 @@
-using AdventOfCode.Runner.Attributes;
-
-using System.Drawing;
-
-namespace AdventOfCode.Problems.AOC2019.Day3
-{
- [ProblemInfo(2019, 3, "Crossed Wires")]
- public class CrossedWires : Problem
- {
- private string[] _inputLines = Array.Empty();
-
- public struct WireSegment
- {
- public Point min, max;
- public Point start, end;
-
- public int Length;
-
- public bool Vertical => min.X == max.X;
-
- public WireSegment(Point a, Point b)
- {
- start = a;
- end = b;
- if (a.X == b.X) //Vertical
- {
- if (a.Y < b.Y)
- {
- min = a;
- max = b;
- }
- else
- {
- min = b;
- max = a;
- }
- Length = Math.Abs(b.Y - a.Y);
- }
- else
- {
- if (a.X < b.X)
- {
- min = a;
- max = b;
- }
- else
- {
- min = b;
- max = a;
- }
- Length = Math.Abs(b.X - a.X);
- }
- }
-
- public WireSegment CreateRelative(Point offset)
- {
- return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y));
- }
-
- public bool ContainsPoint(Point point)
- {
- if (Vertical)
- {
- if (min.X == point.X)
- {
- return min.Y <= point.Y && max.Y >= point.Y;
- }
- else
- return false;
- }
- else
- {
- if (min.Y == point.Y)
- {
- return min.X <= point.X && max.X >= point.X;
- }
- else
- return false;
- }
- }
-
- public bool Contains(WireSegment other)
- {
- if (Vertical != other.Vertical)
- return false;
- if (Vertical)
- {
- return min.Y <= other.min.Y && max.Y >= other.max.Y;
- }
- else
- {
- return min.X <= other.min.X && max.X >= other.max.X;
- }
- }
-
- public WireSegment GetOverlap(WireSegment other)
- {
- if (Vertical)
- {
- if (other.Contains(this))
- return this;
- else if (Contains(other))
- return other;
- if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y)
- {
- return new WireSegment(other.min, max);
- }
- else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y)
- return new WireSegment(min, other.max);
- else
- throw new Exception("No Overlap");
- }
- else
- {
- if (other.Contains(this))
- return this;
- else if (Contains(other))
- return other;
- if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X)
- {
- return new WireSegment(other.min, max);
- }
- else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X)
- return new WireSegment(min, other.max);
- else
- throw new Exception("No Overlap");
- }
- }
-
- public bool Intersect(WireSegment other, out Point intersection)
- {
- if (Vertical)
- {
- if (!other.Vertical)//Other Horizontal
- {
- var potInt = new Point(min.X, other.min.Y);
- if (potInt == default)
- {
- intersection = default;
- return false;
- }
- if (ContainsPoint(potInt) && other.ContainsPoint(potInt))
- {
- intersection = potInt;
- return true;
- }
- else
- {
- intersection = default;
- return false;
- }
- }
- else //Both
- {
- if (min.X != other.min.X)
- {
- intersection = default;
- return false;
- }
- else
- {
- var overlap = GetOverlap(other);
- if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
- intersection = overlap.min == default ? overlap.max : overlap.min;
- else
- intersection = overlap.max == default ? overlap.min : overlap.max;
- if (intersection == default)
- return false;
- return true;
- }
- }
- }
- else
- {
- if (!other.Vertical) //Other Horizontal
- {
- if (min.Y != other.min.Y)
- {
- intersection = default;
- return false;
- }
- var overlap = GetOverlap(other);
- if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
- intersection = overlap.min == default ? overlap.max : overlap.min;
- else
- intersection = overlap.max == default ? overlap.min : overlap.max;
- if (intersection == default)
- return false;
- return true;
- }
- else
- return other.Intersect(this, out intersection);
- }
- }
-
- public override string ToString()
- {
- return $"{start} > {end}";
- }
- }
-
- public static int StepsToPoint(List wires, Point p)
- {
- var steps = 0;
- for (int i = 0; i < wires.Count; i++)
- {
- if (wires[i].ContainsPoint(p))
- {
- if (wires[i].Vertical)
- steps += Math.Abs(wires[i].start.Y - p.Y);
- else
- steps += Math.Abs(wires[i].start.X - p.X);
- break;
- }
- else
- steps += wires[i].Length;
- }
- return steps;
- }
-
- public static int SolveWires(string[] wires)
- {
- var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
-
- int shortestWire = int.MaxValue;
- for (int i = 0; i < wireSegmentsA.Count; i++)
- {
- for (int j = 0; j < wireSegmentsB.Count; j++)
- {
- if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
- {
- var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection);
- if (len < shortestWire)
- shortestWire = len;
- }
- }
- }
- return shortestWire;
- }
-
- public static int SolveClosestDistane(string[] wires)
- {
- var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
-
- int lastIntersection = int.MaxValue;
- for (int i = 0; i < wireSegmentsA.Count; i++)
- {
- for (int j = 0; j < wireSegmentsB.Count; j++)
- {
- if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
- {
- var dist = ManhattanMagnitude(intersection);
- if (dist < lastIntersection)
- lastIntersection = dist;
- }
- }
- }
- return lastIntersection;
- }
-
- private static (List A, List B) CreateWirePair(string[] wires)
- {
- var wireA = wires[0].Split(',');
- var wireSegmentsA = CreateWire(wireA);
-
- var wireB = wires[1].Split(',');
- var wireSegmentsB = CreateWire(wireB);
-
- return (wireSegmentsA, wireSegmentsB);
- }
-
- private static List CreateWire(string[] wires)
- {
- var wireSegments = new List();
-
- for (int i = 0; i < wires.Length; i++)
- {
- var curSegment = wires[i];
- var offset = GetOffset(curSegment);
- if (i == 0)
- wireSegments.Add(new WireSegment(new Point(0, 0), offset));
- else
- wireSegments.Add(wireSegments.Last().CreateRelative(offset));
- }
- return wireSegments;
- }
-
- public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y);
-
- public static Point GetOffset(string move)
- {
- int x = 0, y = 0;
- if (move[0] == 'R')
- x = int.Parse(move.Remove(0, 1));
- else if (move[0] == 'L')
- x = -int.Parse(move.Remove(0, 1));
- else if (move[0] == 'U')
- y = int.Parse(move.Remove(0, 1));
- else if (move[0] == 'D')
- y = -int.Parse(move.Remove(0, 1));
- return new Point(x, y);
- }
-
- public override void LoadInput()
- {
- _inputLines = ReadInputLines();
- }
-
- public override void CalculatePart1()
- {
- Part1 = SolveClosestDistane(_inputLines);
- }
-
- public override void CalculatePart2()
- {
- Part2 = SolveWires(_inputLines);
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+using System.Drawing;
+
+namespace AdventOfCode.Problems.AOC2019.Day3
+{
+ [ProblemInfo(2019, 3, "Crossed Wires")]
+ public class CrossedWires : Problem
+ {
+ private string[] _inputLines = Array.Empty();
+
+ public struct WireSegment
+ {
+ public Point min, max;
+ public Point start, end;
+
+ public int Length;
+
+ public bool Vertical => min.X == max.X;
+
+ public WireSegment(Point a, Point b)
+ {
+ start = a;
+ end = b;
+ if (a.X == b.X) //Vertical
+ {
+ if (a.Y < b.Y)
+ {
+ min = a;
+ max = b;
+ }
+ else
+ {
+ min = b;
+ max = a;
+ }
+ Length = Math.Abs(b.Y - a.Y);
+ }
+ else
+ {
+ if (a.X < b.X)
+ {
+ min = a;
+ max = b;
+ }
+ else
+ {
+ min = b;
+ max = a;
+ }
+ Length = Math.Abs(b.X - a.X);
+ }
+ }
+
+ public WireSegment CreateRelative(Point offset)
+ {
+ return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y));
+ }
+
+ public bool ContainsPoint(Point point)
+ {
+ if (Vertical)
+ {
+ if (min.X == point.X)
+ {
+ return min.Y <= point.Y && max.Y >= point.Y;
+ }
+ else
+ return false;
+ }
+ else
+ {
+ if (min.Y == point.Y)
+ {
+ return min.X <= point.X && max.X >= point.X;
+ }
+ else
+ return false;
+ }
+ }
+
+ public bool Contains(WireSegment other)
+ {
+ if (Vertical != other.Vertical)
+ return false;
+ if (Vertical)
+ {
+ return min.Y <= other.min.Y && max.Y >= other.max.Y;
+ }
+ else
+ {
+ return min.X <= other.min.X && max.X >= other.max.X;
+ }
+ }
+
+ public WireSegment GetOverlap(WireSegment other)
+ {
+ if (Vertical)
+ {
+ if (other.Contains(this))
+ return this;
+ else if (Contains(other))
+ return other;
+ if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y)
+ {
+ return new WireSegment(other.min, max);
+ }
+ else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y)
+ return new WireSegment(min, other.max);
+ else
+ throw new Exception("No Overlap");
+ }
+ else
+ {
+ if (other.Contains(this))
+ return this;
+ else if (Contains(other))
+ return other;
+ if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X)
+ {
+ return new WireSegment(other.min, max);
+ }
+ else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X)
+ return new WireSegment(min, other.max);
+ else
+ throw new Exception("No Overlap");
+ }
+ }
+
+ public bool Intersect(WireSegment other, out Point intersection)
+ {
+ if (Vertical)
+ {
+ if (!other.Vertical)//Other Horizontal
+ {
+ var potInt = new Point(min.X, other.min.Y);
+ if (potInt == default)
+ {
+ intersection = default;
+ return false;
+ }
+ if (ContainsPoint(potInt) && other.ContainsPoint(potInt))
+ {
+ intersection = potInt;
+ return true;
+ }
+ else
+ {
+ intersection = default;
+ return false;
+ }
+ }
+ else //Both
+ {
+ if (min.X != other.min.X)
+ {
+ intersection = default;
+ return false;
+ }
+ else
+ {
+ var overlap = GetOverlap(other);
+ if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
+ intersection = overlap.min == default ? overlap.max : overlap.min;
+ else
+ intersection = overlap.max == default ? overlap.min : overlap.max;
+ if (intersection == default)
+ return false;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (!other.Vertical) //Other Horizontal
+ {
+ if (min.Y != other.min.Y)
+ {
+ intersection = default;
+ return false;
+ }
+ var overlap = GetOverlap(other);
+ if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
+ intersection = overlap.min == default ? overlap.max : overlap.min;
+ else
+ intersection = overlap.max == default ? overlap.min : overlap.max;
+ if (intersection == default)
+ return false;
+ return true;
+ }
+ else
+ return other.Intersect(this, out intersection);
+ }
+ }
+
+ public override string ToString()
+ {
+ return $"{start} > {end}";
+ }
+ }
+
+ public static int StepsToPoint(List wires, Point p)
+ {
+ var steps = 0;
+ for (int i = 0; i < wires.Count; i++)
+ {
+ if (wires[i].ContainsPoint(p))
+ {
+ if (wires[i].Vertical)
+ steps += Math.Abs(wires[i].start.Y - p.Y);
+ else
+ steps += Math.Abs(wires[i].start.X - p.X);
+ break;
+ }
+ else
+ steps += wires[i].Length;
+ }
+ return steps;
+ }
+
+ public static int SolveWires(string[] wires)
+ {
+ var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
+
+ int shortestWire = int.MaxValue;
+ for (int i = 0; i < wireSegmentsA.Count; i++)
+ {
+ for (int j = 0; j < wireSegmentsB.Count; j++)
+ {
+ if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
+ {
+ var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection);
+ if (len < shortestWire)
+ shortestWire = len;
+ }
+ }
+ }
+ return shortestWire;
+ }
+
+ public static int SolveClosestDistane(string[] wires)
+ {
+ var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
+
+ int lastIntersection = int.MaxValue;
+ for (int i = 0; i < wireSegmentsA.Count; i++)
+ {
+ for (int j = 0; j < wireSegmentsB.Count; j++)
+ {
+ if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
+ {
+ var dist = ManhattanMagnitude(intersection);
+ if (dist < lastIntersection)
+ lastIntersection = dist;
+ }
+ }
+ }
+ return lastIntersection;
+ }
+
+ private static (List A, List B) CreateWirePair(string[] wires)
+ {
+ var wireA = wires[0].Split(',');
+ var wireSegmentsA = CreateWire(wireA);
+
+ var wireB = wires[1].Split(',');
+ var wireSegmentsB = CreateWire(wireB);
+
+ return (wireSegmentsA, wireSegmentsB);
+ }
+
+ private static List CreateWire(string[] wires)
+ {
+ var wireSegments = new List();
+
+ for (int i = 0; i < wires.Length; i++)
+ {
+ var curSegment = wires[i];
+ var offset = GetOffset(curSegment);
+ if (i == 0)
+ wireSegments.Add(new WireSegment(new Point(0, 0), offset));
+ else
+ wireSegments.Add(wireSegments.Last().CreateRelative(offset));
+ }
+ return wireSegments;
+ }
+
+ public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y);
+
+ public static Point GetOffset(string move)
+ {
+ int x = 0, y = 0;
+ if (move[0] == 'R')
+ x = int.Parse(move.Remove(0, 1));
+ else if (move[0] == 'L')
+ x = -int.Parse(move.Remove(0, 1));
+ else if (move[0] == 'U')
+ y = int.Parse(move.Remove(0, 1));
+ else if (move[0] == 'D')
+ y = -int.Parse(move.Remove(0, 1));
+ return new Point(x, y);
+ }
+
+ public override void LoadInput()
+ {
+ _inputLines = ReadInputLines();
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = SolveClosestDistane(_inputLines);
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = SolveWires(_inputLines);
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day4/SecureContainer.cs b/AdventOfCode/Problems/AOC2019/Day4/SecureContainer.cs
index 4273046..33d60c2 100644
--- a/AdventOfCode/Problems/AOC2019/Day4/SecureContainer.cs
+++ b/AdventOfCode/Problems/AOC2019/Day4/SecureContainer.cs
@@ -1,147 +1,147 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day4
-{
- [ProblemInfo(2019, 4, "Secure Container")]
- public class SecureContainer : Problem
- {
- public static bool IsValidPassword(int[] password)
- {
- if (password.Length != 6)
- return false;
- return HasRepeating(password) && IsAssending(password);
- }
-
- public static bool HasRepeating(int[] password)
- {
- for (int i = 0; i < password.Length - 1; i++)
- {
- if (password[i] == password[i + 1])
- return true;
- }
- return false;
- }
-
- public static bool HasDoubles(int[] password)
- {
- bool foundDouble = false;
- for (int i = 0; i < 6; i++)
- {
- int c = 0;
- for (int j = 0; j < 6; j++)
- {
- if (password[j] == password[i])
- c++;
- else
- {
- if (c != 0)
- {
- if (c == 2)
- foundDouble = true;
- c = 0;
- }
- }
- }
- if (c == 2)
- foundDouble = true;
- }
- return foundDouble;
- }
-
- public static bool IsAssending(int[] password)
- {
- for (int i = 1; i < 6; i++)
- {
- if (password[i] < password[i - 1])
- {
- return false;
- }
- }
- return true;
- }
-
- public static int CountPasswordsPart1(int lower, int upper)
- {
- int passwordCount = 0;
- int[] curPassword = lower.ToIntArray();
- CleanPassword(ref curPassword);
- while (curPassword.ToInt() <= upper)
- {
- if (IsValidPassword(curPassword))
- {
- passwordCount++;
- }
- curPassword[^1]++;
- Propagate(ref curPassword, curPassword.Length - 1);
- CleanPassword(ref curPassword);
- }
- return passwordCount;
- }
-
- public static int CountPasswordsPart2(int lower, int upper)
- {
- int passwordCount = 0;
- int[] curPassword = lower.ToIntArray();
- CleanPassword(ref curPassword);
- while (curPassword.ToInt() <= upper)
- {
- if (HasDoubles(curPassword))
- {
- passwordCount++;
- }
- curPassword[^1]++;
- Propagate(ref curPassword, curPassword.Length - 1);
- CleanPassword(ref curPassword);
- }
- return passwordCount;
- }
-
- public static void CleanPassword(ref int[] password)
- {
- for (int i = 1; i < 6; i++)
- {
- if (password[i] < password[i - 1])
- {
- password[i] += password[i - 1] - password[i];
- if (password[i] == 10)
- {
- Propagate(ref password, i);
- password[i] = password[i - 1];
- }
- }
- }
- }
-
- public static void Propagate(ref int[] password, int digit)
- {
- for (int i = digit; i >= 0; i--)
- {
- if (i == 0 && password[i] == 10)
- {
- password[i] = 9;
- break;
- }
-
- if (password[i] == 10)
- {
- password[i] = 0;
- password[i - 1]++;
- }
- }
- }
-
- public override void LoadInput()
- {
- }
-
- public override void CalculatePart1()
- {
- Part1 = CountPasswordsPart1(147981, 691423);
- }
-
- public override void CalculatePart2()
- {
- Part2 = CountPasswordsPart2(147981, 691423);
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day4
+{
+ [ProblemInfo(2019, 4, "Secure Container")]
+ public class SecureContainer : Problem
+ {
+ public static bool IsValidPassword(int[] password)
+ {
+ if (password.Length != 6)
+ return false;
+ return HasRepeating(password) && IsAssending(password);
+ }
+
+ public static bool HasRepeating(int[] password)
+ {
+ for (int i = 0; i < password.Length - 1; i++)
+ {
+ if (password[i] == password[i + 1])
+ return true;
+ }
+ return false;
+ }
+
+ public static bool HasDoubles(int[] password)
+ {
+ bool foundDouble = false;
+ for (int i = 0; i < 6; i++)
+ {
+ int c = 0;
+ for (int j = 0; j < 6; j++)
+ {
+ if (password[j] == password[i])
+ c++;
+ else
+ {
+ if (c != 0)
+ {
+ if (c == 2)
+ foundDouble = true;
+ c = 0;
+ }
+ }
+ }
+ if (c == 2)
+ foundDouble = true;
+ }
+ return foundDouble;
+ }
+
+ public static bool IsAssending(int[] password)
+ {
+ for (int i = 1; i < 6; i++)
+ {
+ if (password[i] < password[i - 1])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static int CountPasswordsPart1(int lower, int upper)
+ {
+ int passwordCount = 0;
+ int[] curPassword = lower.ToIntArray();
+ CleanPassword(ref curPassword);
+ while (curPassword.ToInt() <= upper)
+ {
+ if (IsValidPassword(curPassword))
+ {
+ passwordCount++;
+ }
+ curPassword[^1]++;
+ Propagate(ref curPassword, curPassword.Length - 1);
+ CleanPassword(ref curPassword);
+ }
+ return passwordCount;
+ }
+
+ public static int CountPasswordsPart2(int lower, int upper)
+ {
+ int passwordCount = 0;
+ int[] curPassword = lower.ToIntArray();
+ CleanPassword(ref curPassword);
+ while (curPassword.ToInt() <= upper)
+ {
+ if (HasDoubles(curPassword))
+ {
+ passwordCount++;
+ }
+ curPassword[^1]++;
+ Propagate(ref curPassword, curPassword.Length - 1);
+ CleanPassword(ref curPassword);
+ }
+ return passwordCount;
+ }
+
+ public static void CleanPassword(ref int[] password)
+ {
+ for (int i = 1; i < 6; i++)
+ {
+ if (password[i] < password[i - 1])
+ {
+ password[i] += password[i - 1] - password[i];
+ if (password[i] == 10)
+ {
+ Propagate(ref password, i);
+ password[i] = password[i - 1];
+ }
+ }
+ }
+ }
+
+ public static void Propagate(ref int[] password, int digit)
+ {
+ for (int i = digit; i >= 0; i--)
+ {
+ if (i == 0 && password[i] == 10)
+ {
+ password[i] = 9;
+ break;
+ }
+
+ if (password[i] == 10)
+ {
+ password[i] = 0;
+ password[i - 1]++;
+ }
+ }
+ }
+
+ public override void LoadInput()
+ {
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = CountPasswordsPart1(147981, 691423);
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = CountPasswordsPart2(147981, 691423);
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day5/ChanceOfAsteroids.cs b/AdventOfCode/Problems/AOC2019/Day5/ChanceOfAsteroids.cs
index 2170772..90e4954 100644
--- a/AdventOfCode/Problems/AOC2019/Day5/ChanceOfAsteroids.cs
+++ b/AdventOfCode/Problems/AOC2019/Day5/ChanceOfAsteroids.cs
@@ -1,30 +1,30 @@
-using AdventOfCode.Day_5;
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day5;
-
-[ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")]
-internal class ChanceOfAsteroids : Problem
-{
- private IntCodeV2 _cpu = new IntCodeV2();
- private int[] _baseInput = Array.Empty();
-
- public override void CalculatePart1()
- {
- var output = new int[1];
- _cpu.ExecuteCode(_baseInput, new int[] { 1 }, output);
- Part1 = output[0];
- }
-
- public override void CalculatePart2()
- {
- var output = new int[1];
- _cpu.ExecuteCode(_baseInput, new int[] { 5 }, output);
- Part2 = output[0];
- }
-
- public override void LoadInput()
- {
- _baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
- }
+using AdventOfCode.Day_5;
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day5;
+
+[ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")]
+internal class ChanceOfAsteroids : Problem
+{
+ private IntCodeV2 _cpu = new IntCodeV2();
+ private int[] _baseInput = Array.Empty();
+
+ public override void CalculatePart1()
+ {
+ var output = new int[1];
+ _cpu.ExecuteCode(_baseInput, new int[] { 1 }, output);
+ Part1 = output[0];
+ }
+
+ public override void CalculatePart2()
+ {
+ var output = new int[1];
+ _cpu.ExecuteCode(_baseInput, new int[] { 5 }, output);
+ Part2 = output[0];
+ }
+
+ public override void LoadInput()
+ {
+ _baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day5/IntCodeV2.cs b/AdventOfCode/Problems/AOC2019/Day5/IntCodeV2.cs
index bca3eda..9e19eb3 100644
--- a/AdventOfCode/Problems/AOC2019/Day5/IntCodeV2.cs
+++ b/AdventOfCode/Problems/AOC2019/Day5/IntCodeV2.cs
@@ -1,233 +1,233 @@
-namespace AdventOfCode.Day_5
-{
- public class IntCodeV2
- {
- public struct Instruction
- {
- public int opcode;
- public int paramCount;
- public Func action;
-
- public Instruction(int opcode, int paramCount, Func action)
- {
- this.opcode = opcode;
- this.paramCount = paramCount;
- this.action = action;
- }
- }
-
- public bool IsHalted { get; private set; }
- public bool IsRunning { get; private set; }
- public bool PersistentMode { get; private set; }
- public bool SuspendOnWrite { get; private set; }
-
- private Dictionary _instructions;
- private int _instructionPointer;
- private int[]? _inputBuffer;
- private int _inputCounter = 0;
- private int[]? _outputBuffer;
- private int _outputCounter = 0;
- private int[] memory = Array.Empty();
-
- public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false)
- {
- _instructions = new Dictionary();
- PersistentMode = persistentMode;
- SuspendOnWrite = suspendOnOutput;
- IsHalted = false;
- //Add
- _instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- var v3 = mode[0] == 1 ? mem[p3] : p3;
- mem[v3] = v1 + v2;
-
- return true;
- }));
- //Multiply
- _instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- var v3 = mode[0] == 1 ? mem[p3] : p3;
- mem[v3] = v1 * v2;
- return true;
- }));
- //Halt
- _instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) =>
- {
- IsHalted = true;
- IsRunning = false;
- return false;
- }));
- //Read Input
- _instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? mem[p1] : p1;
- mem[v1] = ReadInput();
- //Console.WriteLine($"Input Read: {mem[v1]}");
- return true;
- }));
- //Write Output
- _instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- WriteOutput(v1);
- if (SuspendOnWrite)
- IsRunning = false;
- return true;
- }));
- //Jump if True
- _instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- if (v1 != 0)
- {
- _instructionPointer = v2;
- return false;
- }
- return true;
- }));
- //Jump if False
- _instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- if (v1 == 0)
- {
- _instructionPointer = v2;
- return false;
- }
- return true;
- }));
- //Less than
- _instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- var v3 = mode[0] == 1 ? mem[p3] : p3;
- if (v1 < v2)
- mem[v3] = 1;
- else
- mem[v3] = 0;
- return true;
- }));
- //Equals
- _instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) =>
- {
- var v1 = mode[2] == 1 ? p1 : mem[p1];
- var v2 = mode[1] == 1 ? p2 : mem[p2];
- var v3 = mode[0] == 1 ? mem[p3] : p3;
- if (v1 == v2)
- mem[v3] = 1;
- else
- mem[v3] = 0;
- return true;
- }));
- }
-
- private int ReadInput()
- {
- _inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1);
- if (_inputBuffer != null && _inputCounter < _inputBuffer.Length)
- return _inputBuffer[_inputCounter++];
- else
- {
- Console.Write("Input: ");
- return int.Parse(Console.ReadLine()!);
- }
- }
-
- private void WriteOutput(int output)
- {
- _outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1);
- if (_outputBuffer != null && _outputCounter < _outputBuffer.Length)
- _outputBuffer[_outputCounter++] = output;
- else
- Console.WriteLine(output);
- }
-
- public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null)
- {
- LoadCode(code);
- SetIO(input, output);
- IsHalted = false;
- Run();
- }
-
- public static (int[] opModes, int opcode) ParseInstruction(int instruction)
- {
- var opModes = new int[3];
- var arr = instruction.ToIntArray();
- switch (arr.Length)
- {
- case 1:
- return (opModes, arr[0]);
-
- case 2:
- return (opModes, (arr[^2] * 10) + arr[^1]);
- }
- var opcode = (arr[^2] * 10) + arr[^1];
- for (int i = 1; i <= 3; i++)
- {
- if (arr.Length < i + 2)
- opModes[^i] = 0;
- else
- opModes[^i] = arr[^(i + 2)];
- }
-
- return (opModes, opcode);
- }
-
- public void ResetIO()
- {
- _inputCounter = _outputCounter = 0;
- }
-
- public void SetInputIndex(int index)
- {
- _inputCounter = index;
- }
-
- public void SetIO(int[]? inputBuffer, int[]? outputBuffer)
- {
- ResetIO();
- _inputBuffer = inputBuffer ?? Array.Empty();
- _outputBuffer = outputBuffer ?? Array.Empty();
- }
-
- public void Run()
- {
- IsRunning = true;
- while (IsRunning)
- {
- var (modes, opcode) = ParseInstruction(memory[_instructionPointer]);
- var curInstruction = _instructions[opcode];
- int[] parameters = new int[3];
- for (int i = 0; i < 3; i++)
- {
- if (i >= curInstruction.paramCount)
- parameters[i] = 0;
- else
- parameters[i] = memory[_instructionPointer + i + 1];
- }
-
- if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2]))
- _instructionPointer += curInstruction.paramCount + 1;
-
- if (IsHalted)
- IsRunning = false;
- }
- }
-
- public IntCodeV2 LoadCode(int[] code)
- {
- memory = new int[code.Length];
- code.CopyTo(memory, 0);
- _instructionPointer = 0;
- return this;
- }
- }
+namespace AdventOfCode.Day_5
+{
+ public class IntCodeV2
+ {
+ public struct Instruction
+ {
+ public int opcode;
+ public int paramCount;
+ public Func action;
+
+ public Instruction(int opcode, int paramCount, Func action)
+ {
+ this.opcode = opcode;
+ this.paramCount = paramCount;
+ this.action = action;
+ }
+ }
+
+ public bool IsHalted { get; private set; }
+ public bool IsRunning { get; private set; }
+ public bool PersistentMode { get; private set; }
+ public bool SuspendOnWrite { get; private set; }
+
+ private Dictionary _instructions;
+ private int _instructionPointer;
+ private int[]? _inputBuffer;
+ private int _inputCounter = 0;
+ private int[]? _outputBuffer;
+ private int _outputCounter = 0;
+ private int[] memory = Array.Empty();
+
+ public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false)
+ {
+ _instructions = new Dictionary();
+ PersistentMode = persistentMode;
+ SuspendOnWrite = suspendOnOutput;
+ IsHalted = false;
+ //Add
+ _instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ var v3 = mode[0] == 1 ? mem[p3] : p3;
+ mem[v3] = v1 + v2;
+
+ return true;
+ }));
+ //Multiply
+ _instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ var v3 = mode[0] == 1 ? mem[p3] : p3;
+ mem[v3] = v1 * v2;
+ return true;
+ }));
+ //Halt
+ _instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) =>
+ {
+ IsHalted = true;
+ IsRunning = false;
+ return false;
+ }));
+ //Read Input
+ _instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? mem[p1] : p1;
+ mem[v1] = ReadInput();
+ //Console.WriteLine($"Input Read: {mem[v1]}");
+ return true;
+ }));
+ //Write Output
+ _instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ WriteOutput(v1);
+ if (SuspendOnWrite)
+ IsRunning = false;
+ return true;
+ }));
+ //Jump if True
+ _instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ if (v1 != 0)
+ {
+ _instructionPointer = v2;
+ return false;
+ }
+ return true;
+ }));
+ //Jump if False
+ _instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ if (v1 == 0)
+ {
+ _instructionPointer = v2;
+ return false;
+ }
+ return true;
+ }));
+ //Less than
+ _instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ var v3 = mode[0] == 1 ? mem[p3] : p3;
+ if (v1 < v2)
+ mem[v3] = 1;
+ else
+ mem[v3] = 0;
+ return true;
+ }));
+ //Equals
+ _instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) =>
+ {
+ var v1 = mode[2] == 1 ? p1 : mem[p1];
+ var v2 = mode[1] == 1 ? p2 : mem[p2];
+ var v3 = mode[0] == 1 ? mem[p3] : p3;
+ if (v1 == v2)
+ mem[v3] = 1;
+ else
+ mem[v3] = 0;
+ return true;
+ }));
+ }
+
+ private int ReadInput()
+ {
+ _inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1);
+ if (_inputBuffer != null && _inputCounter < _inputBuffer.Length)
+ return _inputBuffer[_inputCounter++];
+ else
+ {
+ Console.Write("Input: ");
+ return int.Parse(Console.ReadLine()!);
+ }
+ }
+
+ private void WriteOutput(int output)
+ {
+ _outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1);
+ if (_outputBuffer != null && _outputCounter < _outputBuffer.Length)
+ _outputBuffer[_outputCounter++] = output;
+ else
+ Console.WriteLine(output);
+ }
+
+ public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null)
+ {
+ LoadCode(code);
+ SetIO(input, output);
+ IsHalted = false;
+ Run();
+ }
+
+ public static (int[] opModes, int opcode) ParseInstruction(int instruction)
+ {
+ var opModes = new int[3];
+ var arr = instruction.ToIntArray();
+ switch (arr.Length)
+ {
+ case 1:
+ return (opModes, arr[0]);
+
+ case 2:
+ return (opModes, (arr[^2] * 10) + arr[^1]);
+ }
+ var opcode = (arr[^2] * 10) + arr[^1];
+ for (int i = 1; i <= 3; i++)
+ {
+ if (arr.Length < i + 2)
+ opModes[^i] = 0;
+ else
+ opModes[^i] = arr[^(i + 2)];
+ }
+
+ return (opModes, opcode);
+ }
+
+ public void ResetIO()
+ {
+ _inputCounter = _outputCounter = 0;
+ }
+
+ public void SetInputIndex(int index)
+ {
+ _inputCounter = index;
+ }
+
+ public void SetIO(int[]? inputBuffer, int[]? outputBuffer)
+ {
+ ResetIO();
+ _inputBuffer = inputBuffer ?? Array.Empty();
+ _outputBuffer = outputBuffer ?? Array.Empty();
+ }
+
+ public void Run()
+ {
+ IsRunning = true;
+ while (IsRunning)
+ {
+ var (modes, opcode) = ParseInstruction(memory[_instructionPointer]);
+ var curInstruction = _instructions[opcode];
+ int[] parameters = new int[3];
+ for (int i = 0; i < 3; i++)
+ {
+ if (i >= curInstruction.paramCount)
+ parameters[i] = 0;
+ else
+ parameters[i] = memory[_instructionPointer + i + 1];
+ }
+
+ if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2]))
+ _instructionPointer += curInstruction.paramCount + 1;
+
+ if (IsHalted)
+ IsRunning = false;
+ }
+ }
+
+ public IntCodeV2 LoadCode(int[] code)
+ {
+ memory = new int[code.Length];
+ code.CopyTo(memory, 0);
+ _instructionPointer = 0;
+ return this;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day6/OrbitMap.cs b/AdventOfCode/Problems/AOC2019/Day6/OrbitMap.cs
index 62b6d56..c6dd112 100644
--- a/AdventOfCode/Problems/AOC2019/Day6/OrbitMap.cs
+++ b/AdventOfCode/Problems/AOC2019/Day6/OrbitMap.cs
@@ -1,119 +1,119 @@
-namespace AdventOfCode.Problems.AOC2019.Day6
-{
- public class OrbitMap
- {
- public CelestialObject root;
- public Dictionary objectMap;
-
- public OrbitMap(string[] orbits)
- {
- objectMap = new Dictionary();
- GenerateOrbits(orbits);
- }
-
- public void GenerateOrbits(string[] orbits)
- {
- for (int i = 0; i < orbits.Length; i++)
- {
- var bodies = orbits[i].Split(')');
- if (bodies[0] == "COM")
- root = CreateObject("COM");
-
- var parent = GetOrCreateObject(bodies[0]);
- var child = GetOrCreateObject(bodies[1]);
-
- parent.AddChild(child);
- }
- }
-
- public CelestialObject GetOrCreateObject(string name)
- {
- if (objectMap.ContainsKey(name))
- return objectMap[name];
- else
- return CreateObject(name);
- }
-
- public CelestialObject CreateObject(string name)
- {
- var o = new CelestialObject(name);
- objectMap.Add(name, o);
- return o;
- }
-
- public int CalculateOrbits()
- {
- return root.GetOrbitCount();
- }
-
- public List FindPathTo(string name)
- {
- var path = new List();
- root.FindPathTo(name, path);
- return path;
- }
-
- public int GetDepthOf(string name) => root.GetDepth(name);
-
- public class CelestialObject
- {
- public string Name { get; set; }
- public int ChildCount => children.Count;
-
- public List children;
-
- public CelestialObject(string name)
- {
- children = new List();
- Name = name;
- }
-
- public void AddChild(CelestialObject child)
- {
- children.Add(child);
- }
-
- public int GetOrbitCount(int depth = 0)
- {
- var count = 0;
- for (int i = 0; i < children.Count; i++)
- {
- count += children[i].GetOrbitCount(depth + 1);
- }
- return depth + count;
- }
-
- public bool FindPathTo(string name, List path)
- {
- if (name == Name)
- return true;
- for (int i = 0; i < ChildCount; i++)
- {
- if (children[i].FindPathTo(name, path))
- {
- path.Add(children[i]);
- return true;
- }
- }
- return false;
- }
-
- public int GetDepth(string name, int depth = 0)
- {
- if (name == Name)
- return depth;
- var d = 0;
- for (int i = 0; i < ChildCount; i++)
- {
- d += children[i].GetDepth(name, depth + 1);
- }
- return d;
- }
-
- public override string ToString()
- {
- return Name;
- }
- }
- }
+namespace AdventOfCode.Problems.AOC2019.Day6
+{
+ public class OrbitMap
+ {
+ public CelestialObject root;
+ public Dictionary objectMap;
+
+ public OrbitMap(string[] orbits)
+ {
+ objectMap = new Dictionary();
+ GenerateOrbits(orbits);
+ }
+
+ public void GenerateOrbits(string[] orbits)
+ {
+ for (int i = 0; i < orbits.Length; i++)
+ {
+ var bodies = orbits[i].Split(')');
+ if (bodies[0] == "COM")
+ root = CreateObject("COM");
+
+ var parent = GetOrCreateObject(bodies[0]);
+ var child = GetOrCreateObject(bodies[1]);
+
+ parent.AddChild(child);
+ }
+ }
+
+ public CelestialObject GetOrCreateObject(string name)
+ {
+ if (objectMap.ContainsKey(name))
+ return objectMap[name];
+ else
+ return CreateObject(name);
+ }
+
+ public CelestialObject CreateObject(string name)
+ {
+ var o = new CelestialObject(name);
+ objectMap.Add(name, o);
+ return o;
+ }
+
+ public int CalculateOrbits()
+ {
+ return root.GetOrbitCount();
+ }
+
+ public List FindPathTo(string name)
+ {
+ var path = new List();
+ root.FindPathTo(name, path);
+ return path;
+ }
+
+ public int GetDepthOf(string name) => root.GetDepth(name);
+
+ public class CelestialObject
+ {
+ public string Name { get; set; }
+ public int ChildCount => children.Count;
+
+ public List children;
+
+ public CelestialObject(string name)
+ {
+ children = new List();
+ Name = name;
+ }
+
+ public void AddChild(CelestialObject child)
+ {
+ children.Add(child);
+ }
+
+ public int GetOrbitCount(int depth = 0)
+ {
+ var count = 0;
+ for (int i = 0; i < children.Count; i++)
+ {
+ count += children[i].GetOrbitCount(depth + 1);
+ }
+ return depth + count;
+ }
+
+ public bool FindPathTo(string name, List path)
+ {
+ if (name == Name)
+ return true;
+ for (int i = 0; i < ChildCount; i++)
+ {
+ if (children[i].FindPathTo(name, path))
+ {
+ path.Add(children[i]);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public int GetDepth(string name, int depth = 0)
+ {
+ if (name == Name)
+ return depth;
+ var d = 0;
+ for (int i = 0; i < ChildCount; i++)
+ {
+ d += children[i].GetDepth(name, depth + 1);
+ }
+ return d;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day6/UniversalOrbits.cs b/AdventOfCode/Problems/AOC2019/Day6/UniversalOrbits.cs
index 27b06b1..69837bb 100644
--- a/AdventOfCode/Problems/AOC2019/Day6/UniversalOrbits.cs
+++ b/AdventOfCode/Problems/AOC2019/Day6/UniversalOrbits.cs
@@ -1,53 +1,53 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day6;
-
-[ProblemInfo(2019, 6, "Universal Orbit Map")]
-internal class UniversalOrbits : Problem
-{
- private OrbitMap? _map;
-
- public override void CalculatePart1()
- {
- if (_map == null)
- return;
- Part1 = _map.CalculateOrbits();
- }
-
- public override void CalculatePart2()
- {
- if (_map == null)
- return;
-
- var pathToYOU = _map.FindPathTo("YOU");
- var pathToSAN = _map.FindPathTo("SAN");
- string pivot = "";
- int dist = 0;
-
- HashSet pathYOU = new(pathToYOU.Select(o => o.Name));
-
- for (int i = 0; i < pathToSAN.Count; i++)
- {
- if (pathYOU.Contains(pathToSAN[i].Name))
- {
- pivot = pathToSAN[i].Name;
- dist = i;
- break;
- }
- }
- for (int i = 0; i < pathToYOU.Count; i++)
- {
- if (pathToYOU[i].Name == pivot)
- {
- dist += i;
- break;
- }
- }
- Part2 = dist - 2;
- }
-
- public override void LoadInput()
- {
- _map = new OrbitMap(ReadInputLines());
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day6;
+
+[ProblemInfo(2019, 6, "Universal Orbit Map")]
+internal class UniversalOrbits : Problem
+{
+ private OrbitMap? _map;
+
+ public override void CalculatePart1()
+ {
+ if (_map == null)
+ return;
+ Part1 = _map.CalculateOrbits();
+ }
+
+ public override void CalculatePart2()
+ {
+ if (_map == null)
+ return;
+
+ var pathToYOU = _map.FindPathTo("YOU");
+ var pathToSAN = _map.FindPathTo("SAN");
+ string pivot = "";
+ int dist = 0;
+
+ HashSet pathYOU = new(pathToYOU.Select(o => o.Name));
+
+ for (int i = 0; i < pathToSAN.Count; i++)
+ {
+ if (pathYOU.Contains(pathToSAN[i].Name))
+ {
+ pivot = pathToSAN[i].Name;
+ dist = i;
+ break;
+ }
+ }
+ for (int i = 0; i < pathToYOU.Count; i++)
+ {
+ if (pathToYOU[i].Name == pivot)
+ {
+ dist += i;
+ break;
+ }
+ }
+ Part2 = dist - 2;
+ }
+
+ public override void LoadInput()
+ {
+ _map = new OrbitMap(ReadInputLines());
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day7/AmplificationCircuit.cs b/AdventOfCode/Problems/AOC2019/Day7/AmplificationCircuit.cs
index 0ed64e3..ecc1fde 100644
--- a/AdventOfCode/Problems/AOC2019/Day7/AmplificationCircuit.cs
+++ b/AdventOfCode/Problems/AOC2019/Day7/AmplificationCircuit.cs
@@ -1,161 +1,161 @@
-using AdventOfCode.Day_5;
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day7
-{
- [ProblemInfo(2019, 7, "Amplification Circuit")]
- public class AmplificationCircuit : Problem
- {
- private int[] _code = Array.Empty();
-
- public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings)
- {
- if (HasDuplicateValues(phaseSettings))
- return int.MinValue;
- int[] outputBuffer = { 0 };
- int[] inputBuffer;
- //Amp A
- inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] };
- cpu.ExecuteCode(code, inputBuffer, outputBuffer);
- //Amp B
- inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] };
- cpu.ExecuteCode(code, inputBuffer, outputBuffer);
- //Amp C
- inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] };
- cpu.ExecuteCode(code, inputBuffer, outputBuffer);
- //Amp D
- inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] };
- cpu.ExecuteCode(code, inputBuffer, outputBuffer);
- //Amp E
- inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] };
- cpu.ExecuteCode(code, inputBuffer, outputBuffer);
- return outputBuffer[0];
- }
-
- public static int RunFeedback(int[] code, int[] phaseSettings)
- {
- if (HasDuplicateValues(phaseSettings))
- return int.MinValue;
- var ampA = new IntCodeV2(true, true).LoadCode(code);
- var ampB = new IntCodeV2(true, true).LoadCode(code);
- var ampC = new IntCodeV2(true, true).LoadCode(code);
- var ampD = new IntCodeV2(true, true).LoadCode(code);
- var ampE = new IntCodeV2(true, true).LoadCode(code);
- var outputA = new int[] { 273 };
- var outputB = new int[] { 0 };
- var outputC = new int[] { 0 };
- var outputD = new int[] { 0 };
- var outputE = new int[] { 0 };
- var inputA = new int[] { phaseSettings[0], outputE[0] };
- var inputB = new int[] { phaseSettings[1], outputA[0] };
- var inputC = new int[] { phaseSettings[2], outputB[0] };
- var inputD = new int[] { phaseSettings[3], outputC[0] };
- var inputE = new int[] { phaseSettings[4], outputD[0] };
- ampA.SetIO(inputA, outputA);
- ampB.SetIO(inputB, outputB);
- ampC.SetIO(inputC, outputC);
- ampD.SetIO(inputD, outputD);
- ampE.SetIO(inputE, outputE);
- int iter = 0;
- while (!ampE.IsHalted)
- {
- //Console.WriteLine($"Iteration {iter}");
- inputA[1] = outputE[0];
-
- ampA.Run();
- inputB[1] = outputA[0];
- ampB.Run();
- inputC[1] = outputB[0];
- ampC.Run();
- inputD[1] = outputC[0];
- ampD.Run();
- inputE[1] = outputD[0];
- ampE.Run();
-
- //Console.WriteLine($"Output {outputE[0]}");
- iter++;
- }
-
- return outputE[0];
- }
-
- public static bool HasDuplicateValues(int[] arr)
- {
- for (int i = 0; i < arr.Length; i++)
- {
- for (int j = 0; j < arr.Length; j++)
- {
- if (i == j)
- continue;
- if (arr[i] == arr[j])
- return true;
- }
- }
- return false;
- }
-
- public override void LoadInput()
- {
- _code = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
- }
-
- public override void CalculatePart1()
- {
- int output = int.MinValue;
- int min = 0;
- int max = 5;
- var cpu = new IntCodeV2();
-
- for (int i = min; i < max; i++)
- {
- for (int j = min; j < max; j++)
- {
- for (int k = min; k < max; k++)
- {
- for (int l = min; l < max; l++)
- {
- for (int m = min; m < max; m++)
- {
- var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m });
- if (output < result)
- {
- output = result;
- }
- }
- }
- }
- }
- }
- Part1 = output;
- }
-
- public override void CalculatePart2()
- {
- int output = int.MinValue;
- int min = 5;
- int max = 10;
-
- for (int i = min; i < max; i++)
- {
- for (int j = min; j < max; j++)
- {
- for (int k = min; k < max; k++)
- {
- for (int l = min; l < max; l++)
- {
- for (int m = min; m < max; m++)
- {
- var result = RunFeedback(_code, new int[] { i, j, k, l, m });
- if (output < result)
- {
- output = result;
- }
- }
- }
- }
- }
- }
- Part2 = output;
- }
- }
+using AdventOfCode.Day_5;
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day7
+{
+ [ProblemInfo(2019, 7, "Amplification Circuit")]
+ public class AmplificationCircuit : Problem
+ {
+ private int[] _code = Array.Empty();
+
+ public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings)
+ {
+ if (HasDuplicateValues(phaseSettings))
+ return int.MinValue;
+ int[] outputBuffer = { 0 };
+ int[] inputBuffer;
+ //Amp A
+ inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] };
+ cpu.ExecuteCode(code, inputBuffer, outputBuffer);
+ //Amp B
+ inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] };
+ cpu.ExecuteCode(code, inputBuffer, outputBuffer);
+ //Amp C
+ inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] };
+ cpu.ExecuteCode(code, inputBuffer, outputBuffer);
+ //Amp D
+ inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] };
+ cpu.ExecuteCode(code, inputBuffer, outputBuffer);
+ //Amp E
+ inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] };
+ cpu.ExecuteCode(code, inputBuffer, outputBuffer);
+ return outputBuffer[0];
+ }
+
+ public static int RunFeedback(int[] code, int[] phaseSettings)
+ {
+ if (HasDuplicateValues(phaseSettings))
+ return int.MinValue;
+ var ampA = new IntCodeV2(true, true).LoadCode(code);
+ var ampB = new IntCodeV2(true, true).LoadCode(code);
+ var ampC = new IntCodeV2(true, true).LoadCode(code);
+ var ampD = new IntCodeV2(true, true).LoadCode(code);
+ var ampE = new IntCodeV2(true, true).LoadCode(code);
+ var outputA = new int[] { 273 };
+ var outputB = new int[] { 0 };
+ var outputC = new int[] { 0 };
+ var outputD = new int[] { 0 };
+ var outputE = new int[] { 0 };
+ var inputA = new int[] { phaseSettings[0], outputE[0] };
+ var inputB = new int[] { phaseSettings[1], outputA[0] };
+ var inputC = new int[] { phaseSettings[2], outputB[0] };
+ var inputD = new int[] { phaseSettings[3], outputC[0] };
+ var inputE = new int[] { phaseSettings[4], outputD[0] };
+ ampA.SetIO(inputA, outputA);
+ ampB.SetIO(inputB, outputB);
+ ampC.SetIO(inputC, outputC);
+ ampD.SetIO(inputD, outputD);
+ ampE.SetIO(inputE, outputE);
+ int iter = 0;
+ while (!ampE.IsHalted)
+ {
+ //Console.WriteLine($"Iteration {iter}");
+ inputA[1] = outputE[0];
+
+ ampA.Run();
+ inputB[1] = outputA[0];
+ ampB.Run();
+ inputC[1] = outputB[0];
+ ampC.Run();
+ inputD[1] = outputC[0];
+ ampD.Run();
+ inputE[1] = outputD[0];
+ ampE.Run();
+
+ //Console.WriteLine($"Output {outputE[0]}");
+ iter++;
+ }
+
+ return outputE[0];
+ }
+
+ public static bool HasDuplicateValues(int[] arr)
+ {
+ for (int i = 0; i < arr.Length; i++)
+ {
+ for (int j = 0; j < arr.Length; j++)
+ {
+ if (i == j)
+ continue;
+ if (arr[i] == arr[j])
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public override void LoadInput()
+ {
+ _code = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
+ }
+
+ public override void CalculatePart1()
+ {
+ int output = int.MinValue;
+ int min = 0;
+ int max = 5;
+ var cpu = new IntCodeV2();
+
+ for (int i = min; i < max; i++)
+ {
+ for (int j = min; j < max; j++)
+ {
+ for (int k = min; k < max; k++)
+ {
+ for (int l = min; l < max; l++)
+ {
+ for (int m = min; m < max; m++)
+ {
+ var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m });
+ if (output < result)
+ {
+ output = result;
+ }
+ }
+ }
+ }
+ }
+ }
+ Part1 = output;
+ }
+
+ public override void CalculatePart2()
+ {
+ int output = int.MinValue;
+ int min = 5;
+ int max = 10;
+
+ for (int i = min; i < max; i++)
+ {
+ for (int j = min; j < max; j++)
+ {
+ for (int k = min; k < max; k++)
+ {
+ for (int l = min; l < max; l++)
+ {
+ for (int m = min; m < max; m++)
+ {
+ var result = RunFeedback(_code, new int[] { i, j, k, l, m });
+ if (output < result)
+ {
+ output = result;
+ }
+ }
+ }
+ }
+ }
+ }
+ Part2 = output;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/Day8/SpaceImageFormat.cs b/AdventOfCode/Problems/AOC2019/Day8/SpaceImageFormat.cs
index 5556273..b269f26 100644
--- a/AdventOfCode/Problems/AOC2019/Day8/SpaceImageFormat.cs
+++ b/AdventOfCode/Problems/AOC2019/Day8/SpaceImageFormat.cs
@@ -1,83 +1,83 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2019.Day8
-{
- [ProblemInfo(2019, 8, "Space Image Format")]
- public class SpaceImageFormat : Problem
- {
- private int[] _imageData = Array.Empty();
-
- public static void Execute()
- {
- var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
-
- Console.WriteLine(Checksum(imageData, 25, 6));
- }
-
- public static void RenderImage(int[] data, int h, int w)
- {
- var imgSize = h * w;
- var layerCount = data.Length / imgSize;
-
- for (int l = 0; l < layerCount; l++)
- {
- }
- }
-
- public static int Checksum(int[] data, int h, int w)
- {
- var imgSize = h * w;
- var layerCount = data.Length / imgSize;
-
- int[] zeroCount = new int[layerCount];
- int[] oneCount = new int[layerCount];
- int[] twoCount = new int[layerCount];
-
- int smallestLayer = -1;
- int smallestLayerCount = int.MaxValue;
-
- for (int l = 0; l < layerCount; l++)
- {
- for (int i = imgSize * l; i < imgSize * (l + 1); i++)
- {
- switch (data[i])
- {
- case 0:
- zeroCount[l]++;
- break;
-
- case 1:
- oneCount[l]++;
- break;
-
- case 2:
- twoCount[l]++;
- break;
- }
- }
- if (zeroCount[l] <= smallestLayerCount)
- {
- smallestLayer = l;
- smallestLayerCount = zeroCount[l];
- }
- }
-
- return oneCount[smallestLayer] * twoCount[smallestLayer];
- }
-
- public override void LoadInput()
- {
- _imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
- }
-
- public override void CalculatePart1()
- {
- Part1 = Checksum(_imageData, 25, 6);
- }
-
- public override void CalculatePart2()
- {
- Part2 = null;
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2019.Day8
+{
+ [ProblemInfo(2019, 8, "Space Image Format")]
+ public class SpaceImageFormat : Problem
+ {
+ private int[] _imageData = Array.Empty();
+
+ public static void Execute()
+ {
+ var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
+
+ Console.WriteLine(Checksum(imageData, 25, 6));
+ }
+
+ public static void RenderImage(int[] data, int h, int w)
+ {
+ var imgSize = h * w;
+ var layerCount = data.Length / imgSize;
+
+ for (int l = 0; l < layerCount; l++)
+ {
+ }
+ }
+
+ public static int Checksum(int[] data, int h, int w)
+ {
+ var imgSize = h * w;
+ var layerCount = data.Length / imgSize;
+
+ int[] zeroCount = new int[layerCount];
+ int[] oneCount = new int[layerCount];
+ int[] twoCount = new int[layerCount];
+
+ int smallestLayer = -1;
+ int smallestLayerCount = int.MaxValue;
+
+ for (int l = 0; l < layerCount; l++)
+ {
+ for (int i = imgSize * l; i < imgSize * (l + 1); i++)
+ {
+ switch (data[i])
+ {
+ case 0:
+ zeroCount[l]++;
+ break;
+
+ case 1:
+ oneCount[l]++;
+ break;
+
+ case 2:
+ twoCount[l]++;
+ break;
+ }
+ }
+ if (zeroCount[l] <= smallestLayerCount)
+ {
+ smallestLayer = l;
+ smallestLayerCount = zeroCount[l];
+ }
+ }
+
+ return oneCount[smallestLayer] * twoCount[smallestLayer];
+ }
+
+ public override void LoadInput()
+ {
+ _imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = Checksum(_imageData, 25, 6);
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = null;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2019/InputParsing.cs b/AdventOfCode/Problems/AOC2019/InputParsing.cs
index 251ce57..c63fd44 100644
--- a/AdventOfCode/Problems/AOC2019/InputParsing.cs
+++ b/AdventOfCode/Problems/AOC2019/InputParsing.cs
@@ -1,31 +1,31 @@
-namespace AdventOfCode
-{
- public static class InputParsing
- {
- public static int[] ParseIntArray(string file)
- {
- return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray();
- }
-
- public static int[] ParseIntCsv(string file)
- {
- return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray();
- }
-
- public static int ToInt(this int[] intArr)
- {
- int value = 0;
- for (int i = 0; i < intArr.Length; i++)
- {
- value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i];
- }
- return value;
- }
-
- public static int[] ToIntArray(this int number)
- {
- int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray();
- return intArr;
- }
- }
+namespace AdventOfCode
+{
+ public static class InputParsing
+ {
+ public static int[] ParseIntArray(string file)
+ {
+ return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray();
+ }
+
+ public static int[] ParseIntCsv(string file)
+ {
+ return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray();
+ }
+
+ public static int ToInt(this int[] intArr)
+ {
+ int value = 0;
+ for (int i = 0; i < intArr.Length; i++)
+ {
+ value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i];
+ }
+ return value;
+ }
+
+ public static int[] ToIntArray(this int number)
+ {
+ int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray();
+ return intArr;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2021/Day11/DumboOctopus.cs b/AdventOfCode/Problems/AOC2021/Day11/DumboOctopus.cs
index aeb3bc5..2960232 100644
--- a/AdventOfCode/Problems/AOC2021/Day11/DumboOctopus.cs
+++ b/AdventOfCode/Problems/AOC2021/Day11/DumboOctopus.cs
@@ -1,196 +1,196 @@
-using AdventOfCode.Runner.Attributes;
-
-using System.Collections;
-
-namespace AdventOfCode.Problems.AOC2021.Day11;
-
-[ProblemInfo(2021, 11, "Dumbo Octopus")]
-public class DumboOctopus : Problem, IEnumerable
-{
- public byte[] dataPart1 = Array.Empty();
- public byte[] dataPart2 = Array.Empty();
-
- public override void LoadInput()
- {
- var data = ReadInputLines();
- dataPart1 = new byte[10 * 10];
- if (data.Length != 10)
- throw new ArgumentException("Data must contain 10 elements", nameof(data));
- for (int y = 0; y < data.Length; y++)
- {
- var line = data[y];
- if (line.Length != 10)
- throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data));
-
- for (int x = 0; x < line.Length; x++)
- {
- dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1));
- }
- }
- dataPart2 = new byte[10 * 10];
- Array.Copy(dataPart1, dataPart2, dataPart1.Length);
- }
-
- public override void CalculatePart1()
- {
- Part1 = Run(ref dataPart1, 100, out _);
- }
-
- public override void CalculatePart2()
- {
- Run(ref dataPart2, 210, out var fullFlash);
- Part2 = fullFlash;
- }
-
- public IEnumerator GetEnumerator()
- {
- return ((IEnumerable)dataPart1).GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return dataPart1.GetEnumerator();
- }
-
- public int Run(ref byte[] data, int count, out int fullFlash)
- {
- var flashes = 0;
- fullFlash = 0;
- for (int i = 0; i < count; i++)
- {
- var start = flashes;
- Run(ref data, ref flashes);
- if (flashes - start == 100)
- {
- fullFlash = i + 1;
- break;
- }
- }
- return flashes;
- }
-
- public void Run(ref byte[] data, ref int flashes)
- {
- Increment(ref data);
- Flash(ref data, ref flashes);
- }
-
- private static void Increment(ref byte[] data)
- {
- for (int i = 0; i < data.Length; i++)
- data[i]++;
- }
-
- private void Flash(ref byte[] data, ref int flashes)
- {
- int diff;
- do
- {
- var startFlash = flashes;
- for (int i = 0; i < data.Length; i++)
- {
- if (data[i] > 9)
- PerformFlash(ref data, i, ref flashes);
- }
- diff = flashes - startFlash;
- } while (diff != 0);
- }
-
- private void PerformFlash(ref byte[] data, int index, ref int flashes)
- {
- flashes++;
- var y = index / 10;
- var x = index % 10;
-
- data[index] = 0;
-
- if (x > 0)
- {
- //Left
- index = x - 1 + y * 10;
- if (index >= 0 && data[index] != 0)
- data[index]++;
- }
- if (x < 9)
- {
- //Right
- index = x + 1 + y * 10;
- if (index < data.Length && data[index] != 0)
- data[index]++;
- }
- if (y > 0)
- {
- //Up
- index = x + 0 + (y - 1) * 10;
- if (index >= 0 && data[index] != 0)
- data[index]++;
- if (x > 0)
- {
- //Up Left
- index = x - 1 + (y - 1) * 10;
- if (index >= 0 && data[index] != 0)
- data[index]++;
- }
- if (x < 9)
- {
- //Up Right
- index = x + 1 + (y - 1) * 10;
- if (index < data.Length && data[index] != 0)
- data[index]++;
- }
- }
-
- if (y < 9)
- {
- //Bottom
- index = x + 0 + (y + 1) * 10;
- if (index < data.Length && data[index] != 0)
- data[index]++;
- if (x > 0)
- {
- //Bottom Left
- index = x - 1 + (y + 1) * 10;
- if (index < data.Length && data[index] != 0)
- data[index]++;
- }
- if (x < 9)
- {
- //Bottom Right
- index = x + 1 + (y + 1) * 10;
- if (index < data.Length && data[index] != 0)
- data[index]++;
- }
- }
- }
-
- //public override string ToString()
- //{
- // var output = new StringBuilder();
- // for (int y = 0; y < 10; y++)
- // {
- // for (int x = 0; x < 10; x++)
- // {
- // output.Append(DataPart1[x + y * 10]);
- // }
- // output.AppendLine();
- // }
- // return output.ToString();
- //}
-
- //public void Render()
- //{
- // for (int y = 0; y < 10; y++)
- // {
- // for (int x = 0; x < 10; x++)
- // {
- // var index = x + y * 10;
- // if (DataPart1[index] == 0)
- // Console.ForegroundColor = ConsoleColor.Magenta;
- // else
- // Console.ForegroundColor = ConsoleColor.White;
- // Console.Write(DataPart1[index]);
- // }
- // Console.WriteLine();
- // }
- //}
+using AdventOfCode.Runner.Attributes;
+
+using System.Collections;
+
+namespace AdventOfCode.Problems.AOC2021.Day11;
+
+[ProblemInfo(2021, 11, "Dumbo Octopus")]
+public class DumboOctopus : Problem, IEnumerable
+{
+ public byte[] dataPart1 = Array.Empty();
+ public byte[] dataPart2 = Array.Empty();
+
+ public override void LoadInput()
+ {
+ var data = ReadInputLines();
+ dataPart1 = new byte[10 * 10];
+ if (data.Length != 10)
+ throw new ArgumentException("Data must contain 10 elements", nameof(data));
+ for (int y = 0; y < data.Length; y++)
+ {
+ var line = data[y];
+ if (line.Length != 10)
+ throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data));
+
+ for (int x = 0; x < line.Length; x++)
+ {
+ dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1));
+ }
+ }
+ dataPart2 = new byte[10 * 10];
+ Array.Copy(dataPart1, dataPart2, dataPart1.Length);
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = Run(ref dataPart1, 100, out _);
+ }
+
+ public override void CalculatePart2()
+ {
+ Run(ref dataPart2, 210, out var fullFlash);
+ Part2 = fullFlash;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return ((IEnumerable)dataPart1).GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return dataPart1.GetEnumerator();
+ }
+
+ public int Run(ref byte[] data, int count, out int fullFlash)
+ {
+ var flashes = 0;
+ fullFlash = 0;
+ for (int i = 0; i < count; i++)
+ {
+ var start = flashes;
+ Run(ref data, ref flashes);
+ if (flashes - start == 100)
+ {
+ fullFlash = i + 1;
+ break;
+ }
+ }
+ return flashes;
+ }
+
+ public void Run(ref byte[] data, ref int flashes)
+ {
+ Increment(ref data);
+ Flash(ref data, ref flashes);
+ }
+
+ private static void Increment(ref byte[] data)
+ {
+ for (int i = 0; i < data.Length; i++)
+ data[i]++;
+ }
+
+ private void Flash(ref byte[] data, ref int flashes)
+ {
+ int diff;
+ do
+ {
+ var startFlash = flashes;
+ for (int i = 0; i < data.Length; i++)
+ {
+ if (data[i] > 9)
+ PerformFlash(ref data, i, ref flashes);
+ }
+ diff = flashes - startFlash;
+ } while (diff != 0);
+ }
+
+ private void PerformFlash(ref byte[] data, int index, ref int flashes)
+ {
+ flashes++;
+ var y = index / 10;
+ var x = index % 10;
+
+ data[index] = 0;
+
+ if (x > 0)
+ {
+ //Left
+ index = x - 1 + y * 10;
+ if (index >= 0 && data[index] != 0)
+ data[index]++;
+ }
+ if (x < 9)
+ {
+ //Right
+ index = x + 1 + y * 10;
+ if (index < data.Length && data[index] != 0)
+ data[index]++;
+ }
+ if (y > 0)
+ {
+ //Up
+ index = x + 0 + (y - 1) * 10;
+ if (index >= 0 && data[index] != 0)
+ data[index]++;
+ if (x > 0)
+ {
+ //Up Left
+ index = x - 1 + (y - 1) * 10;
+ if (index >= 0 && data[index] != 0)
+ data[index]++;
+ }
+ if (x < 9)
+ {
+ //Up Right
+ index = x + 1 + (y - 1) * 10;
+ if (index < data.Length && data[index] != 0)
+ data[index]++;
+ }
+ }
+
+ if (y < 9)
+ {
+ //Bottom
+ index = x + 0 + (y + 1) * 10;
+ if (index < data.Length && data[index] != 0)
+ data[index]++;
+ if (x > 0)
+ {
+ //Bottom Left
+ index = x - 1 + (y + 1) * 10;
+ if (index < data.Length && data[index] != 0)
+ data[index]++;
+ }
+ if (x < 9)
+ {
+ //Bottom Right
+ index = x + 1 + (y + 1) * 10;
+ if (index < data.Length && data[index] != 0)
+ data[index]++;
+ }
+ }
+ }
+
+ //public override string ToString()
+ //{
+ // var output = new StringBuilder();
+ // for (int y = 0; y < 10; y++)
+ // {
+ // for (int x = 0; x < 10; x++)
+ // {
+ // output.Append(DataPart1[x + y * 10]);
+ // }
+ // output.AppendLine();
+ // }
+ // return output.ToString();
+ //}
+
+ //public void Render()
+ //{
+ // for (int y = 0; y < 10; y++)
+ // {
+ // for (int x = 0; x < 10; x++)
+ // {
+ // var index = x + y * 10;
+ // if (DataPart1[index] == 0)
+ // Console.ForegroundColor = ConsoleColor.Magenta;
+ // else
+ // Console.ForegroundColor = ConsoleColor.White;
+ // Console.Write(DataPart1[index]);
+ // }
+ // Console.WriteLine();
+ // }
+ //}
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2021/Day3/BinaryDiagnostic.cs b/AdventOfCode/Problems/AOC2021/Day3/BinaryDiagnostic.cs
index ec63e99..3004114 100644
--- a/AdventOfCode/Problems/AOC2021/Day3/BinaryDiagnostic.cs
+++ b/AdventOfCode/Problems/AOC2021/Day3/BinaryDiagnostic.cs
@@ -1,71 +1,71 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2021.Day3;
-
-[ProblemInfo(2021, 3, "Binary Diagnostic")]
-public class BinaryDiagnostic : Problem
-{
- public int[][] Data { get; set; } = Array.Empty();
-
- private static int ToDecimal(int[] value)
- {
- return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum();
- }
-
- public override void LoadInput()
- {
- var data = ReadInputLines();
- Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray();
- }
-
- public override void CalculatePart1()
- {
- var width = Data[0].Length;
- var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx]));
-
- var transposed2 = new int[width][];
- for (int i = 0; i < width; i++)
- {
- transposed2[i] = Data.Select(row => row[i]).ToArray();
- }
-
- var mid = Data.Length / 2;
- 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 gammaDec = ToDecimal(gamma);
- var epsilongDec = ToDecimal(epsilon);
-
- Part1 = gammaDec * epsilongDec;
- }
-
- public override void CalculatePart2()
- {
- var oxygen = Data;
- var index = 0;
- while (oxygen.Length > 1)
- {
- var t = oxygen.Select(row => row[index]);
- var m = oxygen.Length / 2f;
- var g = t.Count(c => c == 1) >= m ? 1 : 0;
- oxygen = oxygen.Where(row => row[index] == g).ToArray();
- index++;
- }
-
- var carbon = Data;
- index = 0;
- while (carbon.Length > 1)
- {
- var t = carbon.Select(row => row[index]);
- var m = carbon.Length / 2f;
- var e = t.Count(c => c == 1) < m ? 1 : 0;
- carbon = carbon.Where(row => row[index] == e).ToArray();
- index++;
- }
-
- var oxygenLevel = ToDecimal(oxygen.First());
- var carbonLevel = ToDecimal(carbon.First());
-
- Part2 = oxygenLevel * carbonLevel;
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2021.Day3;
+
+[ProblemInfo(2021, 3, "Binary Diagnostic")]
+public class BinaryDiagnostic : Problem
+{
+ public int[][] Data { get; set; } = Array.Empty();
+
+ private static int ToDecimal(int[] value)
+ {
+ return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum();
+ }
+
+ public override void LoadInput()
+ {
+ var data = ReadInputLines();
+ Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray();
+ }
+
+ public override void CalculatePart1()
+ {
+ var width = Data[0].Length;
+ var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx]));
+
+ var transposed2 = new int[width][];
+ for (int i = 0; i < width; i++)
+ {
+ transposed2[i] = Data.Select(row => row[i]).ToArray();
+ }
+
+ var mid = Data.Length / 2;
+ 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 gammaDec = ToDecimal(gamma);
+ var epsilongDec = ToDecimal(epsilon);
+
+ Part1 = gammaDec * epsilongDec;
+ }
+
+ public override void CalculatePart2()
+ {
+ var oxygen = Data;
+ var index = 0;
+ while (oxygen.Length > 1)
+ {
+ var t = oxygen.Select(row => row[index]);
+ var m = oxygen.Length / 2f;
+ var g = t.Count(c => c == 1) >= m ? 1 : 0;
+ oxygen = oxygen.Where(row => row[index] == g).ToArray();
+ index++;
+ }
+
+ var carbon = Data;
+ index = 0;
+ while (carbon.Length > 1)
+ {
+ var t = carbon.Select(row => row[index]);
+ var m = carbon.Length / 2f;
+ var e = t.Count(c => c == 1) < m ? 1 : 0;
+ carbon = carbon.Where(row => row[index] == e).ToArray();
+ index++;
+ }
+
+ var oxygenLevel = ToDecimal(oxygen.First());
+ var carbonLevel = ToDecimal(carbon.First());
+
+ Part2 = oxygenLevel * carbonLevel;
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2021/Day6/LanternFish.cs b/AdventOfCode/Problems/AOC2021/Day6/LanternFish.cs
index e507ec2..5c374ab 100644
--- a/AdventOfCode/Problems/AOC2021/Day6/LanternFish.cs
+++ b/AdventOfCode/Problems/AOC2021/Day6/LanternFish.cs
@@ -1,50 +1,50 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2021.Day6;
-
-[ProblemInfo(2021, 6, "Lanternfish")]
-internal class LanternFish : Problem
-{
- public int[] Data { get; private set; } = Array.Empty();
-
- public override void LoadInput()
- {
- var input = ReadInputLines();
- Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray();
- }
-
- public override void CalculatePart1()
- {
- var lifetimes = PrepareLifetimes();
- Part1 = Simulate(lifetimes, 80);
- }
-
- public override void CalculatePart2()
- {
- var lifetimes = PrepareLifetimes();
- Part2 = Simulate(lifetimes, 256);
- }
-
- private long[] PrepareLifetimes()
- {
- var lifetimes = new long[9];
- foreach (var life in Data)
- lifetimes[life] += 1;
-
- return lifetimes;
- }
-
- private static long Simulate(long[] lifetimes, int days)
- {
- for (int i = 0; i < days; i++)
- {
- var day0Count = lifetimes[0];
- for (int j = 1; j < lifetimes.Length; j++)
- lifetimes[j - 1] = lifetimes[j];
- lifetimes[6] += day0Count;
- lifetimes[^1] = day0Count;
- }
-
- return lifetimes.Sum();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2021.Day6;
+
+[ProblemInfo(2021, 6, "Lanternfish")]
+internal class LanternFish : Problem
+{
+ public int[] Data { get; private set; } = Array.Empty();
+
+ public override void LoadInput()
+ {
+ var input = ReadInputLines();
+ Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray();
+ }
+
+ public override void CalculatePart1()
+ {
+ var lifetimes = PrepareLifetimes();
+ Part1 = Simulate(lifetimes, 80);
+ }
+
+ public override void CalculatePart2()
+ {
+ var lifetimes = PrepareLifetimes();
+ Part2 = Simulate(lifetimes, 256);
+ }
+
+ private long[] PrepareLifetimes()
+ {
+ var lifetimes = new long[9];
+ foreach (var life in Data)
+ lifetimes[life] += 1;
+
+ return lifetimes;
+ }
+
+ private static long Simulate(long[] lifetimes, int days)
+ {
+ for (int i = 0; i < days; i++)
+ {
+ var day0Count = lifetimes[0];
+ for (int j = 1; j < lifetimes.Length; j++)
+ lifetimes[j - 1] = lifetimes[j];
+ lifetimes[6] += day0Count;
+ lifetimes[^1] = day0Count;
+ }
+
+ return lifetimes.Sum();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs b/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs
index ccb7e78..fa9798d 100644
--- a/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs
+++ b/AdventOfCode/Problems/AOC2022/Day0/TestProblem.cs
@@ -1,32 +1,32 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day0;
-
-[ProblemInfo(2022, 0, "Fancy Test")]
-public class TestProblem : Problem
-{
- public override void LoadInput()
- {
- Thread.Sleep(1000);
- }
-
- public override void CalculatePart1()
- {
- Thread.Sleep(1000);
- }
-
- public override void CalculatePart2()
- {
- Thread.Sleep(1000);
- }
-
- public override void PrintPart1()
- {
- Console.WriteLine("Result");
- }
-
- public override void PrintPart2()
- {
- Console.WriteLine("Result 2");
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day0;
+
+[ProblemInfo(2022, 0, "Fancy Test")]
+public class TestProblem : Problem
+{
+ public override void LoadInput()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public override void CalculatePart1()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public override void CalculatePart2()
+ {
+ Thread.Sleep(1000);
+ }
+
+ public override void PrintPart1()
+ {
+ Console.WriteLine("Result");
+ }
+
+ public override void PrintPart2()
+ {
+ Console.WriteLine("Result 2");
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day1/CalorieCounting.cs b/AdventOfCode/Problems/AOC2022/Day1/CalorieCounting.cs
index 11555c9..9398ca1 100644
--- a/AdventOfCode/Problems/AOC2022/Day1/CalorieCounting.cs
+++ b/AdventOfCode/Problems/AOC2022/Day1/CalorieCounting.cs
@@ -1,54 +1,54 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day1;
-
-[ProblemInfo(2022, 1, "Calorie Counting")]
-internal class CalorieCounting : Problem
-{
- public List> FlaresFood { get; set; }
-
- private (int calories, int elf)? _mostestElf;
- private IEnumerable<(int sum, int idx)>? _mostestElves;
-
- public CalorieCounting()
- {
- FlaresFood = new List>
- {
- new List()
- };
- }
-
- public override void LoadInput()
- {
- var lines = File.ReadAllLines(GetInputFile("input.txt"));
- var c = 0;
- foreach (var calorie in lines)
- {
- if (string.IsNullOrWhiteSpace(calorie))
- {
- FlaresFood.Add(new List());
- c++;
- continue;
- }
- FlaresFood[c].Add(int.Parse(calorie));
- }
- }
-
- public override void CalculatePart1()
- {
- _mostestElf = FlaresFood
- .Select((x, idx) => (sum: x.Sum(), idx))
- .MaxBy(x => x.sum);
-
- Part1 = _mostestElf.Value.ToString();
- }
-
- public override void CalculatePart2()
- {
- _mostestElves = FlaresFood
- .Select((x, idx) => (sum: x.Sum(), idx))
- .OrderByDescending(e => e.sum)
- .Take(3);
- Part2 = _mostestElves.Sum(e => e.sum).ToString();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day1;
+
+[ProblemInfo(2022, 1, "Calorie Counting")]
+internal class CalorieCounting : Problem
+{
+ public List> FlaresFood { get; set; }
+
+ private (int calories, int elf)? _mostestElf;
+ private IEnumerable<(int sum, int idx)>? _mostestElves;
+
+ public CalorieCounting()
+ {
+ FlaresFood = new List>
+ {
+ new List()
+ };
+ }
+
+ public override void LoadInput()
+ {
+ var lines = File.ReadAllLines(GetInputFile("input.txt"));
+ var c = 0;
+ foreach (var calorie in lines)
+ {
+ if (string.IsNullOrWhiteSpace(calorie))
+ {
+ FlaresFood.Add(new List());
+ c++;
+ continue;
+ }
+ FlaresFood[c].Add(int.Parse(calorie));
+ }
+ }
+
+ public override void CalculatePart1()
+ {
+ _mostestElf = FlaresFood
+ .Select((x, idx) => (sum: x.Sum(), idx))
+ .MaxBy(x => x.sum);
+
+ Part1 = _mostestElf.Value.ToString();
+ }
+
+ public override void CalculatePart2()
+ {
+ _mostestElves = FlaresFood
+ .Select((x, idx) => (sum: x.Sum(), idx))
+ .OrderByDescending(e => e.sum)
+ .Take(3);
+ Part2 = _mostestElves.Sum(e => e.sum).ToString();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day10/CathodeCPU.cs b/AdventOfCode/Problems/AOC2022/Day10/CathodeCPU.cs
index 677a55b..d721929 100644
--- a/AdventOfCode/Problems/AOC2022/Day10/CathodeCPU.cs
+++ b/AdventOfCode/Problems/AOC2022/Day10/CathodeCPU.cs
@@ -1,66 +1,66 @@
-namespace AdventOfCode.Problems.AOC2022.Day10;
-
-internal class CathodeCPU
-{
- public enum Instruction
- {
- NoOp,
- AddX
- }
-
- public int X { get; private set; } = 1;
- private int _cycleNumber = 1;
- private int _programCounter;
- private int _pending = -1;
-
- public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func? processor = null)
- {
- var result = new int[outputCycles.Length];
-
- var ridx = 0;
-
- if (processor == null)
- processor = (c, x) => c * x;
-
- ExecuteCode(code, (c, x) =>
- {
- if (ridx < outputCycles.Length && c == outputCycles[ridx])
- {
- result[ridx] = processor(c, x);
- ridx++;
- }
- });
-
- return result;
- }
-
- public void ExecuteCode((Instruction ins, int value)[] code, Action processor)
- {
- while (_programCounter < code.Length)
- {
- var (ins, value) = code[_programCounter];
-
- processor(_cycleNumber, X);
-
- switch ((ins, _pending))
- {
- case { ins: Instruction.NoOp }:
- _programCounter++;
- break;
-
- case { ins: Instruction.AddX, _pending: -1 }:
- _pending = 1;
- break;
-
- case { ins: Instruction.AddX, _pending: 0 }:
- X += value;
- _programCounter++;
- break;
- }
-
- if (_pending >= 0)
- _pending--;
- _cycleNumber++;
- }
- }
+namespace AdventOfCode.Problems.AOC2022.Day10;
+
+internal class CathodeCPU
+{
+ public enum Instruction
+ {
+ NoOp,
+ AddX
+ }
+
+ public int X { get; private set; } = 1;
+ private int _cycleNumber = 1;
+ private int _programCounter;
+ private int _pending = -1;
+
+ public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func? processor = null)
+ {
+ var result = new int[outputCycles.Length];
+
+ var ridx = 0;
+
+ if (processor == null)
+ processor = (c, x) => c * x;
+
+ ExecuteCode(code, (c, x) =>
+ {
+ if (ridx < outputCycles.Length && c == outputCycles[ridx])
+ {
+ result[ridx] = processor(c, x);
+ ridx++;
+ }
+ });
+
+ return result;
+ }
+
+ public void ExecuteCode((Instruction ins, int value)[] code, Action processor)
+ {
+ while (_programCounter < code.Length)
+ {
+ var (ins, value) = code[_programCounter];
+
+ processor(_cycleNumber, X);
+
+ switch ((ins, _pending))
+ {
+ case { ins: Instruction.NoOp }:
+ _programCounter++;
+ break;
+
+ case { ins: Instruction.AddX, _pending: -1 }:
+ _pending = 1;
+ break;
+
+ case { ins: Instruction.AddX, _pending: 0 }:
+ X += value;
+ _programCounter++;
+ break;
+ }
+
+ if (_pending >= 0)
+ _pending--;
+ _cycleNumber++;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day10/CathodeRayTube.cs b/AdventOfCode/Problems/AOC2022/Day10/CathodeRayTube.cs
index 1ce3416..2039115 100644
--- a/AdventOfCode/Problems/AOC2022/Day10/CathodeRayTube.cs
+++ b/AdventOfCode/Problems/AOC2022/Day10/CathodeRayTube.cs
@@ -1,55 +1,55 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day10;
-
-[ProblemInfo(2022, 10, "Cathode-Ray Tube")]
-internal class CathodeRayTube : Problem
-{
- private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>();
-
- public override void CalculatePart1()
- {
- var cpu = new CathodeCPU();
- var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 });
- Part1 = result.Sum();
- }
-
- public override void CalculatePart2()
- {
- var output = Enumerable.Repeat(' ', 6 * 40).ToArray();
-
- var cpu = new CathodeCPU();
- cpu.ExecuteCode(_code, (cycle, signal) =>
- {
- cycle -= 1;
- if (cycle > output.Length)
- return;
-
- var pos = signal % 40;
- var head = (cycle % 40);
- var sprite = Math.Abs(pos - head);
- if (sprite <= 1)
- output[cycle] = '█';
- });
-
- var lines = output.Chunk(40).Select(r => new string(r));
- Part2 = $"\n{string.Join("\n", lines)}";
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- _code = new (CathodeCPU.Instruction ins, int value)[lines.Length];
- for (int i = 0; i < lines.Length; i++)
- {
- var ln = lines[i];
- if (ln == "noop")
- _code[i] = (CathodeCPU.Instruction.NoOp, 0);
- else
- {
- var instruction = ln.Split(' ');
- _code[i] = (Enum.Parse(instruction[0], true), int.Parse(instruction[1]));
- }
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day10;
+
+[ProblemInfo(2022, 10, "Cathode-Ray Tube")]
+internal class CathodeRayTube : Problem
+{
+ private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>();
+
+ public override void CalculatePart1()
+ {
+ var cpu = new CathodeCPU();
+ var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 });
+ Part1 = result.Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ var output = Enumerable.Repeat(' ', 6 * 40).ToArray();
+
+ var cpu = new CathodeCPU();
+ cpu.ExecuteCode(_code, (cycle, signal) =>
+ {
+ cycle -= 1;
+ if (cycle > output.Length)
+ return;
+
+ var pos = signal % 40;
+ var head = (cycle % 40);
+ var sprite = Math.Abs(pos - head);
+ if (sprite <= 1)
+ output[cycle] = '█';
+ });
+
+ var lines = output.Chunk(40).Select(r => new string(r));
+ Part2 = $"\n{string.Join("\n", lines)}";
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ _code = new (CathodeCPU.Instruction ins, int value)[lines.Length];
+ for (int i = 0; i < lines.Length; i++)
+ {
+ var ln = lines[i];
+ if (ln == "noop")
+ _code[i] = (CathodeCPU.Instruction.NoOp, 0);
+ else
+ {
+ var instruction = ln.Split(' ');
+ _code[i] = (Enum.Parse(instruction[0], true), int.Parse(instruction[1]));
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day11/Monkey.cs b/AdventOfCode/Problems/AOC2022/Day11/Monkey.cs
index e26b678..cb13ed5 100644
--- a/AdventOfCode/Problems/AOC2022/Day11/Monkey.cs
+++ b/AdventOfCode/Problems/AOC2022/Day11/Monkey.cs
@@ -1,73 +1,73 @@
-using System.Numerics;
-
-namespace AdventOfCode.Problems.AOC2022.Day11;
-
-internal class Monkey
-{
- public int MonkeyNumber { get; set; }
- public int InspectionCount { get; private set; }
- public List Items { get; set; }
-
- private MonkeyOperator _operator;
- private uint _operand;
- private uint _divisor;
- private int _trueTarget;
- private int _falseTarget;
-
- public Monkey(string[] lines)
- {
- Items = new List();
- MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]);
- Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList();
- var operation = lines[2].Split("= old ")[^1];
- _operator = operation[0] switch
- {
- '*' => MonkeyOperator.Multiply,
- '+' => MonkeyOperator.Add,
- _ => MonkeyOperator.Add
- };
- if (!uint.TryParse(operation[1..], out _operand))
- _operator = MonkeyOperator.Power;
-
- _divisor = uint.Parse(lines[3].Split(' ')[^1]);
- _trueTarget = int.Parse(lines[4].Split(' ')[^1]);
- _falseTarget = int.Parse(lines[5].Split(' ')[^1]);
- }
-
- public BigInteger Inspect(BigInteger value, uint worryOffset = 3)
- {
- InspectionCount++;
- value = Operate(value);
- if (worryOffset != 0)
- value /= worryOffset;
- return value;
- }
-
- public int GetThrowTarget(BigInteger value)
- {
- return value % _divisor == 0 ? _trueTarget : _falseTarget;
- }
-
- private BigInteger Operate(BigInteger value)
- {
- return _operator switch
- {
- MonkeyOperator.Multiply => value * _operand,
- MonkeyOperator.Add => value + _operand,
- MonkeyOperator.Power => value * value,
- _ => value
- };
- }
-
- private enum MonkeyOperator
- {
- Multiply,
- Add,
- Power
- }
-
- public override string ToString()
- {
- return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]";
- }
+using System.Numerics;
+
+namespace AdventOfCode.Problems.AOC2022.Day11;
+
+internal class Monkey
+{
+ public int MonkeyNumber { get; set; }
+ public int InspectionCount { get; private set; }
+ public List Items { get; set; }
+
+ private MonkeyOperator _operator;
+ private uint _operand;
+ private uint _divisor;
+ private int _trueTarget;
+ private int _falseTarget;
+
+ public Monkey(string[] lines)
+ {
+ Items = new List();
+ MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]);
+ Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList();
+ var operation = lines[2].Split("= old ")[^1];
+ _operator = operation[0] switch
+ {
+ '*' => MonkeyOperator.Multiply,
+ '+' => MonkeyOperator.Add,
+ _ => MonkeyOperator.Add
+ };
+ if (!uint.TryParse(operation[1..], out _operand))
+ _operator = MonkeyOperator.Power;
+
+ _divisor = uint.Parse(lines[3].Split(' ')[^1]);
+ _trueTarget = int.Parse(lines[4].Split(' ')[^1]);
+ _falseTarget = int.Parse(lines[5].Split(' ')[^1]);
+ }
+
+ public BigInteger Inspect(BigInteger value, uint worryOffset = 3)
+ {
+ InspectionCount++;
+ value = Operate(value);
+ if (worryOffset != 0)
+ value /= worryOffset;
+ return value;
+ }
+
+ public int GetThrowTarget(BigInteger value)
+ {
+ return value % _divisor == 0 ? _trueTarget : _falseTarget;
+ }
+
+ private BigInteger Operate(BigInteger value)
+ {
+ return _operator switch
+ {
+ MonkeyOperator.Multiply => value * _operand,
+ MonkeyOperator.Add => value + _operand,
+ MonkeyOperator.Power => value * value,
+ _ => value
+ };
+ }
+
+ private enum MonkeyOperator
+ {
+ Multiply,
+ Add,
+ Power
+ }
+
+ public override string ToString()
+ {
+ return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]";
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day11/MonkeyInTheMiddle.cs b/AdventOfCode/Problems/AOC2022/Day11/MonkeyInTheMiddle.cs
index 20526c7..eb08f89 100644
--- a/AdventOfCode/Problems/AOC2022/Day11/MonkeyInTheMiddle.cs
+++ b/AdventOfCode/Problems/AOC2022/Day11/MonkeyInTheMiddle.cs
@@ -1,60 +1,60 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day11;
-
-[ProblemInfo(2022, 11, "Monkey in the Middle")]
-internal class MonkeyInTheMiddle : Problem
-{
- private Monkey[] _monkeysPart1 = Array.Empty();
- private Monkey[] _monkeysPart2 = Array.Empty();
-
- public override void CalculatePart1()
- {
- Simulate(_monkeysPart1, 20);
- Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount)
- .Take(2)
- .Select(m => m.InspectionCount)
- .Aggregate((a, b) => a * b);
- }
-
- public override void CalculatePart2()
- {
- Simulate(_monkeysPart2, 10000, 0);
- Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount)
- .Take(2)
- .Select(m => m.InspectionCount)
- .Aggregate((a, b) => a * b);
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("test.txt").Chunk(7);
- _monkeysPart1 = 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)
- {
- for (int i = 0; i < rounds; i++)
- {
- SimulateRound(monkeys, worry);
- }
- }
-
- private static void SimulateRound(Monkey[] monkeys, uint worry = 3)
- {
- foreach (var monkey in monkeys)
- SimulateTurn(monkey, monkeys, worry);
- }
-
- private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3)
- {
- for (int i = 0; i < monkey.Items.Count; i++)
- {
- var item = monkey.Inspect(monkey.Items[i], worry);
- var target = monkey.GetThrowTarget(item);
- monkeys[target].Items.Add(item);
- }
- monkey.Items.Clear();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day11;
+
+[ProblemInfo(2022, 11, "Monkey in the Middle")]
+internal class MonkeyInTheMiddle : Problem
+{
+ private Monkey[] _monkeysPart1 = Array.Empty();
+ private Monkey[] _monkeysPart2 = Array.Empty();
+
+ public override void CalculatePart1()
+ {
+ Simulate(_monkeysPart1, 20);
+ Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount)
+ .Take(2)
+ .Select(m => m.InspectionCount)
+ .Aggregate((a, b) => a * b);
+ }
+
+ public override void CalculatePart2()
+ {
+ Simulate(_monkeysPart2, 10000, 0);
+ Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount)
+ .Take(2)
+ .Select(m => m.InspectionCount)
+ .Aggregate((a, b) => a * b);
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("test.txt").Chunk(7);
+ _monkeysPart1 = 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)
+ {
+ for (int i = 0; i < rounds; i++)
+ {
+ SimulateRound(monkeys, worry);
+ }
+ }
+
+ private static void SimulateRound(Monkey[] monkeys, uint worry = 3)
+ {
+ foreach (var monkey in monkeys)
+ SimulateTurn(monkey, monkeys, worry);
+ }
+
+ private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3)
+ {
+ for (int i = 0; i < monkey.Items.Count; i++)
+ {
+ var item = monkey.Inspect(monkey.Items[i], worry);
+ var target = monkey.GetThrowTarget(item);
+ monkeys[target].Items.Add(item);
+ }
+ monkey.Items.Clear();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day12/HillClimbing.cs b/AdventOfCode/Problems/AOC2022/Day12/HillClimbing.cs
index 4c0b0c2..90c6573 100644
--- a/AdventOfCode/Problems/AOC2022/Day12/HillClimbing.cs
+++ b/AdventOfCode/Problems/AOC2022/Day12/HillClimbing.cs
@@ -1,22 +1,22 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day12;
-
-[ProblemInfo(2022, 12, "Hill Climbing Algorithm")]
-internal class HillClimbing : Problem
-{
- public override void CalculatePart1()
- {
- throw new NotImplementedException();
- }
-
- public override void CalculatePart2()
- {
- throw new NotImplementedException();
- }
-
- public override void LoadInput()
- {
- throw new NotImplementedException();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day12;
+
+[ProblemInfo(2022, 12, "Hill Climbing Algorithm")]
+internal class HillClimbing : Problem
+{
+ public override void CalculatePart1()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void CalculatePart2()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void LoadInput()
+ {
+ throw new NotImplementedException();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day13/DistressSignal.cs b/AdventOfCode/Problems/AOC2022/Day13/DistressSignal.cs
index bba79ef..ba26680 100644
--- a/AdventOfCode/Problems/AOC2022/Day13/DistressSignal.cs
+++ b/AdventOfCode/Problems/AOC2022/Day13/DistressSignal.cs
@@ -1,22 +1,22 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day13;
-
-[ProblemInfo(2022, 13, "Distress Signal")]
-internal class DistressSignal : Problem
-{
- public override void CalculatePart1()
- {
- throw new NotImplementedException();
- }
-
- public override void CalculatePart2()
- {
- throw new NotImplementedException();
- }
-
- public override void LoadInput()
- {
- throw new NotImplementedException();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day13;
+
+[ProblemInfo(2022, 13, "Distress Signal")]
+internal class DistressSignal : Problem
+{
+ public override void CalculatePart1()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void CalculatePart2()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void LoadInput()
+ {
+ throw new NotImplementedException();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day14/RegolithReservoir.cs b/AdventOfCode/Problems/AOC2022/Day14/RegolithReservoir.cs
index 82dd291..8b837ca 100644
--- a/AdventOfCode/Problems/AOC2022/Day14/RegolithReservoir.cs
+++ b/AdventOfCode/Problems/AOC2022/Day14/RegolithReservoir.cs
@@ -1,22 +1,22 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day14;
-
-[ProblemInfo(2022, 14, "Regolith Reservoir")]
-internal class RegolithReservoir : Problem
-{
- public override void CalculatePart1()
- {
- throw new NotImplementedException();
- }
-
- public override void CalculatePart2()
- {
- throw new NotImplementedException();
- }
-
- public override void LoadInput()
- {
- throw new NotImplementedException();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day14;
+
+[ProblemInfo(2022, 14, "Regolith Reservoir")]
+internal class RegolithReservoir : Problem
+{
+ public override void CalculatePart1()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void CalculatePart2()
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void LoadInput()
+ {
+ throw new NotImplementedException();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day2/RockPaperScissors.cs b/AdventOfCode/Problems/AOC2022/Day2/RockPaperScissors.cs
index 4029747..c5f535a 100644
--- a/AdventOfCode/Problems/AOC2022/Day2/RockPaperScissors.cs
+++ b/AdventOfCode/Problems/AOC2022/Day2/RockPaperScissors.cs
@@ -1,100 +1,100 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day2;
-
-[ProblemInfo(2022, 2, "Rock Paper Scissors")]
-internal class RockPaperScissors : Problem
-{
- private string[] _lines;
-
- public RockPaperScissors()
- {
- _lines = Array.Empty();
- }
-
- public override void LoadInput()
- {
- _lines = File.ReadAllLines(GetInputFile("input.txt"));
- }
-
- public override void CalculatePart1()
- {
- var totalScore = 0;
- foreach (var line in _lines)
- {
- var move = line[0];
- var response = line[^1];
-
- totalScore += GetMoveValue(response);
- totalScore += GetResult(move, response);
- }
- Part1 = totalScore.ToString();
- }
-
- private static int GetMoveValue(char move)
- {
- return move switch
- {
- 'A' => 1,
- 'B' => 2,
- 'C' => 3,
- 'X' => 1,
- 'Y' => 2,
- 'Z' => 3,
- _ => 0,
- };
- }
-
- private static int GetResult(char move, char response)
- {
- return (move, response) switch
- {
- ('A', 'X') => 3,
- ('B', 'X') => 0,
- ('C', 'X') => 6,
- ('A', 'Y') => 6,
- ('B', 'Y') => 3,
- ('C', 'Y') => 0,
- ('A', 'Z') => 0,
- ('B', 'Z') => 6,
- ('C', 'Z') => 3,
- _ => 0,
- };
- }
-
- private static int GetResultValue(char result)
- {
- return result switch
- {
- 'X' => 0,
- 'Y' => 3,
- 'Z' => 6,
- _ => 0,
- };
- }
-
- private static int GetResponseValue(char move, char result)
- {
- var p = result switch
- {
- 'X' => (GetMoveValue(move) + 2) % 3, //Lose
- 'Y' => GetMoveValue(move), //Tie
- 'Z' => (GetMoveValue(move) + 1) % 3, //Win
- _ => 0
- };
- return p == 0 ? 3 : p;
- }
-
- public override void CalculatePart2()
- {
- var score = 0;
- foreach (var line in _lines)
- {
- var move = line[0];
- var result = line[^1];
- score += GetResponseValue(move, result);
- score += GetResultValue(result);
- }
- Part2 = score.ToString();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day2;
+
+[ProblemInfo(2022, 2, "Rock Paper Scissors")]
+internal class RockPaperScissors : Problem
+{
+ private string[] _lines;
+
+ public RockPaperScissors()
+ {
+ _lines = Array.Empty();
+ }
+
+ public override void LoadInput()
+ {
+ _lines = File.ReadAllLines(GetInputFile("input.txt"));
+ }
+
+ public override void CalculatePart1()
+ {
+ var totalScore = 0;
+ foreach (var line in _lines)
+ {
+ var move = line[0];
+ var response = line[^1];
+
+ totalScore += GetMoveValue(response);
+ totalScore += GetResult(move, response);
+ }
+ Part1 = totalScore.ToString();
+ }
+
+ private static int GetMoveValue(char move)
+ {
+ return move switch
+ {
+ 'A' => 1,
+ 'B' => 2,
+ 'C' => 3,
+ 'X' => 1,
+ 'Y' => 2,
+ 'Z' => 3,
+ _ => 0,
+ };
+ }
+
+ private static int GetResult(char move, char response)
+ {
+ return (move, response) switch
+ {
+ ('A', 'X') => 3,
+ ('B', 'X') => 0,
+ ('C', 'X') => 6,
+ ('A', 'Y') => 6,
+ ('B', 'Y') => 3,
+ ('C', 'Y') => 0,
+ ('A', 'Z') => 0,
+ ('B', 'Z') => 6,
+ ('C', 'Z') => 3,
+ _ => 0,
+ };
+ }
+
+ private static int GetResultValue(char result)
+ {
+ return result switch
+ {
+ 'X' => 0,
+ 'Y' => 3,
+ 'Z' => 6,
+ _ => 0,
+ };
+ }
+
+ private static int GetResponseValue(char move, char result)
+ {
+ var p = result switch
+ {
+ 'X' => (GetMoveValue(move) + 2) % 3, //Lose
+ 'Y' => GetMoveValue(move), //Tie
+ 'Z' => (GetMoveValue(move) + 1) % 3, //Win
+ _ => 0
+ };
+ return p == 0 ? 3 : p;
+ }
+
+ public override void CalculatePart2()
+ {
+ var score = 0;
+ foreach (var line in _lines)
+ {
+ var move = line[0];
+ var result = line[^1];
+ score += GetResponseValue(move, result);
+ score += GetResultValue(result);
+ }
+ Part2 = score.ToString();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day3/RucksackReorganization.cs b/AdventOfCode/Problems/AOC2022/Day3/RucksackReorganization.cs
index 821ac0a..33ad3c9 100644
--- a/AdventOfCode/Problems/AOC2022/Day3/RucksackReorganization.cs
+++ b/AdventOfCode/Problems/AOC2022/Day3/RucksackReorganization.cs
@@ -1,54 +1,54 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day3;
-
-[ProblemInfo(2022, 3, "Rucksack Reorganization")]
-internal class RucksackReorganization : Problem
-{
- private string[] _sacks;
-
- public RucksackReorganization()
- {
- _sacks = Array.Empty();
- }
-
- public override void LoadInput()
- {
- _sacks = ReadInputLines("input.txt");
- }
-
- public override void CalculatePart1()
- {
- var total = 0;
- foreach (var sack in _sacks)
- {
- var mid = sack.Length / 2;
- var left = sack[..mid];
- var right = sack[mid..];
- var common = right.First(itm => left.Contains(itm));
- total += GetValue(common);
- }
- Part1 = total.ToString();
- }
-
- public static int GetValue(char c)
- {
- return c switch
- {
- <= 'Z' => c - 'A' + 27,
- _ => c - 'a' + 1
- };
- }
-
- public override void CalculatePart2()
- {
- var groups = _sacks.Chunk(3);
- var total = 0;
- foreach (var group in groups)
- {
- var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge)));
- total += GetValue(badgeType);
- }
- Part2 = total.ToString();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day3;
+
+[ProblemInfo(2022, 3, "Rucksack Reorganization")]
+internal class RucksackReorganization : Problem
+{
+ private string[] _sacks;
+
+ public RucksackReorganization()
+ {
+ _sacks = Array.Empty();
+ }
+
+ public override void LoadInput()
+ {
+ _sacks = ReadInputLines("input.txt");
+ }
+
+ public override void CalculatePart1()
+ {
+ var total = 0;
+ foreach (var sack in _sacks)
+ {
+ var mid = sack.Length / 2;
+ var left = sack[..mid];
+ var right = sack[mid..];
+ var common = right.First(itm => left.Contains(itm));
+ total += GetValue(common);
+ }
+ Part1 = total.ToString();
+ }
+
+ public static int GetValue(char c)
+ {
+ return c switch
+ {
+ <= 'Z' => c - 'A' + 27,
+ _ => c - 'a' + 1
+ };
+ }
+
+ public override void CalculatePart2()
+ {
+ var groups = _sacks.Chunk(3);
+ var total = 0;
+ foreach (var group in groups)
+ {
+ var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge)));
+ total += GetValue(badgeType);
+ }
+ Part2 = total.ToString();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day4/CampCleanup.cs b/AdventOfCode/Problems/AOC2022/Day4/CampCleanup.cs
index ce307c3..fdbd5cf 100644
--- a/AdventOfCode/Problems/AOC2022/Day4/CampCleanup.cs
+++ b/AdventOfCode/Problems/AOC2022/Day4/CampCleanup.cs
@@ -1,63 +1,63 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day4;
-
-[ProblemInfo(2022, 4, "Camp Cleanup")]
-internal class CampCleanup : Problem
-{
- private List<(Range a, Range b)> _pairs = new(500);
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- foreach (var line in lines)
- {
- var (a, b) = line.Split(',')
- .Select(range =>
- range.Split('-')
- .Select(v => int.Parse(v))
- .Chunk(2)
- .Select(r => new Range(r.First(), r.Last()))
- .First()
- ).Chunk(2)
- .Select(pair => (pair.First(), pair.Last()))
- .First();
- _pairs.Add((a, b));
- }
- }
-
- public override void CalculatePart1()
- {
- var total = 0;
- foreach (var (a, b) in _pairs)
- {
- if (a.Contains(b) || b.Contains(a))
- total++;
- }
- Part1 = total;
- }
-
- public override void CalculatePart2()
- {
- foreach (var (a, b) in _pairs)
- {
- if (a.OverlapsWith(b))
- Part2++;
- }
- }
-
- record Range(int A, int B)
- {
- public bool Contains(Range other)
- {
- return (A <= other.A && B >= other.B);
- }
-
- public bool OverlapsWith(Range other)
- {
- 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);
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day4;
+
+[ProblemInfo(2022, 4, "Camp Cleanup")]
+internal class CampCleanup : Problem
+{
+ private List<(Range a, Range b)> _pairs = new(500);
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ foreach (var line in lines)
+ {
+ var (a, b) = line.Split(',')
+ .Select(range =>
+ range.Split('-')
+ .Select(v => int.Parse(v))
+ .Chunk(2)
+ .Select(r => new Range(r.First(), r.Last()))
+ .First()
+ ).Chunk(2)
+ .Select(pair => (pair.First(), pair.Last()))
+ .First();
+ _pairs.Add((a, b));
+ }
+ }
+
+ public override void CalculatePart1()
+ {
+ var total = 0;
+ foreach (var (a, b) in _pairs)
+ {
+ if (a.Contains(b) || b.Contains(a))
+ total++;
+ }
+ Part1 = total;
+ }
+
+ public override void CalculatePart2()
+ {
+ foreach (var (a, b) in _pairs)
+ {
+ if (a.OverlapsWith(b))
+ Part2++;
+ }
+ }
+
+ record Range(int A, int B)
+ {
+ public bool Contains(Range other)
+ {
+ return (A <= other.A && B >= other.B);
+ }
+
+ public bool OverlapsWith(Range other)
+ {
+ 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);
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day5/SupplyStacks.cs b/AdventOfCode/Problems/AOC2022/Day5/SupplyStacks.cs
index f09d45f..66885c2 100644
--- a/AdventOfCode/Problems/AOC2022/Day5/SupplyStacks.cs
+++ b/AdventOfCode/Problems/AOC2022/Day5/SupplyStacks.cs
@@ -1,131 +1,131 @@
-using AdventOfCode.Runner.Attributes;
-
-using Superpower;
-using Superpower.Parsers;
-
-using System.Text.RegularExpressions;
-
-namespace AdventOfCode.Problems.AOC2022.Day5;
-
-[ProblemInfo(2022, 5, "Supply Stacks")]
-internal partial class SupplyStacks : Problem
-{
- private List[] _stacksPart1 = Array.Empty>();
- private List[] _stacksPart2 = Array.Empty>();
-
- private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
- from stack in Character.Digit.Many()
- from frm in Character.Letter.Or(Character.WhiteSpace).Many()
- from source in Character.Digit.Many()
- from to in Character.Letter.Or(Character.WhiteSpace).Many()
- from dst in Character.Digit.Many()
- select (int.Parse(stack), int.Parse(source), int.Parse(dst));
-
- private List<(int stack, int from, int to)> _moves = new();
-
- public override void CalculatePart1()
- {
- foreach (var move in _moves)
- {
- PerformBasicMove(_stacksPart1, move);
- }
- Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
- }
-
- private static void PerformBasicMove(List[] data, (int stack, int from, int to) move)
- {
- var from = data[move.from - 1];
- var to = data[move.to - 1];
- for (int i = 0; i < move.stack; i++)
- {
- var item = from[^1];
- from.RemoveAt(from.Count - 1);
- to.Add(item);
- }
- }
-
- private static void PerformMove(List[] data, (int stack, int from, int to) move)
- {
- var from = data[move.from - 1];
- var to = data[move.to - 1];
- var items = from.Skip(from.Count - move.stack);
- to.AddRange(items);
- from.RemoveRange(from.Count - move.stack, move.stack);
- }
-
- public override void CalculatePart2()
- {
- foreach (var move in _moves)
- {
- PerformMove(_stacksPart2, move);
- }
- Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- var readMoves = false;
-
- var buffers = new List>();
- var moves = new List<(int stack, int from, int to)>();
- foreach (var line in lines)
- {
- if (string.IsNullOrWhiteSpace(line))
- {
- readMoves = true;
- continue;
- }
-
- if (readMoves)
- {
- moves.Add(ParseMoveLineRegex(line));
- }
- else
- {
- var crates = ParseCrateLine(line);
- for (int i = 0; i < crates.Count; i++)
- {
- var crate = crates[i];
- if (buffers.Count == i)
- buffers.Add(crate == ' ' ? new() : new List() { crate });
- else if (crate != ' ')
- buffers[i].Add(crate);
- }
- }
- }
- _stacksPart1 = 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;
- }
-
- //Way slower
- private (int stack, int from, int to) ParseMoveLine(string line)
- {
- return _moveParser.Parse(line);
- }
-
- private static (int stack, int from, int to) ParseMoveLineRegex(string line)
- {
- var r = MoveParser().Matches(line);
- var items = r.First()
- .Groups.Values.Skip(1)
- .Select(v => int.Parse(v.ValueSpan))
- .ToArray();
- return (items[0], items[1], items[2]);
- }
-
- private static List ParseCrateLine(string line)
- {
- var result = new List(line.Length / 4);
- for (int i = 1; i < line.Length; i += 4)
- {
- var c = line[i];
- result.Add(c);
- }
- return result;
- }
-
- [GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
- private static partial Regex MoveParser();
+using AdventOfCode.Runner.Attributes;
+
+using Superpower;
+using Superpower.Parsers;
+
+using System.Text.RegularExpressions;
+
+namespace AdventOfCode.Problems.AOC2022.Day5;
+
+[ProblemInfo(2022, 5, "Supply Stacks")]
+internal partial class SupplyStacks : Problem
+{
+ private List[] _stacksPart1 = Array.Empty>();
+ private List[] _stacksPart2 = Array.Empty>();
+
+ private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
+ from stack in Character.Digit.Many()
+ from frm in Character.Letter.Or(Character.WhiteSpace).Many()
+ from source in Character.Digit.Many()
+ from to in Character.Letter.Or(Character.WhiteSpace).Many()
+ from dst in Character.Digit.Many()
+ select (int.Parse(stack), int.Parse(source), int.Parse(dst));
+
+ private List<(int stack, int from, int to)> _moves = new();
+
+ public override void CalculatePart1()
+ {
+ foreach (var move in _moves)
+ {
+ PerformBasicMove(_stacksPart1, move);
+ }
+ Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
+ }
+
+ private static void PerformBasicMove(List[] data, (int stack, int from, int to) move)
+ {
+ var from = data[move.from - 1];
+ var to = data[move.to - 1];
+ for (int i = 0; i < move.stack; i++)
+ {
+ var item = from[^1];
+ from.RemoveAt(from.Count - 1);
+ to.Add(item);
+ }
+ }
+
+ private static void PerformMove(List[] data, (int stack, int from, int to) move)
+ {
+ var from = data[move.from - 1];
+ var to = data[move.to - 1];
+ var items = from.Skip(from.Count - move.stack);
+ to.AddRange(items);
+ from.RemoveRange(from.Count - move.stack, move.stack);
+ }
+
+ public override void CalculatePart2()
+ {
+ foreach (var move in _moves)
+ {
+ PerformMove(_stacksPart2, move);
+ }
+ Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ var readMoves = false;
+
+ var buffers = new List>();
+ var moves = new List<(int stack, int from, int to)>();
+ foreach (var line in lines)
+ {
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ readMoves = true;
+ continue;
+ }
+
+ if (readMoves)
+ {
+ moves.Add(ParseMoveLineRegex(line));
+ }
+ else
+ {
+ var crates = ParseCrateLine(line);
+ for (int i = 0; i < crates.Count; i++)
+ {
+ var crate = crates[i];
+ if (buffers.Count == i)
+ buffers.Add(crate == ' ' ? new() : new List() { crate });
+ else if (crate != ' ')
+ buffers[i].Add(crate);
+ }
+ }
+ }
+ _stacksPart1 = 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;
+ }
+
+ //Way slower
+ private (int stack, int from, int to) ParseMoveLine(string line)
+ {
+ return _moveParser.Parse(line);
+ }
+
+ private static (int stack, int from, int to) ParseMoveLineRegex(string line)
+ {
+ var r = MoveParser().Matches(line);
+ var items = r.First()
+ .Groups.Values.Skip(1)
+ .Select(v => int.Parse(v.ValueSpan))
+ .ToArray();
+ return (items[0], items[1], items[2]);
+ }
+
+ private static List ParseCrateLine(string line)
+ {
+ var result = new List(line.Length / 4);
+ for (int i = 1; i < line.Length; i += 4)
+ {
+ var c = line[i];
+ result.Add(c);
+ }
+ return result;
+ }
+
+ [GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
+ private static partial Regex MoveParser();
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day6/TuningTrouble.cs b/AdventOfCode/Problems/AOC2022/Day6/TuningTrouble.cs
index ab1be03..343a7dc 100644
--- a/AdventOfCode/Problems/AOC2022/Day6/TuningTrouble.cs
+++ b/AdventOfCode/Problems/AOC2022/Day6/TuningTrouble.cs
@@ -1,35 +1,35 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day6;
-
-[ProblemInfo(2022, 6, "Tuning Trouble")]
-internal class TuningTrouble : Problem
-{
- private string _input = string.Empty;
-
- public override void CalculatePart1()
- {
- Part1 = FindMarker(4);
- }
-
- private int FindMarker(int size = 4)
- {
- for (int i = size; i < _input.Length; i++)
- {
- var group = _input[(i - size)..i];
- if (group.All(c => group.Count(gc => gc == c) == 1))
- return i;
- }
- return -1;
- }
-
- public override void CalculatePart2()
- {
- Part2 = FindMarker(14);
- }
-
- public override void LoadInput()
- {
- _input = ReadInputText();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day6;
+
+[ProblemInfo(2022, 6, "Tuning Trouble")]
+internal class TuningTrouble : Problem
+{
+ private string _input = string.Empty;
+
+ public override void CalculatePart1()
+ {
+ Part1 = FindMarker(4);
+ }
+
+ private int FindMarker(int size = 4)
+ {
+ for (int i = size; i < _input.Length; i++)
+ {
+ var group = _input[(i - size)..i];
+ if (group.All(c => group.Count(gc => gc == c) == 1))
+ return i;
+ }
+ return -1;
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = FindMarker(14);
+ }
+
+ public override void LoadInput()
+ {
+ _input = ReadInputText();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day7/DirectoryNode.cs b/AdventOfCode/Problems/AOC2022/Day7/DirectoryNode.cs
index cf2586c..dce8d50 100644
--- a/AdventOfCode/Problems/AOC2022/Day7/DirectoryNode.cs
+++ b/AdventOfCode/Problems/AOC2022/Day7/DirectoryNode.cs
@@ -1,121 +1,121 @@
-namespace AdventOfCode.Problems.AOC2022.Day7;
-
-internal class DirectoryNode
-{
- public DirectoryNode Parent { get; set; }
- public string Name { get; set; }
- public string FullPath => GetFullPath();
- public List Children { 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 LocalSize => Files.Sum(f => f.size);
-
- public DirectoryNode(string name)
- {
- Name = name;
- Files = new();
- Children = new();
- Parent = this;
- }
-
- public DirectoryNode(string name, DirectoryNode parent)
- {
- Name = name;
- Files = new();
- Children = new();
- Parent = parent;
- }
-
- public DirectoryNode(string name, List<(string name, int size)> files)
- {
- Name = name;
- Files = files;
- Children = new();
- Parent = this;
- }
-
- public DirectoryNode AddDirectory(string path)
- {
- if (path == "/")
- return this;
- if (string.IsNullOrWhiteSpace(path))
- return this;
- var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
- if (segments.Length == 0)
- throw new Exception("Invalid Path?");
- return AddDirectory(segments);
- }
-
- private DirectoryNode AddDirectory(string[] segments)
- {
- var curSegment = segments[0];
- var child = Children.FirstOrDefault(c => c.Name == curSegment);
- if (child == null)
- {
- var node = new DirectoryNode(curSegment, this);
- Children.Add(node);
- if (segments.Length == 1)
- return node;
- else
- return node.AddDirectory(segments[1..]);
- }
- else
- {
- if (segments.Length == 1)
- return child;
- return child.AddDirectory(segments[1..]);
- }
- }
-
- public void AddFile(string name, int size)
- {
- Files.Add((name, size));
- }
-
- public DirectoryNode? GetDirectory(string path)
- {
- if (path == "/")
- return this;
- var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
- if (segments.Length == 0)
- throw new Exception("Invalid Path?");
- return GetDirectory(segments);
- }
-
- private DirectoryNode? GetDirectory(string[] segments)
- {
- if (Children.Count == 0)
- return null;
-
- var child = Children.FirstOrDefault(c => c.Name == segments[0]);
-
- if (child == null)
- return null;
- else
- if (segments.Length == 1)
- return child;
- else
- return child.GetDirectory(segments[1..]);
- }
-
- public List Where(Func filter)
- {
- var result = new List();
- if (filter(this))
- result.Add(this);
- result.AddRange(Children.SelectMany(c => c.Where(filter)));
- return result;
- }
-
- public string GetFullPath()
- {
- if (Parent == this)
- return "";
- return $"{Parent.GetFullPath()}/{Name}";
- }
-
- public override string ToString()
- {
- return $"{Name} - {Children.Count}";
- }
+namespace AdventOfCode.Problems.AOC2022.Day7;
+
+internal class DirectoryNode
+{
+ public DirectoryNode Parent { get; set; }
+ public string Name { get; set; }
+ public string FullPath => GetFullPath();
+ public List Children { 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 LocalSize => Files.Sum(f => f.size);
+
+ public DirectoryNode(string name)
+ {
+ Name = name;
+ Files = new();
+ Children = new();
+ Parent = this;
+ }
+
+ public DirectoryNode(string name, DirectoryNode parent)
+ {
+ Name = name;
+ Files = new();
+ Children = new();
+ Parent = parent;
+ }
+
+ public DirectoryNode(string name, List<(string name, int size)> files)
+ {
+ Name = name;
+ Files = files;
+ Children = new();
+ Parent = this;
+ }
+
+ public DirectoryNode AddDirectory(string path)
+ {
+ if (path == "/")
+ return this;
+ if (string.IsNullOrWhiteSpace(path))
+ return this;
+ var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
+ if (segments.Length == 0)
+ throw new Exception("Invalid Path?");
+ return AddDirectory(segments);
+ }
+
+ private DirectoryNode AddDirectory(string[] segments)
+ {
+ var curSegment = segments[0];
+ var child = Children.FirstOrDefault(c => c.Name == curSegment);
+ if (child == null)
+ {
+ var node = new DirectoryNode(curSegment, this);
+ Children.Add(node);
+ if (segments.Length == 1)
+ return node;
+ else
+ return node.AddDirectory(segments[1..]);
+ }
+ else
+ {
+ if (segments.Length == 1)
+ return child;
+ return child.AddDirectory(segments[1..]);
+ }
+ }
+
+ public void AddFile(string name, int size)
+ {
+ Files.Add((name, size));
+ }
+
+ public DirectoryNode? GetDirectory(string path)
+ {
+ if (path == "/")
+ return this;
+ var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
+ if (segments.Length == 0)
+ throw new Exception("Invalid Path?");
+ return GetDirectory(segments);
+ }
+
+ private DirectoryNode? GetDirectory(string[] segments)
+ {
+ if (Children.Count == 0)
+ return null;
+
+ var child = Children.FirstOrDefault(c => c.Name == segments[0]);
+
+ if (child == null)
+ return null;
+ else
+ if (segments.Length == 1)
+ return child;
+ else
+ return child.GetDirectory(segments[1..]);
+ }
+
+ public List Where(Func filter)
+ {
+ var result = new List();
+ if (filter(this))
+ result.Add(this);
+ result.AddRange(Children.SelectMany(c => c.Where(filter)));
+ return result;
+ }
+
+ public string GetFullPath()
+ {
+ if (Parent == this)
+ return "";
+ return $"{Parent.GetFullPath()}/{Name}";
+ }
+
+ public override string ToString()
+ {
+ return $"{Name} - {Children.Count}";
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day7/NoSpace.cs b/AdventOfCode/Problems/AOC2022/Day7/NoSpace.cs
index 08a217d..3c8f3fc 100644
--- a/AdventOfCode/Problems/AOC2022/Day7/NoSpace.cs
+++ b/AdventOfCode/Problems/AOC2022/Day7/NoSpace.cs
@@ -1,75 +1,75 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day7;
-
-[ProblemInfo(2022, 7, "No Space Left On Device")]
-internal class NoSpace : Problem
-{
- private DirectoryNode _dirTree = new DirectoryNode("/");
-
- public override void CalculatePart1()
- {
- var dirs = _dirTree.Where(d => d.Size <= 100000);
- Part1 = dirs.Sum(d => d.Size);
- }
-
- public override void CalculatePart2()
- {
- var neededPace = 30000000;
- var totalSize = 70000000;
- var unusedSpace = totalSize - _dirTree.Size;
- var targetSize = neededPace - unusedSpace;
- var bigEnough = _dirTree.Where(d => d.Size >= targetSize);
- Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0;
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
-
- var curDir = new Stack();
-
- var dir = "/";
- foreach (var line in lines)
- {
- if (line[0] == '$')
- {
- ParseCommand(line[2..], ref curDir);
- dir = $"/{string.Join("/", curDir.Reverse())}";
- _dirTree.AddDirectory(dir);
- }
- else
- ReadDirectory(line, _dirTree.GetDirectory(dir)!);
- }
- }
-
- private static void ReadDirectory(string line, DirectoryNode curDir)
- {
- if (line.StartsWith("dir"))
- return;
-
- var split = line.Split(' ');
- var name = split[1];
- var size = int.Parse(split[0]);
- curDir.AddFile(name, size);
- }
-
- private static void ParseCommand(string command, ref Stack curDir)
- {
- var split = command.Split(' ');
- var keyword = split.First();
- var param = split.Last();
-
- switch (keyword)
- {
- case "cd":
- if (param == "..")
- curDir.Pop();
- else if (param == "/")
- curDir.Clear();
- else
- curDir.Push(param);
- break;
- }
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day7;
+
+[ProblemInfo(2022, 7, "No Space Left On Device")]
+internal class NoSpace : Problem
+{
+ private DirectoryNode _dirTree = new DirectoryNode("/");
+
+ public override void CalculatePart1()
+ {
+ var dirs = _dirTree.Where(d => d.Size <= 100000);
+ Part1 = dirs.Sum(d => d.Size);
+ }
+
+ public override void CalculatePart2()
+ {
+ var neededPace = 30000000;
+ var totalSize = 70000000;
+ var unusedSpace = totalSize - _dirTree.Size;
+ var targetSize = neededPace - unusedSpace;
+ var bigEnough = _dirTree.Where(d => d.Size >= targetSize);
+ Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0;
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+
+ var curDir = new Stack();
+
+ var dir = "/";
+ foreach (var line in lines)
+ {
+ if (line[0] == '$')
+ {
+ ParseCommand(line[2..], ref curDir);
+ dir = $"/{string.Join("/", curDir.Reverse())}";
+ _dirTree.AddDirectory(dir);
+ }
+ else
+ ReadDirectory(line, _dirTree.GetDirectory(dir)!);
+ }
+ }
+
+ private static void ReadDirectory(string line, DirectoryNode curDir)
+ {
+ if (line.StartsWith("dir"))
+ return;
+
+ var split = line.Split(' ');
+ var name = split[1];
+ var size = int.Parse(split[0]);
+ curDir.AddFile(name, size);
+ }
+
+ private static void ParseCommand(string command, ref Stack curDir)
+ {
+ var split = command.Split(' ');
+ var keyword = split.First();
+ var param = split.Last();
+
+ switch (keyword)
+ {
+ case "cd":
+ if (param == "..")
+ curDir.Pop();
+ else if (param == "/")
+ curDir.Clear();
+ else
+ curDir.Push(param);
+ break;
+ }
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day8/TreetopTreeHouse.cs b/AdventOfCode/Problems/AOC2022/Day8/TreetopTreeHouse.cs
index 6ece543..de4f287 100644
--- a/AdventOfCode/Problems/AOC2022/Day8/TreetopTreeHouse.cs
+++ b/AdventOfCode/Problems/AOC2022/Day8/TreetopTreeHouse.cs
@@ -1,99 +1,99 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day8;
-
-[ProblemInfo(2022, 8, "Treetop Tree House")]
-internal class TreetopTreeHouse : Problem
-{
- private int[][] _input = Array.Empty();
- private int _height;
- private int _width;
-
- public override void CalculatePart1()
- {
- for (int y = 1; y < _height - 1; y++)
- {
- for (int x = 1; x < _width - 1; x++)
- {
- Part1 += IsVisible(x, y) ? 1 : 0;
- }
- }
- Part1 += _height * 2 + _width * 2 - 4;
- }
-
- private bool IsVisible(int x, int y)
- {
- return IsVisibleColumn(x, y) || IsVisibleRow(x, y);
- }
-
- private bool IsVisibleColumn(int col, int row)
- {
- var tree = _input[row][col];
-
- var columnOfTrees = _input.Select(r => r[col]);
-
- var above = columnOfTrees.Take(row);
- var below = columnOfTrees.Skip(row + 1);
-
- return above.All(t => t < tree) || below.All(t => t < tree);
- }
-
- private bool IsVisibleRow(int col, int row)
- {
- var tree = _input[row][col];
-
- var rowOfTrees = _input[row];
-
- var left = rowOfTrees.Take(col);
- var right = rowOfTrees.Skip(col + 1);
-
- return left.All(t => t < tree) || right.All(t => t < tree);
- }
-
- public override void CalculatePart2()
- {
- Part2 = int.MinValue;
- for (int y = 1; y < _height - 1; y++)
- {
- for (int x = 1; x < _width - 1; x++)
- {
- var v = GetScenicScore(x, y);
- if (Part2 < v)
- Part2 = v;
- }
- }
- }
-
- public int GetScenicScore(int row, int col)
- {
- var tree = _input[row][col];
-
- var columnOfTrees = _input.Select(r => r[col]);
- var rowOfTrees = _input[row];
-
- var above = columnOfTrees.Take(row).Reverse();
- var below = columnOfTrees.Skip(row + 1);
- var left = rowOfTrees.Take(col).Reverse();
- var right = rowOfTrees.Skip(col + 1);
-
- var score = above.Select((t, idx) => (t, idx))
- .FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1;
- score *= below.Select((t, idx) => (t, idx))
- .FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1;
-
- score *= left.Select((t, idx) => (t, idx))
- .FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1;
- score *= right.Select((t, idx) => (t, idx))
- .FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1;
-
- return score;
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- _input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray();
- _height = _input.Length;
- _width = _input[0].Length;
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day8;
+
+[ProblemInfo(2022, 8, "Treetop Tree House")]
+internal class TreetopTreeHouse : Problem
+{
+ private int[][] _input = Array.Empty();
+ private int _height;
+ private int _width;
+
+ public override void CalculatePart1()
+ {
+ for (int y = 1; y < _height - 1; y++)
+ {
+ for (int x = 1; x < _width - 1; x++)
+ {
+ Part1 += IsVisible(x, y) ? 1 : 0;
+ }
+ }
+ Part1 += _height * 2 + _width * 2 - 4;
+ }
+
+ private bool IsVisible(int x, int y)
+ {
+ return IsVisibleColumn(x, y) || IsVisibleRow(x, y);
+ }
+
+ private bool IsVisibleColumn(int col, int row)
+ {
+ var tree = _input[row][col];
+
+ var columnOfTrees = _input.Select(r => r[col]);
+
+ var above = columnOfTrees.Take(row);
+ var below = columnOfTrees.Skip(row + 1);
+
+ return above.All(t => t < tree) || below.All(t => t < tree);
+ }
+
+ private bool IsVisibleRow(int col, int row)
+ {
+ var tree = _input[row][col];
+
+ var rowOfTrees = _input[row];
+
+ var left = rowOfTrees.Take(col);
+ var right = rowOfTrees.Skip(col + 1);
+
+ return left.All(t => t < tree) || right.All(t => t < tree);
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = int.MinValue;
+ for (int y = 1; y < _height - 1; y++)
+ {
+ for (int x = 1; x < _width - 1; x++)
+ {
+ var v = GetScenicScore(x, y);
+ if (Part2 < v)
+ Part2 = v;
+ }
+ }
+ }
+
+ public int GetScenicScore(int row, int col)
+ {
+ var tree = _input[row][col];
+
+ var columnOfTrees = _input.Select(r => r[col]);
+ var rowOfTrees = _input[row];
+
+ var above = columnOfTrees.Take(row).Reverse();
+ var below = columnOfTrees.Skip(row + 1);
+ var left = rowOfTrees.Take(col).Reverse();
+ var right = rowOfTrees.Skip(col + 1);
+
+ var score = above.Select((t, idx) => (t, idx))
+ .FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1;
+ score *= below.Select((t, idx) => (t, idx))
+ .FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1;
+
+ score *= left.Select((t, idx) => (t, idx))
+ .FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1;
+ score *= right.Select((t, idx) => (t, idx))
+ .FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1;
+
+ return score;
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ _input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray();
+ _height = _input.Length;
+ _width = _input[0].Length;
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day9/RopeBridge.cs b/AdventOfCode/Problems/AOC2022/Day9/RopeBridge.cs
index 8984c43..1d54327 100644
--- a/AdventOfCode/Problems/AOC2022/Day9/RopeBridge.cs
+++ b/AdventOfCode/Problems/AOC2022/Day9/RopeBridge.cs
@@ -1,31 +1,31 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2022.Day9;
-
-[ProblemInfo(2022, 9, "Rope Bridge")]
-internal class RopeBridge : Problem
-{
- private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>();
-
- public override void CalculatePart1()
- {
- var sim = new RopeSimulator(_moves);
- sim.Simulate();
- Part1 = sim.Visited;
- }
-
- public override void CalculatePart2()
- {
- var sim = new RopeSimulator(_moves, 9);
- sim.Simulate();
- Part2 = sim.Visited;
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- _moves = lines.Select(ln => ln.Split(' '))
- .Select(move => (Enum.Parse(move.First()), int.Parse(move.Last())))
- .ToArray();
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2022.Day9;
+
+[ProblemInfo(2022, 9, "Rope Bridge")]
+internal class RopeBridge : Problem
+{
+ private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>();
+
+ public override void CalculatePart1()
+ {
+ var sim = new RopeSimulator(_moves);
+ sim.Simulate();
+ Part1 = sim.Visited;
+ }
+
+ public override void CalculatePart2()
+ {
+ var sim = new RopeSimulator(_moves, 9);
+ sim.Simulate();
+ Part2 = sim.Visited;
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ _moves = lines.Select(ln => ln.Split(' '))
+ .Select(move => (Enum.Parse(move.First()), int.Parse(move.Last())))
+ .ToArray();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2022/Day9/RopeSimulator.cs b/AdventOfCode/Problems/AOC2022/Day9/RopeSimulator.cs
index 5f6efdc..cc930a7 100644
--- a/AdventOfCode/Problems/AOC2022/Day9/RopeSimulator.cs
+++ b/AdventOfCode/Problems/AOC2022/Day9/RopeSimulator.cs
@@ -1,146 +1,146 @@
-namespace AdventOfCode.Problems.AOC2022.Day9;
-
-public class RopeSimulator
-{
- public int Visited => _visited.Count;
-
- private readonly (Direction dir, int ammount)[] _movement;
- private readonly bool _render;
-
- public enum Direction
- {
- L,
- R,
- U,
- D
- }
-
- private (int x, int y) _head;
- private (int x, int y)[] _segments;
- private Dictionary<(int x, int y), int> _visited;
-
- public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false)
- {
- _movement = movement;
- _render = render;
- _visited = new Dictionary<(int x, int y), int>()
- {
- { (0,0), 1 }
- };
- _head = (0, 0);
- _segments = Enumerable.Repeat((0, 0), segments).ToArray();
- }
-
- public void Simulate()
- {
- foreach (var (dir, ammount) in _movement)
- {
- ProcessStep(dir, ammount);
- }
- }
-
- private void ProcessStep(Direction dir, int ammount)
- {
- for (int i = 0; i < ammount; i++)
- {
- switch (dir)
- {
- case Direction.L:
- _head.x--;
- break;
-
- case Direction.R:
- _head.x++;
- break;
-
- case Direction.U:
- _head.y++;
- break;
-
- case Direction.D:
- _head.y--;
- break;
- }
- FollowHead();
- var tail = _segments.Last();
- if (_visited.ContainsKey(tail))
- _visited[tail]++;
- else
- _visited.Add(tail, 1);
- }
- }
-
- private void FollowHead()
- {
- var curHead = _head;
- for (int i = 0; i < _segments.Length; i++)
- {
- var tail = _segments[i];
- curHead = _segments[i] = FollowSegment(curHead, tail);
- }
- if (_render)
- {
- DrawScene();
- Console.ReadKey();
- }
- }
-
- private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail)
- {
- var xDist = head.x - tail.x;
- var yDist = head.y - tail.y;
-
- if (xDist * xDist + yDist * yDist < 4)
- return tail;
-
- if (xDist > 1)
- head.x -= 1;
- if (xDist < -1)
- head.x += 1;
-
- if (yDist > 1)
- head.y -= 1;
- if (yDist < -1)
- head.y += 1;
-
- return head;
- }
-
- private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail)
- {
- var xDist = Math.Abs(head.x - tail.x);
- var yDist = Math.Abs(head.y - tail.y);
- return (xDist > 1 || yDist > 1);
- }
-
- private void DrawScene(int segment = -1)
- {
- 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 lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y);
- var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y);
-
- var width = upperX - lowerX;
- var height = upperY - lowerY;
-
- Console.Clear();
- Console.ForegroundColor = ConsoleColor.Gray;
- Draw('s', (0, 0), lowerX, upperY);
- Draw('H', _head, lowerX, upperY);
-
- for (int i = _segments.Length - 1; i >= 0; i--)
- {
- if (segment == i)
- Console.ForegroundColor = ConsoleColor.Red;
- else
- Console.ForegroundColor = ConsoleColor.Gray;
- Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY);
- }
- }
-
- private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY)
- {
- Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY);
- Console.WriteLine(c);
- }
+namespace AdventOfCode.Problems.AOC2022.Day9;
+
+public class RopeSimulator
+{
+ public int Visited => _visited.Count;
+
+ private readonly (Direction dir, int ammount)[] _movement;
+ private readonly bool _render;
+
+ public enum Direction
+ {
+ L,
+ R,
+ U,
+ D
+ }
+
+ private (int x, int y) _head;
+ private (int x, int y)[] _segments;
+ private Dictionary<(int x, int y), int> _visited;
+
+ public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false)
+ {
+ _movement = movement;
+ _render = render;
+ _visited = new Dictionary<(int x, int y), int>()
+ {
+ { (0,0), 1 }
+ };
+ _head = (0, 0);
+ _segments = Enumerable.Repeat((0, 0), segments).ToArray();
+ }
+
+ public void Simulate()
+ {
+ foreach (var (dir, ammount) in _movement)
+ {
+ ProcessStep(dir, ammount);
+ }
+ }
+
+ private void ProcessStep(Direction dir, int ammount)
+ {
+ for (int i = 0; i < ammount; i++)
+ {
+ switch (dir)
+ {
+ case Direction.L:
+ _head.x--;
+ break;
+
+ case Direction.R:
+ _head.x++;
+ break;
+
+ case Direction.U:
+ _head.y++;
+ break;
+
+ case Direction.D:
+ _head.y--;
+ break;
+ }
+ FollowHead();
+ var tail = _segments.Last();
+ if (_visited.ContainsKey(tail))
+ _visited[tail]++;
+ else
+ _visited.Add(tail, 1);
+ }
+ }
+
+ private void FollowHead()
+ {
+ var curHead = _head;
+ for (int i = 0; i < _segments.Length; i++)
+ {
+ var tail = _segments[i];
+ curHead = _segments[i] = FollowSegment(curHead, tail);
+ }
+ if (_render)
+ {
+ DrawScene();
+ Console.ReadKey();
+ }
+ }
+
+ private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail)
+ {
+ var xDist = head.x - tail.x;
+ var yDist = head.y - tail.y;
+
+ if (xDist * xDist + yDist * yDist < 4)
+ return tail;
+
+ if (xDist > 1)
+ head.x -= 1;
+ if (xDist < -1)
+ head.x += 1;
+
+ if (yDist > 1)
+ head.y -= 1;
+ if (yDist < -1)
+ head.y += 1;
+
+ return head;
+ }
+
+ private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail)
+ {
+ var xDist = Math.Abs(head.x - tail.x);
+ var yDist = Math.Abs(head.y - tail.y);
+ return (xDist > 1 || yDist > 1);
+ }
+
+ private void DrawScene(int segment = -1)
+ {
+ 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 lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y);
+ var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y);
+
+ var width = upperX - lowerX;
+ var height = upperY - lowerY;
+
+ Console.Clear();
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Draw('s', (0, 0), lowerX, upperY);
+ Draw('H', _head, lowerX, upperY);
+
+ for (int i = _segments.Length - 1; i >= 0; i--)
+ {
+ if (segment == i)
+ Console.ForegroundColor = ConsoleColor.Red;
+ else
+ Console.ForegroundColor = ConsoleColor.Gray;
+ Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY);
+ }
+ }
+
+ private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY)
+ {
+ Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY);
+ Console.WriteLine(c);
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day1/Trebuchet.cs b/AdventOfCode/Problems/AOC2023/Day1/Trebuchet.cs
index 5a0dc59..ca2fc27 100644
--- a/AdventOfCode/Problems/AOC2023/Day1/Trebuchet.cs
+++ b/AdventOfCode/Problems/AOC2023/Day1/Trebuchet.cs
@@ -1,97 +1,97 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2023.Day1;
-
-[ProblemInfo(2023, 1, "Trebuchet!?")]
-public partial class Trebuchet : Problem
-{
- private string[] _inputData = [];
-
- public override void LoadInput()
- {
- _inputData = ReadInputLines();
- }
-
- public override void CalculatePart1()
- {
- Part1 = _inputData.Select(GetCalibrationValues)
- .Select(cv => cv.left * 10 + cv.right)
- .Sum();
- }
-
- private (int left, int right) GetCalibrationValues(string line)
- {
- var (left, right) = (0, 0);
- for (int i = 0; i < line.Length; i++)
- {
- if (line[i] - '0' >= 10)
- continue;
-
- left = line[i] - '0';
- break;
- }
- for (int i = line.Length - 1; i >= 0; i--)
- {
- if (line[i] - '0' >= 10)
- continue;
- right = line[i] - '0';
- break;
- }
- return (left, right);
- }
-
- private readonly (string word, int value)[] _numberWords = new[]
- {
- ("one", 1),
- ("two", 2),
- ("three", 3),
- ("four", 4),
- ("five", 5),
- ("six", 6),
- ("seven", 7),
- ("eight", 8),
- ("nine", 9)
- };
-
- public override void CalculatePart2()
- {
- Part2 = _inputData.Select(GetNamedCalibrationValues)
- .Select(cv => cv.left * 10 + cv.right)
- .Sum();
- }
-
- private (int left, int right) GetNamedCalibrationValues(string line)
- {
- var (left, right) = (0, 0);
- for (int i = 0; i < line.Length; i++)
- {
- var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
- if (word != -1)
- {
- left = word;
- break;
- }
- else if (line[i] - '0' >= 10)
- continue;
-
- left = line[i] - '0';
- break;
- }
-
- 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;
- if (word != -1)
- {
- right = word;
- break;
- }
- else if (line[i] - '0' >= 10)
- continue;
-
- right = line[i] - '0';
- break;
- }
- return (left, right);
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2023.Day1;
+
+[ProblemInfo(2023, 1, "Trebuchet!?")]
+public partial class Trebuchet : Problem
+{
+ private string[] _inputData = [];
+
+ public override void LoadInput()
+ {
+ _inputData = ReadInputLines();
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = _inputData.Select(GetCalibrationValues)
+ .Select(cv => cv.left * 10 + cv.right)
+ .Sum();
+ }
+
+ private (int left, int right) GetCalibrationValues(string line)
+ {
+ var (left, right) = (0, 0);
+ for (int i = 0; i < line.Length; i++)
+ {
+ if (line[i] - '0' >= 10)
+ continue;
+
+ left = line[i] - '0';
+ break;
+ }
+ for (int i = line.Length - 1; i >= 0; i--)
+ {
+ if (line[i] - '0' >= 10)
+ continue;
+ right = line[i] - '0';
+ break;
+ }
+ return (left, right);
+ }
+
+ private readonly (string word, int value)[] _numberWords = new[]
+ {
+ ("one", 1),
+ ("two", 2),
+ ("three", 3),
+ ("four", 4),
+ ("five", 5),
+ ("six", 6),
+ ("seven", 7),
+ ("eight", 8),
+ ("nine", 9)
+ };
+
+ public override void CalculatePart2()
+ {
+ Part2 = _inputData.Select(GetNamedCalibrationValues)
+ .Select(cv => cv.left * 10 + cv.right)
+ .Sum();
+ }
+
+ private (int left, int right) GetNamedCalibrationValues(string line)
+ {
+ var (left, right) = (0, 0);
+ for (int i = 0; i < line.Length; i++)
+ {
+ var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
+ if (word != -1)
+ {
+ left = word;
+ break;
+ }
+ else if (line[i] - '0' >= 10)
+ continue;
+
+ left = line[i] - '0';
+ break;
+ }
+
+ 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;
+ if (word != -1)
+ {
+ right = word;
+ break;
+ }
+ else if (line[i] - '0' >= 10)
+ continue;
+
+ right = line[i] - '0';
+ break;
+ }
+ return (left, right);
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day10/PipeMaze.cs b/AdventOfCode/Problems/AOC2023/Day10/PipeMaze.cs
index ae70244..5d63d80 100644
--- a/AdventOfCode/Problems/AOC2023/Day10/PipeMaze.cs
+++ b/AdventOfCode/Problems/AOC2023/Day10/PipeMaze.cs
@@ -1,106 +1,106 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day10;
-
-[ProblemInfo(2023, 10, "Pipe Maze")]
-internal class PipeMaze : Problem
-{
- private string[] _maze = [];
-
- public override void LoadInput()
- {
- _maze = ReadInputLines();
- }
-
- public override void CalculatePart1()
- {
- var start = GetStartPointPos();
- var nPoints = GetStartConnections(start);
- var seen = new Dictionary<(int, int), int>();
-
- foreach (var point in nPoints)
- {
- var curPoint = start;
- var prevPoint = point;
- var dist = 0;
- while (true)
- {
- dist++;
- var next = GetNextPoint(curPoint, prevPoint);
- prevPoint = curPoint;
- curPoint = next;
- if (next == start)
- break;
- if (seen.TryGetValue(next, out var d))
- {
- if (d > dist)
- seen[next] = dist;
- else
- break;
- }
- else
- seen.Add(next, dist);
- }
- }
-
- Part1 = seen.Values.Max();
- }
-
- private (int x, int y) GetStartPointPos()
- {
- for (int y = 0; y < _maze.Length; y++)
- {
- var x = _maze[y].IndexOf('S');
- if (x >= 0)
- return (x, y);
- }
- throw new Exception("Start point not found");
- }
-
- private List<(int x, int y)> GetStartConnections((int x, int y) pos)
- {
- var points = new List<(int x, int y)>();
- if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L')
- points.Add((pos.x + 1, pos.y));
- if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7')
- points.Add((pos.x - 1, pos.y));
-
- if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7')
- points.Add((pos.x, pos.y + 1));
- if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L')
- points.Add((pos.x, pos.y - 1));
-
- return points;
- }
-
- private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev)
- {
- var curPipe = _maze[pos.y][pos.x];
- (int x, int y) = (pos.x - prev.x, pos.y - prev.y);
-
- if (curPipe == 'S')
- return GetStartConnections(pos).First(p => p != prev);
-
- return curPipe switch
- {
- '|' => (pos.x, pos.y + y),
- '-' => (pos.x + x, pos.y),
- 'L' => (pos.x + y, pos.y + x),
- 'F' => (pos.x - y, pos.y - x),
- 'J' => (pos.x - y, pos.y - x),
- '7' => (pos.x + y, pos.y + x),
- _ => throw new Exception()
- };
- }
-
- public override void CalculatePart2()
- {
- throw new NotImplementedException();
- }
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day10;
+
+[ProblemInfo(2023, 10, "Pipe Maze")]
+internal class PipeMaze : Problem
+{
+ private string[] _maze = [];
+
+ public override void LoadInput()
+ {
+ _maze = ReadInputLines();
+ }
+
+ public override void CalculatePart1()
+ {
+ var start = GetStartPointPos();
+ var nPoints = GetStartConnections(start);
+ var seen = new Dictionary<(int, int), int>();
+
+ foreach (var point in nPoints)
+ {
+ var curPoint = start;
+ var prevPoint = point;
+ var dist = 0;
+ while (true)
+ {
+ dist++;
+ var next = GetNextPoint(curPoint, prevPoint);
+ prevPoint = curPoint;
+ curPoint = next;
+ if (next == start)
+ break;
+ if (seen.TryGetValue(next, out var d))
+ {
+ if (d > dist)
+ seen[next] = dist;
+ else
+ break;
+ }
+ else
+ seen.Add(next, dist);
+ }
+ }
+
+ Part1 = seen.Values.Max();
+ }
+
+ private (int x, int y) GetStartPointPos()
+ {
+ for (int y = 0; y < _maze.Length; y++)
+ {
+ var x = _maze[y].IndexOf('S');
+ if (x >= 0)
+ return (x, y);
+ }
+ throw new Exception("Start point not found");
+ }
+
+ private List<(int x, int y)> GetStartConnections((int x, int y) pos)
+ {
+ var points = new List<(int x, int y)>();
+ if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L')
+ points.Add((pos.x + 1, pos.y));
+ if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7')
+ points.Add((pos.x - 1, pos.y));
+
+ if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7')
+ points.Add((pos.x, pos.y + 1));
+ if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L')
+ points.Add((pos.x, pos.y - 1));
+
+ return points;
+ }
+
+ private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev)
+ {
+ var curPipe = _maze[pos.y][pos.x];
+ (int x, int y) = (pos.x - prev.x, pos.y - prev.y);
+
+ if (curPipe == 'S')
+ return GetStartConnections(pos).First(p => p != prev);
+
+ return curPipe switch
+ {
+ '|' => (pos.x, pos.y + y),
+ '-' => (pos.x + x, pos.y),
+ 'L' => (pos.x + y, pos.y + x),
+ 'F' => (pos.x - y, pos.y - x),
+ 'J' => (pos.x - y, pos.y - x),
+ '7' => (pos.x + y, pos.y + x),
+ _ => throw new Exception()
+ };
+ }
+
+ public override void CalculatePart2()
+ {
+ throw new NotImplementedException();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day11/CosmicExpansion.cs b/AdventOfCode/Problems/AOC2023/Day11/CosmicExpansion.cs
index ea715f8..3e59ca0 100644
--- a/AdventOfCode/Problems/AOC2023/Day11/CosmicExpansion.cs
+++ b/AdventOfCode/Problems/AOC2023/Day11/CosmicExpansion.cs
@@ -1,89 +1,89 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day11;
-
-[ProblemInfo(2023, 11, "Cosmic Expansion")]
-internal class CosmicExpansion : Problem
-{
- private string[] _data = [];
- private int[] _yGaps = [];
- private int[] _xGaps = [];
-
- public override void CalculatePart1()
- {
- var points = GetPoints().Select(p => Inflate(p, 2)).ToList();
- for (int i = 0; i < points.Count - 1; i++)
- {
- for (int j = i + 1; j < points.Count; j++)
- {
- var a = points[i];
- var b = points[j];
- Part1 += GetDistance(a, b);
- }
- }
- }
-
- public List<(int x, int y)> GetPoints()
- {
- var result = new List<(int x, int y)>();
- for (int y = 0; y < _data.Length; y++)
- {
- for (int x = 0; x < _data[0].Length; x++)
- {
- if (_data[y][x] == '#')
- result.Add((x, y));
- }
- }
- return result;
- }
-
- public int GetDistance((int x, int y) a, (int x, int y) b)
- {
- var xDist = Math.Abs(a.x - b.x);
- var yDist = Math.Abs(a.y - b.y);
-
- return xDist + yDist;
- }
-
- public (int x, int y) Inflate((int x, int y) point, int factor)
- {
- factor -= 1;
- var cX = _xGaps.Count(x => point.x >= x);
- var cY = _yGaps.Count(y => point.y >= y);
- return (point.x + cX * factor, point.y + cY * factor);
- }
-
- public override void CalculatePart2()
- {
- var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList();
- for (int i = 0; i < points.Count - 1; i++)
- {
- for (int j = i + 1; j < points.Count; j++)
- {
- var a = points[i];
- var b = points[j];
- Part2 += GetDistance(a, b);
- }
- }
- }
-
- public override void LoadInput()
- {
- _data = ReadInputLines();
- _yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i))
- .Where(v => v.c == _data[0].Length)
- .Select(v => v.i)
- .ToArray();
-
- _xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i))
- .Where(v => v.c == _data[0].Length)
- .Select(v => v.i)
- .ToArray();
- }
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day11;
+
+[ProblemInfo(2023, 11, "Cosmic Expansion")]
+internal class CosmicExpansion : Problem
+{
+ private string[] _data = [];
+ private int[] _yGaps = [];
+ private int[] _xGaps = [];
+
+ public override void CalculatePart1()
+ {
+ var points = GetPoints().Select(p => Inflate(p, 2)).ToList();
+ for (int i = 0; i < points.Count - 1; i++)
+ {
+ for (int j = i + 1; j < points.Count; j++)
+ {
+ var a = points[i];
+ var b = points[j];
+ Part1 += GetDistance(a, b);
+ }
+ }
+ }
+
+ public List<(int x, int y)> GetPoints()
+ {
+ var result = new List<(int x, int y)>();
+ for (int y = 0; y < _data.Length; y++)
+ {
+ for (int x = 0; x < _data[0].Length; x++)
+ {
+ if (_data[y][x] == '#')
+ result.Add((x, y));
+ }
+ }
+ return result;
+ }
+
+ public int GetDistance((int x, int y) a, (int x, int y) b)
+ {
+ var xDist = Math.Abs(a.x - b.x);
+ var yDist = Math.Abs(a.y - b.y);
+
+ return xDist + yDist;
+ }
+
+ public (int x, int y) Inflate((int x, int y) point, int factor)
+ {
+ factor -= 1;
+ var cX = _xGaps.Count(x => point.x >= x);
+ var cY = _yGaps.Count(y => point.y >= y);
+ return (point.x + cX * factor, point.y + cY * factor);
+ }
+
+ public override void CalculatePart2()
+ {
+ var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList();
+ for (int i = 0; i < points.Count - 1; i++)
+ {
+ for (int j = i + 1; j < points.Count; j++)
+ {
+ var a = points[i];
+ var b = points[j];
+ Part2 += GetDistance(a, b);
+ }
+ }
+ }
+
+ public override void LoadInput()
+ {
+ _data = ReadInputLines();
+ _yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i))
+ .Where(v => v.c == _data[0].Length)
+ .Select(v => v.i)
+ .ToArray();
+
+ _xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i))
+ .Where(v => v.c == _data[0].Length)
+ .Select(v => v.i)
+ .ToArray();
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day12/HotSprings.cs b/AdventOfCode/Problems/AOC2023/Day12/HotSprings.cs
index 3e3faf7..ce9155a 100644
--- a/AdventOfCode/Problems/AOC2023/Day12/HotSprings.cs
+++ b/AdventOfCode/Problems/AOC2023/Day12/HotSprings.cs
@@ -1,111 +1,111 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day12;
-
-[ProblemInfo(2023, 12, "Hot Springs")]
-internal class HotSprings : Problem
-{
- private Record[] _data = [];
-
- public override void CalculatePart1()
- {
- Part1 = _data.Select(r => CountPossiblilites(r)).Sum();
- }
-
- public override void CalculatePart2()
- {
- var unfolded = _data.Select(r =>
- {
- var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5));
- var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray();
- return new Record(unfoldData, unfoldPattern);
- }).ToArray();
- Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum();
- }
-
- public static int CountPossiblilites(Record record, int pos = 0)
- {
- if (pos == -1 || pos >= record.Data.Length)
- return record.IsValid ? 1 : 0;
- if (!record.IsValid)
- return 0;
- if (record.Data[pos] != '?')
- return CountPossiblilites(record, record.Data.IndexOf('?'));
-
- var front = record.Data[..pos];
- var back = record.Data[(pos + 1)..];
- var r1 = record with { Data = $"{front}.{back}" };
- var r2 = record with { Data = $"{front}#{back}" };
- return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1);
- }
-
- public override void LoadInput()
- {
- var data = ReadInputLines();
-
- _data = data.Select(x => x.Split(' '))
- .Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray()))
- .ToArray();
- }
-
- public record Record(string Data, int[] Pattern)
- {
- public bool IsValid => CheckValidity(this);
- public static bool CheckValidity(Record record)
- {
- var section = 0;
- var start = 0;
- var inSection = false;
- for (int i = 0; i < record.Data.Length; i++)
- {
- var c = record.Data[i];
- if (section >= record.Pattern.Length)
- return !record.Data[i..].Contains('#');
-
- var len = record.Pattern[section];
-
- switch (c)
- {
- case '?':
- if (inSection && i - start > len)
- return false;
- return true;
-
- case '.':
- if (inSection)
- {
- if (i - start != len)
- return false;
- inSection = false;
- start = 0;
- section++;
- }
- continue;
- case '#':
- if (!inSection)
- {
- inSection = true;
- start = i;
- }
- break;
- }
- }
- if (inSection)
- {
- if (record.Pattern[section] != (record.Data[start..].Length))
- return false;
- else
- section++;
- }
- if (section != record.Pattern.Length)
- return false;
- return true;
- }
- };
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day12;
+
+[ProblemInfo(2023, 12, "Hot Springs")]
+internal class HotSprings : Problem
+{
+ private Record[] _data = [];
+
+ public override void CalculatePart1()
+ {
+ Part1 = _data.Select(r => CountPossiblilites(r)).Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ var unfolded = _data.Select(r =>
+ {
+ var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5));
+ var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray();
+ return new Record(unfoldData, unfoldPattern);
+ }).ToArray();
+ Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum();
+ }
+
+ public static int CountPossiblilites(Record record, int pos = 0)
+ {
+ if (pos == -1 || pos >= record.Data.Length)
+ return record.IsValid ? 1 : 0;
+ if (!record.IsValid)
+ return 0;
+ if (record.Data[pos] != '?')
+ return CountPossiblilites(record, record.Data.IndexOf('?'));
+
+ var front = record.Data[..pos];
+ var back = record.Data[(pos + 1)..];
+ var r1 = record with { Data = $"{front}.{back}" };
+ var r2 = record with { Data = $"{front}#{back}" };
+ return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1);
+ }
+
+ public override void LoadInput()
+ {
+ var data = ReadInputLines();
+
+ _data = data.Select(x => x.Split(' '))
+ .Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray()))
+ .ToArray();
+ }
+
+ public record Record(string Data, int[] Pattern)
+ {
+ public bool IsValid => CheckValidity(this);
+ public static bool CheckValidity(Record record)
+ {
+ var section = 0;
+ var start = 0;
+ var inSection = false;
+ for (int i = 0; i < record.Data.Length; i++)
+ {
+ var c = record.Data[i];
+ if (section >= record.Pattern.Length)
+ return !record.Data[i..].Contains('#');
+
+ var len = record.Pattern[section];
+
+ switch (c)
+ {
+ case '?':
+ if (inSection && i - start > len)
+ return false;
+ return true;
+
+ case '.':
+ if (inSection)
+ {
+ if (i - start != len)
+ return false;
+ inSection = false;
+ start = 0;
+ section++;
+ }
+ continue;
+ case '#':
+ if (!inSection)
+ {
+ inSection = true;
+ start = i;
+ }
+ break;
+ }
+ }
+ if (inSection)
+ {
+ if (record.Pattern[section] != (record.Data[start..].Length))
+ return false;
+ else
+ section++;
+ }
+ if (section != record.Pattern.Length)
+ return false;
+ return true;
+ }
+ };
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day2/CubeConundrum.cs b/AdventOfCode/Problems/AOC2023/Day2/CubeConundrum.cs
index 88fef56..18b1065 100644
--- a/AdventOfCode/Problems/AOC2023/Day2/CubeConundrum.cs
+++ b/AdventOfCode/Problems/AOC2023/Day2/CubeConundrum.cs
@@ -1,31 +1,31 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2023.Day2;
-
-[ProblemInfo(2023, 2, "Cube Conundrum")]
-internal class CubeConundrum : Problem
-{
- private CubeGame[] _gameInfo = [];
-
- public override void LoadInput()
- {
- var lines = ReadInputLines();
- _gameInfo = lines.Select(l => new CubeGame(l)).ToArray();
- }
-
- public override void CalculatePart1()
- {
- Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum();
- }
-
- public override void CalculatePart2()
- {
- Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum();
- }
-
- public IEnumerable FindPossibleGames(CubeRound constraints)
- {
- return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints)))
- .Select(r => r.Id);
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2023.Day2;
+
+[ProblemInfo(2023, 2, "Cube Conundrum")]
+internal class CubeConundrum : Problem
+{
+ private CubeGame[] _gameInfo = [];
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines();
+ _gameInfo = lines.Select(l => new CubeGame(l)).ToArray();
+ }
+
+ public override void CalculatePart1()
+ {
+ Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum();
+ }
+
+ public IEnumerable FindPossibleGames(CubeRound constraints)
+ {
+ return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints)))
+ .Select(r => r.Id);
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day2/CubeGame.cs b/AdventOfCode/Problems/AOC2023/Day2/CubeGame.cs
index 0d9291b..1de0f0a 100644
--- a/AdventOfCode/Problems/AOC2023/Day2/CubeGame.cs
+++ b/AdventOfCode/Problems/AOC2023/Day2/CubeGame.cs
@@ -1,81 +1,81 @@
-namespace AdventOfCode.Problems.AOC2023.Day2;
-
-internal class CubeGame
-{
- public CubeRound[] Rounds { get; }
-
- public int Id { get; }
-
- public CubeGame(string line)
- {
- var info = line.Split(':');
- Id = int.Parse(info[0].Split(' ')[^1]);
-
- var roundsData = info[1].Split(';');
- Rounds = new CubeRound[roundsData.Length];
- for (int i = 0; i < roundsData.Length; i++)
- Rounds[i] = CubeRound.ParseRound(roundsData[i]);
- }
-
- public CubeRound GetMinimalConstraints()
- {
- var (r, g, b) = (0, 0, 0);
- foreach (var round in Rounds)
- {
- if (round.Red > r)
- r = round.Red;
- if (round.Green > g)
- g = round.Green;
- if (round.Blue > b)
- b = round.Blue;
- }
- return new CubeRound(r, g, b);
- }
-}
-
-internal record struct CubeRound(int Red, int Green, int Blue)
-{
- public static CubeRound ParseRound(string round)
- {
- var cubes = round.Split(',');
- var (r, g, b) = (0, 0, 0);
-
- foreach (var cube in cubes)
- {
- var info = cube.TrimStart().Split(' ');
- var count = int.Parse(info[0]);
- switch (info[1])
- {
- case ['r', ..]:
- r = count;
- break;
-
- case ['g', ..]:
- g = count;
- break;
-
- case ['b', ..]:
- b = count;
- break;
- }
- }
- return new CubeRound(r, g, b);
- }
-
- public readonly bool IsPossible(CubeRound constraints)
- {
- if (Red > constraints.Red)
- return false;
- if (Green > constraints.Green)
- return false;
- if (Blue > constraints.Blue)
- return false;
-
- return true;
- }
-
- public readonly int Power()
- {
- return Red * Green * Blue;
- }
+namespace AdventOfCode.Problems.AOC2023.Day2;
+
+internal class CubeGame
+{
+ public CubeRound[] Rounds { get; }
+
+ public int Id { get; }
+
+ public CubeGame(string line)
+ {
+ var info = line.Split(':');
+ Id = int.Parse(info[0].Split(' ')[^1]);
+
+ var roundsData = info[1].Split(';');
+ Rounds = new CubeRound[roundsData.Length];
+ for (int i = 0; i < roundsData.Length; i++)
+ Rounds[i] = CubeRound.ParseRound(roundsData[i]);
+ }
+
+ public CubeRound GetMinimalConstraints()
+ {
+ var (r, g, b) = (0, 0, 0);
+ foreach (var round in Rounds)
+ {
+ if (round.Red > r)
+ r = round.Red;
+ if (round.Green > g)
+ g = round.Green;
+ if (round.Blue > b)
+ b = round.Blue;
+ }
+ return new CubeRound(r, g, b);
+ }
+}
+
+internal record struct CubeRound(int Red, int Green, int Blue)
+{
+ public static CubeRound ParseRound(string round)
+ {
+ var cubes = round.Split(',');
+ var (r, g, b) = (0, 0, 0);
+
+ foreach (var cube in cubes)
+ {
+ var info = cube.TrimStart().Split(' ');
+ var count = int.Parse(info[0]);
+ switch (info[1])
+ {
+ case ['r', ..]:
+ r = count;
+ break;
+
+ case ['g', ..]:
+ g = count;
+ break;
+
+ case ['b', ..]:
+ b = count;
+ break;
+ }
+ }
+ return new CubeRound(r, g, b);
+ }
+
+ public readonly bool IsPossible(CubeRound constraints)
+ {
+ if (Red > constraints.Red)
+ return false;
+ if (Green > constraints.Green)
+ return false;
+ if (Blue > constraints.Blue)
+ return false;
+
+ return true;
+ }
+
+ public readonly int Power()
+ {
+ return Red * Green * Blue;
+ }
};
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day3/GearRatios.cs b/AdventOfCode/Problems/AOC2023/Day3/GearRatios.cs
index 2be2ce5..3175566 100644
--- a/AdventOfCode/Problems/AOC2023/Day3/GearRatios.cs
+++ b/AdventOfCode/Problems/AOC2023/Day3/GearRatios.cs
@@ -1,136 +1,136 @@
-using AdventOfCode.Runner.Attributes;
-
-namespace AdventOfCode.Problems.AOC2023.Day3;
-
-[ProblemInfo(2023, 3, "Gear Ratios")]
-internal class GearRatios : Problem
-{
- private string[] _data = [];
- private int _width;
- private int _height;
-
- public override void LoadInput()
- {
- _data = ReadInputLines();
- _width = _data[0].Length - 1;
- _height = _data.Length - 1;
- }
-
- public override void CalculatePart1()
- {
- var partNumbers = new List();
-
- for (int y = 0; y < _height; y++)
- {
- for (int x = 0; x <= _width; x++)
- {
- var cell = _data[y][x];
- switch (cell)
- {
- case '.':
- continue;
- case < '0' or > '9':
- FindNumbers(x, y, ref partNumbers);
- break;
- }
- }
- }
- Part1 = partNumbers.Sum();
- }
-
- public override void CalculatePart2()
- {
- var ratios = new List();
- var curNums = new List();
- for (int y = 0; y < _height; y++)
- {
- for (int x = 0; x <= _width; x++)
- {
- var cell = _data[y][x];
- switch (cell)
- {
- case '*':
- curNums.Clear();
- FindNumbers(x, y, ref curNums);
- if (curNums.Count == 2)
- ratios.Add(curNums[0] * curNums[1]);
- break;
- }
- }
- }
- Part2 = ratios.Sum();
- }
-
- public void FindNumbers(int x, int y, ref List results)
- {
- var seen = new HashSet<(int x, int y)>();
-
- var n = GetNeighborPoints(x, y);
- foreach (var (xN, yN) in n)
- {
- var c = _data[yN][xN] - '0';
- if (c >= 0) //A bug exists here, I wont fix it
- {
- var num = GetNumber(xN, yN, out var idx);
-
- if (seen.Contains(idx))
- continue;
- seen.Add(idx);
- results.Add(num);
- }
- }
- }
-
- public List<(int x, int y)> GetNeighborPoints(int x, int y)
- {
- var points = new List<(int x, int y)>();
- if (x > 0)
- points.Add((x - 1, y));
- if (x < _width)
- points.Add((x + 1, y));
- if (y > 0)
- points.Add((x, y - 1));
- if (y < _height)
- points.Add((x, y + 1));
- if (x > 0 && y > 0)
- points.Add((x - 1, y - 1));
- if (x > 0 && y < _height)
- points.Add((x - 1, y + 1));
- if (x < _width && y < _height)
- points.Add((x + 1, y + 1));
- if (x < _width && y > 0)
- points.Add((x + 1, y - 1));
-
- return points;
- }
-
- public int GetNumber(int x, int y, out (int iX, int iY) index)
- {
- var row = _data[y];
-
- var numStart = 0;
- var numEnd = _width + 1;
- for (int i = x; i >= 0; i--)
- {
- switch (row[i])
- {
- case < '0' or > '9':
- numStart = i + 1;
- goto leftDone;
- }
- }
- leftDone:
- for (int i = x; i <= _width; i++)
- {
- switch (row[i])
- {
- case < '0' or > '9':
- numEnd = i;
- goto done;
- }
- }
- done:
- index = (numStart, y);
- return int.Parse(row[numStart..numEnd]);
- }
+using AdventOfCode.Runner.Attributes;
+
+namespace AdventOfCode.Problems.AOC2023.Day3;
+
+[ProblemInfo(2023, 3, "Gear Ratios")]
+internal class GearRatios : Problem
+{
+ private string[] _data = [];
+ private int _width;
+ private int _height;
+
+ public override void LoadInput()
+ {
+ _data = ReadInputLines();
+ _width = _data[0].Length - 1;
+ _height = _data.Length - 1;
+ }
+
+ public override void CalculatePart1()
+ {
+ var partNumbers = new List();
+
+ for (int y = 0; y < _height; y++)
+ {
+ for (int x = 0; x <= _width; x++)
+ {
+ var cell = _data[y][x];
+ switch (cell)
+ {
+ case '.':
+ continue;
+ case < '0' or > '9':
+ FindNumbers(x, y, ref partNumbers);
+ break;
+ }
+ }
+ }
+ Part1 = partNumbers.Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ var ratios = new List();
+ var curNums = new List();
+ for (int y = 0; y < _height; y++)
+ {
+ for (int x = 0; x <= _width; x++)
+ {
+ var cell = _data[y][x];
+ switch (cell)
+ {
+ case '*':
+ curNums.Clear();
+ FindNumbers(x, y, ref curNums);
+ if (curNums.Count == 2)
+ ratios.Add(curNums[0] * curNums[1]);
+ break;
+ }
+ }
+ }
+ Part2 = ratios.Sum();
+ }
+
+ public void FindNumbers(int x, int y, ref List results)
+ {
+ var seen = new HashSet<(int x, int y)>();
+
+ var n = GetNeighborPoints(x, y);
+ foreach (var (xN, yN) in n)
+ {
+ var c = _data[yN][xN] - '0';
+ if (c >= 0) //A bug exists here, I wont fix it
+ {
+ var num = GetNumber(xN, yN, out var idx);
+
+ if (seen.Contains(idx))
+ continue;
+ seen.Add(idx);
+ results.Add(num);
+ }
+ }
+ }
+
+ public List<(int x, int y)> GetNeighborPoints(int x, int y)
+ {
+ var points = new List<(int x, int y)>();
+ if (x > 0)
+ points.Add((x - 1, y));
+ if (x < _width)
+ points.Add((x + 1, y));
+ if (y > 0)
+ points.Add((x, y - 1));
+ if (y < _height)
+ points.Add((x, y + 1));
+ if (x > 0 && y > 0)
+ points.Add((x - 1, y - 1));
+ if (x > 0 && y < _height)
+ points.Add((x - 1, y + 1));
+ if (x < _width && y < _height)
+ points.Add((x + 1, y + 1));
+ if (x < _width && y > 0)
+ points.Add((x + 1, y - 1));
+
+ return points;
+ }
+
+ public int GetNumber(int x, int y, out (int iX, int iY) index)
+ {
+ var row = _data[y];
+
+ var numStart = 0;
+ var numEnd = _width + 1;
+ for (int i = x; i >= 0; i--)
+ {
+ switch (row[i])
+ {
+ case < '0' or > '9':
+ numStart = i + 1;
+ goto leftDone;
+ }
+ }
+ leftDone:
+ for (int i = x; i <= _width; i++)
+ {
+ switch (row[i])
+ {
+ case < '0' or > '9':
+ numEnd = i;
+ goto done;
+ }
+ }
+ done:
+ index = (numStart, y);
+ return int.Parse(row[numStart..numEnd]);
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day4/Scratchcards.cs b/AdventOfCode/Problems/AOC2023/Day4/Scratchcards.cs
index 68f2dd6..d95693c 100644
--- a/AdventOfCode/Problems/AOC2023/Day4/Scratchcards.cs
+++ b/AdventOfCode/Problems/AOC2023/Day4/Scratchcards.cs
@@ -1,66 +1,66 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day4;
-[ProblemInfo(2023, 4, "Scratchcards")]
-internal class Scratchcards : Problem
-{
- private (int card, int[] win, int[] have)[] _cards = [];
- private readonly Dictionary _cardCount = [];
-
- public override void CalculatePart1()
- {
- Part1 = _cards
- .Select(c => c.have.Intersect(c.win).Count())
- .Select(c => c == 0 ? 0 : Math.Pow(2, c - 1))
- .Sum();
- }
-
- public override void CalculatePart2()
- {
- Part2 = _cards.Length;
- for (int i = 0; i < _cards.Length; i++)
- {
- var card = _cards[i];
- var wins = card.have.Intersect(card.win).Count();
- var cCount = GetCardCount(card.card);
- for (int j = 1; j <= wins; j++)
- AddCards(card.card + j, cCount);
- Part2 += wins * cCount;
- }
- }
-
- private int GetCardCount(int card)
- {
- if(_cardCount.TryGetValue(card, out var count))
- return count;
- return 1;
- }
-
- private void AddCards(int card, int count)
- {
- if(_cardCount.ContainsKey(card))
- _cardCount[card] += count;
- else
- _cardCount.Add(card, count + 1);
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines();
- _cards = new (int card, int[] win, int[] have)[lines.Length];
- for (int i = 0; i < lines.Length; i++)
- {
- var card = lines[i].Split(':');
- var cardNum = int.Parse(card[0].Split(' ').Last());
- var numbers = card[1].Split('|')
- .Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse));
- _cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray());
- }
- }
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day4;
+[ProblemInfo(2023, 4, "Scratchcards")]
+internal class Scratchcards : Problem
+{
+ private (int card, int[] win, int[] have)[] _cards = [];
+ private readonly Dictionary _cardCount = [];
+
+ public override void CalculatePart1()
+ {
+ Part1 = _cards
+ .Select(c => c.have.Intersect(c.win).Count())
+ .Select(c => c == 0 ? 0 : Math.Pow(2, c - 1))
+ .Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = _cards.Length;
+ for (int i = 0; i < _cards.Length; i++)
+ {
+ var card = _cards[i];
+ var wins = card.have.Intersect(card.win).Count();
+ var cCount = GetCardCount(card.card);
+ for (int j = 1; j <= wins; j++)
+ AddCards(card.card + j, cCount);
+ Part2 += wins * cCount;
+ }
+ }
+
+ private int GetCardCount(int card)
+ {
+ if(_cardCount.TryGetValue(card, out var count))
+ return count;
+ return 1;
+ }
+
+ private void AddCards(int card, int count)
+ {
+ if(_cardCount.ContainsKey(card))
+ _cardCount[card] += count;
+ else
+ _cardCount.Add(card, count + 1);
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines();
+ _cards = new (int card, int[] win, int[] have)[lines.Length];
+ for (int i = 0; i < lines.Length; i++)
+ {
+ var card = lines[i].Split(':');
+ var cardNum = int.Parse(card[0].Split(' ').Last());
+ var numbers = card[1].Split('|')
+ .Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse));
+ _cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray());
+ }
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day5/CategoryEvaluator.cs b/AdventOfCode/Problems/AOC2023/Day5/CategoryEvaluator.cs
index d7a1135..8e7f0a7 100644
--- a/AdventOfCode/Problems/AOC2023/Day5/CategoryEvaluator.cs
+++ b/AdventOfCode/Problems/AOC2023/Day5/CategoryEvaluator.cs
@@ -1,73 +1,73 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day5;
-internal class CategoryEvaluator
-{
- public Dictionary destinations = [];
-
- public CategoryEvaluator(CategoryMapper[] mappers)
- {
- destinations = mappers.ToDictionary(m => m.Destination);
- }
-
- public long Evaluate(Category source, long sourceValue, Category destination)
- {
- var mappers = new List();
- var curMapper = destinations[destination];
- do
- {
- mappers.Add(curMapper);
- curMapper = destinations[curMapper.Source];
- } while (curMapper.Source != source);
- mappers.Add(destinations[mappers.Last().Source]);
- mappers.Reverse();
- var result = sourceValue;
- foreach (var mapper in mappers)
- {
- result = mapper.Evaluate(result);
- }
- return result;
- }
-
- public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination)
- {
- var mappers = new List();
- var curMapper = destinations[destination];
- do
- {
- mappers.Add(curMapper);
- curMapper = destinations[curMapper.Source];
- } while (curMapper.Source != source);
- mappers.Add(destinations[mappers.Last().Source]);
- mappers.Reverse();
- var result = seeds;
- foreach (var mapper in mappers)
- {
- result = mapper.Evaluate(result);
- }
- return result.Distinct().ToArray();
- }
-
- public CategoryMapper GetCategoryMapper(Category destination)
- {
- return destinations[destination];
- }
-
-
- public enum Category
- {
- Seed,
- Soil,
- Fertilizer,
- Water,
- Light,
- Temperature,
- Humidity,
- Location
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day5;
+internal class CategoryEvaluator
+{
+ public Dictionary destinations = [];
+
+ public CategoryEvaluator(CategoryMapper[] mappers)
+ {
+ destinations = mappers.ToDictionary(m => m.Destination);
+ }
+
+ public long Evaluate(Category source, long sourceValue, Category destination)
+ {
+ var mappers = new List();
+ var curMapper = destinations[destination];
+ do
+ {
+ mappers.Add(curMapper);
+ curMapper = destinations[curMapper.Source];
+ } while (curMapper.Source != source);
+ mappers.Add(destinations[mappers.Last().Source]);
+ mappers.Reverse();
+ var result = sourceValue;
+ foreach (var mapper in mappers)
+ {
+ result = mapper.Evaluate(result);
+ }
+ return result;
+ }
+
+ public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination)
+ {
+ var mappers = new List();
+ var curMapper = destinations[destination];
+ do
+ {
+ mappers.Add(curMapper);
+ curMapper = destinations[curMapper.Source];
+ } while (curMapper.Source != source);
+ mappers.Add(destinations[mappers.Last().Source]);
+ mappers.Reverse();
+ var result = seeds;
+ foreach (var mapper in mappers)
+ {
+ result = mapper.Evaluate(result);
+ }
+ return result.Distinct().ToArray();
+ }
+
+ public CategoryMapper GetCategoryMapper(Category destination)
+ {
+ return destinations[destination];
+ }
+
+
+ public enum Category
+ {
+ Seed,
+ Soil,
+ Fertilizer,
+ Water,
+ Light,
+ Temperature,
+ Humidity,
+ Location
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day5/CategoryMapper.cs b/AdventOfCode/Problems/AOC2023/Day5/CategoryMapper.cs
index 927cc2e..19adba3 100644
--- a/AdventOfCode/Problems/AOC2023/Day5/CategoryMapper.cs
+++ b/AdventOfCode/Problems/AOC2023/Day5/CategoryMapper.cs
@@ -1,88 +1,88 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day5;
-internal class CategoryMapper
-{
- public CategoryEvaluator.Category Source { get; }
- public CategoryEvaluator.Category Destination { get; }
- public long[] DestinationStart { get; }
- public long[] DestinationEnd { get; }
- public long[] SourceStart { get; }
- public long[] SourceEnd { get; }
- public long[] RangeLength { get; }
- public long[] Gap { get; }
-
- public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length)
- {
- Source = source;
- Destination = destination;
- DestinationStart = destinationStart;
- DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray();
- SourceStart = sourceStart;
- SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray();
- RangeLength = length;
- Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray();
- }
-
- public static CategoryMapper Parse(string categoryData)
- {
- var lines = categoryData.Split("\r\n");
- var names = lines[0].Split(' ')[0].Split('-');
- var source = Enum.Parse(names[0], true);
- var dst = Enum.Parse(names[^1], true);
-
- var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray());
- var dStart = mappingData.Select(d => d[0]).ToArray();
- var sStart = mappingData.Select(d => d[1]).ToArray();
- var len = mappingData.Select(d => d[2]).ToArray();
- return new CategoryMapper(source, dst, dStart, sStart, len);
-
- }
-
- public long Evaluate(long value)
- {
- for (int i = 0; i < DestinationStart.Length; i++)
- {
- if (SourceStart[i] > value)
- continue;
- if (SourceEnd[i] < value)
- continue;
- return value + Gap[i];
- }
- return value;
- }
-
- public (long start, long end)[] Evaluate((long start, long end)[] ranges)
- {
- var result = new List<(long start, long end)>();
- for (int i = 0; i < DestinationStart.Length; i++)
- {
- result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i]))));
- }
- 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)
- {
- if (source.start >= dst.start && source.end <= dst.end)
- return [source];
- if(source.end < dst.end)
- return [source];
- if(source.start > dst.start)
- return [source];
-
- if(source.start < dst.start)
- return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)];
- else
- return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)];
- }
-
- public override string ToString()
- {
- return $"{Source} -> {Destination}";
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day5;
+internal class CategoryMapper
+{
+ public CategoryEvaluator.Category Source { get; }
+ public CategoryEvaluator.Category Destination { get; }
+ public long[] DestinationStart { get; }
+ public long[] DestinationEnd { get; }
+ public long[] SourceStart { get; }
+ public long[] SourceEnd { get; }
+ public long[] RangeLength { get; }
+ public long[] Gap { get; }
+
+ public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length)
+ {
+ Source = source;
+ Destination = destination;
+ DestinationStart = destinationStart;
+ DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray();
+ SourceStart = sourceStart;
+ SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray();
+ RangeLength = length;
+ Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray();
+ }
+
+ public static CategoryMapper Parse(string categoryData)
+ {
+ var lines = categoryData.Split("\r\n");
+ var names = lines[0].Split(' ')[0].Split('-');
+ var source = Enum.Parse(names[0], true);
+ var dst = Enum.Parse(names[^1], true);
+
+ var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray());
+ var dStart = mappingData.Select(d => d[0]).ToArray();
+ var sStart = mappingData.Select(d => d[1]).ToArray();
+ var len = mappingData.Select(d => d[2]).ToArray();
+ return new CategoryMapper(source, dst, dStart, sStart, len);
+
+ }
+
+ public long Evaluate(long value)
+ {
+ for (int i = 0; i < DestinationStart.Length; i++)
+ {
+ if (SourceStart[i] > value)
+ continue;
+ if (SourceEnd[i] < value)
+ continue;
+ return value + Gap[i];
+ }
+ return value;
+ }
+
+ public (long start, long end)[] Evaluate((long start, long end)[] ranges)
+ {
+ var result = new List<(long start, long end)>();
+ for (int i = 0; i < DestinationStart.Length; i++)
+ {
+ result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i]))));
+ }
+ 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)
+ {
+ if (source.start >= dst.start && source.end <= dst.end)
+ return [source];
+ if(source.end < dst.end)
+ return [source];
+ if(source.start > dst.start)
+ return [source];
+
+ if(source.start < dst.start)
+ return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)];
+ else
+ return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)];
+ }
+
+ public override string ToString()
+ {
+ return $"{Source} -> {Destination}";
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day5/SeedFertilizer.cs b/AdventOfCode/Problems/AOC2023/Day5/SeedFertilizer.cs
index 075ec37..a61f691 100644
--- a/AdventOfCode/Problems/AOC2023/Day5/SeedFertilizer.cs
+++ b/AdventOfCode/Problems/AOC2023/Day5/SeedFertilizer.cs
@@ -1,38 +1,38 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day5;
-[ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")]
-internal class SeedFertilizer : Problem
-{
- private long[] _seeds = [];
- private CategoryEvaluator _evaluator = new ([]);
-
- public override void LoadInput()
- {
- var data = ReadInputText("sample.txt");
- var sections = data.Split("\r\n\r\n");
- _seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray();
-
- var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray();
- _evaluator = new CategoryEvaluator(mappers);
- }
-
- public override void CalculatePart1()
- {
- var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location));
- Part1 = evaludated.Min();
- }
-
- 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);
-
- }
-
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day5;
+[ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")]
+internal class SeedFertilizer : Problem
+{
+ private long[] _seeds = [];
+ private CategoryEvaluator _evaluator = new ([]);
+
+ public override void LoadInput()
+ {
+ var data = ReadInputText("sample.txt");
+ var sections = data.Split("\r\n\r\n");
+ _seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray();
+
+ var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray();
+ _evaluator = new CategoryEvaluator(mappers);
+ }
+
+ public override void CalculatePart1()
+ {
+ var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location));
+ Part1 = evaludated.Min();
+ }
+
+ 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);
+
+ }
+
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day6/WaitForIt.cs b/AdventOfCode/Problems/AOC2023/Day6/WaitForIt.cs
index 69a495f..9d9426c 100644
--- a/AdventOfCode/Problems/AOC2023/Day6/WaitForIt.cs
+++ b/AdventOfCode/Problems/AOC2023/Day6/WaitForIt.cs
@@ -1,65 +1,65 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day6;
-[ProblemInfo(2023, 6, "Wait For It")]
-internal class WaitForIt : Problem
-{
- private int[] _times = [];
- private int[] _distances = [];
- private int _realTime;
- private long _realDistance;
-
- public override void LoadInput()
- {
- var lines = ReadInputLines("input.txt");
- _times = lines[0].Split(':')[1]
- .Split(' ')
- .Where(e => e.Length > 0)
- .Select(int.Parse)
- .ToArray();
-
- _distances = lines[1].Split(':')[1]
- .Split(' ')
- .Where(e => e.Length > 0)
- .Select(int.Parse)
- .ToArray();
-
- _realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", ""));
- _realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", ""));
- }
-
- public override void CalculatePart1()
- {
- var winList = new List();
- for (int i = 0; i < _times.Length; i++)
- {
- var time = _times[i];
- var distance = _distances[i];
- var minTime = (int)Math.Floor((float)distance / time);
- var possibleHeldTimes = Enumerable.Range(minTime, time - minTime);
- var races = possibleHeldTimes.Select(t => (time - t) * t);
- winList.Add(races.Count(d => d > distance));
- }
- Part1 = winList.Aggregate((a, b) => a * b);
- }
-
- public override void CalculatePart2()
- {
- var minTime = (long)Math.Floor((float)_realDistance/ _realTime);
- var maxTime = _realTime - minTime;
- for (long i = minTime; i <= maxTime; i++)
- {
- var dist = (_realTime - i) * i;
- if(dist > _realDistance)
- Part2++;
- }
- }
-
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day6;
+[ProblemInfo(2023, 6, "Wait For It")]
+internal class WaitForIt : Problem
+{
+ private int[] _times = [];
+ private int[] _distances = [];
+ private int _realTime;
+ private long _realDistance;
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines("input.txt");
+ _times = lines[0].Split(':')[1]
+ .Split(' ')
+ .Where(e => e.Length > 0)
+ .Select(int.Parse)
+ .ToArray();
+
+ _distances = lines[1].Split(':')[1]
+ .Split(' ')
+ .Where(e => e.Length > 0)
+ .Select(int.Parse)
+ .ToArray();
+
+ _realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", ""));
+ _realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", ""));
+ }
+
+ public override void CalculatePart1()
+ {
+ var winList = new List();
+ for (int i = 0; i < _times.Length; i++)
+ {
+ var time = _times[i];
+ var distance = _distances[i];
+ var minTime = (int)Math.Floor((float)distance / time);
+ var possibleHeldTimes = Enumerable.Range(minTime, time - minTime);
+ var races = possibleHeldTimes.Select(t => (time - t) * t);
+ winList.Add(races.Count(d => d > distance));
+ }
+ Part1 = winList.Aggregate((a, b) => a * b);
+ }
+
+ public override void CalculatePart2()
+ {
+ var minTime = (long)Math.Floor((float)_realDistance/ _realTime);
+ var maxTime = _realTime - minTime;
+ for (long i = minTime; i <= maxTime; i++)
+ {
+ var dist = (_realTime - i) * i;
+ if(dist > _realDistance)
+ Part2++;
+ }
+ }
+
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day7/CamelCards.cs b/AdventOfCode/Problems/AOC2023/Day7/CamelCards.cs
index bf8aeaf..8e51baf 100644
--- a/AdventOfCode/Problems/AOC2023/Day7/CamelCards.cs
+++ b/AdventOfCode/Problems/AOC2023/Day7/CamelCards.cs
@@ -1,36 +1,36 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day7;
-[ProblemInfo(2023, 7, "Camel Cards")]
-internal class CamelCards : Problem
-{
- private CamelHand[] _hands = [];
- private CamelHand[] _jokerHands = [];
-
- public override void LoadInput()
- {
- var data = ReadInputLines("input.txt");
- _hands = data.Select(d => new CamelHand(d)).ToArray();
- _jokerHands = data.Select(d => new CamelHand(d, true)).ToArray();
- }
-
- public override void CalculatePart1()
- {
- var x = _hands.Order();
- Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
- }
-
- public override void CalculatePart2()
- {
- var x = _jokerHands.Order().Print();
- //x.Where(x => x.Hand.Contains('J')).Print();
- Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
- }
-
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day7;
+[ProblemInfo(2023, 7, "Camel Cards")]
+internal class CamelCards : Problem
+{
+ private CamelHand[] _hands = [];
+ private CamelHand[] _jokerHands = [];
+
+ public override void LoadInput()
+ {
+ var data = ReadInputLines("input.txt");
+ _hands = data.Select(d => new CamelHand(d)).ToArray();
+ _jokerHands = data.Select(d => new CamelHand(d, true)).ToArray();
+ }
+
+ public override void CalculatePart1()
+ {
+ var x = _hands.Order();
+ Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ var x = _jokerHands.Order().Print();
+ //x.Where(x => x.Hand.Contains('J')).Print();
+ Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
+ }
+
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day7/CamelHand.cs b/AdventOfCode/Problems/AOC2023/Day7/CamelHand.cs
index 9352765..62e136c 100644
--- a/AdventOfCode/Problems/AOC2023/Day7/CamelHand.cs
+++ b/AdventOfCode/Problems/AOC2023/Day7/CamelHand.cs
@@ -1,106 +1,106 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day7;
-internal class CamelHand : IComparable
-{
- public static readonly List CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
- public static readonly List CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ];
-
- public string Hand { get; set; }
- public int Bid { get; set; }
- public int Value { get; set; }
- public HandType Type { get; set; }
- public CamelHand(string data, bool useJoker = false)
- {
- var split = data.Split(' ');
- Hand = split[0];
- Bid = int.Parse(split[1]);
- Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand);
- Value = CalculateValue(Hand, useJoker);
- }
-
- public static int CalculateValue(string hand, bool useJoker)
- {
- var total = 0;
- for (int i = 0; i < hand.Length; i++)
- {
- var p = (hand.Length - i - 1);
- var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]);
- total += (v + 1) * (int)Math.Pow(13, p);
- }
- return total;
- }
-
- public bool IsStrongerThan(CamelHand card)
- {
- if (Type > card.Type)
- return true;
- if(Type < card.Type)
- return false;
-
- return Value >= card.Value;
- }
-
- private static HandType GetJokerHandType(string hand)
- {
- var type = GetHandType(hand);
- if (type == HandType.FiveOfKind)
- return type;
-
- if (!hand.Contains('J'))
- return type;
- var bestCard = hand.GroupBy(c => c)
- .OrderByDescending(c => c.Count())
- .First(c => c.Key != 'J').Key;
-
- var newHand = hand.Replace('J', bestCard);
- return GetHandType(newHand);
- }
- private static HandType GetHandType(string hand)
- {
- var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray();
-
- if (cardGroups.Length == 1)
- return HandType.FiveOfKind;
- if(cardGroups.Contains(4))
- return HandType.FourOfKind;
- if (cardGroups.Contains(3) && cardGroups.Contains(2))
- return HandType.FullHouse;
- if(cardGroups.Contains(3))
- return HandType.ThreeOfKind;
-
- var pairs = cardGroups.Count(c => c == 2);
- if (pairs == 2)
- return HandType.TwoPair;
- if (pairs == 1)
- return HandType.OnePair;
-
- return HandType.HighCard;
- }
-
- public int CompareTo(CamelHand? other)
- {
- if(other == null) return 1;
- return IsStrongerThan(other) ? 1 : -1;
- }
-
- public override string ToString()
- {
- return $"[{Value}] {Hand}: {Type} | {Bid}";
- }
-
- public enum HandType
- {
- HighCard,
- OnePair,
- TwoPair,
- ThreeOfKind,
- FullHouse,
- FourOfKind,
- FiveOfKind
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day7;
+internal class CamelHand : IComparable
+{
+ public static readonly List CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
+ public static readonly List CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ];
+
+ public string Hand { get; set; }
+ public int Bid { get; set; }
+ public int Value { get; set; }
+ public HandType Type { get; set; }
+ public CamelHand(string data, bool useJoker = false)
+ {
+ var split = data.Split(' ');
+ Hand = split[0];
+ Bid = int.Parse(split[1]);
+ Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand);
+ Value = CalculateValue(Hand, useJoker);
+ }
+
+ public static int CalculateValue(string hand, bool useJoker)
+ {
+ var total = 0;
+ for (int i = 0; i < hand.Length; i++)
+ {
+ var p = (hand.Length - i - 1);
+ var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]);
+ total += (v + 1) * (int)Math.Pow(13, p);
+ }
+ return total;
+ }
+
+ public bool IsStrongerThan(CamelHand card)
+ {
+ if (Type > card.Type)
+ return true;
+ if(Type < card.Type)
+ return false;
+
+ return Value >= card.Value;
+ }
+
+ private static HandType GetJokerHandType(string hand)
+ {
+ var type = GetHandType(hand);
+ if (type == HandType.FiveOfKind)
+ return type;
+
+ if (!hand.Contains('J'))
+ return type;
+ var bestCard = hand.GroupBy(c => c)
+ .OrderByDescending(c => c.Count())
+ .First(c => c.Key != 'J').Key;
+
+ var newHand = hand.Replace('J', bestCard);
+ return GetHandType(newHand);
+ }
+ private static HandType GetHandType(string hand)
+ {
+ var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray();
+
+ if (cardGroups.Length == 1)
+ return HandType.FiveOfKind;
+ if(cardGroups.Contains(4))
+ return HandType.FourOfKind;
+ if (cardGroups.Contains(3) && cardGroups.Contains(2))
+ return HandType.FullHouse;
+ if(cardGroups.Contains(3))
+ return HandType.ThreeOfKind;
+
+ var pairs = cardGroups.Count(c => c == 2);
+ if (pairs == 2)
+ return HandType.TwoPair;
+ if (pairs == 1)
+ return HandType.OnePair;
+
+ return HandType.HighCard;
+ }
+
+ public int CompareTo(CamelHand? other)
+ {
+ if(other == null) return 1;
+ return IsStrongerThan(other) ? 1 : -1;
+ }
+
+ public override string ToString()
+ {
+ return $"[{Value}] {Hand}: {Type} | {Bid}";
+ }
+
+ public enum HandType
+ {
+ HighCard,
+ OnePair,
+ TwoPair,
+ ThreeOfKind,
+ FullHouse,
+ FourOfKind,
+ FiveOfKind
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2023/Day8/HauntedWasteland.cs b/AdventOfCode/Problems/AOC2023/Day8/HauntedWasteland.cs
index 000a8e0..083d463 100644
--- a/AdventOfCode/Problems/AOC2023/Day8/HauntedWasteland.cs
+++ b/AdventOfCode/Problems/AOC2023/Day8/HauntedWasteland.cs
@@ -1,74 +1,74 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day8;
-
-[ProblemInfo(2023, 8, "Haunted Wasteland")]
-internal class HauntedWasteland : Problem
-{
- private string _path = string.Empty;
- private Dictionary _nodes = [];
-
- public override void LoadInput()
- {
- var data = ReadInputLines();
- _path = data[0];
-
- for (int i = 2; i < data.Length; i++)
- {
- var curLine = data[i].Split('=');
- var node = curLine[0].TrimEnd();
- var branches = curLine[1][2..^1].Split(", ");
- _nodes.Add(node, (branches[0], branches[1]));
- }
- }
-
- public override void CalculatePart1()
- {
- var curPos = "AAA";
- var i = 0;
- var steps = 0;
- do
- {
- curPos = _path[i] switch
- {
- 'L' => _nodes[curPos].left,
- 'R' => _nodes[curPos].right,
- _ => throw new Exception("Something went horribly wrong")
- };
- i = (i + 1) % _path.Length;
- steps++;
- } while (curPos != "ZZZ");
- Part1 = steps;
- }
-
- public override void CalculatePart2()
- {
- var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray();
- var len = new long[curPos.Length];
- var i = 0;
- do
- {
- for (int j = 0; j < curPos.Length; j++)
- {
- if (curPos[j][^1] == 'Z')
- continue;
- len[j]++;
- curPos[j] = _path[i] switch
- {
- 'L' => _nodes[curPos[j]].left,
- 'R' => _nodes[curPos[j]].right,
- _ => throw new Exception("Something went horribly wrong")
- };
- }
- i = (i + 1) % _path.Length;
- } while (curPos.Any(n => n[^1] != 'Z'));
-
- Part2 = len.LCM();
- }
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day8;
+
+[ProblemInfo(2023, 8, "Haunted Wasteland")]
+internal class HauntedWasteland : Problem
+{
+ private string _path = string.Empty;
+ private Dictionary _nodes = [];
+
+ public override void LoadInput()
+ {
+ var data = ReadInputLines();
+ _path = data[0];
+
+ for (int i = 2; i < data.Length; i++)
+ {
+ var curLine = data[i].Split('=');
+ var node = curLine[0].TrimEnd();
+ var branches = curLine[1][2..^1].Split(", ");
+ _nodes.Add(node, (branches[0], branches[1]));
+ }
+ }
+
+ public override void CalculatePart1()
+ {
+ var curPos = "AAA";
+ var i = 0;
+ var steps = 0;
+ do
+ {
+ curPos = _path[i] switch
+ {
+ 'L' => _nodes[curPos].left,
+ 'R' => _nodes[curPos].right,
+ _ => throw new Exception("Something went horribly wrong")
+ };
+ i = (i + 1) % _path.Length;
+ steps++;
+ } while (curPos != "ZZZ");
+ Part1 = steps;
+ }
+
+ public override void CalculatePart2()
+ {
+ var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray();
+ var len = new long[curPos.Length];
+ var i = 0;
+ do
+ {
+ for (int j = 0; j < curPos.Length; j++)
+ {
+ if (curPos[j][^1] == 'Z')
+ continue;
+ len[j]++;
+ curPos[j] = _path[i] switch
+ {
+ 'L' => _nodes[curPos[j]].left,
+ 'R' => _nodes[curPos[j]].right,
+ _ => throw new Exception("Something went horribly wrong")
+ };
+ }
+ i = (i + 1) % _path.Length;
+ } while (curPos.Any(n => n[^1] != 'Z'));
+
+ Part2 = len.LCM();
+ }
}
\ No newline at end of file
diff --git a/AdventOfCode/Problems/AOC2023/Day9/MirageMaintenance.cs b/AdventOfCode/Problems/AOC2023/Day9/MirageMaintenance.cs
index a5a8f02..27c1b21 100644
--- a/AdventOfCode/Problems/AOC2023/Day9/MirageMaintenance.cs
+++ b/AdventOfCode/Problems/AOC2023/Day9/MirageMaintenance.cs
@@ -1,85 +1,85 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2023.Day9;
-[ProblemInfo(2023, 9, "Mirage Maintenance")]
-internal class MirageMaintenance : Problem
-{
- private long[][] _history = [];
-
- public override void LoadInput()
- {
- _history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray();
- }
-
- public long CalculateNumber(long[] values, bool last = true)
- {
- var diffs = new long[values.Length - 1];
- for (int i = 0; i < values.Length - 1; i++)
- diffs[i] = values[i + 1] - values[i];
-
- if (diffs.Any(d => d != 0))
- return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last));
- else
- return last ? values.Last() : values.First();
- }
-
- [Obsolete("Optimize too soon garbage")]
- public long GetNextNumber(long[] history)
- {
- var data = new List>
- {
- new(history.Reverse())
- };
- CalculateLayer(data, 1, 1);
- var sum = data.Select(d => d.First()).Sum();
- Console.WriteLine();
- Console.WriteLine(string.Join(',', history));
- Console.WriteLine();
-
- foreach (var item in data)
- Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString())));
- return sum;
- }
-
- [Obsolete("Optimize too soon garbage")]
- public void CalculateLayer(List> data, int layer, int pos)
- {
- while (data.Count <= layer)
- data.Add([]);
- var lastLayer = layer - 1;
- if (layer != 0 && data[lastLayer].Count <= pos)
- CalculateLayer(data, lastLayer, pos + 1);
-
- var right = data[lastLayer][pos - 1];
- var left = data[lastLayer][pos];
- var diff = right - left;
- data[layer].Add(diff);
- if (diff != 0 && pos == 1)
- CalculateLayer(data, layer + 1, 1);
- }
-
- public enum State
- {
- Diff,
- Expand,
- Predict
- }
-
- public override void CalculatePart1()
- {
- //GetNextNumber(_history[2]);
- Part1 = _history.Select(c => CalculateNumber(c)).Sum();
- }
-
- public override void CalculatePart2()
- {
- Part2 = _history.Select(c => CalculateNumber(c, false)).Sum();
- }
-
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2023.Day9;
+[ProblemInfo(2023, 9, "Mirage Maintenance")]
+internal class MirageMaintenance : Problem
+{
+ private long[][] _history = [];
+
+ public override void LoadInput()
+ {
+ _history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray();
+ }
+
+ public long CalculateNumber(long[] values, bool last = true)
+ {
+ var diffs = new long[values.Length - 1];
+ for (int i = 0; i < values.Length - 1; i++)
+ diffs[i] = values[i + 1] - values[i];
+
+ if (diffs.Any(d => d != 0))
+ return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last));
+ else
+ return last ? values.Last() : values.First();
+ }
+
+ [Obsolete("Optimize too soon garbage")]
+ public long GetNextNumber(long[] history)
+ {
+ var data = new List>
+ {
+ new(history.Reverse())
+ };
+ CalculateLayer(data, 1, 1);
+ var sum = data.Select(d => d.First()).Sum();
+ Console.WriteLine();
+ Console.WriteLine(string.Join(',', history));
+ Console.WriteLine();
+
+ foreach (var item in data)
+ Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString())));
+ return sum;
+ }
+
+ [Obsolete("Optimize too soon garbage")]
+ public void CalculateLayer(List> data, int layer, int pos)
+ {
+ while (data.Count <= layer)
+ data.Add([]);
+ var lastLayer = layer - 1;
+ if (layer != 0 && data[lastLayer].Count <= pos)
+ CalculateLayer(data, lastLayer, pos + 1);
+
+ var right = data[lastLayer][pos - 1];
+ var left = data[lastLayer][pos];
+ var diff = right - left;
+ data[layer].Add(diff);
+ if (diff != 0 && pos == 1)
+ CalculateLayer(data, layer + 1, 1);
+ }
+
+ public enum State
+ {
+ Diff,
+ Expand,
+ Predict
+ }
+
+ public override void CalculatePart1()
+ {
+ //GetNextNumber(_history[2]);
+ Part1 = _history.Select(c => CalculateNumber(c)).Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ Part2 = _history.Select(c => CalculateNumber(c, false)).Sum();
+ }
+
+}
diff --git a/AdventOfCode/Problems/AOC2024/Day1/HistorianHysteria.cs b/AdventOfCode/Problems/AOC2024/Day1/HistorianHysteria.cs
index ac676d4..b4411ae 100644
--- a/AdventOfCode/Problems/AOC2024/Day1/HistorianHysteria.cs
+++ b/AdventOfCode/Problems/AOC2024/Day1/HistorianHysteria.cs
@@ -1,40 +1,40 @@
-using AdventOfCode.Runner.Attributes;
-
-using System;
-using System.Collections.Frozen;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2024.Day1;
-[ProblemInfo(2024, 1, "Historian Hysteria")]
-internal class HistorianHysteria : Problem
-{
- private int[] _left = [];
- private int[] _right = [];
-
- public override void CalculatePart1()
- {
- Part1 = _left.Order()
- .Zip(_right.Order())
- .Select(a => Math.Abs(a.First - a.Second))
- .Sum();
- }
-
- public override void CalculatePart2()
- {
- var rightFeq = _right.GroupBy(x => x)
- .ToFrozenDictionary(g => g.Key, g => g.Count());
- Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0)
- .Sum();
- }
-
- public override void LoadInput()
- {
- var lines = ReadInputLines();
- var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList();
- _left = data.Select(l => l.First()).ToArray();
- _right = data.Select(l => l.Last()).ToArray();
- }
-}
+using AdventOfCode.Runner.Attributes;
+
+using System;
+using System.Collections.Frozen;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2024.Day1;
+[ProblemInfo(2024, 1, "Historian Hysteria")]
+internal class HistorianHysteria : Problem
+{
+ private int[] _left = [];
+ private int[] _right = [];
+
+ public override void CalculatePart1()
+ {
+ Part1 = _left.Order()
+ .Zip(_right.Order())
+ .Select(a => Math.Abs(a.First - a.Second))
+ .Sum();
+ }
+
+ public override void CalculatePart2()
+ {
+ var rightFeq = _right.GroupBy(x => x)
+ .ToFrozenDictionary(g => g.Key, g => g.Count());
+ Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0)
+ .Sum();
+ }
+
+ public override void LoadInput()
+ {
+ var lines = ReadInputLines();
+ var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList();
+ _left = data.Select(l => l.First()).ToArray();
+ _right = data.Select(l => l.Last()).ToArray();
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2024/Day10/HoofIt.cs b/AdventOfCode/Problems/AOC2024/Day10/HoofIt.cs
index aec0b70..59e23c7 100644
--- a/AdventOfCode/Problems/AOC2024/Day10/HoofIt.cs
+++ b/AdventOfCode/Problems/AOC2024/Day10/HoofIt.cs
@@ -1,102 +1,102 @@
-using AdventOfCode.Utils.Models;
-
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AdventOfCode.Problems.AOC2024.Day10;
-[ProblemInfo(2024, 10, "Hoof It")]
-internal class HoofIt : Problem
-{
- private int[][] _data = [];
-
- public static Vec2[] DIRS = [
- new(0, -1),
- new(1, 0),
- new(0, 1),
- new(-1, 0),
- ];
-
- public override void CalculatePart1()
- {
- for (int y = 0; y < _data.Length; y++)
- {
- var row = _data[y];
- for (int x = 0; x < row.Length; x++)
- {
- var h = row[x];
- if (h != 0)
- continue;
- var (s,_) = GetScore(new(x, y));
- Part1 += s;
- }
- }
- }
-
- public override void CalculatePart2()
- {
- for (int y = 0; y < _data.Length; y++)
- {
- var row = _data[y];
- for (int x = 0; x < row.Length; x++)
- {
- var h = row[x];
- if (h != 0)
- continue;
- var (_, s) = GetScore(new(x, y));
- Part2 += s;
- }
- }
- }
-
- public (int score, int scoreDistinct) GetScore(Vec2 pos)
- {
- return GetScore(pos, []);
- }
-
- public (int score, int scoreDistinct) GetScore(Vec2 pos, HashSet> visited)
- {
- var curHeight = _data[pos.Y][pos.X];
- if (curHeight == 9)
- {
- if(visited.Contains(pos))
- return (0, 1);
- visited.Add(pos);
- return (1, 1);
- }
-
- var score = 0;
- var scoreDistinct = 0;
- foreach (var dir in DIRS)
- {
- var n = pos + dir;
- if (!IsInBounds(n))
- continue;
- var h = _data[n.Y][n.X];
- if (h - curHeight != 1)
- continue;
- var (s, d)= GetScore(n, visited);
- score += s;
- scoreDistinct += d;
- }
-
- return (score, scoreDistinct);
- }
-
- public bool IsInBounds(Vec2 pos)
- {
- if (pos.X < 0 || pos.Y < 0)
- return false;
- if(pos.X >= _data.Length || pos.Y >= _data[0].Length)
- return false;
- return true;
- }
-
- public override void LoadInput()
- {
- _data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
- }
-}
+using AdventOfCode.Utils.Models;
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AdventOfCode.Problems.AOC2024.Day10;
+[ProblemInfo(2024, 10, "Hoof It")]
+internal class HoofIt : Problem
+{
+ private int[][] _data = [];
+
+ public static Vec2[] DIRS = [
+ new(0, -1),
+ new(1, 0),
+ new(0, 1),
+ new(-1, 0),
+ ];
+
+ public override void CalculatePart1()
+ {
+ for (int y = 0; y < _data.Length; y++)
+ {
+ var row = _data[y];
+ for (int x = 0; x < row.Length; x++)
+ {
+ var h = row[x];
+ if (h != 0)
+ continue;
+ var (s,_) = GetScore(new(x, y));
+ Part1 += s;
+ }
+ }
+ }
+
+ public override void CalculatePart2()
+ {
+ for (int y = 0; y < _data.Length; y++)
+ {
+ var row = _data[y];
+ for (int x = 0; x < row.Length; x++)
+ {
+ var h = row[x];
+ if (h != 0)
+ continue;
+ var (_, s) = GetScore(new(x, y));
+ Part2 += s;
+ }
+ }
+ }
+
+ public (int score, int scoreDistinct) GetScore(Vec2 pos)
+ {
+ return GetScore(pos, []);
+ }
+
+ public (int score, int scoreDistinct) GetScore(Vec2 pos, HashSet> visited)
+ {
+ var curHeight = _data[pos.Y][pos.X];
+ if (curHeight == 9)
+ {
+ if(visited.Contains(pos))
+ return (0, 1);
+ visited.Add(pos);
+ return (1, 1);
+ }
+
+ var score = 0;
+ var scoreDistinct = 0;
+ foreach (var dir in DIRS)
+ {
+ var n = pos + dir;
+ if (!IsInBounds(n))
+ continue;
+ var h = _data[n.Y][n.X];
+ if (h - curHeight != 1)
+ continue;
+ var (s, d)= GetScore(n, visited);
+ score += s;
+ scoreDistinct += d;
+ }
+
+ return (score, scoreDistinct);
+ }
+
+ public bool IsInBounds(Vec2 pos)
+ {
+ if (pos.X < 0 || pos.Y < 0)
+ return false;
+ if(pos.X >= _data.Length || pos.Y >= _data[0].Length)
+ return false;
+ return true;
+ }
+
+ public override void LoadInput()
+ {
+ _data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
+ }
+}
diff --git a/AdventOfCode/Problems/AOC2024/Day11/PlutonianPebbles.cs b/AdventOfCode/Problems/AOC2024/Day11/PlutonianPebbles.cs
index af9c6ec..6531d8b 100644
--- a/AdventOfCode/Problems/AOC2024/Day11/PlutonianPebbles.cs
+++ b/AdventOfCode/Problems/AOC2024/Day11/PlutonianPebbles.cs
@@ -1,115 +1,115 @@
-using Superpower.Model;
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using static System.Runtime.InteropServices.JavaScript.JSType;
-
-namespace AdventOfCode.Problems.AOC2024.Day11;
-
-[ProblemInfo(2024, 11, "Plutonian Pebbles")]
-public class PlutonianPebbles : Problem
-{
- private List _data = [];
- private readonly Dictionary<(long, long), long> _depthLookup = [];
-
- public override void CalculatePart1()
- {
- Part1 = _data.Sum(v => ProcessStoneRecursive(v, 25));
- }
-
- public override void CalculatePart2()
- {
- Part2 = _data.Sum(v => ProcessStoneRecursive(v, 75));
- }
-
- public long ProcessStoneRecursive(long stone, long target, long curDepth = 0)
- {
- if (curDepth == target)
- return 1;
- var d = target - curDepth;
- if(_depthLookup.TryGetValue((stone, d), out var c))
- return c;
- long result;
- if (stone == 0)
- result = ProcessStoneRecursive(1, target, curDepth + 1);
- else if (FastSplit(stone, out var left, out var right))
- result = ProcessStoneRecursive(left, target, curDepth + 1) + ProcessStoneRecursive(right, target, curDepth + 1);
- else
- result = ProcessStoneRecursive(stone * 2024, target, curDepth + 1);
-
- _depthLookup.Add((stone, d), result);
- return result;
- }
-
- public long Run(long count)
- {
- var a = _data.ToList();
- var b = new List(a.Count);
- for (long i = 0; i < count; i++)
- {
- foreach (var stone in a)
- ProcessStone(stone, b);
-
- (a, b) = (b, a);
- b.Clear();
- }
- return a.Count;
- }
-
- public void ProcessStone(long stone, List data)
- {
- if (stone == 0)
- {
- data.Add(1);
- return;
- }
- if (FastSplit(stone, out var left, out var right))
- {
- data.Add(left);
- data.Add(right);
- return;
- }
- data.Add(stone * 2024);
- }
-
- private static IEnumerable