아직 만들고 있는 페이지입니다.

이 페이지는 아직 만드는 중입니다. 보이는 내용은 바뀔 수 있습니다.

페블링 주행거리계 1

시간 제한1초메모리 제한512 MB

요약
x와 y가 각각 (0,0)과 (0,1)에 놓인 상태에서 x <= y이면 (0,0)에서, 아니면 (0,1)에서 멈추는 오도미터 프로그램을 100개 이하의 명령으로 작성한다.
난이도

보통10점 중 7점

유형
시뮬레이션, 구현, 수학
정답자
아직 제출이 없습니다

문제

Leonardo는 바퀴가 돌아갈 때 조약돌을 떨어뜨려 거리를 측정하는 수레인 최초의 주행거리계를 발명했다. 조약돌의 개수를 세면 바퀴가 돈 횟수를 알 수 있고, 이를 통해 주행거리계가 이동한 거리를 계산할 수 있었다. 우리는 컴퓨터 과학자답게 주행거리계에 소프트웨어 제어를 추가해 기능을 확장했다. 당신의 임무는 아래 규칙에 따라 주행거리계를 프로그래밍하는 것이다.

동작 격자

주행거리계는 256 × 256개의 단위 칸으로 이루어진 가상의 정사각 격자 위에서 움직인다. 각 칸에는 조약돌이 최대 15개까지 들어갈 수 있으며, 각 칸은 좌표 쌍 (행, 열)로 식별되고 각 좌표는 0, …, 255 범위에 있다. 어떤 칸 (i, j)에 대해 인접한 칸은 (존재한다면) (i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)이다. 첫 번째 행이나 마지막 행, 또는 첫 번째 열이나 마지막 열에 있는 칸을 경계라고 한다. 주행거리계는 항상 칸 (0, 0)(북서쪽 모서리)에서 북쪽을 향한 상태로 시작한다.

기본 명령

주행거리계는 다음 명령으로 프로그래밍할 수 있다.

  • left — 왼쪽(반시계 방향)으로 90도 회전하고 현재 칸에 그대로 머문다. 예를 들어 이전에 남쪽을 향하고 있었다면 이 명령 후에는 동쪽을 향한다.
  • right — 오른쪽(시계 방향)으로 90도 회전하고 현재 칸에 그대로 머문다. 예를 들어 이전에 서쪽을 향하고 있었다면 이 명령 후에는 북쪽을 향한다.
  • move — 주행거리계가 향한 방향으로 한 칸 앞으로 이동해 인접한 칸으로 들어간다. 그런 칸이 존재하지 않으면(즉, 그 방향의 경계에 이미 도달했으면) 이 명령은 아무 효과가 없다.
  • get — 현재 칸에서 조약돌 하나를 제거한다. 현재 칸에 조약돌이 없으면 이 명령은 아무 효과가 없다.
  • put — 현재 칸에 조약돌 하나를 추가한다. 현재 칸에 이미 조약돌이 15개 있으면 이 명령은 아무 효과가 없다. 주행거리계의 조약돌은 절대 바닥나지 않는다.
  • halt — 실행을 종료한다.

주행거리계는 프로그램에 주어진 순서대로 명령을 실행한다. 프로그램은 한 줄에 명령을 최대 하나만 포함해야 한다. 빈 줄은 무시된다. 기호 #는 주석을 나타내며, 그 뒤에 줄 끝까지 오는 모든 텍스트는 무시된다. 주행거리계가 프로그램의 끝에 도달하면 실행이 종료된다.

예제 1

주행거리계에 대한 다음 프로그램을 보자. 이 프로그램은 주행거리계를 칸 (0, 2)로 데려가며, 그때 동쪽을 향한다. 첫 번째 move는 주행거리계가 북서쪽 모서리에서 북쪽을 향하고 있으므로 무시된다.

move # no effect
right
# now the odometer is facing east
move
move

레이블, 경계, 조약돌

