§ 14단계 사이클
선인장 솔버는 계절처럼 순환한다. 심고, 기다리고, 정렬하고, 수확한다.
Phase 1 — plant: 모든 타일에 선인장을 심는다. K개 드론이 행을 분담한다.
Phase 2 — wait: 선인장이 다 자랄 때까지 기다린다. can_harvest()가 True가 될 때까지 do_a_flip()으로 시간을 보낸다.
Phase 3 — rows: 각 행을 버블정렬한다. measure()로 크기를 비교하고 swap(East)로 교환한다.
Phase 4 — cols: 각 열을 버블정렬한다. measure() + swap(North).
마지막으로 harvest()로 정렬된 선인장을 수확한다. 그리고 처음부터 다시.
§ 2버블정렬: 행 방향
measure()로 현재 타일의 선인장 크기를 읽고, measure(East)로 오른쪽 타일의 크기를 읽는다. 오른쪽이 더 작으면 swap(East)로 교환한다.
def bubble_row(y):
for j in range(N - 1): # N-1 패스
goto(0, y)
swapped = False
for i in range(N - 1):
cur = measure() # 현재 칸 크기
east_val = measure(East) # 오른쪽 칸 크기
if east_val < cur: # 오름차순 정렬
swap(East) # 인접 교환!
swapped = True
move(East)
if not swapped: # 이미 정렬됨
break
§ 3버블정렬: 열 방향
행 정렬 후 열 정렬을 수행한다. 동일한 버블정렬이지만 방향만 North로 바뀐다. measure(North)로 위쪽 크기를 읽고 swap(North)로 교환한다.
measure() — 현재 타일 엔티티의 크기(선인장) 또는 꽃잎 수(해바라기)를 반환
measure(East) — 인접 타일의 크기를 읽음. 방향 인자 사용
swap(East) — 현재 타일과 인접 타일의 엔티티를 교환. 물리적 이동이 아닌 데이터 교환!
§ 4왜 두 번 정렬해야 하는가
행만 정렬하면 각 행 내에서는 정렬되지만, 행 간에는 무질서하다. 열 정렬까지 해야 전체 격자가 정렬된다.
이것은 "행 정렬 → 열 정렬"이 1D 정렬 두 번으로 2D 정렬을 근사하는 기법이다. 완벽한 2D 정렬을 보장하려면 추가 패스가 필요할 수 있지만, 게임에서는 행+열 두 패스로 충분하다.
§ 5실전 코드: f_cactus.py
실제 게임에서 돌아가는 f_cactus.py는 클로저 팩토리 대신 체인 워커를 사용하여 더 간결하게 구현되어 있다. _phase 리스트로 현재 단계를 공유하고, _spawn_i로 드론 인덱스를 분배한다.
go0()
while True:
run_phase("plant") # 모든 타일에 심기
run_phase("wait") # 성장 대기
run_phase("rows") # 행 버블정렬
run_phase("cols") # 열 버블정렬
goto(0, 0)
harvest() # 정렬된 선인장 수확!