Skip to content

Latest commit

 

History

History

day2

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

Day 2: 1202 프로그램 알람 (1202 Program Alarm)

https://adventofcode.com/2019/day/2

Part 1

달에서 스윙바이를 하려고 이동하던 중, 우주선의 컴퓨터가 "1202 Program Alarm"을 띄우며 시끄럽게 울리기 시작합니다. 무전을 통해 한 요정이 상황을 설명해주었습니다. "걱정마세요. 모든 것이 정상입..." 그 순간, 컴퓨터가 폭주하기 시작합니다.

당신은 요정들에게 컴퓨터에서 수상한 연기가 나고 있다는 사실을 알려줍니다. "그 컴퓨터는 중력 보조 프로그램과 같은 **정수 프로그램(IntCode Program)**를 실행하던 컴퓨터였어요. 새로운 정수 컴퓨터를 만들 여분 부품이 충분히 있을 거에요.

정수 프로그램은 쉼표로 구분된 정수의 리스트입니다. (1,0,0,3,99처럼요) 이를 실행하려면, 우선 리스트의 첫번재 정수를 보면 됩니다.(0번 위치(position)라고 부릅시다.) 이 값은 **연산 코드(opcode)**이며, 1, 2 또는 99 중 하나입니다. 이 연산코드는 무엇을 해야할지 나타냅니다. 예를들어 99는 프로그램이 완료되었고 즉시 종료되어야 한다는 뜻입니다. 그 이외의 코드가 들어온다면, 무언가 잘못되고 있다는 것입니다.

연산 코드 1은 두 개의 위치로부터 값을 읽어들여 그것을 서로 더한 뒤, 세 번째 위치에 저장합니다. 연산 코드 뒤에 바로 이어지는 세 개의 숫자가 그 위치를 나타냅니다. 첫 번째와 두 번째 값이 읽어들일 값이 있는 위치를, 세 번째 값이 저장할 장소의 위치를 나타냅니다.

예를 들어 정수 프로그램이 1,10,20,30을 만나면, 10번째 위치와 20번째 위치에서 값을 읽어들여, 그 값들을 더하고, 30번째 위치에 그 결과를 저장합니다.

연산 코드 2는 연산 코드 1과 똑같이 동작하지만, 더하는 대신 두 숫자를 곱합니다. 다시 한번 강조하지만, 연산 코드 뒤의 숫자들은 값이 아니라 값이 어디에 있는지를 나타냅니다.

한 연산 코드에 대한 처리를 끝내면, 4개의 숫자를 건너뛰어 다음 명령어를 실행하면 됩니다.

예를 들어, 다음과 같은 프로그램이 있다고 해봅시다.

1,9,10,3,2,3,11,0,99,30,40,50

알기 쉽게 여러 줄로 나누어 보겠습니다.

1,9,10,3,
2,3,11,0,
99,
30,40,50

처음 네 숫자(1,9,10,3)의 위치는 차례대로 0, 1, 2, 3 입니다. 그리고 차례대로 첫 번째 연산코드(1), 입력 값의 위치(9, 10), 더한 값을 저장할 위치(3)을 나타냅니다. 9번째 위치에 있는 숫자는 30이고 10번째 위치에 있는 숫자는 40이므로, 이를 더하면 70이 됩니다. 이 값을 3번째 위치에 저장하면 프로그램은 다음과 같아집니다.

1,9,10,70,
2,3,11,0,
99,
30,40,50

이후 네 칸을 이동하면 다음 연산 코드인 2에 도달할 수 있습니다. 덧셈 대신 곱셈을 하는 것만 다르고, 나머지는 똑같습니다. 곱할 값은 3번째와 11번째 위치에 있으므로, 입력 값은 70과 50입니다. 곱한 결과인 3500은 0번째 위치에 저장됩니다.

3500,9,10,70,
2,3,11,0,
99,
30,40,50

네 칸을 더 이동하면 99가 나오므로, 프로그램이 종료됩니다.

