Advent of Code Day 7 풀이: 타키온 빔 분할
Source: Dev.to
원래 이 글은 제 블로그에 올렸습니다.
올해는 Advent of Code를 따라가고 있습니다. 저는 스스로에게 “functionalish” 솔루션을 작성하도록 도전했습니다. 제가 가장 좋아한 퍼즐 중 하나를 소개합니다.
Advent of Code의 Day 7에서, 우리는 텔레포터에 갇힌 채로 타키온 빔을 연구하고 있습니다.
우리는 모든 크리스마스 준비를 돕기 위해 엘프들을 도우려다 텔레포터에 갇혔습니다. 하지만 매 단계마다 상황이 더 복잡해져서 불가능한 임무가 되었습니다. 마치 The Mandalorian의 한 에피소드에 나오는 느낌이죠. 어쨌든, 코드를 다시 보겠습니다…
저는 이 퍼즐을 매 반복마다 빔을 이동시켜 매니폴드의 끝에 닿을 때까지 진행되는 게임으로 상상합니다.
빔 이동
Beam은 주어진 반복 단계에서 매니폴드 안에 있는 위치들의 리스트입니다.
record Position(int X, int Y);
record Beam(IEnumerable<Location> Locations);
매니폴드는 문자열의 2차원 배열입니다. 각 셀은 빈 공간이거나 스플리터일 수 있습니다. 예시:
var manifold = new string[][]
{
new[] { ".", ".", "S", ".", "." },
new[] { ".", ".", ".", ".", "." },
new[] { ".", ".", "^", ".", "." },
new[] { ".", ".", ".", ".", "." }
};
빔을 이동시키는 메서드
static Beam Move(string[][] manifold, Beam beam)
{
var newLocations = new HashSet<Position>();
foreach (var current in beam.Locations)
{
var downward = manifold[current.X + 1][current.Y];
if (downward == ".")
{
newLocations.Add(new Position(current.X + 1, current.Y));
}
else if (downward == "^")
{
// split the beam left and right
newLocations.Add(new Position(current.X + 1, current.Y - 1));
newLocations.Add(new Position(current.X + 1, current.Y + 1));
}
}
return new Beam(newLocations);
}
시작 위치 찾기
static Beam Start(string[][] manifold)
{
for (int i = 0; i ());
}
위 두 메서드를 사용하면 빔을 생성하고 아래쪽으로 이동시킬 수 있습니다:
var start = Start(manifold);
var newPosition = Move(manifold, start);
newPosition = Move(manifold, newPosition);
이제 남은 일은 스플릿 횟수를 세고 빔을 끝까지 이동시키는 것입니다.
Counting splits
우리는 빔이 자체적으로 움직여서 매니폴드의 바닥에 도달할 때까지 진행시킵니다:
var beam = Start(manifold);
while (!HasReachedTheEnd(manifold, beam))
{
beam = Move(manifold, beam);
}
다음 단계는 빔이 갈라지는 순간을 세는 것입니다. 이를 Move() 안에서 수행합니다.
Full solution (sample input is hard‑coded)
var manifold = new string[][]
{
new[] { ".", ".", ".", ".", ".", ".", ".", "S", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", "^", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", "^", ".", "^", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", "^", ".", "^", ".", "^", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", "^", ".", "^", ".", ".", ".", "^", ".", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", ".", "^", ".", "^", ".", ".", ".", "^", ".", "^", ".", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", ".", "^", ".", ".", ".", "^", ".", ".", ".", ".", ".", "^", ".", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." },
new[] { ".", "^", ".", "^", ".", "^", ".", "^", ".", "^", ".", ".", ".", "^", "." },
new[] { ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", ".", "." }
};
var beam = Start(manifold);
while (!HasReachedTheEnd(manifold, beam))
{
beam = Move(manifold, beam);
}
Console.WriteLine(beam.SplitCount);
Console.ReadLine();
static Beam Start(string[][] manifold)
{
for (int i = 0; i ());
}
static bool HasReachedTheEnd(string[][] manifold, Beam beam)
{
var anyBeam = beam.Locations.First();
return anyBeam.X >= manifold.Length - 1;
}
static Beam Move(string[][] manifold, Beam beam)
{
var splits = 0;
var newLocations = new HashSet<Position>();
foreach (var current in beam.Locations)
{
var downward = manifold[current.X + 1][current.Y];
if (downward == ".")
{
newLocations.Add(new Position(current.X + 1, current.Y));
}
else if (downward == "^")
{
splits++;
newLocations.Add(new Position(current.X + 1, current.Y - 1));
newLocations.Add(new Position(current.X + 1, current.Y + 1));
}
}
return new Beam(beam.SplitCount + splits, newLocations);
}
record Position(int X, int Y);
record Beam(int SplitCount, IEnumerable<Position> Locations);
나는 “타키온”이란 단어가 만들어낸 말이라고 생각했는데 구글링을 해보니 실제 존재한다는 것을 알게 되었습니다. 타키온이 정확히 무엇인지 이제 알게 되었네요.
A tachyon is. Win‑win.
Et voilà!
Advent of Code sharpens your coding skills. But coding is more than typing symbols fast. It's also about teamwork, collaboration, and many skills I share in my book, *Street‑Smart Coding: 30 Ways to Get Better at Coding.* That's the roadmap I wish I'd known from day one.
**[Get your copy of Street‑Smart Coding here](https://imcsarag.gumroad.com/l/streetsmartcoding/?utm_source=devto&utm_medium=post&utm_campaign=advent-2025-7)**