1. 문제
www.codewars.com/kata/55b3425df71c1201a800009c
문제 설명
You are the "computer expert" of a local Athletic Association (C.A.A.). Many teams of runners come to compete. Each time you get a string of all race results of every team who has run. For example here is a string showing the individual results of a team of 5 runners:
"01|15|59, 1|47|6, 01|17|20, 1|32|34, 2|3|17"
Each part of the string is of the form:h|m|swhere h, m, s (h for hour, m for minutes, s for seconds) are positive or null integer (represented as strings) with one or two digits. There are no traps in this format.
To compare the results of the teams you are asked for giving three statistics;range, average and median.
Range: difference between the lowest and highest values. In {4, 6, 9, 3, 7} the lowest value is 3, and the highest is 9, so the range is 9 − 3 = 6.
Mean or Average: To calculate mean, add together all of the numbers in a set and then divide the sum by the total count of numbers.
Median: In statistics, the median is the number separating the higher half of a data sample from the lower half. The median of a finite list of numbers can be found by arranging all the observations from lowest value to highest value and picking the middle one (e.g., the median of {3, 3, 5, 9, 11} is 5) when there is an odd number of observations. If there is an even number of observations, then there is no single middle value; the median is then defined to be the mean of the two middle values (the median of {3, 5, 6, 9} is (5 + 6) / 2 = 5.5).
the form:
"Range: hh|mm|ss Average: hh|mm|ss Median: hh|mm|ss"
where hh, mm, ss are integers (represented by strings) witheach 2 digits.
제한 사항
Remarks:
-
if a result in seconds is ab.xy... it will be giventruncatedas ab.
-
if the given string is "" you will return ""
입출력 예
input - "01|15|59, 1|47|6, 01|17|20, 1|32|34, 2|3|17"
result - "Range: hh|mm|ss Average: hh|mm|ss Median: hh|mm|ss"
2. 어떻게 풀까?
- input으로 들어온 time 문자열을 쪼갠다.
- 각 time 문자열을 시간, 분, 초를 계산해서, 혹은
LocalTime
을 이용해서List
에 저장 후 정렬한다.- 전에
Time
패키지 공부 한 것을 써먹기 위해LocalTime
을 사용해서 해결
- 전에
List
를 통해 Range, Average, Median을 구하고String
으로 표현한다.
3. 코드
테스트 코드
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.*;
import org.junit.Test;
public class StatTest {
@Test
public void testWhenInputIsEmptyString() {
String expected = "";
String input = "";
assertThat(Stat.stat(input), is(expected));
}
@Test
public void testWhenInputSizeIs1() {
String expected = "Range: 00|00|00 Average: 00|15|00 Median: 00|15|00";
String input = "0|15|0";
assertThat(Stat.stat(input), is(expected));
}
@Test
public void testWhenInputSizeIsOdd() {
String expected = "Range: 01|01|18 Average: 01|38|05 Median: 01|32|34";
String input = "01|15|59, 1|47|16, 01|17|20, 1|32|34, 2|17|17";
assertThat(Stat.stat(input), is(expected));
}
@Test
public void testWhenInputSizeIsEven() {
String expected = "Range: 00|31|17 Average: 02|25|24 Median: 02|19|40";
String input = "02|15|59, 2|47|16, 02|17|20, 2|32|34, 2|17|17, 2|22|00";
assertThat(Stat.stat(input), is(expected));
}
}
실제 코드
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Stat {
public static String stat(String strg) {
if (strg.isEmpty()) {
return "";
}
List<LocalTime> list = getSortedTimeList(strg);
LocalTime range = getRange(list);
LocalTime average = getAverage(list);
LocalTime median = getMedian(list);
return getResultString(range, average, median);
}
private static List<LocalTime> getSortedTimeList(String strg) {
List<LocalTime> list = new ArrayList<>();
String[] split = strg.split(", ");
for (int i = 0; i < split.length; i++) {
LocalTime temp = LocalTime.parse(split[i], DateTimeFormatter.ofPattern("H|mm|s"));
list.add(temp);
}
list.sort(Comparator.naturalOrder());
return list;
}
private static LocalTime getRange(List<LocalTime> list) {
LocalTime min = list.get(0);
LocalTime max = list.get(list.size() - 1);
long seconds = min.until(max, ChronoUnit.SECONDS);
return LocalTime.ofSecondOfDay(seconds);
}
private static LocalTime getAverage(List<LocalTime> list) {
long seconds = 0;
for (int i = 0; i < list.size(); i++) {
seconds += list.get(i).toSecondOfDay();
}
return LocalTime.ofSecondOfDay(seconds / list.size());
}
private static LocalTime getMedian(List<LocalTime> list) {
long seconds = 0;
if (list.size() % 2 == 1) {
seconds = list.get(list.size() / 2).toSecondOfDay();
} else {
seconds += list.get(list.size() / 2).toSecondOfDay();
seconds += list.get(list.size() / 2 - 1).toSecondOfDay();
seconds /= 2;
}
return LocalTime.ofSecondOfDay(seconds);
}
private static String getResultString(LocalTime range, LocalTime average, LocalTime median) {
return String.format("Range: %s Average: %s Median: %s",
range.format(DateTimeFormatter.ofPattern("HH|mm|ss")),
average.format(DateTimeFormatter.ofPattern("HH|mm|ss")),
median.format(DateTimeFormatter.ofPattern("HH|mm|ss")));
}
}
getSortedTimeList()
에서 input 문자열을 ", "로 쪼갠 뒤List
에 저장 후 정렬했다.getRange()
,getAverage()
,getMedian()
에서List
에 저장한LocalTime
들을 계산했다.
4. 느낀 점
- 문제를 처음 보고 '|'의 index를 통해 시, 분, 초를 구하고 그것들을 초로 바꾸어
List
에 저장해서 정렬 후, range/average/medain을 계산하려 했는데, 전에 공부했던 Time 패키지의LocalTime
을 이용하면 쉽게 해결 할 수 있겠다고 생각해서 사용해 보았다. List<LocalTime>
을 정렬하면 정렬이 안될줄 알았는데 아주 잘 되서 신기했다.LocalTime
을 이용할 때, 전에 포스팅한 Time 패키지를 참고했다. 정리 해놓길 잘했다는 생각이 든다.
'Coding Test > Codewars' 카테고리의 다른 글
[Codewars] 6Kyu, Simple Frequency Sort (Java, Python) (0) | 2022.01.17 |
---|---|
코드워즈 - Square Matrix Multiplication (01/21) (java) (0) | 2021.01.21 |
코드워즈 - Rainfall (11/17) (java) (0) | 2020.11.17 |
코드워즈 - Large Factorials (10/31) (java) (0) | 2020.10.31 |