https://adventofcode.com/2019/day/17
조기 경보 시스템은 다가오는 태양 플레어를 감지하고 선박의 전자기 차폐막을 자동으로 활성화합니다. 불행하게도 이로 인해 임박한 위험을 인식하지 못한 채 보호막 바깥의 안전하지 않은 외부 발판에 있던 많은 소형 로봇의 와이파이가 차단되었습니다. 그들을 구하려면 빠르게 조치를 취해야 합니다!
사용할 수 있는 유일한 도구는 유선 카메라 몇 대와 현재 충전소에서 충전되고 있는 소형 진공 로봇입니다. 화질은 좋지 않으나, 진공로봇에는 불필요하게 밝은 LED가 있어 장소를 파악하는데는 문제가 없습니다.
Aft Scaffolding Control and Information Interface(ASCII, 퍼즐 입력)인 Intcode 프로그램을 사용하여 카메라와 진공 로봇을 다룰 수 있습니다. 현재 진공 로봇이 잠들어 있기 때문에 카메라에만 접근할 수 있습니다.
Intcode 컴퓨터에서 ASCII 프로그램을 실행하면 현재 보이는 발판들이 제공됩니다. 순전히 우연의 일치로 출력은 아스키 코드로 출력됩니다. 즉, 35
는 #
을 의미하고,46
은 .
을 의미하며, 10
은 현재 라인 아래에서 새로운 라인을 시작하라는 의미입니다. (한 줄 내에서 문자는 왼쪽에서 오른쪽으로 그려집니다.)
카메라 출력에서 #
은 발판을 나타내고 .
은 열린 공간을 나타냅니다. 진공 로봇은 위, 아래, 왼쪽 또는 오른쪽을 향하고 있는지에 따라 각각 ^
, v
, <
또는 >
로 표시됩니다. 이것들을 그릴 때 진공 로봇은 항상 발판 위에 있습니다. 진공 로봇이 발판에서 떨어져 공간을 넘어 제어불가능한 텀블링을 하고있다면, 대신 X
로 표시됩니다.
일반적으로 발판은 경로를 형성하지만 때때로 자신의 위치로 돌아가게 됩니다. 예를 들어 카메라가 다음과 같이 화면을 출력한다고 가정합시다.
..#..........
..#..........
#######...###
#.#...#...#.#
#############
..#...#...#..
..#####...^..
여기에서 진공 로봇은 위(^
)를 향하고 화면의 오른쪽 하단 근처에 있는 발판의 한쪽 끝에 앉아 있습니다. 발판은 계속 올라가며, 여러 번 루프를 돌고, 화면의 왼쪽 상단에서 끝나게 됩니다.
첫 번째 단계는 잘 정의된 일부 지점의 정렬 매개변수를 가져와서 카메라를 보정하는 것입니다. 이는 우선 모든 발판들의 교차점들을 찾습니다. 각 교차점에 대해 정렬 매개변수는 화면의 왼쪽 가장자리와 발판의 왼쪽 사이의 거리에 화면의 위쪽 가장자리와 발판의 위쪽 사이의 거리를 곱한 값입니다. 아래에 위 화면에서 발판들의 교차점을 O
로 표시했습니다.
..#..........
..#..........
##O####...###
#.#...#...#.#
##O###O###O##
..#...#...#..
..#####...^..
여기에는 다음과 같은 교차점들이 있습니다.
- 상단 왼쪽의 교차점은 화면의 왼쪽으로 2개의 발판이, 화면의 위쪽으로 2개의 발판이 있습니다. 그래서 이 교차점의 정렬 파라미터는
2 * 2 = 4
입니다. - 하단 왼쪽의 교차점은 화면의 왼쪽으로 2개의 발판이, 화면의 위쪽으로 4개의 발판이 있습니다. 그래서 이 교차점의 정렬 파라미터는
2 * 4 = 8
입니다. - 하단 중간의 교차점은 화면의 왼쪽으로 6개의 발판이, 화면의 위쪽으로 4개의 발판이 있습니다. 그래서 이 교차점의 정렬 파라미터는
6 * 4 = 24
입니다. - 하단 오른쪽 교차점의 정렬 파라미터는
40
입니다.
카메라를 보정하기 위해, 당신은 정렬 파라미터들의 합을 구해야 합니다. 위 예시에서는 76
입니다.
당신의 ASCII 프로그램을 실행하세요. 발판 교차점들의 정렬 파라미터의 합은 얼마입니까?
이제 까다로운 부분입니다. 다른 모든 로봇에게 태양 플레어에 대해 알려야 합니다. 진공 로봇은 범위에 다른 로봇이 들어오기만 하면, 자동으로 이 작업을 수행할 수 있습니다. 그러나 카메라를 통해서는 다른 로봇을 볼 수 없으므로 대신 확실한 방법을 써야 합니다. 진공 로봇이 모든 발판들을 적어도 한 번은 방문하도록 해야 합니다.
진공 로봇은 보통 무작위로 돌아다니지만, 오늘은 그럴 시간이 없습니다. 당신은 이동 로직을 새로운 규칙으로 재정의해야 합니다.
ASCII 프로그램의 0
번 주소의 값을 1
에서 2
로 변경하여 진공 로봇을 강제로 깨우십시오. 이렇게 하면 진공 로봇이 사용할 새로운 이동 규칙을 묻는 메시지가 자동으로 표시됩니다. ASCII 프로그램은 입력 명령을 사용하여 이를 수신하지만, 아스키 코드로 제공되어야 합니다. 단일 개행을 나타내는 아스키 코드 10
으로 로직의 각 라인을 종료합니다.
먼저 주 이동 루틴을 묻는 메시지가 표시됩니다. 주 루틴은 이동 함수 A
, B
, 또는 C
만 호출할 수 있습니다. 아스키 텍스트로 사용할 이동 함수들을 제공하고, 이는 쉼표(,
, 아스키 코드 44
)로 구분되며, 개행(아스키 코드 10
)으로 끝납니다. 예를 들어, A
를 두 번 호출한 다음 B
와 C
를 세 번 번갈아가며 호출하려면, A,A,B,C,B,C,B,C
문자열을 제공한 다음 개행을 제공하십시오.
그런 다음 각 이동 함수에 대한 프롬프트가 표시됩니다. 이동 함수들은 L
을 사용해 좌회전, R
로 우회전할 수 있으며, 또는 숫자를 사용하여 앞으로 얼마나 이동할 지를 나타냅니다. 이동 함수는 다른 이동 함수를 호출하지 않을 수 있습니다. 또한, 쉼표로 동작을 구분하고 줄 바꿈으로 목록을 끝냅니다. 예를 들어 앞으로 10칸 이동하고, 좌회전한 뒤, 앞으로 9칸 이동하고, 우회전한 뒤, 마지막으로 앞으로 6칸 이동하려면, 문자열 10,L,8,R,6
과 줄바꿈을 제공하며 됩니다.
마지막으로 연속된 비디오 피드를 볼 것인지 묻는 메시지가 나타납니다. y
또는 n
, 개행 문자를 제공하세요. 연속 비디오 피드를 활성화되면 진행 상황을 확인할 수 있지만, 상당한 양의 처리 능력이 필요하고 당신의 Intcode 컴퓨터가 과열될 수도 있습니다.
진공 로봇의 제한된 메모리 양으로 인해, 주 루틴 및 이동 함수의 ASCII 정의들은 줄 바꿈을 제외하면 각각 최대 20자를 포함할 수 있습니다.
예를 들어 다음 카메라 피드를 보겠습니다.
#######...#####
#.....#...#...#
#.....#...#...#
......#...#...#
......#...###.#
......#.....#.#
^########...#.#
......#.#...#.#
......#########
........#...#..
....#########..
....#...#......
....#...#......
....#...#......
....#####......
진공 로봇이 모든 발판을 한 번 이상 방문하기 위해 취할 수 있는 한 가지 경로는 다음과 같습니다.
R,8,R,8,R,4,R,4,R,8,L,6,L,2,R,4,R,4,R,8,R,8,R,8,L,6,L,2
메모리 제한이 없으면, 이 전체 문자열을 함수 A에 제공하고, 주 루틴 호출을 한 번만 수행할 수 있습니다. 그러나 그럴 수 없기 때문에, 더 작게 분할해야 합니다.
그에 대한 접근 방식은 다음과 같습니다.
- 메인 루틴:
A,B,C,B,A,C
(ASCII 입력:65
,44
,66
,44
,67
,44
,66
,44
,65
,44
,67
,10
) - 기능 A:
R,8,R,8
(ASCII 입력:82
,44
,56
,44
,82
,44
,56
,10
) - 기능 B:
R,4,R,4,R,8
(ASCII 입력:82
,44
,52
,44
,82
,44
,52
,44
,82
,44
,56
,10
) - 기능 C:
L,6,L,2
(ASCII 입력:76
,44
,54
,44
,76
,44
,50
,10
)
시각적으로 이것은 원하는 경로를 다음 부분으로 나눕니다.
A, B, C, B, A, C
R,8,R,8, R,4,R,4,R,8, L,6,L,2, R,4,R,4,R,8, R,8,R,8, L,6,L,2
CCCCCCA...BBBBB
C.....A...B...B
C.....A...B...B
......A...B...B
......A...CCC.B
......A.....C.B
^AAAAAAAA...C.B
......A.A...C.B
......AAAAAA#AB
........A...C..
....BBBB#BBBB..
....B...A......
....B...A......
....B...A......
....BBBBA......
물론 실제 배 외부의 발판들은 훨씬 더 복잡합니다.
진공 로봇이 다른 로봇을 찾아 임박한 태양 플레어에 대해 알릴 때, 삐걱거리는 소리를 내며 발견한 모든 우주 먼지를 수집하여 발판을 깨끗이 청소할 수밖에 없습니다. 프로그래밍된 일련의 움직임이 완료되면, 청소 로봇은 도킹 스테이션으로 돌아가 하나의 출력 명령어를 사용해 수집한 우주 먼지의 양을 아스키가 아닌 값으로 출력합니다.
모든 발판을 한 번 이상 방문한 후 진공 로봇이 얼마나 많은 먼지를 모았다고 보고합니까?