Apple is Apple

문제

생태학에서 나무의 분포도를 측정하는 것은 중요하다.
그러므로 당신은 미국 전역의 나무들이 주어졌을 때, 각 종이 전체에서 몇 %를 차지하는지 구하는 프로그램을 만들어야 한다.

입력 및 출력

  • 입력: 프로그램은 여러 줄로 이루어져 있으며, 한 줄에 하나의 나무 종 이름이 주어진다.
    어떤 종 이름도 30글자를 넘지 않으며, 입력에는 최대 10,000개의 종이 주어지고 최대 1,000,000그루의 나무가 주어진다.
  • 출력: 주어진 각 종의 이름을 사전순으로 출력하고, 그 종이 차지하는 비율을 백분율로 소수점 4째자리까지 반올림해 함께 출력한다.

풀이

예제 입력으로 다음과 같이 여러 줄로 나무 종류가 나열되어 있다. 이 종류들을 전체에서 비율로 나타내기 위해서는 같은 종끼리 묶을 필요가 있다.
같은 종 별로 묶어서 종 별 갯수를 세고, 전체 갯수로 나누어서 백분율을 구한 뒤, 퍼센테이지로 표현하면 되는 문제이다.

코드

import java.io.BufferedWriter
import java.io.OutputStreamWriter

val bw = BufferedWriter(OutputStreamWriter(System.out))
fun main() = with(System.`in`.bufferedReader()){
    val list = mutableListOf<String>()
    while(true){
        val str = readLine()
        if(str == null || str.isEmpty()) break
        list.add(str)
    }
    val size = list.size

    list.groupBy { it }.map{it.key to it.value.size}.sortedBy { it.first }.forEach{
        bw.write(it.first + " %.4f\n".format((it.second*100.0).toDouble() / size))
    }
    bw.flush()
    bw.close()
    close()
}

먼저, readLine()을 통해 문자열이 들어오지 않을 때까지 받고, 리스트에 저장한다.
이제 이 리스트를 조작하여 정답을 도출해낸다.
먼저, Kotlin Collection의 groupBy 매소드를 사용하여 컬렉션 내의 원소들을 같은 것 끼리 그룹화시켜준다.
예를 들어, list = listOf(1,1,2,2,2,3,3,3)이라는 리스트가 있을 때, list.groupBy{it}을 수행하면 다음과 같은 결과가 출력된다.
[(1,[1,1]),(2,[2,2,2]),(3,[3,3,3])] 원소 하나를 Key를 갖고, 모든 같은 값을 리스트로 만들어 Value로 같게된다.
이 문제의 문자열 입력처럼 받게 되면 [(Ash,[Ash, Ash...]), (Aspen, [Aspen, Aspen...]), ...] 형식으로 만들어지게 된다.
비율을 구하기 위해서는 각 종류별 개수가 필요하다. 그래서 Collection 조작하는 map메소드를 통해 그룹화한 리스트의 Value를 문자열이 아닌 리스트의 size로 변경해준다.
변경하면 리스트의 원소들을 Map에서 Pair구조로 변경된다.
그 다음으로 출력부분에서 사전순으로 출력을 해주어야 하므로 sortBy{it.first}를 통해 사전순(오름차순) 정렬을 한다.
마지막으로, 각 종의 개수에서 리스트의 전체길이를 나누어 백분율을 구하고, 출력형식에 맞게 출력한다.

결과

image


메모리가 조금 많이 사용된 모습을 볼 수 있었는데, 입력이 최대 10,000개의 종에서 1,000,000그루의 나무가 주어졌는데, 입력이 많아 리스트가 커질 뿐만아니라
그 커진 리스트를 조작하는 과정에서 메모리를 더 사용해서 이러한 결과가 나온 것 같다.

profile

Apple is Apple

@mjjjjjj