현재 상태에 따라 프로그램의 흐름을 바꾸려면 레이블을 사용할 수 있다. 레이블은 a, …, z, A, …, Z, 0, …, 9에서 고른 기호로 이루어진, 길이가 최대 128인 대소문자를 구분하는 문자열이다. 레이블과 관련된 새 명령은 아래에 나열되어 있다. 아래 설명에서 L은 유효한 레이블을 나타낸다.

  • L: (즉, L 뒤에 콜론 ‘:’) — 프로그램 내에서 레이블 L의 위치를 선언한다. 선언된 모든 레이블은 서로 달라야 한다. 레이블을 선언하는 것은 주행거리계에 아무 영향을 주지 않는다.
  • jump L — 레이블 L이 있는 줄로 무조건 점프하여 실행을 계속한다.
  • border L — 주행거리계가 격자의 가장자리를 향해 경계 위에 있으면(즉, move 명령이 아무 효과가 없을 것이면) 레이블 L이 있는 줄로 점프하여 실행을 계속한다. 그렇지 않으면 실행은 정상적으로 계속되며 이 명령은 아무 효과가 없다.
  • pebble L — 현재 칸에 조약돌이 하나 이상 있으면 레이블 L이 있는 줄로 점프하여 실행을 계속한다. 그렇지 않으면 실행은 정상적으로 계속되며 이 명령은 아무 효과가 없다.

예제 2

다음 프로그램은 0번 행에서 첫 번째(가장 서쪽) 조약돌을 찾아 그 자리에서 멈춘다. 0번 행에 조약돌이 없으면 행의 끝 경계에서 멈춘다. 두 레이블 leonardo와 davinci를 사용한다.

right
leonardo:
pebble davinci # pebble found
border davinci # end of the row
move
jump leonardo
davinci:
halt

주행거리계는 오른쪽으로 회전하는 것으로 시작한다. 반복문은 레이블 선언 leonardo:로 시작하고 jump leonardo 명령으로 끝난다. 반복문에서 주행거리계는 조약돌의 존재나 행 끝의 경계를 확인한다. 둘 다 아니면 주행거리계는 현재 칸 (0, j)에서 인접한 칸 (0, j + 1)로 move한다. 후자가 존재하기 때문이다. 여기서 halt 명령은 프로그램이 어차피 종료되므로 엄밀히 필요하지는 않다.

위에서 설명한 주행거리계의 자체 언어로 된 프로그램을 제출해야 하며, 그 프로그램은 주행거리계가 기대한 대로 동작하게 해야 한다. 각 하위 과제(아래 참조)는 주행거리계가 수행해야 하는 동작과 제출한 풀이가 만족해야 하는 제약을 명시한다. 제약은 다음 두 가지 사항에 관한 것이다.

  • 프로그램 크기 — 프로그램이 충분히 짧아야 한다. 프로그램의 크기는 프로그램에 있는 명령의 개수이다. 레이블 선언, 주석, 빈 줄은 크기에 포함되지 않는다.
  • 실행 길이 — 프로그램이 충분히 빠르게 종료되어야 한다. 실행 길이는 수행한 단계의 수이다. 명령을 한 번 실행할 때마다, 그 명령이 효과가 있었는지와 무관하게 한 단계로 센다. 레이블 선언, 주석, 빈 줄은 한 단계로 세지 않는다.

예제 1에서 프로그램 크기는 4이고 실행 길이는 4이다. 예제 2에서 프로그램 크기는 6이고, 칸 (0, 10)에 조약돌이 하나 있는 격자에서 실행하면 실행 길이는 43단계이다. right, 각각 4단계(pebble davinci; border davinci; move; jump leonardo)를 수행하는 반복문 10회, 그리고 마지막으로 pebble davinci와 halt이다.

처음에 칸 (0, 0)에는 조약돌이 x개, 칸 (0, 1)에는 y개 있고 다른 모든 칸은 비어 있다. 어떤 칸에도 조약돌이 최대 15개까지만 들어갈 수 있음을 기억하라. x ≤ y이면 주행거리계가 칸 (0, 0)에서 종료되고, 그렇지 않으면 칸 (0, 1)에서 종료되는 프로그램을 작성하라. 종료 시 주행거리계가 향하는 방향은 상관없다. 종료 시 격자에 조약돌이 몇 개 있고 어디에 있는지도 상관없다.

제한

  • 프로그램 크기 ≤ 100
  • 실행 길이 ≤ 1 000

예제1

  1. 예제 1

    입력
    0 0
    
    예상 출력
    right
    loop:
    pebble end0
    get
    move
    pebble end1
    get
    right
    right
    move
    right
    right
    jump loop
    end0:
    halt
    end1:
    halt