Aoc 2025 day 1
This commit is contained in:
126
.gitattributes
vendored
126
.gitattributes
vendored
@@ -1,63 +1,63 @@
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# Set default behavior to automatically normalize line endings.
|
# Set default behavior to automatically normalize line endings.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
* text=auto
|
* text=auto
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Set default behavior for command prompt diff.
|
# Set default behavior for command prompt diff.
|
||||||
#
|
#
|
||||||
# This is need for earlier builds of msysgit that does not have it on by
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
# default for csharp files.
|
# default for csharp files.
|
||||||
# Note: This is only used by command line
|
# Note: This is only used by command line
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#*.cs diff=csharp
|
#*.cs diff=csharp
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Set the merge driver for project and solution files
|
# Set the merge driver for project and solution files
|
||||||
#
|
#
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
# these files as binary and thus will always conflict and require user
|
# these files as binary and thus will always conflict and require user
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#*.sln merge=binary
|
#*.sln merge=binary
|
||||||
#*.csproj merge=binary
|
#*.csproj merge=binary
|
||||||
#*.vbproj merge=binary
|
#*.vbproj merge=binary
|
||||||
#*.vcxproj merge=binary
|
#*.vcxproj merge=binary
|
||||||
#*.vcproj merge=binary
|
#*.vcproj merge=binary
|
||||||
#*.dbproj merge=binary
|
#*.dbproj merge=binary
|
||||||
#*.fsproj merge=binary
|
#*.fsproj merge=binary
|
||||||
#*.lsproj merge=binary
|
#*.lsproj merge=binary
|
||||||
#*.wixproj merge=binary
|
#*.wixproj merge=binary
|
||||||
#*.modelproj merge=binary
|
#*.modelproj merge=binary
|
||||||
#*.sqlproj merge=binary
|
#*.sqlproj merge=binary
|
||||||
#*.wwaproj merge=binary
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# behavior for image files
|
# behavior for image files
|
||||||
#
|
#
|
||||||
# image files are treated as binary by default.
|
# image files are treated as binary by default.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#*.jpg binary
|
#*.jpg binary
|
||||||
#*.png binary
|
#*.png binary
|
||||||
#*.gif binary
|
#*.gif binary
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# diff behavior for common document formats
|
# diff behavior for common document formats
|
||||||
#
|
#
|
||||||
# Convert binary document formats to text before diffing them. This feature
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
# is only available from the command line. Turn it on by uncommenting the
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
# entries below.
|
# entries below.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#*.doc diff=astextplain
|
#*.doc diff=astextplain
|
||||||
#*.DOC diff=astextplain
|
#*.DOC diff=astextplain
|
||||||
#*.docx diff=astextplain
|
#*.docx diff=astextplain
|
||||||
#*.DOCX diff=astextplain
|
#*.DOCX diff=astextplain
|
||||||
#*.dot diff=astextplain
|
#*.dot diff=astextplain
|
||||||
#*.DOT diff=astextplain
|
#*.DOT diff=astextplain
|
||||||
#*.pdf diff=astextplain
|
#*.pdf diff=astextplain
|
||||||
#*.PDF diff=astextplain
|
#*.PDF diff=astextplain
|
||||||
#*.rtf diff=astextplain
|
#*.rtf diff=astextplain
|
||||||
#*.RTF diff=astextplain
|
#*.RTF diff=astextplain
|
||||||
|
|||||||
726
.gitignore
vendored
726
.gitignore
vendored
@@ -1,363 +1,363 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
##
|
##
|
||||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
*.rsuser
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
*.sln.docstates
|
*.sln.docstates
|
||||||
|
|
||||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
*.userprefs
|
*.userprefs
|
||||||
|
|
||||||
# Mono auto generated files
|
# Mono auto generated files
|
||||||
mono_crash.*
|
mono_crash.*
|
||||||
|
|
||||||
# Build results
|
# Build results
|
||||||
[Dd]ebug/
|
[Dd]ebug/
|
||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
[Ww][Ii][Nn]32/
|
[Ww][Ii][Nn]32/
|
||||||
[Aa][Rr][Mm]/
|
[Aa][Rr][Mm]/
|
||||||
[Aa][Rr][Mm]64/
|
[Aa][Rr][Mm]64/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
[Oo]ut/
|
[Oo]ut/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
[Ll]ogs/
|
[Ll]ogs/
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
#wwwroot/
|
#wwwroot/
|
||||||
|
|
||||||
# Visual Studio 2017 auto generated files
|
# Visual Studio 2017 auto generated files
|
||||||
Generated\ Files/
|
Generated\ Files/
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
[Bb]uild[Ll]og.*
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
# NUnit
|
# NUnit
|
||||||
*.VisualState.xml
|
*.VisualState.xml
|
||||||
TestResult.xml
|
TestResult.xml
|
||||||
nunit-*.xml
|
nunit-*.xml
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
# Build Results of an ATL Project
|
||||||
[Dd]ebugPS/
|
[Dd]ebugPS/
|
||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
dlldata.c
|
dlldata.c
|
||||||
|
|
||||||
# Benchmark Results
|
# Benchmark Results
|
||||||
BenchmarkDotNet.Artifacts/
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
# .NET Core
|
# .NET Core
|
||||||
project.lock.json
|
project.lock.json
|
||||||
project.fragment.lock.json
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
|
||||||
# ASP.NET Scaffolding
|
# ASP.NET Scaffolding
|
||||||
ScaffoldingReadMe.txt
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
# StyleCop
|
# StyleCop
|
||||||
StyleCopReport.xml
|
StyleCopReport.xml
|
||||||
|
|
||||||
# Files built by Visual Studio
|
# Files built by Visual Studio
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
*_h.h
|
*_h.h
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
*.iobj
|
*.iobj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
*.ipdb
|
*.ipdb
|
||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
*.sbr
|
*.sbr
|
||||||
*.tlb
|
*.tlb
|
||||||
*.tli
|
*.tli
|
||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
*_wpftmp.csproj
|
*_wpftmp.csproj
|
||||||
*.log
|
*.log
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
.builds
|
.builds
|
||||||
*.pidb
|
*.pidb
|
||||||
*.svclog
|
*.svclog
|
||||||
*.scc
|
*.scc
|
||||||
|
|
||||||
# Chutzpah Test files
|
# Chutzpah Test files
|
||||||
_Chutzpah*
|
_Chutzpah*
|
||||||
|
|
||||||
# Visual C++ cache files
|
# Visual C++ cache files
|
||||||
ipch/
|
ipch/
|
||||||
*.aps
|
*.aps
|
||||||
*.ncb
|
*.ncb
|
||||||
*.opendb
|
*.opendb
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
*.cachefile
|
*.cachefile
|
||||||
*.VC.db
|
*.VC.db
|
||||||
*.VC.VC.opendb
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
*.sap
|
*.sap
|
||||||
|
|
||||||
# Visual Studio Trace Files
|
# Visual Studio Trace Files
|
||||||
*.e2e
|
*.e2e
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
# TFS 2012 Local Workspace
|
||||||
$tf/
|
$tf/
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
# Guidance Automation Toolkit
|
||||||
*.gpState
|
*.gpState
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
# ReSharper is a .NET coding add-in
|
||||||
_ReSharper*/
|
_ReSharper*/
|
||||||
*.[Rr]e[Ss]harper
|
*.[Rr]e[Ss]harper
|
||||||
*.DotSettings.user
|
*.DotSettings.user
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
# TeamCity is a build add-in
|
||||||
_TeamCity*
|
_TeamCity*
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
# DotCover is a Code Coverage Tool
|
||||||
*.dotCover
|
*.dotCover
|
||||||
|
|
||||||
# AxoCover is a Code Coverage Tool
|
# AxoCover is a Code Coverage Tool
|
||||||
.axoCover/*
|
.axoCover/*
|
||||||
!.axoCover/settings.json
|
!.axoCover/settings.json
|
||||||
|
|
||||||
# Coverlet is a free, cross platform Code Coverage Tool
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
coverage*.json
|
coverage*.json
|
||||||
coverage*.xml
|
coverage*.xml
|
||||||
coverage*.info
|
coverage*.info
|
||||||
|
|
||||||
# Visual Studio code coverage results
|
# Visual Studio code coverage results
|
||||||
*.coverage
|
*.coverage
|
||||||
*.coveragexml
|
*.coveragexml
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
nCrunchTemp_*
|
nCrunchTemp_*
|
||||||
|
|
||||||
# MightyMoose
|
# MightyMoose
|
||||||
*.mm.*
|
*.mm.*
|
||||||
AutoTest.Net/
|
AutoTest.Net/
|
||||||
|
|
||||||
# Web workbench (sass)
|
# Web workbench (sass)
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
|
|
||||||
# Installshield output folder
|
# Installshield output folder
|
||||||
[Ee]xpress/
|
[Ee]xpress/
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
# DocProject is a documentation generator add-in
|
||||||
DocProject/buildhelp/
|
DocProject/buildhelp/
|
||||||
DocProject/Help/*.HxT
|
DocProject/Help/*.HxT
|
||||||
DocProject/Help/*.HxC
|
DocProject/Help/*.HxC
|
||||||
DocProject/Help/*.hhc
|
DocProject/Help/*.hhc
|
||||||
DocProject/Help/*.hhk
|
DocProject/Help/*.hhk
|
||||||
DocProject/Help/*.hhp
|
DocProject/Help/*.hhp
|
||||||
DocProject/Help/Html2
|
DocProject/Help/Html2
|
||||||
DocProject/Help/html
|
DocProject/Help/html
|
||||||
|
|
||||||
# Click-Once directory
|
# Click-Once directory
|
||||||
publish/
|
publish/
|
||||||
|
|
||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.[Pp]ublish.xml
|
*.[Pp]ublish.xml
|
||||||
*.azurePubxml
|
*.azurePubxml
|
||||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
*.pubxml
|
*.pubxml
|
||||||
*.publishproj
|
*.publishproj
|
||||||
|
|
||||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
# in these scripts will be unencrypted
|
# in these scripts will be unencrypted
|
||||||
PublishScripts/
|
PublishScripts/
|
||||||
|
|
||||||
# NuGet Packages
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# NuGet Symbol Packages
|
# NuGet Symbol Packages
|
||||||
*.snupkg
|
*.snupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
**/[Pp]ackages/*
|
**/[Pp]ackages/*
|
||||||
# except build/, which is used as an MSBuild target.
|
# except build/, which is used as an MSBuild target.
|
||||||
!**/[Pp]ackages/build/
|
!**/[Pp]ackages/build/
|
||||||
# Uncomment if necessary however generally it will be regenerated when needed
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
#!**/[Pp]ackages/repositories.config
|
#!**/[Pp]ackages/repositories.config
|
||||||
# NuGet v3's project.json files produces more ignorable files
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
*.nuget.props
|
*.nuget.props
|
||||||
*.nuget.targets
|
*.nuget.targets
|
||||||
|
|
||||||
# Microsoft Azure Build Output
|
# Microsoft Azure Build Output
|
||||||
csx/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
|
|
||||||
# Microsoft Azure Emulator
|
# Microsoft Azure Emulator
|
||||||
ecf/
|
ecf/
|
||||||
rcf/
|
rcf/
|
||||||
|
|
||||||
# Windows Store app package directories and files
|
# Windows Store app package directories and files
|
||||||
AppPackages/
|
AppPackages/
|
||||||
BundleArtifacts/
|
BundleArtifacts/
|
||||||
Package.StoreAssociation.xml
|
Package.StoreAssociation.xml
|
||||||
_pkginfo.txt
|
_pkginfo.txt
|
||||||
*.appx
|
*.appx
|
||||||
*.appxbundle
|
*.appxbundle
|
||||||
*.appxupload
|
*.appxupload
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
*.[Cc]ache
|
*.[Cc]ache
|
||||||
# but keep track of directories ending in .cache
|
# but keep track of directories ending in .cache
|
||||||
!?*.[Cc]ache/
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
ClientBin/
|
ClientBin/
|
||||||
~$*
|
~$*
|
||||||
*~
|
*~
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
*.jfm
|
*.jfm
|
||||||
*.pfx
|
*.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
orleans.codegen.cs
|
orleans.codegen.cs
|
||||||
|
|
||||||
# Including strong name files can present a security risk
|
# Including strong name files can present a security risk
|
||||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
#*.snk
|
#*.snk
|
||||||
|
|
||||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
#bower_components/
|
#bower_components/
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
# RIA/Silverlight projects
|
||||||
Generated_Code/
|
Generated_Code/
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
# Backup & report files from converting an old project file
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
# because we have git ;-)
|
# because we have git ;-)
|
||||||
_UpgradeReport_Files/
|
_UpgradeReport_Files/
|
||||||
Backup*/
|
Backup*/
|
||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
ServiceFabricBackup/
|
ServiceFabricBackup/
|
||||||
*.rptproj.bak
|
*.rptproj.bak
|
||||||
|
|
||||||
# SQL Server files
|
# SQL Server files
|
||||||
*.mdf
|
*.mdf
|
||||||
*.ldf
|
*.ldf
|
||||||
*.ndf
|
*.ndf
|
||||||
|
|
||||||
# Business Intelligence projects
|
# Business Intelligence projects
|
||||||
*.rdl.data
|
*.rdl.data
|
||||||
*.bim.layout
|
*.bim.layout
|
||||||
*.bim_*.settings
|
*.bim_*.settings
|
||||||
*.rptproj.rsuser
|
*.rptproj.rsuser
|
||||||
*- [Bb]ackup.rdl
|
*- [Bb]ackup.rdl
|
||||||
*- [Bb]ackup ([0-9]).rdl
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
# Microsoft Fakes
|
# Microsoft Fakes
|
||||||
FakesAssemblies/
|
FakesAssemblies/
|
||||||
|
|
||||||
# GhostDoc plugin setting file
|
# GhostDoc plugin setting file
|
||||||
*.GhostDoc.xml
|
*.GhostDoc.xml
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
.ntvs_analysis.dat
|
.ntvs_analysis.dat
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
# Visual Studio 6 build log
|
||||||
*.plg
|
*.plg
|
||||||
|
|
||||||
# Visual Studio 6 workspace options file
|
# Visual Studio 6 workspace options file
|
||||||
*.opt
|
*.opt
|
||||||
|
|
||||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
*.vbw
|
*.vbw
|
||||||
|
|
||||||
# Visual Studio LightSwitch build output
|
# Visual Studio LightSwitch build output
|
||||||
**/*.HTMLClient/GeneratedArtifacts
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/GeneratedArtifacts
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
**/*.DesktopClient/ModelManifest.xml
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
**/*.Server/GeneratedArtifacts
|
**/*.Server/GeneratedArtifacts
|
||||||
**/*.Server/ModelManifest.xml
|
**/*.Server/ModelManifest.xml
|
||||||
_Pvt_Extensions
|
_Pvt_Extensions
|
||||||
|
|
||||||
# Paket dependency manager
|
# Paket dependency manager
|
||||||
.paket/paket.exe
|
.paket/paket.exe
|
||||||
paket-files/
|
paket-files/
|
||||||
|
|
||||||
# FAKE - F# Make
|
# FAKE - F# Make
|
||||||
.fake/
|
.fake/
|
||||||
|
|
||||||
# CodeRush personal settings
|
# CodeRush personal settings
|
||||||
.cr/personal
|
.cr/personal
|
||||||
|
|
||||||
# Python Tools for Visual Studio (PTVS)
|
# Python Tools for Visual Studio (PTVS)
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
# Cake - Uncomment if you are using it
|
# Cake - Uncomment if you are using it
|
||||||
# tools/**
|
# tools/**
|
||||||
# !tools/packages.config
|
# !tools/packages.config
|
||||||
|
|
||||||
# Tabs Studio
|
# Tabs Studio
|
||||||
*.tss
|
*.tss
|
||||||
|
|
||||||
# Telerik's JustMock configuration file
|
# Telerik's JustMock configuration file
|
||||||
*.jmconfig
|
*.jmconfig
|
||||||
|
|
||||||
# BizTalk build output
|
# BizTalk build output
|
||||||
*.btp.cs
|
*.btp.cs
|
||||||
*.btm.cs
|
*.btm.cs
|
||||||
*.odx.cs
|
*.odx.cs
|
||||||
*.xsd.cs
|
*.xsd.cs
|
||||||
|
|
||||||
# OpenCover UI analysis results
|
# OpenCover UI analysis results
|
||||||
OpenCover/
|
OpenCover/
|
||||||
|
|
||||||
# Azure Stream Analytics local run output
|
# Azure Stream Analytics local run output
|
||||||
ASALocalRun/
|
ASALocalRun/
|
||||||
|
|
||||||
# MSBuild Binary and Structured Log
|
# MSBuild Binary and Structured Log
|
||||||
*.binlog
|
*.binlog
|
||||||
|
|
||||||
# NVidia Nsight GPU debugger configuration file
|
# NVidia Nsight GPU debugger configuration file
|
||||||
*.nvuser
|
*.nvuser
|
||||||
|
|
||||||
# MFractors (Xamarin productivity tool) working folder
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
.mfractor/
|
.mfractor/
|
||||||
|
|
||||||
# Local History for Visual Studio
|
# Local History for Visual Studio
|
||||||
.localhistory/
|
.localhistory/
|
||||||
|
|
||||||
# BeatPulse healthcheck temp database
|
# BeatPulse healthcheck temp database
|
||||||
healthchecksdb
|
healthchecksdb
|
||||||
|
|
||||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
MigrationBackup/
|
MigrationBackup/
|
||||||
|
|
||||||
# Ionide (cross platform F# VS Code tools) working folder
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
.ionide/
|
.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.4.33110.190
|
VisualStudioVersion = 17.4.33110.190
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdventOfCode", "AdventOfCode\AdventOfCode.csproj", "{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CAAB9EC2-0787-4CBC-87E3-4529BFB56B3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
|
SolutionGuid = {1FDE3D49-4BB6-48E2-B2CE-617A7B97684B}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@@ -1,81 +1,83 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Problems\*\*\*.txt">
|
<EmbeddedResource Include="Problems\*\*\*.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Problems\*\*\*.csv">
|
<EmbeddedResource Include="Problems\*\*\*.csv">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Problems\AOC2022\Day10\input.txt" />
|
<None Remove="Problems\AOC2022\Day10\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day10\sara.txt" />
|
<None Remove="Problems\AOC2022\Day10\sara.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day10\simple.txt" />
|
<None Remove="Problems\AOC2022\Day10\simple.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day10\test.txt" />
|
<None Remove="Problems\AOC2022\Day10\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day11\input.txt" />
|
<None Remove="Problems\AOC2022\Day11\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day11\test.txt" />
|
<None Remove="Problems\AOC2022\Day11\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day3\input.txt" />
|
<None Remove="Problems\AOC2022\Day3\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day3\test.txt" />
|
<None Remove="Problems\AOC2022\Day3\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day4\input.txt" />
|
<None Remove="Problems\AOC2022\Day4\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day4\test.txt" />
|
<None Remove="Problems\AOC2022\Day4\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day5\input.txt" />
|
<None Remove="Problems\AOC2022\Day5\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day5\test.txt" />
|
<None Remove="Problems\AOC2022\Day5\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day6\input.txt" />
|
<None Remove="Problems\AOC2022\Day6\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day6\test.txt" />
|
<None Remove="Problems\AOC2022\Day6\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day8\input.txt" />
|
<None Remove="Problems\AOC2022\Day8\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day8\test.txt" />
|
<None Remove="Problems\AOC2022\Day8\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day9\input.txt" />
|
<None Remove="Problems\AOC2022\Day9\input.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day9\test.txt" />
|
<None Remove="Problems\AOC2022\Day9\test.txt" />
|
||||||
<None Remove="Problems\AOC2022\Day9\test2.txt" />
|
<None Remove="Problems\AOC2022\Day9\test2.txt" />
|
||||||
<None Remove="problems\aoc2023\day10\input.txt" />
|
<None Remove="problems\aoc2023\day10\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day10\sample.txt" />
|
<None Remove="problems\aoc2023\day10\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day11\input.txt" />
|
<None Remove="problems\aoc2023\day11\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day11\sample.txt" />
|
<None Remove="problems\aoc2023\day11\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day12\input.txt" />
|
<None Remove="problems\aoc2023\day12\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day12\sample.txt" />
|
<None Remove="problems\aoc2023\day12\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day1\input.txt" />
|
<None Remove="problems\aoc2023\day1\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day2\input.txt" />
|
<None Remove="problems\aoc2023\day2\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day3\input.txt" />
|
<None Remove="problems\aoc2023\day3\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day3\sample.txt" />
|
<None Remove="problems\aoc2023\day3\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day3\sara.txt" />
|
<None Remove="problems\aoc2023\day3\sara.txt" />
|
||||||
<None Remove="problems\aoc2023\day4\input.txt" />
|
<None Remove="problems\aoc2023\day4\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day4\sample.txt" />
|
<None Remove="problems\aoc2023\day4\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day5\input.txt" />
|
<None Remove="problems\aoc2023\day5\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day5\sample.txt" />
|
<None Remove="problems\aoc2023\day5\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day6\input.txt" />
|
<None Remove="problems\aoc2023\day6\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day6\sample.txt" />
|
<None Remove="problems\aoc2023\day6\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day7\input.txt" />
|
<None Remove="problems\aoc2023\day7\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day7\sample.txt" />
|
<None Remove="problems\aoc2023\day7\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day7\sara.txt" />
|
<None Remove="problems\aoc2023\day7\sara.txt" />
|
||||||
<None Remove="problems\aoc2023\day8\input.txt" />
|
<None Remove="problems\aoc2023\day8\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day8\sample.txt" />
|
<None Remove="problems\aoc2023\day8\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day9\input.txt" />
|
<None Remove="problems\aoc2023\day9\input.txt" />
|
||||||
<None Remove="problems\aoc2023\day9\sample.txt" />
|
<None Remove="problems\aoc2023\day9\sample.txt" />
|
||||||
<None Remove="problems\aoc2023\day9\sara.txt" />
|
<None Remove="problems\aoc2023\day9\sara.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Problems\AOC2015\" />
|
<Folder Include="Problems\AOC2015\" />
|
||||||
<Folder Include="Problems\AOC2021\" />
|
<Folder Include="Problems\AOC2021\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Superpower" Version="3.0.0" />
|
<PackageReference Include="MaybeError" Version="1.2.0" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Superpower" Version="3.1.1-dev-00257" />
|
||||||
</Project>
|
<PackageReference Include="ZLinq" Version="1.5.4" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|||||||
2
AdventOfCode/Problems/.gitignore
vendored
2
AdventOfCode/Problems/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
*/*/*.txt
|
*/*/*.txt
|
||||||
*/*/*.csv
|
*/*/*.csv
|
||||||
@@ -1,58 +1,58 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2015.Day10;
|
namespace AdventOfCode.Problems.AOC2015.Day10;
|
||||||
|
|
||||||
[ProblemInfo(2015, 10, "Evles Look, Elves Say")]
|
[ProblemInfo(2015, 10, "Evles Look, Elves Say")]
|
||||||
internal class LookAndSay : Problem<int, int>
|
internal class LookAndSay : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string _input = string.Empty;
|
private string _input = string.Empty;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = Run(40);
|
Part1 = Run(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = Run(50);
|
Part2 = Run(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_input = "3113322113";
|
_input = "3113322113";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Run(int iter)
|
public int Run(int iter)
|
||||||
{
|
{
|
||||||
var value = new StringBuilder(_input);
|
var value = new StringBuilder(_input);
|
||||||
for (int i = 0; i < iter; i++)
|
for (int i = 0; i < iter; i++)
|
||||||
CalculateNext(ref value);
|
CalculateNext(ref value);
|
||||||
|
|
||||||
return value.Length;
|
return value.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CalculateNext(ref StringBuilder input)
|
private static void CalculateNext(ref StringBuilder input)
|
||||||
{
|
{
|
||||||
var next = new StringBuilder();
|
var next = new StringBuilder();
|
||||||
var len = input.Length;
|
var len = input.Length;
|
||||||
var curCount = 1;
|
var curCount = 1;
|
||||||
var curChar = input[0];
|
var curChar = input[0];
|
||||||
for (int i = 1; i < len; i++)
|
for (int i = 1; i < len; i++)
|
||||||
{
|
{
|
||||||
var c = input[i];
|
var c = input[i];
|
||||||
if (c != curChar)
|
if (c != curChar)
|
||||||
{
|
{
|
||||||
next.Append(curCount).Append(curChar);
|
next.Append(curCount).Append(curChar);
|
||||||
curChar = c;
|
curChar = c;
|
||||||
curCount = 1;
|
curCount = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curCount++;
|
curCount++;
|
||||||
}
|
}
|
||||||
next.Append(curCount).Append(curChar);
|
next.Append(curCount).Append(curChar);
|
||||||
|
|
||||||
input = next;
|
input = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,110 +1,110 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2015.Day5;
|
namespace AdventOfCode.Problems.AOC2015.Day5;
|
||||||
|
|
||||||
[ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")]
|
[ProblemInfo(2015, 5, "Doesn't He Have Intern-Elves For This?")]
|
||||||
public class NiceList : Problem<int, int>
|
public class NiceList : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _inputData = Array.Empty<string>();
|
private string[] _inputData = Array.Empty<string>();
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_inputData = ReadInputLines();
|
_inputData = ReadInputLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _inputData.Length; i++)
|
for (int i = 0; i < _inputData.Length; i++)
|
||||||
{
|
{
|
||||||
if (IsNice(_inputData[i]))
|
if (IsNice(_inputData[i]))
|
||||||
Part1++;
|
Part1++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _inputData.Length; i++)
|
for (int i = 0; i < _inputData.Length; i++)
|
||||||
{
|
{
|
||||||
if (IsNice2(_inputData[i]))
|
if (IsNice2(_inputData[i]))
|
||||||
{
|
{
|
||||||
Part2++;
|
Part2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsNice2(string value)
|
private static bool IsNice2(string value)
|
||||||
{
|
{
|
||||||
var pairs = new Dictionary<string, List<int>>();
|
var pairs = new Dictionary<string, List<int>>();
|
||||||
var separatedPair = false;
|
var separatedPair = false;
|
||||||
|
|
||||||
for (int i = 1; i < value.Length; i++)
|
for (int i = 1; i < value.Length; i++)
|
||||||
{
|
{
|
||||||
var c = value[i];
|
var c = value[i];
|
||||||
var curIndex = i - 1;
|
var curIndex = i - 1;
|
||||||
var pair = value[curIndex..(i + 1)];
|
var pair = value[curIndex..(i + 1)];
|
||||||
if (pairs.ContainsKey(pair))
|
if (pairs.ContainsKey(pair))
|
||||||
{
|
{
|
||||||
if (pairs[pair].Contains(curIndex - 1))
|
if (pairs[pair].Contains(curIndex - 1))
|
||||||
continue;
|
continue;
|
||||||
pairs[pair].Add(curIndex);
|
pairs[pair].Add(curIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pairs.Add(pair, new List<int>() { curIndex });
|
pairs.Add(pair, new List<int>() { curIndex });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
continue;
|
continue;
|
||||||
if (value[i - 2] == c)
|
if (value[i - 2] == c)
|
||||||
separatedPair = true;
|
separatedPair = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return separatedPair && pairs.Any(p => p.Value.Count >= 2);
|
return separatedPair && pairs.Any(p => p.Value.Count >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsNice(string value)
|
private static bool IsNice(string value)
|
||||||
{
|
{
|
||||||
var vowelCount = 0;
|
var vowelCount = 0;
|
||||||
var doubleLetters = false;
|
var doubleLetters = false;
|
||||||
for (int i = 0; i < value.Length; i++)
|
for (int i = 0; i < value.Length; i++)
|
||||||
{
|
{
|
||||||
char c = value[i];
|
char c = value[i];
|
||||||
if (IsVowel(c))
|
if (IsVowel(c))
|
||||||
vowelCount++;
|
vowelCount++;
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
var lastChar = value[i - 1];
|
var lastChar = value[i - 1];
|
||||||
if (IsIllegal(c, lastChar))
|
if (IsIllegal(c, lastChar))
|
||||||
return false;
|
return false;
|
||||||
if (IsDouble(c, lastChar))
|
if (IsDouble(c, lastChar))
|
||||||
doubleLetters = true;
|
doubleLetters = true;
|
||||||
}
|
}
|
||||||
return doubleLetters && vowelCount >= 3;
|
return doubleLetters && vowelCount >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsVowel(char c)
|
private static bool IsVowel(char c)
|
||||||
{
|
{
|
||||||
return c switch
|
return c switch
|
||||||
{
|
{
|
||||||
'a' or 'e' or 'i' or 'o' or 'u' => true,
|
'a' or 'e' or 'i' or 'o' or 'u' => true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsDouble(char c, char lastChar)
|
private static bool IsDouble(char c, char lastChar)
|
||||||
{
|
{
|
||||||
return c == lastChar;
|
return c == lastChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsIllegal(char c, char lastChar)
|
private static bool IsIllegal(char c, char lastChar)
|
||||||
{
|
{
|
||||||
return (lastChar, c) switch
|
return (lastChar, c) switch
|
||||||
{
|
{
|
||||||
('a', 'b') => true,
|
('a', 'b') => true,
|
||||||
('c', 'd') => true,
|
('c', 'd') => true,
|
||||||
('p', 'q') => true,
|
('p', 'q') => true,
|
||||||
('x', 'y') => true,
|
('x', 'y') => true,
|
||||||
_ => false
|
_ => false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,41 +1,41 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day1
|
namespace AdventOfCode.Problems.AOC2019.Day1
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")]
|
[ProblemInfo(2019, 1, "The Tyranny of the Rocket Equation")]
|
||||||
public class FuelCaluclation : Problem<int, int>
|
public class FuelCaluclation : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[] _input = Array.Empty<int>();
|
private int[] _input = Array.Empty<int>();
|
||||||
|
|
||||||
public static int GetFuelRequirement(int[] input)
|
public static int GetFuelRequirement(int[] input)
|
||||||
{
|
{
|
||||||
var curFuel = input.Sum(i => GetFuelCost(i));
|
var curFuel = input.Sum(i => GetFuelCost(i));
|
||||||
return curFuel;
|
return curFuel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetFuelCost(int mass)
|
public static int GetFuelCost(int mass)
|
||||||
{
|
{
|
||||||
var curCost = mass / 3 - 2;
|
var curCost = mass / 3 - 2;
|
||||||
if (curCost <= 0)
|
if (curCost <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
return curCost + GetFuelCost(curCost);
|
return curCost + GetFuelCost(curCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetCost(int mass) => mass / 3 - 2;
|
public static int GetCost(int mass) => mass / 3 - 2;
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_input = InputParsing.ParseIntArray(GetInputFile());
|
_input = InputParsing.ParseIntArray(GetInputFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _input.Sum(i => GetCost(i));
|
Part1 = _input.Sum(i => GetCost(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = GetFuelRequirement(_input);
|
Part2 = GetFuelRequirement(_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,72 +1,72 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day2
|
namespace AdventOfCode.Problems.AOC2019.Day2
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 2, "Program Alarm")]
|
[ProblemInfo(2019, 2, "Program Alarm")]
|
||||||
public class IntCode : Problem<int, int>
|
public class IntCode : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[] _inputPart1 = Array.Empty<int>();
|
private int[] _inputPart1 = Array.Empty<int>();
|
||||||
private int[] _inputPart2 = Array.Empty<int>();
|
private int[] _inputPart2 = Array.Empty<int>();
|
||||||
|
|
||||||
public static int ExecuteCode(int[] code, int noun, int verb)
|
public static int ExecuteCode(int[] code, int noun, int verb)
|
||||||
{
|
{
|
||||||
int[] memory = code;
|
int[] memory = code;
|
||||||
memory[1] = noun;
|
memory[1] = noun;
|
||||||
memory[2] = verb;
|
memory[2] = verb;
|
||||||
var curAddr = 0;
|
var curAddr = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var opCode = memory[curAddr];
|
var opCode = memory[curAddr];
|
||||||
|
|
||||||
if (opCode == 99) //Halt
|
if (opCode == 99) //Halt
|
||||||
return memory[0];
|
return memory[0];
|
||||||
|
|
||||||
//Working Adresses
|
//Working Adresses
|
||||||
int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3];
|
int a = memory[curAddr + 1], b = memory[curAddr + 2], c = memory[curAddr + 3];
|
||||||
|
|
||||||
if (a > memory.Length || b > memory.Length || c > memory.Length)
|
if (a > memory.Length || b > memory.Length || c > memory.Length)
|
||||||
{
|
{
|
||||||
Console.WriteLine("ERROR: Out of Bounds");
|
Console.WriteLine("ERROR: Out of Bounds");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opCode == 1) //Add
|
if (opCode == 1) //Add
|
||||||
memory[c] = memory[a] + memory[b];
|
memory[c] = memory[a] + memory[b];
|
||||||
if (opCode == 2) //Multiply
|
if (opCode == 2) //Multiply
|
||||||
memory[c] = memory[a] * memory[b];
|
memory[c] = memory[a] * memory[b];
|
||||||
|
|
||||||
curAddr += 4;
|
curAddr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
_inputPart1 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
||||||
_inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
_inputPart2 = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = ExecuteCode(_inputPart1, 12, 2);
|
Part1 = ExecuteCode(_inputPart1, 12, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
int targetOutput = 19690720;
|
int targetOutput = 19690720;
|
||||||
for (int n = 0; n < 100; n++)
|
for (int n = 0; n < 100; n++)
|
||||||
{
|
{
|
||||||
for (int v = 0; v < 100; v++)
|
for (int v = 0; v < 100; v++)
|
||||||
{
|
{
|
||||||
var curInput = new int[_inputPart2.Length];
|
var curInput = new int[_inputPart2.Length];
|
||||||
Array.Copy(_inputPart2, curInput, _inputPart2.Length);
|
Array.Copy(_inputPart2, curInput, _inputPart2.Length);
|
||||||
if (ExecuteCode(curInput, n, v) == targetOutput)
|
if (ExecuteCode(curInput, n, v) == targetOutput)
|
||||||
{
|
{
|
||||||
Part2 = 100 * n + v;
|
Part2 = 100 * n + v;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,319 +1,319 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day3
|
namespace AdventOfCode.Problems.AOC2019.Day3
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 3, "Crossed Wires")]
|
[ProblemInfo(2019, 3, "Crossed Wires")]
|
||||||
public class CrossedWires : Problem<int, int>
|
public class CrossedWires : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _inputLines = Array.Empty<string>();
|
private string[] _inputLines = Array.Empty<string>();
|
||||||
|
|
||||||
public struct WireSegment
|
public struct WireSegment
|
||||||
{
|
{
|
||||||
public Point min, max;
|
public Point min, max;
|
||||||
public Point start, end;
|
public Point start, end;
|
||||||
|
|
||||||
public int Length;
|
public int Length;
|
||||||
|
|
||||||
public bool Vertical => min.X == max.X;
|
public bool Vertical => min.X == max.X;
|
||||||
|
|
||||||
public WireSegment(Point a, Point b)
|
public WireSegment(Point a, Point b)
|
||||||
{
|
{
|
||||||
start = a;
|
start = a;
|
||||||
end = b;
|
end = b;
|
||||||
if (a.X == b.X) //Vertical
|
if (a.X == b.X) //Vertical
|
||||||
{
|
{
|
||||||
if (a.Y < b.Y)
|
if (a.Y < b.Y)
|
||||||
{
|
{
|
||||||
min = a;
|
min = a;
|
||||||
max = b;
|
max = b;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
min = b;
|
min = b;
|
||||||
max = a;
|
max = a;
|
||||||
}
|
}
|
||||||
Length = Math.Abs(b.Y - a.Y);
|
Length = Math.Abs(b.Y - a.Y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (a.X < b.X)
|
if (a.X < b.X)
|
||||||
{
|
{
|
||||||
min = a;
|
min = a;
|
||||||
max = b;
|
max = b;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
min = b;
|
min = b;
|
||||||
max = a;
|
max = a;
|
||||||
}
|
}
|
||||||
Length = Math.Abs(b.X - a.X);
|
Length = Math.Abs(b.X - a.X);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WireSegment CreateRelative(Point offset)
|
public WireSegment CreateRelative(Point offset)
|
||||||
{
|
{
|
||||||
return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y));
|
return new WireSegment(end, new Point(end.X + offset.X, end.Y + offset.Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsPoint(Point point)
|
public bool ContainsPoint(Point point)
|
||||||
{
|
{
|
||||||
if (Vertical)
|
if (Vertical)
|
||||||
{
|
{
|
||||||
if (min.X == point.X)
|
if (min.X == point.X)
|
||||||
{
|
{
|
||||||
return min.Y <= point.Y && max.Y >= point.Y;
|
return min.Y <= point.Y && max.Y >= point.Y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (min.Y == point.Y)
|
if (min.Y == point.Y)
|
||||||
{
|
{
|
||||||
return min.X <= point.X && max.X >= point.X;
|
return min.X <= point.X && max.X >= point.X;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains(WireSegment other)
|
public bool Contains(WireSegment other)
|
||||||
{
|
{
|
||||||
if (Vertical != other.Vertical)
|
if (Vertical != other.Vertical)
|
||||||
return false;
|
return false;
|
||||||
if (Vertical)
|
if (Vertical)
|
||||||
{
|
{
|
||||||
return min.Y <= other.min.Y && max.Y >= other.max.Y;
|
return min.Y <= other.min.Y && max.Y >= other.max.Y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return min.X <= other.min.X && max.X >= other.max.X;
|
return min.X <= other.min.X && max.X >= other.max.X;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WireSegment GetOverlap(WireSegment other)
|
public WireSegment GetOverlap(WireSegment other)
|
||||||
{
|
{
|
||||||
if (Vertical)
|
if (Vertical)
|
||||||
{
|
{
|
||||||
if (other.Contains(this))
|
if (other.Contains(this))
|
||||||
return this;
|
return this;
|
||||||
else if (Contains(other))
|
else if (Contains(other))
|
||||||
return other;
|
return other;
|
||||||
if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y)
|
if (max.Y >= other.min.Y && min.Y <= other.min.Y && max.Y <= other.max.Y)
|
||||||
{
|
{
|
||||||
return new WireSegment(other.min, max);
|
return new WireSegment(other.min, max);
|
||||||
}
|
}
|
||||||
else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y)
|
else if (max.Y >= other.max.Y && min.Y >= other.min.Y && min.Y <= other.max.Y)
|
||||||
return new WireSegment(min, other.max);
|
return new WireSegment(min, other.max);
|
||||||
else
|
else
|
||||||
throw new Exception("No Overlap");
|
throw new Exception("No Overlap");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (other.Contains(this))
|
if (other.Contains(this))
|
||||||
return this;
|
return this;
|
||||||
else if (Contains(other))
|
else if (Contains(other))
|
||||||
return other;
|
return other;
|
||||||
if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X)
|
if (max.X >= other.min.X && min.X <= other.min.X && max.X <= other.max.X)
|
||||||
{
|
{
|
||||||
return new WireSegment(other.min, max);
|
return new WireSegment(other.min, max);
|
||||||
}
|
}
|
||||||
else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X)
|
else if (max.X >= other.max.X && min.X >= other.min.X && min.X <= other.max.X)
|
||||||
return new WireSegment(min, other.max);
|
return new WireSegment(min, other.max);
|
||||||
else
|
else
|
||||||
throw new Exception("No Overlap");
|
throw new Exception("No Overlap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Intersect(WireSegment other, out Point intersection)
|
public bool Intersect(WireSegment other, out Point intersection)
|
||||||
{
|
{
|
||||||
if (Vertical)
|
if (Vertical)
|
||||||
{
|
{
|
||||||
if (!other.Vertical)//Other Horizontal
|
if (!other.Vertical)//Other Horizontal
|
||||||
{
|
{
|
||||||
var potInt = new Point(min.X, other.min.Y);
|
var potInt = new Point(min.X, other.min.Y);
|
||||||
if (potInt == default)
|
if (potInt == default)
|
||||||
{
|
{
|
||||||
intersection = default;
|
intersection = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ContainsPoint(potInt) && other.ContainsPoint(potInt))
|
if (ContainsPoint(potInt) && other.ContainsPoint(potInt))
|
||||||
{
|
{
|
||||||
intersection = potInt;
|
intersection = potInt;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
intersection = default;
|
intersection = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //Both
|
else //Both
|
||||||
{
|
{
|
||||||
if (min.X != other.min.X)
|
if (min.X != other.min.X)
|
||||||
{
|
{
|
||||||
intersection = default;
|
intersection = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var overlap = GetOverlap(other);
|
var overlap = GetOverlap(other);
|
||||||
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
|
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
|
||||||
intersection = overlap.min == default ? overlap.max : overlap.min;
|
intersection = overlap.min == default ? overlap.max : overlap.min;
|
||||||
else
|
else
|
||||||
intersection = overlap.max == default ? overlap.min : overlap.max;
|
intersection = overlap.max == default ? overlap.min : overlap.max;
|
||||||
if (intersection == default)
|
if (intersection == default)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!other.Vertical) //Other Horizontal
|
if (!other.Vertical) //Other Horizontal
|
||||||
{
|
{
|
||||||
if (min.Y != other.min.Y)
|
if (min.Y != other.min.Y)
|
||||||
{
|
{
|
||||||
intersection = default;
|
intersection = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var overlap = GetOverlap(other);
|
var overlap = GetOverlap(other);
|
||||||
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
|
if (ManhattanMagnitude(overlap.min) < ManhattanMagnitude(overlap.max))
|
||||||
intersection = overlap.min == default ? overlap.max : overlap.min;
|
intersection = overlap.min == default ? overlap.max : overlap.min;
|
||||||
else
|
else
|
||||||
intersection = overlap.max == default ? overlap.min : overlap.max;
|
intersection = overlap.max == default ? overlap.min : overlap.max;
|
||||||
if (intersection == default)
|
if (intersection == default)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return other.Intersect(this, out intersection);
|
return other.Intersect(this, out intersection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{start} > {end}";
|
return $"{start} > {end}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int StepsToPoint(List<WireSegment> wires, Point p)
|
public static int StepsToPoint(List<WireSegment> wires, Point p)
|
||||||
{
|
{
|
||||||
var steps = 0;
|
var steps = 0;
|
||||||
for (int i = 0; i < wires.Count; i++)
|
for (int i = 0; i < wires.Count; i++)
|
||||||
{
|
{
|
||||||
if (wires[i].ContainsPoint(p))
|
if (wires[i].ContainsPoint(p))
|
||||||
{
|
{
|
||||||
if (wires[i].Vertical)
|
if (wires[i].Vertical)
|
||||||
steps += Math.Abs(wires[i].start.Y - p.Y);
|
steps += Math.Abs(wires[i].start.Y - p.Y);
|
||||||
else
|
else
|
||||||
steps += Math.Abs(wires[i].start.X - p.X);
|
steps += Math.Abs(wires[i].start.X - p.X);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
steps += wires[i].Length;
|
steps += wires[i].Length;
|
||||||
}
|
}
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int SolveWires(string[] wires)
|
public static int SolveWires(string[] wires)
|
||||||
{
|
{
|
||||||
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
|
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
|
||||||
|
|
||||||
int shortestWire = int.MaxValue;
|
int shortestWire = int.MaxValue;
|
||||||
for (int i = 0; i < wireSegmentsA.Count; i++)
|
for (int i = 0; i < wireSegmentsA.Count; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < wireSegmentsB.Count; j++)
|
for (int j = 0; j < wireSegmentsB.Count; j++)
|
||||||
{
|
{
|
||||||
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
|
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
|
||||||
{
|
{
|
||||||
var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection);
|
var len = StepsToPoint(wireSegmentsA, intersection) + StepsToPoint(wireSegmentsB, intersection);
|
||||||
if (len < shortestWire)
|
if (len < shortestWire)
|
||||||
shortestWire = len;
|
shortestWire = len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shortestWire;
|
return shortestWire;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int SolveClosestDistane(string[] wires)
|
public static int SolveClosestDistane(string[] wires)
|
||||||
{
|
{
|
||||||
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
|
var (wireSegmentsA, wireSegmentsB) = CreateWirePair(wires);
|
||||||
|
|
||||||
int lastIntersection = int.MaxValue;
|
int lastIntersection = int.MaxValue;
|
||||||
for (int i = 0; i < wireSegmentsA.Count; i++)
|
for (int i = 0; i < wireSegmentsA.Count; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < wireSegmentsB.Count; j++)
|
for (int j = 0; j < wireSegmentsB.Count; j++)
|
||||||
{
|
{
|
||||||
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
|
if (wireSegmentsA[i].Intersect(wireSegmentsB[j], out var intersection))
|
||||||
{
|
{
|
||||||
var dist = ManhattanMagnitude(intersection);
|
var dist = ManhattanMagnitude(intersection);
|
||||||
if (dist < lastIntersection)
|
if (dist < lastIntersection)
|
||||||
lastIntersection = dist;
|
lastIntersection = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lastIntersection;
|
return lastIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (List<WireSegment> A, List<WireSegment> B) CreateWirePair(string[] wires)
|
private static (List<WireSegment> A, List<WireSegment> B) CreateWirePair(string[] wires)
|
||||||
{
|
{
|
||||||
var wireA = wires[0].Split(',');
|
var wireA = wires[0].Split(',');
|
||||||
var wireSegmentsA = CreateWire(wireA);
|
var wireSegmentsA = CreateWire(wireA);
|
||||||
|
|
||||||
var wireB = wires[1].Split(',');
|
var wireB = wires[1].Split(',');
|
||||||
var wireSegmentsB = CreateWire(wireB);
|
var wireSegmentsB = CreateWire(wireB);
|
||||||
|
|
||||||
return (wireSegmentsA, wireSegmentsB);
|
return (wireSegmentsA, wireSegmentsB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<WireSegment> CreateWire(string[] wires)
|
private static List<WireSegment> CreateWire(string[] wires)
|
||||||
{
|
{
|
||||||
var wireSegments = new List<WireSegment>();
|
var wireSegments = new List<WireSegment>();
|
||||||
|
|
||||||
for (int i = 0; i < wires.Length; i++)
|
for (int i = 0; i < wires.Length; i++)
|
||||||
{
|
{
|
||||||
var curSegment = wires[i];
|
var curSegment = wires[i];
|
||||||
var offset = GetOffset(curSegment);
|
var offset = GetOffset(curSegment);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
wireSegments.Add(new WireSegment(new Point(0, 0), offset));
|
wireSegments.Add(new WireSegment(new Point(0, 0), offset));
|
||||||
else
|
else
|
||||||
wireSegments.Add(wireSegments.Last().CreateRelative(offset));
|
wireSegments.Add(wireSegments.Last().CreateRelative(offset));
|
||||||
}
|
}
|
||||||
return wireSegments;
|
return wireSegments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y);
|
public static int ManhattanMagnitude(Point point) => Math.Abs(point.X) + Math.Abs(point.Y);
|
||||||
|
|
||||||
public static Point GetOffset(string move)
|
public static Point GetOffset(string move)
|
||||||
{
|
{
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
if (move[0] == 'R')
|
if (move[0] == 'R')
|
||||||
x = int.Parse(move.Remove(0, 1));
|
x = int.Parse(move.Remove(0, 1));
|
||||||
else if (move[0] == 'L')
|
else if (move[0] == 'L')
|
||||||
x = -int.Parse(move.Remove(0, 1));
|
x = -int.Parse(move.Remove(0, 1));
|
||||||
else if (move[0] == 'U')
|
else if (move[0] == 'U')
|
||||||
y = int.Parse(move.Remove(0, 1));
|
y = int.Parse(move.Remove(0, 1));
|
||||||
else if (move[0] == 'D')
|
else if (move[0] == 'D')
|
||||||
y = -int.Parse(move.Remove(0, 1));
|
y = -int.Parse(move.Remove(0, 1));
|
||||||
return new Point(x, y);
|
return new Point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_inputLines = ReadInputLines();
|
_inputLines = ReadInputLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = SolveClosestDistane(_inputLines);
|
Part1 = SolveClosestDistane(_inputLines);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = SolveWires(_inputLines);
|
Part2 = SolveWires(_inputLines);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,147 +1,147 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day4
|
namespace AdventOfCode.Problems.AOC2019.Day4
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 4, "Secure Container")]
|
[ProblemInfo(2019, 4, "Secure Container")]
|
||||||
public class SecureContainer : Problem<int, int>
|
public class SecureContainer : Problem<int, int>
|
||||||
{
|
{
|
||||||
public static bool IsValidPassword(int[] password)
|
public static bool IsValidPassword(int[] password)
|
||||||
{
|
{
|
||||||
if (password.Length != 6)
|
if (password.Length != 6)
|
||||||
return false;
|
return false;
|
||||||
return HasRepeating(password) && IsAssending(password);
|
return HasRepeating(password) && IsAssending(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasRepeating(int[] password)
|
public static bool HasRepeating(int[] password)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < password.Length - 1; i++)
|
for (int i = 0; i < password.Length - 1; i++)
|
||||||
{
|
{
|
||||||
if (password[i] == password[i + 1])
|
if (password[i] == password[i + 1])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasDoubles(int[] password)
|
public static bool HasDoubles(int[] password)
|
||||||
{
|
{
|
||||||
bool foundDouble = false;
|
bool foundDouble = false;
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (int j = 0; j < 6; j++)
|
for (int j = 0; j < 6; j++)
|
||||||
{
|
{
|
||||||
if (password[j] == password[i])
|
if (password[j] == password[i])
|
||||||
c++;
|
c++;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (c != 0)
|
if (c != 0)
|
||||||
{
|
{
|
||||||
if (c == 2)
|
if (c == 2)
|
||||||
foundDouble = true;
|
foundDouble = true;
|
||||||
c = 0;
|
c = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == 2)
|
if (c == 2)
|
||||||
foundDouble = true;
|
foundDouble = true;
|
||||||
}
|
}
|
||||||
return foundDouble;
|
return foundDouble;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsAssending(int[] password)
|
public static bool IsAssending(int[] password)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < 6; i++)
|
for (int i = 1; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (password[i] < password[i - 1])
|
if (password[i] < password[i - 1])
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountPasswordsPart1(int lower, int upper)
|
public static int CountPasswordsPart1(int lower, int upper)
|
||||||
{
|
{
|
||||||
int passwordCount = 0;
|
int passwordCount = 0;
|
||||||
int[] curPassword = lower.ToIntArray();
|
int[] curPassword = lower.ToIntArray();
|
||||||
CleanPassword(ref curPassword);
|
CleanPassword(ref curPassword);
|
||||||
while (curPassword.ToInt() <= upper)
|
while (curPassword.ToInt() <= upper)
|
||||||
{
|
{
|
||||||
if (IsValidPassword(curPassword))
|
if (IsValidPassword(curPassword))
|
||||||
{
|
{
|
||||||
passwordCount++;
|
passwordCount++;
|
||||||
}
|
}
|
||||||
curPassword[^1]++;
|
curPassword[^1]++;
|
||||||
Propagate(ref curPassword, curPassword.Length - 1);
|
Propagate(ref curPassword, curPassword.Length - 1);
|
||||||
CleanPassword(ref curPassword);
|
CleanPassword(ref curPassword);
|
||||||
}
|
}
|
||||||
return passwordCount;
|
return passwordCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountPasswordsPart2(int lower, int upper)
|
public static int CountPasswordsPart2(int lower, int upper)
|
||||||
{
|
{
|
||||||
int passwordCount = 0;
|
int passwordCount = 0;
|
||||||
int[] curPassword = lower.ToIntArray();
|
int[] curPassword = lower.ToIntArray();
|
||||||
CleanPassword(ref curPassword);
|
CleanPassword(ref curPassword);
|
||||||
while (curPassword.ToInt() <= upper)
|
while (curPassword.ToInt() <= upper)
|
||||||
{
|
{
|
||||||
if (HasDoubles(curPassword))
|
if (HasDoubles(curPassword))
|
||||||
{
|
{
|
||||||
passwordCount++;
|
passwordCount++;
|
||||||
}
|
}
|
||||||
curPassword[^1]++;
|
curPassword[^1]++;
|
||||||
Propagate(ref curPassword, curPassword.Length - 1);
|
Propagate(ref curPassword, curPassword.Length - 1);
|
||||||
CleanPassword(ref curPassword);
|
CleanPassword(ref curPassword);
|
||||||
}
|
}
|
||||||
return passwordCount;
|
return passwordCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void CleanPassword(ref int[] password)
|
public static void CleanPassword(ref int[] password)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < 6; i++)
|
for (int i = 1; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (password[i] < password[i - 1])
|
if (password[i] < password[i - 1])
|
||||||
{
|
{
|
||||||
password[i] += password[i - 1] - password[i];
|
password[i] += password[i - 1] - password[i];
|
||||||
if (password[i] == 10)
|
if (password[i] == 10)
|
||||||
{
|
{
|
||||||
Propagate(ref password, i);
|
Propagate(ref password, i);
|
||||||
password[i] = password[i - 1];
|
password[i] = password[i - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Propagate(ref int[] password, int digit)
|
public static void Propagate(ref int[] password, int digit)
|
||||||
{
|
{
|
||||||
for (int i = digit; i >= 0; i--)
|
for (int i = digit; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (i == 0 && password[i] == 10)
|
if (i == 0 && password[i] == 10)
|
||||||
{
|
{
|
||||||
password[i] = 9;
|
password[i] = 9;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (password[i] == 10)
|
if (password[i] == 10)
|
||||||
{
|
{
|
||||||
password[i] = 0;
|
password[i] = 0;
|
||||||
password[i - 1]++;
|
password[i - 1]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = CountPasswordsPart1(147981, 691423);
|
Part1 = CountPasswordsPart1(147981, 691423);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = CountPasswordsPart2(147981, 691423);
|
Part2 = CountPasswordsPart2(147981, 691423);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,30 +1,30 @@
|
|||||||
using AdventOfCode.Day_5;
|
using AdventOfCode.Day_5;
|
||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day5;
|
namespace AdventOfCode.Problems.AOC2019.Day5;
|
||||||
|
|
||||||
[ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")]
|
[ProblemInfo(2019, 5, "Sunny with a Chance of Asteroids")]
|
||||||
internal class ChanceOfAsteroids : Problem<int, int>
|
internal class ChanceOfAsteroids : Problem<int, int>
|
||||||
{
|
{
|
||||||
private IntCodeV2 _cpu = new IntCodeV2();
|
private IntCodeV2 _cpu = new IntCodeV2();
|
||||||
private int[] _baseInput = Array.Empty<int>();
|
private int[] _baseInput = Array.Empty<int>();
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var output = new int[1];
|
var output = new int[1];
|
||||||
_cpu.ExecuteCode(_baseInput, new int[] { 1 }, output);
|
_cpu.ExecuteCode(_baseInput, new int[] { 1 }, output);
|
||||||
Part1 = output[0];
|
Part1 = output[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var output = new int[1];
|
var output = new int[1];
|
||||||
_cpu.ExecuteCode(_baseInput, new int[] { 5 }, output);
|
_cpu.ExecuteCode(_baseInput, new int[] { 5 }, output);
|
||||||
Part2 = output[0];
|
Part2 = output[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
_baseInput = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,233 +1,233 @@
|
|||||||
namespace AdventOfCode.Day_5
|
namespace AdventOfCode.Day_5
|
||||||
{
|
{
|
||||||
public class IntCodeV2
|
public class IntCodeV2
|
||||||
{
|
{
|
||||||
public struct Instruction
|
public struct Instruction
|
||||||
{
|
{
|
||||||
public int opcode;
|
public int opcode;
|
||||||
public int paramCount;
|
public int paramCount;
|
||||||
public Func<int[], int[], int, int, int, bool> action;
|
public Func<int[], int[], int, int, int, bool> action;
|
||||||
|
|
||||||
public Instruction(int opcode, int paramCount, Func<int[], int[], int, int, int, bool> action)
|
public Instruction(int opcode, int paramCount, Func<int[], int[], int, int, int, bool> action)
|
||||||
{
|
{
|
||||||
this.opcode = opcode;
|
this.opcode = opcode;
|
||||||
this.paramCount = paramCount;
|
this.paramCount = paramCount;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsHalted { get; private set; }
|
public bool IsHalted { get; private set; }
|
||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
public bool PersistentMode { get; private set; }
|
public bool PersistentMode { get; private set; }
|
||||||
public bool SuspendOnWrite { get; private set; }
|
public bool SuspendOnWrite { get; private set; }
|
||||||
|
|
||||||
private Dictionary<int, Instruction> _instructions;
|
private Dictionary<int, Instruction> _instructions;
|
||||||
private int _instructionPointer;
|
private int _instructionPointer;
|
||||||
private int[]? _inputBuffer;
|
private int[]? _inputBuffer;
|
||||||
private int _inputCounter = 0;
|
private int _inputCounter = 0;
|
||||||
private int[]? _outputBuffer;
|
private int[]? _outputBuffer;
|
||||||
private int _outputCounter = 0;
|
private int _outputCounter = 0;
|
||||||
private int[] memory = Array.Empty<int>();
|
private int[] memory = Array.Empty<int>();
|
||||||
|
|
||||||
public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false)
|
public IntCodeV2(bool persistentMode = false, bool suspendOnOutput = false)
|
||||||
{
|
{
|
||||||
_instructions = new Dictionary<int, Instruction>();
|
_instructions = new Dictionary<int, Instruction>();
|
||||||
PersistentMode = persistentMode;
|
PersistentMode = persistentMode;
|
||||||
SuspendOnWrite = suspendOnOutput;
|
SuspendOnWrite = suspendOnOutput;
|
||||||
IsHalted = false;
|
IsHalted = false;
|
||||||
//Add
|
//Add
|
||||||
_instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(1, new Instruction(1, 3, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
||||||
mem[v3] = v1 + v2;
|
mem[v3] = v1 + v2;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Multiply
|
//Multiply
|
||||||
_instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(2, new Instruction(2, 3, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
||||||
mem[v3] = v1 * v2;
|
mem[v3] = v1 * v2;
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Halt
|
//Halt
|
||||||
_instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(99, new Instruction(99, 0, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
IsHalted = true;
|
IsHalted = true;
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
//Read Input
|
//Read Input
|
||||||
_instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(3, new Instruction(3, 1, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? mem[p1] : p1;
|
var v1 = mode[2] == 1 ? mem[p1] : p1;
|
||||||
mem[v1] = ReadInput();
|
mem[v1] = ReadInput();
|
||||||
//Console.WriteLine($"Input Read: {mem[v1]}");
|
//Console.WriteLine($"Input Read: {mem[v1]}");
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Write Output
|
//Write Output
|
||||||
_instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(4, new Instruction(4, 1, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
WriteOutput(v1);
|
WriteOutput(v1);
|
||||||
if (SuspendOnWrite)
|
if (SuspendOnWrite)
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Jump if True
|
//Jump if True
|
||||||
_instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(5, new Instruction(5, 2, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
if (v1 != 0)
|
if (v1 != 0)
|
||||||
{
|
{
|
||||||
_instructionPointer = v2;
|
_instructionPointer = v2;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Jump if False
|
//Jump if False
|
||||||
_instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(6, new Instruction(6, 2, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
if (v1 == 0)
|
if (v1 == 0)
|
||||||
{
|
{
|
||||||
_instructionPointer = v2;
|
_instructionPointer = v2;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Less than
|
//Less than
|
||||||
_instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(7, new Instruction(7, 3, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
||||||
if (v1 < v2)
|
if (v1 < v2)
|
||||||
mem[v3] = 1;
|
mem[v3] = 1;
|
||||||
else
|
else
|
||||||
mem[v3] = 0;
|
mem[v3] = 0;
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
//Equals
|
//Equals
|
||||||
_instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) =>
|
_instructions.Add(8, new Instruction(8, 3, (mem, mode, p1, p2, p3) =>
|
||||||
{
|
{
|
||||||
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
var v1 = mode[2] == 1 ? p1 : mem[p1];
|
||||||
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
var v2 = mode[1] == 1 ? p2 : mem[p2];
|
||||||
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
var v3 = mode[0] == 1 ? mem[p3] : p3;
|
||||||
if (v1 == v2)
|
if (v1 == v2)
|
||||||
mem[v3] = 1;
|
mem[v3] = 1;
|
||||||
else
|
else
|
||||||
mem[v3] = 0;
|
mem[v3] = 0;
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ReadInput()
|
private int ReadInput()
|
||||||
{
|
{
|
||||||
_inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1);
|
_inputCounter = Math.Min(_inputCounter, (_inputBuffer?.Length ?? 1) - 1);
|
||||||
if (_inputBuffer != null && _inputCounter < _inputBuffer.Length)
|
if (_inputBuffer != null && _inputCounter < _inputBuffer.Length)
|
||||||
return _inputBuffer[_inputCounter++];
|
return _inputBuffer[_inputCounter++];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Write("Input: ");
|
Console.Write("Input: ");
|
||||||
return int.Parse(Console.ReadLine()!);
|
return int.Parse(Console.ReadLine()!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteOutput(int output)
|
private void WriteOutput(int output)
|
||||||
{
|
{
|
||||||
_outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1);
|
_outputCounter = Math.Min(_outputCounter, (_outputBuffer?.Length ?? 1) - 1);
|
||||||
if (_outputBuffer != null && _outputCounter < _outputBuffer.Length)
|
if (_outputBuffer != null && _outputCounter < _outputBuffer.Length)
|
||||||
_outputBuffer[_outputCounter++] = output;
|
_outputBuffer[_outputCounter++] = output;
|
||||||
else
|
else
|
||||||
Console.WriteLine(output);
|
Console.WriteLine(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null)
|
public void ExecuteCode(int[] code, int[]? input = null, int[]? output = null)
|
||||||
{
|
{
|
||||||
LoadCode(code);
|
LoadCode(code);
|
||||||
SetIO(input, output);
|
SetIO(input, output);
|
||||||
IsHalted = false;
|
IsHalted = false;
|
||||||
Run();
|
Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (int[] opModes, int opcode) ParseInstruction(int instruction)
|
public static (int[] opModes, int opcode) ParseInstruction(int instruction)
|
||||||
{
|
{
|
||||||
var opModes = new int[3];
|
var opModes = new int[3];
|
||||||
var arr = instruction.ToIntArray();
|
var arr = instruction.ToIntArray();
|
||||||
switch (arr.Length)
|
switch (arr.Length)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return (opModes, arr[0]);
|
return (opModes, arr[0]);
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return (opModes, (arr[^2] * 10) + arr[^1]);
|
return (opModes, (arr[^2] * 10) + arr[^1]);
|
||||||
}
|
}
|
||||||
var opcode = (arr[^2] * 10) + arr[^1];
|
var opcode = (arr[^2] * 10) + arr[^1];
|
||||||
for (int i = 1; i <= 3; i++)
|
for (int i = 1; i <= 3; i++)
|
||||||
{
|
{
|
||||||
if (arr.Length < i + 2)
|
if (arr.Length < i + 2)
|
||||||
opModes[^i] = 0;
|
opModes[^i] = 0;
|
||||||
else
|
else
|
||||||
opModes[^i] = arr[^(i + 2)];
|
opModes[^i] = arr[^(i + 2)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (opModes, opcode);
|
return (opModes, opcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetIO()
|
public void ResetIO()
|
||||||
{
|
{
|
||||||
_inputCounter = _outputCounter = 0;
|
_inputCounter = _outputCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInputIndex(int index)
|
public void SetInputIndex(int index)
|
||||||
{
|
{
|
||||||
_inputCounter = index;
|
_inputCounter = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetIO(int[]? inputBuffer, int[]? outputBuffer)
|
public void SetIO(int[]? inputBuffer, int[]? outputBuffer)
|
||||||
{
|
{
|
||||||
ResetIO();
|
ResetIO();
|
||||||
_inputBuffer = inputBuffer ?? Array.Empty<int>();
|
_inputBuffer = inputBuffer ?? Array.Empty<int>();
|
||||||
_outputBuffer = outputBuffer ?? Array.Empty<int>();
|
_outputBuffer = outputBuffer ?? Array.Empty<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
while (IsRunning)
|
while (IsRunning)
|
||||||
{
|
{
|
||||||
var (modes, opcode) = ParseInstruction(memory[_instructionPointer]);
|
var (modes, opcode) = ParseInstruction(memory[_instructionPointer]);
|
||||||
var curInstruction = _instructions[opcode];
|
var curInstruction = _instructions[opcode];
|
||||||
int[] parameters = new int[3];
|
int[] parameters = new int[3];
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
if (i >= curInstruction.paramCount)
|
if (i >= curInstruction.paramCount)
|
||||||
parameters[i] = 0;
|
parameters[i] = 0;
|
||||||
else
|
else
|
||||||
parameters[i] = memory[_instructionPointer + i + 1];
|
parameters[i] = memory[_instructionPointer + i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2]))
|
if (curInstruction.action(memory, modes, parameters[0], parameters[1], parameters[2]))
|
||||||
_instructionPointer += curInstruction.paramCount + 1;
|
_instructionPointer += curInstruction.paramCount + 1;
|
||||||
|
|
||||||
if (IsHalted)
|
if (IsHalted)
|
||||||
IsRunning = false;
|
IsRunning = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntCodeV2 LoadCode(int[] code)
|
public IntCodeV2 LoadCode(int[] code)
|
||||||
{
|
{
|
||||||
memory = new int[code.Length];
|
memory = new int[code.Length];
|
||||||
code.CopyTo(memory, 0);
|
code.CopyTo(memory, 0);
|
||||||
_instructionPointer = 0;
|
_instructionPointer = 0;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,119 +1,119 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2019.Day6
|
namespace AdventOfCode.Problems.AOC2019.Day6
|
||||||
{
|
{
|
||||||
public class OrbitMap
|
public class OrbitMap
|
||||||
{
|
{
|
||||||
public CelestialObject root;
|
public CelestialObject root;
|
||||||
public Dictionary<string, CelestialObject> objectMap;
|
public Dictionary<string, CelestialObject> objectMap;
|
||||||
|
|
||||||
public OrbitMap(string[] orbits)
|
public OrbitMap(string[] orbits)
|
||||||
{
|
{
|
||||||
objectMap = new Dictionary<string, CelestialObject>();
|
objectMap = new Dictionary<string, CelestialObject>();
|
||||||
GenerateOrbits(orbits);
|
GenerateOrbits(orbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GenerateOrbits(string[] orbits)
|
public void GenerateOrbits(string[] orbits)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < orbits.Length; i++)
|
for (int i = 0; i < orbits.Length; i++)
|
||||||
{
|
{
|
||||||
var bodies = orbits[i].Split(')');
|
var bodies = orbits[i].Split(')');
|
||||||
if (bodies[0] == "COM")
|
if (bodies[0] == "COM")
|
||||||
root = CreateObject("COM");
|
root = CreateObject("COM");
|
||||||
|
|
||||||
var parent = GetOrCreateObject(bodies[0]);
|
var parent = GetOrCreateObject(bodies[0]);
|
||||||
var child = GetOrCreateObject(bodies[1]);
|
var child = GetOrCreateObject(bodies[1]);
|
||||||
|
|
||||||
parent.AddChild(child);
|
parent.AddChild(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CelestialObject GetOrCreateObject(string name)
|
public CelestialObject GetOrCreateObject(string name)
|
||||||
{
|
{
|
||||||
if (objectMap.ContainsKey(name))
|
if (objectMap.ContainsKey(name))
|
||||||
return objectMap[name];
|
return objectMap[name];
|
||||||
else
|
else
|
||||||
return CreateObject(name);
|
return CreateObject(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CelestialObject CreateObject(string name)
|
public CelestialObject CreateObject(string name)
|
||||||
{
|
{
|
||||||
var o = new CelestialObject(name);
|
var o = new CelestialObject(name);
|
||||||
objectMap.Add(name, o);
|
objectMap.Add(name, o);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateOrbits()
|
public int CalculateOrbits()
|
||||||
{
|
{
|
||||||
return root.GetOrbitCount();
|
return root.GetOrbitCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<CelestialObject> FindPathTo(string name)
|
public List<CelestialObject> FindPathTo(string name)
|
||||||
{
|
{
|
||||||
var path = new List<CelestialObject>();
|
var path = new List<CelestialObject>();
|
||||||
root.FindPathTo(name, path);
|
root.FindPathTo(name, path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetDepthOf(string name) => root.GetDepth(name);
|
public int GetDepthOf(string name) => root.GetDepth(name);
|
||||||
|
|
||||||
public class CelestialObject
|
public class CelestialObject
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public int ChildCount => children.Count;
|
public int ChildCount => children.Count;
|
||||||
|
|
||||||
public List<CelestialObject> children;
|
public List<CelestialObject> children;
|
||||||
|
|
||||||
public CelestialObject(string name)
|
public CelestialObject(string name)
|
||||||
{
|
{
|
||||||
children = new List<CelestialObject>();
|
children = new List<CelestialObject>();
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddChild(CelestialObject child)
|
public void AddChild(CelestialObject child)
|
||||||
{
|
{
|
||||||
children.Add(child);
|
children.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOrbitCount(int depth = 0)
|
public int GetOrbitCount(int depth = 0)
|
||||||
{
|
{
|
||||||
var count = 0;
|
var count = 0;
|
||||||
for (int i = 0; i < children.Count; i++)
|
for (int i = 0; i < children.Count; i++)
|
||||||
{
|
{
|
||||||
count += children[i].GetOrbitCount(depth + 1);
|
count += children[i].GetOrbitCount(depth + 1);
|
||||||
}
|
}
|
||||||
return depth + count;
|
return depth + count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FindPathTo(string name, List<CelestialObject> path)
|
public bool FindPathTo(string name, List<CelestialObject> path)
|
||||||
{
|
{
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
return true;
|
return true;
|
||||||
for (int i = 0; i < ChildCount; i++)
|
for (int i = 0; i < ChildCount; i++)
|
||||||
{
|
{
|
||||||
if (children[i].FindPathTo(name, path))
|
if (children[i].FindPathTo(name, path))
|
||||||
{
|
{
|
||||||
path.Add(children[i]);
|
path.Add(children[i]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetDepth(string name, int depth = 0)
|
public int GetDepth(string name, int depth = 0)
|
||||||
{
|
{
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
return depth;
|
return depth;
|
||||||
var d = 0;
|
var d = 0;
|
||||||
for (int i = 0; i < ChildCount; i++)
|
for (int i = 0; i < ChildCount; i++)
|
||||||
{
|
{
|
||||||
d += children[i].GetDepth(name, depth + 1);
|
d += children[i].GetDepth(name, depth + 1);
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,53 +1,53 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day6;
|
namespace AdventOfCode.Problems.AOC2019.Day6;
|
||||||
|
|
||||||
[ProblemInfo(2019, 6, "Universal Orbit Map")]
|
[ProblemInfo(2019, 6, "Universal Orbit Map")]
|
||||||
internal class UniversalOrbits : Problem<int, int>
|
internal class UniversalOrbits : Problem<int, int>
|
||||||
{
|
{
|
||||||
private OrbitMap? _map;
|
private OrbitMap? _map;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
if (_map == null)
|
if (_map == null)
|
||||||
return;
|
return;
|
||||||
Part1 = _map.CalculateOrbits();
|
Part1 = _map.CalculateOrbits();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
if (_map == null)
|
if (_map == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var pathToYOU = _map.FindPathTo("YOU");
|
var pathToYOU = _map.FindPathTo("YOU");
|
||||||
var pathToSAN = _map.FindPathTo("SAN");
|
var pathToSAN = _map.FindPathTo("SAN");
|
||||||
string pivot = "";
|
string pivot = "";
|
||||||
int dist = 0;
|
int dist = 0;
|
||||||
|
|
||||||
HashSet<string> pathYOU = new(pathToYOU.Select(o => o.Name));
|
HashSet<string> pathYOU = new(pathToYOU.Select(o => o.Name));
|
||||||
|
|
||||||
for (int i = 0; i < pathToSAN.Count; i++)
|
for (int i = 0; i < pathToSAN.Count; i++)
|
||||||
{
|
{
|
||||||
if (pathYOU.Contains(pathToSAN[i].Name))
|
if (pathYOU.Contains(pathToSAN[i].Name))
|
||||||
{
|
{
|
||||||
pivot = pathToSAN[i].Name;
|
pivot = pathToSAN[i].Name;
|
||||||
dist = i;
|
dist = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < pathToYOU.Count; i++)
|
for (int i = 0; i < pathToYOU.Count; i++)
|
||||||
{
|
{
|
||||||
if (pathToYOU[i].Name == pivot)
|
if (pathToYOU[i].Name == pivot)
|
||||||
{
|
{
|
||||||
dist += i;
|
dist += i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part2 = dist - 2;
|
Part2 = dist - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_map = new OrbitMap(ReadInputLines());
|
_map = new OrbitMap(ReadInputLines());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,161 +1,161 @@
|
|||||||
using AdventOfCode.Day_5;
|
using AdventOfCode.Day_5;
|
||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day7
|
namespace AdventOfCode.Problems.AOC2019.Day7
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 7, "Amplification Circuit")]
|
[ProblemInfo(2019, 7, "Amplification Circuit")]
|
||||||
public class AmplificationCircuit : Problem<int, int>
|
public class AmplificationCircuit : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[] _code = Array.Empty<int>();
|
private int[] _code = Array.Empty<int>();
|
||||||
|
|
||||||
public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings)
|
public static int RunPhase(IntCodeV2 cpu, int[] code, int[] phaseSettings)
|
||||||
{
|
{
|
||||||
if (HasDuplicateValues(phaseSettings))
|
if (HasDuplicateValues(phaseSettings))
|
||||||
return int.MinValue;
|
return int.MinValue;
|
||||||
int[] outputBuffer = { 0 };
|
int[] outputBuffer = { 0 };
|
||||||
int[] inputBuffer;
|
int[] inputBuffer;
|
||||||
//Amp A
|
//Amp A
|
||||||
inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] };
|
inputBuffer = new int[] { phaseSettings[0], outputBuffer[0] };
|
||||||
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
||||||
//Amp B
|
//Amp B
|
||||||
inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] };
|
inputBuffer = new int[] { phaseSettings[1], outputBuffer[0] };
|
||||||
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
||||||
//Amp C
|
//Amp C
|
||||||
inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] };
|
inputBuffer = new int[] { phaseSettings[2], outputBuffer[0] };
|
||||||
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
||||||
//Amp D
|
//Amp D
|
||||||
inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] };
|
inputBuffer = new int[] { phaseSettings[3], outputBuffer[0] };
|
||||||
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
||||||
//Amp E
|
//Amp E
|
||||||
inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] };
|
inputBuffer = new int[] { phaseSettings[4], outputBuffer[0] };
|
||||||
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
cpu.ExecuteCode(code, inputBuffer, outputBuffer);
|
||||||
return outputBuffer[0];
|
return outputBuffer[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int RunFeedback(int[] code, int[] phaseSettings)
|
public static int RunFeedback(int[] code, int[] phaseSettings)
|
||||||
{
|
{
|
||||||
if (HasDuplicateValues(phaseSettings))
|
if (HasDuplicateValues(phaseSettings))
|
||||||
return int.MinValue;
|
return int.MinValue;
|
||||||
var ampA = new IntCodeV2(true, true).LoadCode(code);
|
var ampA = new IntCodeV2(true, true).LoadCode(code);
|
||||||
var ampB = new IntCodeV2(true, true).LoadCode(code);
|
var ampB = new IntCodeV2(true, true).LoadCode(code);
|
||||||
var ampC = new IntCodeV2(true, true).LoadCode(code);
|
var ampC = new IntCodeV2(true, true).LoadCode(code);
|
||||||
var ampD = new IntCodeV2(true, true).LoadCode(code);
|
var ampD = new IntCodeV2(true, true).LoadCode(code);
|
||||||
var ampE = new IntCodeV2(true, true).LoadCode(code);
|
var ampE = new IntCodeV2(true, true).LoadCode(code);
|
||||||
var outputA = new int[] { 273 };
|
var outputA = new int[] { 273 };
|
||||||
var outputB = new int[] { 0 };
|
var outputB = new int[] { 0 };
|
||||||
var outputC = new int[] { 0 };
|
var outputC = new int[] { 0 };
|
||||||
var outputD = new int[] { 0 };
|
var outputD = new int[] { 0 };
|
||||||
var outputE = new int[] { 0 };
|
var outputE = new int[] { 0 };
|
||||||
var inputA = new int[] { phaseSettings[0], outputE[0] };
|
var inputA = new int[] { phaseSettings[0], outputE[0] };
|
||||||
var inputB = new int[] { phaseSettings[1], outputA[0] };
|
var inputB = new int[] { phaseSettings[1], outputA[0] };
|
||||||
var inputC = new int[] { phaseSettings[2], outputB[0] };
|
var inputC = new int[] { phaseSettings[2], outputB[0] };
|
||||||
var inputD = new int[] { phaseSettings[3], outputC[0] };
|
var inputD = new int[] { phaseSettings[3], outputC[0] };
|
||||||
var inputE = new int[] { phaseSettings[4], outputD[0] };
|
var inputE = new int[] { phaseSettings[4], outputD[0] };
|
||||||
ampA.SetIO(inputA, outputA);
|
ampA.SetIO(inputA, outputA);
|
||||||
ampB.SetIO(inputB, outputB);
|
ampB.SetIO(inputB, outputB);
|
||||||
ampC.SetIO(inputC, outputC);
|
ampC.SetIO(inputC, outputC);
|
||||||
ampD.SetIO(inputD, outputD);
|
ampD.SetIO(inputD, outputD);
|
||||||
ampE.SetIO(inputE, outputE);
|
ampE.SetIO(inputE, outputE);
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
while (!ampE.IsHalted)
|
while (!ampE.IsHalted)
|
||||||
{
|
{
|
||||||
//Console.WriteLine($"Iteration {iter}");
|
//Console.WriteLine($"Iteration {iter}");
|
||||||
inputA[1] = outputE[0];
|
inputA[1] = outputE[0];
|
||||||
|
|
||||||
ampA.Run();
|
ampA.Run();
|
||||||
inputB[1] = outputA[0];
|
inputB[1] = outputA[0];
|
||||||
ampB.Run();
|
ampB.Run();
|
||||||
inputC[1] = outputB[0];
|
inputC[1] = outputB[0];
|
||||||
ampC.Run();
|
ampC.Run();
|
||||||
inputD[1] = outputC[0];
|
inputD[1] = outputC[0];
|
||||||
ampD.Run();
|
ampD.Run();
|
||||||
inputE[1] = outputD[0];
|
inputE[1] = outputD[0];
|
||||||
ampE.Run();
|
ampE.Run();
|
||||||
|
|
||||||
//Console.WriteLine($"Output {outputE[0]}");
|
//Console.WriteLine($"Output {outputE[0]}");
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputE[0];
|
return outputE[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasDuplicateValues(int[] arr)
|
public static bool HasDuplicateValues(int[] arr)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < arr.Length; i++)
|
for (int i = 0; i < arr.Length; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < arr.Length; j++)
|
for (int j = 0; j < arr.Length; j++)
|
||||||
{
|
{
|
||||||
if (i == j)
|
if (i == j)
|
||||||
continue;
|
continue;
|
||||||
if (arr[i] == arr[j])
|
if (arr[i] == arr[j])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_code = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
_code = InputParsing.ParseIntCsv(GetInputFile("input.csv"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
int output = int.MinValue;
|
int output = int.MinValue;
|
||||||
int min = 0;
|
int min = 0;
|
||||||
int max = 5;
|
int max = 5;
|
||||||
var cpu = new IntCodeV2();
|
var cpu = new IntCodeV2();
|
||||||
|
|
||||||
for (int i = min; i < max; i++)
|
for (int i = min; i < max; i++)
|
||||||
{
|
{
|
||||||
for (int j = min; j < max; j++)
|
for (int j = min; j < max; j++)
|
||||||
{
|
{
|
||||||
for (int k = min; k < max; k++)
|
for (int k = min; k < max; k++)
|
||||||
{
|
{
|
||||||
for (int l = min; l < max; l++)
|
for (int l = min; l < max; l++)
|
||||||
{
|
{
|
||||||
for (int m = min; m < max; m++)
|
for (int m = min; m < max; m++)
|
||||||
{
|
{
|
||||||
var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m });
|
var result = RunPhase(cpu, _code, new int[] { i, j, k, l, m });
|
||||||
if (output < result)
|
if (output < result)
|
||||||
{
|
{
|
||||||
output = result;
|
output = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part1 = output;
|
Part1 = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
int output = int.MinValue;
|
int output = int.MinValue;
|
||||||
int min = 5;
|
int min = 5;
|
||||||
int max = 10;
|
int max = 10;
|
||||||
|
|
||||||
for (int i = min; i < max; i++)
|
for (int i = min; i < max; i++)
|
||||||
{
|
{
|
||||||
for (int j = min; j < max; j++)
|
for (int j = min; j < max; j++)
|
||||||
{
|
{
|
||||||
for (int k = min; k < max; k++)
|
for (int k = min; k < max; k++)
|
||||||
{
|
{
|
||||||
for (int l = min; l < max; l++)
|
for (int l = min; l < max; l++)
|
||||||
{
|
{
|
||||||
for (int m = min; m < max; m++)
|
for (int m = min; m < max; m++)
|
||||||
{
|
{
|
||||||
var result = RunFeedback(_code, new int[] { i, j, k, l, m });
|
var result = RunFeedback(_code, new int[] { i, j, k, l, m });
|
||||||
if (output < result)
|
if (output < result)
|
||||||
{
|
{
|
||||||
output = result;
|
output = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part2 = output;
|
Part2 = output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,83 +1,83 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2019.Day8
|
namespace AdventOfCode.Problems.AOC2019.Day8
|
||||||
{
|
{
|
||||||
[ProblemInfo(2019, 8, "Space Image Format")]
|
[ProblemInfo(2019, 8, "Space Image Format")]
|
||||||
public class SpaceImageFormat : Problem<int, string>
|
public class SpaceImageFormat : Problem<int, string>
|
||||||
{
|
{
|
||||||
private int[] _imageData = Array.Empty<int>();
|
private int[] _imageData = Array.Empty<int>();
|
||||||
|
|
||||||
public static void Execute()
|
public static void Execute()
|
||||||
{
|
{
|
||||||
var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
|
var imageData = File.ReadAllText("Day8/input.txt").Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
|
||||||
|
|
||||||
Console.WriteLine(Checksum(imageData, 25, 6));
|
Console.WriteLine(Checksum(imageData, 25, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RenderImage(int[] data, int h, int w)
|
public static void RenderImage(int[] data, int h, int w)
|
||||||
{
|
{
|
||||||
var imgSize = h * w;
|
var imgSize = h * w;
|
||||||
var layerCount = data.Length / imgSize;
|
var layerCount = data.Length / imgSize;
|
||||||
|
|
||||||
for (int l = 0; l < layerCount; l++)
|
for (int l = 0; l < layerCount; l++)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int Checksum(int[] data, int h, int w)
|
public static int Checksum(int[] data, int h, int w)
|
||||||
{
|
{
|
||||||
var imgSize = h * w;
|
var imgSize = h * w;
|
||||||
var layerCount = data.Length / imgSize;
|
var layerCount = data.Length / imgSize;
|
||||||
|
|
||||||
int[] zeroCount = new int[layerCount];
|
int[] zeroCount = new int[layerCount];
|
||||||
int[] oneCount = new int[layerCount];
|
int[] oneCount = new int[layerCount];
|
||||||
int[] twoCount = new int[layerCount];
|
int[] twoCount = new int[layerCount];
|
||||||
|
|
||||||
int smallestLayer = -1;
|
int smallestLayer = -1;
|
||||||
int smallestLayerCount = int.MaxValue;
|
int smallestLayerCount = int.MaxValue;
|
||||||
|
|
||||||
for (int l = 0; l < layerCount; l++)
|
for (int l = 0; l < layerCount; l++)
|
||||||
{
|
{
|
||||||
for (int i = imgSize * l; i < imgSize * (l + 1); i++)
|
for (int i = imgSize * l; i < imgSize * (l + 1); i++)
|
||||||
{
|
{
|
||||||
switch (data[i])
|
switch (data[i])
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
zeroCount[l]++;
|
zeroCount[l]++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
oneCount[l]++;
|
oneCount[l]++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
twoCount[l]++;
|
twoCount[l]++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zeroCount[l] <= smallestLayerCount)
|
if (zeroCount[l] <= smallestLayerCount)
|
||||||
{
|
{
|
||||||
smallestLayer = l;
|
smallestLayer = l;
|
||||||
smallestLayerCount = zeroCount[l];
|
smallestLayerCount = zeroCount[l];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return oneCount[smallestLayer] * twoCount[smallestLayer];
|
return oneCount[smallestLayer] * twoCount[smallestLayer];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
|
_imageData = ReadInputText().Replace("\n", "").Select(c => int.Parse(c.ToString())).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = Checksum(_imageData, 25, 6);
|
Part1 = Checksum(_imageData, 25, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = null;
|
Part2 = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
namespace AdventOfCode
|
namespace AdventOfCode
|
||||||
{
|
{
|
||||||
public static class InputParsing
|
public static class InputParsing
|
||||||
{
|
{
|
||||||
public static int[] ParseIntArray(string file)
|
public static int[] ParseIntArray(string file)
|
||||||
{
|
{
|
||||||
return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray();
|
return File.ReadAllLines(file).Select(s => int.Parse(s)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] ParseIntCsv(string file)
|
public static int[] ParseIntCsv(string file)
|
||||||
{
|
{
|
||||||
return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray();
|
return File.ReadAllText(file).Split(',').Select(s => int.Parse(s)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int ToInt(this int[] intArr)
|
public static int ToInt(this int[] intArr)
|
||||||
{
|
{
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for (int i = 0; i < intArr.Length; i++)
|
for (int i = 0; i < intArr.Length; i++)
|
||||||
{
|
{
|
||||||
value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i];
|
value += (int)Math.Pow(10, intArr.Length - i - 1) * intArr[i];
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] ToIntArray(this int number)
|
public static int[] ToIntArray(this int number)
|
||||||
{
|
{
|
||||||
int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray();
|
int[] intArr = number.ToString().Select(d => int.Parse(d.ToString())).ToArray();
|
||||||
return intArr;
|
return intArr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,196 +1,196 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2021.Day11;
|
namespace AdventOfCode.Problems.AOC2021.Day11;
|
||||||
|
|
||||||
[ProblemInfo(2021, 11, "Dumbo Octopus")]
|
[ProblemInfo(2021, 11, "Dumbo Octopus")]
|
||||||
public class DumboOctopus : Problem<int, int>, IEnumerable<byte>
|
public class DumboOctopus : Problem<int, int>, IEnumerable<byte>
|
||||||
{
|
{
|
||||||
public byte[] dataPart1 = Array.Empty<byte>();
|
public byte[] dataPart1 = Array.Empty<byte>();
|
||||||
public byte[] dataPart2 = Array.Empty<byte>();
|
public byte[] dataPart2 = Array.Empty<byte>();
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputLines();
|
var data = ReadInputLines();
|
||||||
dataPart1 = new byte[10 * 10];
|
dataPart1 = new byte[10 * 10];
|
||||||
if (data.Length != 10)
|
if (data.Length != 10)
|
||||||
throw new ArgumentException("Data must contain 10 elements", nameof(data));
|
throw new ArgumentException("Data must contain 10 elements", nameof(data));
|
||||||
for (int y = 0; y < data.Length; y++)
|
for (int y = 0; y < data.Length; y++)
|
||||||
{
|
{
|
||||||
var line = data[y];
|
var line = data[y];
|
||||||
if (line.Length != 10)
|
if (line.Length != 10)
|
||||||
throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data));
|
throw new ArgumentException($"Lines must contain 10 elements. Line: {y + 1}", nameof(data));
|
||||||
|
|
||||||
for (int x = 0; x < line.Length; x++)
|
for (int x = 0; x < line.Length; x++)
|
||||||
{
|
{
|
||||||
dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1));
|
dataPart1[x + y * 10] = byte.Parse(line.Substring(x, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dataPart2 = new byte[10 * 10];
|
dataPart2 = new byte[10 * 10];
|
||||||
Array.Copy(dataPart1, dataPart2, dataPart1.Length);
|
Array.Copy(dataPart1, dataPart2, dataPart1.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = Run(ref dataPart1, 100, out _);
|
Part1 = Run(ref dataPart1, 100, out _);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Run(ref dataPart2, 210, out var fullFlash);
|
Run(ref dataPart2, 210, out var fullFlash);
|
||||||
Part2 = fullFlash;
|
Part2 = fullFlash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<byte> GetEnumerator()
|
public IEnumerator<byte> GetEnumerator()
|
||||||
{
|
{
|
||||||
return ((IEnumerable<byte>)dataPart1).GetEnumerator();
|
return ((IEnumerable<byte>)dataPart1).GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
{
|
{
|
||||||
return dataPart1.GetEnumerator();
|
return dataPart1.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Run(ref byte[] data, int count, out int fullFlash)
|
public int Run(ref byte[] data, int count, out int fullFlash)
|
||||||
{
|
{
|
||||||
var flashes = 0;
|
var flashes = 0;
|
||||||
fullFlash = 0;
|
fullFlash = 0;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var start = flashes;
|
var start = flashes;
|
||||||
Run(ref data, ref flashes);
|
Run(ref data, ref flashes);
|
||||||
if (flashes - start == 100)
|
if (flashes - start == 100)
|
||||||
{
|
{
|
||||||
fullFlash = i + 1;
|
fullFlash = i + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flashes;
|
return flashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(ref byte[] data, ref int flashes)
|
public void Run(ref byte[] data, ref int flashes)
|
||||||
{
|
{
|
||||||
Increment(ref data);
|
Increment(ref data);
|
||||||
Flash(ref data, ref flashes);
|
Flash(ref data, ref flashes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Increment(ref byte[] data)
|
private static void Increment(ref byte[] data)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < data.Length; i++)
|
for (int i = 0; i < data.Length; i++)
|
||||||
data[i]++;
|
data[i]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Flash(ref byte[] data, ref int flashes)
|
private void Flash(ref byte[] data, ref int flashes)
|
||||||
{
|
{
|
||||||
int diff;
|
int diff;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
var startFlash = flashes;
|
var startFlash = flashes;
|
||||||
for (int i = 0; i < data.Length; i++)
|
for (int i = 0; i < data.Length; i++)
|
||||||
{
|
{
|
||||||
if (data[i] > 9)
|
if (data[i] > 9)
|
||||||
PerformFlash(ref data, i, ref flashes);
|
PerformFlash(ref data, i, ref flashes);
|
||||||
}
|
}
|
||||||
diff = flashes - startFlash;
|
diff = flashes - startFlash;
|
||||||
} while (diff != 0);
|
} while (diff != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PerformFlash(ref byte[] data, int index, ref int flashes)
|
private void PerformFlash(ref byte[] data, int index, ref int flashes)
|
||||||
{
|
{
|
||||||
flashes++;
|
flashes++;
|
||||||
var y = index / 10;
|
var y = index / 10;
|
||||||
var x = index % 10;
|
var x = index % 10;
|
||||||
|
|
||||||
data[index] = 0;
|
data[index] = 0;
|
||||||
|
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
{
|
{
|
||||||
//Left
|
//Left
|
||||||
index = x - 1 + y * 10;
|
index = x - 1 + y * 10;
|
||||||
if (index >= 0 && data[index] != 0)
|
if (index >= 0 && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
if (x < 9)
|
if (x < 9)
|
||||||
{
|
{
|
||||||
//Right
|
//Right
|
||||||
index = x + 1 + y * 10;
|
index = x + 1 + y * 10;
|
||||||
if (index < data.Length && data[index] != 0)
|
if (index < data.Length && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
if (y > 0)
|
if (y > 0)
|
||||||
{
|
{
|
||||||
//Up
|
//Up
|
||||||
index = x + 0 + (y - 1) * 10;
|
index = x + 0 + (y - 1) * 10;
|
||||||
if (index >= 0 && data[index] != 0)
|
if (index >= 0 && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
{
|
{
|
||||||
//Up Left
|
//Up Left
|
||||||
index = x - 1 + (y - 1) * 10;
|
index = x - 1 + (y - 1) * 10;
|
||||||
if (index >= 0 && data[index] != 0)
|
if (index >= 0 && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
if (x < 9)
|
if (x < 9)
|
||||||
{
|
{
|
||||||
//Up Right
|
//Up Right
|
||||||
index = x + 1 + (y - 1) * 10;
|
index = x + 1 + (y - 1) * 10;
|
||||||
if (index < data.Length && data[index] != 0)
|
if (index < data.Length && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < 9)
|
if (y < 9)
|
||||||
{
|
{
|
||||||
//Bottom
|
//Bottom
|
||||||
index = x + 0 + (y + 1) * 10;
|
index = x + 0 + (y + 1) * 10;
|
||||||
if (index < data.Length && data[index] != 0)
|
if (index < data.Length && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
{
|
{
|
||||||
//Bottom Left
|
//Bottom Left
|
||||||
index = x - 1 + (y + 1) * 10;
|
index = x - 1 + (y + 1) * 10;
|
||||||
if (index < data.Length && data[index] != 0)
|
if (index < data.Length && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
if (x < 9)
|
if (x < 9)
|
||||||
{
|
{
|
||||||
//Bottom Right
|
//Bottom Right
|
||||||
index = x + 1 + (y + 1) * 10;
|
index = x + 1 + (y + 1) * 10;
|
||||||
if (index < data.Length && data[index] != 0)
|
if (index < data.Length && data[index] != 0)
|
||||||
data[index]++;
|
data[index]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public override string ToString()
|
//public override string ToString()
|
||||||
//{
|
//{
|
||||||
// var output = new StringBuilder();
|
// var output = new StringBuilder();
|
||||||
// for (int y = 0; y < 10; y++)
|
// for (int y = 0; y < 10; y++)
|
||||||
// {
|
// {
|
||||||
// for (int x = 0; x < 10; x++)
|
// for (int x = 0; x < 10; x++)
|
||||||
// {
|
// {
|
||||||
// output.Append(DataPart1[x + y * 10]);
|
// output.Append(DataPart1[x + y * 10]);
|
||||||
// }
|
// }
|
||||||
// output.AppendLine();
|
// output.AppendLine();
|
||||||
// }
|
// }
|
||||||
// return output.ToString();
|
// return output.ToString();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//public void Render()
|
//public void Render()
|
||||||
//{
|
//{
|
||||||
// for (int y = 0; y < 10; y++)
|
// for (int y = 0; y < 10; y++)
|
||||||
// {
|
// {
|
||||||
// for (int x = 0; x < 10; x++)
|
// for (int x = 0; x < 10; x++)
|
||||||
// {
|
// {
|
||||||
// var index = x + y * 10;
|
// var index = x + y * 10;
|
||||||
// if (DataPart1[index] == 0)
|
// if (DataPart1[index] == 0)
|
||||||
// Console.ForegroundColor = ConsoleColor.Magenta;
|
// Console.ForegroundColor = ConsoleColor.Magenta;
|
||||||
// else
|
// else
|
||||||
// Console.ForegroundColor = ConsoleColor.White;
|
// Console.ForegroundColor = ConsoleColor.White;
|
||||||
// Console.Write(DataPart1[index]);
|
// Console.Write(DataPart1[index]);
|
||||||
// }
|
// }
|
||||||
// Console.WriteLine();
|
// Console.WriteLine();
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
@@ -1,71 +1,71 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2021.Day3;
|
namespace AdventOfCode.Problems.AOC2021.Day3;
|
||||||
|
|
||||||
[ProblemInfo(2021, 3, "Binary Diagnostic")]
|
[ProblemInfo(2021, 3, "Binary Diagnostic")]
|
||||||
public class BinaryDiagnostic : Problem<int, int>
|
public class BinaryDiagnostic : Problem<int, int>
|
||||||
{
|
{
|
||||||
public int[][] Data { get; set; } = Array.Empty<int[]>();
|
public int[][] Data { get; set; } = Array.Empty<int[]>();
|
||||||
|
|
||||||
private static int ToDecimal(int[] value)
|
private static int ToDecimal(int[] value)
|
||||||
{
|
{
|
||||||
return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum();
|
return (int)value.Select((b, idx) => b * Math.Pow(2, value.Length - idx - 1)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputLines();
|
var data = ReadInputLines();
|
||||||
Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray();
|
Data = data.Select(line => line.Select(b => int.Parse(b.ToString())).ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var width = Data[0].Length;
|
var width = Data[0].Length;
|
||||||
var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx]));
|
var transposed = Enumerable.Range(0, width).Select(idx => Data.Select(row => row[idx]));
|
||||||
|
|
||||||
var transposed2 = new int[width][];
|
var transposed2 = new int[width][];
|
||||||
for (int i = 0; i < width; i++)
|
for (int i = 0; i < width; i++)
|
||||||
{
|
{
|
||||||
transposed2[i] = Data.Select(row => row[i]).ToArray();
|
transposed2[i] = Data.Select(row => row[i]).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
var mid = Data.Length / 2;
|
var mid = Data.Length / 2;
|
||||||
var gamma = transposed.Select(col => col.Count(c => c == 1) > mid ? 1 : 0).ToArray();
|
var gamma = transposed.Select(col => col.Count(c => c == 1) > mid ? 1 : 0).ToArray();
|
||||||
var epsilon = gamma.Select(b => b == 0 ? 1 : 0).ToArray();
|
var epsilon = gamma.Select(b => b == 0 ? 1 : 0).ToArray();
|
||||||
|
|
||||||
var gammaDec = ToDecimal(gamma);
|
var gammaDec = ToDecimal(gamma);
|
||||||
var epsilongDec = ToDecimal(epsilon);
|
var epsilongDec = ToDecimal(epsilon);
|
||||||
|
|
||||||
Part1 = gammaDec * epsilongDec;
|
Part1 = gammaDec * epsilongDec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var oxygen = Data;
|
var oxygen = Data;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
while (oxygen.Length > 1)
|
while (oxygen.Length > 1)
|
||||||
{
|
{
|
||||||
var t = oxygen.Select(row => row[index]);
|
var t = oxygen.Select(row => row[index]);
|
||||||
var m = oxygen.Length / 2f;
|
var m = oxygen.Length / 2f;
|
||||||
var g = t.Count(c => c == 1) >= m ? 1 : 0;
|
var g = t.Count(c => c == 1) >= m ? 1 : 0;
|
||||||
oxygen = oxygen.Where(row => row[index] == g).ToArray();
|
oxygen = oxygen.Where(row => row[index] == g).ToArray();
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var carbon = Data;
|
var carbon = Data;
|
||||||
index = 0;
|
index = 0;
|
||||||
while (carbon.Length > 1)
|
while (carbon.Length > 1)
|
||||||
{
|
{
|
||||||
var t = carbon.Select(row => row[index]);
|
var t = carbon.Select(row => row[index]);
|
||||||
var m = carbon.Length / 2f;
|
var m = carbon.Length / 2f;
|
||||||
var e = t.Count(c => c == 1) < m ? 1 : 0;
|
var e = t.Count(c => c == 1) < m ? 1 : 0;
|
||||||
carbon = carbon.Where(row => row[index] == e).ToArray();
|
carbon = carbon.Where(row => row[index] == e).ToArray();
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oxygenLevel = ToDecimal(oxygen.First());
|
var oxygenLevel = ToDecimal(oxygen.First());
|
||||||
var carbonLevel = ToDecimal(carbon.First());
|
var carbonLevel = ToDecimal(carbon.First());
|
||||||
|
|
||||||
Part2 = oxygenLevel * carbonLevel;
|
Part2 = oxygenLevel * carbonLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,50 +1,50 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2021.Day6;
|
namespace AdventOfCode.Problems.AOC2021.Day6;
|
||||||
|
|
||||||
[ProblemInfo(2021, 6, "Lanternfish")]
|
[ProblemInfo(2021, 6, "Lanternfish")]
|
||||||
internal class LanternFish : Problem<long, long>
|
internal class LanternFish : Problem<long, long>
|
||||||
{
|
{
|
||||||
public int[] Data { get; private set; } = Array.Empty<int>();
|
public int[] Data { get; private set; } = Array.Empty<int>();
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var input = ReadInputLines();
|
var input = ReadInputLines();
|
||||||
Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray();
|
Data = input.First().Split(",").Select(v => int.Parse(v)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var lifetimes = PrepareLifetimes();
|
var lifetimes = PrepareLifetimes();
|
||||||
Part1 = Simulate(lifetimes, 80);
|
Part1 = Simulate(lifetimes, 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var lifetimes = PrepareLifetimes();
|
var lifetimes = PrepareLifetimes();
|
||||||
Part2 = Simulate(lifetimes, 256);
|
Part2 = Simulate(lifetimes, 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long[] PrepareLifetimes()
|
private long[] PrepareLifetimes()
|
||||||
{
|
{
|
||||||
var lifetimes = new long[9];
|
var lifetimes = new long[9];
|
||||||
foreach (var life in Data)
|
foreach (var life in Data)
|
||||||
lifetimes[life] += 1;
|
lifetimes[life] += 1;
|
||||||
|
|
||||||
return lifetimes;
|
return lifetimes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long Simulate(long[] lifetimes, int days)
|
private static long Simulate(long[] lifetimes, int days)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < days; i++)
|
for (int i = 0; i < days; i++)
|
||||||
{
|
{
|
||||||
var day0Count = lifetimes[0];
|
var day0Count = lifetimes[0];
|
||||||
for (int j = 1; j < lifetimes.Length; j++)
|
for (int j = 1; j < lifetimes.Length; j++)
|
||||||
lifetimes[j - 1] = lifetimes[j];
|
lifetimes[j - 1] = lifetimes[j];
|
||||||
lifetimes[6] += day0Count;
|
lifetimes[6] += day0Count;
|
||||||
lifetimes[^1] = day0Count;
|
lifetimes[^1] = day0Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lifetimes.Sum();
|
return lifetimes.Sum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,32 +1,32 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day0;
|
namespace AdventOfCode.Problems.AOC2022.Day0;
|
||||||
|
|
||||||
[ProblemInfo(2022, 0, "Fancy Test")]
|
[ProblemInfo(2022, 0, "Fancy Test")]
|
||||||
public class TestProblem : Problem
|
public class TestProblem : Problem
|
||||||
{
|
{
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PrintPart1()
|
public override void PrintPart1()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Result");
|
Console.WriteLine("Result");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PrintPart2()
|
public override void PrintPart2()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Result 2");
|
Console.WriteLine("Result 2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,54 +1,54 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day1;
|
namespace AdventOfCode.Problems.AOC2022.Day1;
|
||||||
|
|
||||||
[ProblemInfo(2022, 1, "Calorie Counting")]
|
[ProblemInfo(2022, 1, "Calorie Counting")]
|
||||||
internal class CalorieCounting : Problem
|
internal class CalorieCounting : Problem
|
||||||
{
|
{
|
||||||
public List<List<int>> FlaresFood { get; set; }
|
public List<List<int>> FlaresFood { get; set; }
|
||||||
|
|
||||||
private (int calories, int elf)? _mostestElf;
|
private (int calories, int elf)? _mostestElf;
|
||||||
private IEnumerable<(int sum, int idx)>? _mostestElves;
|
private IEnumerable<(int sum, int idx)>? _mostestElves;
|
||||||
|
|
||||||
public CalorieCounting()
|
public CalorieCounting()
|
||||||
{
|
{
|
||||||
FlaresFood = new List<List<int>>
|
FlaresFood = new List<List<int>>
|
||||||
{
|
{
|
||||||
new List<int>()
|
new List<int>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = File.ReadAllLines(GetInputFile("input.txt"));
|
var lines = File.ReadAllLines(GetInputFile("input.txt"));
|
||||||
var c = 0;
|
var c = 0;
|
||||||
foreach (var calorie in lines)
|
foreach (var calorie in lines)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(calorie))
|
if (string.IsNullOrWhiteSpace(calorie))
|
||||||
{
|
{
|
||||||
FlaresFood.Add(new List<int>());
|
FlaresFood.Add(new List<int>());
|
||||||
c++;
|
c++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FlaresFood[c].Add(int.Parse(calorie));
|
FlaresFood[c].Add(int.Parse(calorie));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
_mostestElf = FlaresFood
|
_mostestElf = FlaresFood
|
||||||
.Select((x, idx) => (sum: x.Sum(), idx))
|
.Select((x, idx) => (sum: x.Sum(), idx))
|
||||||
.MaxBy(x => x.sum);
|
.MaxBy(x => x.sum);
|
||||||
|
|
||||||
Part1 = _mostestElf.Value.ToString();
|
Part1 = _mostestElf.Value.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
_mostestElves = FlaresFood
|
_mostestElves = FlaresFood
|
||||||
.Select((x, idx) => (sum: x.Sum(), idx))
|
.Select((x, idx) => (sum: x.Sum(), idx))
|
||||||
.OrderByDescending(e => e.sum)
|
.OrderByDescending(e => e.sum)
|
||||||
.Take(3);
|
.Take(3);
|
||||||
Part2 = _mostestElves.Sum(e => e.sum).ToString();
|
Part2 = _mostestElves.Sum(e => e.sum).ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,66 +1,66 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2022.Day10;
|
namespace AdventOfCode.Problems.AOC2022.Day10;
|
||||||
|
|
||||||
internal class CathodeCPU
|
internal class CathodeCPU
|
||||||
{
|
{
|
||||||
public enum Instruction
|
public enum Instruction
|
||||||
{
|
{
|
||||||
NoOp,
|
NoOp,
|
||||||
AddX
|
AddX
|
||||||
}
|
}
|
||||||
|
|
||||||
public int X { get; private set; } = 1;
|
public int X { get; private set; } = 1;
|
||||||
private int _cycleNumber = 1;
|
private int _cycleNumber = 1;
|
||||||
private int _programCounter;
|
private int _programCounter;
|
||||||
private int _pending = -1;
|
private int _pending = -1;
|
||||||
|
|
||||||
public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func<int, int, int>? processor = null)
|
public int[] ExecuteCode((Instruction ins, int value)[] code, int[] outputCycles, Func<int, int, int>? processor = null)
|
||||||
{
|
{
|
||||||
var result = new int[outputCycles.Length];
|
var result = new int[outputCycles.Length];
|
||||||
|
|
||||||
var ridx = 0;
|
var ridx = 0;
|
||||||
|
|
||||||
if (processor == null)
|
if (processor == null)
|
||||||
processor = (c, x) => c * x;
|
processor = (c, x) => c * x;
|
||||||
|
|
||||||
ExecuteCode(code, (c, x) =>
|
ExecuteCode(code, (c, x) =>
|
||||||
{
|
{
|
||||||
if (ridx < outputCycles.Length && c == outputCycles[ridx])
|
if (ridx < outputCycles.Length && c == outputCycles[ridx])
|
||||||
{
|
{
|
||||||
result[ridx] = processor(c, x);
|
result[ridx] = processor(c, x);
|
||||||
ridx++;
|
ridx++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteCode((Instruction ins, int value)[] code, Action<int, int> processor)
|
public void ExecuteCode((Instruction ins, int value)[] code, Action<int, int> processor)
|
||||||
{
|
{
|
||||||
while (_programCounter < code.Length)
|
while (_programCounter < code.Length)
|
||||||
{
|
{
|
||||||
var (ins, value) = code[_programCounter];
|
var (ins, value) = code[_programCounter];
|
||||||
|
|
||||||
processor(_cycleNumber, X);
|
processor(_cycleNumber, X);
|
||||||
|
|
||||||
switch ((ins, _pending))
|
switch ((ins, _pending))
|
||||||
{
|
{
|
||||||
case { ins: Instruction.NoOp }:
|
case { ins: Instruction.NoOp }:
|
||||||
_programCounter++;
|
_programCounter++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case { ins: Instruction.AddX, _pending: -1 }:
|
case { ins: Instruction.AddX, _pending: -1 }:
|
||||||
_pending = 1;
|
_pending = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case { ins: Instruction.AddX, _pending: 0 }:
|
case { ins: Instruction.AddX, _pending: 0 }:
|
||||||
X += value;
|
X += value;
|
||||||
_programCounter++;
|
_programCounter++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pending >= 0)
|
if (_pending >= 0)
|
||||||
_pending--;
|
_pending--;
|
||||||
_cycleNumber++;
|
_cycleNumber++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,55 +1,55 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day10;
|
namespace AdventOfCode.Problems.AOC2022.Day10;
|
||||||
|
|
||||||
[ProblemInfo(2022, 10, "Cathode-Ray Tube")]
|
[ProblemInfo(2022, 10, "Cathode-Ray Tube")]
|
||||||
internal class CathodeRayTube : Problem<int, string>
|
internal class CathodeRayTube : Problem<int, string>
|
||||||
{
|
{
|
||||||
private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>();
|
private (CathodeCPU.Instruction ins, int value)[] _code = Array.Empty<(CathodeCPU.Instruction ins, int value)>();
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var cpu = new CathodeCPU();
|
var cpu = new CathodeCPU();
|
||||||
var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 });
|
var result = cpu.ExecuteCode(_code, new[] { 20, 60, 100, 140, 180, 220 });
|
||||||
Part1 = result.Sum();
|
Part1 = result.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var output = Enumerable.Repeat(' ', 6 * 40).ToArray();
|
var output = Enumerable.Repeat(' ', 6 * 40).ToArray();
|
||||||
|
|
||||||
var cpu = new CathodeCPU();
|
var cpu = new CathodeCPU();
|
||||||
cpu.ExecuteCode(_code, (cycle, signal) =>
|
cpu.ExecuteCode(_code, (cycle, signal) =>
|
||||||
{
|
{
|
||||||
cycle -= 1;
|
cycle -= 1;
|
||||||
if (cycle > output.Length)
|
if (cycle > output.Length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var pos = signal % 40;
|
var pos = signal % 40;
|
||||||
var head = (cycle % 40);
|
var head = (cycle % 40);
|
||||||
var sprite = Math.Abs(pos - head);
|
var sprite = Math.Abs(pos - head);
|
||||||
if (sprite <= 1)
|
if (sprite <= 1)
|
||||||
output[cycle] = '█';
|
output[cycle] = '█';
|
||||||
});
|
});
|
||||||
|
|
||||||
var lines = output.Chunk(40).Select(r => new string(r));
|
var lines = output.Chunk(40).Select(r => new string(r));
|
||||||
Part2 = $"\n{string.Join("\n", lines)}";
|
Part2 = $"\n{string.Join("\n", lines)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
_code = new (CathodeCPU.Instruction ins, int value)[lines.Length];
|
_code = new (CathodeCPU.Instruction ins, int value)[lines.Length];
|
||||||
for (int i = 0; i < lines.Length; i++)
|
for (int i = 0; i < lines.Length; i++)
|
||||||
{
|
{
|
||||||
var ln = lines[i];
|
var ln = lines[i];
|
||||||
if (ln == "noop")
|
if (ln == "noop")
|
||||||
_code[i] = (CathodeCPU.Instruction.NoOp, 0);
|
_code[i] = (CathodeCPU.Instruction.NoOp, 0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var instruction = ln.Split(' ');
|
var instruction = ln.Split(' ');
|
||||||
_code[i] = (Enum.Parse<CathodeCPU.Instruction>(instruction[0], true), int.Parse(instruction[1]));
|
_code[i] = (Enum.Parse<CathodeCPU.Instruction>(instruction[0], true), int.Parse(instruction[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,73 +1,73 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day11;
|
namespace AdventOfCode.Problems.AOC2022.Day11;
|
||||||
|
|
||||||
internal class Monkey
|
internal class Monkey
|
||||||
{
|
{
|
||||||
public int MonkeyNumber { get; set; }
|
public int MonkeyNumber { get; set; }
|
||||||
public int InspectionCount { get; private set; }
|
public int InspectionCount { get; private set; }
|
||||||
public List<BigInteger> Items { get; set; }
|
public List<BigInteger> Items { get; set; }
|
||||||
|
|
||||||
private MonkeyOperator _operator;
|
private MonkeyOperator _operator;
|
||||||
private uint _operand;
|
private uint _operand;
|
||||||
private uint _divisor;
|
private uint _divisor;
|
||||||
private int _trueTarget;
|
private int _trueTarget;
|
||||||
private int _falseTarget;
|
private int _falseTarget;
|
||||||
|
|
||||||
public Monkey(string[] lines)
|
public Monkey(string[] lines)
|
||||||
{
|
{
|
||||||
Items = new List<BigInteger>();
|
Items = new List<BigInteger>();
|
||||||
MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]);
|
MonkeyNumber = int.Parse(lines[0].Split(' ')[^1][0..^1]);
|
||||||
Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList();
|
Items = lines[1].Split(": ")[^1].Split(", ").Select(v => BigInteger.Parse(v)).ToList();
|
||||||
var operation = lines[2].Split("= old ")[^1];
|
var operation = lines[2].Split("= old ")[^1];
|
||||||
_operator = operation[0] switch
|
_operator = operation[0] switch
|
||||||
{
|
{
|
||||||
'*' => MonkeyOperator.Multiply,
|
'*' => MonkeyOperator.Multiply,
|
||||||
'+' => MonkeyOperator.Add,
|
'+' => MonkeyOperator.Add,
|
||||||
_ => MonkeyOperator.Add
|
_ => MonkeyOperator.Add
|
||||||
};
|
};
|
||||||
if (!uint.TryParse(operation[1..], out _operand))
|
if (!uint.TryParse(operation[1..], out _operand))
|
||||||
_operator = MonkeyOperator.Power;
|
_operator = MonkeyOperator.Power;
|
||||||
|
|
||||||
_divisor = uint.Parse(lines[3].Split(' ')[^1]);
|
_divisor = uint.Parse(lines[3].Split(' ')[^1]);
|
||||||
_trueTarget = int.Parse(lines[4].Split(' ')[^1]);
|
_trueTarget = int.Parse(lines[4].Split(' ')[^1]);
|
||||||
_falseTarget = int.Parse(lines[5].Split(' ')[^1]);
|
_falseTarget = int.Parse(lines[5].Split(' ')[^1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger Inspect(BigInteger value, uint worryOffset = 3)
|
public BigInteger Inspect(BigInteger value, uint worryOffset = 3)
|
||||||
{
|
{
|
||||||
InspectionCount++;
|
InspectionCount++;
|
||||||
value = Operate(value);
|
value = Operate(value);
|
||||||
if (worryOffset != 0)
|
if (worryOffset != 0)
|
||||||
value /= worryOffset;
|
value /= worryOffset;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetThrowTarget(BigInteger value)
|
public int GetThrowTarget(BigInteger value)
|
||||||
{
|
{
|
||||||
return value % _divisor == 0 ? _trueTarget : _falseTarget;
|
return value % _divisor == 0 ? _trueTarget : _falseTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigInteger Operate(BigInteger value)
|
private BigInteger Operate(BigInteger value)
|
||||||
{
|
{
|
||||||
return _operator switch
|
return _operator switch
|
||||||
{
|
{
|
||||||
MonkeyOperator.Multiply => value * _operand,
|
MonkeyOperator.Multiply => value * _operand,
|
||||||
MonkeyOperator.Add => value + _operand,
|
MonkeyOperator.Add => value + _operand,
|
||||||
MonkeyOperator.Power => value * value,
|
MonkeyOperator.Power => value * value,
|
||||||
_ => value
|
_ => value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum MonkeyOperator
|
private enum MonkeyOperator
|
||||||
{
|
{
|
||||||
Multiply,
|
Multiply,
|
||||||
Add,
|
Add,
|
||||||
Power
|
Power
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]";
|
return $"{MonkeyNumber}: ({InspectionCount}) [{string.Join(", ", Items)}]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,60 +1,60 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day11;
|
namespace AdventOfCode.Problems.AOC2022.Day11;
|
||||||
|
|
||||||
[ProblemInfo(2022, 11, "Monkey in the Middle")]
|
[ProblemInfo(2022, 11, "Monkey in the Middle")]
|
||||||
internal class MonkeyInTheMiddle : Problem<int, int>
|
internal class MonkeyInTheMiddle : Problem<int, int>
|
||||||
{
|
{
|
||||||
private Monkey[] _monkeysPart1 = Array.Empty<Monkey>();
|
private Monkey[] _monkeysPart1 = Array.Empty<Monkey>();
|
||||||
private Monkey[] _monkeysPart2 = Array.Empty<Monkey>();
|
private Monkey[] _monkeysPart2 = Array.Empty<Monkey>();
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Simulate(_monkeysPart1, 20);
|
Simulate(_monkeysPart1, 20);
|
||||||
Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount)
|
Part1 = _monkeysPart1.OrderByDescending(m => m.InspectionCount)
|
||||||
.Take(2)
|
.Take(2)
|
||||||
.Select(m => m.InspectionCount)
|
.Select(m => m.InspectionCount)
|
||||||
.Aggregate((a, b) => a * b);
|
.Aggregate((a, b) => a * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Simulate(_monkeysPart2, 10000, 0);
|
Simulate(_monkeysPart2, 10000, 0);
|
||||||
Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount)
|
Part2 = _monkeysPart2.OrderByDescending(m => m.InspectionCount)
|
||||||
.Take(2)
|
.Take(2)
|
||||||
.Select(m => m.InspectionCount)
|
.Select(m => m.InspectionCount)
|
||||||
.Aggregate((a, b) => a * b);
|
.Aggregate((a, b) => a * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("test.txt").Chunk(7);
|
var lines = ReadInputLines("test.txt").Chunk(7);
|
||||||
_monkeysPart1 = lines.Select(ln => new Monkey(ln)).ToArray();
|
_monkeysPart1 = lines.Select(ln => new Monkey(ln)).ToArray();
|
||||||
_monkeysPart2 = lines.Select(ln => new Monkey(ln)).ToArray();
|
_monkeysPart2 = lines.Select(ln => new Monkey(ln)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Simulate(Monkey[] monkeys, int rounds, uint worry = 3)
|
private static void Simulate(Monkey[] monkeys, int rounds, uint worry = 3)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < rounds; i++)
|
for (int i = 0; i < rounds; i++)
|
||||||
{
|
{
|
||||||
SimulateRound(monkeys, worry);
|
SimulateRound(monkeys, worry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SimulateRound(Monkey[] monkeys, uint worry = 3)
|
private static void SimulateRound(Monkey[] monkeys, uint worry = 3)
|
||||||
{
|
{
|
||||||
foreach (var monkey in monkeys)
|
foreach (var monkey in monkeys)
|
||||||
SimulateTurn(monkey, monkeys, worry);
|
SimulateTurn(monkey, monkeys, worry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3)
|
private static void SimulateTurn(Monkey monkey, Monkey[] monkeys, uint worry = 3)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < monkey.Items.Count; i++)
|
for (int i = 0; i < monkey.Items.Count; i++)
|
||||||
{
|
{
|
||||||
var item = monkey.Inspect(monkey.Items[i], worry);
|
var item = monkey.Inspect(monkey.Items[i], worry);
|
||||||
var target = monkey.GetThrowTarget(item);
|
var target = monkey.GetThrowTarget(item);
|
||||||
monkeys[target].Items.Add(item);
|
monkeys[target].Items.Add(item);
|
||||||
}
|
}
|
||||||
monkey.Items.Clear();
|
monkey.Items.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day12;
|
namespace AdventOfCode.Problems.AOC2022.Day12;
|
||||||
|
|
||||||
[ProblemInfo(2022, 12, "Hill Climbing Algorithm")]
|
[ProblemInfo(2022, 12, "Hill Climbing Algorithm")]
|
||||||
internal class HillClimbing : Problem
|
internal class HillClimbing : Problem
|
||||||
{
|
{
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day13;
|
namespace AdventOfCode.Problems.AOC2022.Day13;
|
||||||
|
|
||||||
[ProblemInfo(2022, 13, "Distress Signal")]
|
[ProblemInfo(2022, 13, "Distress Signal")]
|
||||||
internal class DistressSignal : Problem
|
internal class DistressSignal : Problem
|
||||||
{
|
{
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day14;
|
namespace AdventOfCode.Problems.AOC2022.Day14;
|
||||||
|
|
||||||
[ProblemInfo(2022, 14, "Regolith Reservoir")]
|
[ProblemInfo(2022, 14, "Regolith Reservoir")]
|
||||||
internal class RegolithReservoir : Problem
|
internal class RegolithReservoir : Problem
|
||||||
{
|
{
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,100 +1,100 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day2;
|
namespace AdventOfCode.Problems.AOC2022.Day2;
|
||||||
|
|
||||||
[ProblemInfo(2022, 2, "Rock Paper Scissors")]
|
[ProblemInfo(2022, 2, "Rock Paper Scissors")]
|
||||||
internal class RockPaperScissors : Problem
|
internal class RockPaperScissors : Problem
|
||||||
{
|
{
|
||||||
private string[] _lines;
|
private string[] _lines;
|
||||||
|
|
||||||
public RockPaperScissors()
|
public RockPaperScissors()
|
||||||
{
|
{
|
||||||
_lines = Array.Empty<string>();
|
_lines = Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_lines = File.ReadAllLines(GetInputFile("input.txt"));
|
_lines = File.ReadAllLines(GetInputFile("input.txt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var totalScore = 0;
|
var totalScore = 0;
|
||||||
foreach (var line in _lines)
|
foreach (var line in _lines)
|
||||||
{
|
{
|
||||||
var move = line[0];
|
var move = line[0];
|
||||||
var response = line[^1];
|
var response = line[^1];
|
||||||
|
|
||||||
totalScore += GetMoveValue(response);
|
totalScore += GetMoveValue(response);
|
||||||
totalScore += GetResult(move, response);
|
totalScore += GetResult(move, response);
|
||||||
}
|
}
|
||||||
Part1 = totalScore.ToString();
|
Part1 = totalScore.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetMoveValue(char move)
|
private static int GetMoveValue(char move)
|
||||||
{
|
{
|
||||||
return move switch
|
return move switch
|
||||||
{
|
{
|
||||||
'A' => 1,
|
'A' => 1,
|
||||||
'B' => 2,
|
'B' => 2,
|
||||||
'C' => 3,
|
'C' => 3,
|
||||||
'X' => 1,
|
'X' => 1,
|
||||||
'Y' => 2,
|
'Y' => 2,
|
||||||
'Z' => 3,
|
'Z' => 3,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetResult(char move, char response)
|
private static int GetResult(char move, char response)
|
||||||
{
|
{
|
||||||
return (move, response) switch
|
return (move, response) switch
|
||||||
{
|
{
|
||||||
('A', 'X') => 3,
|
('A', 'X') => 3,
|
||||||
('B', 'X') => 0,
|
('B', 'X') => 0,
|
||||||
('C', 'X') => 6,
|
('C', 'X') => 6,
|
||||||
('A', 'Y') => 6,
|
('A', 'Y') => 6,
|
||||||
('B', 'Y') => 3,
|
('B', 'Y') => 3,
|
||||||
('C', 'Y') => 0,
|
('C', 'Y') => 0,
|
||||||
('A', 'Z') => 0,
|
('A', 'Z') => 0,
|
||||||
('B', 'Z') => 6,
|
('B', 'Z') => 6,
|
||||||
('C', 'Z') => 3,
|
('C', 'Z') => 3,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetResultValue(char result)
|
private static int GetResultValue(char result)
|
||||||
{
|
{
|
||||||
return result switch
|
return result switch
|
||||||
{
|
{
|
||||||
'X' => 0,
|
'X' => 0,
|
||||||
'Y' => 3,
|
'Y' => 3,
|
||||||
'Z' => 6,
|
'Z' => 6,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetResponseValue(char move, char result)
|
private static int GetResponseValue(char move, char result)
|
||||||
{
|
{
|
||||||
var p = result switch
|
var p = result switch
|
||||||
{
|
{
|
||||||
'X' => (GetMoveValue(move) + 2) % 3, //Lose
|
'X' => (GetMoveValue(move) + 2) % 3, //Lose
|
||||||
'Y' => GetMoveValue(move), //Tie
|
'Y' => GetMoveValue(move), //Tie
|
||||||
'Z' => (GetMoveValue(move) + 1) % 3, //Win
|
'Z' => (GetMoveValue(move) + 1) % 3, //Win
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
return p == 0 ? 3 : p;
|
return p == 0 ? 3 : p;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var score = 0;
|
var score = 0;
|
||||||
foreach (var line in _lines)
|
foreach (var line in _lines)
|
||||||
{
|
{
|
||||||
var move = line[0];
|
var move = line[0];
|
||||||
var result = line[^1];
|
var result = line[^1];
|
||||||
score += GetResponseValue(move, result);
|
score += GetResponseValue(move, result);
|
||||||
score += GetResultValue(result);
|
score += GetResultValue(result);
|
||||||
}
|
}
|
||||||
Part2 = score.ToString();
|
Part2 = score.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,54 +1,54 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day3;
|
namespace AdventOfCode.Problems.AOC2022.Day3;
|
||||||
|
|
||||||
[ProblemInfo(2022, 3, "Rucksack Reorganization")]
|
[ProblemInfo(2022, 3, "Rucksack Reorganization")]
|
||||||
internal class RucksackReorganization : Problem
|
internal class RucksackReorganization : Problem
|
||||||
{
|
{
|
||||||
private string[] _sacks;
|
private string[] _sacks;
|
||||||
|
|
||||||
public RucksackReorganization()
|
public RucksackReorganization()
|
||||||
{
|
{
|
||||||
_sacks = Array.Empty<string>();
|
_sacks = Array.Empty<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_sacks = ReadInputLines("input.txt");
|
_sacks = ReadInputLines("input.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var total = 0;
|
var total = 0;
|
||||||
foreach (var sack in _sacks)
|
foreach (var sack in _sacks)
|
||||||
{
|
{
|
||||||
var mid = sack.Length / 2;
|
var mid = sack.Length / 2;
|
||||||
var left = sack[..mid];
|
var left = sack[..mid];
|
||||||
var right = sack[mid..];
|
var right = sack[mid..];
|
||||||
var common = right.First(itm => left.Contains(itm));
|
var common = right.First(itm => left.Contains(itm));
|
||||||
total += GetValue(common);
|
total += GetValue(common);
|
||||||
}
|
}
|
||||||
Part1 = total.ToString();
|
Part1 = total.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetValue(char c)
|
public static int GetValue(char c)
|
||||||
{
|
{
|
||||||
return c switch
|
return c switch
|
||||||
{
|
{
|
||||||
<= 'Z' => c - 'A' + 27,
|
<= 'Z' => c - 'A' + 27,
|
||||||
_ => c - 'a' + 1
|
_ => c - 'a' + 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var groups = _sacks.Chunk(3);
|
var groups = _sacks.Chunk(3);
|
||||||
var total = 0;
|
var total = 0;
|
||||||
foreach (var group in groups)
|
foreach (var group in groups)
|
||||||
{
|
{
|
||||||
var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge)));
|
var badgeType = group[0].First(badge => group[1..].All(sack => sack.Contains(badge)));
|
||||||
total += GetValue(badgeType);
|
total += GetValue(badgeType);
|
||||||
}
|
}
|
||||||
Part2 = total.ToString();
|
Part2 = total.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day4;
|
namespace AdventOfCode.Problems.AOC2022.Day4;
|
||||||
|
|
||||||
[ProblemInfo(2022, 4, "Camp Cleanup")]
|
[ProblemInfo(2022, 4, "Camp Cleanup")]
|
||||||
internal class CampCleanup : Problem<int, int>
|
internal class CampCleanup : Problem<int, int>
|
||||||
{
|
{
|
||||||
private List<(Range a, Range b)> _pairs = new(500);
|
private List<(Range a, Range b)> _pairs = new(500);
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
var (a, b) = line.Split(',')
|
var (a, b) = line.Split(',')
|
||||||
.Select(range =>
|
.Select(range =>
|
||||||
range.Split('-')
|
range.Split('-')
|
||||||
.Select(v => int.Parse(v))
|
.Select(v => int.Parse(v))
|
||||||
.Chunk(2)
|
.Chunk(2)
|
||||||
.Select(r => new Range(r.First(), r.Last()))
|
.Select(r => new Range(r.First(), r.Last()))
|
||||||
.First()
|
.First()
|
||||||
).Chunk(2)
|
).Chunk(2)
|
||||||
.Select(pair => (pair.First(), pair.Last()))
|
.Select(pair => (pair.First(), pair.Last()))
|
||||||
.First();
|
.First();
|
||||||
_pairs.Add((a, b));
|
_pairs.Add((a, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var total = 0;
|
var total = 0;
|
||||||
foreach (var (a, b) in _pairs)
|
foreach (var (a, b) in _pairs)
|
||||||
{
|
{
|
||||||
if (a.Contains(b) || b.Contains(a))
|
if (a.Contains(b) || b.Contains(a))
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
Part1 = total;
|
Part1 = total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
foreach (var (a, b) in _pairs)
|
foreach (var (a, b) in _pairs)
|
||||||
{
|
{
|
||||||
if (a.OverlapsWith(b))
|
if (a.OverlapsWith(b))
|
||||||
Part2++;
|
Part2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record Range(int A, int B)
|
record Range(int A, int B)
|
||||||
{
|
{
|
||||||
public bool Contains(Range other)
|
public bool Contains(Range other)
|
||||||
{
|
{
|
||||||
return (A <= other.A && B >= other.B);
|
return (A <= other.A && B >= other.B);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool OverlapsWith(Range other)
|
public bool OverlapsWith(Range other)
|
||||||
{
|
{
|
||||||
return (B >= other.A && A <= other.A) || (A <= other.B && B >= other.B) || (A >= other.A && B <= other.B);
|
return (B >= other.A && A <= other.A) || (A <= other.B && B >= other.B) || (A >= other.A && B <= other.B);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator Range((int a, int b) value) => new(value.a, value.b);
|
public static implicit operator Range((int a, int b) value) => new(value.a, value.b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,131 +1,131 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using Superpower;
|
using Superpower;
|
||||||
using Superpower.Parsers;
|
using Superpower.Parsers;
|
||||||
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day5;
|
namespace AdventOfCode.Problems.AOC2022.Day5;
|
||||||
|
|
||||||
[ProblemInfo(2022, 5, "Supply Stacks")]
|
[ProblemInfo(2022, 5, "Supply Stacks")]
|
||||||
internal partial class SupplyStacks : Problem
|
internal partial class SupplyStacks : Problem
|
||||||
{
|
{
|
||||||
private List<char>[] _stacksPart1 = Array.Empty<List<char>>();
|
private List<char>[] _stacksPart1 = Array.Empty<List<char>>();
|
||||||
private List<char>[] _stacksPart2 = Array.Empty<List<char>>();
|
private List<char>[] _stacksPart2 = Array.Empty<List<char>>();
|
||||||
|
|
||||||
private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
|
private readonly TextParser<(int, int, int)> _moveParser = from move in Character.Letter.Or(Character.WhiteSpace).Many()
|
||||||
from stack in Character.Digit.Many()
|
from stack in Character.Digit.Many()
|
||||||
from frm in Character.Letter.Or(Character.WhiteSpace).Many()
|
from frm in Character.Letter.Or(Character.WhiteSpace).Many()
|
||||||
from source in Character.Digit.Many()
|
from source in Character.Digit.Many()
|
||||||
from to in Character.Letter.Or(Character.WhiteSpace).Many()
|
from to in Character.Letter.Or(Character.WhiteSpace).Many()
|
||||||
from dst in Character.Digit.Many()
|
from dst in Character.Digit.Many()
|
||||||
select (int.Parse(stack), int.Parse(source), int.Parse(dst));
|
select (int.Parse(stack), int.Parse(source), int.Parse(dst));
|
||||||
|
|
||||||
private List<(int stack, int from, int to)> _moves = new();
|
private List<(int stack, int from, int to)> _moves = new();
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
foreach (var move in _moves)
|
foreach (var move in _moves)
|
||||||
{
|
{
|
||||||
PerformBasicMove(_stacksPart1, move);
|
PerformBasicMove(_stacksPart1, move);
|
||||||
}
|
}
|
||||||
Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
|
Part1 = new string(_stacksPart1.Select(b => b.Last()).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PerformBasicMove(List<char>[] data, (int stack, int from, int to) move)
|
private static void PerformBasicMove(List<char>[] data, (int stack, int from, int to) move)
|
||||||
{
|
{
|
||||||
var from = data[move.from - 1];
|
var from = data[move.from - 1];
|
||||||
var to = data[move.to - 1];
|
var to = data[move.to - 1];
|
||||||
for (int i = 0; i < move.stack; i++)
|
for (int i = 0; i < move.stack; i++)
|
||||||
{
|
{
|
||||||
var item = from[^1];
|
var item = from[^1];
|
||||||
from.RemoveAt(from.Count - 1);
|
from.RemoveAt(from.Count - 1);
|
||||||
to.Add(item);
|
to.Add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PerformMove(List<char>[] data, (int stack, int from, int to) move)
|
private static void PerformMove(List<char>[] data, (int stack, int from, int to) move)
|
||||||
{
|
{
|
||||||
var from = data[move.from - 1];
|
var from = data[move.from - 1];
|
||||||
var to = data[move.to - 1];
|
var to = data[move.to - 1];
|
||||||
var items = from.Skip(from.Count - move.stack);
|
var items = from.Skip(from.Count - move.stack);
|
||||||
to.AddRange(items);
|
to.AddRange(items);
|
||||||
from.RemoveRange(from.Count - move.stack, move.stack);
|
from.RemoveRange(from.Count - move.stack, move.stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
foreach (var move in _moves)
|
foreach (var move in _moves)
|
||||||
{
|
{
|
||||||
PerformMove(_stacksPart2, move);
|
PerformMove(_stacksPart2, move);
|
||||||
}
|
}
|
||||||
Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
|
Part2 = new string(_stacksPart2.Select(b => b.Last()).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
var readMoves = false;
|
var readMoves = false;
|
||||||
|
|
||||||
var buffers = new List<List<char>>();
|
var buffers = new List<List<char>>();
|
||||||
var moves = new List<(int stack, int from, int to)>();
|
var moves = new List<(int stack, int from, int to)>();
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(line))
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
{
|
{
|
||||||
readMoves = true;
|
readMoves = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readMoves)
|
if (readMoves)
|
||||||
{
|
{
|
||||||
moves.Add(ParseMoveLineRegex(line));
|
moves.Add(ParseMoveLineRegex(line));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var crates = ParseCrateLine(line);
|
var crates = ParseCrateLine(line);
|
||||||
for (int i = 0; i < crates.Count; i++)
|
for (int i = 0; i < crates.Count; i++)
|
||||||
{
|
{
|
||||||
var crate = crates[i];
|
var crate = crates[i];
|
||||||
if (buffers.Count == i)
|
if (buffers.Count == i)
|
||||||
buffers.Add(crate == ' ' ? new() : new List<char>() { crate });
|
buffers.Add(crate == ' ' ? new() : new List<char>() { crate });
|
||||||
else if (crate != ' ')
|
else if (crate != ' ')
|
||||||
buffers[i].Add(crate);
|
buffers[i].Add(crate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_stacksPart1 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
|
_stacksPart1 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
|
||||||
_stacksPart2 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
|
_stacksPart2 = buffers.Select(b => b.Take(b.Count - 1).Reverse().ToList()).ToArray();
|
||||||
_moves = moves;
|
_moves = moves;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Way slower
|
//Way slower
|
||||||
private (int stack, int from, int to) ParseMoveLine(string line)
|
private (int stack, int from, int to) ParseMoveLine(string line)
|
||||||
{
|
{
|
||||||
return _moveParser.Parse(line);
|
return _moveParser.Parse(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (int stack, int from, int to) ParseMoveLineRegex(string line)
|
private static (int stack, int from, int to) ParseMoveLineRegex(string line)
|
||||||
{
|
{
|
||||||
var r = MoveParser().Matches(line);
|
var r = MoveParser().Matches(line);
|
||||||
var items = r.First()
|
var items = r.First()
|
||||||
.Groups.Values.Skip(1)
|
.Groups.Values.Skip(1)
|
||||||
.Select(v => int.Parse(v.ValueSpan))
|
.Select(v => int.Parse(v.ValueSpan))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
return (items[0], items[1], items[2]);
|
return (items[0], items[1], items[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<char> ParseCrateLine(string line)
|
private static List<char> ParseCrateLine(string line)
|
||||||
{
|
{
|
||||||
var result = new List<char>(line.Length / 4);
|
var result = new List<char>(line.Length / 4);
|
||||||
for (int i = 1; i < line.Length; i += 4)
|
for (int i = 1; i < line.Length; i += 4)
|
||||||
{
|
{
|
||||||
var c = line[i];
|
var c = line[i];
|
||||||
result.Add(c);
|
result.Add(c);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
|
[GeneratedRegex("move (\\d+) from (\\d+) to (\\d+)")]
|
||||||
private static partial Regex MoveParser();
|
private static partial Regex MoveParser();
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day6;
|
namespace AdventOfCode.Problems.AOC2022.Day6;
|
||||||
|
|
||||||
[ProblemInfo(2022, 6, "Tuning Trouble")]
|
[ProblemInfo(2022, 6, "Tuning Trouble")]
|
||||||
internal class TuningTrouble : Problem<int, int>
|
internal class TuningTrouble : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string _input = string.Empty;
|
private string _input = string.Empty;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = FindMarker(4);
|
Part1 = FindMarker(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int FindMarker(int size = 4)
|
private int FindMarker(int size = 4)
|
||||||
{
|
{
|
||||||
for (int i = size; i < _input.Length; i++)
|
for (int i = size; i < _input.Length; i++)
|
||||||
{
|
{
|
||||||
var group = _input[(i - size)..i];
|
var group = _input[(i - size)..i];
|
||||||
if (group.All(c => group.Count(gc => gc == c) == 1))
|
if (group.All(c => group.Count(gc => gc == c) == 1))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = FindMarker(14);
|
Part2 = FindMarker(14);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_input = ReadInputText();
|
_input = ReadInputText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,121 +1,121 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2022.Day7;
|
namespace AdventOfCode.Problems.AOC2022.Day7;
|
||||||
|
|
||||||
internal class DirectoryNode
|
internal class DirectoryNode
|
||||||
{
|
{
|
||||||
public DirectoryNode Parent { get; set; }
|
public DirectoryNode Parent { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string FullPath => GetFullPath();
|
public string FullPath => GetFullPath();
|
||||||
public List<DirectoryNode> Children { get; set; }
|
public List<DirectoryNode> Children { get; set; }
|
||||||
public List<(string name, int size)> Files { get; set; }
|
public List<(string name, int size)> Files { get; set; }
|
||||||
public int Size => Files.Sum(f => f.size) + Children.Sum(c => c.Size);
|
public int Size => Files.Sum(f => f.size) + Children.Sum(c => c.Size);
|
||||||
public int LocalSize => Files.Sum(f => f.size);
|
public int LocalSize => Files.Sum(f => f.size);
|
||||||
|
|
||||||
public DirectoryNode(string name)
|
public DirectoryNode(string name)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Files = new();
|
Files = new();
|
||||||
Children = new();
|
Children = new();
|
||||||
Parent = this;
|
Parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryNode(string name, DirectoryNode parent)
|
public DirectoryNode(string name, DirectoryNode parent)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Files = new();
|
Files = new();
|
||||||
Children = new();
|
Children = new();
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryNode(string name, List<(string name, int size)> files)
|
public DirectoryNode(string name, List<(string name, int size)> files)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Files = files;
|
Files = files;
|
||||||
Children = new();
|
Children = new();
|
||||||
Parent = this;
|
Parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryNode AddDirectory(string path)
|
public DirectoryNode AddDirectory(string path)
|
||||||
{
|
{
|
||||||
if (path == "/")
|
if (path == "/")
|
||||||
return this;
|
return this;
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
return this;
|
return this;
|
||||||
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
||||||
if (segments.Length == 0)
|
if (segments.Length == 0)
|
||||||
throw new Exception("Invalid Path?");
|
throw new Exception("Invalid Path?");
|
||||||
return AddDirectory(segments);
|
return AddDirectory(segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirectoryNode AddDirectory(string[] segments)
|
private DirectoryNode AddDirectory(string[] segments)
|
||||||
{
|
{
|
||||||
var curSegment = segments[0];
|
var curSegment = segments[0];
|
||||||
var child = Children.FirstOrDefault(c => c.Name == curSegment);
|
var child = Children.FirstOrDefault(c => c.Name == curSegment);
|
||||||
if (child == null)
|
if (child == null)
|
||||||
{
|
{
|
||||||
var node = new DirectoryNode(curSegment, this);
|
var node = new DirectoryNode(curSegment, this);
|
||||||
Children.Add(node);
|
Children.Add(node);
|
||||||
if (segments.Length == 1)
|
if (segments.Length == 1)
|
||||||
return node;
|
return node;
|
||||||
else
|
else
|
||||||
return node.AddDirectory(segments[1..]);
|
return node.AddDirectory(segments[1..]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (segments.Length == 1)
|
if (segments.Length == 1)
|
||||||
return child;
|
return child;
|
||||||
return child.AddDirectory(segments[1..]);
|
return child.AddDirectory(segments[1..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddFile(string name, int size)
|
public void AddFile(string name, int size)
|
||||||
{
|
{
|
||||||
Files.Add((name, size));
|
Files.Add((name, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryNode? GetDirectory(string path)
|
public DirectoryNode? GetDirectory(string path)
|
||||||
{
|
{
|
||||||
if (path == "/")
|
if (path == "/")
|
||||||
return this;
|
return this;
|
||||||
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
var segments = path.Split("/").Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
|
||||||
if (segments.Length == 0)
|
if (segments.Length == 0)
|
||||||
throw new Exception("Invalid Path?");
|
throw new Exception("Invalid Path?");
|
||||||
return GetDirectory(segments);
|
return GetDirectory(segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirectoryNode? GetDirectory(string[] segments)
|
private DirectoryNode? GetDirectory(string[] segments)
|
||||||
{
|
{
|
||||||
if (Children.Count == 0)
|
if (Children.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var child = Children.FirstOrDefault(c => c.Name == segments[0]);
|
var child = Children.FirstOrDefault(c => c.Name == segments[0]);
|
||||||
|
|
||||||
if (child == null)
|
if (child == null)
|
||||||
return null;
|
return null;
|
||||||
else
|
else
|
||||||
if (segments.Length == 1)
|
if (segments.Length == 1)
|
||||||
return child;
|
return child;
|
||||||
else
|
else
|
||||||
return child.GetDirectory(segments[1..]);
|
return child.GetDirectory(segments[1..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DirectoryNode> Where(Func<DirectoryNode, bool> filter)
|
public List<DirectoryNode> Where(Func<DirectoryNode, bool> filter)
|
||||||
{
|
{
|
||||||
var result = new List<DirectoryNode>();
|
var result = new List<DirectoryNode>();
|
||||||
if (filter(this))
|
if (filter(this))
|
||||||
result.Add(this);
|
result.Add(this);
|
||||||
result.AddRange(Children.SelectMany(c => c.Where(filter)));
|
result.AddRange(Children.SelectMany(c => c.Where(filter)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetFullPath()
|
public string GetFullPath()
|
||||||
{
|
{
|
||||||
if (Parent == this)
|
if (Parent == this)
|
||||||
return "";
|
return "";
|
||||||
return $"{Parent.GetFullPath()}/{Name}";
|
return $"{Parent.GetFullPath()}/{Name}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Name} - {Children.Count}";
|
return $"{Name} - {Children.Count}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,75 +1,75 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day7;
|
namespace AdventOfCode.Problems.AOC2022.Day7;
|
||||||
|
|
||||||
[ProblemInfo(2022, 7, "No Space Left On Device")]
|
[ProblemInfo(2022, 7, "No Space Left On Device")]
|
||||||
internal class NoSpace : Problem<int, int>
|
internal class NoSpace : Problem<int, int>
|
||||||
{
|
{
|
||||||
private DirectoryNode _dirTree = new DirectoryNode("/");
|
private DirectoryNode _dirTree = new DirectoryNode("/");
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var dirs = _dirTree.Where(d => d.Size <= 100000);
|
var dirs = _dirTree.Where(d => d.Size <= 100000);
|
||||||
Part1 = dirs.Sum(d => d.Size);
|
Part1 = dirs.Sum(d => d.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var neededPace = 30000000;
|
var neededPace = 30000000;
|
||||||
var totalSize = 70000000;
|
var totalSize = 70000000;
|
||||||
var unusedSpace = totalSize - _dirTree.Size;
|
var unusedSpace = totalSize - _dirTree.Size;
|
||||||
var targetSize = neededPace - unusedSpace;
|
var targetSize = neededPace - unusedSpace;
|
||||||
var bigEnough = _dirTree.Where(d => d.Size >= targetSize);
|
var bigEnough = _dirTree.Where(d => d.Size >= targetSize);
|
||||||
Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0;
|
Part2 = bigEnough.MinBy(d => d.Size)?.Size ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
|
|
||||||
var curDir = new Stack<string>();
|
var curDir = new Stack<string>();
|
||||||
|
|
||||||
var dir = "/";
|
var dir = "/";
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
if (line[0] == '$')
|
if (line[0] == '$')
|
||||||
{
|
{
|
||||||
ParseCommand(line[2..], ref curDir);
|
ParseCommand(line[2..], ref curDir);
|
||||||
dir = $"/{string.Join("/", curDir.Reverse())}";
|
dir = $"/{string.Join("/", curDir.Reverse())}";
|
||||||
_dirTree.AddDirectory(dir);
|
_dirTree.AddDirectory(dir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ReadDirectory(line, _dirTree.GetDirectory(dir)!);
|
ReadDirectory(line, _dirTree.GetDirectory(dir)!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadDirectory(string line, DirectoryNode curDir)
|
private static void ReadDirectory(string line, DirectoryNode curDir)
|
||||||
{
|
{
|
||||||
if (line.StartsWith("dir"))
|
if (line.StartsWith("dir"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var split = line.Split(' ');
|
var split = line.Split(' ');
|
||||||
var name = split[1];
|
var name = split[1];
|
||||||
var size = int.Parse(split[0]);
|
var size = int.Parse(split[0]);
|
||||||
curDir.AddFile(name, size);
|
curDir.AddFile(name, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ParseCommand(string command, ref Stack<string> curDir)
|
private static void ParseCommand(string command, ref Stack<string> curDir)
|
||||||
{
|
{
|
||||||
var split = command.Split(' ');
|
var split = command.Split(' ');
|
||||||
var keyword = split.First();
|
var keyword = split.First();
|
||||||
var param = split.Last();
|
var param = split.Last();
|
||||||
|
|
||||||
switch (keyword)
|
switch (keyword)
|
||||||
{
|
{
|
||||||
case "cd":
|
case "cd":
|
||||||
if (param == "..")
|
if (param == "..")
|
||||||
curDir.Pop();
|
curDir.Pop();
|
||||||
else if (param == "/")
|
else if (param == "/")
|
||||||
curDir.Clear();
|
curDir.Clear();
|
||||||
else
|
else
|
||||||
curDir.Push(param);
|
curDir.Push(param);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,99 +1,99 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day8;
|
namespace AdventOfCode.Problems.AOC2022.Day8;
|
||||||
|
|
||||||
[ProblemInfo(2022, 8, "Treetop Tree House")]
|
[ProblemInfo(2022, 8, "Treetop Tree House")]
|
||||||
internal class TreetopTreeHouse : Problem<int, int>
|
internal class TreetopTreeHouse : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[][] _input = Array.Empty<int[]>();
|
private int[][] _input = Array.Empty<int[]>();
|
||||||
private int _height;
|
private int _height;
|
||||||
private int _width;
|
private int _width;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
for (int y = 1; y < _height - 1; y++)
|
for (int y = 1; y < _height - 1; y++)
|
||||||
{
|
{
|
||||||
for (int x = 1; x < _width - 1; x++)
|
for (int x = 1; x < _width - 1; x++)
|
||||||
{
|
{
|
||||||
Part1 += IsVisible(x, y) ? 1 : 0;
|
Part1 += IsVisible(x, y) ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part1 += _height * 2 + _width * 2 - 4;
|
Part1 += _height * 2 + _width * 2 - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVisible(int x, int y)
|
private bool IsVisible(int x, int y)
|
||||||
{
|
{
|
||||||
return IsVisibleColumn(x, y) || IsVisibleRow(x, y);
|
return IsVisibleColumn(x, y) || IsVisibleRow(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVisibleColumn(int col, int row)
|
private bool IsVisibleColumn(int col, int row)
|
||||||
{
|
{
|
||||||
var tree = _input[row][col];
|
var tree = _input[row][col];
|
||||||
|
|
||||||
var columnOfTrees = _input.Select(r => r[col]);
|
var columnOfTrees = _input.Select(r => r[col]);
|
||||||
|
|
||||||
var above = columnOfTrees.Take(row);
|
var above = columnOfTrees.Take(row);
|
||||||
var below = columnOfTrees.Skip(row + 1);
|
var below = columnOfTrees.Skip(row + 1);
|
||||||
|
|
||||||
return above.All(t => t < tree) || below.All(t => t < tree);
|
return above.All(t => t < tree) || below.All(t => t < tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsVisibleRow(int col, int row)
|
private bool IsVisibleRow(int col, int row)
|
||||||
{
|
{
|
||||||
var tree = _input[row][col];
|
var tree = _input[row][col];
|
||||||
|
|
||||||
var rowOfTrees = _input[row];
|
var rowOfTrees = _input[row];
|
||||||
|
|
||||||
var left = rowOfTrees.Take(col);
|
var left = rowOfTrees.Take(col);
|
||||||
var right = rowOfTrees.Skip(col + 1);
|
var right = rowOfTrees.Skip(col + 1);
|
||||||
|
|
||||||
return left.All(t => t < tree) || right.All(t => t < tree);
|
return left.All(t => t < tree) || right.All(t => t < tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = int.MinValue;
|
Part2 = int.MinValue;
|
||||||
for (int y = 1; y < _height - 1; y++)
|
for (int y = 1; y < _height - 1; y++)
|
||||||
{
|
{
|
||||||
for (int x = 1; x < _width - 1; x++)
|
for (int x = 1; x < _width - 1; x++)
|
||||||
{
|
{
|
||||||
var v = GetScenicScore(x, y);
|
var v = GetScenicScore(x, y);
|
||||||
if (Part2 < v)
|
if (Part2 < v)
|
||||||
Part2 = v;
|
Part2 = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetScenicScore(int row, int col)
|
public int GetScenicScore(int row, int col)
|
||||||
{
|
{
|
||||||
var tree = _input[row][col];
|
var tree = _input[row][col];
|
||||||
|
|
||||||
var columnOfTrees = _input.Select(r => r[col]);
|
var columnOfTrees = _input.Select(r => r[col]);
|
||||||
var rowOfTrees = _input[row];
|
var rowOfTrees = _input[row];
|
||||||
|
|
||||||
var above = columnOfTrees.Take(row).Reverse();
|
var above = columnOfTrees.Take(row).Reverse();
|
||||||
var below = columnOfTrees.Skip(row + 1);
|
var below = columnOfTrees.Skip(row + 1);
|
||||||
var left = rowOfTrees.Take(col).Reverse();
|
var left = rowOfTrees.Take(col).Reverse();
|
||||||
var right = rowOfTrees.Skip(col + 1);
|
var right = rowOfTrees.Skip(col + 1);
|
||||||
|
|
||||||
var score = above.Select((t, idx) => (t, idx))
|
var score = above.Select((t, idx) => (t, idx))
|
||||||
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1;
|
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: above.Count() - 1)).idx + 1;
|
||||||
score *= below.Select((t, idx) => (t, idx))
|
score *= below.Select((t, idx) => (t, idx))
|
||||||
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1;
|
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: below.Count() - 1)).idx + 1;
|
||||||
|
|
||||||
score *= left.Select((t, idx) => (t, idx))
|
score *= left.Select((t, idx) => (t, idx))
|
||||||
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1;
|
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: left.Count() - 1)).idx + 1;
|
||||||
score *= right.Select((t, idx) => (t, idx))
|
score *= right.Select((t, idx) => (t, idx))
|
||||||
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1;
|
.FirstOrDefault(v => v.t >= tree, (t: 0, idx: right.Count() - 1)).idx + 1;
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
_input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray();
|
_input = lines.Select(ln => ln.Select(tree => int.Parse(tree.ToString())).ToArray()).ToArray();
|
||||||
_height = _input.Length;
|
_height = _input.Length;
|
||||||
_width = _input[0].Length;
|
_width = _input[0].Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2022.Day9;
|
namespace AdventOfCode.Problems.AOC2022.Day9;
|
||||||
|
|
||||||
[ProblemInfo(2022, 9, "Rope Bridge")]
|
[ProblemInfo(2022, 9, "Rope Bridge")]
|
||||||
internal class RopeBridge : Problem<int, int>
|
internal class RopeBridge : Problem<int, int>
|
||||||
{
|
{
|
||||||
private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>();
|
private (RopeSimulator.Direction, int)[] _moves = Array.Empty<(RopeSimulator.Direction, int)>();
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var sim = new RopeSimulator(_moves);
|
var sim = new RopeSimulator(_moves);
|
||||||
sim.Simulate();
|
sim.Simulate();
|
||||||
Part1 = sim.Visited;
|
Part1 = sim.Visited;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var sim = new RopeSimulator(_moves, 9);
|
var sim = new RopeSimulator(_moves, 9);
|
||||||
sim.Simulate();
|
sim.Simulate();
|
||||||
Part2 = sim.Visited;
|
Part2 = sim.Visited;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
_moves = lines.Select(ln => ln.Split(' '))
|
_moves = lines.Select(ln => ln.Split(' '))
|
||||||
.Select(move => (Enum.Parse<RopeSimulator.Direction>(move.First()), int.Parse(move.Last())))
|
.Select(move => (Enum.Parse<RopeSimulator.Direction>(move.First()), int.Parse(move.Last())))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,146 +1,146 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2022.Day9;
|
namespace AdventOfCode.Problems.AOC2022.Day9;
|
||||||
|
|
||||||
public class RopeSimulator
|
public class RopeSimulator
|
||||||
{
|
{
|
||||||
public int Visited => _visited.Count;
|
public int Visited => _visited.Count;
|
||||||
|
|
||||||
private readonly (Direction dir, int ammount)[] _movement;
|
private readonly (Direction dir, int ammount)[] _movement;
|
||||||
private readonly bool _render;
|
private readonly bool _render;
|
||||||
|
|
||||||
public enum Direction
|
public enum Direction
|
||||||
{
|
{
|
||||||
L,
|
L,
|
||||||
R,
|
R,
|
||||||
U,
|
U,
|
||||||
D
|
D
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int x, int y) _head;
|
private (int x, int y) _head;
|
||||||
private (int x, int y)[] _segments;
|
private (int x, int y)[] _segments;
|
||||||
private Dictionary<(int x, int y), int> _visited;
|
private Dictionary<(int x, int y), int> _visited;
|
||||||
|
|
||||||
public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false)
|
public RopeSimulator((Direction dir, int ammount)[] movement, int segments = 1, bool render = false)
|
||||||
{
|
{
|
||||||
_movement = movement;
|
_movement = movement;
|
||||||
_render = render;
|
_render = render;
|
||||||
_visited = new Dictionary<(int x, int y), int>()
|
_visited = new Dictionary<(int x, int y), int>()
|
||||||
{
|
{
|
||||||
{ (0,0), 1 }
|
{ (0,0), 1 }
|
||||||
};
|
};
|
||||||
_head = (0, 0);
|
_head = (0, 0);
|
||||||
_segments = Enumerable.Repeat((0, 0), segments).ToArray();
|
_segments = Enumerable.Repeat((0, 0), segments).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Simulate()
|
public void Simulate()
|
||||||
{
|
{
|
||||||
foreach (var (dir, ammount) in _movement)
|
foreach (var (dir, ammount) in _movement)
|
||||||
{
|
{
|
||||||
ProcessStep(dir, ammount);
|
ProcessStep(dir, ammount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessStep(Direction dir, int ammount)
|
private void ProcessStep(Direction dir, int ammount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ammount; i++)
|
for (int i = 0; i < ammount; i++)
|
||||||
{
|
{
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case Direction.L:
|
case Direction.L:
|
||||||
_head.x--;
|
_head.x--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Direction.R:
|
case Direction.R:
|
||||||
_head.x++;
|
_head.x++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Direction.U:
|
case Direction.U:
|
||||||
_head.y++;
|
_head.y++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Direction.D:
|
case Direction.D:
|
||||||
_head.y--;
|
_head.y--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FollowHead();
|
FollowHead();
|
||||||
var tail = _segments.Last();
|
var tail = _segments.Last();
|
||||||
if (_visited.ContainsKey(tail))
|
if (_visited.ContainsKey(tail))
|
||||||
_visited[tail]++;
|
_visited[tail]++;
|
||||||
else
|
else
|
||||||
_visited.Add(tail, 1);
|
_visited.Add(tail, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FollowHead()
|
private void FollowHead()
|
||||||
{
|
{
|
||||||
var curHead = _head;
|
var curHead = _head;
|
||||||
for (int i = 0; i < _segments.Length; i++)
|
for (int i = 0; i < _segments.Length; i++)
|
||||||
{
|
{
|
||||||
var tail = _segments[i];
|
var tail = _segments[i];
|
||||||
curHead = _segments[i] = FollowSegment(curHead, tail);
|
curHead = _segments[i] = FollowSegment(curHead, tail);
|
||||||
}
|
}
|
||||||
if (_render)
|
if (_render)
|
||||||
{
|
{
|
||||||
DrawScene();
|
DrawScene();
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail)
|
private static (int x, int y) FollowSegment((int x, int y) head, (int x, int y) tail)
|
||||||
{
|
{
|
||||||
var xDist = head.x - tail.x;
|
var xDist = head.x - tail.x;
|
||||||
var yDist = head.y - tail.y;
|
var yDist = head.y - tail.y;
|
||||||
|
|
||||||
if (xDist * xDist + yDist * yDist < 4)
|
if (xDist * xDist + yDist * yDist < 4)
|
||||||
return tail;
|
return tail;
|
||||||
|
|
||||||
if (xDist > 1)
|
if (xDist > 1)
|
||||||
head.x -= 1;
|
head.x -= 1;
|
||||||
if (xDist < -1)
|
if (xDist < -1)
|
||||||
head.x += 1;
|
head.x += 1;
|
||||||
|
|
||||||
if (yDist > 1)
|
if (yDist > 1)
|
||||||
head.y -= 1;
|
head.y -= 1;
|
||||||
if (yDist < -1)
|
if (yDist < -1)
|
||||||
head.y += 1;
|
head.y += 1;
|
||||||
|
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail)
|
private static bool ShouldMoveTail((int x, int y) head, (int x, int y) tail)
|
||||||
{
|
{
|
||||||
var xDist = Math.Abs(head.x - tail.x);
|
var xDist = Math.Abs(head.x - tail.x);
|
||||||
var yDist = Math.Abs(head.y - tail.y);
|
var yDist = Math.Abs(head.y - tail.y);
|
||||||
return (xDist > 1 || yDist > 1);
|
return (xDist > 1 || yDist > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawScene(int segment = -1)
|
private void DrawScene(int segment = -1)
|
||||||
{
|
{
|
||||||
var upperX = Math.Max(_head.x, _segments.MaxBy(s => s.x).x);
|
var upperX = Math.Max(_head.x, _segments.MaxBy(s => s.x).x);
|
||||||
var upperY = Math.Max(_head.y, _segments.MaxBy(s => s.y).y);
|
var upperY = Math.Max(_head.y, _segments.MaxBy(s => s.y).y);
|
||||||
var lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y);
|
var lowerX = Math.Min(_head.x, _segments.MinBy(s => s.y).y);
|
||||||
var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y);
|
var lowerY = Math.Min(_head.y, _segments.MinBy(s => s.y).y);
|
||||||
|
|
||||||
var width = upperX - lowerX;
|
var width = upperX - lowerX;
|
||||||
var height = upperY - lowerY;
|
var height = upperY - lowerY;
|
||||||
|
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
Draw('s', (0, 0), lowerX, upperY);
|
Draw('s', (0, 0), lowerX, upperY);
|
||||||
Draw('H', _head, lowerX, upperY);
|
Draw('H', _head, lowerX, upperY);
|
||||||
|
|
||||||
for (int i = _segments.Length - 1; i >= 0; i--)
|
for (int i = _segments.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (segment == i)
|
if (segment == i)
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
else
|
else
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY);
|
Draw((i + 1).ToString()[0], _segments[i], lowerX, upperY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY)
|
private void Draw(char c, (int x, int y) pos, int offsetX, int offsetY)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY);
|
Console.SetCursorPosition(pos.x + offsetX, -pos.y + offsetY);
|
||||||
Console.WriteLine(c);
|
Console.WriteLine(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,97 +1,97 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day1;
|
namespace AdventOfCode.Problems.AOC2023.Day1;
|
||||||
|
|
||||||
[ProblemInfo(2023, 1, "Trebuchet!?")]
|
[ProblemInfo(2023, 1, "Trebuchet!?")]
|
||||||
public partial class Trebuchet : Problem<int, int>
|
public partial class Trebuchet : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _inputData = [];
|
private string[] _inputData = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_inputData = ReadInputLines();
|
_inputData = ReadInputLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _inputData.Select(GetCalibrationValues)
|
Part1 = _inputData.Select(GetCalibrationValues)
|
||||||
.Select(cv => cv.left * 10 + cv.right)
|
.Select(cv => cv.left * 10 + cv.right)
|
||||||
.Sum();
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int left, int right) GetCalibrationValues(string line)
|
private (int left, int right) GetCalibrationValues(string line)
|
||||||
{
|
{
|
||||||
var (left, right) = (0, 0);
|
var (left, right) = (0, 0);
|
||||||
for (int i = 0; i < line.Length; i++)
|
for (int i = 0; i < line.Length; i++)
|
||||||
{
|
{
|
||||||
if (line[i] - '0' >= 10)
|
if (line[i] - '0' >= 10)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
left = line[i] - '0';
|
left = line[i] - '0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (int i = line.Length - 1; i >= 0; i--)
|
for (int i = line.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (line[i] - '0' >= 10)
|
if (line[i] - '0' >= 10)
|
||||||
continue;
|
continue;
|
||||||
right = line[i] - '0';
|
right = line[i] - '0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (left, right);
|
return (left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly (string word, int value)[] _numberWords = new[]
|
private readonly (string word, int value)[] _numberWords = new[]
|
||||||
{
|
{
|
||||||
("one", 1),
|
("one", 1),
|
||||||
("two", 2),
|
("two", 2),
|
||||||
("three", 3),
|
("three", 3),
|
||||||
("four", 4),
|
("four", 4),
|
||||||
("five", 5),
|
("five", 5),
|
||||||
("six", 6),
|
("six", 6),
|
||||||
("seven", 7),
|
("seven", 7),
|
||||||
("eight", 8),
|
("eight", 8),
|
||||||
("nine", 9)
|
("nine", 9)
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = _inputData.Select(GetNamedCalibrationValues)
|
Part2 = _inputData.Select(GetNamedCalibrationValues)
|
||||||
.Select(cv => cv.left * 10 + cv.right)
|
.Select(cv => cv.left * 10 + cv.right)
|
||||||
.Sum();
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int left, int right) GetNamedCalibrationValues(string line)
|
private (int left, int right) GetNamedCalibrationValues(string line)
|
||||||
{
|
{
|
||||||
var (left, right) = (0, 0);
|
var (left, right) = (0, 0);
|
||||||
for (int i = 0; i < line.Length; i++)
|
for (int i = 0; i < line.Length; i++)
|
||||||
{
|
{
|
||||||
var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
|
var word = _numberWords.FirstOrDefault(v => line[i..].StartsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
|
||||||
if (word != -1)
|
if (word != -1)
|
||||||
{
|
{
|
||||||
left = word;
|
left = word;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (line[i] - '0' >= 10)
|
else if (line[i] - '0' >= 10)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
left = line[i] - '0';
|
left = line[i] - '0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = line.Length - 1; i >= 0; i--)
|
for (int i = line.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var word = _numberWords.FirstOrDefault(v => line[..(i + 1)].EndsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
|
var word = _numberWords.FirstOrDefault(v => line[..(i + 1)].EndsWith(v.word, StringComparison.Ordinal), (word: "", value: -1)).value;
|
||||||
if (word != -1)
|
if (word != -1)
|
||||||
{
|
{
|
||||||
right = word;
|
right = word;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (line[i] - '0' >= 10)
|
else if (line[i] - '0' >= 10)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
right = line[i] - '0';
|
right = line[i] - '0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (left, right);
|
return (left, right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,106 +1,106 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day10;
|
namespace AdventOfCode.Problems.AOC2023.Day10;
|
||||||
|
|
||||||
[ProblemInfo(2023, 10, "Pipe Maze")]
|
[ProblemInfo(2023, 10, "Pipe Maze")]
|
||||||
internal class PipeMaze : Problem<int, int>
|
internal class PipeMaze : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _maze = [];
|
private string[] _maze = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_maze = ReadInputLines();
|
_maze = ReadInputLines();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var start = GetStartPointPos();
|
var start = GetStartPointPos();
|
||||||
var nPoints = GetStartConnections(start);
|
var nPoints = GetStartConnections(start);
|
||||||
var seen = new Dictionary<(int, int), int>();
|
var seen = new Dictionary<(int, int), int>();
|
||||||
|
|
||||||
foreach (var point in nPoints)
|
foreach (var point in nPoints)
|
||||||
{
|
{
|
||||||
var curPoint = start;
|
var curPoint = start;
|
||||||
var prevPoint = point;
|
var prevPoint = point;
|
||||||
var dist = 0;
|
var dist = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
dist++;
|
dist++;
|
||||||
var next = GetNextPoint(curPoint, prevPoint);
|
var next = GetNextPoint(curPoint, prevPoint);
|
||||||
prevPoint = curPoint;
|
prevPoint = curPoint;
|
||||||
curPoint = next;
|
curPoint = next;
|
||||||
if (next == start)
|
if (next == start)
|
||||||
break;
|
break;
|
||||||
if (seen.TryGetValue(next, out var d))
|
if (seen.TryGetValue(next, out var d))
|
||||||
{
|
{
|
||||||
if (d > dist)
|
if (d > dist)
|
||||||
seen[next] = dist;
|
seen[next] = dist;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
seen.Add(next, dist);
|
seen.Add(next, dist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Part1 = seen.Values.Max();
|
Part1 = seen.Values.Max();
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int x, int y) GetStartPointPos()
|
private (int x, int y) GetStartPointPos()
|
||||||
{
|
{
|
||||||
for (int y = 0; y < _maze.Length; y++)
|
for (int y = 0; y < _maze.Length; y++)
|
||||||
{
|
{
|
||||||
var x = _maze[y].IndexOf('S');
|
var x = _maze[y].IndexOf('S');
|
||||||
if (x >= 0)
|
if (x >= 0)
|
||||||
return (x, y);
|
return (x, y);
|
||||||
}
|
}
|
||||||
throw new Exception("Start point not found");
|
throw new Exception("Start point not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<(int x, int y)> GetStartConnections((int x, int y) pos)
|
private List<(int x, int y)> GetStartConnections((int x, int y) pos)
|
||||||
{
|
{
|
||||||
var points = new List<(int x, int y)>();
|
var points = new List<(int x, int y)>();
|
||||||
if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L')
|
if (_maze[pos.y + 1][pos.x] is '|' or 'J' or 'L')
|
||||||
points.Add((pos.x + 1, pos.y));
|
points.Add((pos.x + 1, pos.y));
|
||||||
if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7')
|
if (_maze[pos.y - 1][pos.x] is '|' or 'F' or '7')
|
||||||
points.Add((pos.x - 1, pos.y));
|
points.Add((pos.x - 1, pos.y));
|
||||||
|
|
||||||
if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7')
|
if (_maze[pos.y][pos.x + 1] is '-' or 'J' or '7')
|
||||||
points.Add((pos.x, pos.y + 1));
|
points.Add((pos.x, pos.y + 1));
|
||||||
if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L')
|
if (_maze[pos.y][pos.x - 1] is '-' or 'F' or 'L')
|
||||||
points.Add((pos.x, pos.y - 1));
|
points.Add((pos.x, pos.y - 1));
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev)
|
private (int x, int y) GetNextPoint((int x, int y) pos, (int x, int y) prev)
|
||||||
{
|
{
|
||||||
var curPipe = _maze[pos.y][pos.x];
|
var curPipe = _maze[pos.y][pos.x];
|
||||||
(int x, int y) = (pos.x - prev.x, pos.y - prev.y);
|
(int x, int y) = (pos.x - prev.x, pos.y - prev.y);
|
||||||
|
|
||||||
if (curPipe == 'S')
|
if (curPipe == 'S')
|
||||||
return GetStartConnections(pos).First(p => p != prev);
|
return GetStartConnections(pos).First(p => p != prev);
|
||||||
|
|
||||||
return curPipe switch
|
return curPipe switch
|
||||||
{
|
{
|
||||||
'|' => (pos.x, pos.y + y),
|
'|' => (pos.x, pos.y + y),
|
||||||
'-' => (pos.x + x, pos.y),
|
'-' => (pos.x + x, pos.y),
|
||||||
'L' => (pos.x + y, pos.y + x),
|
'L' => (pos.x + y, pos.y + x),
|
||||||
'F' => (pos.x - y, pos.y - x),
|
'F' => (pos.x - y, pos.y - x),
|
||||||
'J' => (pos.x - y, pos.y - x),
|
'J' => (pos.x - y, pos.y - x),
|
||||||
'7' => (pos.x + y, pos.y + x),
|
'7' => (pos.x + y, pos.y + x),
|
||||||
_ => throw new Exception()
|
_ => throw new Exception()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,89 +1,89 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day11;
|
namespace AdventOfCode.Problems.AOC2023.Day11;
|
||||||
|
|
||||||
[ProblemInfo(2023, 11, "Cosmic Expansion")]
|
[ProblemInfo(2023, 11, "Cosmic Expansion")]
|
||||||
internal class CosmicExpansion : Problem<int, long>
|
internal class CosmicExpansion : Problem<int, long>
|
||||||
{
|
{
|
||||||
private string[] _data = [];
|
private string[] _data = [];
|
||||||
private int[] _yGaps = [];
|
private int[] _yGaps = [];
|
||||||
private int[] _xGaps = [];
|
private int[] _xGaps = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var points = GetPoints().Select(p => Inflate(p, 2)).ToList();
|
var points = GetPoints().Select(p => Inflate(p, 2)).ToList();
|
||||||
for (int i = 0; i < points.Count - 1; i++)
|
for (int i = 0; i < points.Count - 1; i++)
|
||||||
{
|
{
|
||||||
for (int j = i + 1; j < points.Count; j++)
|
for (int j = i + 1; j < points.Count; j++)
|
||||||
{
|
{
|
||||||
var a = points[i];
|
var a = points[i];
|
||||||
var b = points[j];
|
var b = points[j];
|
||||||
Part1 += GetDistance(a, b);
|
Part1 += GetDistance(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(int x, int y)> GetPoints()
|
public List<(int x, int y)> GetPoints()
|
||||||
{
|
{
|
||||||
var result = new List<(int x, int y)>();
|
var result = new List<(int x, int y)>();
|
||||||
for (int y = 0; y < _data.Length; y++)
|
for (int y = 0; y < _data.Length; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < _data[0].Length; x++)
|
for (int x = 0; x < _data[0].Length; x++)
|
||||||
{
|
{
|
||||||
if (_data[y][x] == '#')
|
if (_data[y][x] == '#')
|
||||||
result.Add((x, y));
|
result.Add((x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetDistance((int x, int y) a, (int x, int y) b)
|
public int GetDistance((int x, int y) a, (int x, int y) b)
|
||||||
{
|
{
|
||||||
var xDist = Math.Abs(a.x - b.x);
|
var xDist = Math.Abs(a.x - b.x);
|
||||||
var yDist = Math.Abs(a.y - b.y);
|
var yDist = Math.Abs(a.y - b.y);
|
||||||
|
|
||||||
return xDist + yDist;
|
return xDist + yDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int x, int y) Inflate((int x, int y) point, int factor)
|
public (int x, int y) Inflate((int x, int y) point, int factor)
|
||||||
{
|
{
|
||||||
factor -= 1;
|
factor -= 1;
|
||||||
var cX = _xGaps.Count(x => point.x >= x);
|
var cX = _xGaps.Count(x => point.x >= x);
|
||||||
var cY = _yGaps.Count(y => point.y >= y);
|
var cY = _yGaps.Count(y => point.y >= y);
|
||||||
return (point.x + cX * factor, point.y + cY * factor);
|
return (point.x + cX * factor, point.y + cY * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList();
|
var points = GetPoints().Select(p => Inflate(p, 1000000)).ToList();
|
||||||
for (int i = 0; i < points.Count - 1; i++)
|
for (int i = 0; i < points.Count - 1; i++)
|
||||||
{
|
{
|
||||||
for (int j = i + 1; j < points.Count; j++)
|
for (int j = i + 1; j < points.Count; j++)
|
||||||
{
|
{
|
||||||
var a = points[i];
|
var a = points[i];
|
||||||
var b = points[j];
|
var b = points[j];
|
||||||
Part2 += GetDistance(a, b);
|
Part2 += GetDistance(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines();
|
_data = ReadInputLines();
|
||||||
_yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i))
|
_yGaps = _data.Select((v, i) => (c: v.Count(x => x == '.'), i))
|
||||||
.Where(v => v.c == _data[0].Length)
|
.Where(v => v.c == _data[0].Length)
|
||||||
.Select(v => v.i)
|
.Select(v => v.i)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
_xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i))
|
_xGaps = _data.Transpose().Select((v, i) => (c: v.Count(x => x == '.'), i))
|
||||||
.Where(v => v.c == _data[0].Length)
|
.Where(v => v.c == _data[0].Length)
|
||||||
.Select(v => v.i)
|
.Select(v => v.i)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,111 +1,111 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day12;
|
namespace AdventOfCode.Problems.AOC2023.Day12;
|
||||||
|
|
||||||
[ProblemInfo(2023, 12, "Hot Springs")]
|
[ProblemInfo(2023, 12, "Hot Springs")]
|
||||||
internal class HotSprings : Problem<int, int>
|
internal class HotSprings : Problem<int, int>
|
||||||
{
|
{
|
||||||
private Record[] _data = [];
|
private Record[] _data = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _data.Select(r => CountPossiblilites(r)).Sum();
|
Part1 = _data.Select(r => CountPossiblilites(r)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var unfolded = _data.Select(r =>
|
var unfolded = _data.Select(r =>
|
||||||
{
|
{
|
||||||
var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5));
|
var unfoldData = string.Join("", Enumerable.Repeat(r.Data, 5));
|
||||||
var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray();
|
var unfoldPattern = Enumerable.Repeat(r.Pattern, 5).SelectMany(x => x).ToArray();
|
||||||
return new Record(unfoldData, unfoldPattern);
|
return new Record(unfoldData, unfoldPattern);
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum();
|
Part2 = unfolded.Select(r => CountPossiblilites(r)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountPossiblilites(Record record, int pos = 0)
|
public static int CountPossiblilites(Record record, int pos = 0)
|
||||||
{
|
{
|
||||||
if (pos == -1 || pos >= record.Data.Length)
|
if (pos == -1 || pos >= record.Data.Length)
|
||||||
return record.IsValid ? 1 : 0;
|
return record.IsValid ? 1 : 0;
|
||||||
if (!record.IsValid)
|
if (!record.IsValid)
|
||||||
return 0;
|
return 0;
|
||||||
if (record.Data[pos] != '?')
|
if (record.Data[pos] != '?')
|
||||||
return CountPossiblilites(record, record.Data.IndexOf('?'));
|
return CountPossiblilites(record, record.Data.IndexOf('?'));
|
||||||
|
|
||||||
var front = record.Data[..pos];
|
var front = record.Data[..pos];
|
||||||
var back = record.Data[(pos + 1)..];
|
var back = record.Data[(pos + 1)..];
|
||||||
var r1 = record with { Data = $"{front}.{back}" };
|
var r1 = record with { Data = $"{front}.{back}" };
|
||||||
var r2 = record with { Data = $"{front}#{back}" };
|
var r2 = record with { Data = $"{front}#{back}" };
|
||||||
return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1);
|
return CountPossiblilites(r1, pos + 1) + CountPossiblilites(r2, pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputLines();
|
var data = ReadInputLines();
|
||||||
|
|
||||||
_data = data.Select(x => x.Split(' '))
|
_data = data.Select(x => x.Split(' '))
|
||||||
.Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray()))
|
.Select(x => new Record(x[0], x[1].Split(',').Select(int.Parse).ToArray()))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Record(string Data, int[] Pattern)
|
public record Record(string Data, int[] Pattern)
|
||||||
{
|
{
|
||||||
public bool IsValid => CheckValidity(this);
|
public bool IsValid => CheckValidity(this);
|
||||||
public static bool CheckValidity(Record record)
|
public static bool CheckValidity(Record record)
|
||||||
{
|
{
|
||||||
var section = 0;
|
var section = 0;
|
||||||
var start = 0;
|
var start = 0;
|
||||||
var inSection = false;
|
var inSection = false;
|
||||||
for (int i = 0; i < record.Data.Length; i++)
|
for (int i = 0; i < record.Data.Length; i++)
|
||||||
{
|
{
|
||||||
var c = record.Data[i];
|
var c = record.Data[i];
|
||||||
if (section >= record.Pattern.Length)
|
if (section >= record.Pattern.Length)
|
||||||
return !record.Data[i..].Contains('#');
|
return !record.Data[i..].Contains('#');
|
||||||
|
|
||||||
var len = record.Pattern[section];
|
var len = record.Pattern[section];
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case '?':
|
case '?':
|
||||||
if (inSection && i - start > len)
|
if (inSection && i - start > len)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
if (inSection)
|
if (inSection)
|
||||||
{
|
{
|
||||||
if (i - start != len)
|
if (i - start != len)
|
||||||
return false;
|
return false;
|
||||||
inSection = false;
|
inSection = false;
|
||||||
start = 0;
|
start = 0;
|
||||||
section++;
|
section++;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case '#':
|
case '#':
|
||||||
if (!inSection)
|
if (!inSection)
|
||||||
{
|
{
|
||||||
inSection = true;
|
inSection = true;
|
||||||
start = i;
|
start = i;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inSection)
|
if (inSection)
|
||||||
{
|
{
|
||||||
if (record.Pattern[section] != (record.Data[start..].Length))
|
if (record.Pattern[section] != (record.Data[start..].Length))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
section++;
|
section++;
|
||||||
}
|
}
|
||||||
if (section != record.Pattern.Length)
|
if (section != record.Pattern.Length)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day2;
|
namespace AdventOfCode.Problems.AOC2023.Day2;
|
||||||
|
|
||||||
[ProblemInfo(2023, 2, "Cube Conundrum")]
|
[ProblemInfo(2023, 2, "Cube Conundrum")]
|
||||||
internal class CubeConundrum : Problem<int, int>
|
internal class CubeConundrum : Problem<int, int>
|
||||||
{
|
{
|
||||||
private CubeGame[] _gameInfo = [];
|
private CubeGame[] _gameInfo = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines();
|
var lines = ReadInputLines();
|
||||||
_gameInfo = lines.Select(l => new CubeGame(l)).ToArray();
|
_gameInfo = lines.Select(l => new CubeGame(l)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum();
|
Part1 = FindPossibleGames(new CubeRound(12, 13, 14)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum();
|
Part2 = _gameInfo.Select(g => g.GetMinimalConstraints().Power()).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<int> FindPossibleGames(CubeRound constraints)
|
public IEnumerable<int> FindPossibleGames(CubeRound constraints)
|
||||||
{
|
{
|
||||||
return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints)))
|
return _gameInfo.Where(g => !g.Rounds.Any(r => !r.IsPossible(constraints)))
|
||||||
.Select(r => r.Id);
|
.Select(r => r.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,81 +1,81 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2023.Day2;
|
namespace AdventOfCode.Problems.AOC2023.Day2;
|
||||||
|
|
||||||
internal class CubeGame
|
internal class CubeGame
|
||||||
{
|
{
|
||||||
public CubeRound[] Rounds { get; }
|
public CubeRound[] Rounds { get; }
|
||||||
|
|
||||||
public int Id { get; }
|
public int Id { get; }
|
||||||
|
|
||||||
public CubeGame(string line)
|
public CubeGame(string line)
|
||||||
{
|
{
|
||||||
var info = line.Split(':');
|
var info = line.Split(':');
|
||||||
Id = int.Parse(info[0].Split(' ')[^1]);
|
Id = int.Parse(info[0].Split(' ')[^1]);
|
||||||
|
|
||||||
var roundsData = info[1].Split(';');
|
var roundsData = info[1].Split(';');
|
||||||
Rounds = new CubeRound[roundsData.Length];
|
Rounds = new CubeRound[roundsData.Length];
|
||||||
for (int i = 0; i < roundsData.Length; i++)
|
for (int i = 0; i < roundsData.Length; i++)
|
||||||
Rounds[i] = CubeRound.ParseRound(roundsData[i]);
|
Rounds[i] = CubeRound.ParseRound(roundsData[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CubeRound GetMinimalConstraints()
|
public CubeRound GetMinimalConstraints()
|
||||||
{
|
{
|
||||||
var (r, g, b) = (0, 0, 0);
|
var (r, g, b) = (0, 0, 0);
|
||||||
foreach (var round in Rounds)
|
foreach (var round in Rounds)
|
||||||
{
|
{
|
||||||
if (round.Red > r)
|
if (round.Red > r)
|
||||||
r = round.Red;
|
r = round.Red;
|
||||||
if (round.Green > g)
|
if (round.Green > g)
|
||||||
g = round.Green;
|
g = round.Green;
|
||||||
if (round.Blue > b)
|
if (round.Blue > b)
|
||||||
b = round.Blue;
|
b = round.Blue;
|
||||||
}
|
}
|
||||||
return new CubeRound(r, g, b);
|
return new CubeRound(r, g, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal record struct CubeRound(int Red, int Green, int Blue)
|
internal record struct CubeRound(int Red, int Green, int Blue)
|
||||||
{
|
{
|
||||||
public static CubeRound ParseRound(string round)
|
public static CubeRound ParseRound(string round)
|
||||||
{
|
{
|
||||||
var cubes = round.Split(',');
|
var cubes = round.Split(',');
|
||||||
var (r, g, b) = (0, 0, 0);
|
var (r, g, b) = (0, 0, 0);
|
||||||
|
|
||||||
foreach (var cube in cubes)
|
foreach (var cube in cubes)
|
||||||
{
|
{
|
||||||
var info = cube.TrimStart().Split(' ');
|
var info = cube.TrimStart().Split(' ');
|
||||||
var count = int.Parse(info[0]);
|
var count = int.Parse(info[0]);
|
||||||
switch (info[1])
|
switch (info[1])
|
||||||
{
|
{
|
||||||
case ['r', ..]:
|
case ['r', ..]:
|
||||||
r = count;
|
r = count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ['g', ..]:
|
case ['g', ..]:
|
||||||
g = count;
|
g = count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ['b', ..]:
|
case ['b', ..]:
|
||||||
b = count;
|
b = count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new CubeRound(r, g, b);
|
return new CubeRound(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly bool IsPossible(CubeRound constraints)
|
public readonly bool IsPossible(CubeRound constraints)
|
||||||
{
|
{
|
||||||
if (Red > constraints.Red)
|
if (Red > constraints.Red)
|
||||||
return false;
|
return false;
|
||||||
if (Green > constraints.Green)
|
if (Green > constraints.Green)
|
||||||
return false;
|
return false;
|
||||||
if (Blue > constraints.Blue)
|
if (Blue > constraints.Blue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly int Power()
|
public readonly int Power()
|
||||||
{
|
{
|
||||||
return Red * Green * Blue;
|
return Red * Green * Blue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,136 +1,136 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day3;
|
namespace AdventOfCode.Problems.AOC2023.Day3;
|
||||||
|
|
||||||
[ProblemInfo(2023, 3, "Gear Ratios")]
|
[ProblemInfo(2023, 3, "Gear Ratios")]
|
||||||
internal class GearRatios : Problem<int, int>
|
internal class GearRatios : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _data = [];
|
private string[] _data = [];
|
||||||
private int _width;
|
private int _width;
|
||||||
private int _height;
|
private int _height;
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines();
|
_data = ReadInputLines();
|
||||||
_width = _data[0].Length - 1;
|
_width = _data[0].Length - 1;
|
||||||
_height = _data.Length - 1;
|
_height = _data.Length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var partNumbers = new List<int>();
|
var partNumbers = new List<int>();
|
||||||
|
|
||||||
for (int y = 0; y < _height; y++)
|
for (int y = 0; y < _height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x <= _width; x++)
|
for (int x = 0; x <= _width; x++)
|
||||||
{
|
{
|
||||||
var cell = _data[y][x];
|
var cell = _data[y][x];
|
||||||
switch (cell)
|
switch (cell)
|
||||||
{
|
{
|
||||||
case '.':
|
case '.':
|
||||||
continue;
|
continue;
|
||||||
case < '0' or > '9':
|
case < '0' or > '9':
|
||||||
FindNumbers(x, y, ref partNumbers);
|
FindNumbers(x, y, ref partNumbers);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part1 = partNumbers.Sum();
|
Part1 = partNumbers.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var ratios = new List<int>();
|
var ratios = new List<int>();
|
||||||
var curNums = new List<int>();
|
var curNums = new List<int>();
|
||||||
for (int y = 0; y < _height; y++)
|
for (int y = 0; y < _height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x <= _width; x++)
|
for (int x = 0; x <= _width; x++)
|
||||||
{
|
{
|
||||||
var cell = _data[y][x];
|
var cell = _data[y][x];
|
||||||
switch (cell)
|
switch (cell)
|
||||||
{
|
{
|
||||||
case '*':
|
case '*':
|
||||||
curNums.Clear();
|
curNums.Clear();
|
||||||
FindNumbers(x, y, ref curNums);
|
FindNumbers(x, y, ref curNums);
|
||||||
if (curNums.Count == 2)
|
if (curNums.Count == 2)
|
||||||
ratios.Add(curNums[0] * curNums[1]);
|
ratios.Add(curNums[0] * curNums[1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Part2 = ratios.Sum();
|
Part2 = ratios.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FindNumbers(int x, int y, ref List<int> results)
|
public void FindNumbers(int x, int y, ref List<int> results)
|
||||||
{
|
{
|
||||||
var seen = new HashSet<(int x, int y)>();
|
var seen = new HashSet<(int x, int y)>();
|
||||||
|
|
||||||
var n = GetNeighborPoints(x, y);
|
var n = GetNeighborPoints(x, y);
|
||||||
foreach (var (xN, yN) in n)
|
foreach (var (xN, yN) in n)
|
||||||
{
|
{
|
||||||
var c = _data[yN][xN] - '0';
|
var c = _data[yN][xN] - '0';
|
||||||
if (c >= 0) //A bug exists here, I wont fix it
|
if (c >= 0) //A bug exists here, I wont fix it
|
||||||
{
|
{
|
||||||
var num = GetNumber(xN, yN, out var idx);
|
var num = GetNumber(xN, yN, out var idx);
|
||||||
|
|
||||||
if (seen.Contains(idx))
|
if (seen.Contains(idx))
|
||||||
continue;
|
continue;
|
||||||
seen.Add(idx);
|
seen.Add(idx);
|
||||||
results.Add(num);
|
results.Add(num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(int x, int y)> GetNeighborPoints(int x, int y)
|
public List<(int x, int y)> GetNeighborPoints(int x, int y)
|
||||||
{
|
{
|
||||||
var points = new List<(int x, int y)>();
|
var points = new List<(int x, int y)>();
|
||||||
if (x > 0)
|
if (x > 0)
|
||||||
points.Add((x - 1, y));
|
points.Add((x - 1, y));
|
||||||
if (x < _width)
|
if (x < _width)
|
||||||
points.Add((x + 1, y));
|
points.Add((x + 1, y));
|
||||||
if (y > 0)
|
if (y > 0)
|
||||||
points.Add((x, y - 1));
|
points.Add((x, y - 1));
|
||||||
if (y < _height)
|
if (y < _height)
|
||||||
points.Add((x, y + 1));
|
points.Add((x, y + 1));
|
||||||
if (x > 0 && y > 0)
|
if (x > 0 && y > 0)
|
||||||
points.Add((x - 1, y - 1));
|
points.Add((x - 1, y - 1));
|
||||||
if (x > 0 && y < _height)
|
if (x > 0 && y < _height)
|
||||||
points.Add((x - 1, y + 1));
|
points.Add((x - 1, y + 1));
|
||||||
if (x < _width && y < _height)
|
if (x < _width && y < _height)
|
||||||
points.Add((x + 1, y + 1));
|
points.Add((x + 1, y + 1));
|
||||||
if (x < _width && y > 0)
|
if (x < _width && y > 0)
|
||||||
points.Add((x + 1, y - 1));
|
points.Add((x + 1, y - 1));
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetNumber(int x, int y, out (int iX, int iY) index)
|
public int GetNumber(int x, int y, out (int iX, int iY) index)
|
||||||
{
|
{
|
||||||
var row = _data[y];
|
var row = _data[y];
|
||||||
|
|
||||||
var numStart = 0;
|
var numStart = 0;
|
||||||
var numEnd = _width + 1;
|
var numEnd = _width + 1;
|
||||||
for (int i = x; i >= 0; i--)
|
for (int i = x; i >= 0; i--)
|
||||||
{
|
{
|
||||||
switch (row[i])
|
switch (row[i])
|
||||||
{
|
{
|
||||||
case < '0' or > '9':
|
case < '0' or > '9':
|
||||||
numStart = i + 1;
|
numStart = i + 1;
|
||||||
goto leftDone;
|
goto leftDone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
leftDone:
|
leftDone:
|
||||||
for (int i = x; i <= _width; i++)
|
for (int i = x; i <= _width; i++)
|
||||||
{
|
{
|
||||||
switch (row[i])
|
switch (row[i])
|
||||||
{
|
{
|
||||||
case < '0' or > '9':
|
case < '0' or > '9':
|
||||||
numEnd = i;
|
numEnd = i;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
index = (numStart, y);
|
index = (numStart, y);
|
||||||
return int.Parse(row[numStart..numEnd]);
|
return int.Parse(row[numStart..numEnd]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,66 +1,66 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day4;
|
namespace AdventOfCode.Problems.AOC2023.Day4;
|
||||||
[ProblemInfo(2023, 4, "Scratchcards")]
|
[ProblemInfo(2023, 4, "Scratchcards")]
|
||||||
internal class Scratchcards : Problem<double, int>
|
internal class Scratchcards : Problem<double, int>
|
||||||
{
|
{
|
||||||
private (int card, int[] win, int[] have)[] _cards = [];
|
private (int card, int[] win, int[] have)[] _cards = [];
|
||||||
private readonly Dictionary<int, int> _cardCount = [];
|
private readonly Dictionary<int, int> _cardCount = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _cards
|
Part1 = _cards
|
||||||
.Select(c => c.have.Intersect(c.win).Count())
|
.Select(c => c.have.Intersect(c.win).Count())
|
||||||
.Select(c => c == 0 ? 0 : Math.Pow(2, c - 1))
|
.Select(c => c == 0 ? 0 : Math.Pow(2, c - 1))
|
||||||
.Sum();
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = _cards.Length;
|
Part2 = _cards.Length;
|
||||||
for (int i = 0; i < _cards.Length; i++)
|
for (int i = 0; i < _cards.Length; i++)
|
||||||
{
|
{
|
||||||
var card = _cards[i];
|
var card = _cards[i];
|
||||||
var wins = card.have.Intersect(card.win).Count();
|
var wins = card.have.Intersect(card.win).Count();
|
||||||
var cCount = GetCardCount(card.card);
|
var cCount = GetCardCount(card.card);
|
||||||
for (int j = 1; j <= wins; j++)
|
for (int j = 1; j <= wins; j++)
|
||||||
AddCards(card.card + j, cCount);
|
AddCards(card.card + j, cCount);
|
||||||
Part2 += wins * cCount;
|
Part2 += wins * cCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetCardCount(int card)
|
private int GetCardCount(int card)
|
||||||
{
|
{
|
||||||
if(_cardCount.TryGetValue(card, out var count))
|
if(_cardCount.TryGetValue(card, out var count))
|
||||||
return count;
|
return count;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCards(int card, int count)
|
private void AddCards(int card, int count)
|
||||||
{
|
{
|
||||||
if(_cardCount.ContainsKey(card))
|
if(_cardCount.ContainsKey(card))
|
||||||
_cardCount[card] += count;
|
_cardCount[card] += count;
|
||||||
else
|
else
|
||||||
_cardCount.Add(card, count + 1);
|
_cardCount.Add(card, count + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines();
|
var lines = ReadInputLines();
|
||||||
_cards = new (int card, int[] win, int[] have)[lines.Length];
|
_cards = new (int card, int[] win, int[] have)[lines.Length];
|
||||||
for (int i = 0; i < lines.Length; i++)
|
for (int i = 0; i < lines.Length; i++)
|
||||||
{
|
{
|
||||||
var card = lines[i].Split(':');
|
var card = lines[i].Split(':');
|
||||||
var cardNum = int.Parse(card[0].Split(' ').Last());
|
var cardNum = int.Parse(card[0].Split(' ').Last());
|
||||||
var numbers = card[1].Split('|')
|
var numbers = card[1].Split('|')
|
||||||
.Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse));
|
.Select(v => v.Split(' ').Where(v => v.Length > 0).Select(int.Parse));
|
||||||
_cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray());
|
_cards[i] = (cardNum, numbers.First().ToArray(), numbers.Last().ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +1,73 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day5;
|
namespace AdventOfCode.Problems.AOC2023.Day5;
|
||||||
internal class CategoryEvaluator
|
internal class CategoryEvaluator
|
||||||
{
|
{
|
||||||
public Dictionary<Category, CategoryMapper> destinations = [];
|
public Dictionary<Category, CategoryMapper> destinations = [];
|
||||||
|
|
||||||
public CategoryEvaluator(CategoryMapper[] mappers)
|
public CategoryEvaluator(CategoryMapper[] mappers)
|
||||||
{
|
{
|
||||||
destinations = mappers.ToDictionary(m => m.Destination);
|
destinations = mappers.ToDictionary(m => m.Destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Evaluate(Category source, long sourceValue, Category destination)
|
public long Evaluate(Category source, long sourceValue, Category destination)
|
||||||
{
|
{
|
||||||
var mappers = new List<CategoryMapper>();
|
var mappers = new List<CategoryMapper>();
|
||||||
var curMapper = destinations[destination];
|
var curMapper = destinations[destination];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
mappers.Add(curMapper);
|
mappers.Add(curMapper);
|
||||||
curMapper = destinations[curMapper.Source];
|
curMapper = destinations[curMapper.Source];
|
||||||
} while (curMapper.Source != source);
|
} while (curMapper.Source != source);
|
||||||
mappers.Add(destinations[mappers.Last().Source]);
|
mappers.Add(destinations[mappers.Last().Source]);
|
||||||
mappers.Reverse();
|
mappers.Reverse();
|
||||||
var result = sourceValue;
|
var result = sourceValue;
|
||||||
foreach (var mapper in mappers)
|
foreach (var mapper in mappers)
|
||||||
{
|
{
|
||||||
result = mapper.Evaluate(result);
|
result = mapper.Evaluate(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination)
|
public (long start, long end)[] Evaluate(Category source, (long start, long end)[] seeds, Category destination)
|
||||||
{
|
{
|
||||||
var mappers = new List<CategoryMapper>();
|
var mappers = new List<CategoryMapper>();
|
||||||
var curMapper = destinations[destination];
|
var curMapper = destinations[destination];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
mappers.Add(curMapper);
|
mappers.Add(curMapper);
|
||||||
curMapper = destinations[curMapper.Source];
|
curMapper = destinations[curMapper.Source];
|
||||||
} while (curMapper.Source != source);
|
} while (curMapper.Source != source);
|
||||||
mappers.Add(destinations[mappers.Last().Source]);
|
mappers.Add(destinations[mappers.Last().Source]);
|
||||||
mappers.Reverse();
|
mappers.Reverse();
|
||||||
var result = seeds;
|
var result = seeds;
|
||||||
foreach (var mapper in mappers)
|
foreach (var mapper in mappers)
|
||||||
{
|
{
|
||||||
result = mapper.Evaluate(result);
|
result = mapper.Evaluate(result);
|
||||||
}
|
}
|
||||||
return result.Distinct().ToArray();
|
return result.Distinct().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CategoryMapper GetCategoryMapper(Category destination)
|
public CategoryMapper GetCategoryMapper(Category destination)
|
||||||
{
|
{
|
||||||
return destinations[destination];
|
return destinations[destination];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public enum Category
|
public enum Category
|
||||||
{
|
{
|
||||||
Seed,
|
Seed,
|
||||||
Soil,
|
Soil,
|
||||||
Fertilizer,
|
Fertilizer,
|
||||||
Water,
|
Water,
|
||||||
Light,
|
Light,
|
||||||
Temperature,
|
Temperature,
|
||||||
Humidity,
|
Humidity,
|
||||||
Location
|
Location
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,88 +1,88 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day5;
|
namespace AdventOfCode.Problems.AOC2023.Day5;
|
||||||
internal class CategoryMapper
|
internal class CategoryMapper
|
||||||
{
|
{
|
||||||
public CategoryEvaluator.Category Source { get; }
|
public CategoryEvaluator.Category Source { get; }
|
||||||
public CategoryEvaluator.Category Destination { get; }
|
public CategoryEvaluator.Category Destination { get; }
|
||||||
public long[] DestinationStart { get; }
|
public long[] DestinationStart { get; }
|
||||||
public long[] DestinationEnd { get; }
|
public long[] DestinationEnd { get; }
|
||||||
public long[] SourceStart { get; }
|
public long[] SourceStart { get; }
|
||||||
public long[] SourceEnd { get; }
|
public long[] SourceEnd { get; }
|
||||||
public long[] RangeLength { get; }
|
public long[] RangeLength { get; }
|
||||||
public long[] Gap { get; }
|
public long[] Gap { get; }
|
||||||
|
|
||||||
public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length)
|
public CategoryMapper(CategoryEvaluator.Category source, CategoryEvaluator.Category destination, long[] destinationStart, long[] sourceStart, long[] length)
|
||||||
{
|
{
|
||||||
Source = source;
|
Source = source;
|
||||||
Destination = destination;
|
Destination = destination;
|
||||||
DestinationStart = destinationStart;
|
DestinationStart = destinationStart;
|
||||||
DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray();
|
DestinationEnd = destinationStart.Select((v, i) => v + length[i]).ToArray();
|
||||||
SourceStart = sourceStart;
|
SourceStart = sourceStart;
|
||||||
SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray();
|
SourceEnd = sourceStart.Select((v, i) => v + length[i]).ToArray();
|
||||||
RangeLength = length;
|
RangeLength = length;
|
||||||
Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray();
|
Gap = sourceStart.Select((v, i) => destinationStart[i] - v).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CategoryMapper Parse(string categoryData)
|
public static CategoryMapper Parse(string categoryData)
|
||||||
{
|
{
|
||||||
var lines = categoryData.Split("\r\n");
|
var lines = categoryData.Split("\r\n");
|
||||||
var names = lines[0].Split(' ')[0].Split('-');
|
var names = lines[0].Split(' ')[0].Split('-');
|
||||||
var source = Enum.Parse<CategoryEvaluator.Category>(names[0], true);
|
var source = Enum.Parse<CategoryEvaluator.Category>(names[0], true);
|
||||||
var dst = Enum.Parse<CategoryEvaluator.Category>(names[^1], true);
|
var dst = Enum.Parse<CategoryEvaluator.Category>(names[^1], true);
|
||||||
|
|
||||||
var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray());
|
var mappingData = lines[1..].Select(ln => ln.Split(' ').Select(long.Parse).ToArray());
|
||||||
var dStart = mappingData.Select(d => d[0]).ToArray();
|
var dStart = mappingData.Select(d => d[0]).ToArray();
|
||||||
var sStart = mappingData.Select(d => d[1]).ToArray();
|
var sStart = mappingData.Select(d => d[1]).ToArray();
|
||||||
var len = mappingData.Select(d => d[2]).ToArray();
|
var len = mappingData.Select(d => d[2]).ToArray();
|
||||||
return new CategoryMapper(source, dst, dStart, sStart, len);
|
return new CategoryMapper(source, dst, dStart, sStart, len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Evaluate(long value)
|
public long Evaluate(long value)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < DestinationStart.Length; i++)
|
for (int i = 0; i < DestinationStart.Length; i++)
|
||||||
{
|
{
|
||||||
if (SourceStart[i] > value)
|
if (SourceStart[i] > value)
|
||||||
continue;
|
continue;
|
||||||
if (SourceEnd[i] < value)
|
if (SourceEnd[i] < value)
|
||||||
continue;
|
continue;
|
||||||
return value + Gap[i];
|
return value + Gap[i];
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public (long start, long end)[] Evaluate((long start, long end)[] ranges)
|
public (long start, long end)[] Evaluate((long start, long end)[] ranges)
|
||||||
{
|
{
|
||||||
var result = new List<(long start, long end)>();
|
var result = new List<(long start, long end)>();
|
||||||
for (int i = 0; i < DestinationStart.Length; i++)
|
for (int i = 0; i < DestinationStart.Length; i++)
|
||||||
{
|
{
|
||||||
result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i]))));
|
result.AddRange(ranges.SelectMany(r => SubdivideRange(r, (SourceStart[i], SourceEnd[i]))));
|
||||||
}
|
}
|
||||||
return result.Distinct().Select(v => (Evaluate(v.start), Evaluate(v.end))).ToArray();
|
return result.Distinct().Select(v => (Evaluate(v.start), Evaluate(v.end))).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (long start, long end)[] SubdivideRange((long start, long end) source, (long start, long end) dst)
|
public static (long start, long end)[] SubdivideRange((long start, long end) source, (long start, long end) dst)
|
||||||
{
|
{
|
||||||
if (source.start >= dst.start && source.end <= dst.end)
|
if (source.start >= dst.start && source.end <= dst.end)
|
||||||
return [source];
|
return [source];
|
||||||
if(source.end < dst.end)
|
if(source.end < dst.end)
|
||||||
return [source];
|
return [source];
|
||||||
if(source.start > dst.start)
|
if(source.start > dst.start)
|
||||||
return [source];
|
return [source];
|
||||||
|
|
||||||
if(source.start < dst.start)
|
if(source.start < dst.start)
|
||||||
return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)];
|
return [(source.start, dst.start - 1), (dst.start, source.end), (source.end + 1, dst.end)];
|
||||||
else
|
else
|
||||||
return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)];
|
return [(dst.start, source.start - 1), (source.start, dst.end), (dst.end + 1, source.end)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Source} -> {Destination}";
|
return $"{Source} -> {Destination}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day5;
|
namespace AdventOfCode.Problems.AOC2023.Day5;
|
||||||
[ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")]
|
[ProblemInfo(2023, 5, "If You Give A Seed A Fertilizer")]
|
||||||
internal class SeedFertilizer : Problem<long, long>
|
internal class SeedFertilizer : Problem<long, long>
|
||||||
{
|
{
|
||||||
private long[] _seeds = [];
|
private long[] _seeds = [];
|
||||||
private CategoryEvaluator _evaluator = new ([]);
|
private CategoryEvaluator _evaluator = new ([]);
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputText("sample.txt");
|
var data = ReadInputText("sample.txt");
|
||||||
var sections = data.Split("\r\n\r\n");
|
var sections = data.Split("\r\n\r\n");
|
||||||
_seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray();
|
_seeds = sections[0].Split(": ")[1].Split(" ").Select(long.Parse).ToArray();
|
||||||
|
|
||||||
var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray();
|
var mappers = sections[1..].Select(CategoryMapper.Parse).ToArray();
|
||||||
_evaluator = new CategoryEvaluator(mappers);
|
_evaluator = new CategoryEvaluator(mappers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location));
|
var evaludated = _seeds.Select(s => _evaluator.Evaluate(CategoryEvaluator.Category.Seed, s, CategoryEvaluator.Category.Location));
|
||||||
Part1 = evaludated.Min();
|
Part1 = evaludated.Min();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var splitRanges = _evaluator.Evaluate(CategoryEvaluator.Category.Seed, _seeds.Chunk(2).Select(s => (s[0], s[0] + s[1])).ToArray(), CategoryEvaluator.Category.Location);
|
var splitRanges = _evaluator.Evaluate(CategoryEvaluator.Category.Seed, _seeds.Chunk(2).Select(s => (s[0], s[0] + s[1])).ToArray(), CategoryEvaluator.Category.Location);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +1,65 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day6;
|
namespace AdventOfCode.Problems.AOC2023.Day6;
|
||||||
[ProblemInfo(2023, 6, "Wait For It")]
|
[ProblemInfo(2023, 6, "Wait For It")]
|
||||||
internal class WaitForIt : Problem<int, long>
|
internal class WaitForIt : Problem<int, long>
|
||||||
{
|
{
|
||||||
private int[] _times = [];
|
private int[] _times = [];
|
||||||
private int[] _distances = [];
|
private int[] _distances = [];
|
||||||
private int _realTime;
|
private int _realTime;
|
||||||
private long _realDistance;
|
private long _realDistance;
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
_times = lines[0].Split(':')[1]
|
_times = lines[0].Split(':')[1]
|
||||||
.Split(' ')
|
.Split(' ')
|
||||||
.Where(e => e.Length > 0)
|
.Where(e => e.Length > 0)
|
||||||
.Select(int.Parse)
|
.Select(int.Parse)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
_distances = lines[1].Split(':')[1]
|
_distances = lines[1].Split(':')[1]
|
||||||
.Split(' ')
|
.Split(' ')
|
||||||
.Where(e => e.Length > 0)
|
.Where(e => e.Length > 0)
|
||||||
.Select(int.Parse)
|
.Select(int.Parse)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
_realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", ""));
|
_realTime = int.Parse(lines[0].Split(":")[1].Replace(" ", ""));
|
||||||
_realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", ""));
|
_realDistance = long.Parse(lines[1].Split(":")[1].Replace(" ", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var winList = new List<int>();
|
var winList = new List<int>();
|
||||||
for (int i = 0; i < _times.Length; i++)
|
for (int i = 0; i < _times.Length; i++)
|
||||||
{
|
{
|
||||||
var time = _times[i];
|
var time = _times[i];
|
||||||
var distance = _distances[i];
|
var distance = _distances[i];
|
||||||
var minTime = (int)Math.Floor((float)distance / time);
|
var minTime = (int)Math.Floor((float)distance / time);
|
||||||
var possibleHeldTimes = Enumerable.Range(minTime, time - minTime);
|
var possibleHeldTimes = Enumerable.Range(minTime, time - minTime);
|
||||||
var races = possibleHeldTimes.Select(t => (time - t) * t);
|
var races = possibleHeldTimes.Select(t => (time - t) * t);
|
||||||
winList.Add(races.Count(d => d > distance));
|
winList.Add(races.Count(d => d > distance));
|
||||||
}
|
}
|
||||||
Part1 = winList.Aggregate((a, b) => a * b);
|
Part1 = winList.Aggregate((a, b) => a * b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var minTime = (long)Math.Floor((float)_realDistance/ _realTime);
|
var minTime = (long)Math.Floor((float)_realDistance/ _realTime);
|
||||||
var maxTime = _realTime - minTime;
|
var maxTime = _realTime - minTime;
|
||||||
for (long i = minTime; i <= maxTime; i++)
|
for (long i = minTime; i <= maxTime; i++)
|
||||||
{
|
{
|
||||||
var dist = (_realTime - i) * i;
|
var dist = (_realTime - i) * i;
|
||||||
if(dist > _realDistance)
|
if(dist > _realDistance)
|
||||||
Part2++;
|
Part2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day7;
|
namespace AdventOfCode.Problems.AOC2023.Day7;
|
||||||
[ProblemInfo(2023, 7, "Camel Cards")]
|
[ProblemInfo(2023, 7, "Camel Cards")]
|
||||||
internal class CamelCards : Problem<int, int>
|
internal class CamelCards : Problem<int, int>
|
||||||
{
|
{
|
||||||
private CamelHand[] _hands = [];
|
private CamelHand[] _hands = [];
|
||||||
private CamelHand[] _jokerHands = [];
|
private CamelHand[] _jokerHands = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputLines("input.txt");
|
var data = ReadInputLines("input.txt");
|
||||||
_hands = data.Select(d => new CamelHand(d)).ToArray();
|
_hands = data.Select(d => new CamelHand(d)).ToArray();
|
||||||
_jokerHands = data.Select(d => new CamelHand(d, true)).ToArray();
|
_jokerHands = data.Select(d => new CamelHand(d, true)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var x = _hands.Order();
|
var x = _hands.Order();
|
||||||
Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
|
Part1 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var x = _jokerHands.Order().Print();
|
var x = _jokerHands.Order().Print();
|
||||||
//x.Where(x => x.Hand.Contains('J')).Print();
|
//x.Where(x => x.Hand.Contains('J')).Print();
|
||||||
Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
|
Part2 = x.Select((h, i) => (i + 1) * h.Bid).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,106 +1,106 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day7;
|
namespace AdventOfCode.Problems.AOC2023.Day7;
|
||||||
internal class CamelHand : IComparable<CamelHand>
|
internal class CamelHand : IComparable<CamelHand>
|
||||||
{
|
{
|
||||||
public static readonly List<char> CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
|
public static readonly List<char> CARDS = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A' ];
|
||||||
public static readonly List<char> CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ];
|
public static readonly List<char> CARDS_JOKER = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A' ];
|
||||||
|
|
||||||
public string Hand { get; set; }
|
public string Hand { get; set; }
|
||||||
public int Bid { get; set; }
|
public int Bid { get; set; }
|
||||||
public int Value { get; set; }
|
public int Value { get; set; }
|
||||||
public HandType Type { get; set; }
|
public HandType Type { get; set; }
|
||||||
public CamelHand(string data, bool useJoker = false)
|
public CamelHand(string data, bool useJoker = false)
|
||||||
{
|
{
|
||||||
var split = data.Split(' ');
|
var split = data.Split(' ');
|
||||||
Hand = split[0];
|
Hand = split[0];
|
||||||
Bid = int.Parse(split[1]);
|
Bid = int.Parse(split[1]);
|
||||||
Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand);
|
Type = useJoker ? GetJokerHandType(Hand) : GetHandType(Hand);
|
||||||
Value = CalculateValue(Hand, useJoker);
|
Value = CalculateValue(Hand, useJoker);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CalculateValue(string hand, bool useJoker)
|
public static int CalculateValue(string hand, bool useJoker)
|
||||||
{
|
{
|
||||||
var total = 0;
|
var total = 0;
|
||||||
for (int i = 0; i < hand.Length; i++)
|
for (int i = 0; i < hand.Length; i++)
|
||||||
{
|
{
|
||||||
var p = (hand.Length - i - 1);
|
var p = (hand.Length - i - 1);
|
||||||
var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]);
|
var v = useJoker ? CARDS_JOKER.IndexOf(hand[i]) : CARDS.IndexOf(hand[i]);
|
||||||
total += (v + 1) * (int)Math.Pow(13, p);
|
total += (v + 1) * (int)Math.Pow(13, p);
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsStrongerThan(CamelHand card)
|
public bool IsStrongerThan(CamelHand card)
|
||||||
{
|
{
|
||||||
if (Type > card.Type)
|
if (Type > card.Type)
|
||||||
return true;
|
return true;
|
||||||
if(Type < card.Type)
|
if(Type < card.Type)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Value >= card.Value;
|
return Value >= card.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HandType GetJokerHandType(string hand)
|
private static HandType GetJokerHandType(string hand)
|
||||||
{
|
{
|
||||||
var type = GetHandType(hand);
|
var type = GetHandType(hand);
|
||||||
if (type == HandType.FiveOfKind)
|
if (type == HandType.FiveOfKind)
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
if (!hand.Contains('J'))
|
if (!hand.Contains('J'))
|
||||||
return type;
|
return type;
|
||||||
var bestCard = hand.GroupBy(c => c)
|
var bestCard = hand.GroupBy(c => c)
|
||||||
.OrderByDescending(c => c.Count())
|
.OrderByDescending(c => c.Count())
|
||||||
.First(c => c.Key != 'J').Key;
|
.First(c => c.Key != 'J').Key;
|
||||||
|
|
||||||
var newHand = hand.Replace('J', bestCard);
|
var newHand = hand.Replace('J', bestCard);
|
||||||
return GetHandType(newHand);
|
return GetHandType(newHand);
|
||||||
}
|
}
|
||||||
private static HandType GetHandType(string hand)
|
private static HandType GetHandType(string hand)
|
||||||
{
|
{
|
||||||
var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray();
|
var cardGroups = hand.GroupBy(c => c).Select(g => g.Count()).ToArray();
|
||||||
|
|
||||||
if (cardGroups.Length == 1)
|
if (cardGroups.Length == 1)
|
||||||
return HandType.FiveOfKind;
|
return HandType.FiveOfKind;
|
||||||
if(cardGroups.Contains(4))
|
if(cardGroups.Contains(4))
|
||||||
return HandType.FourOfKind;
|
return HandType.FourOfKind;
|
||||||
if (cardGroups.Contains(3) && cardGroups.Contains(2))
|
if (cardGroups.Contains(3) && cardGroups.Contains(2))
|
||||||
return HandType.FullHouse;
|
return HandType.FullHouse;
|
||||||
if(cardGroups.Contains(3))
|
if(cardGroups.Contains(3))
|
||||||
return HandType.ThreeOfKind;
|
return HandType.ThreeOfKind;
|
||||||
|
|
||||||
var pairs = cardGroups.Count(c => c == 2);
|
var pairs = cardGroups.Count(c => c == 2);
|
||||||
if (pairs == 2)
|
if (pairs == 2)
|
||||||
return HandType.TwoPair;
|
return HandType.TwoPair;
|
||||||
if (pairs == 1)
|
if (pairs == 1)
|
||||||
return HandType.OnePair;
|
return HandType.OnePair;
|
||||||
|
|
||||||
return HandType.HighCard;
|
return HandType.HighCard;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CompareTo(CamelHand? other)
|
public int CompareTo(CamelHand? other)
|
||||||
{
|
{
|
||||||
if(other == null) return 1;
|
if(other == null) return 1;
|
||||||
return IsStrongerThan(other) ? 1 : -1;
|
return IsStrongerThan(other) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"[{Value}] {Hand}: {Type} | {Bid}";
|
return $"[{Value}] {Hand}: {Type} | {Bid}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum HandType
|
public enum HandType
|
||||||
{
|
{
|
||||||
HighCard,
|
HighCard,
|
||||||
OnePair,
|
OnePair,
|
||||||
TwoPair,
|
TwoPair,
|
||||||
ThreeOfKind,
|
ThreeOfKind,
|
||||||
FullHouse,
|
FullHouse,
|
||||||
FourOfKind,
|
FourOfKind,
|
||||||
FiveOfKind
|
FiveOfKind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +1,74 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day8;
|
namespace AdventOfCode.Problems.AOC2023.Day8;
|
||||||
|
|
||||||
[ProblemInfo(2023, 8, "Haunted Wasteland")]
|
[ProblemInfo(2023, 8, "Haunted Wasteland")]
|
||||||
internal class HauntedWasteland : Problem<int, long>
|
internal class HauntedWasteland : Problem<int, long>
|
||||||
{
|
{
|
||||||
private string _path = string.Empty;
|
private string _path = string.Empty;
|
||||||
private Dictionary<string, (string left, string right)> _nodes = [];
|
private Dictionary<string, (string left, string right)> _nodes = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var data = ReadInputLines();
|
var data = ReadInputLines();
|
||||||
_path = data[0];
|
_path = data[0];
|
||||||
|
|
||||||
for (int i = 2; i < data.Length; i++)
|
for (int i = 2; i < data.Length; i++)
|
||||||
{
|
{
|
||||||
var curLine = data[i].Split('=');
|
var curLine = data[i].Split('=');
|
||||||
var node = curLine[0].TrimEnd();
|
var node = curLine[0].TrimEnd();
|
||||||
var branches = curLine[1][2..^1].Split(", ");
|
var branches = curLine[1][2..^1].Split(", ");
|
||||||
_nodes.Add(node, (branches[0], branches[1]));
|
_nodes.Add(node, (branches[0], branches[1]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var curPos = "AAA";
|
var curPos = "AAA";
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var steps = 0;
|
var steps = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
curPos = _path[i] switch
|
curPos = _path[i] switch
|
||||||
{
|
{
|
||||||
'L' => _nodes[curPos].left,
|
'L' => _nodes[curPos].left,
|
||||||
'R' => _nodes[curPos].right,
|
'R' => _nodes[curPos].right,
|
||||||
_ => throw new Exception("Something went horribly wrong")
|
_ => throw new Exception("Something went horribly wrong")
|
||||||
};
|
};
|
||||||
i = (i + 1) % _path.Length;
|
i = (i + 1) % _path.Length;
|
||||||
steps++;
|
steps++;
|
||||||
} while (curPos != "ZZZ");
|
} while (curPos != "ZZZ");
|
||||||
Part1 = steps;
|
Part1 = steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray();
|
var curPos = _nodes.Keys.Where(n => n[^1] == 'A').ToArray();
|
||||||
var len = new long[curPos.Length];
|
var len = new long[curPos.Length];
|
||||||
var i = 0;
|
var i = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
for (int j = 0; j < curPos.Length; j++)
|
for (int j = 0; j < curPos.Length; j++)
|
||||||
{
|
{
|
||||||
if (curPos[j][^1] == 'Z')
|
if (curPos[j][^1] == 'Z')
|
||||||
continue;
|
continue;
|
||||||
len[j]++;
|
len[j]++;
|
||||||
curPos[j] = _path[i] switch
|
curPos[j] = _path[i] switch
|
||||||
{
|
{
|
||||||
'L' => _nodes[curPos[j]].left,
|
'L' => _nodes[curPos[j]].left,
|
||||||
'R' => _nodes[curPos[j]].right,
|
'R' => _nodes[curPos[j]].right,
|
||||||
_ => throw new Exception("Something went horribly wrong")
|
_ => throw new Exception("Something went horribly wrong")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
i = (i + 1) % _path.Length;
|
i = (i + 1) % _path.Length;
|
||||||
} while (curPos.Any(n => n[^1] != 'Z'));
|
} while (curPos.Any(n => n[^1] != 'Z'));
|
||||||
|
|
||||||
Part2 = len.LCM();
|
Part2 = len.LCM();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,85 +1,85 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2023.Day9;
|
namespace AdventOfCode.Problems.AOC2023.Day9;
|
||||||
[ProblemInfo(2023, 9, "Mirage Maintenance")]
|
[ProblemInfo(2023, 9, "Mirage Maintenance")]
|
||||||
internal class MirageMaintenance : Problem<long, long>
|
internal class MirageMaintenance : Problem<long, long>
|
||||||
{
|
{
|
||||||
private long[][] _history = [];
|
private long[][] _history = [];
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray();
|
_history = ReadInputLines("input.txt").Select(ln => ln.Split(' ').Select(long.Parse).ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long CalculateNumber(long[] values, bool last = true)
|
public long CalculateNumber(long[] values, bool last = true)
|
||||||
{
|
{
|
||||||
var diffs = new long[values.Length - 1];
|
var diffs = new long[values.Length - 1];
|
||||||
for (int i = 0; i < values.Length - 1; i++)
|
for (int i = 0; i < values.Length - 1; i++)
|
||||||
diffs[i] = values[i + 1] - values[i];
|
diffs[i] = values[i + 1] - values[i];
|
||||||
|
|
||||||
if (diffs.Any(d => d != 0))
|
if (diffs.Any(d => d != 0))
|
||||||
return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last));
|
return last ? (values.Last() + CalculateNumber(diffs, last)) : (values.First() - CalculateNumber(diffs, last));
|
||||||
else
|
else
|
||||||
return last ? values.Last() : values.First();
|
return last ? values.Last() : values.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Optimize too soon garbage")]
|
[Obsolete("Optimize too soon garbage")]
|
||||||
public long GetNextNumber(long[] history)
|
public long GetNextNumber(long[] history)
|
||||||
{
|
{
|
||||||
var data = new List<List<long>>
|
var data = new List<List<long>>
|
||||||
{
|
{
|
||||||
new(history.Reverse())
|
new(history.Reverse())
|
||||||
};
|
};
|
||||||
CalculateLayer(data, 1, 1);
|
CalculateLayer(data, 1, 1);
|
||||||
var sum = data.Select(d => d.First()).Sum();
|
var sum = data.Select(d => d.First()).Sum();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine(string.Join(',', history));
|
Console.WriteLine(string.Join(',', history));
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
|
|
||||||
foreach (var item in data)
|
foreach (var item in data)
|
||||||
Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString())));
|
Console.WriteLine(string.Join(" | ", item.Select(n => n.ToString())));
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Optimize too soon garbage")]
|
[Obsolete("Optimize too soon garbage")]
|
||||||
public void CalculateLayer(List<List<long>> data, int layer, int pos)
|
public void CalculateLayer(List<List<long>> data, int layer, int pos)
|
||||||
{
|
{
|
||||||
while (data.Count <= layer)
|
while (data.Count <= layer)
|
||||||
data.Add([]);
|
data.Add([]);
|
||||||
var lastLayer = layer - 1;
|
var lastLayer = layer - 1;
|
||||||
if (layer != 0 && data[lastLayer].Count <= pos)
|
if (layer != 0 && data[lastLayer].Count <= pos)
|
||||||
CalculateLayer(data, lastLayer, pos + 1);
|
CalculateLayer(data, lastLayer, pos + 1);
|
||||||
|
|
||||||
var right = data[lastLayer][pos - 1];
|
var right = data[lastLayer][pos - 1];
|
||||||
var left = data[lastLayer][pos];
|
var left = data[lastLayer][pos];
|
||||||
var diff = right - left;
|
var diff = right - left;
|
||||||
data[layer].Add(diff);
|
data[layer].Add(diff);
|
||||||
if (diff != 0 && pos == 1)
|
if (diff != 0 && pos == 1)
|
||||||
CalculateLayer(data, layer + 1, 1);
|
CalculateLayer(data, layer + 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum State
|
public enum State
|
||||||
{
|
{
|
||||||
Diff,
|
Diff,
|
||||||
Expand,
|
Expand,
|
||||||
Predict
|
Predict
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
//GetNextNumber(_history[2]);
|
//GetNextNumber(_history[2]);
|
||||||
Part1 = _history.Select(c => CalculateNumber(c)).Sum();
|
Part1 = _history.Select(c => CalculateNumber(c)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = _history.Select(c => CalculateNumber(c, false)).Sum();
|
Part2 = _history.Select(c => CalculateNumber(c, false)).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day1;
|
namespace AdventOfCode.Problems.AOC2024.Day1;
|
||||||
[ProblemInfo(2024, 1, "Historian Hysteria")]
|
[ProblemInfo(2024, 1, "Historian Hysteria")]
|
||||||
internal class HistorianHysteria : Problem<int, int>
|
internal class HistorianHysteria : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[] _left = [];
|
private int[] _left = [];
|
||||||
private int[] _right = [];
|
private int[] _right = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _left.Order()
|
Part1 = _left.Order()
|
||||||
.Zip(_right.Order())
|
.Zip(_right.Order())
|
||||||
.Select(a => Math.Abs(a.First - a.Second))
|
.Select(a => Math.Abs(a.First - a.Second))
|
||||||
.Sum();
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var rightFeq = _right.GroupBy(x => x)
|
var rightFeq = _right.GroupBy(x => x)
|
||||||
.ToFrozenDictionary(g => g.Key, g => g.Count());
|
.ToFrozenDictionary(g => g.Key, g => g.Count());
|
||||||
Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0)
|
Part2 = _left.Select(x => rightFeq.TryGetValue(x, out var f) ? f * x : 0)
|
||||||
.Sum();
|
.Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines();
|
var lines = ReadInputLines();
|
||||||
var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList();
|
var data = lines.Select(l => l.Split(' ').Select(int.Parse)).ToList();
|
||||||
_left = data.Select(l => l.First()).ToArray();
|
_left = data.Select(l => l.First()).ToArray();
|
||||||
_right = data.Select(l => l.Last()).ToArray();
|
_right = data.Select(l => l.Last()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,102 +1,102 @@
|
|||||||
using AdventOfCode.Utils.Models;
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day10;
|
namespace AdventOfCode.Problems.AOC2024.Day10;
|
||||||
[ProblemInfo(2024, 10, "Hoof It")]
|
[ProblemInfo(2024, 10, "Hoof It")]
|
||||||
internal class HoofIt : Problem<int, int>
|
internal class HoofIt : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[][] _data = [];
|
private int[][] _data = [];
|
||||||
|
|
||||||
public static Vec2<int>[] DIRS = [
|
public static Vec2<int>[] DIRS = [
|
||||||
new(0, -1),
|
new(0, -1),
|
||||||
new(1, 0),
|
new(1, 0),
|
||||||
new(0, 1),
|
new(0, 1),
|
||||||
new(-1, 0),
|
new(-1, 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
for (int y = 0; y < _data.Length; y++)
|
for (int y = 0; y < _data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = _data[y];
|
var row = _data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
var h = row[x];
|
var h = row[x];
|
||||||
if (h != 0)
|
if (h != 0)
|
||||||
continue;
|
continue;
|
||||||
var (s,_) = GetScore(new(x, y));
|
var (s,_) = GetScore(new(x, y));
|
||||||
Part1 += s;
|
Part1 += s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
for (int y = 0; y < _data.Length; y++)
|
for (int y = 0; y < _data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = _data[y];
|
var row = _data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
var h = row[x];
|
var h = row[x];
|
||||||
if (h != 0)
|
if (h != 0)
|
||||||
continue;
|
continue;
|
||||||
var (_, s) = GetScore(new(x, y));
|
var (_, s) = GetScore(new(x, y));
|
||||||
Part2 += s;
|
Part2 += s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int score, int scoreDistinct) GetScore(Vec2<int> pos)
|
public (int score, int scoreDistinct) GetScore(Vec2<int> pos)
|
||||||
{
|
{
|
||||||
return GetScore(pos, []);
|
return GetScore(pos, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int score, int scoreDistinct) GetScore(Vec2<int> pos, HashSet<Vec2<int>> visited)
|
public (int score, int scoreDistinct) GetScore(Vec2<int> pos, HashSet<Vec2<int>> visited)
|
||||||
{
|
{
|
||||||
var curHeight = _data[pos.Y][pos.X];
|
var curHeight = _data[pos.Y][pos.X];
|
||||||
if (curHeight == 9)
|
if (curHeight == 9)
|
||||||
{
|
{
|
||||||
if(visited.Contains(pos))
|
if(visited.Contains(pos))
|
||||||
return (0, 1);
|
return (0, 1);
|
||||||
visited.Add(pos);
|
visited.Add(pos);
|
||||||
return (1, 1);
|
return (1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var score = 0;
|
var score = 0;
|
||||||
var scoreDistinct = 0;
|
var scoreDistinct = 0;
|
||||||
foreach (var dir in DIRS)
|
foreach (var dir in DIRS)
|
||||||
{
|
{
|
||||||
var n = pos + dir;
|
var n = pos + dir;
|
||||||
if (!IsInBounds(n))
|
if (!IsInBounds(n))
|
||||||
continue;
|
continue;
|
||||||
var h = _data[n.Y][n.X];
|
var h = _data[n.Y][n.X];
|
||||||
if (h - curHeight != 1)
|
if (h - curHeight != 1)
|
||||||
continue;
|
continue;
|
||||||
var (s, d)= GetScore(n, visited);
|
var (s, d)= GetScore(n, visited);
|
||||||
score += s;
|
score += s;
|
||||||
scoreDistinct += d;
|
scoreDistinct += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (score, scoreDistinct);
|
return (score, scoreDistinct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsInBounds(Vec2<int> pos)
|
public bool IsInBounds(Vec2<int> pos)
|
||||||
{
|
{
|
||||||
if (pos.X < 0 || pos.Y < 0)
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
return false;
|
return false;
|
||||||
if(pos.X >= _data.Length || pos.Y >= _data[0].Length)
|
if(pos.X >= _data.Length || pos.Y >= _data[0].Length)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
|
_data = ReadInputLines("input.txt").Select(l => l.Select(v => v - '0').ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +1,115 @@
|
|||||||
using Superpower.Model;
|
using Superpower.Model;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day11;
|
namespace AdventOfCode.Problems.AOC2024.Day11;
|
||||||
|
|
||||||
[ProblemInfo(2024, 11, "Plutonian Pebbles")]
|
[ProblemInfo(2024, 11, "Plutonian Pebbles")]
|
||||||
public class PlutonianPebbles : Problem<long, long>
|
public class PlutonianPebbles : Problem<long, long>
|
||||||
{
|
{
|
||||||
private List<long> _data = [];
|
private List<long> _data = [];
|
||||||
private readonly Dictionary<(long, long), long> _depthLookup = [];
|
private readonly Dictionary<(long, long), long> _depthLookup = [];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = _data.Sum(v => ProcessStoneRecursive(v, 25));
|
Part1 = _data.Sum(v => ProcessStoneRecursive(v, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = _data.Sum(v => ProcessStoneRecursive(v, 75));
|
Part2 = _data.Sum(v => ProcessStoneRecursive(v, 75));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ProcessStoneRecursive(long stone, long target, long curDepth = 0)
|
public long ProcessStoneRecursive(long stone, long target, long curDepth = 0)
|
||||||
{
|
{
|
||||||
if (curDepth == target)
|
if (curDepth == target)
|
||||||
return 1;
|
return 1;
|
||||||
var d = target - curDepth;
|
var d = target - curDepth;
|
||||||
if(_depthLookup.TryGetValue((stone, d), out var c))
|
if(_depthLookup.TryGetValue((stone, d), out var c))
|
||||||
return c;
|
return c;
|
||||||
long result;
|
long result;
|
||||||
if (stone == 0)
|
if (stone == 0)
|
||||||
result = ProcessStoneRecursive(1, target, curDepth + 1);
|
result = ProcessStoneRecursive(1, target, curDepth + 1);
|
||||||
else if (FastSplit(stone, out var left, out var right))
|
else if (FastSplit(stone, out var left, out var right))
|
||||||
result = ProcessStoneRecursive(left, target, curDepth + 1) + ProcessStoneRecursive(right, target, curDepth + 1);
|
result = ProcessStoneRecursive(left, target, curDepth + 1) + ProcessStoneRecursive(right, target, curDepth + 1);
|
||||||
else
|
else
|
||||||
result = ProcessStoneRecursive(stone * 2024, target, curDepth + 1);
|
result = ProcessStoneRecursive(stone * 2024, target, curDepth + 1);
|
||||||
|
|
||||||
_depthLookup.Add((stone, d), result);
|
_depthLookup.Add((stone, d), result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Run(long count)
|
public long Run(long count)
|
||||||
{
|
{
|
||||||
var a = _data.ToList();
|
var a = _data.ToList();
|
||||||
var b = new List<long>(a.Count);
|
var b = new List<long>(a.Count);
|
||||||
for (long i = 0; i < count; i++)
|
for (long i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
foreach (var stone in a)
|
foreach (var stone in a)
|
||||||
ProcessStone(stone, b);
|
ProcessStone(stone, b);
|
||||||
|
|
||||||
(a, b) = (b, a);
|
(a, b) = (b, a);
|
||||||
b.Clear();
|
b.Clear();
|
||||||
}
|
}
|
||||||
return a.Count;
|
return a.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ProcessStone(long stone, List<long> data)
|
public void ProcessStone(long stone, List<long> data)
|
||||||
{
|
{
|
||||||
if (stone == 0)
|
if (stone == 0)
|
||||||
{
|
{
|
||||||
data.Add(1);
|
data.Add(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (FastSplit(stone, out var left, out var right))
|
if (FastSplit(stone, out var left, out var right))
|
||||||
{
|
{
|
||||||
data.Add(left);
|
data.Add(left);
|
||||||
data.Add(right);
|
data.Add(right);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
data.Add(stone * 2024);
|
data.Add(stone * 2024);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<long> Split(long stone, int len)
|
private static IEnumerable<long> Split(long stone, int len)
|
||||||
{
|
{
|
||||||
var v = stone.ToString();
|
var v = stone.ToString();
|
||||||
return [long.Parse(v[..(len / 2)]), long.Parse(v[(len / 2)..])];
|
return [long.Parse(v[..(len / 2)]), long.Parse(v[(len / 2)..])];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool FastSplit(long stone, out long left, out long right)
|
private static bool FastSplit(long stone, out long left, out long right)
|
||||||
{
|
{
|
||||||
|
|
||||||
var len = stone.DigitCount();
|
var len = stone.DigitCount();
|
||||||
if (len % 2 != 0)
|
if (len % 2 != 0)
|
||||||
{
|
{
|
||||||
left = 0;
|
left = 0;
|
||||||
right = 0;
|
right = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var l = QuickMath.FastPow10(len / 2);
|
var l = QuickMath.FastPow10(len / 2);
|
||||||
var a = stone / l;
|
var a = stone / l;
|
||||||
|
|
||||||
(left, right) = (a, stone - (a * l));
|
(left, right) = (a, stone - (a * l));
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsEvenDigits(long value, out int len)
|
private static bool IsEvenDigits(long value, out int len)
|
||||||
{
|
{
|
||||||
var v = len = value.ToString().Length;
|
var v = len = value.ToString().Length;
|
||||||
return v % 2 == 0;
|
return v % 2 == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputText("input.txt").Split(' ').Select(long.Parse).ToList();
|
_data = ReadInputText("input.txt").Split(' ').Select(long.Parse).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,301 +1,301 @@
|
|||||||
using AdventOfCode.Utils.Models;
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day12;
|
namespace AdventOfCode.Problems.AOC2024.Day12;
|
||||||
|
|
||||||
[ProblemInfo(2024, 12, "Garden Groups")]
|
[ProblemInfo(2024, 12, "Garden Groups")]
|
||||||
internal class GardenGroups : Problem<int, int>
|
internal class GardenGroups : Problem<int, int>
|
||||||
{
|
{
|
||||||
private char[][] _data = [];
|
private char[][] _data = [];
|
||||||
|
|
||||||
public static readonly Vec2<int>[] DIRS = [
|
public static readonly Vec2<int>[] DIRS = [
|
||||||
new(0,1),
|
new(0,1),
|
||||||
new(1,0),
|
new(1,0),
|
||||||
new(0,-1),
|
new(0,-1),
|
||||||
new(-1,0),
|
new(-1,0),
|
||||||
];
|
];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var r = FindPlots(_data);
|
var r = FindPlots(_data);
|
||||||
Part1 = r.Sum(plot => plot.area.Count * plot.perimeter);
|
Part1 = r.Sum(plot => plot.area.Count * plot.perimeter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var plots = FindPlots(_data);
|
var plots = FindPlots(_data);
|
||||||
var r = plots.Select(plot => (plot.plant, area: plot.area.Count, sides: CountSides(GroupSides(plot.outline, plot.area), plot.area)));
|
var r = plots.Select(plot => (plot.plant, area: plot.area.Count, sides: CountSides(GroupSides(plot.outline, plot.area), plot.area)));
|
||||||
foreach (var (plant, area, perimeter, outline) in plots)
|
foreach (var (plant, area, perimeter, outline) in plots)
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
var groups = GroupSides(outline, area);
|
var groups = GroupSides(outline, area);
|
||||||
Console.WriteLine($"{plant}: {CountSides(groups, area)}, {groups.Count}");
|
Console.WriteLine($"{plant}: {CountSides(groups, area)}, {groups.Count}");
|
||||||
DrawPlot(area, groups, plant);
|
DrawPlot(area, groups, plant);
|
||||||
}
|
}
|
||||||
Part2 = r.Sum(v => v.area * v.sides);
|
Part2 = r.Sum(v => v.area * v.sides);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<List<Vec2<int>>> GroupSides(List<Vec2<int>> outline, List<Vec2<int>> area)
|
public static List<List<Vec2<int>>> GroupSides(List<Vec2<int>> outline, List<Vec2<int>> area)
|
||||||
{
|
{
|
||||||
var result = new List<List<Vec2<int>>>();
|
var result = new List<List<Vec2<int>>>();
|
||||||
var visited = new HashSet<Vec2<int>>();
|
var visited = new HashSet<Vec2<int>>();
|
||||||
var open = new HashSet<Vec2<int>>(outline);
|
var open = new HashSet<Vec2<int>>(outline);
|
||||||
|
|
||||||
while (open.Count > 0)
|
while (open.Count > 0)
|
||||||
{
|
{
|
||||||
var p = open.First();
|
var p = open.First();
|
||||||
open.Remove(p);
|
open.Remove(p);
|
||||||
if(visited.Contains(p))
|
if(visited.Contains(p))
|
||||||
continue;
|
continue;
|
||||||
visited.Add(p);
|
visited.Add(p);
|
||||||
var group = new List<Vec2<int>>() { p };
|
var group = new List<Vec2<int>>() { p };
|
||||||
GetGroup(p, group);
|
GetGroup(p, group);
|
||||||
result.Add(group);
|
result.Add(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetGroup(Vec2<int> point, List<Vec2<int>> group)
|
void GetGroup(Vec2<int> point, List<Vec2<int>> group)
|
||||||
{
|
{
|
||||||
var up = DIRS[0];
|
var up = DIRS[0];
|
||||||
var right = DIRS[1];
|
var right = DIRS[1];
|
||||||
if(outline.Contains(point + up) || outline.Contains(point - up))
|
if(outline.Contains(point + up) || outline.Contains(point - up))
|
||||||
{
|
{
|
||||||
ProcessDirection(point, up, group);
|
ProcessDirection(point, up, group);
|
||||||
ProcessDirection(point, -up, group);
|
ProcessDirection(point, -up, group);
|
||||||
}
|
}
|
||||||
else if(outline.Contains(point + right) || outline.Contains(point - right))
|
else if(outline.Contains(point + right) || outline.Contains(point - right))
|
||||||
{
|
{
|
||||||
ProcessDirection(point, right, group);
|
ProcessDirection(point, right, group);
|
||||||
ProcessDirection(point, -right, group);
|
ProcessDirection(point, -right, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessDirection(Vec2<int> point, Vec2<int> dir, List<Vec2<int>> group)
|
void ProcessDirection(Vec2<int> point, Vec2<int> dir, List<Vec2<int>> group)
|
||||||
{
|
{
|
||||||
var n = point + dir;
|
var n = point + dir;
|
||||||
if (!outline.Contains(n) || visited.Contains(n))
|
if (!outline.Contains(n) || visited.Contains(n))
|
||||||
return;
|
return;
|
||||||
//if (!area.Contains(n + dir.YX) && !area.Contains(n - dir.YX))
|
//if (!area.Contains(n + dir.YX) && !area.Contains(n - dir.YX))
|
||||||
// return;
|
// return;
|
||||||
visited.Add(n);
|
visited.Add(n);
|
||||||
group.Add(n);
|
group.Add(n);
|
||||||
ProcessDirection(n, dir, group);
|
ProcessDirection(n, dir, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawPlot(List<Vec2<int>> area, List<List<Vec2<int>>> outline, char plant)
|
public static void DrawPlot(List<Vec2<int>> area, List<List<Vec2<int>>> outline, char plant)
|
||||||
{
|
{
|
||||||
var (min, max) = GetBounds(outline.SelectMany(v => v).ToList());
|
var (min, max) = GetBounds(outline.SelectMany(v => v).ToList());
|
||||||
|
|
||||||
int Sides(Vec2<int> point, List<Vec2<int>> group)
|
int Sides(Vec2<int> point, List<Vec2<int>> group)
|
||||||
{
|
{
|
||||||
var s = 0;
|
var s = 0;
|
||||||
foreach (var dir in DIRS)
|
foreach (var dir in DIRS)
|
||||||
{
|
{
|
||||||
var n = point + dir;
|
var n = point + dir;
|
||||||
if (area.Contains(n))
|
if (area.Contains(n))
|
||||||
s++;
|
s++;
|
||||||
if(group.Count > 1 && outline.Any(g => group != g && g.Contains(n)))
|
if(group.Count > 1 && outline.Any(g => group != g && g.Contains(n)))
|
||||||
s--;
|
s--;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleColor[] colors = [
|
ConsoleColor[] colors = [
|
||||||
ConsoleColor.Red,
|
ConsoleColor.Red,
|
||||||
ConsoleColor.DarkGreen,
|
ConsoleColor.DarkGreen,
|
||||||
ConsoleColor.Blue,
|
ConsoleColor.Blue,
|
||||||
ConsoleColor.DarkRed,
|
ConsoleColor.DarkRed,
|
||||||
ConsoleColor.Magenta,
|
ConsoleColor.Magenta,
|
||||||
ConsoleColor.DarkCyan,
|
ConsoleColor.DarkCyan,
|
||||||
ConsoleColor.DarkBlue,
|
ConsoleColor.DarkBlue,
|
||||||
ConsoleColor.DarkMagenta,
|
ConsoleColor.DarkMagenta,
|
||||||
ConsoleColor.DarkYellow
|
ConsoleColor.DarkYellow
|
||||||
];
|
];
|
||||||
|
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
for (int y = min.Y; y <= max.Y; y++)
|
||||||
{
|
{
|
||||||
for (int x = min.X; x <= max.X; x++)
|
for (int x = min.X; x <= max.X; x++)
|
||||||
{
|
{
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
var p = new Vec2<int>(x,y);
|
var p = new Vec2<int>(x,y);
|
||||||
if (area.Contains(p))
|
if (area.Contains(p))
|
||||||
{
|
{
|
||||||
Console.BackgroundColor = ConsoleColor.Black;
|
Console.BackgroundColor = ConsoleColor.Black;
|
||||||
Console.Write(plant);
|
Console.Write(plant);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var curSideGroup = outline.FirstOrDefault(v => v.Contains(p));
|
var curSideGroup = outline.FirstOrDefault(v => v.Contains(p));
|
||||||
if (curSideGroup != null)
|
if (curSideGroup != null)
|
||||||
{
|
{
|
||||||
var idx = outline.IndexOf(curSideGroup);
|
var idx = outline.IndexOf(curSideGroup);
|
||||||
Console.BackgroundColor = colors[idx % colors.Length];
|
Console.BackgroundColor = colors[idx % colors.Length];
|
||||||
var s = Sides(p, curSideGroup);
|
var s = Sides(p, curSideGroup);
|
||||||
if(curSideGroup.Count > 1 && IsInclosed(curSideGroup, outline, area))
|
if(curSideGroup.Count > 1 && IsInclosed(curSideGroup, outline, area))
|
||||||
Console.Write('&');
|
Console.Write('&');
|
||||||
else
|
else
|
||||||
Console.Write(s);
|
Console.Write(s);
|
||||||
}else
|
}else
|
||||||
Console.Write(' ');
|
Console.Write(' ');
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DrawPoints(List<Vec2<int>> data, char display)
|
public static void DrawPoints(List<Vec2<int>> data, char display)
|
||||||
{
|
{
|
||||||
var (min, max) = GetBounds(data);
|
var (min, max) = GetBounds(data);
|
||||||
|
|
||||||
var output = new StringBuilder();
|
var output = new StringBuilder();
|
||||||
for (int y = min.Y; y <= max.Y; y++)
|
for (int y = min.Y; y <= max.Y; y++)
|
||||||
{
|
{
|
||||||
for (int x = min.X; x <= max.X; x++)
|
for (int x = min.X; x <= max.X; x++)
|
||||||
{
|
{
|
||||||
var p = new Vec2<int>(x,y);
|
var p = new Vec2<int>(x,y);
|
||||||
if (data.Contains(p))
|
if (data.Contains(p))
|
||||||
output.Append(display);
|
output.Append(display);
|
||||||
else
|
else
|
||||||
output.Append(' ');
|
output.Append(' ');
|
||||||
|
|
||||||
}
|
}
|
||||||
output.AppendLine();
|
output.AppendLine();
|
||||||
}
|
}
|
||||||
Console.WriteLine(output);
|
Console.WriteLine(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (Vec2<int> min, Vec2<int> max) GetBounds(List<Vec2<int>> points)
|
public static (Vec2<int> min, Vec2<int> max) GetBounds(List<Vec2<int>> points)
|
||||||
{
|
{
|
||||||
var min = Vec2<int>.Splat(int.MaxValue);
|
var min = Vec2<int>.Splat(int.MaxValue);
|
||||||
var max = Vec2<int>.Splat(int.MinValue);
|
var max = Vec2<int>.Splat(int.MinValue);
|
||||||
foreach (var pos in points)
|
foreach (var pos in points)
|
||||||
{
|
{
|
||||||
if (pos.X < min.X)
|
if (pos.X < min.X)
|
||||||
min.X = pos.X;
|
min.X = pos.X;
|
||||||
if (pos.Y < min.Y)
|
if (pos.Y < min.Y)
|
||||||
min.Y = pos.Y;
|
min.Y = pos.Y;
|
||||||
|
|
||||||
if (pos.X > max.X)
|
if (pos.X > max.X)
|
||||||
max.X = pos.X;
|
max.X = pos.X;
|
||||||
if (pos.Y > max.Y)
|
if (pos.Y > max.Y)
|
||||||
max.Y = pos.Y;
|
max.Y = pos.Y;
|
||||||
}
|
}
|
||||||
return (min, max);
|
return (min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsInclosed(List<Vec2<int>> side, List<List<Vec2<int>>> sides, List<Vec2<int>> area)
|
public static bool IsInclosed(List<Vec2<int>> side, List<List<Vec2<int>>> sides, List<Vec2<int>> area)
|
||||||
{
|
{
|
||||||
var otherSides = sides.Where(g => g != side).SelectMany(s => s).ToFrozenSet();
|
var otherSides = sides.Where(g => g != side).SelectMany(s => s).ToFrozenSet();
|
||||||
foreach (var point in side)
|
foreach (var point in side)
|
||||||
{
|
{
|
||||||
foreach (var dir in DIRS)
|
foreach (var dir in DIRS)
|
||||||
{
|
{
|
||||||
var n = point + dir;
|
var n = point + dir;
|
||||||
if (side.Contains(n))
|
if (side.Contains(n))
|
||||||
continue;
|
continue;
|
||||||
if (!area.Contains(n))
|
if (!area.Contains(n))
|
||||||
return false;
|
return false;
|
||||||
if (otherSides.Contains(n))
|
if (otherSides.Contains(n))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int CountSides(List<List<Vec2<int>>> groups, List<Vec2<int>> area)
|
public static int CountSides(List<List<Vec2<int>>> groups, List<Vec2<int>> area)
|
||||||
{
|
{
|
||||||
int Sides(Vec2<int> point, List<Vec2<int>> group)
|
int Sides(Vec2<int> point, List<Vec2<int>> group)
|
||||||
{
|
{
|
||||||
var s = 0;
|
var s = 0;
|
||||||
foreach (var dir in DIRS)
|
foreach (var dir in DIRS)
|
||||||
{
|
{
|
||||||
var n = point + dir;
|
var n = point + dir;
|
||||||
if(area.Contains(n))
|
if(area.Contains(n))
|
||||||
s++;
|
s++;
|
||||||
if (group.Count > 1 && groups.Any(g => group != g && g.Contains(n)))
|
if (group.Count > 1 && groups.Any(g => group != g && g.Contains(n)))
|
||||||
s--;
|
s--;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return groups.Sum(s => s.Select(p => Sides(p, s)).Max() + (s.Count > 1 && IsInclosed(s, groups, area) ? 1 : 0));
|
return groups.Sum(s => s.Select(p => Sides(p, s)).Max() + (s.Count > 1 && IsInclosed(s, groups, area) ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<(char plant, List<Vec2<int>> area, int perimeter, List<Vec2<int>> outline)> FindPlots(char[][] data)
|
private static List<(char plant, List<Vec2<int>> area, int perimeter, List<Vec2<int>> outline)> FindPlots(char[][] data)
|
||||||
{
|
{
|
||||||
var visited = new HashSet<Vec2<int>>(data.Length * data[0].Length);
|
var visited = new HashSet<Vec2<int>>(data.Length * data[0].Length);
|
||||||
|
|
||||||
var results = new List<(char plant, List<Vec2<int>>, int perimeter, List<Vec2<int>> outline)>();
|
var results = new List<(char plant, List<Vec2<int>>, int perimeter, List<Vec2<int>> outline)>();
|
||||||
|
|
||||||
for (int y = 0; y < data.Length; y++)
|
for (int y = 0; y < data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = data[y];
|
var row = data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
var p = new Vec2<int>(x, y);
|
var p = new Vec2<int>(x, y);
|
||||||
if (visited.Contains(p))
|
if (visited.Contains(p))
|
||||||
continue;
|
continue;
|
||||||
var members = new List<Vec2<int>>();
|
var members = new List<Vec2<int>>();
|
||||||
var plant = data[y][x];
|
var plant = data[y][x];
|
||||||
var perimeter = 0;
|
var perimeter = 0;
|
||||||
var outline = new List<Vec2<int>>();
|
var outline = new List<Vec2<int>>();
|
||||||
GetMembers(data, plant, p, visited, members, ref perimeter, outline);
|
GetMembers(data, plant, p, visited, members, ref perimeter, outline);
|
||||||
results.Add((plant, members, perimeter, outline));
|
results.Add((plant, members, perimeter, outline));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetMembers(char[][] data, char plant, Vec2<int> point, HashSet<Vec2<int>> visited, List<Vec2<int>> members, ref int perimeter, List<Vec2<int>> outline)
|
private static void GetMembers(char[][] data, char plant, Vec2<int> point, HashSet<Vec2<int>> visited, List<Vec2<int>> members, ref int perimeter, List<Vec2<int>> outline)
|
||||||
{
|
{
|
||||||
if (visited.Contains(point))
|
if (visited.Contains(point))
|
||||||
return;
|
return;
|
||||||
visited.Add(point);
|
visited.Add(point);
|
||||||
members.Add(point);
|
members.Add(point);
|
||||||
|
|
||||||
foreach (var dir in DIRS)
|
foreach (var dir in DIRS)
|
||||||
{
|
{
|
||||||
var n = dir + point;
|
var n = dir + point;
|
||||||
if (!IsInBounds(n, data))
|
if (!IsInBounds(n, data))
|
||||||
{
|
{
|
||||||
perimeter += 1;
|
perimeter += 1;
|
||||||
outline.Add(n);
|
outline.Add(n);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (data[n.Y][n.X] != plant)
|
if (data[n.Y][n.X] != plant)
|
||||||
{
|
{
|
||||||
perimeter += 1;
|
perimeter += 1;
|
||||||
outline.Add(n);
|
outline.Add(n);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
GetMembers(data, plant, n, visited, members, ref perimeter, outline);
|
GetMembers(data, plant, n, visited, members, ref perimeter, outline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsInBounds(Vec2<int> pos, char[][] data)
|
public static bool IsInBounds(Vec2<int> pos, char[][] data)
|
||||||
{
|
{
|
||||||
if (pos.X < 0 || pos.Y < 0)
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
return false;
|
return false;
|
||||||
if (pos.X >= data.Length || pos.Y >= data[0].Length)
|
if (pos.X >= data.Length || pos.Y >= data[0].Length)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("sample3.txt").Select(ln => ln.ToCharArray()).ToArray();
|
_data = ReadInputLines("sample3.txt").Select(ln => ln.ToCharArray()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,107 +1,107 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day2;
|
namespace AdventOfCode.Problems.AOC2024.Day2;
|
||||||
[ProblemInfo(2024, 2, "Red-Nosed Reports")]
|
[ProblemInfo(2024, 2, "Red-Nosed Reports")]
|
||||||
internal class RedNosedReports : Problem<int, int>
|
internal class RedNosedReports : Problem<int, int>
|
||||||
{
|
{
|
||||||
private int[][] _data = [];
|
private int[][] _data = [];
|
||||||
|
|
||||||
private static bool CheckIncrease(int l) => l >= 1 && l <= 3;
|
private static bool CheckIncrease(int l) => l >= 1 && l <= 3;
|
||||||
private static bool CheckDecrease(int l) => l <= -1 && l >= -3;
|
private static bool CheckDecrease(int l) => l <= -1 && l >= -3;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var reportAnalysis = Analyze();
|
var reportAnalysis = Analyze();
|
||||||
var increasing = reportAnalysis.Count(r => r.All(CheckIncrease));
|
var increasing = reportAnalysis.Count(r => r.All(CheckIncrease));
|
||||||
var decreasing = reportAnalysis.Count(r => r.All(CheckDecrease));
|
var decreasing = reportAnalysis.Count(r => r.All(CheckDecrease));
|
||||||
Part1 = increasing + decreasing;
|
Part1 = increasing + decreasing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
foreach (var report in _data)
|
foreach (var report in _data)
|
||||||
{
|
{
|
||||||
if (CheckSafety(report, out _))
|
if (CheckSafety(report, out _))
|
||||||
Part2++;
|
Part2++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CheckSafety(int[] report, out bool increase)
|
private static bool CheckSafety(int[] report, out bool increase)
|
||||||
{
|
{
|
||||||
increase = false;
|
increase = false;
|
||||||
var inFail = Check(report, CheckIncrease);
|
var inFail = Check(report, CheckIncrease);
|
||||||
var deFail = Check(report, CheckDecrease);
|
var deFail = Check(report, CheckDecrease);
|
||||||
|
|
||||||
if(inFail.Count == 0)
|
if(inFail.Count == 0)
|
||||||
{
|
{
|
||||||
increase = true;
|
increase = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inFail.Count < report.Length && RemoveFails(report, inFail).Any(g => Check(g, CheckIncrease).Count == 0))
|
if (inFail.Count < report.Length && RemoveFails(report, inFail).Any(g => Check(g, CheckIncrease).Count == 0))
|
||||||
{
|
{
|
||||||
increase = true;
|
increase = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(deFail.Count == 0)
|
if(deFail.Count == 0)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (deFail.Count < report.Length && RemoveFails(report, deFail).Any(g => Check(g, CheckDecrease).Count == 0))
|
if (deFail.Count < report.Length && RemoveFails(report, deFail).Any(g => Check(g, CheckDecrease).Count == 0))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int[][] RemoveFails(int[] report, List<int> fails)
|
static int[][] RemoveFails(int[] report, List<int> fails)
|
||||||
{
|
{
|
||||||
var results = new int[fails.Count][];
|
var results = new int[fails.Count][];
|
||||||
for (int i = 0; i < fails.Count; i++)
|
for (int i = 0; i < fails.Count; i++)
|
||||||
{
|
{
|
||||||
var f = fails[i];
|
var f = fails[i];
|
||||||
results[i] = f == 0 ? report[1..] : f == report.Length-1 ? report[..^1] : [.. report[..f], .. report[(f+1)..]];
|
results[i] = f == 0 ? report[1..] : f == report.Length-1 ? report[..^1] : [.. report[..f], .. report[(f+1)..]];
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<int> Check(int[] report, Func<int, bool> check)
|
static List<int> Check(int[] report, Func<int, bool> check)
|
||||||
{
|
{
|
||||||
var fails = new List<int>();
|
var fails = new List<int>();
|
||||||
for (int i = 1; i < report.Length; i++)
|
for (int i = 1; i < report.Length; i++)
|
||||||
{
|
{
|
||||||
var d = report[i] - report[i-1];
|
var d = report[i] - report[i-1];
|
||||||
if (!check(d))
|
if (!check(d))
|
||||||
fails.AddRange([i, i-1]);
|
fails.AddRange([i, i-1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fails.Distinct().ToList();
|
return fails.Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[][] Analyze()
|
private int[][] Analyze()
|
||||||
{
|
{
|
||||||
var reportAnalysis = new int[_data.Length][];
|
var reportAnalysis = new int[_data.Length][];
|
||||||
for (int ridx = 0; ridx < _data.Length; ridx++)
|
for (int ridx = 0; ridx < _data.Length; ridx++)
|
||||||
{
|
{
|
||||||
int[]? report = _data[ridx];
|
int[]? report = _data[ridx];
|
||||||
var safety = new int[report.Length - 1];
|
var safety = new int[report.Length - 1];
|
||||||
for (int i = 1; i < report.Length; i++)
|
for (int i = 1; i < report.Length; i++)
|
||||||
safety[i - 1] = report[i] - report[i - 1];
|
safety[i - 1] = report[i] - report[i - 1];
|
||||||
reportAnalysis[ridx] = safety;
|
reportAnalysis[ridx] = safety;
|
||||||
}
|
}
|
||||||
return reportAnalysis;
|
return reportAnalysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("input.txt").Select(l => l.Split(' ').Select(int.Parse).ToArray()).ToArray();
|
_data = ReadInputLines("input.txt").Select(l => l.Split(' ').Select(int.Parse).ToArray()).ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,54 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day3;
|
namespace AdventOfCode.Problems.AOC2024.Day3;
|
||||||
[ProblemInfo(2024, 3, "Mull It Over")]
|
[ProblemInfo(2024, 3, "Mull It Over")]
|
||||||
internal partial class MullItOver : Problem<int, int>
|
internal partial class MullItOver : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string _data = string.Empty;
|
private string _data = string.Empty;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var matches = Mul().Matches(_data);
|
var matches = Mul().Matches(_data);
|
||||||
Part1 = matches.Select(m => (int.Parse(m.Groups["a"].ValueSpan), int.Parse(m.Groups["b"].ValueSpan))).Select(v => v.Item1 * v.Item2).Sum();
|
Part1 = matches.Select(m => (int.Parse(m.Groups["a"].ValueSpan), int.Parse(m.Groups["b"].ValueSpan))).Select(v => v.Item1 * v.Item2).Sum();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var doing = true;
|
var doing = true;
|
||||||
var muls = DosAndDonts().Matches(_data);
|
var muls = DosAndDonts().Matches(_data);
|
||||||
foreach (Match match in muls)
|
foreach (Match match in muls)
|
||||||
{
|
{
|
||||||
switch (match.ValueSpan)
|
switch (match.ValueSpan)
|
||||||
{
|
{
|
||||||
case ['d', 'o', 'n', ..]:
|
case ['d', 'o', 'n', ..]:
|
||||||
doing = false;
|
doing = false;
|
||||||
break;
|
break;
|
||||||
case ['d', 'o', ..]:
|
case ['d', 'o', ..]:
|
||||||
doing = true;
|
doing = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!doing)
|
if (!doing)
|
||||||
continue;
|
continue;
|
||||||
Part2 += int.Parse(match.Groups["a"].ValueSpan) * int.Parse(match.Groups["b"].ValueSpan);
|
Part2 += int.Parse(match.Groups["a"].ValueSpan) * int.Parse(match.Groups["b"].ValueSpan);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputText("input.txt");
|
_data = ReadInputText("input.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex("(mul\\((?<a>\\d+)\\,(?<b>\\d+)\\))|(do\\(\\))|(don't\\(\\))")]
|
[GeneratedRegex("(mul\\((?<a>\\d+)\\,(?<b>\\d+)\\))|(do\\(\\))|(don't\\(\\))")]
|
||||||
private static partial Regex DosAndDonts();
|
private static partial Regex DosAndDonts();
|
||||||
[GeneratedRegex("mul\\((?<a>\\d+)\\,(?<b>\\d+)\\)")]
|
[GeneratedRegex("mul\\((?<a>\\d+)\\,(?<b>\\d+)\\)")]
|
||||||
private static partial Regex Mul();
|
private static partial Regex Mul();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,127 +1,127 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Pos = (int x, int y);
|
using Pos = (int x, int y);
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day4;
|
namespace AdventOfCode.Problems.AOC2024.Day4;
|
||||||
[ProblemInfo(2024, 4, "Ceres Search")]
|
[ProblemInfo(2024, 4, "Ceres Search")]
|
||||||
internal class CeresSearch : Problem<int, int>
|
internal class CeresSearch : Problem<int, int>
|
||||||
{
|
{
|
||||||
|
|
||||||
private string[] _data = [];
|
private string[] _data = [];
|
||||||
private static readonly Pos[] dirs = [
|
private static readonly Pos[] dirs = [
|
||||||
(-1, 0), //Left
|
(-1, 0), //Left
|
||||||
(-1, -1), //Top Left
|
(-1, -1), //Top Left
|
||||||
(0, -1), //Top
|
(0, -1), //Top
|
||||||
(1, -1), //Top Right
|
(1, -1), //Top Right
|
||||||
(1, 0), //Right
|
(1, 0), //Right
|
||||||
(1, 1), //Bottom Right
|
(1, 1), //Bottom Right
|
||||||
(0, 1), //Bottom
|
(0, 1), //Bottom
|
||||||
(-1, 1), //Bottom Left
|
(-1, 1), //Bottom Left
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly Pos[] xdirs = [
|
private static readonly Pos[] xdirs = [
|
||||||
(-1, -1), //Top Left
|
(-1, -1), //Top Left
|
||||||
(1, -1), //Top Right
|
(1, -1), //Top Right
|
||||||
(1, 1), //Bottom Right
|
(1, 1), //Bottom Right
|
||||||
(-1, 1), //Bottom Left
|
(-1, 1), //Bottom Left
|
||||||
];
|
];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
Part1 = FindWord(_data, "XMAS");
|
Part1 = FindWord(_data, "XMAS");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
Part2 = FindXWord(_data, "MAS");
|
Part2 = FindXWord(_data, "MAS");
|
||||||
}
|
}
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("input.txt");
|
_data = ReadInputLines("input.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FindXWord(string[] data, string target)
|
private static int FindXWord(string[] data, string target)
|
||||||
{
|
{
|
||||||
var matches = 0;
|
var matches = 0;
|
||||||
var pivot = target.Length / 2;
|
var pivot = target.Length / 2;
|
||||||
var tgt = target[pivot];
|
var tgt = target[pivot];
|
||||||
var branchA = string.Join("", target[..(pivot+1)].Reverse());
|
var branchA = string.Join("", target[..(pivot+1)].Reverse());
|
||||||
var branchB = target[pivot..];
|
var branchB = target[pivot..];
|
||||||
for (int y = 1; y < data.Length-1; y++)
|
for (int y = 1; y < data.Length-1; y++)
|
||||||
{
|
{
|
||||||
var row = data[y];
|
var row = data[y];
|
||||||
for (int x = 1; x < row.Length-1; x++)
|
for (int x = 1; x < row.Length-1; x++)
|
||||||
{
|
{
|
||||||
var c = row[x];
|
var c = row[x];
|
||||||
if (c == tgt)
|
if (c == tgt)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < xdirs.Length; i++)
|
for (int i = 0; i < xdirs.Length; i++)
|
||||||
{
|
{
|
||||||
Pos dir = xdirs[i];
|
Pos dir = xdirs[i];
|
||||||
Pos opposingDir = xdirs[(i + 2) % xdirs.Length];
|
Pos opposingDir = xdirs[(i + 2) % xdirs.Length];
|
||||||
|
|
||||||
if (CheckWord(data, (x, y), dir, branchA, 1) && CheckWord(data, (x,y), opposingDir, branchB, 1))
|
if (CheckWord(data, (x, y), dir, branchA, 1) && CheckWord(data, (x,y), opposingDir, branchB, 1))
|
||||||
{
|
{
|
||||||
Pos dir2 = xdirs[(i+1) % xdirs.Length];
|
Pos dir2 = xdirs[(i+1) % xdirs.Length];
|
||||||
Pos opposingDir2 = xdirs[(i + 3) % xdirs.Length];
|
Pos opposingDir2 = xdirs[(i + 3) % xdirs.Length];
|
||||||
if (CheckWord(data, (x, y), dir2, branchA, 1) && CheckWord(data, (x, y), opposingDir2, branchB, 1))
|
if (CheckWord(data, (x, y), dir2, branchA, 1) && CheckWord(data, (x, y), opposingDir2, branchB, 1))
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FindWord(string[] data, string target)
|
private static int FindWord(string[] data, string target)
|
||||||
{
|
{
|
||||||
var matches = 0;
|
var matches = 0;
|
||||||
var tgt = target[0];
|
var tgt = target[0];
|
||||||
for (int y = 0; y < data.Length; y++)
|
for (int y = 0; y < data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = data[y];
|
var row = data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
var c = row[x];
|
var c = row[x];
|
||||||
if(c == tgt)
|
if(c == tgt)
|
||||||
{
|
{
|
||||||
foreach (var dir in dirs)
|
foreach (var dir in dirs)
|
||||||
{
|
{
|
||||||
if(CheckWord(data, (x, y), dir, target, 1))
|
if(CheckWord(data, (x, y), dir, target, 1))
|
||||||
matches++;
|
matches++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CheckWord(string[] data, Pos pos, Pos dir, string target, int targetPos)
|
private static bool CheckWord(string[] data, Pos pos, Pos dir, string target, int targetPos)
|
||||||
{
|
{
|
||||||
Pos curPos = (pos.x + dir.x, pos.y + dir.y);
|
Pos curPos = (pos.x + dir.x, pos.y + dir.y);
|
||||||
|
|
||||||
|
|
||||||
if(curPos.y < 0 || curPos.y >= data.Length)
|
if(curPos.y < 0 || curPos.y >= data.Length)
|
||||||
return false;
|
return false;
|
||||||
if (curPos.x < 0 || curPos.x >= data[0].Length)
|
if (curPos.x < 0 || curPos.x >= data[0].Length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var c = data[curPos.y][curPos.x];
|
var c = data[curPos.y][curPos.x];
|
||||||
if(c == target[targetPos])
|
if(c == target[targetPos])
|
||||||
{
|
{
|
||||||
if (targetPos == target.Length - 1)
|
if (targetPos == target.Length - 1)
|
||||||
return true;
|
return true;
|
||||||
return CheckWord(data, curPos, dir, target, targetPos + 1);
|
return CheckWord(data, curPos, dir, target, targetPos + 1);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,96 +1,96 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Rule = (int after, int before);
|
using Rule = (int after, int before);
|
||||||
|
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day5;
|
namespace AdventOfCode.Problems.AOC2024.Day5;
|
||||||
internal class PageList
|
internal class PageList
|
||||||
{
|
{
|
||||||
private readonly List<Rule> _rules;
|
private readonly List<Rule> _rules;
|
||||||
private PageNode _root;
|
private PageNode _root;
|
||||||
|
|
||||||
public PageList(int[] pages, List<Rule> rules)
|
public PageList(int[] pages, List<Rule> rules)
|
||||||
{
|
{
|
||||||
_rules = rules.Where(r => pages.Contains(r.before)).ToList();
|
_rules = rules.Where(r => pages.Contains(r.before)).ToList();
|
||||||
_root = new PageNode(pages[0], GetRulesForPage(pages[0]));
|
_root = new PageNode(pages[0], GetRulesForPage(pages[0]));
|
||||||
for (int i = 1; i < pages.Length; i++)
|
for (int i = 1; i < pages.Length; i++)
|
||||||
AddPage(pages[i]);
|
AddPage(pages[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddPage(int page)
|
public void AddPage(int page)
|
||||||
{
|
{
|
||||||
var node = new PageNode(page, GetRulesForPage(page));
|
var node = new PageNode(page, GetRulesForPage(page));
|
||||||
if(node.IsBefore(_root))
|
if(node.IsBefore(_root))
|
||||||
{
|
{
|
||||||
node.NextNode = _root;
|
node.NextNode = _root;
|
||||||
_root = node;
|
_root = node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var curNode = _root;
|
var curNode = _root;
|
||||||
while(curNode != null)
|
while(curNode != null)
|
||||||
{
|
{
|
||||||
if(curNode.IsBefore(node))
|
if(curNode.IsBefore(node))
|
||||||
{
|
{
|
||||||
if(curNode.NextNode == null)
|
if(curNode.NextNode == null)
|
||||||
{
|
{
|
||||||
curNode.NextNode = node;
|
curNode.NextNode = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(node.IsBefore(curNode.NextNode))
|
else if(node.IsBefore(curNode.NextNode))
|
||||||
{
|
{
|
||||||
node.NextNode = curNode.NextNode;
|
node.NextNode = curNode.NextNode;
|
||||||
curNode.NextNode = node;
|
curNode.NextNode = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
curNode = curNode.NextNode;
|
curNode = curNode.NextNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Rule> GetRulesForPage(int page)
|
public List<Rule> GetRulesForPage(int page)
|
||||||
{
|
{
|
||||||
return _rules.Where(r => r.after == page).ToList();
|
return _rules.Where(r => r.after == page).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<int> Traverse()
|
public List<int> Traverse()
|
||||||
{
|
{
|
||||||
var list = new List<int>();
|
var list = new List<int>();
|
||||||
var curNode = _root;
|
var curNode = _root;
|
||||||
while(curNode != null)
|
while(curNode != null)
|
||||||
{
|
{
|
||||||
list.Add(curNode.Page);
|
list.Add(curNode.Page);
|
||||||
curNode = curNode.NextNode;
|
curNode = curNode.NextNode;
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class PageNode
|
internal class PageNode
|
||||||
{
|
{
|
||||||
public int Page { get; set; }
|
public int Page { get; set; }
|
||||||
public int[] Before { get; set; }
|
public int[] Before { get; set; }
|
||||||
public PageNode? NextNode { get; set; }
|
public PageNode? NextNode { get; set; }
|
||||||
|
|
||||||
public PageNode(int page, List<Rule> rules)
|
public PageNode(int page, List<Rule> rules)
|
||||||
{
|
{
|
||||||
Page = page;
|
Page = page;
|
||||||
Before = rules.Count == 0 ? [int.MinValue] : rules.Select(r => r.before).ToArray();
|
Before = rules.Count == 0 ? [int.MinValue] : rules.Select(r => r.before).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Page} << {Before}";
|
return $"{Page} << {Before}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBefore(PageNode other)
|
public bool IsBefore(PageNode other)
|
||||||
{
|
{
|
||||||
if(Before.Any(b => b == other.Page))
|
if(Before.Any(b => b == other.Page))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,77 +1,77 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Rule = (int after, int before);
|
using Rule = (int after, int before);
|
||||||
|
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day5;
|
namespace AdventOfCode.Problems.AOC2024.Day5;
|
||||||
[ProblemInfo(2024, 5, "Print Queue")]
|
[ProblemInfo(2024, 5, "Print Queue")]
|
||||||
internal class PrintQueue : Problem<int, int>
|
internal class PrintQueue : Problem<int, int>
|
||||||
{
|
{
|
||||||
private List<Rule> _rules = [];
|
private List<Rule> _rules = [];
|
||||||
private List<int[]> updates = [];
|
private List<int[]> updates = [];
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
foreach (var update in updates)
|
foreach (var update in updates)
|
||||||
{
|
{
|
||||||
if (IsOrdered(update, out _))
|
if (IsOrdered(update, out _))
|
||||||
{
|
{
|
||||||
var mid = update[update.Length / 2];
|
var mid = update[update.Length / 2];
|
||||||
Part1 += mid;
|
Part1 += mid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsOrdered(int[] update, out List<int> orderd)
|
public bool IsOrdered(int[] update, out List<int> orderd)
|
||||||
{
|
{
|
||||||
var list = new PageList(update, _rules);
|
var list = new PageList(update, _rules);
|
||||||
orderd = list.Traverse();
|
orderd = list.Traverse();
|
||||||
return orderd.Zip(update).All(e => e.First== e.Second);
|
return orderd.Zip(update).All(e => e.First== e.Second);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int[] SortUpdates(int[] updates)
|
public int[] SortUpdates(int[] updates)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
foreach (var update in updates)
|
foreach (var update in updates)
|
||||||
{
|
{
|
||||||
if (!IsOrdered(update, out var ordered))
|
if (!IsOrdered(update, out var ordered))
|
||||||
{
|
{
|
||||||
var mid = ordered[update.Length / 2];
|
var mid = ordered[update.Length / 2];
|
||||||
Part2 += mid;
|
Part2 += mid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
|
|
||||||
var parsingPages = false;
|
var parsingPages = false;
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(line))
|
if (string.IsNullOrWhiteSpace(line))
|
||||||
{
|
{
|
||||||
parsingPages = true;
|
parsingPages = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (parsingPages)
|
if (parsingPages)
|
||||||
{
|
{
|
||||||
updates.Add(line.Split(',').Select(int.Parse).ToArray());
|
updates.Add(line.Split(',').Select(int.Parse).ToArray());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
var d = line.Split('|').Select(int.Parse);
|
var d = line.Split('|').Select(int.Parse);
|
||||||
_rules.Add((d.First(), d.Last()));
|
_rules.Add((d.First(), d.Last()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,392 +1,392 @@
|
|||||||
using AdventOfCode.Utils.Models;
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Turn = (AdventOfCode.Utils.Models.Vec2<int> pos, int dir, int step);
|
using Turn = (AdventOfCode.Utils.Models.Vec2<int> pos, int dir, int step);
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day6;
|
namespace AdventOfCode.Problems.AOC2024.Day6;
|
||||||
|
|
||||||
[ProblemInfo(2024, 6, "Guard Gallivant")]
|
[ProblemInfo(2024, 6, "Guard Gallivant")]
|
||||||
internal class GuardGallivant : Problem<int, int>
|
internal class GuardGallivant : Problem<int, int>
|
||||||
{
|
{
|
||||||
private char[][] _data = [];
|
private char[][] _data = [];
|
||||||
private int _height;
|
private int _height;
|
||||||
private int _width;
|
private int _width;
|
||||||
public static readonly Vec2<int>[] DIRS = [
|
public static readonly Vec2<int>[] DIRS = [
|
||||||
new (0, -1),
|
new (0, -1),
|
||||||
new (1, 0),
|
new (1, 0),
|
||||||
new (0, 1),
|
new (0, 1),
|
||||||
new (-1, 0),
|
new (-1, 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var map = new GuardMap(_data, GetStartPos());
|
var map = new GuardMap(_data, GetStartPos());
|
||||||
Part1 = map.GetPath().DistinctBy(p => p.pos).Count();
|
Part1 = map.GetPath().DistinctBy(p => p.pos).Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
//this does not work
|
//this does not work
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var start = GetStartPos();
|
var start = GetStartPos();
|
||||||
var map = new GuardMap(_data, start);
|
var map = new GuardMap(_data, start);
|
||||||
var path = map.GetPath();
|
var path = map.GetPath();
|
||||||
var visited = path.Select(p => p.pos).ToFrozenSet();
|
var visited = path.Select(p => p.pos).ToFrozenSet();
|
||||||
var nodes = new List<GuardNode>();
|
var nodes = new List<GuardNode>();
|
||||||
var found = new HashSet<Vec2<int>>();
|
var found = new HashSet<Vec2<int>>();
|
||||||
foreach (var (pos, node) in path)
|
foreach (var (pos, node) in path)
|
||||||
{
|
{
|
||||||
var turn = (node.Direction + 1) % 4;
|
var turn = (node.Direction + 1) % 4;
|
||||||
if (pos == start)
|
if (pos == start)
|
||||||
continue;
|
continue;
|
||||||
if (map.GetNextObstacle(pos, turn, out var next))
|
if (map.GetNextObstacle(pos, turn, out var next))
|
||||||
{
|
{
|
||||||
var obstacleNode = new GuardNode(pos, turn, 0);
|
var obstacleNode = new GuardNode(pos, turn, 0);
|
||||||
var obstaclePos = pos + DIRS[node.Direction];
|
var obstaclePos = pos + DIRS[node.Direction];
|
||||||
if (!IsInBounds(obstaclePos))
|
if (!IsInBounds(obstaclePos))
|
||||||
continue;
|
continue;
|
||||||
if (map.SolveNewPath(obstacleNode, pos + DIRS[node.Direction], nodes))
|
if (map.SolveNewPath(obstacleNode, pos + DIRS[node.Direction], nodes))
|
||||||
{
|
{
|
||||||
if (!found.Contains(obstaclePos))
|
if (!found.Contains(obstaclePos))
|
||||||
{
|
{
|
||||||
Part2++;
|
Part2++;
|
||||||
//map.PrintBoard(nodes, pos, obstaclePos);
|
//map.PrintBoard(nodes, pos, obstaclePos);
|
||||||
//Console.ReadLine();
|
//Console.ReadLine();
|
||||||
}
|
}
|
||||||
found.Add(obstaclePos);
|
found.Add(obstaclePos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec2<int> GetStartPos()
|
private Vec2<int> GetStartPos()
|
||||||
{
|
{
|
||||||
for (int y = 0; y < _data.Length; y++)
|
for (int y = 0; y < _data.Length; y++)
|
||||||
{
|
{
|
||||||
var row = _data[y];
|
var row = _data[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
if (row[x] == '^')
|
if (row[x] == '^')
|
||||||
return new(x, y);
|
return new(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Exception("Start Position not found");
|
throw new Exception("Start Position not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInBounds(Vec2<int> pos)
|
private bool IsInBounds(Vec2<int> pos)
|
||||||
{
|
{
|
||||||
if (pos.X < 0 || pos.Y < 0)
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
return false;
|
return false;
|
||||||
if (pos.X >= _width || pos.Y >= _height)
|
if (pos.X >= _width || pos.Y >= _height)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_data = ReadInputLines("input.txt").Select(r => r.ToCharArray()).ToArray();
|
_data = ReadInputLines("input.txt").Select(r => r.ToCharArray()).ToArray();
|
||||||
_height = _data.Length;
|
_height = _data.Length;
|
||||||
_width = _data[0].Length;
|
_width = _data[0].Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file class GuardMap
|
file class GuardMap
|
||||||
{
|
{
|
||||||
public List<GuardNode> Nodes { get; set; }
|
public List<GuardNode> Nodes { get; set; }
|
||||||
private readonly bool[][] _map;
|
private readonly bool[][] _map;
|
||||||
|
|
||||||
private readonly int _height;
|
private readonly int _height;
|
||||||
private readonly int _width;
|
private readonly int _width;
|
||||||
|
|
||||||
public GuardMap(char[][] map, Vec2<int> start)
|
public GuardMap(char[][] map, Vec2<int> start)
|
||||||
{
|
{
|
||||||
_map = map.Select(r => r.Select(c => c == '#' ? true : false).ToArray()).ToArray();
|
_map = map.Select(r => r.Select(c => c == '#' ? true : false).ToArray()).ToArray();
|
||||||
_height = map.Length;
|
_height = map.Length;
|
||||||
_width = map[0].Length;
|
_width = map[0].Length;
|
||||||
var startNode = new GuardNode(start, 0, 0);
|
var startNode = new GuardNode(start, 0, 0);
|
||||||
Nodes = [startNode];
|
Nodes = [startNode];
|
||||||
Solve();
|
Solve();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(Vec2<int> pos, GuardNode node)> GetPath()
|
public List<(Vec2<int> pos, GuardNode node)> GetPath()
|
||||||
{
|
{
|
||||||
return GetPath(Nodes);
|
return GetPath(Nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FrozenSet<Vec2<int>> GetPathSet(List<GuardNode> nodes)
|
public FrozenSet<Vec2<int>> GetPathSet(List<GuardNode> nodes)
|
||||||
{
|
{
|
||||||
var path = GetPath(nodes);
|
var path = GetPath(nodes);
|
||||||
return path.Select(p => p.pos).ToFrozenSet();
|
return path.Select(p => p.pos).ToFrozenSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<(Vec2<int> pos, GuardNode node)> GetPath(List<GuardNode> nodes)
|
public List<(Vec2<int> pos, GuardNode node)> GetPath(List<GuardNode> nodes)
|
||||||
{
|
{
|
||||||
var path = new List<(Vec2<int>, GuardNode)>();
|
var path = new List<(Vec2<int>, GuardNode)>();
|
||||||
|
|
||||||
var curNode = nodes[0];
|
var curNode = nodes[0];
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (curNode.Next is int nextId && nextId >= 0)
|
if (curNode.Next is int nextId && nextId >= 0)
|
||||||
{
|
{
|
||||||
var next = nodes[nextId];
|
var next = nodes[nextId];
|
||||||
path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode)));
|
path.AddRange(GetPointsBetween(curNode.Pos, next.Pos, curNode.Direction).Select(p => (p, curNode)));
|
||||||
curNode = next;
|
curNode = next;
|
||||||
}
|
}
|
||||||
else if (curNode.Next == -1)
|
else if (curNode.Next == -1)
|
||||||
{
|
{
|
||||||
var end = curNode.Direction switch
|
var end = curNode.Direction switch
|
||||||
{
|
{
|
||||||
0 => new Vec2<int>(curNode.Pos.X, -1),
|
0 => new Vec2<int>(curNode.Pos.X, -1),
|
||||||
1 => new Vec2<int>(_width, curNode.Pos.Y),
|
1 => new Vec2<int>(_width, curNode.Pos.Y),
|
||||||
2 => new Vec2<int>(curNode.Pos.X, _height),
|
2 => new Vec2<int>(curNode.Pos.X, _height),
|
||||||
3 => new Vec2<int>(-1, curNode.Pos.Y),
|
3 => new Vec2<int>(-1, curNode.Pos.Y),
|
||||||
_ => throw new InvalidOperationException()
|
_ => throw new InvalidOperationException()
|
||||||
};
|
};
|
||||||
path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode)));
|
path.AddRange(GetPointsBetween(curNode.Pos, end, curNode.Direction).Select(p => (p, curNode)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Vec2<int>> GetPointsBetween(Vec2<int> start, Vec2<int> end, int dir)
|
private List<Vec2<int>> GetPointsBetween(Vec2<int> start, Vec2<int> end, int dir)
|
||||||
{
|
{
|
||||||
var result = new List<Vec2<int>>();
|
var result = new List<Vec2<int>>();
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
for (int i = start.Y; i > end.Y; i--)
|
for (int i = start.Y; i > end.Y; i--)
|
||||||
result.Add(new Vec2<int>(start.X, i));
|
result.Add(new Vec2<int>(start.X, i));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
for (int i = start.X; i < end.X; i++)
|
for (int i = start.X; i < end.X; i++)
|
||||||
result.Add(new Vec2<int>(i, start.Y));
|
result.Add(new Vec2<int>(i, start.Y));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
for (int i = start.Y; i < end.Y; i++)
|
for (int i = start.Y; i < end.Y; i++)
|
||||||
result.Add(new Vec2<int>(start.X, i));
|
result.Add(new Vec2<int>(start.X, i));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
for (int i = start.X; i > end.X; i--)
|
for (int i = start.X; i > end.X; i--)
|
||||||
result.Add(new Vec2<int>(i, start.Y));
|
result.Add(new Vec2<int>(i, start.Y));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Solve()
|
private void Solve()
|
||||||
{
|
{
|
||||||
var curNode = Nodes[0];
|
var curNode = Nodes[0];
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next))
|
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next))
|
||||||
{
|
{
|
||||||
curNode.Next = -1;
|
curNode.Next = -1;
|
||||||
Nodes[curNode.Id] = curNode;
|
Nodes[curNode.Id] = curNode;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count);
|
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, Nodes.Count);
|
||||||
curNode.Next = newNode.Id;
|
curNode.Next = newNode.Id;
|
||||||
Nodes[curNode.Id] = curNode;
|
Nodes[curNode.Id] = curNode;
|
||||||
Nodes.Add(newNode);
|
Nodes.Add(newNode);
|
||||||
curNode = newNode;
|
curNode = newNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SolveNewPath(GuardNode start, Vec2<int> extraObsticle, List<GuardNode> nodes)
|
public bool SolveNewPath(GuardNode start, Vec2<int> extraObsticle, List<GuardNode> nodes)
|
||||||
{
|
{
|
||||||
var curNode = start;
|
var curNode = start;
|
||||||
nodes.Clear();
|
nodes.Clear();
|
||||||
nodes.Add(start);
|
nodes.Add(start);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next, extraObsticle))
|
if (!GetNextObstacle(curNode.Pos, curNode.Direction, out var next, extraObsticle))
|
||||||
return false;
|
return false;
|
||||||
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, nodes.Count);
|
var newNode = new GuardNode(next - GuardGallivant.DIRS[curNode.Direction], (curNode.Direction + 1) % 4, nodes.Count);
|
||||||
if (nodes.Any(n => n.Pos == newNode.Pos && n.Direction == newNode.Direction))
|
if (nodes.Any(n => n.Pos == newNode.Pos && n.Direction == newNode.Direction))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
curNode.Next = newNode.Id;
|
curNode.Next = newNode.Id;
|
||||||
nodes[curNode.Id] = curNode;
|
nodes[curNode.Id] = curNode;
|
||||||
curNode = newNode;
|
curNode = newNode;
|
||||||
nodes.Add(newNode);
|
nodes.Add(newNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetNextObstacle(Vec2<int> start, int dir, out Vec2<int> pos, Vec2<int>? extraObsticle = null)
|
public bool GetNextObstacle(Vec2<int> start, int dir, out Vec2<int> pos, Vec2<int>? extraObsticle = null)
|
||||||
{
|
{
|
||||||
if (extraObsticle is Vec2<int> ex)
|
if (extraObsticle is Vec2<int> ex)
|
||||||
_map[ex.Y][ex.X] = true;
|
_map[ex.Y][ex.X] = true;
|
||||||
pos = default;
|
pos = default;
|
||||||
|
|
||||||
var (sX, sY) = start;
|
var (sX, sY) = start;
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
for (int y = sY; y >= 0; y--)
|
for (int y = sY; y >= 0; y--)
|
||||||
{
|
{
|
||||||
if (_map[y][sX])
|
if (_map[y][sX])
|
||||||
{
|
{
|
||||||
pos = new(sX, y);
|
pos = new(sX, y);
|
||||||
ResetExtraObsticle();
|
ResetExtraObsticle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
var rowRight = _map[sY];
|
var rowRight = _map[sY];
|
||||||
for (int x = sX; x < _width; x++)
|
for (int x = sX; x < _width; x++)
|
||||||
{
|
{
|
||||||
if (rowRight[x])
|
if (rowRight[x])
|
||||||
{
|
{
|
||||||
pos = new(x, sY);
|
pos = new(x, sY);
|
||||||
ResetExtraObsticle();
|
ResetExtraObsticle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
for (int y = sY; y < _height; y++)
|
for (int y = sY; y < _height; y++)
|
||||||
{
|
{
|
||||||
if (_map[y][sX])
|
if (_map[y][sX])
|
||||||
{
|
{
|
||||||
pos = new(sX, y);
|
pos = new(sX, y);
|
||||||
ResetExtraObsticle();
|
ResetExtraObsticle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
var rowLeft = _map[sY];
|
var rowLeft = _map[sY];
|
||||||
for (int x = sX; x >= 0; x--)
|
for (int x = sX; x >= 0; x--)
|
||||||
{
|
{
|
||||||
if (rowLeft[x])
|
if (rowLeft[x])
|
||||||
{
|
{
|
||||||
pos = new(x, sY);
|
pos = new(x, sY);
|
||||||
ResetExtraObsticle();
|
ResetExtraObsticle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetExtraObsticle()
|
void ResetExtraObsticle()
|
||||||
{
|
{
|
||||||
if (extraObsticle is Vec2<int> ex)
|
if (extraObsticle is Vec2<int> ex)
|
||||||
_map[ex.Y][ex.X] = false;
|
_map[ex.Y][ex.X] = false;
|
||||||
}
|
}
|
||||||
ResetExtraObsticle();
|
ResetExtraObsticle();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintBoard(List<GuardNode> nodes, Vec2<int> start, Vec2<int>? extraObsticle = null)
|
public void PrintBoard(List<GuardNode> nodes, Vec2<int> start, Vec2<int>? extraObsticle = null)
|
||||||
{
|
{
|
||||||
var path = GetPathSet(nodes);
|
var path = GetPathSet(nodes);
|
||||||
for (int y = 0; y < _height; y++)
|
for (int y = 0; y < _height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < _width; x++)
|
for (int x = 0; x < _width; x++)
|
||||||
{
|
{
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
var p = new Vec2<int>(x, y);
|
var p = new Vec2<int>(x, y);
|
||||||
var node = nodes.FirstOrDefault(n => n.Pos == p, new GuardNode(p, 0, -1));
|
var node = nodes.FirstOrDefault(n => n.Pos == p, new GuardNode(p, 0, -1));
|
||||||
if (node.Id != -1)
|
if (node.Id != -1)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
if (node.Id == 0)
|
if (node.Id == 0)
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
else if (node.Id == nodes.Count - 1)
|
else if (node.Id == nodes.Count - 1)
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
switch (node.Direction)
|
switch (node.Direction)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
Console.Write('^');
|
Console.Write('^');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
Console.Write('>');
|
Console.Write('>');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
Console.Write('v');
|
Console.Write('v');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
Console.Write('<');
|
Console.Write('<');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (p == start)
|
if (p == start)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Magenta;
|
Console.ForegroundColor = ConsoleColor.Magenta;
|
||||||
Console.Write('S');
|
Console.Write('S');
|
||||||
}
|
}
|
||||||
if (_map[y][x])
|
if (_map[y][x])
|
||||||
Console.Write('#');
|
Console.Write('#');
|
||||||
else if (p == extraObsticle)
|
else if (p == extraObsticle)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.DarkBlue;
|
Console.ForegroundColor = ConsoleColor.DarkBlue;
|
||||||
Console.Write('$');
|
Console.Write('$');
|
||||||
}
|
}
|
||||||
else if (path.Contains(p))
|
else if (path.Contains(p))
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.DarkGray;
|
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||||
Console.Write('.');
|
Console.Write('.');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Console.Write(' ');
|
Console.Write(' ');
|
||||||
}
|
}
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file struct GuardNode
|
file struct GuardNode
|
||||||
{
|
{
|
||||||
public int Id { get; private set; }
|
public int Id { get; private set; }
|
||||||
public Vec2<int> Pos { get; }
|
public Vec2<int> Pos { get; }
|
||||||
public int Direction { get; }
|
public int Direction { get; }
|
||||||
public int? Next { get; set; }
|
public int? Next { get; set; }
|
||||||
public GuardNode(Vec2<int> pos, int dir, int id)
|
public GuardNode(Vec2<int> pos, int dir, int id)
|
||||||
{
|
{
|
||||||
Pos = pos;
|
Pos = pos;
|
||||||
Direction = dir;
|
Direction = dir;
|
||||||
Id = id;
|
Id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLoop(List<GuardNode> nodes)
|
public bool IsLoop(List<GuardNode> nodes)
|
||||||
{
|
{
|
||||||
return NodeExists(Id, nodes);
|
return NodeExists(Id, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool NodeExists(int target, List<GuardNode> nodes)
|
public bool NodeExists(int target, List<GuardNode> nodes)
|
||||||
{
|
{
|
||||||
if (Next == target)
|
if (Next == target)
|
||||||
return true;
|
return true;
|
||||||
if (Next is int id)
|
if (Next is int id)
|
||||||
return nodes[id].NodeExists(target, nodes);
|
return nodes[id].NodeExists(target, nodes);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Pos}: {Direction}";
|
return $"{Pos}: {Direction}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,70 +1,70 @@
|
|||||||
namespace AdventOfCode.Problems.AOC2024.Day7;
|
namespace AdventOfCode.Problems.AOC2024.Day7;
|
||||||
|
|
||||||
[ProblemInfo(2024, 7, "Bridge Repair")]
|
[ProblemInfo(2024, 7, "Bridge Repair")]
|
||||||
internal class BridgeRepair : Problem<ulong, ulong>
|
internal class BridgeRepair : Problem<ulong, ulong>
|
||||||
{
|
{
|
||||||
private List<(ulong total, ulong[] nums)> _data = [];
|
private List<(ulong total, ulong[] nums)> _data = [];
|
||||||
|
|
||||||
private enum Operator
|
private enum Operator
|
||||||
{
|
{
|
||||||
Mul,
|
Mul,
|
||||||
Add,
|
Add,
|
||||||
Concat
|
Concat
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
foreach (var (target, nums) in _data)
|
foreach (var (target, nums) in _data)
|
||||||
{
|
{
|
||||||
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add]))
|
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add]))
|
||||||
Part1 += target;
|
Part1 += target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
foreach (var (target, nums) in _data)
|
foreach (var (target, nums) in _data)
|
||||||
{
|
{
|
||||||
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add, Operator.Concat]))
|
if (IsSolvable(target, nums, [Operator.Mul, Operator.Add, Operator.Concat]))
|
||||||
Part2 += target;
|
Part2 += target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsSolvable(ulong target, ulong[] nums, Operator[] ops)
|
private static bool IsSolvable(ulong target, ulong[] nums, Operator[] ops)
|
||||||
{
|
{
|
||||||
return ops.Any(o => IsSolvable(target, nums, o, nums[0], ops));
|
return ops.Any(o => IsSolvable(target, nums, o, nums[0], ops));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsSolvable(ulong target, ulong[] nums, Operator curOperator, ulong curTotal, Operator[] ops, int idx = 1)
|
private static bool IsSolvable(ulong target, ulong[] nums, Operator curOperator, ulong curTotal, Operator[] ops, int idx = 1)
|
||||||
{
|
{
|
||||||
if (target == curTotal && idx == nums.Length)
|
if (target == curTotal && idx == nums.Length)
|
||||||
return true;
|
return true;
|
||||||
if (curTotal > target)
|
if (curTotal > target)
|
||||||
return false;
|
return false;
|
||||||
if (idx >= nums.Length)
|
if (idx >= nums.Length)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
curTotal = curOperator switch
|
curTotal = curOperator switch
|
||||||
{
|
{
|
||||||
Operator.Mul => curTotal * nums[idx],
|
Operator.Mul => curTotal * nums[idx],
|
||||||
Operator.Add => curTotal + nums[idx],
|
Operator.Add => curTotal + nums[idx],
|
||||||
Operator.Concat => ulong.Parse($"{curTotal}{nums[idx]}"),
|
Operator.Concat => ulong.Parse($"{curTotal}{nums[idx]}"),
|
||||||
_ => throw new InvalidOperationException(),
|
_ => throw new InvalidOperationException(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return ops.Any(o => IsSolvable(target, nums, o, curTotal, ops, idx + 1));
|
return ops.Any(o => IsSolvable(target, nums, o, curTotal, ops, idx + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
var lines = ReadInputLines("input.txt");
|
var lines = ReadInputLines("input.txt");
|
||||||
_data = new List<(ulong total, ulong[] nums)>(lines.Length);
|
_data = new List<(ulong total, ulong[] nums)>(lines.Length);
|
||||||
foreach (var line in lines)
|
foreach (var line in lines)
|
||||||
{
|
{
|
||||||
var s = line.Split(':');
|
var s = line.Split(':');
|
||||||
var sum = ulong.Parse(s[0].Trim());
|
var sum = ulong.Parse(s[0].Trim());
|
||||||
var nums = s[1].Trim().Split(' ').Select(ulong.Parse).ToArray();
|
var nums = s[1].Trim().Split(' ').Select(ulong.Parse).ToArray();
|
||||||
_data.Add((sum, nums));
|
_data.Add((sum, nums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,139 +1,139 @@
|
|||||||
using AdventOfCode.Utils.Models;
|
using AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
|
|
||||||
namespace AdventOfCode.Problems.AOC2024.Day8;
|
namespace AdventOfCode.Problems.AOC2024.Day8;
|
||||||
|
|
||||||
[ProblemInfo(2024, 8, "Resonant Collinearity")]
|
[ProblemInfo(2024, 8, "Resonant Collinearity")]
|
||||||
internal class ResonantCollinearity : Problem<int, int>
|
internal class ResonantCollinearity : Problem<int, int>
|
||||||
{
|
{
|
||||||
private string[] _map = [];
|
private string[] _map = [];
|
||||||
private int _width;
|
private int _width;
|
||||||
private int _height;
|
private int _height;
|
||||||
private FrozenDictionary<char, List<Vec2<int>>> _nodes = FrozenDictionary<char, List<Vec2<int>>>.Empty;
|
private FrozenDictionary<char, List<Vec2<int>>> _nodes = FrozenDictionary<char, List<Vec2<int>>>.Empty;
|
||||||
|
|
||||||
public override void CalculatePart1()
|
public override void CalculatePart1()
|
||||||
{
|
{
|
||||||
var antiNodes = new List<Vec2<int>>();
|
var antiNodes = new List<Vec2<int>>();
|
||||||
foreach (var (nodeType, nodes) in _nodes)
|
foreach (var (nodeType, nodes) in _nodes)
|
||||||
{
|
{
|
||||||
foreach (var a in nodes)
|
foreach (var a in nodes)
|
||||||
{
|
{
|
||||||
foreach (var b in nodes)
|
foreach (var b in nodes)
|
||||||
{
|
{
|
||||||
if (a == b)
|
if (a == b)
|
||||||
continue;
|
continue;
|
||||||
antiNodes.AddRange(GetAntiNodes(a, b));
|
antiNodes.AddRange(GetAntiNodes(a, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//PrintBoard(antiNodes);
|
//PrintBoard(antiNodes);
|
||||||
Part1 = antiNodes.Where(IsInBounds).Distinct().Count();
|
Part1 = antiNodes.Where(IsInBounds).Distinct().Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PrintBoard(List<Vec2<int>> antinodes)
|
public void PrintBoard(List<Vec2<int>> antinodes)
|
||||||
{
|
{
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
for (int y = 0; y < _height; y++)
|
for (int y = 0; y < _height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < _width; x++)
|
for (int x = 0; x < _width; x++)
|
||||||
{
|
{
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
var p = new Vec2<int>(x, y);
|
var p = new Vec2<int>(x, y);
|
||||||
if (antinodes.Contains(p))
|
if (antinodes.Contains(p))
|
||||||
Console.BackgroundColor = ConsoleColor.DarkGreen;
|
Console.BackgroundColor = ConsoleColor.DarkGreen;
|
||||||
Console.Write(_map[y][x]);
|
Console.Write(_map[y][x]);
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
}
|
}
|
||||||
Console.ResetColor();
|
Console.ResetColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsInBounds(Vec2<int> pos)
|
public bool IsInBounds(Vec2<int> pos)
|
||||||
{
|
{
|
||||||
if (pos.X < 0 || pos.Y < 0)
|
if (pos.X < 0 || pos.Y < 0)
|
||||||
return false;
|
return false;
|
||||||
if (pos.X >= _width || pos.Y >= _height)
|
if (pos.X >= _width || pos.Y >= _height)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec2<int>[] GetAntiNodes(Vec2<int> a, Vec2<int> b)
|
private Vec2<int>[] GetAntiNodes(Vec2<int> a, Vec2<int> b)
|
||||||
{
|
{
|
||||||
var dir = a - b;
|
var dir = a - b;
|
||||||
|
|
||||||
var aNode1 = dir + a;
|
var aNode1 = dir + a;
|
||||||
var aNode2 = -dir + b;
|
var aNode2 = -dir + b;
|
||||||
|
|
||||||
return [aNode1, aNode2];
|
return [aNode1, aNode2];
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vec2<int>[] GetHarmonicAntiNodes(Vec2<int> a, Vec2<int> b)
|
private Vec2<int>[] GetHarmonicAntiNodes(Vec2<int> a, Vec2<int> b)
|
||||||
{
|
{
|
||||||
var dir = a - b;
|
var dir = a - b;
|
||||||
|
|
||||||
List<Vec2<int>> GetNodes(Vec2<int> start, Vec2<int> dir)
|
List<Vec2<int>> GetNodes(Vec2<int> start, Vec2<int> dir)
|
||||||
{
|
{
|
||||||
var results = new List<Vec2<int>>();
|
var results = new List<Vec2<int>>();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var p = dir + start;
|
var p = dir + start;
|
||||||
if(!IsInBounds(p))
|
if(!IsInBounds(p))
|
||||||
break;
|
break;
|
||||||
results.Add(p);
|
results.Add(p);
|
||||||
start = p;
|
start = p;
|
||||||
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [.. GetNodes(a, dir), .. GetNodes(b, -dir)];
|
return [.. GetNodes(a, dir), .. GetNodes(b, -dir)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalculatePart2()
|
public override void CalculatePart2()
|
||||||
{
|
{
|
||||||
var antiNodes = new List<Vec2<int>>();
|
var antiNodes = new List<Vec2<int>>();
|
||||||
foreach (var (nodeType, nodes) in _nodes)
|
foreach (var (nodeType, nodes) in _nodes)
|
||||||
{
|
{
|
||||||
foreach (var a in nodes)
|
foreach (var a in nodes)
|
||||||
{
|
{
|
||||||
foreach (var b in nodes)
|
foreach (var b in nodes)
|
||||||
{
|
{
|
||||||
if (a == b)
|
if (a == b)
|
||||||
continue;
|
continue;
|
||||||
antiNodes.AddRange(GetHarmonicAntiNodes(a, b));
|
antiNodes.AddRange(GetHarmonicAntiNodes(a, b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//PrintBoard(antiNodes);
|
//PrintBoard(antiNodes);
|
||||||
antiNodes.AddRange(_nodes.Values.Where(v => v.Count > 1).SelectMany(v => v));
|
antiNodes.AddRange(_nodes.Values.Where(v => v.Count > 1).SelectMany(v => v));
|
||||||
Part2 = antiNodes.Distinct().Count();
|
Part2 = antiNodes.Distinct().Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void LoadInput()
|
public override void LoadInput()
|
||||||
{
|
{
|
||||||
_map = ReadInputLines("input.txt");
|
_map = ReadInputLines("input.txt");
|
||||||
var nodes = new Dictionary<char, List<Vec2<int>>>();
|
var nodes = new Dictionary<char, List<Vec2<int>>>();
|
||||||
_width = _map[0].Length;
|
_width = _map[0].Length;
|
||||||
_height = _map.Length;
|
_height = _map.Length;
|
||||||
for (int y = 0; y < _map.Length; y++)
|
for (int y = 0; y < _map.Length; y++)
|
||||||
{
|
{
|
||||||
var row = _map[y];
|
var row = _map[y];
|
||||||
for (int x = 0; x < row.Length; x++)
|
for (int x = 0; x < row.Length; x++)
|
||||||
{
|
{
|
||||||
switch (row[x])
|
switch (row[x])
|
||||||
{
|
{
|
||||||
case '.':
|
case '.':
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
var p = new Vec2<int>(x, y);
|
var p = new Vec2<int>(x, y);
|
||||||
if (!nodes.TryAdd(row[x], [p]))
|
if (!nodes.TryAdd(row[x], [p]))
|
||||||
nodes[row[x]].Add(p);
|
nodes[row[x]].Add(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_nodes = nodes.ToFrozenDictionary();
|
_nodes = nodes.ToFrozenDictionary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
61
AdventOfCode/Problems/AOC2025/Day1/SecretEntrance.cs
Normal file
61
AdventOfCode/Problems/AOC2025/Day1/SecretEntrance.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using ZLinq;
|
||||||
|
|
||||||
|
namespace AdventOfCode.Problems.AOC2025.Day1;
|
||||||
|
|
||||||
|
[ProblemInfo(2025, 1, "Secret Entrance")]
|
||||||
|
internal class SecretEntrance : Problem<int, int>
|
||||||
|
{
|
||||||
|
public int[] Input { get; set; } = [];
|
||||||
|
public override void CalculatePart1()
|
||||||
|
{
|
||||||
|
var c = 0;
|
||||||
|
var v = 50;
|
||||||
|
foreach (var item in Input)
|
||||||
|
{
|
||||||
|
v += item;
|
||||||
|
v = v.Mod(100);
|
||||||
|
if (v == 0)
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
Part1 = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalculatePart2()
|
||||||
|
{
|
||||||
|
var c = 0;
|
||||||
|
var v = 50;
|
||||||
|
foreach (var item in Input)
|
||||||
|
{
|
||||||
|
var sign = int.Sign(item);
|
||||||
|
for (int i = 0; i < Math.Abs(item); i++)
|
||||||
|
{
|
||||||
|
v += sign;
|
||||||
|
v = v.Mod(100);
|
||||||
|
if (v == 0)
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Part2 = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadInput()
|
||||||
|
{
|
||||||
|
Input = ReadInputLines("input.txt")
|
||||||
|
.AsValueEnumerable()
|
||||||
|
.Select(l =>
|
||||||
|
{
|
||||||
|
return l[0] switch
|
||||||
|
{
|
||||||
|
'L' => -int.Parse(l[1..]),
|
||||||
|
'R' => int.Parse(l[1..]),
|
||||||
|
_ => throw new NotImplementedException()
|
||||||
|
};
|
||||||
|
}).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
global using AdventOfCode.Runner;
|
global using AdventOfCode.Runner;
|
||||||
global using AdventOfCode.Runner.Attributes;
|
global using AdventOfCode.Runner.Attributes;
|
||||||
global using AdventOfCode.Utils;
|
global using AdventOfCode.Utils;
|
||||||
|
|
||||||
|
|
||||||
var runner = new AOCRunner();
|
var runner = new AOCRunner();
|
||||||
runner.RenderInteractiveMenu();
|
runner.RenderInteractiveMenu();
|
||||||
@@ -1,424 +1,424 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
|
|
||||||
public class AOCRunner
|
public class AOCRunner
|
||||||
{
|
{
|
||||||
private Dictionary<int, List<(ProblemInfoAttribute info, Type type)>> _loadedProblems;
|
private Dictionary<int, List<(ProblemInfoAttribute info, Type type)>> _loadedProblems;
|
||||||
private List<int> _years;
|
private List<int> _years;
|
||||||
private int _selectedYear;
|
private int _selectedYear;
|
||||||
private int _selectedDay;
|
private int _selectedDay;
|
||||||
private int _scollOffset = 0;
|
private int _scollOffset = 0;
|
||||||
private int _maxProblemCount;
|
private int _maxProblemCount;
|
||||||
private bool _isQuiting;
|
private bool _isQuiting;
|
||||||
|
|
||||||
private bool _isProblemMode = false;
|
private bool _isProblemMode = false;
|
||||||
|
|
||||||
public AOCRunner()
|
public AOCRunner()
|
||||||
{
|
{
|
||||||
Console.OutputEncoding = Encoding.UTF8;
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
_loadedProblems = new();
|
_loadedProblems = new();
|
||||||
_years = new List<int>();
|
_years = new List<int>();
|
||||||
_selectedYear = DateTime.Now.Year;
|
_selectedYear = DateTime.Now.Year;
|
||||||
FindProblemClasses();
|
FindProblemClasses();
|
||||||
|
|
||||||
if (!_loadedProblems.ContainsKey(_selectedYear))
|
if (!_loadedProblems.ContainsKey(_selectedYear))
|
||||||
_selectedYear = _loadedProblems.Keys.First();
|
_selectedYear = _loadedProblems.Keys.First();
|
||||||
|
|
||||||
InitSizing();
|
InitSizing();
|
||||||
if (_years.Count > 0)
|
if (_years.Count > 0)
|
||||||
{
|
{
|
||||||
_selectedDay = _loadedProblems[_selectedYear].Count - 1;
|
_selectedDay = _loadedProblems[_selectedYear].Count - 1;
|
||||||
ConstrainListScroll();
|
ConstrainListScroll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AOCRunner WithDay(int day)
|
public AOCRunner WithDay(int day)
|
||||||
{
|
{
|
||||||
var problem = _loadedProblems[_selectedYear].FirstOrDefault(d => d.info.Day == day);
|
var problem = _loadedProblems[_selectedYear].FirstOrDefault(d => d.info.Day == day);
|
||||||
if (problem == default)
|
if (problem == default)
|
||||||
throw new ArgumentException($"There are no problems have been loaded for the day '{day}' of year '{_selectedYear}'", nameof(day));
|
throw new ArgumentException($"There are no problems have been loaded for the day '{day}' of year '{_selectedYear}'", nameof(day));
|
||||||
|
|
||||||
_selectedDay = _loadedProblems[_selectedYear].IndexOf(problem);
|
_selectedDay = _loadedProblems[_selectedYear].IndexOf(problem);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AOCRunner WithYear(int year)
|
public AOCRunner WithYear(int year)
|
||||||
{
|
{
|
||||||
if (!_loadedProblems.ContainsKey(year))
|
if (!_loadedProblems.ContainsKey(year))
|
||||||
throw new ArgumentException($"There are no problems have been loaded for the year '{year}'", nameof(year));
|
throw new ArgumentException($"There are no problems have been loaded for the year '{year}'", nameof(year));
|
||||||
_selectedYear = year;
|
_selectedYear = year;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitSizing()
|
private void InitSizing()
|
||||||
{
|
{
|
||||||
_maxProblemCount = Console.WindowHeight - 9;
|
_maxProblemCount = Console.WindowHeight - 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConstrainListScroll()
|
private void ConstrainListScroll()
|
||||||
{
|
{
|
||||||
if (_selectedDay >= _maxProblemCount)
|
if (_selectedDay >= _maxProblemCount)
|
||||||
{
|
{
|
||||||
_scollOffset = _loadedProblems[_selectedYear].Count - _maxProblemCount;
|
_scollOffset = _loadedProblems[_selectedYear].Count - _maxProblemCount;
|
||||||
}
|
}
|
||||||
if (_selectedDay < _scollOffset)
|
if (_selectedDay < _scollOffset)
|
||||||
{
|
{
|
||||||
_scollOffset = _selectedDay;
|
_scollOffset = _selectedDay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FindProblemClasses()
|
private void FindProblemClasses()
|
||||||
{
|
{
|
||||||
var types = Assembly.GetExecutingAssembly().DefinedTypes.Where(t => !t.IsAbstract);
|
var types = Assembly.GetExecutingAssembly().DefinedTypes.Where(t => !t.IsAbstract);
|
||||||
if (types == null)
|
if (types == null)
|
||||||
return;
|
return;
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
{
|
{
|
||||||
var info = type.GetCustomAttribute<ProblemInfoAttribute>();
|
var info = type.GetCustomAttribute<ProblemInfoAttribute>();
|
||||||
if (info == null)
|
if (info == null)
|
||||||
continue;
|
continue;
|
||||||
if (_loadedProblems.TryGetValue(info.Year, out var list))
|
if (_loadedProblems.TryGetValue(info.Year, out var list))
|
||||||
list.Add((info, type));
|
list.Add((info, type));
|
||||||
else
|
else
|
||||||
_loadedProblems.Add(info.Year, new() { (info, type) });
|
_loadedProblems.Add(info.Year, new() { (info, type) });
|
||||||
}
|
}
|
||||||
foreach (var (year, list) in _loadedProblems)
|
foreach (var (year, list) in _loadedProblems)
|
||||||
_loadedProblems[year] = list.OrderBy(l => l.info.Day).ToList();
|
_loadedProblems[year] = list.OrderBy(l => l.info.Day).ToList();
|
||||||
_years = _loadedProblems.Keys.OrderDescending().ToList();
|
_years = _loadedProblems.Keys.OrderDescending().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RunDay(int year, int dayIndex)
|
private void RunDay(int year, int dayIndex)
|
||||||
{
|
{
|
||||||
var yearList = _loadedProblems[year];
|
var yearList = _loadedProblems[year];
|
||||||
if (yearList.Count <= dayIndex || dayIndex < 0)
|
if (yearList.Count <= dayIndex || dayIndex < 0)
|
||||||
Console.WriteLine($"No problem exists for day index {dayIndex}");
|
Console.WriteLine($"No problem exists for day index {dayIndex}");
|
||||||
|
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
var (info, problemType) = yearList[dayIndex];
|
var (info, problemType) = yearList[dayIndex];
|
||||||
Console.Write("Problem: ");
|
Console.Write("Problem: ");
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
Console.WriteLine($"\t{info.Name}");
|
Console.WriteLine($"\t{info.Name}");
|
||||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||||
Console.WriteLine($"\t\t{info.Year} - Day {info.Day}");
|
Console.WriteLine($"\t\t{info.Year} - Day {info.Day}");
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
|
|
||||||
if (Activator.CreateInstance(problemType) is not IProblem problem)
|
if (Activator.CreateInstance(problemType) is not IProblem problem)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Failed to create problem isntance");
|
Console.WriteLine("Failed to create problem isntance");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var time = ReadInput(problem);
|
var time = ReadInput(problem);
|
||||||
time += RunPart("Calculating Part 1", problem.CalculatePart1);
|
time += RunPart("Calculating Part 1", problem.CalculatePart1);
|
||||||
time += RunPart("Calculating Part 2", problem.CalculatePart2);
|
time += RunPart("Calculating Part 2", problem.CalculatePart2);
|
||||||
|
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.Write($"Total Elapsed Time: ");
|
Console.Write($"Total Elapsed Time: ");
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine($"{time.TotalMilliseconds}ms");
|
Console.WriteLine($"{time.TotalMilliseconds}ms");
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
|
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Printing Results:");
|
Console.WriteLine("Printing Results:");
|
||||||
|
|
||||||
Console.WriteLine("---- Part 1 ----");
|
Console.WriteLine("---- Part 1 ----");
|
||||||
problem.PrintPart1();
|
problem.PrintPart1();
|
||||||
Console.Write("\n\n");
|
Console.Write("\n\n");
|
||||||
Console.WriteLine("---- Part 2 ----");
|
Console.WriteLine("---- Part 2 ----");
|
||||||
problem.PrintPart2();
|
problem.PrintPart2();
|
||||||
Console.Write("\n\n");
|
Console.Write("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeSpan ReadInput(IProblem problem)
|
private static TimeSpan ReadInput(IProblem problem)
|
||||||
{
|
{
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.Write("Loading Input data... ");
|
Console.Write("Loading Input data... ");
|
||||||
sw.Start();
|
sw.Start();
|
||||||
problem.LoadInput();
|
problem.LoadInput();
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
Console.Write("Done in ");
|
Console.Write("Done in ");
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
|
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
|
||||||
return sw.Elapsed;
|
return sw.Elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TimeSpan RunPart(string name, Action action)
|
private static TimeSpan RunPart(string name, Action action)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
Console.Write($"{name}... ");
|
Console.Write($"{name}... ");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sw.Start();
|
sw.Start();
|
||||||
action();
|
action();
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
Console.Write("Done in ");
|
Console.Write("Done in ");
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
|
Console.WriteLine($"{sw.Elapsed.TotalMilliseconds:n}ms");
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine("Not Implemented");
|
Console.WriteLine("Not Implemented");
|
||||||
}
|
}
|
||||||
//catch (Exception e)
|
//catch (Exception e)
|
||||||
//{
|
//{
|
||||||
// Console.ForegroundColor = ConsoleColor.Red;
|
// Console.ForegroundColor = ConsoleColor.Red;
|
||||||
// Console.WriteLine("Failed");
|
// Console.WriteLine("Failed");
|
||||||
// Console.WriteLine(e);
|
// Console.WriteLine(e);
|
||||||
//}
|
//}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
}
|
}
|
||||||
return sw.Elapsed;
|
return sw.Elapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenderInteractiveMenu()
|
public void RenderInteractiveMenu()
|
||||||
{
|
{
|
||||||
Console.BackgroundColor = ConsoleColor.Black;
|
Console.BackgroundColor = ConsoleColor.Black;
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
Console.CursorVisible = false;
|
Console.CursorVisible = false;
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
while (!_isQuiting)
|
while (!_isQuiting)
|
||||||
{
|
{
|
||||||
InitSizing();
|
InitSizing();
|
||||||
RenderTopBar();
|
RenderTopBar();
|
||||||
RenderContentView();
|
RenderContentView();
|
||||||
ReadInput();
|
ReadInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadInput()
|
private void ReadInput()
|
||||||
{
|
{
|
||||||
var input = Console.ReadKey(true);
|
var input = Console.ReadKey(true);
|
||||||
if (_isProblemMode)
|
if (_isProblemMode)
|
||||||
{
|
{
|
||||||
if (input.Key is ConsoleKey.Enter or ConsoleKey.Escape)
|
if (input.Key is ConsoleKey.Enter or ConsoleKey.Escape)
|
||||||
{
|
{
|
||||||
_isProblemMode = false;
|
_isProblemMode = false;
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var yearIndex = _years.IndexOf(_selectedYear);
|
var yearIndex = _years.IndexOf(_selectedYear);
|
||||||
var dayMax = _loadedProblems[_selectedYear].Count - 1;
|
var dayMax = _loadedProblems[_selectedYear].Count - 1;
|
||||||
switch (input.Key)
|
switch (input.Key)
|
||||||
{
|
{
|
||||||
case ConsoleKey.LeftArrow:
|
case ConsoleKey.LeftArrow:
|
||||||
_scollOffset = 0;
|
_scollOffset = 0;
|
||||||
_selectedDay = 0;
|
_selectedDay = 0;
|
||||||
if (yearIndex == 0)
|
if (yearIndex == 0)
|
||||||
{
|
{
|
||||||
_selectedYear = _years.Last();
|
_selectedYear = _years.Last();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_selectedYear = _years[--yearIndex];
|
_selectedYear = _years[--yearIndex];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleKey.RightArrow:
|
case ConsoleKey.RightArrow:
|
||||||
_scollOffset = 0;
|
_scollOffset = 0;
|
||||||
_selectedDay = 0;
|
_selectedDay = 0;
|
||||||
if (yearIndex == _years.Count - 1)
|
if (yearIndex == _years.Count - 1)
|
||||||
{
|
{
|
||||||
_selectedYear = _years.First();
|
_selectedYear = _years.First();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_selectedYear = _years[++yearIndex];
|
_selectedYear = _years[++yearIndex];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleKey.UpArrow:
|
case ConsoleKey.UpArrow:
|
||||||
if (_selectedDay == 0)
|
if (_selectedDay == 0)
|
||||||
{
|
{
|
||||||
_selectedDay = dayMax;
|
_selectedDay = dayMax;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_selectedDay--;
|
_selectedDay--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleKey.DownArrow:
|
case ConsoleKey.DownArrow:
|
||||||
if (_selectedDay == dayMax)
|
if (_selectedDay == dayMax)
|
||||||
{
|
{
|
||||||
_selectedDay = 0;
|
_selectedDay = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_selectedDay++;
|
_selectedDay++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleKey.Enter:
|
case ConsoleKey.Enter:
|
||||||
_isProblemMode = true;
|
_isProblemMode = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ConsoleKey.Escape:
|
case ConsoleKey.Escape:
|
||||||
_isQuiting = true;
|
_isQuiting = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ConstrainListScroll();
|
ConstrainListScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderTopBar()
|
private void RenderTopBar()
|
||||||
{
|
{
|
||||||
if (_isProblemMode)
|
if (_isProblemMode)
|
||||||
return;
|
return;
|
||||||
//Render Border
|
//Render Border
|
||||||
DrawBorder(1, 0, Console.WindowWidth, 3);
|
DrawBorder(1, 0, Console.WindowWidth, 3);
|
||||||
Console.SetCursorPosition(Console.WindowWidth / 2 - 4, 1);
|
Console.SetCursorPosition(Console.WindowWidth / 2 - 4, 1);
|
||||||
Console.ForegroundColor = ConsoleColor.Blue;
|
Console.ForegroundColor = ConsoleColor.Blue;
|
||||||
Console.Write(" Years ");
|
Console.Write(" Years ");
|
||||||
//Render Tabs
|
//Render Tabs
|
||||||
RenderTabList();
|
RenderTabList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderTabList()
|
private void RenderTabList()
|
||||||
{
|
{
|
||||||
var buttonWidth = 6;
|
var buttonWidth = 6;
|
||||||
var tabMaxPos = Console.WindowWidth - 3;
|
var tabMaxPos = Console.WindowWidth - 3;
|
||||||
for (int i = 0; i < _years.Count; i++)
|
for (int i = 0; i < _years.Count; i++)
|
||||||
{
|
{
|
||||||
var year = _years[i];
|
var year = _years[i];
|
||||||
var col = (i * 7) + 2;
|
var col = (i * 7) + 2;
|
||||||
var end = col + buttonWidth;
|
var end = col + buttonWidth;
|
||||||
if (end >= tabMaxPos)
|
if (end >= tabMaxPos)
|
||||||
break;
|
break;
|
||||||
if (year == _selectedYear)
|
if (year == _selectedYear)
|
||||||
DrawSelectedButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Red, ConsoleColor.Blue);
|
DrawSelectedButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Red, ConsoleColor.Blue);
|
||||||
else
|
else
|
||||||
DrawButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Gray, Console.BackgroundColor);
|
DrawButton(year.ToString(), 2, col, buttonWidth, 1, ConsoleColor.Gray, Console.BackgroundColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderContentView()
|
private void RenderContentView()
|
||||||
{
|
{
|
||||||
if (!_isProblemMode)
|
if (!_isProblemMode)
|
||||||
{
|
{
|
||||||
DrawBorder(5, 0, Console.WindowWidth, Console.WindowHeight - 5);
|
DrawBorder(5, 0, Console.WindowWidth, Console.WindowHeight - 5);
|
||||||
Console.SetCursorPosition(Console.WindowWidth / 2 - 5, 5);
|
Console.SetCursorPosition(Console.WindowWidth / 2 - 5, 5);
|
||||||
Console.ForegroundColor = ConsoleColor.Blue;
|
Console.ForegroundColor = ConsoleColor.Blue;
|
||||||
Console.Write(" Problems ");
|
Console.Write(" Problems ");
|
||||||
RenderProblemList();
|
RenderProblemList();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
RenderProblemResults();
|
RenderProblemResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderProblemList()
|
private void RenderProblemList()
|
||||||
{
|
{
|
||||||
if (_loadedProblems.Count == 0)
|
if (_loadedProblems.Count == 0)
|
||||||
{
|
{
|
||||||
DrawButton("There are no problems...", 6, 2, Console.WindowWidth - 2, Console.WindowHeight - 7);
|
DrawButton("There are no problems...", 6, 2, Console.WindowWidth - 2, Console.WindowHeight - 7);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var problems = _loadedProblems[_selectedYear];
|
var problems = _loadedProblems[_selectedYear];
|
||||||
|
|
||||||
var listEnd = Math.Min(_maxProblemCount, problems.Count);
|
var listEnd = Math.Min(_maxProblemCount, problems.Count);
|
||||||
|
|
||||||
for (int i = 0; i < listEnd; i++)
|
for (int i = 0; i < listEnd; i++)
|
||||||
{
|
{
|
||||||
var (info, _) = problems[i + _scollOffset];
|
var (info, _) = problems[i + _scollOffset];
|
||||||
var buttonText = $"{i + _scollOffset}.\t[Day {info.Day}] {info.Name}";
|
var buttonText = $"{i + _scollOffset}.\t[Day {info.Day}] {info.Name}";
|
||||||
var row = i + 7;
|
var row = i + 7;
|
||||||
if (i + _scollOffset == _selectedDay)
|
if (i + _scollOffset == _selectedDay)
|
||||||
DrawSelectedButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.DarkMagenta, ConsoleColor.DarkGray, false, 2);
|
DrawSelectedButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.DarkMagenta, ConsoleColor.DarkGray, false, 2);
|
||||||
else
|
else
|
||||||
DrawButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.Cyan, Console.BackgroundColor, false, 2);
|
DrawButton(buttonText, row, 2, Console.WindowWidth - 4, 1, ConsoleColor.Cyan, Console.BackgroundColor, false, 2);
|
||||||
}
|
}
|
||||||
for (int i = problems.Count + 7; i < Console.WindowHeight - 2; i++)
|
for (int i = problems.Count + 7; i < Console.WindowHeight - 2; i++)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(2, i);
|
Console.SetCursorPosition(2, i);
|
||||||
Console.Write(new string(' ', Console.WindowWidth - 4));
|
Console.Write(new string(' ', Console.WindowWidth - 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RenderProblemResults()
|
private void RenderProblemResults()
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(2, 7);
|
Console.SetCursorPosition(2, 7);
|
||||||
RunDay(_selectedYear, _selectedDay);
|
RunDay(_selectedYear, _selectedDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawSelectedButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
|
private void DrawSelectedButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
|
||||||
{
|
{
|
||||||
//text = $"\ue0c7{text}\ue0c6";
|
//text = $"\ue0c7{text}\ue0c6";
|
||||||
var origBg = Console.BackgroundColor;
|
var origBg = Console.BackgroundColor;
|
||||||
Console.BackgroundColor = background;
|
Console.BackgroundColor = background;
|
||||||
for (int y = row; y < row + height; y++)
|
for (int y = row; y < row + height; y++)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(col, y);
|
Console.SetCursorPosition(col, y);
|
||||||
Console.Write(new string(' ', width));
|
Console.Write(new string(' ', width));
|
||||||
}
|
}
|
||||||
Console.ForegroundColor = color;
|
Console.ForegroundColor = color;
|
||||||
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
|
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
|
||||||
var yOffset = centered ? height / 2 : padding;
|
var yOffset = centered ? height / 2 : padding;
|
||||||
if (height == 1)
|
if (height == 1)
|
||||||
yOffset = 0;
|
yOffset = 0;
|
||||||
Console.SetCursorPosition(col + xOffset, row + yOffset);
|
Console.SetCursorPosition(col + xOffset, row + yOffset);
|
||||||
Console.Write(text);
|
Console.Write(text);
|
||||||
Console.BackgroundColor = origBg;
|
Console.BackgroundColor = origBg;
|
||||||
Console.ForegroundColor = background;
|
Console.ForegroundColor = background;
|
||||||
Console.SetCursorPosition(col, row + height / 2);
|
Console.SetCursorPosition(col, row + height / 2);
|
||||||
Console.Write('\ue0c7');
|
Console.Write('\ue0c7');
|
||||||
Console.SetCursorPosition(col + width - 1, row + height / 2);
|
Console.SetCursorPosition(col + width - 1, row + height / 2);
|
||||||
Console.Write('\ue0c6');
|
Console.Write('\ue0c6');
|
||||||
|
|
||||||
Console.BackgroundColor = origBg;
|
Console.BackgroundColor = origBg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
|
private void DrawButton(string text, int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black, bool centered = true, int padding = 0)
|
||||||
{
|
{
|
||||||
var origBg = Console.BackgroundColor;
|
var origBg = Console.BackgroundColor;
|
||||||
Console.BackgroundColor = background;
|
Console.BackgroundColor = background;
|
||||||
for (int y = row; y < row + height; y++)
|
for (int y = row; y < row + height; y++)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(col, y);
|
Console.SetCursorPosition(col, y);
|
||||||
Console.Write(new string(' ', width));
|
Console.Write(new string(' ', width));
|
||||||
}
|
}
|
||||||
Console.ForegroundColor = color;
|
Console.ForegroundColor = color;
|
||||||
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
|
var xOffset = centered ? (width / 2) - (text.Length / 2) : padding;
|
||||||
var yOffset = centered ? height / 2 : padding;
|
var yOffset = centered ? height / 2 : padding;
|
||||||
if (height == 1)
|
if (height == 1)
|
||||||
yOffset = 0;
|
yOffset = 0;
|
||||||
Console.SetCursorPosition(col + xOffset, row + yOffset);
|
Console.SetCursorPosition(col + xOffset, row + yOffset);
|
||||||
Console.Write(text);
|
Console.Write(text);
|
||||||
Console.BackgroundColor = origBg;
|
Console.BackgroundColor = origBg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawBorder(int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, bool drawFill = false)
|
private void DrawBorder(int row, int col, int width, int height, ConsoleColor color = ConsoleColor.Gray, bool drawFill = false)
|
||||||
{
|
{
|
||||||
//║═╔╗╝╚
|
//║═╔╗╝╚
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
var w = col + width - 1;
|
var w = col + width - 1;
|
||||||
var h = row + height - 1;
|
var h = row + height - 1;
|
||||||
for (int x = col; x <= w; x++)
|
for (int x = col; x <= w; x++)
|
||||||
{
|
{
|
||||||
for (int y = row; y <= h; y++)
|
for (int y = row; y <= h; y++)
|
||||||
{
|
{
|
||||||
Console.SetCursorPosition(x, y);
|
Console.SetCursorPosition(x, y);
|
||||||
if (x == col && y == row)
|
if (x == col && y == row)
|
||||||
Console.Write('╔');
|
Console.Write('╔');
|
||||||
else if (x == col && y == h)
|
else if (x == col && y == h)
|
||||||
Console.Write('╚');
|
Console.Write('╚');
|
||||||
else if (x == w && y == row)
|
else if (x == w && y == row)
|
||||||
Console.Write('╗');
|
Console.Write('╗');
|
||||||
else if (x == w && y == h)
|
else if (x == w && y == h)
|
||||||
Console.Write('╝');
|
Console.Write('╝');
|
||||||
else if (x == col || x == w)
|
else if (x == col || x == w)
|
||||||
Console.Write('║');
|
Console.Write('║');
|
||||||
else if (y == row || y == h)
|
else if (y == row || y == h)
|
||||||
Console.Write('═');
|
Console.Write('═');
|
||||||
else if (drawFill)
|
else if (drawFill)
|
||||||
Console.Write(' ');
|
Console.Write(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
namespace AdventOfCode.Runner.Attributes;
|
namespace AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
public class ProblemInfoAttribute : Attribute
|
public class ProblemInfoAttribute : Attribute
|
||||||
{
|
{
|
||||||
public int Day { get; init; }
|
public int Day { get; init; }
|
||||||
public int Year { get; init; }
|
public int Year { get; init; }
|
||||||
public string Name { get; init; }
|
public string Name { get; init; }
|
||||||
|
|
||||||
public ProblemInfoAttribute(int year, int day, string name)
|
public ProblemInfoAttribute(int year, int day, string name)
|
||||||
{
|
{
|
||||||
Year = year;
|
Year = year;
|
||||||
Day = day;
|
Day = day;
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,63 +1,63 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static IEnumerable<T> Print<T>(this IEnumerable<T> values)
|
public static IEnumerable<T> Print<T>(this IEnumerable<T> values)
|
||||||
{
|
{
|
||||||
foreach (var item in values)
|
foreach (var item in values)
|
||||||
{
|
{
|
||||||
Console.WriteLine(item);
|
Console.WriteLine(item);
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T LCM<T>(this IEnumerable<T> values) where T : INumber<T>
|
public static T LCM<T>(this IEnumerable<T> values) where T : INumber<T>
|
||||||
{
|
{
|
||||||
var a = values.First();
|
var a = values.First();
|
||||||
values = values.Skip(1);
|
values = values.Skip(1);
|
||||||
foreach (var item in values)
|
foreach (var item in values)
|
||||||
{
|
{
|
||||||
a = a.LCM(item);
|
a = a.LCM(item);
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<IEnumerable<T2>> Transpose<T, T2>(this IEnumerable<T> data) where T: IEnumerable<T2>
|
public static IEnumerable<IEnumerable<T2>> Transpose<T, T2>(this IEnumerable<T> data) where T: IEnumerable<T2>
|
||||||
{
|
{
|
||||||
var range = Enumerable.Range(0, data.First().Count());
|
var range = Enumerable.Range(0, data.First().Count());
|
||||||
|
|
||||||
return range.Select(i => data.Select(l => l.Skip(i).First()));
|
return range.Select(i => data.Select(l => l.Skip(i).First()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<T> Transpose<T, T2>(this IEnumerable<T> data, Func<IEnumerable<T2>, T> formatter) where T : IEnumerable<T2>
|
public static IEnumerable<T> Transpose<T, T2>(this IEnumerable<T> data, Func<IEnumerable<T2>, T> formatter) where T : IEnumerable<T2>
|
||||||
{
|
{
|
||||||
var range = Enumerable.Range(0, data.First().Count());
|
var range = Enumerable.Range(0, data.First().Count());
|
||||||
|
|
||||||
return range.Select(i => formatter(data.Select(l => l.Skip(i).First())));
|
return range.Select(i => formatter(data.Select(l => l.Skip(i).First())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<string> Transpose(this IEnumerable<string> data)
|
public static IEnumerable<string> Transpose(this IEnumerable<string> data)
|
||||||
{
|
{
|
||||||
return Transpose<string, char>(data, a => string.Join("", a));
|
return Transpose<string, char>(data, a => string.Join("", a));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<List<T>> Permute<T>(this IEnumerable<T> values)
|
public static IEnumerable<List<T>> Permute<T>(this IEnumerable<T> values)
|
||||||
{
|
{
|
||||||
IEnumerable<List<T>> permutate(IEnumerable<T> reminder, IEnumerable<T> prefix)
|
IEnumerable<List<T>> permutate(IEnumerable<T> reminder, IEnumerable<T> prefix)
|
||||||
{
|
{
|
||||||
return !reminder.Any()
|
return !reminder.Any()
|
||||||
? new List<List<T>> { prefix.ToList() }
|
? new List<List<T>> { prefix.ToList() }
|
||||||
: reminder.SelectMany((c, i) => permutate(
|
: reminder.SelectMany((c, i) => permutate(
|
||||||
reminder.Take(i).Concat(reminder.Skip(i + 1)).ToList(),
|
reminder.Take(i).Concat(reminder.Skip(i + 1)).ToList(),
|
||||||
prefix.Append(c)));
|
prefix.Append(c)));
|
||||||
}
|
}
|
||||||
return permutate(values, Enumerable.Empty<T>());
|
return permutate(values, Enumerable.Empty<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
|
|
||||||
public static class ExtraMath
|
public static class ExtraMath
|
||||||
{
|
{
|
||||||
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
public static T GCF<T>(this T a, T b) where T : INumber<T>
|
||||||
{
|
{
|
||||||
while (!b.Equals(T.Zero))
|
while (!b.Equals(T.Zero))
|
||||||
{
|
{
|
||||||
var t = b;
|
var t = b;
|
||||||
b = a % b;
|
b = a % b;
|
||||||
a = t;
|
a = t;
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T LCM<T>(this T a, T b) where T : INumber<T>
|
public static T LCM<T>(this T a, T b) where T : INumber<T>
|
||||||
{
|
{
|
||||||
return (a / GCF(a, b)) * b;
|
return (a / GCF(a, b)) * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Max<T>(this T a, T b) where T : INumber<T>
|
public static T Max<T>(this T a, T b) where T : INumber<T>
|
||||||
{
|
{
|
||||||
return T.Max(a, b);
|
return T.Max(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T Min<T>(this T a, T b) where T : INumber<T>
|
public static T Min<T>(this T a, T b) where T : INumber<T>
|
||||||
{
|
{
|
||||||
return T.Min(a, b);
|
return T.Min(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,89 +1,89 @@
|
|||||||
using AdventOfCode.Runner.Attributes;
|
using AdventOfCode.Runner.Attributes;
|
||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace AdventOfCode.Runner;
|
namespace AdventOfCode.Runner;
|
||||||
|
|
||||||
public interface IProblem
|
public interface IProblem
|
||||||
{
|
{
|
||||||
void LoadInput();
|
void LoadInput();
|
||||||
|
|
||||||
void CalculatePart1();
|
void CalculatePart1();
|
||||||
|
|
||||||
void PrintPart1();
|
void PrintPart1();
|
||||||
|
|
||||||
void CalculatePart2();
|
void CalculatePart2();
|
||||||
|
|
||||||
void PrintPart2();
|
void PrintPart2();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class Problem : Problem<string, string>
|
public abstract class Problem : Problem<string, string>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class Problem<TPart1, TPart2> : IProblem
|
public abstract class Problem<TPart1, TPart2> : IProblem
|
||||||
{
|
{
|
||||||
protected TPart1? Part1 { get; set; }
|
protected TPart1? Part1 { get; set; }
|
||||||
protected TPart2? Part2 { get; set; }
|
protected TPart2? Part2 { get; set; }
|
||||||
|
|
||||||
public abstract void LoadInput();
|
public abstract void LoadInput();
|
||||||
|
|
||||||
public abstract void CalculatePart1();
|
public abstract void CalculatePart1();
|
||||||
|
|
||||||
public virtual void PrintPart1()
|
public virtual void PrintPart1()
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
if (Part1 == null)
|
if (Part1 == null)
|
||||||
{
|
{
|
||||||
Console.Write("Part 1: ");
|
Console.Write("Part 1: ");
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine("No Solution");
|
Console.WriteLine("No Solution");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Write("Part 1: ");
|
Console.Write("Part 1: ");
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
Console.WriteLine($"{Part1}");
|
Console.WriteLine($"{Part1}");
|
||||||
}
|
}
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void CalculatePart2();
|
public abstract void CalculatePart2();
|
||||||
|
|
||||||
public virtual void PrintPart2()
|
public virtual void PrintPart2()
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
if (Part2 == null)
|
if (Part2 == null)
|
||||||
{
|
{
|
||||||
Console.Write("Part 2: ");
|
Console.Write("Part 2: ");
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine("No Solution");
|
Console.WriteLine("No Solution");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Write("Part 2: ");
|
Console.Write("Part 2: ");
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
Console.WriteLine($"{Part2}");
|
Console.WriteLine($"{Part2}");
|
||||||
}
|
}
|
||||||
Console.ForegroundColor = ConsoleColor.Gray;
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetInputFile(string filename = "input.txt")
|
protected string GetInputFile(string filename = "input.txt")
|
||||||
{
|
{
|
||||||
var info = this.GetType().GetCustomAttribute<ProblemInfoAttribute>();
|
var info = this.GetType().GetCustomAttribute<ProblemInfoAttribute>();
|
||||||
if (info == null)
|
if (info == null)
|
||||||
return filename;
|
return filename;
|
||||||
|
|
||||||
return Path.Combine($"Problems/AOC{info.Year}/Day{info.Day}", filename);
|
return Path.Combine($"Problems/AOC{info.Year}/Day{info.Day}", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string[] ReadInputLines(string filename = "input.txt")
|
protected string[] ReadInputLines(string filename = "input.txt")
|
||||||
{
|
{
|
||||||
return File.ReadAllLines(GetInputFile(filename));
|
return File.ReadAllLines(GetInputFile(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string ReadInputText(string filename = "input.txt")
|
protected string ReadInputText(string filename = "input.txt")
|
||||||
{
|
{
|
||||||
return File.ReadAllText(GetInputFile(filename));
|
return File.ReadAllText(GetInputFile(filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Numerics;
|
||||||
using System.Threading.Tasks;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
namespace AdventOfCode.Utils;
|
|
||||||
public static class Extensions
|
namespace AdventOfCode.Utils;
|
||||||
{
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
|
||||||
public static string AsJoinedString<T>(this IEnumerable<T> data, string delim = ", ")
|
{
|
||||||
{
|
return string.Join(delim, data);
|
||||||
return string.Join(delim, data);
|
}
|
||||||
}
|
|
||||||
}
|
public static T Mod<T>(this T value, T divisor) where T : INumber<T>
|
||||||
|
{
|
||||||
|
T remainder = value % divisor;
|
||||||
|
|
||||||
|
if (remainder < T.Zero)
|
||||||
|
return remainder + divisor;
|
||||||
|
else
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace AdventOfCode.Utils.Models;
|
namespace AdventOfCode.Utils.Models;
|
||||||
|
|
||||||
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
public record struct Vec2<T>(T X, T Y) where T : INumber<T>
|
||||||
{
|
{
|
||||||
public static Vec2<T> Zero => new (T.Zero, T.Zero);
|
public static Vec2<T> Zero => new (T.Zero, T.Zero);
|
||||||
public static Vec2<T> One => new (T.One, T.One);
|
public static Vec2<T> One => new (T.One, T.One);
|
||||||
|
|
||||||
public readonly Vec2<T> YX => new(Y, X);
|
public readonly Vec2<T> YX => new(Y, X);
|
||||||
public readonly Vec2<T> YY => new(Y, Y);
|
public readonly Vec2<T> YY => new(Y, Y);
|
||||||
public readonly Vec2<T> XX => new(X, X);
|
public readonly Vec2<T> XX => new(X, X);
|
||||||
public static Vec2<T> Splat(T v) => new(v, v);
|
public static Vec2<T> Splat(T v) => new(v, v);
|
||||||
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X + right.X, left.Y + right.Y);
|
||||||
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right) => new Vec2<T>(left.X - right.X, left.Y - right.Y);
|
||||||
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
|
public static Vec2<T> operator -(Vec2<T> vec) => new Vec2<T>(-vec.X, -vec.Y);
|
||||||
public static Vec2<T> operator *(Vec2<T> left, T right) => new Vec2<T>(left.X * right, left.Y * right);
|
public static Vec2<T> operator *(Vec2<T> left, T right) => new Vec2<T>(left.X * right, left.Y * right);
|
||||||
public static Vec2<T> operator *(T left, Vec2<T> right) => new Vec2<T>(right.X * left, right.Y * left);
|
public static Vec2<T> operator *(T left, Vec2<T> right) => new Vec2<T>(right.X * left, right.Y * left);
|
||||||
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
public static Vec2<T> operator /(Vec2<T> left, T right) => new Vec2<T>(left.X / right, left.Y / right);
|
||||||
|
|
||||||
public T DistanceSq(Vec2<T> other)
|
public T DistanceSq(Vec2<T> other)
|
||||||
{
|
{
|
||||||
var a = other.X - this.X;
|
var a = other.X - this.X;
|
||||||
var b = other.Y - this.Y;
|
var b = other.Y - this.Y;
|
||||||
return (a * a) + (b * b);
|
return (a * a) + (b * b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
public record struct Vec3<T>(T X, T Y, T Z) where T : INumber<T>
|
||||||
{
|
{
|
||||||
public static Vec3<T> Zero => new(T.Zero, T.Zero, T.Zero);
|
public static Vec3<T> Zero => new(T.Zero, T.Zero, T.Zero);
|
||||||
public static Vec3<T> One => new(T.One, T.One, T.One);
|
public static Vec3<T> One => new(T.One, T.One, T.One);
|
||||||
public static Vec3<T> Splat(T v) => new(v, v, v);
|
public static Vec3<T> Splat(T v) => new(v, v, v);
|
||||||
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
|
||||||
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right) => new Vec3<T>(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
|
||||||
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
public static Vec3<T> operator -(Vec3<T> vec) => new Vec3<T>(-vec.X, -vec.Y, -vec.Z);
|
||||||
public static Vec3<T> operator *(Vec3<T> left, T right) => new Vec3<T>(left.X * right, left.Y * right, left.Z * right);
|
public static Vec3<T> operator *(Vec3<T> left, T right) => new Vec3<T>(left.X * right, left.Y * right, left.Z * right);
|
||||||
public static Vec3<T> operator *(T left, Vec3<T> right) => new Vec3<T>(right.X * left, right.Y * left, right.Z * left);
|
public static Vec3<T> operator *(T left, Vec3<T> right) => new Vec3<T>(right.X * left, right.Y * left, right.Z * left);
|
||||||
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
public static Vec3<T> operator /(Vec3<T> left, T right) => new Vec3<T>(left.X / right, left.Y / right, left.Z / right);
|
||||||
|
|
||||||
public T DistanceSq(Vec3<T> other)
|
public T DistanceSq(Vec3<T> other)
|
||||||
{
|
{
|
||||||
var a = other.X - this.X;
|
var a = other.X - this.X;
|
||||||
var b = other.Y - this.Y;
|
var b = other.Y - this.Y;
|
||||||
var c = other.Z - this.Z;
|
var c = other.Z - this.Z;
|
||||||
return (a * a) + (b * b) + (c * c);
|
return (a * a) + (b * b) + (c * c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,37 @@
|
|||||||
namespace AdventOfCode.Utils;
|
namespace AdventOfCode.Utils;
|
||||||
|
|
||||||
public static class QuickMath
|
public static class QuickMath
|
||||||
{
|
{
|
||||||
private static readonly long[] pow10Long = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000];
|
private static readonly long[] pow10Long = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000];
|
||||||
private static readonly int[] pow10int = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
|
private static readonly int[] pow10int = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
|
||||||
|
|
||||||
public static long FastPow10(long exp)
|
public static long FastPow10(long exp)
|
||||||
{
|
{
|
||||||
return pow10Long[exp];
|
return pow10Long[exp];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int FastPow10(int exp)
|
public static int FastPow10(int exp)
|
||||||
{
|
{
|
||||||
return pow10int[exp];
|
return pow10int[exp];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly long[] longCorrectionTable= [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 9999999999, 99999999999, 999999999999, 9999999999999, 99999999999999, 999999999999999, 9999999999999999, 99999999999999999, 999999999999999999];
|
private static readonly long[] longCorrectionTable= [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, 9999999999, 99999999999, 999999999999, 9999999999999, 99999999999999, 999999999999999, 9999999999999999, 99999999999999999, 999999999999999999];
|
||||||
private static readonly int[] intCorrectionTable = [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999];
|
private static readonly int[] intCorrectionTable = [9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999];
|
||||||
public static long DigitCount(this long value)
|
public static long DigitCount(this long value)
|
||||||
{
|
{
|
||||||
var l2 = 63 - long.LeadingZeroCount(value | 1);
|
var l2 = 63 - long.LeadingZeroCount(value | 1);
|
||||||
var ans = ((9 * l2) >> 5);
|
var ans = ((9 * l2) >> 5);
|
||||||
if (value > longCorrectionTable[ans])
|
if (value > longCorrectionTable[ans])
|
||||||
ans += 1;
|
ans += 1;
|
||||||
return ans + 1;
|
return ans + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int DigitCount(this int value)
|
public static int DigitCount(this int value)
|
||||||
{
|
{
|
||||||
var l2 = 31 - int.LeadingZeroCount(value | 1);
|
var l2 = 31 - int.LeadingZeroCount(value | 1);
|
||||||
var ans = ((9 * l2) >> 5);
|
var ans = ((9 * l2) >> 5);
|
||||||
if (value > intCorrectionTable[ans])
|
if (value > intCorrectionTable[ans])
|
||||||
ans += 1;
|
ans += 1;
|
||||||
return ans + 1;
|
return ans + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user