머쓱이는 태어난 지 6개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음을 최대 한 번씩 사용해 조합한(이어 붙인) 발음밖에 하지 못합니다. 문자열 배열 babbling 이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.
public class 옹알이 {
@Test
void tester() {
int solution = solution(new String[]{"ayaye", "uuuma", "ye", "yemawoo", "ayaa"});
Assertions.assertEquals(3, solution);
}
public int solution(String[] inputs) {
int count = 0;
for (String input : inputs) {
int nextIndex = 0;
while (true) {
if (nextIndex >= input.length()) {
count++;
// 성공
break;
}
if ((nextIndex = scanWord(input, nextIndex)) == -1) {
// 실패
break;
}
}
}
return count;
}
private int scanWord(String input, int nextIndex) {
List<String> speakableWords = List.of("aya", "ye", "woo", "ma");
char firstChar = input.charAt(nextIndex);
int i;
for (i = 0; i<speakableWords.size(); i++) {
String speakableWord = speakableWords.get(i);
if (speakableWord.charAt(0) == firstChar) {
if (input.length() < nextIndex + speakableWord.length()) {
nextIndex = -1;
break;
}
String substring = input.substring(nextIndex, nextIndex + speakableWord.length());
if (speakableWord.equals(substring)) {
nextIndex += speakableWord.length();
break;
}
}
}
if (i == speakableWords.size()) {
return -1;
} else {
return nextIndex;
}
}
}
public class 옹알이 {
@Test
void tester() {
int solution = solution(new String[]{"ayaye", "uuuma", "ye", "yemawoo", "ayaa"});
Assertions.assertEquals(3, solution);
}
// 최종 해결책
public int solution(String[] sentences) {
return (int) Arrays.stream(sentences)
.filter(this::canSpeakSentence)
.count();
}
private boolean canSpeakSentence(String targetSentence) {
String gettingCut = targetSentence;
while (true) {
String subSentence = gettingCut;
// 문장이 말할 수 있는 발음으로 시작하는지 찾기
Optional<String> startedWord = Stream.of("aya", "ye", "woo", "ma")
.filter(word -> started(subSentence, word))
.findAny();
// 문장이 말할 수 있는 발음으로 시작하지 않는다면 문장을 말할 수 없습니다.
if (startedWord.isEmpty()) {
return false;
}
// 이어지는 문장이 발음 가능한지 검사하기 위해 찾아진 발음을 문장에서 제거
gettingCut = gettingCut.substring(startedWord.get().length());
if (gettingCut.isEmpty()) {
return true;
}
}
}
boolean started(String targetSentence, String canSpeakWord) {
if (targetSentence.length() < canSpeakWord.length()) {
return false;
}
String targetSub = targetSentence.substring(0, canSpeakWord.length());
return targetSub.equals(canSpeakWord);
}
주먹구구식 코드를 작성하며 for 문의 흐름과 언제 break 로 분기해야 할지 전체 흐름이 한 눈에 파악되지 않아 어려웠고 불안한 마음이 들었다. Java의 Stream을 사용해 선언적으로 코드를 작성하다 보니 훨씬 코드 작성이 쉬워졌고 안정적인 마음이 들었다. 코드 가독성도 향상된 것 같다.