This gist contains some Advent of Code solutions for the 2021 season.
Last active
December 7, 2021 17:42
-
-
Save JPRuskin/6cdd5117d14ea02cd1c2104cd5456b45 to your computer and use it in GitHub Desktop.
Solutions to Advent of Code 2021, probably in PowerShell.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[int[]]$Reports = @(199,200,208,210,200,207,240,269,260,263) | |
) | |
$Increases = 0 | |
foreach ($Depth in $Reports) { | |
if ($LastDepth -and $Depth -gt $LastDepth) { | |
$Increases++ | |
} | |
$LastDepth = $Depth | |
} | |
Write-Host "There are $($Increases) measurements that are larger than the previous measurement." | |
$LargerSums = 0 | |
for ($i=0; $i -le ($Reports.Count - 2); $i++) { | |
$Window = $Reports[$i] + $Reports[$i+1] + $Reports[$i+2] | |
if ($LastWindow -and $Window -gt $LastWindow) { | |
$LargerSums++ | |
} | |
$LastWindow = $Window | |
} | |
Write-Host "There are $($LargerSums) sums that are larger than the previous sum." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[string[]]$Instructions = @" | |
forward 5 | |
down 5 | |
forward 8 | |
up 3 | |
down 8 | |
forward 2 | |
"@.Split("`n") | |
) | |
# Part 1 | |
$Horizontal = 0 | |
$Depth = 0 | |
switch -regex ($Instructions) { | |
"forward (\d+)" {$Horizontal += $Matches[1]} | |
"down (\d+)" {$Depth += $Matches[1]} | |
"up (\d+)" {$Depth -= $Matches[1]} | |
} | |
Write-Host "$Horizontal * $Depth = $($Horizontal * $Depth)" | |
# Part 2 | |
$Horizontal = 0 | |
$Depth = 0 | |
$Aim = 0 | |
switch -regex ($Instructions) { | |
"forward (\d+)" { | |
$Horizontal += $Matches[1] | |
$Depth += $Aim * $Matches[1] | |
} | |
"down (\d+)" {$Aim += $Matches[1]} | |
"up (\d+)" {$Aim -= $Matches[1]} | |
} | |
Write-Host "$Horizontal * $Depth = $($Horizontal * $Depth)" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[string[]]$Report = @" | |
00100 | |
11110 | |
10110 | |
10111 | |
10101 | |
01111 | |
00111 | |
11100 | |
10000 | |
11001 | |
00010 | |
01010 | |
"@.Split("`n") | |
) | |
function Get-ModeBit { | |
param( | |
[Parameter(Mandatory)] | |
[string[]]$Data, | |
[int]$Bit = 0 | |
) | |
end { | |
$Data.ForEach{$_[$Bit]} | Group-Object | Sort-Object Count -Descending | Select-Object -ExpandProperty Name -First 1 | |
} | |
} | |
function ConvertFromBinaryString { | |
# https://gist.github.com/JPRuskin/2e0f5315f5960d34ff71743a4ade765a#file-aoc_day5-ps1 | |
[CmdletBinding()] | |
param( | |
[Parameter(ValueFromPipeline, Mandatory)] | |
[string]$String, | |
[Parameter()] | |
[char]$On = "1", | |
[Parameter()] | |
[char]$Off = "0" | |
) | |
[Convert]::ToInt32($String.Trim().Replace($On, "a").Replace($Off, "b").Replace("a", "1").Replace("b", "0"), 2) | |
} | |
# Part 1 | |
[string]$ModeBinary = "$(for ($i=0; $i -lt $Report[0].Length; $i++) { | |
Get-ModeBit -Data $Report -Bit $i | |
})".TrimEnd().Replace(' ','') | |
Write-Host "G: $($ModeBinary)" | |
$GammaRate = ConvertFromBinaryString -String $ModeBinary.Replace(' ', '') -On "1" -Off "0" | |
$EpsilonRate = ConvertFromBinaryString -String $ModeBinary.Replace(' ', '') -On "0" -Off "1" | |
Write-Host "$GammaRate * $EpsilonRate = $($GammaRate * $EpsilonRate)" | |
# Part 2 | |
function Get-Rating { | |
param( | |
[string[]]$Data, | |
[switch]$Least # CO2 -> Least | |
) | |
end { | |
$MatchData = $Data | |
$Bit = 0 | |
while ($MatchData.Count -gt 1) { | |
$BitCount = $MatchData.ForEach{$_[$Bit]} | Group-Object | Sort-Object Count -Descending | |
$ModeBit = if ($BitCount[0].Count -eq $BitCount[1].Count) { | |
Write-Verbose "Tie between $($MatchData)!" | |
[int](-not [bool]$Least) # Default in ties | |
} else { | |
$BitCount[[bool]$Least].Name | |
} | |
$MatchData = $MatchData.Where{ | |
$_[$Bit] -eq "$($ModeBit)" | |
} | |
$Bit++ | |
} | |
$MatchData | |
} | |
} | |
Write-Host "O2: $(($O2 = Get-Rating $Report | ConvertFromBinaryString))" | |
Write-Host "CO2: $(($CO2 = Get-Rating $Report -Least | ConvertFromBinaryString))" | |
Write-Host "Life Support = $($O2 * $CO2)" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[int[]]$Numbers = @(7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1), | |
$Boards = (Get-Content -Path $PSScriptRoot\Day4Input.txt -Delimiter " | |
") | |
) | |
Class BingoBoard { | |
[int[]]$Values = @() | |
[int[]]$Marked = @() | |
[int]$Width = 5 | |
[int]$Height = 5 | |
[bool]$Bingo | |
[void]Mark([int[]]$Number) { | |
$this.Marked += $Number | |
} | |
[bool]CheckRow($Number) { | |
$Start = $Number * $this.Width | |
return $false -notin $this.Values[$Start..($Start + $this.Width - 1)].ForEach{$this.Marked -contains $_} | |
} | |
[bool]CheckColumn($Number) { | |
$Column = @($Number) + @(1..$this.Height | ForEach-Object {$Number + ($_ * $this.Width)}) | |
return $false -notin $this.Values[$Column].ForEach{$this.Marked -contains $_} | |
} | |
[bool]CheckWin() { | |
$this.Bingo = $true -in @( | |
0..($this.Width-1) | ForEach-Object {$this.CheckColumn($_)} | |
0..($this.Height-1) | ForEach-Object {$this.CheckRow($_)} | |
) | |
return $this.Bingo | |
} | |
[int]CalculateScore() { | |
return ($this.Values.Where{$_ -notin $this.Marked} | Measure-Object -Sum).Sum | |
} | |
BingoBoard ([string]$Values) { | |
$this.Values = $Values.Split("`n").Split(" ").Trim(" ").Where{$_} | |
} | |
} | |
if ($Boards.Count -gt 1) { | |
[BingoBoard[]]$Boards = $Boards | |
} else { | |
Write-Error "Failed to split the boards." -ErrorAction Stop | |
} | |
# Part 1: Play the game(s) | |
$i = 0 | |
while ($true -notin $Boards.CheckWin()) { | |
$Boards.Mark($Numbers[$i++]) | |
} | |
Write-Host "First Winner Score: $($Boards.Where{$_.Bingo}.CalculateScore() * $Numbers[$i-1])" | |
# Part 2: Continue, to find the last winner | |
while ($Boards.CheckWin().Where{$_ -eq $false}.Count -gt 1) { | |
$Boards.Mark($Numbers[$i++]) | |
} | |
$LastBoard = $Boards.Where{-not $_.Bingo} | |
while (-not $LastBoard.CheckWin()) { | |
$LastBoard.Mark($Numbers[$i++]) | |
} | |
Write-Host "Final Winner Score: $($LastBoard.CalculateScore() * $Numbers[$i-1])" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[string[]]$Vents = (Get-Content $PSScriptRoot\Day5.input) | |
) | |
class Coordinate { | |
[int]$X | |
[int]$Y | |
Coordinate ([string]$Position) { | |
$this.X, $this.Y = $Position.Split(',') | |
} | |
[string] ToString () { | |
return "$($this.X),$($this.Y)" | |
} | |
} | |
class Vent { | |
[Coordinate]$Begin | |
[Coordinate]$End | |
[bool]$StraightLine | |
[Coordinate[]]$Positions = @() | |
[void] GetAllCoordinates () { | |
if ($this.Begin.X -eq $this.End.X -or $this.Begin.Y -eq $this.End.Y) { | |
$this.StraightLine = $true | |
foreach ($X in $this.Begin.X..$this.End.X) { | |
foreach ($Y in $this.Begin.Y..$this.End.Y) { | |
$this.Positions += "$X,$Y" | |
} | |
} | |
} else { | |
$this.StraightLine = $false # $this.Begin.X -eq $this.End.X -or $this.Begin.Y -eq $this.End.Y | |
$Xs = @($this.Begin.X..$this.End.X) | |
$Ys = @($this.Begin.Y..$this.End.Y) | |
$i = 0 | |
$Xs.ForEach{$this.Positions += "$($_),$($Ys[$i++])"} | |
} | |
} | |
Vent ([string]$Definition) { | |
if ($Definition -match "^(?<Begin>\d+,\d+) -> (?<End>\d+,\d+)$") { | |
$this.Begin = $Matches.Begin | |
$this.End = $Matches.End | |
$this.GetAllCoordinates() | |
} else { | |
Write-Warning "'$($Definition)' does not match the expected pattern." | |
} | |
} | |
} | |
$All = [Vent[]]$Vents | |
# Part 1 | |
$IntersectingPoints = $All.Where{$_.StraightLine}.Positions | Group-Object | Where-Object Count -gt 1 | |
Write-Host "There are $($IntersectingPoints.Count) intersections for straight lines." | |
# Part 2 | |
$IntersectingPoints = $All.Positions | Group-Object | Where-Object Count -gt 1 | |
Write-Host "There are $($IntersectingPoints.Count) intersections." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
$InitialState = @(3,4,3,1,2), | |
$Days = 80 # 256 | |
) | |
<# Part 1 | |
foreach ($Day in 1..$Days) { | |
$State = switch ($State ? $State : $InitialState) { | |
0 {6, 8} | |
default {$_-1} | |
} | |
} | |
Write-Host "There are $($State.Count) lanternfish after $($Days) days." | |
#> | |
# Part 2 | |
$FishState = @{ | |
0 = $InitialState.Where{$_ -eq 0}.Count | |
1 = $InitialState.Where{$_ -eq 1}.Count | |
2 = $InitialState.Where{$_ -eq 2}.Count | |
3 = $InitialState.Where{$_ -eq 3}.Count | |
4 = $InitialState.Where{$_ -eq 4}.Count | |
5 = $InitialState.Where{$_ -eq 5}.Count | |
6 = $InitialState.Where{$_ -eq 6}.Count | |
7 = $InitialState.Where{$_ -eq 7}.Count | |
8 = $InitialState.Where{$_ -eq 8}.Count | |
} | |
foreach ($Day in 1..$Days) { | |
$NewState = @{} | |
switch ($FishState.Keys) { | |
0 { | |
$NewState[6] += $FishState[0] | |
$NewState[8] += $FishState[0] | |
} | |
default { | |
$NewState[$_ - 1] += $FishState[$_] | |
} | |
} | |
$FishState = $NewState | |
Write-Progress -Activity "Generating Lanternfish" -CurrentOperation "Day $Day" -PercentComplete ($Day/$Days*100) | |
} | |
Write-Host "There are $(($FishState.Values | Measure-Object -Sum).Sum) lanternfish after $($Days) days." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[int[]]$CrabLocation = @(16, 1, 2, 0, 4, 2, 7, 1, 2, 14) | |
) | |
function Get-TotalCost { | |
param( | |
[Parameter(Mandatory, ValueFromPipeline)] | |
[int[]]$Position, | |
[Parameter(Mandatory)] | |
[int]$Target, | |
[switch]$LinearFuelCost | |
) | |
begin { | |
$Cost = 0 | |
if (-not $script:Map) { | |
$script:Map = @{} | |
} | |
} | |
process { | |
foreach ($Single in $Position) { | |
[int[]]$Objects = $Single, $Target | Sort-Object | |
$Steps = $Objects[1] - $Objects[0] | |
$Cost += if ($LinearFuelCost) { | |
$Steps | |
} else { | |
if (-not $script:Map[$Steps]) { | |
$script:Map[$Steps] = $Steps * ($Steps + 1) / 2 # ($Steps..1 | Measure-Object -Sum).Sum # this worked in all examples but failed in Day2 | |
} | |
$script:Map[$Steps] | |
} | |
} | |
} | |
end { | |
$Cost | |
} | |
} | |
function Get-SecondsRemaining { | |
param( | |
$Percent, | |
[switch]$Reset | |
) | |
if ($Reset -or -not $script:Stopwatch) { | |
$script:Stopwatch = [system.diagnostics.stopwatch]::StartNew() | |
} | |
$script:Stopwatch.Elapsed.TotalSeconds / ($Percent / 100) * (100 - $Percent) / 100 | |
if ($Percent -ge 100) { | |
$script:Stopwatch = $null | |
} | |
} | |
$script:Stopwatch = $null | |
# Part 1 -LinearFuelCost, 2 | |
$SortedList = $CrabLocation | Sort-Object | |
if ($script:LastRun -ne "$($SortedList[0]), $($SortedList[-1]))") { | |
$Range = @{} | |
$script:LastRun = "$($SortedList[0]), $($SortedList[-1]))" | |
} | |
foreach ($Position in $SortedList[0]..$SortedList[-1]) { | |
try { | |
$Percent = $Position / $SortedList[-1] * 100 | |
$Seconds = Get-SecondsRemaining -Percent $Percent | |
Write-Progress -Activity "Contemplating Crab Movement" -Status "Calculating cost for '$Position' (of $($SortedList[-1]))" -PercentComplete $Percent -SecondsRemaining $Seconds | |
} catch {} # If it takes long enough for me to play with this, that's probably a bad sign | |
if (-not $Range[$Position]) { | |
$Range[$Position] = Get-TotalCost -Position $CrabLocation -Target $Position | |
} | |
} | |
$Range = $Range.GetEnumerator | |
Write-Host "The cheapest possible outcome is position $($Range[0].Position) with a cost of $($Range[0].Cost)." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment