본문 바로가기
Research/problems

프로그래머스_lv0_외계어사전

by RIEM 2022. 11. 28.

문제

문제 설명

PROGRAMMERS-962 행성에 불시착한 우주비행사 머쓱이는 외계행성의 언어를 공부하려고 합니다. 알파벳이 담긴 배열 spell과 외계어 사전 dic이 매개변수로 주어집니다. spell에 담긴 알파벳을 한번씩만 모두 사용한 단어가 dic에 존재한다면 1, 존재하지 않는다면 2를 return하도록 solution 함수를 완성해주세요.

  • spell, dic 둘 다 어레이 형태의 매개변수다. spell에 있는 알파벳의 조합한 단어가 dict 어레이에 있는지 확인하고, 1 또는 2를 리턴하면 된다. 0, 1이 아니라 1, 2이다.

 

제한사항

spell과 dic의 원소는 알파벳 소문자로만 이루어져있습니다.

  • 알파벳 대문자, 숫자는 신경안써도 된다

2 ≤ spell의 크기 ≤ 10

  • 2~10개이다. 1개의 경우는 생각안해도 된다.

spell의 원소의 길이는 1입니다.

  • 알파벳의 length는 항상 1

1 ≤ dic의 크기 ≤ 10

  • dict의 개수는 1~10개이다. 

1 ≤ dic의 원소의 길이 ≤ 10

  • dict 단어 길이 또한 1~10개

spell의 원소를 모두 사용해 단어를 만들어야 합니다.

  • spell의 일부만 사용한 것은 제외할 것

spell의 원소를 모두 사용해 만들 수 있는 단어는 dic에 두 개 이상 존재하지 않습니다.

  • spell 원소 사용해서 만든 단어 1개만 찾으면 곧바로 리턴해서 효율을 높이자

dic과 spell 모두 중복된 원소를 갖지 않습니다.

  • 다르다라는 의미로 받아들이면 될까?

 

입출력 예 설명

입출력 예 #1

"p", "o", "s" 를 조합해 만들 수 있는 단어가 dic에 존재하지 않습니다. 따라서 2를 return합니다.

입출력 예 #2

"z", "d", "x" 를 조합해 만들 수 있는 단어 "dzx"가 dic에 존재합니다. 따라서 1을 return합니다.

입출력 예 #3

"s", "o", "m", "d" 를 조합해 만들 수 있는 단어가 dic에 존재하지 않습니다. 따라서 2을 return합니다.

유의사항

입출력 예 #3 에서 "moos", "smm", "som"도 "s", "o", "m", "d" 를 조합해 만들 수 있지만 spell의 원소를 모두 사용해야 하기 때문에 정답이 아닙니다.

 

생각

유의사항을 보면 단어 모두를 사용한 단어라는 조건이 있다. 이것이 문제 해결의 핵심인 것으로 보인다. 누락없이 모두 들어가있는지 확인하는 코드를 만들자. 

 function() {

  • spell을 알파벳 순으로 소팅한다
  • dic를 루프한다
  • 2를 리턴한다

}

우선 누락이 없는 경우를 확인하기 위해서, 알파벳 순으로 소팅한 어레이를 만들고 높은 강도로 동일한지 확인하는 방식으로 문제를 해결하고자 한다.

function solution(spell, dic) {
    const answer = spell.sort().join('');
		console.log('spell: '+ answer);
	
		dic.forEach(el => {
			const itemSplited = el.split('').sort().join('');
			console.log('dict item: '+ itemSplited)
			if(itemSplited === answer) {
				console.log('1');
				return 1;
			}
		})
    return 2;
}

console.log(solution(["z", "d", "x"], ["def", "dww", "dzx", "loveaw"]))
 

itemSplited가 answer일 경우, 1을 리턴하라고 했는데, console.log(‘1’)은 실행되는데 return은 되지 않는다. 왜 이런 현상이 발생하는걸까.

 

해결

function solution(spell, dic) {
    const answer = spell.sort().join('');
		console.log('spell: '+ answer);
		let checker = 2;
	
		dic.forEach(el => {
			const itemSplited = el.split('').sort().join('');
			console.log('dict item: '+ itemSplited)
			if(itemSplited === answer) {
				checker = 1;
			}
		})
		return checker;
}​

찾아보니 return은 함수에서만 쓴다는 글을 발견했다. 같은 맥락의 문제인지는 모르겠지만 혹시 forEach 내에서는 return을 할 수 없는 것이 아닐까라는 의문이 생겼다. 그래서 checker라는 변수에 참 거짓 정보를 기록했더니 잘 작동된다.

https://www.codeit.kr/community/threads/5392

다른 해결 방법

function solution(spell, dic) {
    return dic.filter(v=>spell.every(c=>v.includes(c))).length ? 1 : 2;
}

어떤 분은 dic을 조건으로 filter한 결과 어레이의 길이가 truthy일 경우 1을 반환하고 그렇지 않으면 2를 반환하는 방법으로 접근했다. 

  • filter를 위해 dic의 각 아이템을 루프하면서("def", "dww", "dzx", "loveaw")
  • spell의 요소(c) 모두가 dic의 아이템 v에 include하냐? 는 조건을 따진다

우선 v, c 표기 때문에 직관적으로 잘 와닿지 않는다.

function solution(spell, dic) {

  return dic.filter(word => spell.every(chr => word.includes(chr))).length? 1:2;

}

나라면 위와 같이 v, c를 word, chr로 표현했을 것 같다.

 

회고

문제의 원인이 정확하게 무엇인지 파악이 되지 않는다. 아마도 스코프와 관련된 문제인걸까.  

오버스택플로우 답변에 따르면 forEach()는 마치 짱구처럼 막을 방도가 없다고 한다. 막기 위해선 아래를 사용해야 한다.

  • 단순 루프
  • for of
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex(0

https://stackoverflow.com/questions/34653612/what-does-return-keyword-mean-inside-foreach-function

변수명이 코드를 이해하는데 영향을 미치기 때문에 변수명에도 신경을 써야겠다는 생각을 했다.

레퍼런스

https://school.programmers.co.kr/learn/courses/30/lessons/120869

 

댓글