해결: PowerShell로 Advent of Code 하는 사람?

발행: (2026년 1월 1일 오전 07:26 GMT+9)
11 min read
원문: Dev.to

Source: Dev.to

죄송합니다만, 해당 URL에 있는 전체 글 내용을 직접 가져올 수 없습니다. 번역이 필요한 텍스트를 여기 채팅창에 복사해 주시면, 요청하신 대로 한국어로 번역해 드리겠습니다.

Executive Summary

TL;DR: PowerShell에서 Advent of Code (AoC)를 해결하는 것은 입력 파싱이 장황하고 복잡한 알고리즘에서 성능 병목이 발생하는 등 여러 어려움이 있습니다.
해결 방안은:

  • 관용적인 PowerShell 파이프라인 및 .NET 통합 활용.
  • 핵심 부분에 C# 인터옵을 사용해 속도 향상.
  • 외부 고성능 유틸리티를 오케스트레이션.

왜 관용적인 PowerShell을 사용해야 할까?

  • 객체‑지향 파이프라인 – cmdlet을 연결하고, 객체를 전달하며, 코드를 읽기 쉽게 유지합니다.
  • 내장 cmdlet – 강력한 문자열 조작, 정규식, 파일 처리 기능을 제공합니다.
  • 직접 .NET 호출 – cmdlet만으로는 부족할 때 언제든지 .NET 타입에 접근할 수 있습니다.

많은 AoC 퍼즐에서 이 접근 방식은 자연스럽고, 읽기 쉬우며, 충분합니다.

PowerShell이 성능 장벽에 부딪힐 때

  • 대용량 데이터 세트, 깊은 재귀, 혹은 집중적인 시뮬레이션은 PowerShell 스크립트가 초가 아니라 분 단위로 실행되게 만들 수 있습니다.
  • 고급 데이터 구조(우선순위 큐, 사용자 정의 그래프, 불변 컬렉션)는 순수 PowerShell에서 효율적으로 구현하기 번거롭습니다.
  • 알고리즘 기본 요소 부족 – PowerShell은 Python이나 C#에서 제공되는 풍부한 표준‑라이브러리 도구가 없습니다.

해결책: C# interop(Add-Type)을 사용해 핵심 경로 코드를 구현한 뒤, PowerShell에서 컴파일된 클래스를 호출합니다.

외부 도구 오케스트레이션

PowerShell는 “접착제” 역할을 하며:

  1. 입력을 준비합니다.
  2. 외부의 고성능 바이너리(e.g., grep, custom C/C++ tools)를 실행합니다.
  3. 출력물을 PowerShell 객체로 다시 처리합니다.

실용적인 PowerShell 패턴

1. 구분된 입력 파일에서 숫자 합산

input.txt

10,20,30
15,25,35
# Read each line, split by comma, convert to integer, and sum
$totalSum = Get-Content -Path 'input.txt' |
    ForEach-Object { $_ -split ',' } |
    ForEach-Object { [int]$_ } |
    Measure-Object -Sum |
    Select-Object -ExpandProperty Sum

Write-Host "Total Sum: $totalSum"

2. 그리드 / 매트릭스 작업

grid.txt (example)

#.##
.#.#
##.#
# Load the grid as an array of character arrays
$grid = Get-Content -Path 'grid.txt' | ForEach-Object { $_.ToCharArray() }

# Access an element (row 1, column 2)
Write-Host "Element at (1,2): $($grid[1][2])"

# Iterate through the grid
for ($row = 0; $row -lt $grid.Length; $row++) {
    for ($col = 0; $col -lt $grid[$row].Length; $col++) {
        Write-Host "($row,$col) = $($grid[$row][$col])"
    }
}

3. 성능 및 유연성을 위한 .NET 컬렉션 사용

# Mutable generic List[int]
$myList = [System.Collections.Generic.List[int]]::new()
$myList.Add(10)
$myList.Add(20)
$myList.Add(30)

