코딩테스트 큐: 상담 창구 대기열 명령 처리

··설명 약 4분·작성: 해비·블로그 소개

읽기 전에 알아두면 좋아요

아래 개념이 익숙하면 본문을 바로 읽으세요. 낯선 개념만 링크에서 복습하면 됩니다.

개념과 예제는 실행하지 않아도 읽을 수 있습니다. 내 컴퓨터·터미널에서 직접 실행하는 과정은 선택 실습입니다.

과정 위치와 선택 복습 안내

과정 위치: 자료구조 개념과 문제 · 문제

과정 위치는 이 글이 속한 묶음입니다. 이 단계의 모든 개념을 먼저 읽을 필요는 없습니다. 위에 연결한 개념 중 낯선 내용만 복습하세요. 문제의 조건·상태·갱신 순서는 익숙한 언어로 설명하면 됩니다.

JavaScript로 문법·실행 복습하기 (선택)

개념 글의 코드는 JavaScript 예시입니다. 문제 화면에서는 JavaScript·Python·Java·C++·C# 중 익숙한 언어의 함수를 작성하세요. 본문의 Node.js 입출력 예시는 로컬 실행을 위한 별도 안내입니다.

상담 창구 대기열의 명령과 조회 결과는 어떤 순서로 처리하나요?

대기열 명령을 입력 순서대로 처리하고 요구한 조회 결과를 반환하는 문제입니다. 배열·명령 처리·큐의 기본을 준비하고, 아래 입력·반환 계약을 확인해 직접 풀어보세요.

적용 조건·범위: 정답 파일은 createQueue 선언부터 solve, 표준 입력 처리까지 포함합니다. 다른 가이드 파일을 require하지 않습니다. Node 내장 fs만 표준 입력을 읽는 데 사용합니다. 유효 입력 계약을 가정하는 연습 풀이이며 잘못된 명령·누락 줄을 진단하는 파서는 아닙니다.

공식 문서 참고: 관련 개념: 버지니아공대 OpenDSA의 큐와 FIFO

독립 창작 문제: 상담 창구 대기열

도착한 순서를 지키며 고객을 호출하고 대기 인원을 출력합니다. 같은 이름의 고객도 각각 별도 방문으로 보관합니다.

큐의 FIFO 구조 개념 표지

이 문제는 BlogFlow 학습용으로 독립 창작했습니다. 외부 문제의 지문·예시·테스트를 복제하지 않았습니다.

개념 연결: 큐와 FIFO 가이드

문제

비어 있는 상담 창구에 명령이 순서대로 주어집니다. ARRIVE 이름은 고객을 대기열 뒤에 추가합니다. CALL은 가장 먼저 온 고객 이름을 출력한 뒤 대기열에서 제거하며, 비어 있으면 EMPTY를 출력합니다. COUNT는 현재 인원 수를 출력합니다. 이름이 같아도 도착한 횟수만큼 별도 항목으로 취급합니다.

입력·출력·제약

첫 줄은 정수 Q(0~100,000), 다음 Q줄은 정의된 명령입니다. 이름은 공백 없는 1~40 코드포인트 문자열입니다. CALL과 COUNT 결과를 각 한 줄로 출력하며 결과가 하나도 없으면 아무것도 출력하지 않습니다. 명령과 이름 사이에는 공백 하나를 사용합니다.

예시 1

입력:

7
ARRIVE 민수
ARRIVE 수지
CALL
ARRIVE 준호
COUNT
CALL
CALL

출력:

민수
2
수지
준호

예시 2: 빈 상태

입력:

2
CALL
COUNT

출력:

EMPTY
0

힌트

아직 읽지 않은 첫 위치 head를 움직이세요. 빈 큐는 값이 undefined인지가 아니라 head와 배열 길이가 같은지로 판단합니다.

직접 풀어보기

먼저 선택한 언어의 입력·반환 계약에 맞춰 작성해 보세요. 힌트 받기와 정답과 비교하기는 코드를 실행하지 않는 AI 분석입니다. 해답·해설은 아래에서 필요할 때 펼칠 수 있습니다.

0 / 6,000바이트

입력 예시 전체를 문자열로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. 입력 공백과 LF/CRLF 줄바꿈을 처리합니다. Tab은 다음 항목으로 이동합니다. 입력 영역 오른쪽 아래를 끌어 높이를 조절할 수 있습니다.

