diff --git a/docs/PROBLEM1.md b/docs/PROBLEM1.md index b69b3ec9ba..2e319e0395 100644 --- a/docs/PROBLEM1.md +++ b/docs/PROBLEM1.md @@ -23,3 +23,16 @@ | [97, 98] | [197, 198] | 0 | | [131, 132] | [211, 212] | 1 | | [99, 102] | [211, 212] | -1 | + +## 기능 목록 + +1. 페이지의 각 자리 합을 구하는 메서드 +2. 페이지의 각 자리 곱을 구하는 메서드 +3. 페이지의 연산 중 가장 큰 수를 구하는 메서드 +4. 포비와 크롱 중 점수를 비교해 승자를 구하는 메서드 + +## 에러 처리 + +1. 시작 면이나 마지막 면이 나오면 에러 발생 +2. 포비와 크롱의 길이는 무조건 2 / 아니었을 때 에러 발생 +3. 책 왼쪽, 오른쪽 페이지 불일치 에러 발생 \ No newline at end of file diff --git a/docs/PROBLEM2.md b/docs/PROBLEM2.md index a632723439..c0be99bed4 100644 --- a/docs/PROBLEM2.md +++ b/docs/PROBLEM2.md @@ -21,3 +21,14 @@ | --- | --- | | "browoanoommnaon" | "brown" | | "zyelleyz" | "" | + +## 기능 목록 + +1. String을 Stack으로 변경하는 메서드 +2. cryptogram에 중복된 문자열을 제거 메소드 +3. 결과 반환 메서드 + +## 에러 처리 + +1. cryptogram의 길이가 1이상 1000이하가 아니면 에러 +2. cryptogram이 소문자로만 이루어져 있지 않으면 에러 \ No newline at end of file diff --git a/docs/PROBLEM3.md b/docs/PROBLEM3.md index 7720d84555..b03ae632e2 100644 --- a/docs/PROBLEM3.md +++ b/docs/PROBLEM3.md @@ -14,3 +14,13 @@ | --- | --- | | 13 | 4 | | 33 | 14 | + +## 기능 목록 + +1. 1부터 숫자까지 반복해서 3, 6, 9가 들어있는 횟수를 반환하는 메소드 +2. 3,6,9 횟수 증가 메소드 +3. 문자열에 3, 6, 9가 있는지 판단하는 메소드 + +## 에러 처리 + +1. 숫자의 범위는 1부터 10,000 이하 \ No newline at end of file diff --git a/docs/PROBLEM4.md b/docs/PROBLEM4.md index f2ff9edab0..4f46c03009 100644 --- a/docs/PROBLEM4.md +++ b/docs/PROBLEM4.md @@ -19,3 +19,13 @@ | word | result | | --- | --- | | "I love you" | "R olev blf" | + +## 기능 목록 + +1. 알파벳표를 반대 알파벳으로 매핑하는 메서드 +2. 알파벳 대소문자 판별 메서드 +3. 문제 결과를 반환하는 메서드 + +## 에러 처리 + +1. word의 길이 에러 처리 \ No newline at end of file diff --git a/docs/PROBLEM6.md b/docs/PROBLEM6.md index 963375acea..5f6ce3500b 100644 --- a/docs/PROBLEM6.md +++ b/docs/PROBLEM6.md @@ -21,3 +21,18 @@ | forms | result | | --- | --- | | [ ["jm@email.com", "제이엠"], ["jason@email.com", "제이슨"], ["woniee@email.com", "워니"], ["mj@email.com", "엠제이"], ["nowm@email.com", "이제엠"] ] | ["jason@email.com", "jm@email.com", "mj@email.com"] | + + +## 기능 목록 + +1. 두 글자 이상 연속 판단 메서드 +2. 중복된 닉네임의 이메일을 저장하는 메서드 +3. 결과 오름차순 정렬 후 중복 제거 메서드 + +## 에러 처리 + +1. 크루의 개수 에러 처리 +2. 이메일 형식 에러 처리 +3. 이메일 길이 에러 처리 +4. 닉네임 길이 에러 처리 +5. 닉네임 한글 에러 처리 \ No newline at end of file diff --git a/src/main/java/onboarding/Problem1.java b/src/main/java/onboarding/Problem1.java index b99e6b5e67..07125750ae 100644 --- a/src/main/java/onboarding/Problem1.java +++ b/src/main/java/onboarding/Problem1.java @@ -1,10 +1,29 @@ package onboarding; + import java.util.List; +import java.util.stream.Stream; + +import static onboarding.problem1.util.ErrorHandler.isNotCorrectPage; +import static onboarding.problem1.util.PageHandler.*; +import static onboarding.problem1.util.findWinner.getWinner; + class Problem1 { + + + public static final int isNotCorrectPage = -1; + + public static int solution(List pobi, List crong) { - int answer = Integer.MAX_VALUE; - return answer; + + if (isNotCorrectPage(pobi) || isNotCorrectPage(crong)) { + return isNotCorrectPage; + } + int pobiMaxPage = getMaxPage(getPageSumMax(pobi), getPageMultiMax(pobi)); + int crongMaxPage = getMaxPage(getPageSumMax(crong), getPageMultiMax(crong)); + + return getWinner(pobiMaxPage, crongMaxPage); + } } \ No newline at end of file diff --git a/src/main/java/onboarding/Problem2.java b/src/main/java/onboarding/Problem2.java index ee836e9cac..7d84fc4aae 100644 --- a/src/main/java/onboarding/Problem2.java +++ b/src/main/java/onboarding/Problem2.java @@ -1,8 +1,51 @@ package onboarding; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Objects; + +import static onboarding.problem2.CrypErrorHandler.checkCryptogram; + public class Problem2 { public static String solution(String cryptogram) { - String answer = "answer"; - return answer; + + checkCryptogram(cryptogram); + Deque cryptogramStack = convertStringToStack(cryptogram); + Deque resultStack = removeDuplicateChar(cryptogramStack); + + return resultPassword(resultStack); + } + + private static Deque convertStringToStack(String cryptogram){ + Deque stack = new ArrayDeque(); + for (char word : cryptogram.toCharArray()){ + stack.add(word); + } + return stack; + } + + private static Deque removeDuplicateChar(Deque cryptogram) { + Deque resultStack = new ArrayDeque(); + while (!cryptogram.isEmpty()){ + Character word = cryptogram.removeFirst(); + if (isDuplicate(resultStack, word)){ + resultStack.removeLast(); + continue; + } + resultStack.addLast(word); + } + return resultStack; + } + + private static String resultPassword(Deque resultStack) { + StringBuilder password = new StringBuilder(); + while (!resultStack.isEmpty()){ + password.append(resultStack.removeFirst()); + } + return password.toString(); + } + + private static boolean isDuplicate(Deque resultStack, Character word) { + return !resultStack.isEmpty() && Objects.equals(word, resultStack.peekLast()); } } diff --git a/src/main/java/onboarding/Problem3.java b/src/main/java/onboarding/Problem3.java index 12e095d6e3..e705706a6b 100644 --- a/src/main/java/onboarding/Problem3.java +++ b/src/main/java/onboarding/Problem3.java @@ -1,8 +1,55 @@ package onboarding; +import java.util.stream.IntStream; + public class Problem3 { + + public static final String NUMBER_RANGE_ONE_TO_THOUSAND = "숫자의 범위는 1부터 10000 이하입니다."; + public static final char TREE = '3'; + public static final char SIX = '6'; + public static final char NINE = '9'; public static int solution(int number) { - int answer = 0; - return answer; + validateNumberRange(number); + return getCount(number); + } + + private static void validateNumberRange(int number) { + if (number < 1 || number > 10000){ + throw new IllegalArgumentException(NUMBER_RANGE_ONE_TO_THOUSAND); + } + } + + public static int getCount(int number){ + int count = 0; + for (int i = 1; i <= number; i++){ + String num = String.valueOf(i); + count = upCount(count, num); + } + return count; + } + + private static int upCount(int count, String num) { + for (int j = 0; j < num.length(); j++){ + if (isInclude369(num, j)){ + count++; + } + } + return count; + } + + private static boolean isInclude369(String num, int j) { + return num.charAt(j) == TREE || num.charAt(j) == SIX || num.charAt(j) == NINE; } + + + // 람다식으로 바꾸었을 때 + public static int getResult(int number){ + return IntStream.rangeClosed(1, number) + .mapToObj(String::valueOf) + .mapToInt(num -> Math.toIntExact(num.chars() + .filter(ch -> ch == TREE || ch == SIX || ch == NINE) + .count())) + .sum(); + } + } diff --git a/src/main/java/onboarding/Problem4.java b/src/main/java/onboarding/Problem4.java index 9bc4334fa9..74dc80786c 100644 --- a/src/main/java/onboarding/Problem4.java +++ b/src/main/java/onboarding/Problem4.java @@ -1,8 +1,10 @@ package onboarding; +import onboarding.problem4.Sentence; + public class Problem4 { public static String solution(String word) { - String answer = ""; - return answer; + return new Sentence(word).getResult(); } + } diff --git a/src/main/java/onboarding/Problem6.java b/src/main/java/onboarding/Problem6.java index f6c7b32344..0c3756465b 100644 --- a/src/main/java/onboarding/Problem6.java +++ b/src/main/java/onboarding/Problem6.java @@ -1,10 +1,12 @@ package onboarding; -import java.util.List; +import onboarding.problem6.Crews; + +import java.util.*; public class Problem6 { public static List solution(List> forms) { - List answer = List.of("answer"); - return answer; + return new Crews(forms).getResultEmail(); } + } diff --git a/src/main/java/onboarding/problem1/util/ErrorHandler.java b/src/main/java/onboarding/problem1/util/ErrorHandler.java new file mode 100644 index 0000000000..fc899e5623 --- /dev/null +++ b/src/main/java/onboarding/problem1/util/ErrorHandler.java @@ -0,0 +1,35 @@ +package onboarding.problem1.util; + +import java.util.List; + +public final class ErrorHandler { + + public static boolean validateLeftRightPage(List user) { + if (user.get(0) == (user.get(1) - 1)) { + return true; + } + return false; + } + + public static boolean validateStartOrEndPage(List user) { + if (user.get(0) >= 1 && user.get(1) <= 400) { + return true; + } + return true; + } + + public static boolean validatePageLength(List user) { + if (user.size() == 2) { + return true; + } + return false; + } + + public static boolean isNotCorrectPage(List user) { + if (validateLeftRightPage(user) && validateStartOrEndPage(user) && validatePageLength(user)) { + return false; + } + return true; + } + +} diff --git a/src/main/java/onboarding/problem1/util/PageHandler.java b/src/main/java/onboarding/problem1/util/PageHandler.java new file mode 100644 index 0000000000..8565c98cdf --- /dev/null +++ b/src/main/java/onboarding/problem1/util/PageHandler.java @@ -0,0 +1,30 @@ +package onboarding.problem1.util; + +import java.util.List; +import java.util.stream.Stream; + +public final class PageHandler { + public static Stream getPage(List user) { + return user.stream().map(Object::toString); + } + + public static int getPageSumMax(List user) { + Stream page = getPage(user); + return page.mapToInt(str -> str.chars() + .map(Character::getNumericValue) + .sum()) + .max().orElseThrow(NullPointerException::new); + } + + public static int getPageMultiMax(List user) { + Stream page = getPage(user); + return page.mapToInt(str -> str.chars() + .map(Character::getNumericValue) + .reduce(1, (a, b) -> a * b)) + .max().orElseThrow(NullPointerException::new); + } + + public static int getMaxPage(int pageSumMax, int pageMultiMax) { + return Math.max(pageSumMax, pageMultiMax); + } +} diff --git a/src/main/java/onboarding/problem1/util/findWinner.java b/src/main/java/onboarding/problem1/util/findWinner.java new file mode 100644 index 0000000000..19c37e97f1 --- /dev/null +++ b/src/main/java/onboarding/problem1/util/findWinner.java @@ -0,0 +1,32 @@ +package onboarding.problem1.util; + +public final class findWinner { + public static final int CRONG_WIN = 2; + public static final int POBI_WIN = 1; + public static final int NO_WINNER = 0; + + public static int getWinner(int pobiMaxPage, int crongMaxPage) { + if (isPobiWin(pobiMaxPage, crongMaxPage)) + return POBI_WIN; + + if (isCrongWin(pobiMaxPage, crongMaxPage)) + return CRONG_WIN; + + return NO_WINNER; + } + + public static boolean isPobiWin(int pobiMaxPage, int crongMaxPage) { + if (pobiMaxPage > crongMaxPage) { + return true; + } + return false; + } + + public static boolean isCrongWin(int pobiMaxPage, int crongMaxPage) { + if (crongMaxPage > pobiMaxPage) { + return true; + } + return false; + } + +} diff --git a/src/main/java/onboarding/problem2/CrypErrorHandler.java b/src/main/java/onboarding/problem2/CrypErrorHandler.java new file mode 100644 index 0000000000..3a48c2e974 --- /dev/null +++ b/src/main/java/onboarding/problem2/CrypErrorHandler.java @@ -0,0 +1,26 @@ +package onboarding.problem2; + +public final class CrypErrorHandler { + + public final static String CRYP_LENGTH_IS_ONE_TO_HUND= "1이상 1000이하인 문자열이어야합니다."; + public final static String CRYP_COMPOSE_BY_SMALL_LETTER = "cryptogram은 소문자로만 이루어져 있습니다."; + private static void validateCrypLength(String cryptogram) { + if (cryptogram.length() < 1 || cryptogram.length() > 1000){ + throw new IllegalArgumentException(CRYP_LENGTH_IS_ONE_TO_HUND); + } + } + + private static void validateCrypSmallLetter(String cryptogram) { + for (char word : cryptogram.toCharArray()){ + if (!Character.isLowerCase(word)){ + throw new IllegalArgumentException(CRYP_COMPOSE_BY_SMALL_LETTER); + } + } + } + + public static void checkCryptogram(String cryptogram){ + validateCrypLength(cryptogram); + validateCrypSmallLetter(cryptogram); + } + +} diff --git a/src/main/java/onboarding/problem4/Alphabet.java b/src/main/java/onboarding/problem4/Alphabet.java new file mode 100644 index 0000000000..70fb424aa9 --- /dev/null +++ b/src/main/java/onboarding/problem4/Alphabet.java @@ -0,0 +1,18 @@ +package onboarding.problem4; + +import java.util.HashMap; +import java.util.Map; + +import static onboarding.problem4.Sentence.END_UPPER_ALPHABET; +import static onboarding.problem4.Sentence.START_UPPER_ALPHABET; + +public final class Alphabet { + public static final Map mapAlphabet = new HashMap<>(26); + + public static void getMapAlphabetToReverse(){ + for(char c = START_UPPER_ALPHABET; c <= END_UPPER_ALPHABET; c++){ + char reverseChar = (char)(END_UPPER_ALPHABET - (c - START_UPPER_ALPHABET)); + mapAlphabet.put(c, reverseChar); + } + } +} diff --git a/src/main/java/onboarding/problem4/Sentence.java b/src/main/java/onboarding/problem4/Sentence.java new file mode 100644 index 0000000000..377948a308 --- /dev/null +++ b/src/main/java/onboarding/problem4/Sentence.java @@ -0,0 +1,57 @@ +package onboarding.problem4; + +import static onboarding.problem4.Alphabet.mapAlphabet; + +public class Sentence { + + public final static Character START_LOWER_ALPHABET = 'a'; + public final static Character END_LOWER_ALPHABET = 'z'; + public final static Character START_UPPER_ALPHABET = 'A'; + public final static Character END_UPPER_ALPHABET = 'Z'; + public final static int CHANGE_ALPHABET_SIZE = 32; + + private final String sentence; + private final StringBuilder sb = new StringBuilder(); + + public Sentence(String sentence) { + this.sentence = sentence; + } + + public String getResult(){ + Alphabet.getMapAlphabetToReverse(); + for(int i = 0; i < sentence.length(); i++){ + char ch = sentence.charAt(i); + whenBlank(ch); + whenLower(ch); + whenUpper(ch); + } + return sb.toString(); + } + + private void whenBlank(char ch){ + if(ch == ' '){ + sb.append(' '); + } + } + + private void whenLower(char ch){ + if (ch >= START_LOWER_ALPHABET && ch <= END_LOWER_ALPHABET){ + sb.append(toLower(mapAlphabet.get(toUpper(ch)))); + } + } + + private void whenUpper(char ch){ + if (ch >= START_UPPER_ALPHABET && ch <= END_UPPER_ALPHABET){ + sb.append(mapAlphabet.get(ch)); + } + } + + private char toUpper(char ch){ + return (char)(ch - CHANGE_ALPHABET_SIZE); + } + + private char toLower(char ch){ + return (char)(ch + CHANGE_ALPHABET_SIZE); + } +} + diff --git a/src/main/java/onboarding/problem6/Crew.java b/src/main/java/onboarding/problem6/Crew.java new file mode 100644 index 0000000000..529e5d4513 --- /dev/null +++ b/src/main/java/onboarding/problem6/Crew.java @@ -0,0 +1,53 @@ +package onboarding.problem6; + +import java.util.regex.Pattern; + +public class Crew { + + private String email; + private String name; + + Crew(String email, String name) { + + this.email = email; + this.name = name; + + validEmailType(); + validEmailLength(); + validNickNameLength(); + validKoreanNickName(); + } + + public String getName() { + return name; + } + + public String getEmail(){ + return email; + } + + private void validEmailType(){ + if(!email.contains("email.com")){ + throw new IllegalArgumentException("이메일은 'email.com' 도메인만 가능합니다."); + } + } + + private void validEmailLength() { + if (email.length() < 11 || email.length() >= 20){ + throw new IllegalArgumentException("이메일 길이는 11자 이상 20자 미만입니다."); + } + } + + private void validNickNameLength(){ + if (name.length() < 1 || name.length() >= 20){ + throw new IllegalArgumentException("닉네임 길이는 1자 이상 20자 미만입니다."); + } + } + + private void validKoreanNickName() { + String regex = "^[가-힣]*$"; + if (!Pattern.matches(regex, name)) { + throw new IllegalArgumentException("닉네임은 한글만 가능합니다."); + } + } +} diff --git a/src/main/java/onboarding/problem6/Crews.java b/src/main/java/onboarding/problem6/Crews.java new file mode 100644 index 0000000000..4ab190e62e --- /dev/null +++ b/src/main/java/onboarding/problem6/Crews.java @@ -0,0 +1,58 @@ +package onboarding.problem6; + +import java.util.List; +import java.util.stream.Collectors; + +public class Crews { + + private List crews; + private List nicknames; + + public Crews(List> forms) { + this.crews = mapCrewsList(forms); + this.nicknames = mapNicknames(); + } + + + + public List mapCrewsList(List> forms) { + crewCountErrorHandler(forms); + return forms.stream() + .map(form -> new Crew(form.get(0), form.get(1))) + .collect(Collectors.toList()); + } + + public List mapNicknames(){ + return crews.stream().map(Crew::getName).collect(Collectors.toList()); + } + + + public List getResultEmail() { + return duplicateNames().stream() + .flatMap(filterNickname -> crews.stream() + .filter(crew -> filterNickname.equals(crew.getName())) + .map(Crew::getEmail)) + .sorted() + .distinct() + .collect(Collectors.toList()); + } + + private List duplicateNames(){ + return nicknames.stream() + .filter(nickname -> { + List separated = new NameSeparate(nickname).getSeparatedNickname(); + return crews.stream() + .map(Crew::getName) + .filter(name -> !name.equals(nickname)) // Exclude the same nickname + .anyMatch(name -> separated.stream().anyMatch(name::contains)); + }).collect(Collectors.toList()); + } + + private void crewCountErrorHandler(List> forms){ + if((long) forms.size() < 1 || (long) forms.size() > 10000){ + throw new IllegalArgumentException("크루는 1명 이상 10,000명 이하입니다."); + } + } +} + + diff --git a/src/main/java/onboarding/problem6/NameSeparate.java b/src/main/java/onboarding/problem6/NameSeparate.java new file mode 100644 index 0000000000..eeff7bc955 --- /dev/null +++ b/src/main/java/onboarding/problem6/NameSeparate.java @@ -0,0 +1,24 @@ +package onboarding.problem6; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class NameSeparate { + + List separatedNickname; + + NameSeparate(String nickname){ + this.separatedNickname = separateNickname(nickname); + } + + private List separateNickname(String nickname){ + return IntStream.range(0, nickname.length()-1) + .mapToObj(i -> nickname.substring(i, i+2)) + .collect(Collectors.toList()); + } + + public List getSeparatedNickname() { + return separatedNickname; + } +} diff --git a/src/test/java/onboarding/problem1/problem1Test.java b/src/test/java/onboarding/problem1/problem1Test.java new file mode 100644 index 0000000000..c1fc29d637 --- /dev/null +++ b/src/test/java/onboarding/problem1/problem1Test.java @@ -0,0 +1,93 @@ +package onboarding.problem1; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static onboarding.problem1.util.ErrorHandler.*; +import static onboarding.problem1.util.PageHandler.*; +import static onboarding.problem1.util.findWinner.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class problem1Test { + + @Nested + class ErrorHandlerTest{ + + List user = List.of(97,98); + + @Test + void isLeftRightPage() { + assertThat(validateLeftRightPage(user)).isEqualTo(true); + } + + @Test + void isStartOrEndPage() { + assertThat(validateStartOrEndPage(user)).isEqualTo(true); + } + + @Test + void isPageLength(){ + assertThat(validatePageLength(user)).isEqualTo(true); + } + + @Test + void checkIsNotCorrectPage(){ + assertThat(isNotCorrectPage(user)).isEqualTo(false); + } + } + + @Nested + class FindWinnerTest { + + @Test + void checkPobiWin() { + int pobiMaxPage = 200; + int crongMaxPage = 100; + + assertAll( + () -> assertThat(isPobiWin(pobiMaxPage,crongMaxPage)).isTrue(), + () -> assertThat(getWinner(pobiMaxPage, crongMaxPage)).isEqualTo(POBI_WIN) + ); + } + + @Test + void checkCrongWin() { + int pobiMaxPage = 100; + int crongMaxPage = 200; + + assertAll( + () -> assertThat(isCrongWin(pobiMaxPage,crongMaxPage)).isTrue(), + () -> assertThat(getWinner(pobiMaxPage, crongMaxPage)).isEqualTo(CRONG_WIN) + ); + } + + @Test + void checkTie() { + int pobiMaxPage = 100; + int crongMaxPage = 100; + + assertThat(getWinner(pobiMaxPage, crongMaxPage)).isEqualTo(NO_WINNER); + } + + } + + @Nested + class PageHandlerTest { + + + @Test + void checkMaxPage() { + List user = List.of(97, 98); + + assertAll( + () -> assertThat(getPageSumMax(user)).isEqualTo(17), + () -> assertThat(getPageMultiMax(user)).isEqualTo(72), + () -> assertThat(getMaxPage(getPageSumMax(user), getPageMultiMax(user))).isEqualTo(72) + ); + + } + } +}