본문 바로가기

컴퓨터&프로그래밍/Baekjoon

[백준/C#] 7785 - 회사에 있는 사람

1. 문제

각 직원은 자기가 원할 때 출근할 수 있고, 아무 때나 퇴근할 수 있다.

상근이는 모든 사람의 출입카드 시스템의 로그를 가지고 있다. 이 로그는 어떤 사람이 회사에 들어왔는지, 나갔는지가 기록되어 있다. 로그가 주어졌을 때, 현재 회사에 있는 모든 사람을 구하는 프로그램을 작성하시오.

- 입력

첫째 줄에 로그에 기록된 출입 기록의 수 n이 주어진다. (2 ≤ n ≤ 106)

다음 n개의 줄에는 출입 기록이 순서대로 주어지며, 각 사람의 이름이 주어지고 "enter"나 "leave"가 주어진다. "enter"인 경우는 출근, "leave"인 경우는 퇴근이다.

회사에는 동명이인이 없으며, 대소문자가 다른 경우에는 다른 이름이다. 사람들의 이름은 알파벳 대소문자로 구성된 5글자 이하의 문자열이다.

 

- 출력

현재 회사에 있는 사람의 이름을 사전 순의 역순으로 한 줄에 한 명씩 출력한다.

 

- 설명

지금까지는 삽입만 했습니다. 이제 제거도 해봅시다.

예제 입력 예제 출력
4
Baha enter
Askar enter
Baha leave
Artem enter
Askar
Artem
 

7785번: 회사에 있는 사람

첫째 줄에 로그에 기록된 출입 기록의 수 n이 주어진다. (2 ≤ n ≤ 106) 다음 n개의 줄에는 출입 기록이 순서대로 주어지며, 각 사람의 이름이 주어지고 "enter"나 "leave"가 주어진다. "enter"인 경우는

www.acmicpc.net


2. 풀이

SortedSet을 이용한 풀이, Dictionary를 이용한 풀이가 있다.

enter가 찍혀있으면 기록하고, leave가 찍혀있으면 해당 직원을 목록에서 제거하면 된다.

 

- SortedSet<이름>

// 회사에 있는 사람
SortedSet<string> remains = new SortedSet<string>();

// 입력
using(var read = new StreamReader(Console.OpenStandardInput())) {
    int n = int.Parse(read.ReadLine());
    for (int i = 0; i < n; i++) {
        string[] input = read.ReadLine().Split(" ");
        if (input[1] == "enter") remains.Add(input[0]);	// 들어간 경우 기록
        else remains.Remove(input[0]);	// 나간 경우 해당 직원 목록에서 제거
    }
}

// 역순으로 정렬
var res = remains.OrderByDescending(x=>x).ToArray();

// 출력
using (var print = new StreamWriter(Console.OpenStandardOutput(0))) {
    foreach (string str in res)
        print.WriteLine(str);
}

 

- Dictionary<이름, 상태>

// 회사에 있는 사람
Dictionary<string,string> remains = new Dictionary<string, string>();

// 입력
using (var read = new StreamReader(Console.OpenStandardInput())) {
    int n = int.Parse(read.ReadLine());
    for (int i = 0; i < n; i++) {
        string[] input = read.ReadLine().Split(' ');
        // 이름이 키, 상태가 값
    if (remains.ContainsKey(input[0]) && input[1] == "leave") remains.Remove(input[0]);
    else remains.Add(input[0], input[1]);
    }
}

// 역순으로 정렬
var res = remains.OrderByDescending(x => x.Key);

// 출력
using (var write = new StreamWriter(Console.OpenStandardOutput())) {
    foreach (var name in res)
        write.WriteLine(name.Key);
}

3. 배운 점

- 메모

StreamReader를 잘못 써서 엄청나게 삽질했다.

입력 첫 줄은 Console.ReadLine()으로 받고, 그다음부터 StreamWriter로 받는 방식으로 코딩을 했었고, 내 컴퓨터에서는 문제없었다.

하지만 제출하면 어떤 로직을 써도 오류가 나서 로직도 검토하고 다른 사람 제출과 비교도 해봤지만 여전히 런타임 에러 (IndexOutOfRange)가 떴다.

한 줄 한 줄 비교한 결과 원인을 찾았는데, 입력 방식을 나눠놓은 것이 문제였다.

덕분에 이거 저거 다 써보긴 했다. 3일 동안 헤매서 그렇지...

 

- SortedSet<T>

정렬 순서가 있는 집합이다. 

 

SortedSet<T> 클래스 (System.Collections.Generic)

정렬된 순서대로 유지 관리되는 개체의 컬렉션을 나타냅니다.

learn.microsoft.com

 

- StreamReader

특정 인코딩의 바이트 스트림에서 문자를 읽는 텍스트 리더라고 한다.

파일 읽어올 때 사용하는 건데, StreamWriter때와 마찬가지로 Console.ReadLine보다 훨씬 속도가 빠르다.

백준에서 입력받다가 시간 초과당하지 않기 위해서 쓴다.

https://learn.microsoft.com/ko-kr/dotnet/api/system.io.streamreader?view=net-7.0

 

StreamReader 클래스 (System.IO)

특정 인코딩의 바이트 스트림에서 문자를 읽는 TextReader 를 구현합니다.

learn.microsoft.com

 



Calendar
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Visits
Today
Yesterday