Day 06 of Advent of Code, and after yesterdays Blueprints it’s time for a C++ palate cleanser with a side order of Unit Testing.
The problem consists of sub-string character uniqueness checking. I appreciate that this solution can be optimized but it is fast enough for the size of the puzzle input so it’ll do.
// added to AoC22BPFunctionLibrary.h // Find the fist location in the string where the preceding L characters are not repeated UFUNCTION(BlueprintCallable) static int FindStartOfPackerMarker(const FString& Input, int L=4); // added to AoC22BPFunctionLibrary.cpp bool UniqueInSpan(int c, int a, int b, const FString& Input) { for(int i=a;i!=b;++i) if (Input[i]==c) return false; return true; } int UAoC22BPFunctionLibrary::FindStartOfPackerMarker(const FString& Input, int L) { const int e = Input.Len() - L; for (int i=0;i!=e;++i) { bool NonUnique = false; for (int j=0;j!=L;++j) { if (!UniqueInSpan(Input[i+j],i+j+1,i+L, Input)) { NonUnique = true; break; } } if (NonUnique) continue; return i+L; } return -1; }
This is simple function solves the problem and is fast to just call directly from the blueprint (see header image), so lets now take a moment to look at some Unit Testing:
// in a new file, AoC2022D05_Test.cpp #include "Misc/AutomationTest.h" #include "AoC22BPFunctionLibrary.h" // // The very simplest C++ Unit test that can be run by the UE Session Frontend / Automation tab // See: https://docs.unrealengine.com/4.27/en-US/TestingAndOptimization/Automation/TechnicalGuide/ // IMPLEMENT_SIMPLE_AUTOMATION_TEST(FAoC2022D05_Test, "AOC.2022.D05", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) bool FAoC2022D05_Test::RunTest(FString const& Parameters) { // PART 1 TestEqual(TEXT("bvwbjplbgvbhsrlpgdmjqwftvncz: first marker after character 5"), UAoC22BPFunctionLibrary::FindStartOfPackerMarker(TEXT("bvwbjplbgvbhsrlpgdmjqwftvncz")), 5); // (the next three test cases have been removed for brevity) // PART 2 TestEqual(TEXT("mjqjpqmgbljsphdztnvjfqwrcgsmlb: first marker after character 19"), UAoC22BPFunctionLibrary::FindStartOfPackerMarker(TEXT("mjqjpqmgbljsphdztnvjfqwrcgsmlb"), 14), 19); // (the next four test cases have been removed for brevity) // return TRUE if the test passes // note: the test as a whole still fails if the "Test" macros failed return true; }
In Rider I can now right-click on the source file and Run Unit Test:
And this compiles and runs and I get results direct in the IDE:
If you are not fortunate enough to have access to a Rider license (you need the pro/ultimate edition for this tight Unreal integration), then the tests can be run from the Editor -> Session Front End -> Automation. If the Session Front End tab isn’t open by default (it was for me but this seems to be new in 5.1), you can find it under the Tools menu.
I will likely use this more over the remaining days, as the problems get harder. A TDD workflow is a great fit for Advent of Code.