익스텐트와 디스크 조각 모음

면접 대비

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

요약
디스크 블록 위에서 RADDD의 2단계 조각 모음 패스를 시뮬레이션하고 각 파일의 최종 익스텐트 배치를 출력한다.
난이도

보통10점 중 5점

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

문제

현대 파일 시스템은 파일을 항상 연속된 위치에 저장하지는 않는다. 대신 파일을 익스텐트(extent) 라고 부르는 조각으로 나누며, 각 익스텐트는 디스크 위 거의 아무 곳에나 놓일 수 있다. 하나의 익스텐트는 물리 디스크의 단위인 블록(block) 한 개 이상을 연속으로 차지한다. 서로 다른 파일은 블록이나 익스텐트를 절대 공유하지 않으며, 사용되지 않는 빈 블록이 남아 있을 수 있다.

이렇게 파일 데이터가 흩어져 있으면, 파일의 모든 블록이 순서대로 붙어 있어 하나의 익스텐트를 이룰 때보다 접근이 느려진다. 그래서 많은 파일 시스템은 조각 모음(defragmentation), 즉 각 파일의 블록이 순서대로 이어지도록 파일을 재배치하는 기능을 지원한다.

RAD's Awesome Dynamic Filesystem(줄여서 RADfs)에서 파일은 몇 개의 익스텐트든 차지할 수 있고, 각 익스텐트는 반드시 서로 붙어 있는 블록 두 개 이상으로 이루어진다. 익스텐트의 첫 블록은 그 익스텐트에 대한 메타데이터를 담고, 나머지 블록은 파일 데이터의 일부를 담는다. 예를 들면:

RADfs.doc: 37-38,102-114,23-47

여기서 RADfs.doc는 디스크에서 40개의 블록을 차지한다(2+13+252 + 13 + 25). 하지만 파일 자체의 데이터는 37블록뿐이다(익스텐트마다 메타데이터 블록이 하나씩 들어가므로 40−3=3740 - 3 = 37). 이 파일이 가질 수 있는 가장 작은 디스크 점유 크기는 38블록(데이터 37블록 + 메타데이터 1블록)이며, 이는 파일 전체가 하나의 익스텐트에 담길 때에만 가능하다. 예를 들면:

RADfs.doc: 115-152

이제 메타데이터 블록(115) 뒤로 37개의 데이터 블록이 하나의 익스텐트에 이어진다.

RADfs 팀은 RADical Defragmentation Daemon(줄여서 RADDD) 도 만들었다. 여유 공간이 충분하다면, 간단한 두 단계 알고리즘만으로도 파일이 차지하는 익스텐트 수를 크게 줄인다.

RADDD의 한 번의 패스(pass) 는 다음과 같이 동작한다.

1단계("뒤로 보내기"). 이번 패스의 이 단계에서 아직 처리되지 않은 모든 파일을, 현재 차지한 첫 블록 번호의 오름차순으로 처리한다.

  • 파일과 메타데이터 블록 하나를 함께 담을 수 있을 만큼 큰, 즉 (데이터 블록 수)+1(\text{데이터 블록 수}) + 1개의 연속된 빈 블록으로 이루어진 구간 중 디스크 끝에 가장 가까운 것을 찾는다.
  • 그런 구간이 있으면, 파일을 디스크 끝에 최대한 가깝게 붙여 그 블록들로 옮기고, 원래 블록을 빈 것으로 표시한다.
  • 없으면 파일을 그대로 둔다.

2단계("앞으로 보내기"). 이번 패스의 이 단계에서 아직 처리되지 않은 모든 파일을, 현재 차지한 마지막 블록 번호의 내림차순으로 처리한다.

  • 파일과 메타데이터 블록 하나를 함께 담을 수 있을 만큼 큰 연속된 빈 블록 구간 중 디스크 처음에 가장 가까운 것을 찾는다.
  • 그런 구간이 있으면, 파일을 디스크 처음에 최대한 가깝게 붙여 그 블록들로 옮기고, 원래 블록을 빈 것으로 표시한다.
  • 없으면 파일을 그대로 둔다.