비밀키·개인정보는 입력하지 마세요. 코드는 이 페이지에만 유지됩니다.

해답·해설 보기
JavaScript 해답
function createQueue() {
    let items = [];
    let head = 0;
    return {
        enqueue(value) {
            items.push(value);
        },
        dequeue() {
            if (head === items.length) {
                return {
                    done : true
                };
            }
            const value = items[head];
            items[head] = undefined;
            head += 1;
            if (head === items.length) {
                items = [];
                head = 0;
            } else if (head >= 1024 && head * 2 >= items.length) {
                items = items.slice(head);
                head = 0;
            }
            return {
                done : false, value
            };
        },
        size() {
            return items.length - head;
        },
    };
}
function solve(input) {
    const text = input.trim();
    if (! text) {
        return '';
    }
    const lines = text.split(/\r?\n/);
    const count = Number(lines[0]);
    const queue = createQueue();
    const output = [];
    for (let i = 1; i <= count; i++) {
        const[command, name] = lines[i].split(' ');
        if (command === 'ARRIVE') {
            queue.enqueue(name);
        } else if (command === 'CALL') {
            const result = queue.dequeue();
            output.push(result.done ? 'EMPTY' : result.value);
        } else if (command === 'COUNT') {
            output.push(String(queue.size()));
        }
    }
    return output.join('\n');
}

입력 예시 전체를 문자열로 전달하고 출력 문자열을 반환합니다. solve(input)를 호출합니다. 표준 입력·출력 코드는 추가하지 않습니다. 입력 공백과 LF/CRLF 줄바꿈을 처리합니다.

Node.js 24 CommonJS용 코드입니다. 전체를 queue-helpdesk-problem.cjs로 저장하고 예시 입력을 input.txt에 UTF-8로 저장합니다. 아래 명령은 셸에 맞게 하나를 골라 사용하세요.

PowerShell 7 (UTF-8 파이프):

Get-Content -Raw -Encoding UTF8 .\input.txt | node .\queue-helpdesk-problem.cjs

macOS / Linux Bash:

node queue-helpdesk-problem.cjs < input.txt
function createQueue() {
  let items = [];
  let head = 0;
  return {
    enqueue(value) {
      items.push(value);
    },
    dequeue() {
      if (head === items.length) {
        return { done: true };
      }
      const value = items[head];
      items[head] = undefined;
      head += 1;
      if (head === items.length) {
        items = [];
        head = 0;
      } else if (head >= 1024 && head * 2 >= items.length) {
        items = items.slice(head);
        head = 0;
      }
      return { done: false, value };
    },
    size() {
      return items.length - head;
    },
  };
}

function solve(input) {
  const text = input.trim();
  if (!text) {
    return '';
  }
  const lines = text.split(/\r?\n/);
  const count = Number(lines[0]);
  const queue = createQueue();
  const output = [];
  for (let i = 1; i <= count; i++) {
    const [command, name] = lines[i].split(' ');
    if (command === 'ARRIVE') {
      queue.enqueue(name);
    } else if (command === 'CALL') {
      const result = queue.dequeue();
      output.push(result.done ? 'EMPTY' : result.value);
    } else if (command === 'COUNT') {
      output.push(String(queue.size()));
    }
  }
  return output.join('\n');
}

module.exports = { solve };

if (require.main === module) {
  const input = require('node:fs').readFileSync(0, 'utf8');
  process.stdout.write(solve(input));
}

명령과 상태 변화

명령 처리 뒤 목록 출력
ARRIVE 민수 민수 없음
ARRIVE 수지 민수 → 수지 없음
CALL 수지 민수
ARRIVE 준호 수지 → 준호 없음
COUNT 수지 → 준호 2
CALL, CALL 빈 큐 수지, 준호

왜 이 구현으로 맞는가

정답 파일은 createQueue 선언부터 solve, 표준 입력 처리까지 포함합니다. 다른 가이드 파일을 require하지 않습니다. Node 내장 fs만 표준 입력을 읽는 데 사용합니다. 유효 입력 계약을 가정하는 연습 풀이이며 잘못된 명령·누락 줄을 진단하는 파서는 아닙니다.

