[카카오 인턴] 키패드 누르기
📑 문1) 스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.
이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.
제한사항
입출력 예
numbers | hand | result |
---|---|---|
[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] | right | LRLLLRLLRRL |
[7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] | left | LRLLRRLLLRR |
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0] | right | LLRLLRLLRL |
입출력 예 설명
입출력 예 #1
순서대로 눌러야 할 번호가 [1,3,4,5,8,2,1,4,5,9,5]
이고, 오른손잡이입니다.
왼손 위치 | 오른손 위치 | 눌러야 할 숫자 | 사용한 손 | 설명 |
---|---|---|---|---|
* | # | 1 | L | 1은 왼손으로 누릅니다. |
1 | # | 3 | R | 3은 오른손으로 누릅니다. |
1 | 3 | 4 | L | 4는 왼손으로 누릅니다. |
4 | 3 | 5 | L | 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다. |
5 | 3 | 8 | L | 왼손 거리는 1, 오른손 거리는 3이므로 왼손으로 8을 누릅니다. |
8 | 3 | 2 | R | 왼손 거리는 2, 오른손 거리는 1이므로 오른손으로 2를 누릅니다. |
8 | 2 | 1 | L | 1은 왼손으로 누릅니다. |
1 | 2 | 4 | L | 4는 왼손으로 누릅니다. |
4 | 2 | 5 | R | 왼손 거리와 오른손 거리가 1로 같으므로, 오른손으로 5를 누릅니다. |
4 | 5 | 9 | R | 9는 오른손으로 누릅니다. |
4 | 9 | 5 | L | 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다. |
5 | 9 | - | - |
따라서 "LRLLLRLLRRL"를 return 합니다.
입출력 예 #2
왼손잡이가 [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2]
를 순서대로 누르면 사용한 손은 "LRLLRRLLLRR"
이 됩니다.
입출력 예 #3
오른손잡이가 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
를 순서대로 누르면 사용한 손은 "LLRLLRLLRL"
이 됩니다.
나의 풀이
package programmers;
public class PressTheKeypad {
public static String solution(int[] numbers, String hand) {
String answer = "";
int[] left = {3,0}; // *의 위치
int[] right = {3,2}; //#의 위치
int[][] keyPad = {
{0, 0}, {0, 1}, {0, 2},
{1, 0}, {1, 1}, {1, 2},
{2, 0}, {2, 1}, {2, 2},
{3, 0}, {3, 1}, {3, 2}
};
for(int number: numbers) {
if(number == 1 || number == 4 || number == 7) {
answer += "L";
left = keyPad[number - 1];
} else if(number == 3 || number == 6 || number == 9) {
answer += "R";
right = keyPad[number - 1];
} else {
if(number == 0) number = 11;
int leftDist = Math.abs(left[0] - keyPad[number-1][0]) + Math.abs(left[1] - keyPad[number-1][1]);
int rightDist = Math.abs(right[0] - keyPad[number-1][0]) + Math.abs(right[1] - keyPad[number-1][1]);
if(leftDist < rightDist) {
answer += "L";
left = keyPad[number - 1];
} else if(leftDist > rightDist) {
answer += "R";
right = keyPad[number - 1];
} else {
if(hand.equals("left")) {
answer += "L";
left = keyPad[number - 1];
} else {
answer += "R";
right = keyPad[number - 1];
}
}
}
}
System.out.println(answer);
return answer;
}
public static void main(String[] args) {
solution(new int[] {1,3,4,5,8,2,1,4,5,9,5}, "right");
}
}
나의 생각
keyPad
의 위치를 좌표로 변환한 값을 2차원 배열에 저장하고, 처음 오른손, 왼손 엄지의 위치 좌표를 1차원 배열로 저장하였다. 자판을 입력할 매개변수 numbers
를 반복 돌려, 숫자 1,4,7 은 무조건 L
, 숫자 3,6,9는 무조건 R
이며 , 현재 hand의 위치에 따라 숫자 2,5,8,0은 오른손으로 입력할 지, 왼손으로 입력할 지가 달라지는데 이를 위한 임시 변수가 left
,right
에 저장된다. 여기서 number -1
의 이유는 index가 0부터 시작하기 때문이다. 핵심 로직을 보면 다음과 같다.
else {
if(number == 0) number = 11;
int leftDist = Math.abs(left[0] - keyPad[number-1][0]) + Math.abs(left[1] - keyPad[number-1][1]);
int rightDist = Math.abs(right[0] - keyPad[number-1][0]) + Math.abs(right[1] - keyPad[number-1][1]);
if(leftDist < rightDist) {
answer += "L";
left = keyPad[number - 1];
} else if(leftDist > rightDist) {
answer += "R";
right = keyPad[number - 1];
} else {
if(hand.equals("left")) {
answer += "L";
left = keyPad[number - 1];
} else {
answer += "R";
right = keyPad[number - 1];
}
}
}
}
number = 0
은 숫자 11로 대체되고, leftDist, rightDist 즉, 오른손, 왼손의 거리를 구하여 가까운 위치에 있는 손가락으로 입력하는 하는것이다.
📑 문2) 카카오에 입사한 신입 개발자 네오는 "카카오계정개발팀"에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. "네오"에게 주어진 첫 업무는 새로 가입하는 유저들이 카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 추천해주는 프로그램을 개발하는 것입니다.
다음은 카카오 아이디의 규칙입니다.
"네오"는 다음과 같이 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해 주려고 합니다.
신규 유저가 입력한 아이디가 new_id 라고 한다면,
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
예를 들어, new_id 값이 "...!@BaT#*..y.abcdefghijklm" 라면, 위 7단계를 거치고 나면 new_id는 아래와 같이 변경됩니다.
1단계 대문자 'B'와 'T'가 소문자 'b'와 't'로 바뀌었습니다.
"...!@BaT#*..y.abcdefghijklm" → "...!@bat#*..y.abcdefghijklm"
2단계 '!', '@', '#', '' 문자가 제거되었습니다.
`"...!@bat#..y.abcdefghijklm" → "...bat..y.abcdefghijklm"`
3단계 '...'와 '..' 가 '.'로 바뀌었습니다.
"...bat..y.abcdefghijklm" → ".bat.y.abcdefghijklm"
4단계 아이디의 처음에 위치한 '.'가 제거되었습니다.
".bat.y.abcdefghijklm" → "bat.y.abcdefghijklm"
5단계 아이디가 빈 문자열이 아니므로 변화가 없습니다.
"bat.y.abcdefghijklm" → "bat.y.abcdefghijklm"
6단계 아이디의 길이가 16자 이상이므로, 처음 15자를 제외한 나머지 문자들이 제거되었습니다.
"bat.y.abcdefghijklm" → "bat.y.abcdefghi"
7단계 아이디의 길이가 2자 이하가 아니므로 변화가 없습니다.
"bat.y.abcdefghi" → "bat.y.abcdefghi"
따라서 신규 유저가 입력한 new_id가 "...!@BaT#*..y.abcdefghijklm"일 때, 네오의 프로그램이 추천하는 새로운 아이디는 "bat.y.abcdefghi" 입니다.
신규 유저가 입력한 아이디를 나타내는 new_id가 매개변수로 주어질 때, "네오"가 설계한 7단계의 처리 과정을 거친 후의 추천 아이디를 return 하도록 solution 함수를 완성해 주세요.
제한사항
newid는 길이 1 이상 1,000 이하인 문자열입니다.
new_id는 알파벳 대문자, 알파벳 소문자, 숫자, 특수문자로 구성되어 있습니다.
new_id에 나타날 수 있는 특수문자는 `-.~!@#$%^&*()=+[{]}:?,<>/` 로 한정됩니다.
입출력 예
no | new_id | result |
---|---|---|
예1 | "...!@BaT#*..y.abcdefghijklm" | "bat.y.abcdefghi" |
예2 | "z-+.^." | "z--" |
예3 | "=.=" | "aaa" |
예4 | "123_.def" | "123_.def" |
예5 | "abcdefghijklmn.p" | "abcdefghijklmn" |
입출력 예 설명
입출력 예 #2
입출력 예 #3
입출력 예 #4
입출력 예 #5
1단계 변화 없습니다.
2단계 변화 없습니다.
3단계 변화 없습니다.
4단계 변화 없습니다.
5단계 변화 없습니다.
6단계 "abcdefghijklmn.p" → "abcdefghijklmn." → "abcdefghijklmn"
7단계 변화 없습니다.
나의 풀이
package programmers;
public class IdRecommendation {
public static String solution(String new_id) {
new_id = new_id.toLowerCase();
new_id = new_id.replaceAll("[^a-z0-9-_.]", "");
new_id = new_id.replaceAll("\\.{2,}", ".");
new_id = new_id.replaceAll("^[.]|[.]$","");
if(new_id.isEmpty()) {
new_id = "a";
}
if(new_id.length() >= 16) {
new_id = new_id.substring(0,15);
if(new_id.endsWith(".")) {
new_id = new_id.substring(0,new_id.length() -1);
}
}
if(new_id.length() <= 2) {
while(new_id.length() < 3) {
new_id += new_id.charAt(new_id.length() - 1);
}
}
System.out.println(new_id);
return new_id;
}
public static void main(String[] args) {
solution("=.=");
}
}
나의 생각
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.
6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.
먼저, 각 단계를 설명을 자세히 하였기 때문에, 한줄씩 코드를 작성해보자.
new_id = new_id.toLowerCase();
[^a-z0-9-_.]
를 하나씩 분석해보면, ^
: 대괄호 안의 첫 번째 문자로 나오면, 대괄호 안에 나열된 문자들과 일치하지 않는 문자를 찾는 부정 문자 클래스를 정의a-z
: 소문자 알파벳 'a'부터'z'까지의 모든 문자와 일치0-9
: 숫자'0'부터 '9'까지의 모든 숫자와 일치-,_
: 하이픈, 마침표 자체와 일치new_id = new_id.replaceAll("\\.{2,}", ".");
\\.
: 마침표(.)는 정규 표현식에서 특별한 의미를 가지므로, 리터럴 문자로 사용하려면 이스케이프가 필요함. 자바에서 문자열 내에서 정규 표현식을 사용하면, 첫 번째 역슬래시(\
)가 자자 문자열 내에서의 이스케이프 문자로 처리되므로, 마침표를 리터럴로 사용하려면 두 개의 역슬래시(\\.
)가 필요함{2,}
: 이 부분은 직전의 문자나 그룹(여기서는 마침표)이 2번 이상 연속으로 나타내는 부분new_id = new_id.replaceAll("^[.]|[.]$","");
대괄호안([^]
)에 존재하면 부정을 나타내지만 ^[]
은 시작을 의미하며, []$
은 끝 부분을 의미한다. 따라서, 시작부분에 . 또는 끝 부분에 . 이 있으면~
으로 해석할 수 있다.
if(new_id.isEmpty()) {
new_id = "a";
}
if(new_id.length() >= 16) {
new_id = new_id.substring(0,15);
if(new_id.endsWith(".")) {
new_id = new_id.substring(0,new_id.length() -1);
}
}
16자 이상이면, 첫 15개의 문자를 제외한 나머지를 자르고 만약 제거 후 마침표(.)가 new_id끝에 존재하면 마침표를 제거하는 로직
if(new_id.length() <= 2) {
while(new_id.length() < 3) {
new_id += new_id.charAt(new_id.length() - 1);
}
}
new_id의 길이가 2자 이하면, 길이가 3이 될때까지 무한 반복을 돌려, 마지막 글자를 끝에 붙이는 로직
빌더패턴을 사용한 로직 구현
package programmers;
public class IdBuilderPattern {
public static String solution(String new_id) {
String s = new KakaoID(new_id)
.replaceToLowerCase() // 모든 대문자를 소문자로 변환
.filter() // 허용된 문자만 남김
.toSingleDot() // 연속된 마침표를 하나로 치환
.noStartEndDot() // 시작과 끝의 마침표 제거
.noBlank() // 빈 문자열을 "a"로 치환
.noGreaterThan16() // 16자 이상이면 자름
.noLessThan2() // 2자 이하라면 마지막 문자 반복
.getResult(); // 최종 결과 반환
//System.out.println(s);
return s;
}
private static class KakaoID {
private String s;
KakaoID(String s) {
this.s = s;
System.out.println(s);
}
private KakaoID replaceToLowerCase() {
s = s.toLowerCase();
return this;
}
private KakaoID filter() {
s = s.replaceAll("[^a-z0-9-_.]", "");
return this;
}
private KakaoID toSingleDot() {
s = s.replaceAll("[.]{2,}", ".");
return this;
}
private KakaoID noStartEndDot() {
s = s.replaceAll("^[.]|[.]$", "");
return this;
}
private KakaoID noBlank() {
s = s.isEmpty() ? "a": s ;
return this;
}
private KakaoID noGreaterThan16() {
if(s.length() >= 16) {
s = s.substring(0,15);
}
s = s.replaceAll("[.]$", "");
return this;
}
private KakaoID noLessThan2() {
StringBuilder sb = new StringBuilder(s);
while (sb.length() < 3) {
sb.append(sb.charAt(sb.length() - 1));
}
s = sb.toString();
return this;
}
private String getResult() {
return s;
}
}
public static void main(String[] args) {
solution("===");
}
}
📑 문3) 햄버거 가게에서 일을 하는 상수는 햄버거를 포장하는 일을 합니다. 함께 일을 하는 다른 직원들이 햄버거에 들어갈 재료를 조리해 주면 조리된 순서대로 상수의 앞에 아래서부터 위로 쌓이게 되고, 상수는 순서에 맞게 쌓여서 완성된 햄버거를 따로 옮겨 포장을 하게 됩니다. 상수가 일하는 가게는 정해진 순서(아래서부터, 빵 – 야채 – 고기 - 빵)로 쌓인 햄버거만 포장을 합니다. 상수는 손이 굉장히 빠르기 때문에 상수가 포장하는 동안 속 재료가 추가적으로 들어오는 일은 없으며, 재료의 높이는 무시하여 재료가 높이 쌓여서 일이 힘들어지는 경우는 없습니다.
예를 들어, 상수의 앞에 쌓이는 재료의 순서가 [야채, 빵, 빵, 야채, 고기, 빵, 야채, 고기, 빵]
일 때, 상수는 여섯 번째 재료가 쌓였을 때, 세 번째 재료부터 여섯 번째 재료를 이용하여 햄버거를 포장하고, 아홉 번째 재료가 쌓였을 때, 두 번째 재료와 일곱 번째 재료부터 아홉 번째 재료를 이용하여 햄버거를 포장합니다. 즉, 2개의 햄버거를 포장하게 됩니다.
상수에게 전해지는 재료의 정보를 나타내는 정수 배열 ingredient가 주어졌을 때, 상수가 포장하는 햄버거의 개수를 return 하도록 solution 함수를 완성하시오.
제한사항
입출력 예
ingredient | result |
---|---|
[2,1,1,2,3,1,2,3,1] | 2 |
[1,3,2,1,2,1,3,1,2] | 0 |
입출력 예 설명
입출력 예 #2
나의 풀이
실패한 로직
package programmers;
public class makingHamburgers {
public static int solution(int[] ingredients) {
int cnt = 0;
StringBuilder hamburger = new StringBuilder();
for(int ingredient : ingredients) {
hamburger.append(Integer.toString(ingredient));
}
while(hamburger.toString().contains("1231")) {
hamburger = new StringBuilder(hamburger.toString().replaceAll("1231", ""));
cnt++;
}
System.out.println(cnt);
return cnt;
}
public static void main(String[] args) {
solution(new int[] {1, 3, 2, 1, 2, 1, 3, 1, 2});
}
}
잘못 구현한 이유
replaceAll
메서드는 문자열에서 존재하는 모든 특정 문자 예) 1231
을 ""
로 바꾸기 때문에 예상치못한 오류가 발생할 수 있음시간 초과로 실패한 로직 (위의 오류는 수정)
package programmers;
public class makingHamburgers {
public static int solution(int[] ingredients) {
int cnt = 0;
StringBuilder hamburger = new StringBuilder();
for(int ingredient : ingredients) {
hamburger.append(Integer.toString(ingredient));
}
while(true) {
int index = hamburger.indexOf("1231");
if(index == -1) {
break;
}
hamburger.replace(index, index + 4, "");
cnt++;
}
System.out.println(cnt);
return cnt;
}
public static void main(String[] args) {
solution(new int[] {2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 3, 1, 3, 1});
}
}
스택을 적용한 로직
package programmers;
import java.util.Stack;
public class makingHamburgers {
public static int solution(int[] ingredients) {
int cnt = 0;
Stack<Integer> stack = new Stack<>();
for(int ingredient : ingredients) {
stack.push(ingredient);
if(stack.size() >= 4) {
int last = stack.pop();
int third = stack.pop();
int second = stack.pop();
int first = stack.pop();
if (first == 1 && second == 2 && third == 3 && last == 1) {
cnt++;
} else {
stack.push(first);
stack.push(second);
stack.push(third);
stack.push(last);
}
}
}
System.out.println(stack);
System.out.println(cnt);
return cnt;
}
public static void main(String[] args) {
solution(new int[] {2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 3, 1, 3, 1});
}
}
stack 클래스를 쓰지않는 방법
package programmers;
import java.util.Arrays;
public class makingHamburgers {
public static int solution(int[] ingredients) {
int[] stack = new int[ingredients.length];
int index = 0;
int cnt = 0;
for(int ingredient : ingredients) {
stack[index++] = ingredient;
System.out.println(Arrays.toString(stack));
if(index >= 4 && stack[index - 1] == 1
&& stack[index - 2] == 3
&& stack[index - 3] == 2
&& stack[index - 4] == 1) {
index -= 4;
cnt++;
}
}
System.out.println(cnt);
return cnt;
}
public static void main(String[] args) {
solution(new int[] {2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 3, 1, 3, 1});
}
}
📑 문4) 나만의 카카오 성격 유형 검사지를 만들려고 합니다.
성격 유형 검사는 다음과 같은 4개 지표로 성격 유형을 구분합니다. 성격은 각 지표에서 두 유형 중 하나로 결정됩니다.
지표 번호 | 성격 유형 |
---|---|
1번 지표 | 라이언형(R), 튜브형(T) |
2번 지표 | 콘형(C), 프로도형(F) |
3번 지표 | 제이지형(J), 무지형(M) |
4번 지표 | 어피치형(A), 네오형(N) |
4개의 지표가 있으므로 성격 유형은 총 16(=2 x 2 x 2 x 2)가지가 나올 수 있습니다. 예를 들어, "RFMN"이나 "TCMA"와 같은 성격 유형이 있습니다.
검사지에는 총 n개의 질문이 있고, 각 질문에는 아래와 같은 7개의 선택지가 있습니다.
매우 비동의
비동의
약간 비동의
모르겠음
약간 동의
동의
매우 동의
각 질문은 1가지 지표로 성격 유형 점수를 판단합니다.
예를 들어, 어떤 한 질문에서 4번 지표로 아래 표처럼 점수를 매길 수 있습니다.
선택지 | 성격 유형 점수 |
---|---|
매우 비동의 | 네오형 3점 |
비동의 | 네오형 2점 |
약간 비동의 | 네오형 1점 |
모르겠음 | 어떤 성격 유형도 점수를 얻지 않습니다 |
약간 동의 | 어피치형 1점 |
동의 | 어피치형 2점 |
매우 동의 | 어피치형 3점 |
이때 검사자가 질문에서 약간 동의 선택지를 선택할 경우 어피치형(A) 성격 유형 1점을 받게 됩니다. 만약 검사자가 매우 비동의 선택지를 선택할 경우 네오형(N) 성격 유형 3점을 받게 됩니다.
위 예시처럼 네오형이 비동의, 어피치형이 동의인 경우만 주어지지 않고, 질문에 따라 네오형이 동의, 어피치형이 비동의인 경우도 주어질 수 있습니다.
하지만 각 선택지는 고정적인 크기의 점수를 가지고 있습니다.
매우 동의
나 매우 비동의
선택지를 선택하면 3점을 얻습니다.동의
나 비동의
선택지를 선택하면 2점을 얻습니다.약간 동의
나 약간 비동의
선택지를 선택하면 1점을 얻습니다.모르겠음
선택지를 선택하면 점수를 얻지 않습니다.검사 결과는 모든 질문의 성격 유형 점수를 더하여 각 지표에서 더 높은 점수를 받은 성격 유형이 검사자의 성격 유형이라고 판단합니다. 단, 하나의 지표에서 각 성격 유형 점수가 같으면, 두 성격 유형 중 사전 순으로 빠른 성격 유형을 검사자의 성격 유형이라고 판단합니다.
질문마다 판단하는 지표를 담은 1차원 문자열 배열 survey와 검사자가 각 질문마다 선택한 선택지를 담은 1차원 정수 배열 choices가 매개변수로 주어집니다. 이때, 검사자의 성격 유형 검사 결과를 지표 번호 순서대로 return 하도록 solution 함수를 완성해주세요.
제한사항
1 ≤ survey의 길이 ( = n) ≤ 1,000
choices의 길이 = survey의 길이
choices | 뜻 |
---|---|
1 | 매우 비동의 |
2 | 비동의 |
3 | 약간 비동의 |
4 | 모르겠음 |
5 | 약간 동의 |
6 | 동의 |
7 | 매우 동의 |
입출력 예
survey | choices | result |
---|---|---|
"AN", "CF", "MJ", "RT", "NA" | [5, 3, 2, 7, 5] | "TCMA" |
"TR", "RT", "TR" | [7, 1, 3] | "RCJA" |
나의 풀이
package programmers;
import java.util.HashMap;
public class PersonalityTypeTest {
public static String solution(String[] surveys, int[] choices) {
String answer = "";
HashMap<Character, Integer> map = new HashMap<>();
char[] possibleChars = {'R', 'T', 'C', 'F', 'J', 'M', 'A', 'N'};
for (char ch : possibleChars) {
map.put(ch, 0);
}
for(int i = 0; i < surveys.length; i++) {
if(choices[i] > 4) {
map.put(surveys[i].charAt(1), map.get(surveys[i].charAt(1)) + choices[i] - 4);
}else {
map.put(surveys[i].charAt(0), map.get(surveys[i].charAt(0)) + 4 - choices[i]);
}
}
if (map.get('R') >= map.get('T'))
answer += "R";
else
answer += "T";
if (map.get('C') >= map.get('F'))
answer += "C";
else
answer += "F";
if (map.get('J') >= map.get('M'))
answer += "J";
else
answer += "M";
if (map.get('A') >= map.get('N'))
answer += "A";
else
answer += "N";
return answer;
}
public static void main(String[] args) {
solution(new String[] {"AN", "CF", "MJ", "RT", "NA"}, new int[] {5,3,2,7,5});
}
}
📑 문5) 코딩테스트를 준비하는 머쓱이는 프로그래머스에서 문제를 풀고 나중에 다시 코드를 보면서 공부하려고 작성한 코드를 컴퓨터 바탕화면에 아무 위치에나 저장해 둡니다. 저장한 코드가 많아지면서 머쓱이는 본인의 컴퓨터 바탕화면이 너무 지저분하다고 생각했습니다. 프로그래머스에서 작성했던 코드는 그 문제에 가서 다시 볼 수 있기 때문에 저장해 둔 파일들을 전부 삭제하기로 했습니다.
컴퓨터 바탕화면은 각 칸이 정사각형인 격자판입니다. 이때 컴퓨터 바탕화면의 상태를 나타낸 문자열 배열 wallpaper가 주어집니다. 파일들은 바탕화면의 격자칸에 위치하고 바탕화면의 격자점들은 바탕화면의 가장 왼쪽 위를 (0, 0)으로 시작해 (세로 좌표, 가로 좌표)로 표현합니다. 빈칸은 ".", 파일이 있는 칸은 "#"의 값을 가집니다. 드래그를 하면 파일들을 선택할 수 있고, 선택된 파일들을 삭제할 수 있습니다. 머쓱이는 최소한의 이동거리를 갖는 한 번의 드래그로 모든 파일을 선택해서 한 번에 지우려고 하며 드래그로 파일들을 선택하는 방법은 다음과 같습니다.
드래그는 바탕화면의 격자점 S(lux, luy)를 마우스 왼쪽 버튼으로 클릭한 상태로 격자점 E(rdx, rdy)로 이동한 뒤 마우스 왼쪽 버튼을 떼는 행동입니다. 이때, "점 S에서 점 E로 드래그한다"고 표현하고 점 S와 점 E를 각각 드래그의 시작점, 끝점이라고 표현합니다.
점 S(lux, luy)에서 점 E(rdx, rdy)로 드래그를 할 때, "드래그 한 거리"는 |rdx - lux| + |rdy - luy|로 정의합니다.
점 S에서 점 E로 드래그를 하면 바탕화면에서 두 격자점을 각각 왼쪽 위, 오른쪽 아래로 하는 직사각형 내부에 있는 모든 파일이 선택됩니다.
예를 들어 wallpaper = [".#...", "..#..", "...#."]인 바탕화면을 그림으로 나타내면 다음과 같습니다.
이러한 바탕화면에서 다음 그림과 같이 S(0, 1)에서 E(3, 4)로 드래그하면 세 개의 파일이 모두 선택되므로 드래그 한 거리 (3 - 0) + (4 - 1) = 6을 최솟값으로 모든 파일을 선택 가능합니다.
(0, 0)에서 (3, 5)로 드래그해도 모든 파일을 선택할 수 있지만 이때 드래그 한 거리는 (3 - 0) + (5 - 0) = 8이고 이전의 방법보다 거리가 늘어납니다.
머쓱이의 컴퓨터 바탕화면의 상태를 나타내는 문자열 배열 wallpaper가 매개변수로 주어질 때 바탕화면의 파일들을 한 번에 삭제하기 위해 최소한의 이동거리를 갖는 드래그의 시작점과 끝점을 담은 정수 배열을 return하는 solution 함수를 작성해 주세요. 드래그의 시작점이 (lux, luy), 끝점이 (rdx, rdy)라면 정수 배열 [lux, luy, rdx, rdy]를 return하면 됩니다.
제한사항
입출력 예
wallpaper | result |
---|---|
[".#...", "..#..", "...#."] | [0,1,3,4] |
["..........", ".....#....", "......##..", "...##.....", "....#....."] | [1,3,5,8] |
[".##...##.", "#..#.#..#", "#...#...#", ".#.....#.", "..#...#..", "...#.#...", "....#...."] | [0,0,7,9] |
["..", "#."] | [1,0,2,1] |
나의 풀이
package programmers;
public class WallPaper {
public static int[] solution(String[] wallpaper) {
int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
for (int i = 0; i < wallpaper.length; i++) {
for (int j = 0; j < wallpaper[i].length(); j++) {
if (wallpaper[i].charAt(j) == '#') {
if (i < minX) minX = i;
if (i > maxX) maxX = i;
if (j < minY) minY = j;
if (j > maxY) maxY = j;
}
}
}
maxX += 1;
maxY += 1;
return new int[]{minX, minY, maxX, maxY};
}
public static void main(String[] args) {
solution(new String[] {".#...", "..#..", "...#."});
}
}
글 재미있게 봤습니다.