파일을 옮기는 동안에는, 옮겨지는 그 파일이 현재 차지하고 있는 블록도 빈 블록으로 간주한다. 한 번의 패스가 끝나면 일부 파일은 하나의 익스텐트로 줄어들 수 있고, 패스를 더 실행하면 디스크를 더욱 정리할 수 있다.

한편 사용 중이라서 옮길 수 없는 파일도 있다. 이런 파일은 이동 불가(immobile) 로 표시되며 RADDD가 아예 건드리지 않는다. 다만 그 파일이 차지한 블록은 계속 사용 중인 상태로 남는다.

디스크의 크기, 현재 파일 배치, 그리고 실행할 RADDD 패스 횟수가 주어질 때, 최종 배치를 구하라.

입력

첫 줄에는 데이터 세트의 개수를 나타내는 정수 NN (1≤N≤1001 \le N \le 100)이 주어진다. 각 데이터 세트는 다음으로 구성된다.

  • 파일 시스템의 블록 수를 나타내는 정수 SS (2≤S≤1000002 \le S \le 100000)가 담긴 한 줄;
  • 파일 개수를 나타내는 정수 CC (1≤C≤1001 \le C \le 100)가 담긴 한 줄;
  • 파일을 설명하는 CC개의 줄. 각 줄은 NAME TYPE E A-B[ X-Y ...] 형식이며, 여기서:
    • NAME은 데이터 세트 안에서 유일한 식별자로, 소문자 1~16자이다;
    • TYPE은 파일이 이동 불가이면 I, 그렇지 않으면 M이다;
    • E (1≤E≤201 \le E \le 20)는 파일이 차지하는 익스텐트의 개수이다;
    • A와 B (1≤A,B≤S1 \le A, B \le S)는 각각 첫 번째 익스텐트의 첫 블록과 마지막 블록이다;
    • X와 Y는 있다면 두 번째 익스텐트의 첫 블록과 마지막 블록이며, 이후도 같은 방식이다;
  • 실행할 RADDD 패스 횟수를 나타내는 정수 PP (1≤P≤1001 \le P \le 100)가 담긴 한 줄.

출력

각 데이터 세트마다 DATA SET #k 형식의 줄을 출력한다. 여기서 kk는 첫 데이터 세트가 1, 두 번째가 2, 이런 식이다. 그다음 RADDD 패스를 모두 실행한 뒤의 파일 배치를, 각 파일이 차지한 첫 블록 번호의 오름차순으로 CC개의 줄에 출력한다. 형식은 입력과 동일하게 하며, 파일이 여러 익스텐트를 차지하는 경우 각 익스텐트의 첫 블록 번호 오름차순으로 나열한다.

예제3

  1. 예제 1

    입력
    2
    152
    1
    radfsdoc M 3 37-38 102-114 23-47
    1
    100
    4
    swapfile I 3 5-10 80-95 25-50
    smallfile M 2 1-4 11-14
    bigfile M 2 15-24 51-60
    tinyfile M 1 61-64
    2
    
    예상 출력
    DATA SET #1
    radfsdoc M 1 1-38
    DATA SET #2
    tinyfile M 1 1-4
    swapfile I 3 5-10 25-50 80-95
    bigfile M 2 15-24 51-60
    smallfile M 1 61-67
    
  2. 예제 2

    입력
    1
    10
    1
    a M 1 1-5
    1
    
    예상 출력
    DATA SET #1
    a M 1 1-5
    
  3. 예제 3

    입력
    3
    10
    1
    a M 1 1-5
    1
    8
    1
    b M 2 1-2 4-5
    2
    6
    1
    c I 1 1-3
    1
    
    예상 출력
    DATA SET #1
    a M 1 1-5
    DATA SET #2
    b M 1 1-3
    DATA SET #3
    c I 1 1-3