코드 리뷰 - ChatGPT
44. 2016년
페어 프로그래밍 코드
package pair5;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.Locale;
/**
* 2016년
* 2016년 1월 1일은 금요일입니다.
* 2016년 a월 b일은 무슨 요일일까요?
* 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, `solution`을 완성하세요.
*/
public class Calender {
// [31 29 31 30 31 30 31 31 30 31 30 31]
// a = 월, b = 일
// 1월 1일 = 금
// 1월 8일 = 금 ... 29일 = 금
// 2월 5일 = 금
private static String solution(int a, int b) {
String answer = "";
int[] days = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
String[] week = {"THU", "FRI", "SAT", "SUN", "MON", "TUE", "WED"};
int sum = 0;
for (int i=0; i<a-1; i++) {
sum += days[i];
}
sum += b;
int remain = sum % 7;
answer = week[remain];
return answer;
}
// 다른 방법
// 2016년에서 사용자가 a : 월, b : 일
public static String getDayOfWeekUpperCase(int month, int day) {
// LocalDate 객체 생성
LocalDate date = LocalDate.of(2016, month, day);
// 요일 정보를 가져옴
DayOfWeek dayOfWeek = date.getDayOfWeek();
// 요일 정보를 short 형식으로 받고, 모두 대문자로 변환
String dayOfWeekShortUpperCase = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.US).toUpperCase();
return dayOfWeekShortUpperCase;
}
public static void main(String[] args) {
System.out.println(getDayOfWeekUpperCase(2,6));
String answer = Calender.solution(5, 24);
System.out.println(getDayOfWeekUpperCase(2,6));
}
}
코드 리뷰
- 가독성
- 코드는 매우 간결하고 이해하기 쉽습니다. 변수 이름이 명확하고, 주석도 적절하게 사용되었습니다.
- LocalDate와 DayOfWeek 클래스를 사용하여 날짜와 요일을 처리하는 방법은 자바에서 날짜와 시간을 다룰 때의 표준 접근 방식입니다.
- 성능
- 성능에 대한 우려는 거의 없습니다. 이 코드는 단일 연산에서 실행되며, LocalDate 클래스는 날짜 관련 계산을 위해 최적화되어 있습니다.
- 이 경우 성능 최적화를 위해 변경할 수 있는 부분은 별로 없으며, 제공된 입력 범위 내에서 코드는 매우 효율적으로 실행될 것입니다.
- 확장성과 유지보수
- 이 함수는 2016년 한 해에만 국한되어 있으며, 다른 연도의 날짜를 처리하도록 확장하려면 연도를 매개변수로 추가하는 등 코드 수정이 필요합니다.
- 유지보수 측면에서 코드는 매우 깔끔하고 잘 구조화되어 있어, 필요한 변경이나 확장이 용이합니다.
- 개선사항
- TextStyle.SHORT 대신 TextStyle.FULL을 사용하여 요일을 전체 이름으로 반환하도록 변경할 수 있지만, 문제 요구 사항에 따라 SHORT 형식이 적절합니다.
- 코드의 유연성을 높이고자 한다면, Locale을 하드코딩하는 대신 함수의 매개변수로부터 받을 수 있도록 하는 것도 고려할 수 있습니다. 이렇게 하면 다른 로케일에 대해서도 코드를 사용할 수 있게 됩니다.
45. 카드 뭉치
페어 프로그래밍 코드
package pair5;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.LinkedList;
import java.util.Queue;
/**
* 카드 뭉치
* 원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다.
* 한 번 사용한 카드는 다시 사용할 수 없습니다.
* 카드를 사용하지 않고 다음 카드로 넘어갈 수 없습니다.
* 기존에 주어진 카드 뭉치의 단어 순서는 바꿀 수 없습니다.
*
* 문자열로 이루어진 배열 cards1, cards2와 원하는 단어 배열 goal이 매개변수로 주어질 때,
* cards1과 cards2에 적힌 단어들로
* goal를 만들 있다면 "Yes"를, 만들 수 없다면 "No"를
* return하는 solution 함수를 완성해주세요.
*/
public class PackOfCards {
private static String solution(String[] cards1, String[] cards2, String[] goal) {
String answer = "Yes";
List<String> cardsList1 = new ArrayList<>(Arrays.asList(cards1));
List<String> cardsList2 = new ArrayList<>(Arrays.asList(cards2));
for (int i=0; i<goal.length; i++) {
if (!cardsList1.isEmpty() && cardsList1.get(0).equals(goal[i])) {
cardsList1.remove(goal[i]);
} else if (!cardsList2.isEmpty() && cardsList2.get(0).equals(goal[i])) {
cardsList2.remove(goal[i]);
} else {
return "No";
}
}
// Queue 사용 방법
// cards1, cards2를 Queue로 변환
// Queue<String> card1 = new LinkedList<>(Arrays.asList(cards1));
// Queue<String> card2 = new LinkedList<>(Arrays.asList(cards2));
//
// for (int i = 0; i < goal.length; i++) {
// if (!card1.isEmpty() && card1.peek().equals(goal[i])) {
// card1.poll();
// } else if (!card2.isEmpty() && card2.peek().equals(goal[i])) {
// card2.poll();
// } else {
// return "No";
// }
// }
return answer;
}
public static void main(String[] args) {
String[] cards1 = {"i", "drink", "water"};
String[] cards2 = {"want", "to"};
String[] goal = {"i", "want", "to", "drink", "water"};
String answer = solution(cards1, cards2, goal);
System.out.println(answer);
}
}
코드 리뷰
- 가독성
- 변수명과 메소드 구조가 명확하며, 주석이나 추가 설명 없이도 코드의 의도와 로직을 이해하기 쉽습니다.
- Queue 인터페이스를 사용하여 카드 뭉치를 관리하는 방식은 이 문제에 적합하며, poll() 메소드를 사용해 카드를 순서대로 처리하는 로직이 직관적입니다.
- 성능
- LinkedList를 사용한 Queue 구현은 이 경우에 적절합니다. 각 카드를 확인하고 제거하는데 상수 시간(O(1))이 소요되므로, 전체적인 성능은 좋습니다.
- 전체 로직은 goal 배열의 길이에 비례하는 시간복잡도를 가집니다(O(n)), 여기서 n은 goal 배열의 길이입니다. 이는 주어진 문제를 해결하는 데 있어 효율적입니다.
- 확장성과 유지보수
- 코드는 주어진 문제에 특화되어 있으며, 다른 유형의 카드 게임이나 더 복잡한 규칙에 적용하려면 수정이 필요할 수 있습니다. 그러나 현재 형태로는 문제 요구사항을 잘 충족합니다.
- 유지보수 측면에서, 변수와 로직이 간결하므로 필요한 변경을 적용하기 쉬울 것입니다.
- 개선사항
- 코드는 이미 깔끔하고 효율적으로 작성되어 있어서, 기능적인 측면에서의 개선점은 크게 보이지 않습니다.
- 더 복잡한 시나리오를 고려하지 않는 이상, 현재 로직의 구조를 변경할 필요는 없어 보입니다.
- 다만, 문제의 복잡도나 요구사항이 확장될 경우, 예를 들어 카드를 건너뛰거나 다시 사용할 수 있는 규칙이 추가된다면, 현재 로직을 조정하거나 새로운 데이터 구조를 도입해야 할 수 있습니다.
46. 과일 장수
페어 프로그래밍 코드
package pair5;
import java.util.Arrays;
public class Fruit {
/**
* 과일 장수
* 사과 1개의 점수 = k
* 상자 1개당 사과 개수 = m
* 상자에 들어 있는 가장 낮은 점수의 사과 = p
* 1개의 상자 가격 = p * m
* 각가의 사과의 점수 배열 = score
* [1,1,1,2,2,3,3]
*/
public static int solution(int k, int m, int[] score) {
int answer = 0;
Arrays.sort(score); // 사과 점수 별 오름차순
for (int i = score.length-1; i >= m-1; i -= m) {
answer += score[i-m+1] * m;
}
return answer;
}
public static void main(String[] args) {
// int[] score = {1, 2, 3, 1, 2, 3, 1};
int[] score = {4, 1, 2, 2, 4, 4, 4, 4, 1, 2, 4, 2};
System.out.println(solution(4, 3, score));
}
}
코드 리뷰
- 문제점
- .잘못된 최소 점수 계산: 코드에서 min 변수는 사용되지 않습니다. 이 변수는 원래 상자에 담긴 사과 중 가장 낮은 점수를 의미하는 것 같지만, 실제 계산에는 영향을 주지 않습니다.
47. 모의고사 완전 탐색
페어 프로그래밍 코드
package test3;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test47 {
public static int[] solution(int[] answers) {
int[] one = {1, 2, 3, 4, 5};
int[] two = {2, 1, 2, 3, 2, 4, 2, 5};
int[] three = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int oneCnt = 0;
int twoCnt = 0;
int threeCnt = 0;
for (int i = 0; i < answers.length; i++) {
if (answers[i] == one[i % one.length]) oneCnt++;
if (answers[i] == two[i % two.length]) twoCnt++;
if (answers[i] == three[i % three.length]) threeCnt++;
}
int[] arr = new int[]{oneCnt, twoCnt, threeCnt};
Arrays.sort(arr);
int max = arr[2];
List<Integer> list = new ArrayList<>();
if (oneCnt == max) list.add(1);
if (twoCnt == max) list.add(2);
if (threeCnt == max) list.add(3);
int[] answer = list.stream().mapToInt(i -> i).toArray();
return answer;
}
}
코드 리뷰
- 가독성
- 코드는 매우 간결하고 명확합니다. 변수 이름(one, two, three, oneCnt, twoCnt, threeCnt)은 각각의 용도를 잘 나타내며, 코드의 의도를 쉽게 이해할 수 있도록 돕습니다.
- 반복문과 조건문은 명확하게 구성되어 있어, 각 수포자가 어떻게 답안을 찍는지와 이를 어떻게 카운팅하는지 쉽게 파악할 수 있습니다.
- 성능
- 반복문과 조건문은 명확하게 구성되어 있어, 각 수포자가 어떻게 답안을 찍는지와 이를 어떻게 카운팅하는지 쉽게 파악할 수 있습니다.
- 확장성
- 현재 코드는 특정한 패턴(one, two, three)과 고정된 수포자 수(3명)에 맞춰져 있습니다. 만약 추가적인 수포자가 등장하거나 패턴이 변경될 경우, 새로운 배열을 추가하고 로직에 반영해야 합니다.
- 확장성을 높이기 위해, 수포자의 답안 패턴을 관리하는 별도의 클래스나 구조체를 도입하고, 이를 일반화하여 관리할 수 있는 방법을 고려할 수 있습니다.
- 유지보수
- 코드의 구조가 단순하고 명확하기 때문에 유지 보수 측면에서 유리합니다. 새로운 요구 사항이나 변경 사항이 생겼을 때, 관련 로직을 쉽게 수정하거나 추가할 수 있습니다.
- 하지만, 수포자의 답안 패턴이 변경되거나 새로운 수포자가 추가될 경우, 코드를 직접 수정해야 합니다. 이러한 변경에 더 유연하게 대응하기 위해, 답안 패턴을 외부 데이터로부터 동적으로 로딩하는 방법 등을 고려할 수 있습니다.
- 개선사항
- 정답을 카운트하고 최대값을 찾는 과정에서 arr 배열을 정렬하는 대신, 처음부터 최대값을 계산할 수 있습니다. 이는 불필요한 정렬 과정을 제거하여 효율성을 높입니다.
- 최대 점수를 받은 사람을 찾는 과정에서 정렬된 arr 배열을 사용하는 대신, 직접 oneCnt, twoCnt, threeCnt를 비교하여 최대값을 결정할 수 있습니다.
개선 코드
import java.util.ArrayList;
class Solution {
public int[] solution(int[] answers) {
int[] one = {1, 2, 3, 4, 5};
int[] two = {2, 1, 2, 3, 2, 4, 2, 5};
int[] three = {3, 3, 1, 1, 2, 2, 4, 4, 5, 5};
int oneCnt = 0;
int twoCnt = 0;
int threeCnt = 0;
for (int i = 0; i < answers.length; i++) {
if (answers[i] == one[i % one.length]) oneCnt++;
if (answers[i] == two[i % two.length]) twoCnt++;
if (answers[i] == three[i % three.length]) threeCnt++;
}
int max = Math.max(oneCnt, Math.max(twoCnt, threeCnt));
ArrayList<Integer> list = new ArrayList<>();
if (oneCnt == max) list.add(1);
if (twoCnt == max) list.add(2);
if (threeCnt == max) list.add(3);
return list.stream().mapToInt(i -> i).toArray();
}
}
'항해 99 > Java' 카테고리의 다른 글
Java - 프로세스, 쓰레드 (0) | 2024.02.19 |
---|---|
WIL - 2 (0) | 2024.02.18 |
Java - 오류 및 예외 처리, 제네릭, Collection (1) | 2024.02.17 |
페어 프로그래밍 - 코딩 테스트 4 (1) | 2024.02.16 |
페어 프로그래밍 - 코딩 테스트 3 (0) | 2024.02.15 |