solve는 첫 줄의 명령 수를 읽고 정확히 그만큼 순회합니다. ARRIVE에는 반환할 결과가 없으므로 output에 넣지 않습니다. CALL은 dequeue의 done으로 빈 상태를 구분하고 COUNT는 size를 문자열로 바꿉니다. output.join("\n")은 결과 사이에만 줄바꿈을 넣어 Q=0일 때 빈 문자열을 반환합니다.

각 명령 직전 큐의 유효 구간에는 아직 호출하지 않은 방문만 도착 순으로 남아 있습니다. enqueue가 뒤에 추가하고 dequeue가 앞의 한 항목만 제거하므로 명령 처리 뒤에도 이 불변식은 유지됩니다. COUNT가 전체 items.length를 읽으면 이미 호출한 슬롯까지 세므로 반드시 size를 사용합니다.

head가 커지면 소비한 앞부분이 물리 배열에 남습니다. dequeue는 사용한 슬롯의 참조를 먼저 끊고, 충분히 많은 슬롯을 소비했을 때 남은 값만 복사합니다. 한 압축은 O(K)이지만 그 비용을 앞선 제거들에 나누면 큐 연산은 분할 상환 O(1)입니다.

시간·공간과 문자열 비용

큐에 남은 최대 항목 수를 K라 하면 큐 구조만의 공간은 O(K+1024)입니다. 그러나 이 프로그램은 전체 입력 문자열, 줄 배열, 출력 배열과 마지막 결합 문자열까지 메모리에 보관합니다. 입력 문자 수 S, 출력 문자 수 R, 명령 수 Q를 포함한 전체 추가 저장은 O(S+R+Q+K), K≤Q이므로 O(S+R+Q)입니다. 따라서 프로그램 전체 공간을 O(K)라고 쓰면 입력·출력을 빠뜨립니다. 문자열 처리까지 포함한 총시간은 통상적 동적 배열 모델에서 O(S+R+Q) 상환이며, 큐 연산만 따로 보면 O(Q) 상환입니다.

표본을 직접 확인하는 코드

다음 코드를 queue-helpdesk-check.cjs로 저장한 뒤 node queue-helpdesk-check.cjs로 실행하세요. assert가 일치하면 출력 없이 종료하고, 결과가 다르면 예외가 발생합니다. 같은 폴더의 정답 파일을 가져오는 이 블록은 풀이 본체가 아니라 표본 확인용입니다.

const assert = require('node:assert/strict');
const { solve } = require('./queue-helpdesk-problem.cjs');

const input = "7\nARRIVE 민수\nARRIVE 수지\nCALL\nARRIVE 준호\nCOUNT\nCALL\nCALL";
const expected = "민수\n2\n수지\n준호";
assert.equal(solve(input), expected);
assert.equal(solve("2\nCALL\nCOUNT"), "EMPTY\n0");
assert.equal(solve('0'), '');

연결 학습

큐와 FIFO 가이드에서 메서드별 불변식을 확인하세요. 공식 문제 사이트의 백준 10845 큐는 다른 계약을 가진 추가 연습입니다. 공식 링크 확인일: 2026년 9월 10일.

이 문제를 푼 뒤 확인하기

풀이 직접 실행

본문 풀이에 예제 입력을 넣고, 입력을 바꿔 계산 결과를 비교합니다.

예제 크게 보기 (새 탭)

빈 큐에서 꺼내는 명령과 넣은 순서대로 꺼내는 명령을 차례로 추적해 보세요.

본문의 예제와 이 반례를 직접 실행해 예상 출력과 비교하고, 결과가 다르면 입력 조건과 반복 범위를 다시 확인하세요.

이 글이 도움이 되었나요?

조회 중

이어서 공부하기

체크포인트: 해설을 가리고 다시 풀고, 경계 입력을 하나 바꾸어 예상 결과와 실제 결과를 비교하세요. 삽입·제거 전후의 상태를 그리고, 내장 도구를 쓰는 풀이와 직접 구현의 목적을 구분하세요.

다음 추천 · 자료구조 개념: 단방향 연결 리스트: head·tail 삽입과 삭제

같은 주제에서 다음 개념과 예제로 이해를 넓힙니다.

권장 순서는 학습 가이드와 같습니다. 다른 순서는 접힌 참고 목록에서 확인할 수 있습니다. 읽음 표시는 숙달이나 채점 결과가 아닙니다.

원래 과정 목록 순서 (선택)

읽음 기록

읽음 — / 전체 58개 · 필수 58개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기