다음은 몇 가지 작은 프로그램들의 초기 값과 최종 값입니다.

  • 1,0,0,0,992,0,0,0,99가 됩니다. (1 + 1 = 2)
  • 2,3,0,3,992,3,0,6,99가 됩니다. (3 * 2 = 6)
  • 2,4,4,5,99,02,4,4,5,99,9801가 됩니다. (99 * 99 = 9801)
  • 1,1,1,4,99,5,6,0,9930,1,1,4,2,5,6,0,99가 됩니다.

정상 동작하는 컴퓨터를 만들고나서, 처음 해야할 일은 중력 보조 프로그램(퍼즐 입력)을 컴퓨터에 불이 나기 전 상태인 "1202 프로그램 알람" 상태로 복원하는 것입니다. 이걸 하기위해, 프로그램을 실행하기 전에, 1번째 위치의 값을 12로 바꾸고, 2번째 위치의 값을 2로 바꿔주어야 합니다. 이후 프로그램이 종료된 뒤, 0번 위치에는 어떤 값이 들어가있습니까?

Part 2

"좋아요, 새 컴퓨터는 잘 동작하는 것 같네요. 아마 다음에도 이걸 쓸 일이 있을테니, 소중히 다루어 주세요. 원래 정수 컴퓨터는 방금 당신이 만든 것보다 더 많은 기능을 지원하지만, 그건 필요할 때 다시 알려드릴게요."

"지금은 스윙바이를 하는 것에 집중하도록 하죠. 그러려면 우선 방금 만든 것에 대한 몇 가지 용어들을 정리해야할 것 같네요."

정수 프로그램은 정수들의 리스트로 주어지고, 그 값들은 컴퓨터 메모리의 초기 값으로 사용됩니다. 정수 프로그램을 실행하면, 메모리의 초기 값를 프로그램으로 세팅해야 합니다. 메모리상 위치(position)는 주소 혹은 번지(address)라고 부릅시다. 예를들어 메모리의 첫번째 값은 "0번지(address 0)"입니다.

연산 코드(1, 2, 99)는 각 명령어(instruction)의 시작을 나타냅니다. 연산 코드 뒤에 있는 숫자들은 명령어의 파라미터(parameters)라고 합니다. 예를 들어 명령어 1,2,3,4의 경우, 1은 연산 코드, 2, 3, 4는 파라미터입니다. 명령어 99는 연산 코드만을 가지고 파라미터는 가지지 않습니다.

현재 실행 중인 명령어의 주소를 명령 포인터(instruction pointer)라고 하고, 이는 0부터 시작합니다. 한 명령어의 실행이 끝나면, 명령 포인터의 값은 명령어의 값들의 개수만큼 증가합니다. 정수 컴퓨터에 다른 명령어가 추가되기 전까진 이 값은 항상 4입니다. (종료 명령어는 명령 포인터를 1만큼 증가시키겠지만, 그 대신 프로그램을 즉시 종료시킵니다.)

"이렇게 용어를 정리했으니 더 나아갈 수 있겠네요. 스윙바이를 성공시키기 위해서는, 프로그램이 19690720이라는 출력을 내는 입력값을 찾아야 합니다."

방금 전에 했던 것처럼, 입력 값은 프로그램의 1번지와 2번지의 값으로 주어집니다. 이 프로그램에서는 1번지의 값을 명사, 2번지의 값을 동사라고 합시다. 각 입력 값은 0이상 99이하의 값 중 하나입니다.

프로그램이 종료되면, 출력 값은 방금 전처럼 0번지의 값이 됩니다. 각 입력 값에 대해 프로그램을 실행한 후에는, 컴퓨터의 메모리를 초기값(퍼즐 입력)으로 다시 세팅해야 한다는 것을 잊지마세요. 달리 말하면, 이정 시도의 메모리를 재사용해서는 안됩니다.

19690720이라는 출력을 만드는 명사와 동사의 입력 값을 찾으세요. 그 후, 100 * 명사 + 동사의 값을 알려주세요. (예를 들어, 명사가 12, 동사가 2라면 정답은 1202입니다.)