Skip to content

Thad writes blogs

this is a lot more work than i expected

Menu
  • About
  • Pin Posts
Menu

Advent of Code in Unreal Engine Day 9

Posted on December 10, 2022December 10, 2022 by Thad

Day 9 of Advent of Code has chain of elements following each other on a grid, and as with Advent of Code in Unreal Engine Day 8 I have stuck with using C++ and a TDD-lite approach, within Unreal.

I start with a single test that matches the example from the puzzle description:

	// Part 1 Example
	
	const TArray< FString > Example = {
		TEXT("R 4"),
		TEXT("U 4"),
		TEXT("L 3"),
		TEXT("D 1"),
		TEXT("R 4"),
		TEXT("D 1"),
		TEXT("L 5"),
		TEXT("R 2")		
	};
	TestEqual(TEXT("Example Tail Visits 13"),
	UAoC22BPFunctionLibrary::D09_Calculate(Example), 13);

My solution (not shown) works and Part 2 is reveled to be the same but with a longer chain. I add the new tests cases for Part 2:

	// Part 2 Tests
	
	TestEqual(TEXT("(Long Rope) Tail Visits 1"),
	UAoC22BPFunctionLibrary::D09_Calculate(Example, 10), 1);
	
	const TArray< FString > LargerExample = {
		TEXT("R 5"),
		TEXT("U 8"),
		TEXT("L 8"),
		TEXT("D 3"),
		TEXT("R 17"),
		TEXT("D 10"),
		TEXT("L 25"),
		TEXT("U 20")	
	};
	TestEqual(TEXT("Larger Example Visits 36"),
	UAoC22BPFunctionLibrary::D09_Calculate(LargerExample, 10), 36);

And then generalize the Part 1 answer from hard-coded 2-element chain, to arbitrary length chains:

int UAoC22BPFunctionLibrary::D09_Calculate(const TArray<FString>& Input, int Len)
{
	ensure(Len>0);
	
	TArray< FVector2d > Rope;
	Rope.AddZeroed(Len);

	TSet< FVector2d > Visited;
	Visited.Add(Rope.Last());
	
	for (const FString& Command : Input)
	{
		FString Left, Right;
		Command.Split(TEXT(" "), &Left, &Right);

		FVector2d Dir;
		if (Left == "U") Dir = {0,1};
		else if (Left == "D") Dir = {0,-1};
		else if (Left == "L") Dir = {1,0};
		else if (Left == "R") Dir = {-1,0};

		int Count = FCString::Atoi(*Right);

		while(Count--)
		{
			Rope[0] += Dir;
			for (int i=1;i!=Rope.Num();++i)
			{
				// check for "not touching"
				const FVector2d TailToHead(Rope[i-1]-Rope[i]);				
				if (TailToHead.SquaredLength()>2)
				{
					if (Rope[i].X < Rope[i-1].X) Rope[i].X++;
					else if (Rope[i].X > Rope[i-1].X) Rope[i].X--;
					if (Rope[i].Y < Rope[i-1].Y) Rope[i].Y++;
					else if (Rope[i].Y > Rope[i-1].Y) Rope[i].Y--;				
				}
			}

			Visited.Add(Rope.Last());
		}
	}
	
	return Visited.Num();
}

It is worth noting that in this code, I am using Unreal’s TSet with a floating-point FVector2d. This is not something I would recommend in production code, and could certainly have put my getting the right answer at risk, due to the problems with floating point equality comparisons, but it worked perfectly, I expect because the only math operations I am doing are ++ and –, and the rope stays within a few hundred units of its origin, and so my vectors are able to store the positions exactly.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Archives

  • October 2024
  • January 2023
  • December 2022
  • November 2022

Categories

  • Food
  • meta
  • Uncategorized
© 2025 Thad writes blogs | Powered by Minimalist Blog WordPress Theme