오늘은 알고리즘 문제를 풀다가 겪은 고충을 남기려고 한다.
해당 문제는 문자열 다루기 기본이다.
+. 출처를 기재하였고 비상업적인 블로그이기 때문에 사용이 가능한 것은 확인했지만, 혹시 현재 내용도 위배에 해당된다면 바로 삭제하도록 하겠습니다.
맨 처음 완성되었다고 생각한 코드는 대강 이러했다.
function solution(s) {
let toNum = s-0;
return !isNaN(toNum) && (s.length === 4 || s.length === 6) ? true : false;
}
빼기 연산을 시키면 숫자형으로 변환되는 것을 활용하여
변환 결과가 NaN인지 확인하고, 이후 문자열 길이를 체크해서 검사 결과를 리턴한다.
* NaN은 등호 연산자(=== 나 !==)를 통해 비교할 수 없기 때문에(NaN끼리 비교해도 false가 나온다) isNaN()을 사용해야 체크할 수 있다. typeof 또한 number로 출력된다!!
그런데 테스트 케이스에서 실패가 발생했다.
하지만 아무리 생각해도 어디가 문제라는 건지 알 수가 없었다.
숫자인지도 확인했고 문자열의 길이도 확인했다.
문자열의 길이는 명확하니 숫자 부분에 문제가 있는 건가 싶었다.
알파벳이 들어갔는데도 숫자라고 생각하는 경우가 있는 게 분명하다.
그렇게 검색하다가 원인을 알게 되었다.
function solution(s) {
if (!isNaN(s-0) && (s.length === 4 || s.length === 6)) {
for (let i = 1; i < s.length-1; i++){
if(s[i] === 'e' || s[i] === 'E'){
return false
}
}
return true
} else {
return false;
}
}
바로 지수형이다.
문자열의 중간에 e가 들어가 있을 경우 지수형이라고 판단해서 멀쩡한 숫자로 변환되고 있었던 것이다.
심지어 대문자 E도 인식한다.
따라서 조건을 만족하면 두번째 자리부터 (마지막-1)번째 자리까지 e나 E가 포함되어 있는지 확인하는 문을 추가했다.
굳이 이런 for문을 사용한 것에는 이러한 과정이 있다.
원래는 지수형인 점을 활용해서
변환 후 자릿수==가 변하거나 숫자의 크기가 달라지는 경우를 (ex. 10e5 => 1000000)
생각했는데, 자릿수는 e 옆의 숫자에 따라 달라지지 않을 수도 있는 것이고 '0001' 같은 경우 순수한 숫자인데도 영향을 받게 된다.
같은 이유로 숫자의 크기도 e가 들어갔다고 해서 특정한 범위로 한정할 수 없다.
아예 한 자리씩 숫자인지 확인하는 방법도 생각해봤었는데,
이 경우도 조건문에서 boolean으로 변환되기에 0일 경우 피해를 입었다.
(그런데 지금 생각해보니 isNaN을 사용하면 괜찮지 않나...?)
function solution(s) {
if (s.length === 4 || s.length === 6) {
for (let i = 0; i < s.length; i++){
if(!(s[i]-0)){
return false
}
else if(isNaN(s[i]-0)){
return false
}
}
return true
} else {
return false;
}
}
이 경우도 문제가 없는 것 같긴 하지만
개인적으로는 처음 코드가 더 마음에 든다.
점수가 꽤 많이 올라서 뿌듯하다!