In Advent of Code Day 8 we are looking at a grid and comparing the heights of trees in four directions, along the column and row, first to determine visibility, and then to calculate a “scenic score” (how many trees can be seen in each direction).
I am playing catch-up, having missed two days, so this one is going to be kept simple (in C++).
I start this one with some unit tests, one matching the example from the puzzle description, and a few smaller tests to make sure the edge cases are properly handled:
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FAoC2022D08_Test, "AOC.2022.D08", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) bool FAoC2022D08_Test::RunTest(FString const& Parameters) { TArray< FString > OneTree = { TEXT("1"), }; TestEqual(TEXT("One Tree"), UAoC22BPFunctionLibrary::D08_CalculateVisibility(OneTree), 1); TArray< FString > EdgeOnlyCase = { TEXT("33"), TEXT("22"), }; TestEqual(TEXT("Edge Only: 4 Trees"), UAoC22BPFunctionLibrary::D08_CalculateVisibility(EdgeOnlyCase), 4); TArray< FString > Eight = { TEXT("222"), TEXT("222"), TEXT("222"), }; TestEqual(TEXT("3x3, 1 hidden (Eight)"), UAoC22BPFunctionLibrary::D08_CalculateVisibility(Eight), 8); TArray< FString > TestCase = { TEXT("30373"), TEXT("25512"), TEXT("65332"), TEXT("33549"), TEXT("35390") }; TestEqual(TEXT("21"), UAoC22BPFunctionLibrary::D08_CalculateVisibility(TestCase), 21); return true; }
Then the implementation. Given the 99*99 grid, there is not need to try anything complex, this problem can be brute-forced in C++:
int UAoC22BPFunctionLibrary::D08_CalculateVisibility(const TArray<FString>& Input) { const int GridDX = Input.Num(); const int GridDY = Input[0].Len(); int Total = 0; const FIntPoint Scan[] { {1,0}, {-1,0}, {0,1}, {0,-1}, }; for (int X = 0; X!=GridDX; ++X) { ensure(Input[X].Len()==GridDY); for (int Y = 0; Y!=GridDY; ++Y) { const int T = Input[X][Y]; for (int S=0;S!=4;++S) { bool Occluded = false; FIntPoint P2 = {X,Y}; P2 += Scan[S]; // while in bounds and not blocked while(P2.X>=0 && P2.Y>=0 && P2.X<GridDX && P2.Y<GridDY && !Occluded) { if (Input[P2.X][P2.Y] >= T) Occluded = true; P2 += Scan[S]; } if (!Occluded) { Total++; break; } } } } return Total; }
For Part 2 we calculate a “scenic score” for each tree. The example gives us one new unit test:
TestEqual(TEXT("Scenic Score"), UAoC22BPFunctionLibrary::D08_CalculateScenicScore(TestCase), 8);
I copy-pasted Part 1 into a new function and edited it:
int UAoC22BPFunctionLibrary::D08_CalculateScenicScore(const TArray<FString>& Input) { const int GridDX = Input.Num(); const int GridDY = Input[0].Len(); int Total = 0; const FIntPoint Scan[] { {1,0}, {-1,0}, {0,1}, {0,-1}, }; for (int X = 0; X!=GridDX; ++X) { ensure(Input[X].Len()==GridDY); for (int Y = 0; Y!=GridDY; ++Y) { const int T = Input[X][Y]; int Score[4]={0,0,0,0}; for (int S=0;S!=4;++S) { FIntPoint P2 = {X,Y}; P2 += Scan[S]; int TreesSeen = 0; // while in bounds while(P2.X>=0 && P2.Y>=0 && P2.X<GridDX && P2.Y<GridDY) { TreesSeen+=1; if (Input[P2.X][P2.Y] >= T) break; P2 += Scan[S]; } Score[S]=TreesSeen; } const int ScoreCombo = Score[0]*Score[1]*Score[2]*Score[3]; if (ScoreCombo>Total) { Total=ScoreCombo; } } } return Total; }
Which worked first time.
1 thought on “Advent of Code in Unreal Engine Day 8”