1주차가 시작되었다. 현장실습 과정을 진행하며 해당 프리코스를 얼마나 잘해낼지는 모르겠지만 그래도 최선을 다해보려 한다. ! 회사에 있느라 오티 수업을 듣지 못하였다.
출근하면서 듣는걸로
자바를 사용하여 코딩테스트 문제를 푸는게 처음이라 조금 어려울 거라 예상된다. 그래도 1주차는 첫번째 문제는 그렇게 어려운걸 내지 않으셔서 정말 다행이다.
문제는 요기
포비와 크롱이의 쪽수 페이지를 더하거나 곱해서 그 중에 큰 수를 자기 점수로 하여 가장 높은 사람이 게임의 승자가 되게 하는 문제이다.
쪽수가 Integer 형의 List로 들어온다. 문제를 보자마자 생각난 방법은 포비와 크롱이의 쪽수를 반복문을 통해 하나씩 보고 해당 쪽수를 String으로 변환 후 split한다. 그 후 각 자릿수를 다시 Integer형으로 변환하여 덧셈이나 곱셈을 수행하고 큰 값을 자신의 점수로 변경하는 형식의 로직을 생각했다.
그랬더니! 코드가 너무 길고 복잡해지는 기분이라 이걸 어떻게 refactoring 할 수 있을까에 대한 고민이 생긴다.
기능 목록
- 입력 값 예외처리
- 왼쪽이 홀수가 아님
- 페이지의 차이가 1을 넘음
- 맨 앞페이지이거나 맨 뒷페이지인 경우
- 점수 구하기
- 입력 페이지들의 자릿수 분할하기
- 각 자릿수의 덧셈 구하기
- 각 자릿수의 곱셈 구하기
- 구한 값들 중 가장 큰 수를 반환
- 반환된 점수를 자신의 점수로 정하기
- 포비와 크롱의 점수 비교 후 결과 반환
일단 첫 try 코드부터 보여줄궤?
package onboarding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/*
포비와 크롱이 페이지 번호가 1부터 시작되는 400페이지의 책을 주웠다. 책을 살펴보니 왼쪽 페이지는 홀수, 오른쪽 페이지는 짝수 번호이고
모든 페이지에는 번호가 적혀있었다. 책이 마음에 든 포비와 크롱은 페이지 번호 게임을 통해 게임에서 이긴 사람이 책을 갖기로 한다.
페이지 번호 게임의 규칙은 아래와 같다.
1. 책을 임의로 펼친다.
2. 왼쪽 페이지 번호의 각 자리 숫자를 모두 더하거나, 모두 곱해 가장 큰 수를 구한다.
3. 오른쪽 페이지 번호의 각 자리 숫자를 모두 더하거나, 모두 곱해 가장 큰 수를 구한다.
4. 2~3 과정에서 가장 큰 수를 본인의 점수로 한다.
5. 점수를 비교해 가장 높은 사람이 게임의 승자가 된다.
6. 시작 면이나 마지막 면이 나오도록 책을 펼치지 않는다.
포비와 크롱이 펼친 페이지가 들어있는 리스트/배열 pobi와 crong이 주어질 때, 포비가 이긴다면 1, 크롱이 이긴다면 2, 무승부는 0, 예외사항은 -1로
return 하도록 solution 메서드를 완성하라.
*/
class Problem1 {
public static int solution(List<Integer> pobi, List<Integer> crong) {
int answer = Integer.MAX_VALUE;
int pobiMax = Integer.MIN_VALUE;
int crongMax = Integer.MIN_VALUE;
if (pobi.get(1)-pobi.get(0) != 1 || crong.get(1)-crong.get(0) != 1) return -1;
for (Integer pobiVal : pobi) {
List<String> p = Arrays.asList(pobiVal.toString().split(""));
int sum = 0;
int mul = 1;
for (String s : p) {
sum += Integer.parseInt(s);
mul *= Integer.parseInt(s);
}
if (pobiMax < sum) pobiMax = sum;
if (pobiMax < mul) pobiMax = mul;
}
for (Integer crongVal : crong) {
List<String> p = Arrays.asList(crongVal.toString().split(""));
int sum = 0;
int mul = 1;
for (String s : p) {
sum += Integer.parseInt(s);
mul *= Integer.parseInt(s);
}
if (crongMax < sum) crongMax = sum;
if (crongMax < mul) crongMax = mul;
}
if (pobiMax == crongMax) answer = 0;
else if (pobiMax > crongMax) answer = 1;
else if (pobiMax < crongMax) answer = 2;
else answer = -1;
return answer;
}
}
사실 부끄러워 이런 코드
함수를 사용해 봤다.
package onboarding;
import java.util.List;
class Problem1 {
public static int maxVal(List<Integer> pages)
{
int maxVal = Integer.MIN_VALUE;
for (Integer page : pages) {
int sum = 0;
int mul = 1;
for (String strPage : page.toString().split("")) {
sum += Integer.parseInt(strPage);
mul *= Integer.parseInt(strPage);
}
if(maxVal<sum) maxVal = sum;
if(maxVal<mul) maxVal = mul;
}
return maxVal;
}
public static int solution(List<Integer> pobi, List<Integer> crong) {
int answer = Integer.MAX_VALUE;
if ((pobi.get(1)-pobi.get(0) != 1)
|| (crong.get(1)-crong.get(0) != 1)
|| (pobi.get(0) == 1) || (pobi.get(1) == 400)
|| (crong.get(0) == 1) || (crong.get(1) == 400))
{
answer = -1;
return answer;
}
int pobiScore = maxVal(pobi);
int crongScore = maxVal(crong);
if(pobiScore == crongScore) answer = 0;
else if(pobiScore > crongScore) answer = 1;
else answer = 2;
return answer;
}
}
더 좋은 방법이 있을 텐데,,, 머리말려야지..
// for문을 이용한 split -> list 변환
String str = "a,b,c,d,e,f,g";
List<String> list = new ArrayList<String>();
String[] splitStr = str.split(",");
for(int i=0; i<splitStr.length; i++){
list.add(splitStr[i]);
}
// Array.asList를 이용한 변환 ( 위에 방법보다 빠름 )
String str = "a,b,c,d,e,f,g";
List<String> list = Arrays.asList(str.split(","));
연속으로 반복되는 문자들을 차례대로 삭제하며 암호문을 해독하는 문제이다.
반복문을 이용하여 문자들을 앞에서부터 차례로 순차 탐색하여 연속중복문자열을 삭제하는 함수를 생성하여서, 해당 암호문이 해독 될 때까지 (더 이상 연속중복문자가 없을때 까지) 반복하는 방법을 이용하여 문제를 해결하고자 하였다.
다른 방법이 있을 것 같다. 리팩토링 필수 일 듯 싶다.ㅠㅡㅠ
기능 목록
- 중복 문자를 삭제하기
- 문자열의 첫번째 문자부터 마지막 문자까지 탐색
- 연속하는 중복 문자를 삭제
- 처리한 후의 문자열 반환
- 암호문 해독
- 중복 문자가 없을 때까지 중복 문자 삭제
- 결과 반환
일단 첫번째 코드
package onboarding;
import java.util.List;
public class Problem2 {
public static String deleteRepeation(String crypt){
String deleteCrypt = crypt;
if (crypt.equals("") || crypt.charAt(0) == crypt.charAt(1)) return "";
int i = 0;
StringBuilder temp = new StringBuilder();
while(i<deleteCrypt.length()){
if((i+2) < deleteCrypt.length() && deleteCrypt.charAt(i) == deleteCrypt.charAt(i+1))
{
i += 2;
continue;
}
temp.append(deleteCrypt.charAt(i));
i += 1;
}
deleteCrypt = temp.toString();
return deleteCrypt;
}
public static String solution(String cryptogram) {
String answer = "answer";
String deleteCrypt = deleteRepeation(cryptogram);
while(true)
{
if(deleteCrypt.equals(cryptogram)) break;
cryptogram = deleteCrypt;
deleteCrypt = deleteRepeation(cryptogram);
}
answer = cryptogram;
return answer;
}
}
생각해보니 연속 중복 문자를 삭제하는 함수를 저런식으로 작성하면 2번의 연속된 반복문자만 삭제하게 될 것 같다. 이외에 여러가지 예외 상황이 있을 듯한데 지금
졸려서 머리가 안돌아간다.내일의 유진이가 리팩토링 해야 할 것 같다.
수정 했지롱
package onboarding;
import java.util.List;
public class Problem2 {
public static String deleteRepeation(String crypt){
StringBuilder deleteCrypt = new StringBuilder();;
if (crypt.equals("")) return "";
deleteCrypt.append(crypt.charAt(0));
int i = 0;
while(i<crypt.length()-1){
if(crypt.charAt(i) == crypt.charAt(i+1))
{
if (deleteCrypt.charAt(deleteCrypt.length()-1) == crypt.charAt(i))
{
deleteCrypt.delete(deleteCrypt.length()-1,deleteCrypt.length());
}
i += 1;
continue;
}
deleteCrypt.append(crypt.charAt(i+1));
i += 1;
}
return deleteCrypt.toString();
}
public static String solution(String cryptogram) {
String answer = "answer";
String deleteCrypt = deleteRepeation(cryptogram);
while(true)
{
if(deleteCrypt.equals(cryptogram)) break;
cryptogram = deleteCrypt;
deleteCrypt = deleteRepeation(cryptogram);
}
answer = cryptogram;
return answer;
}
}
이제 연속된 문자 여러개 나와도 삭제 가능해졌다. 넣었다 뺏다 하니까 좀 그럴듯 하긴 한디 리팩토링 언제하쥬?
마지막?
해당 number 까지의 3,6,9의 개수를 세서 반환한다.
number 까지의 수를 모두 리스트에 넣어서 문자로 변환, 쪼개서 3,6,9의 개수를 세는 방식 사용한다.
package onboarding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Problem3 {
public static int solution(int number) {
int answer = 0;
List<Integer> range = IntStream.range(1, number+1).boxed().collect(Collectors.toList());
List<String> strRange = new ArrayList<>();
for (Integer num : range) {
strRange.addAll(Arrays.stream(num.toString().split("")).collect(Collectors.toList()));
}
answer += Collections.frequency(strRange,"3");
answer += Collections.frequency(strRange,"6");
answer += Collections.frequency(strRange,"9");
return answer;
}
}
메소드 우애 쪼개누!
청개구리 사전 !
아스키코드 값을 구해서 리스트에서 찾으면 easyyyy 할듯
첫번째
package onboarding;
public class Problem4 {
public static String solution(String word) {
StringBuilder answer = new StringBuilder();
String dictCap = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
String dictSmall = "zyxwvutsrqponmlkjihgfedcba";
int num = 0;
for(int i = 0;i<word.length();i++){
if((int)word.charAt(i) == 32)
{
answer.append(" ");
continue;
}
if(Character.isUpperCase(word.charAt(i)))
{
// 대문자
num = (int)word.charAt(i) - 65;
answer.append(dictCap.charAt(num));
continue;
}
num = (int)word.charAt(i) - 97;
answer.append(dictSmall.charAt(num));
}
return answer.toString();
}
}
돈의 액수 별로 화폐 반환하는 문제!
이거 처음 코테 준비 시작할때 여러번 풀었던 거라 자신이 쪼꿈있다구요!
기능 목록
- 출금할 돈의 화폐별 개수 구하기
- money를 각 화폐단위로 나눈 나머지 구하기
- 나머지를 answer 리스트 추가
- money에서 화폐단위 * 나머지를 빼기
- 위의 과정을 모든 화폐단위 별로 반복
package onboarding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Problem3 {
public static List<String> getStrRange(List<Integer> range) {
List<String> strRange = new ArrayList<>();
for (Integer num : range) {
strRange.addAll(Arrays.stream(num.toString().split("")).collect(Collectors.toList()));
}
return strRange;
}
public static int solution(int number) {
int answer = 0;
List<Integer> range = IntStream.range(1, number+1).boxed().collect(Collectors.toList());
List<String> strRange = getStrRange(range);
answer += Collections.frequency(strRange,"3");
answer += Collections.frequency(strRange,"6");
answer += Collections.frequency(strRange,"9");
return answer;
}
}
이거 살짜쿵 어려웠다 인정? 그리구 테케 추가되면 틀릴거같은 문제라서 다시 봐야할거같움!
기능 목록
- 크루의 닉네임을 두 글자 씩 분할
- 두 글자씩 분할한 닉네임이 2개 이상인 것을 찾기
- 해당 두 글자를 닉네임으로 가진 크루의 이메일 찾기
package onboarding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Problem6 {
public static List<String> solution(List<List<String>> forms) {
List<String> answer = new ArrayList<>();
List<String> sepNames = new ArrayList<>();
for (List<String> form : forms) {
String name = form.get(1);
for(int i = 0;i<name.length()-1;i++)
{
sepNames.add(name.substring(i,i+2));
}
}
String dupName = "";
for (String sepName : sepNames) {
if(Collections.frequency(sepNames,sepName) != 1)
{
dupName = sepName;
break;
}
}
for (List<String> form : forms) {
if (form.get(1).contains(dupName)) answer.add(form.get(0));
}
Collections.sort(answer);
return answer;
}
}
기능 목록
- 모든 사용자의 친구 리스트 생성
- user와 공통된 친구를 가진 경우 10점의 점수 주기
- 타임라인 방문 횟수에 따라 1점의 점수 주기
- 오름차순 정렬 후 반환
package onboarding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Problem7 {
public static List<String> solution(String user, List<List<String>> friends, List<String> visitors) {
List<String> answer = new ArrayList<>();
Map<String,List<String>> friendsList = new HashMap<>();
for (List<String> friend : friends) {
List<String> tmp = friendsList.getOrDefault(friend.get(0), new ArrayList<>());
tmp.add(friend.get(1));
friendsList.put(friend.get(0),tmp);
tmp = friendsList.getOrDefault(friend.get(1),new ArrayList<>());
tmp.add(friend.get(0));
friendsList.put(friend.get(1),tmp);
}
Map<String,Integer> scroeList = new HashMap<>();
for (String name : friendsList.keySet()) {
if(friendsList.get(name).contains(user))
{
for (String f : friendsList.get(name)) {
if(f.equals(user)) continue;
int score = scroeList.getOrDefault(f, 0);
scroeList.put(f,score+10);
}
}
}
for (String visitor : visitors) {
int score = scroeList.getOrDefault(visitor,0);
scroeList.put(visitor,score+1);
}
List<String> keySet = new ArrayList<>(scroeList.keySet());
// Value 값으로 오름차순 정렬
keySet.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return scroeList.get(o2).compareTo(scroeList.get(o1));
}
});
for (String key : keySet) {
if (friendsList.get(user).contains(key)) continue;
answer.add(key);
}
return answer;
}
}
리팩토링 후
package onboarding;
import java.util.*;
public class Problem7 {
public static Map<String, List<String>> getFriendsList(List<List<String>> friends) {
Map<String,List<String>> friendsList = new HashMap<>();
List<String> tmp;
for (List<String> friend : friends) {
tmp = friendsList.getOrDefault(friend.get(0), new ArrayList<>());
tmp.add(friend.get(1));
friendsList.put(friend.get(0),tmp);
tmp = friendsList.getOrDefault(friend.get(1),new ArrayList<>());
tmp.add(friend.get(0));
friendsList.put(friend.get(1),tmp);
}
return friendsList;
}
public static Map<String, Integer> getScoreLists(Map<String,List<String>> friendsList, String user) {
Map<String, Integer> scoreList = new HashMap<>();
for (String name : friendsList.keySet()) {
if(friendsList.get(name).contains(user)) {
for (String friend : friendsList.get(name)) {
if (friend.equals(user)) {
continue;
}
int score = scoreList.getOrDefault(friend,0);
scoreList.put(friend,score+10);
}
}
}
return scoreList;
}
public static void checkVisitor(List<String> visitors, Map<String, Integer> scoreLists) {
for (String visitor : visitors) {
int score = scoreLists.getOrDefault(visitor,0);
scoreLists.put(visitor,score + 1);
}
}
public static List<String> solution(String user, List<List<String>> friends, List<String> visitors) {
List<String> answer = new ArrayList<>();
Map<String,List<String>> friendsList = getFriendsList(friends);
Map<String,Integer> scoreLists = getScoreLists(friendsList,user);
checkVisitor(visitors, scoreLists);
List<String> keySet = new ArrayList<>(scoreLists.keySet());
keySet.sort((o1, o2) -> {
int comp = scoreLists.get(o2).compareTo(scoreLists.get(o1));
if (comp != 0) {
return comp;
}
return o1.compareTo(o2);
});
for (String key : keySet) {
if (friendsList.get(user).contains(key)) continue;
answer.add(key);
}
return answer;
}
}
똑같은 로직으로 이렇게 다양한 코드가 나올수 있음을 알았음!
자바 코딩 컨벤션이라던가 깃 커밋 컨벤션에 대해 알아볼수 있었고 클래스 사용, 객체지향, 일급 컬렉션 등 각종 세세 정보에 대해 배우는 시간을 가질 수 있었다. 자바의 길은 멀고 험난하지만 잘 뚫고 헤쳐나가 봐야징징징
징징거리지마 징징아 😂
토마토님 글 잘 쓰시네요~! 너무 재밌게 읽었어요! 앞으로도 화이팅하세요~~