티스토리 뷰
오늘 본 테스트는 내게는 너무나 어려웠다. 시간이 충분하다면 재밌게 풀 수 있는 문제들이었던 것 같은데 시간 분배에 아주 실패했다. 우선 4개의 문제를 둘러보고 먼저 시작할 문제를 골라 시작했는데, 계속 조금만 더 디버깅해보면 될 것 같은 생각에 붙잡고 있다가 시간이 흐르고 다른 문제를 풀기 시작하기에는 시간이 부족할 것 같아서 이 문제라도 풀어내야겠다 하고 끝까지 붙잡고 있다가 시험이 끝난 뒤에도 한참 디버깅하고, 점심 먹고 다시 앉아 함수를 분리해서 코드를 다시 짜보았다.
입력으로 플레이어 수와 매 턴에 플레이어가 뽑아서 나온 카드가 순서대로 주어진다. 게임에는 A, J, Q, K 네 가지 카드가 사용되고, 각 카드마다 수행 내용이 다른데 마지막에 각 플레이어가 가지게 되는 사탕의 개수를 출력하는 것이 이번 문제다. 카드 A는 카드를 뽑은 사람에게 사탕 하나를 주고, 카드 J는 카드를 뽑은 사람의 양 옆의 사람에게 사탕 하나를 준다. 카드 Q는 플레이어 전부에게 사탕을 하나씩 준다. 그리고 특별한 카드 K는 카드를 뽑은 사람 자신이 팔로우할 플레이어를 한 명 선택할 수 있고, 팔로우는 2명 이상도 가능하다. 팔로우란 플레이어가 사탕을 받았을 때 팔로우하고 있는 사람도 사탕을 받게 되는 것이다. 예를 들어 1번 플레이어가 카드 K를 뽑고 2번 플레이어를 팔로우하기로 했다면 1번 플레이어가 사탕을 받을 때 2번 플레이어도 사탕을 받게 되는 것이다. 따라서 카드 K는 숫자가 이어서 입력으로 주어지는데 팔로우할 플레이어의 번호이고, 플레이어의 번호는 0부터 시작한다. 매 턴에서 받을 수 있는 최대 사탕의 개수는 1개뿐이다.
자료구조의 특이사항은 매 턴에서 받을 수 있는 사탕의 개수를 한 개로 제한하기 위해 해당 턴에서 사탕을 받았는지 여부를 체크하는 배열과 팔로우 상태를 표현하기 위한 해시 맵을 사용했다. 플레이어의 번호를 Key값으로 사용하고, Value 값으로 해당 플레이어가 팔로우하는 플레이어를 추가할 수 있는 ArrayList를 사용했다.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Main {
static int players; // 플레이어 수
static int[] candy; // 각 플레이어의 사탕 개수
static HashMap<Integer, ArrayList<Integer>> followers; // 팔로워 저장
static boolean[] gotAlready; // 이번 턴에 사탕을 받았는지 여부
static int turn; // 순서
public static void main(String[] args) throws Exception {
// 5
// A A A A
// 5
// J A Q A J A
Scanner sc = new Scanner(System.in);
players = Integer.parseInt(sc.nextLine());
candy = new int[players];
gotAlready = new boolean[players];
followers = new HashMap<>();
for (int i = 0; i < players; i++) {
followers.put(i, new ArrayList<Integer>());
}
turn = 0;
String openedCards = sc.nextLine();
StringTokenizer st = new StringTokenizer(openedCards, " ");
String card = "";
while (st.hasMoreTokens()) {
if (turn >= players) turn = 0;
card = st.nextToken();
if (card.equals("K")) {
continue;
} else if (card.equals("Q")) {
giveCandyToAll();
} else if (card.equals("J")) {
giveCandytoBothSides(turn);
resetGotAlready();
} else if (card.equals("A")) {
giveCandyToPlayer(turn);
resetGotAlready();
} else {
followers.get(turn).add(Integer.parseInt(card));
}
turn++;
}
print();
}
static public void print() {
for (int i = 0; i < candy.length; i++) {
if (i == 0)
System.out.print(candy[i]);
else
System.out.print(" " + candy[i]);
}
}
static public void giveCandyToPlayer(int currentPlayer) {
if (!gotAlready[currentPlayer]) {
candy[currentPlayer]++;
gotAlready[currentPlayer] = true;
}
giveCandyToHisFollowers(currentPlayer);
}
static private void giveCandyToHisFollowers(int currentPlayer) {
if (!followers.get(currentPlayer).isEmpty())
for (int i = 0; i < followers.get(currentPlayer).size(); i++)
if (!gotAlready[followers.get(currentPlayer).get(i)]) {
candy[followers.get(currentPlayer).get(i)]++;
gotAlready[followers.get(currentPlayer).get(i)] = true;
giveCandyToHisFollowers(followers.get(currentPlayer).get(i));
}
}
static public void giveCandytoBothSides(int currentPlayer) {
if (currentPlayer <= 0) {
giveCandyToPlayer(players-1);
giveCandyToPlayer(currentPlayer+1);
} else if (currentPlayer == players-1) {
giveCandyToPlayer(currentPlayer-1);
giveCandyToPlayer(0);
} else {
giveCandyToPlayer(currentPlayer-1);
giveCandyToPlayer(currentPlayer+1);
}
}
static public void giveCandyToAll() {
for (int i = 0; i < players; i++)
candy[i]++;
}
static public void resetGotAlready() {
for (int i = 0; i < players; i++)
if (gotAlready[i])
gotAlready[i] = false;
}
static void makeCircle() {
}
}
플레이어와 관련된 상태와 행위가 많기 때문에 플레이어 객체를 생성해서 짜보는 것이 좋을 것 같다. 최근에 푼 문제중에 제일 재밌었다. 오늘은 여기까지!
'개발 > 알고리즘' 카테고리의 다른 글
[프로그래머스] 오른쪽에서 왼쪽으로 n회 접은 종이의 상태 나타내기 (0) | 2019.10.28 |
---|---|
[Codility] Find the Longest Substring without Repeating Characters Three Times in a Row (0) | 2019.10.05 |
삼항연산자, 비교연산자, Math.max()를 이용한 최대값 구하기 비교 (0) | 2019.09.28 |
[백준] 회전하는 큐(1021) (0) | 2019.09.27 |
[구름] 전광판 광고 (0) | 2019.09.24 |