[Kotlin] 백준 1159번 농구 경기 with 코틀린

: ) YOUNG·2022년 5월 1일
2

Kotlin 알고리즘

목록 보기
1/28
post-thumbnail

문제

백준 1159번
https://www.acmicpc.net/problem/1159


상근이는 농구의 세계에서 점차 영향력을 넓혀가고 있다. 처음에 그는 농구 경기를 좋아하는 사람이었다. 농구에 대한 열정은 그를 막을 수 없었고, 결국 상근이는 농구장을 청소하는 일을 시작했다. 상근이도 농구장을 청소하면서 감독이 되기 위해 가져야할 능력을 공부해나갔다. 서당개 3년이면 풍월을 읊듯이 상근이는 점점 감독으로 한 걸음 다가가고 있었다. 어느 날 그에게 지방의 한 프로농구팀을 감독할 기회가 생기게 되었다. 그는 엄청난 지도력을 보여주며 프로 리그에서 우승을 했고, 이제 국가대표팀의 감독이 되었다.

내일은 일본과 국가대표 친선 경기가 있는 날이다. 상근이는 내일 경기에 나설 선발 명단을 작성해야 한다.

국가대표팀의 감독이 된 이후에 상근이는 매우 게을러졌다. 그는 선수의 이름을 기억하지 못하고, 각 선수의 능력도 알지 못한다. 따라서, 누가 선발인지 기억하기 쉽게 하기 위해 성의 첫 글자가 같은 선수 5명을 선발하려고 한다. 만약, 성의 첫 글자가 같은 선수가 5명보다 적다면, 상근이는 내일 있을 친선 경기를 기권하려고 한다.

상근이는 내일 경기를 위해 뽑을 수 있는 성의 첫 글자를 모두 구해보려고 한다.


생각하기

Kotlin에서 HashMap공부를 하기 위해 다시 들렀다.

Java로는 너무 쉽게 풀었기 때문에 로직은 알고있어서 그냥 코딩만 하면되는데...

Kotlin으로 HashMap 처음써서 그런가 진짜 지랄맞게 복잡했다..
그래서 여러가지 시도를 모두 기록해보려고 한다.

문제를 풀은 방법은 간단하다.

테스트케이스로 들어오는 이름들의 첫 글자만 map에 넣어서 저장하면 되는데
map<Char, Int> 형으로 했다.

처음에 자바에서는 <Character, Integer> 니까 당연히 그럴 거라고 생각해서 만들었는데, 자꾸 오류가 나서 뭐가 문제일까 했는데, kotlin에서는 그냥 <Char, Int>로 해도 문제가 없었다..

이후에는 getOrDefault를 써서 쉽게 풀 수 있었다.

getOrDefault는 HashMap에서 value값을 default로 하나를 정해주면,
모든 key값에 공통적으로 그 값이 들어간다.

여기서는 같은 key값이 들어오게 되면 value로 지정된 default값을 +1로 들어올 때 마다 1증가하게 만들었다.

이러면 같은 성씨의 이름을 가진 선수가 몇명인지 map에 저장할 수 있다.

동작

Java에서도 map을 출력하는 방법이 있어서 여기서도 여러가지를 시도해보았다.

그리고 결과에서도 한번 비교를 해보았다.

1. 일반 for문을 사용해서 출력

첫 번째 방법. 그냥 반복문 출력.
이 방법이 의외로 가장 효율적이었다.

    for((key, value) in map) {
        if(value >= 5) {
            sb.append(key);
        }
    }

이렇게 일반 반복문으로 map을 순환해서 value값을 비교하여 key값을 넣는게 가장 빨랐다.

솔직히 조금 느릴줄 알았는데, 좀 의외였다.


2. Iterator의 EntrySet을 활용해서 출력

두 번째는 Iterator의 EntrySet을 활용해서 출력
Java에서는 이 방법을 활용해서 HashMap을 출력하는게 가장 빠르기 때문에 당연히 이게 가장 빠를 줄 알았는데, 2등의 결과.

처음 for문과 큰 차이는 없지만, 어쨋든 느린거는 사실이었다.

    var it : Iterator<Map.Entry<Char, Int>> = map.entries.iterator();
    while(it.hasNext()) {
        var entrySet : Map.Entry<Char, Int> = it.next();
        
        if(entrySet.value >= 5) {
            sb.append(entrySet.key);
        }
    }

4ms의 차이


3. forEach를 사용한 출력

솔직히 이건 기대도 안했던게 Java에서도 이걸 사용하면 진짜 말도 안되게 느리게 나오기 때문에 절대로 사용하지 않는다.

그래도 혹시 몰라서 돌려봤지만 결과는 역시나 였다.

    map.forEach { key, value -> if(value >= 5) { sb.append(key); } }

최대한 짧게 작성했는데도 불구하고

240ms이라는 어마어마한 시간..
다시는 사용하지 않겠다..

결론

  • Kotlin에서는 Map에서 제네릭에 객체형이 아닌 일반형이 가능하다.
  • Kotlin에서 Map을 쓸 때는 일반 for문이나 Itrator를 쓰자



코드


import java.io.*;
import java.util.*;
import kotlin.collections.HashMap

fun main() {
    var br = BufferedReader(InputStreamReader(System.`in`));
    var sb = StringBuilder();

    var num = Integer.parseInt(br.readLine())
    var map : HashMap<Char, Int> = HashMap<Char, Int>();

    // 들어오는 이름의 첫 글자를 분리해서 집어넣어야함.
    while(num-->0) {
        var name = br.readLine()[0]
        map.put(name, map.getOrDefault(name, 0) + 1);
    }


    for((key, value) in map) {
        if(value >= 5) {
            sb.append(key);
        }
    }

    if(sb.length == 0) {
        print("PREDAJA")
    }
    else {
        print(sb)
    }

} // End of main

0개의 댓글