xxxxxxxxxx
import java.util.*;
public class Algorithm {
private static Scanner scanner = new Scanner(System.in);
private static Map<Point, String> scoreBoards = new TreeMap<Point, String>(new Comparator<Point>() {
public int compare(Point o1, Point o2) {
if (o1.distance > o2.distance) {
return 1;
} else if (o1.distance == o2.distance) {
return 0;
} else {
return -1;
}
}
});
public static void main(String[] args) {
int gameSet = scanner.nextInt();
while (gameSet > 0) {
setGameInput();
System.out.println(gamePlay());
gameSet--;
}
}
private static void setGameInput() {
int stoneNumber = scanner.nextInt();
while (stoneNumber > 0) {
int x = scanner.nextInt();
int y = scanner.nextInt();
String playerName = scanner.nextLine();
scoreBoards.put(new Point(x, y), playerName);
stoneNumber--;
}
}
private static String gamePlay() {
int winningScore = 0;
int count = 0;
boolean loserFlag = false;
Map.Entry<Point, String> loser = null;
Map.Entry<Point, String> winner = null;
for (Map.Entry<Point, String> entry : scoreBoards.entrySet()) {
if (count == 0) {
winner = entry;
winningScore++;
count++;
continue;
}
if (count != 0 && winner.getValue().equals(entry.getValue()) && loserFlag == false) {
winningScore++;
continue;
}
if (count != 0 && !winner.getValue().equals(entry.getValue()) && loserFlag == false) {
loserFlag = true;
loser = entry;
break;
}
}
return winner.getValue() + " : " + winningScore;
}
public static class Point {
int x, y;
double distance;
public Point(int x, int y) {
this.x = x;
this.y = y;
this.distance = Math.sqrt((Math.pow(x, 2)) + Math.pow(y, 2));
}
public double getDistance() {
return distance;
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x &&
y == point.y &&
Double.compare(point.distance, distance) == 0;
}
public int hashCode() {
return Objects.hash(x, y, distance);
}
}
}
컬링 게임에서 승자 찾는 로직을 구현해보았다. 주언어를 자바로 전향하고나서 처음 풀어보는 알고리즘 문제다. 두달간 테크캠프에서 자바를 꾸준히 보고 쓰고 해봤지만, 역시 이런 문법과 알고리즘 문제를 해결할 때는, 페어보다 혼자하는게 더 체득이 잘 되는 듯 하다. 물론 페어로 하면 상대방의 스킬까지 다 습득할 수 있어서 좋긴 하다. 하지만 눈으로 본걸 직접 써보지 않으면 아무리 많이 봐도 내 것이 되지 못한다. 모든일이 마찬가지다. 깊은 생각을 하고, 많이 보고, 많이 공부한 사람보다, 적당히 생각하고 적당히 보고, 적당히 공부한 다음에, 행동으로 옮겨 직접 몸으로 부딪히면서 경험하는 사람이 결국은 일을 잘하게 된다. 자만하거나 게을러지면 안된다.
Map
이번 문제에서는 Map을 메인으로 써보려고 노력했다. ScoreBoard에 기록되는 {스톤의 위치, 이름}
가 Key, Value
로 묶을 수 있다고 생각했다. (짜고나서 다시 생각해보니 이름이 Key, 스톤의 위치가 Value로 짰어야 의미상 더 맞는 것 같다.)
Point클래스를 생성해서 위치를 나타냈고, 해당 클래스로부터 get변수이름
으로 가져와서 Distance관련 비즈니스 로직을 구현하지 않고, ''상태값을 가지고 있는 클래스에 일을 시켜라'' 라는 포비의 말에 따라 Distance 로직을 Point 클래스에 구현하였다. 이렇게 구현했을 때의 장점은, 재사용성의 증가와 가독성인 듯 하다. 만약 거리 계산이 필요한 곳에서 매번 getX getY
를 하여 distance 계산을 하게 된다면 중복 코드가 발생할 것이고, 혹여나 이것을 따로 메소드화 한다고 하더라도, 그 상태값을 가지고 있지 않은 다른 클래스에서 메소드화를 하게 된다면 객체 설계가 뒤죽박죽이 되어 가독성이 떨어지거나, 이상한 의존관계가 생기게 될 것이다.
그동안 코드를 짜면서 Map 사용을 많이 해보진 않았었다. 그래서 최대한 Map의 기능들을 활용하고 싶었다.
xxxxxxxxxx
private static Map<Point, String> scoreBoards = new TreeMap<Point, String>(new Comparator<Point>() {
public int compare(Point o1, Point o2) {
if (o1.distance > o2.distance) {
return 1;
} else if (o1.distance == o2.distance) {
return 0;
} else {
return -1;
}
}
});
Map의 종류에는 HashMap, TreeMap, LinkedHashMap이 있고, 중복을 허용하지 않는다.
HashMap :
xxxxxxxxxx
Entry<K,V>[] entry;
내부적으로 위 형태의 배열로 되어있다. 배열의 인덱스는 내부 해쉬 함수를 통해 알 수 있다. 해쉬 값으로 순서가 정해지므로 규칙이 없다.
TreeMap :
xxxxxxxxxx
new TreeMap<Point, String>(new Comparator<정렬할 기준>() { compare })
내부적으로 레드-블랙 트리 형태로 저장이 된다. 키값에 대한 Comparator를 구현하고 그것에 따라서 정렬된채로 저장된다.사용 방법은 위와 같다.
LinkedHashMap :
내부적으로 링크드리스트 형태로 저장이 된다. 입력 순서대로 출력이 된다.
Entry :
Map에서 하나의 객체를 표현할 때 Map.Entry<K,V> 로 표현한다.
검색 성능은 HashMap : O(1) 가 가장 좋다. TreeMap은 랜덤 접근에 대하여 O(logn)이다.
참고자료
- 매우 좋은 자료 : https://d2.naver.com/helloworld/831311
'기술 > Algorithm' 카테고리의 다른 글
Brian Kernighan's 알고리즘 (0) | 2018.10.15 |
---|---|
감시 문제 (0) | 2018.10.11 |
카카오 코딩테스트 6번 (0) | 2018.09.17 |
카카오 코딩테스트 2번 (0) | 2018.09.17 |
카카오 코딩테스트 1번 (0) | 2018.09.17 |