Write-Host "List count: $($myList.Count)"
$myList.Remove(20)
Write-Host "List after removal: $($myList -join ', ')"

# Dictionary (hashtable in PowerShell)
$myDictionary = @{}
$myDictionary["apple"]  = 1
$myDictionary["banana"] = 2

Write-Host "Value for apple: $($myDictionary["apple"])"

C# 인터롭 for Hot‑Path 코드

When “idiomatic PowerShell” isn’t fast enough, embed C# directly:

Add-Type @"
using System;
using System.Collections.Generic;

public static class AoCHelper {
    // Example: fast sum of an int array
    public static long FastSum(int[] numbers) {
        long sum = 0;
        foreach (int n in numbers) sum += n;
        return sum;
    }

    // Add more performance‑critical methods here
}
"@

# Use the compiled class from PowerShell
$numbers = 1..1_000_000
$sum = [AoCHelper]::FastSum($numbers)
Write-Host "Fast sum = $sum"

성능이 중요한 알고리즘을 C#로 작성하고 Add-Type으로 컴파일한 뒤, 일반 PowerShell 메서드처럼 호출합니다.

Source:

모두 합쳐 보기

  1. 시작 – 구문 분석 및 오케스트레이션을 위해 관용적인 PowerShell을 사용합니다.
  2. 병목 현상 식별Measure-Command 또는 프로파일링을 활용합니다.
  3. 핫‑패스 섹션 교체 – C# 인터옵 또는 외부 도구로 대체합니다.
  4. 스크립트 가독성 및 유지보수성 유지 – 인터옵 노출을 최소화합니다.

최종 생각

  • Advent of Code는 PowerShell의 강점과 한계를 탐구하기에 훌륭한 놀이터입니다.
  • 파이프라인 중심 스크립팅, .NET 파워, C# 인터옵, 그리고 외부 유틸리티를 결합하면 가장 까다로운 AoC 퍼즐도 효율적으로 해결하면서 PowerShell이 뛰어난 자동화 언어가 되는 명료성을 유지할 수 있습니다.

C#에서 빠른 피보나치 수열 계산

우리는 정적 메서드를 사용하여 N번째 피보나치 수를 빠르게 계산하는 C# 클래스를 정의할 것입니다.

$cSharpCode = @'
using System;

public static class FibonacciCalculator
{
    public static long GetNthFibonacci(int n)
    {
        if (n  left.Equals(right);
    public static bool operator !=(Point left, Point right) => !(left == right);
}
'@

Add-Type -TypeDefinition $cSharpCode -Language CSharp

# Create and use Point structs
$p1 = New-Object Point(10, 20)
$p2 = New-Object Point(10, 20)
$p3 = New-Object Point(5, 5)

Write-Host "Point 1: $p1"
Write-Host "Point 2: $p2"
Write-Host "Point 3: $p3"

if ($p1 -eq $p2) { Write-Host "P1 and P2 are equal." }
if ($p1 -ne $p3) { Write-Host "P1 and P3 are not equal." }

외부 도구 활용

특정 하위 문제에 가장 효율적인 해결책이 PowerShell이나 C#로 직접 구현하는 것이 아니라, 이미 존재하고 고도로 최적화된 외부 도구를 호출하는 경우가 있습니다. PowerShell은 이러한 도구들을 조정하고, 데이터 흐름을 연결하며, 결과를 통합하는 데 뛰어납니다.

예시: 고급 패턴 매칭을 위한 WSL grep 사용

# Assume input.txt contains:
# This is a test line.
# Another line with the word test.
# No match here.

# Find all lines containing "test"
$matchedLines = wsl.exe grep "test" "input.txt"

Write-Host "Lines containing 'test':"
$matchedLines | ForEach-Object { Write-Host $_ }

예시: 사용자 정의 컴파일 실행 파일 호출

# Create a dummy input file for the external tool
Set-Content -Path 'puzzle_map.txt' -Value @'
###########
#S........#
###.......#
#.........#
#.......E.#
###########
'@

# Run the external pathfinder.exe (takes a file path and returns the shortest path length)
$pathResult = & ".\pathfinder.exe" "puzzle_map.txt"

Write-Host "Pathfinder result: $pathResult"

# If the external tool outputs JSON, you can parse it:
# $jsonResult = & ".\myparser.exe" "data.json" | ConvertFrom-Json
# $value = $jsonResult.SomeProperty

예시: 외부 도구와 데이터 파이프라인 연결

PowerShell 파이프라인은 외부 프로세스와 상호 작용하여 데이터를 표준 입력으로 전달하고 표준 출력을 캡처할 수 있습니다.

# Simulate an external tool that counts characters (e.g., `wc -c` on Linux)
# For Windows we’ll use a simple Python script (counter.py):
#   import sys
#   print(sum(len(line) for line in sys.stdin))

$dataToSend = @(
    "Line 1"
    "Another Line"
    "Last One"
)

# Pipe data to the Python script and capture its output
# Ensure python.exe is in your PATH or specify its full path
$charCount = $dataToSend | python.exe - ".\counter.py"

Write-Host "Total characters (excluding newlines): $charCount"

올바른 접근 방식 선택

기능 / 접근 방식순수 PowerShell (관용적)C# 인터옵 (Add-Type)외부 도구 오케스트레이션
가독성 및 유지보수성높음 (PowerShell 사용자에게)중간‑낮음 (PowerShell과 C# 혼합)중간 (PowerShell이 오케스트레이션; 외부 로직은 불투명)
성능중간‑낮음 (인터프리터, 객체 오버헤드)높음 (컴파일된 C#가 네이티브 속도로 실행)매우 높음 (고도로 최적화된 외부 바이너리 활용)

적절한 방법 선택은 특정 Advent of Code 퍼즐, 사용자의 편안함 수준, 그리고 성능 요구 사항에 따라 달라집니다. PowerShell을 접착제로 사용하고, C#를 핵심 경로 계산에 활용하며, 외부 유틸리티가 명확한 이점을 제공할 때 이를 이용하십시오.

개발 노력

  • Low to Medium – 익숙한 언어, 빠른 프로토타이핑.
  • Medium to High – C# 지식이 필요하고, 디버깅을 분할할 수 있음.
  • Medium – 외부 도구 API와 입출력 이해가 필요함.

복잡도 처리

  • 대부분의 텍스트 처리, 데이터 조작, 단순 알고리즘에 적합합니다.
  • 복잡한 알고리즘, 맞춤형 데이터 구조, 성능이 중요한 로직에 탁월합니다.
  • 기존 도구가 완벽히 맞는 특정 하위 문제에 탁월합니다.

AoC 적합성

  • 대다수 퍼즐, 특히 Part 1에 대한 기본 선택.
  • Part 1 솔루션이 너무 느린 경우 Part 2에 이상적.
  • 특정 문제에 특화된 틈새(예: 복잡한 정규식, 도구가 존재한다면 특정 그래프 알고리즘).

디버깅 경험

  • Excellent PowerShell ISE/VS Code 내에서 우수.
  • Mixed – 스크립트용 PowerShell 디버거, PowerShell 내에서 C# 로직은 종종 불투명.
  • Mixed – 오케스트레이션용 PowerShell 디버거, 외부 도구 디버깅은 별도.

👉 원문 기사를 읽어보세요 TechResolve.blog

Back to Blog

관련 글

더 보기 »

C# Smart Enums: 고급

C Smart Enums: advanced의 표지 이미지 https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-upload...

C# 스마트 Enum: 최적화

문제: “LINQ 세금” 파트 1에서는 매직 넘버를 레코드로 교체했습니다. 특정 상태를 찾기 위해 LINQ를 사용했습니다: csharp var status = Status.All.SingleOrDe...