본문 바로가기

내일배움캠프

Javascript 기초 문법 연습하기

1주차 강의를 모두 듣고 문제를 풀면서 배운 내용 확인하기.

문제1

대문자와 소문자가 섞여있는 문자열 s가 주어집니다. s에 'p'의 개수와 'y'의 개수를 비교해 같으면 True, 다르면 False를 return 하는 solution를 완성하세요. 'p', 'y' 모두 하나도 없는 경우는 항상 True를 리턴합니다. 단, 개수를 비교할 때 대문자와 소문자는 구별하지 않습니다.

예를 들어 s가 "pPoooyY"면 true를 return하고 "Pyy"라면 false를 return합니다.

 

나의 풀이

function solution(s){
    var answer
    
    var ss = s.split("")
		// string인 s를 ""를 기준으로 하여 각 알파벳으로 이루어진 배열로 바꾼다.
    
    let p = ss.filter(function(item){
        return (item === 'p' || item === 'P');
    })
		// 배열을 p 또는 P만 필터링하여 새로운 배열을 만든다.
    
    let y = ss.filter(function(item){
        return (item === 'y' || item === 'Y');
    })
		// 배열을 y 또는 Y만 필터링하여 새로운 배열을 만든다.
    
    if(p.length === y.length){
        answer = true
    } else if(p.length === 0 && y.length === 0) {
        answer = true
    } else {
        answer = false
    }
    // 두 배열의 길이가 같을 때 true를 출력하고, 두 배열 모두 길이가 0일 때 또한 true를 
    // 출력하고 두 배열의 길이가 다를 때 false를 출력하도록 조건문을 만든다.
	
		return answer;
}

기능은 원하는대로 구현되었다.

그 후 다른 사람들이 만든 코드와 비교해보며 아쉬운 점들을 정리해보았다.

 

아쉬운점

단순한 방법들을 사용하다보니 코드가 길어지는 것은 어쩔 수가 없는 것 같다. 좀더 코딩에 익숙해지고 다양한 방법들을 사용하다보면 적절한 길이의 코드를 만들 수 있을 것이라고 생각한다.

 

p, y를 필터링할 때 || 를 사용하여 묶기보다 toUpperCase, toLowerCase 를 활용했다면 더 나았을까 라는 생각을 했다. 물론 지금은 저 방법이 더 간단하게 보일 수 있지만 더 많은 조건이나 더 복잡한 코딩이 필요할 때는 대문자, 소문자로 변환해서 통일하여 조건을 거는 것이 더 나은 방법이지 않을까하는 생각을 해보았다.

 

마지막으로 다른 사람의 풀이 중 정말 깔끔하게 문제를 해결한 코드를 정리해보려고 한다.

function numPY(s){
    return s.toUpperCase().split("P").length === s.toUpperCase().split("Y").length;
}

놀랍게도 한 줄로 위의 모든 기능을 구현했다.

위의 코드에 대해 정리해보자.

s.toUpperCase()
함수가 호출되면, 입력받은 문자열 s를 대문자로 변환한다.
.split("P")
문자열 s를 대문자로 변환한 후, 'P'를 기준으로 분할하여 배열로 만든다.
.length
이렇게 생성된 배열의 길이를 구한다.
s.toUpperCase().split("Y").length
문자열 s를 대문자로 변환한 후, 'Y'를 기준으로 분할하여 배열로 만든 후, 생성된 배열의 길이를 구한다.
===
'P'로 분할한 배열과 'Y'로 분할한 배열의 길이를 비교하여 같은지 확인한다.
배열의 길이가 같다면, 'P'와 'Y'의 개수가 동일하므로 true를 반환하고, 
그렇지 않은 경우, 'P'와 'Y'의 개수가 다르므로 false를 반환한다.

이 코드에서 놀란 점은 코드가 짧다는 것도 있지만

1. 문자를 각각 바꾼 것이 아니라 전부 대문자로 바꾸고 시작하여 P와 p를 구분할 필요를 없앴고

2. 나는 배열을 문자 하나하나 나눠서 P를 count 한 것에 반에 이 코드는 p를 기준으로 분할하여 배열의 개수를 셈으로써

    P의 개수를 파악했다는 것이다.

 

이 코드 뿐만 아니라 다른 코드들을 보면서 코딩을 많이 해보고 이러한 코드를 많이 봐야겠다고 느꼈다. 그러면 좀 더 알맞은 편안한 코딩을 할 수 있지 않을까.

 

문제2

어떤 정수들이 있습니다. 이 정수들의 절댓값을 차례대로 담은 정수 배열 absolutes와 이 정수들의 부호를 차례대로 담은 불리언 배열 signs가 매개변수로 주어집니다. 실제 정수들의 합을 구하여 return 하도록 solution 함수를 완성해주세요.

 

위의 문제는 그래도 몇 번의 시도끝에 기능을 구현해냈던 것과 달리 이 문제는 오래 걸렸다.

너무 문제 자체에 갇혀있었던 것도 있었고, 안되는 부분에서 해결방법을 찾기가 힘들어서 오래걸렸다.

나의 풀이

1번째 코딩

function solution(absolutes, signs) {
    var answer
    
    var sign
    
    for(i=0; i <= absolutes.length; i++){
    if(signs[i] === true) {
        sign = 1    
    } else {
        sign = -1
    }
    
    var realNum
    
    realNum = absolutes[i]*sign
    }
    
    answer += realNum 
    
    console.log(answer)
    return answer;
}

오류

실행한 결괏값 null이 기댓값과 다릅니다.
출력 NaN

 

우선 어디서 잘못되었는지 찾기 위해 function 내부의 요소들을 가져와 vscode에서 임의의 absolutes, signs 배열을 주고 돌려보았다.

let absolutes = [1, 2, 3];
let signs = [false, false, true];

var answer;

var sign;

for (i = 0; i <= absolutes.length; i++) {
  if (signs[i] === true) {
    sign = 1;
  } else {
    sign = -1;
  }

  var realNum;

  realNum = absolutes[i] * sign;
}

answer += realNum;

console.log(answer);

결과는

NaN

 

여기서 우선 쓸데없는 코드들을 삭제하고 위치가 안 맞는 코드들의 위치를 이동시켜주며 다시 vscode로 실행해 보았다.

let absolutes = [1, 2, 3];
let signs = [false, false, true];

    var answer
    var num
    
    for(let i = 0; i <= signs.length; i++){
        if(signs[i] === true) {
            num = absolutes[i] * 1
        } else {
             num = absolutes[i] * -1
         }
        
        answer += num
    }
    
    
    console.log(answer)

결과는 여전히

NaN

 

왜 그런지 열심히 구글링을 해보다가 몇 가지 문제점을 발견했다.

1. answer의 초기값 설정

answer의 초기값이 설정되지 않았기 때문에 undefined로 초기화되고 이후에 연산이 발생하면 NaN이 반환된다.

2. 반복문 조건에서 < signs.length 로 수정

let absolutes = [1, 2, 3];
let signs = [false, false, true];

var answer = 0; // 변수 초기화 추가
var num;

for (let i = 0; i < signs.length; i++) {
  // 부등호 수정 (signs.length 대신 signs.length - 1)
  if (signs[i] === true) {
    num = absolutes[i];
  } else {
    num = -absolutes[i];
  }

  answer += num;
}

console.log(answer);

결과는

0

문제에서 제시했던데로 기능하는 것을 확인할 수 있었다!

 

이제 이것을 function 함수에 넣어 받아온 배열로 제대로 기능하는지 확인하는 것만 남았다.

function solution(absolutes, signs) {
    var answer = 0;
    var num;

    for (let i = 0; i < signs.length; i++) {
 
        if (signs[i] === true) {
             num = absolutes[i];
        } else {
            num = -absolutes[i];
        }
    
        answer += num;
    }

    console.log(answer);
    return answer;
}

결과는

테스트 1
입력값 〉	[4, 7, 12], [true, false, true]
기댓값 〉	9
실행 결과 〉	테스트를 통과하였습니다.
출력 〉	9
테스트 2
입력값 〉	[1, 2, 3], [false, false, true]
기댓값 〉	0
실행 결과 〉	테스트를 통과하였습니다.
출력 〉	0

테스트를 통과할 수 있었다!!

거의 2시간 동안 열심히 구글링하고 삽질한 끝에 다행히 원하는 기능을 구현할 수 있었다. 생각보다 너무 오래걸려서 중간에 꺾일 뻔 했지만 마무리할 수 있어서 다행이다.

아쉬운점

아직 오류메시지가 뜨지 않고 원하는 값이 나오지 않았을 때 어떻게 대처해야할 지 잘 모르겠다.

어느 부분에서 잘못되었는지 찾는 과정에서 아직 모르는 것이 많다보니 방향없이 이것저것 찾아보느라 시간이 많이 소비되었다.

위에서 말했듯이 코딩을 계속 많이 하고 코드를 접해보면서 많은 오류와 많은 실패를 경험해보고 그것들을 잘 정리해서 다음에 같은 상황이 발생했을 때는 어렵지 않게 잘못된 부분을 찾을 수 있도록 해야겠다.

 

마지막으로 다른 사람의 풀이 중 깔끔하게 문제를 해결한 코드를 정리해보려고 한다.

function solution(absolutes, signs) {
    let answer = 0;
		// 두 배열 길이 같음
    for (let i = 0; i < absolutes.length; i++) {
				// 부호에 따라 +-
        signs[i] ? answer += absolutes[i] : answer -= absolutes[i]
    }
    return answer;
}

 

위의 코드에 대해 정리해보자.

let answer = 0;
// answer에 초기값 부여
for (let i = 0; i < absolutes.length; i++) {
// for문으로 배열요소 모두에 대해 반복
signs[i] ? answer += absolutes[i] : answer -= absolutes[i]
// 부호에 따라 +-
// 삼항 연산자를 사용하여
//signs[i]가 true 일 때는 absolutes[i]를 answer에 더해주고
//signs[i]가 false 일 때는 absolutes[i]를 answer에서 빼준다
return answer;
//answer 값 return

이 코드에서 놀란 점은

1. 우선 if문으로 길게 작성해야 했던 것을 삼항 연산자를 활용하여 한 줄로 표현할 수 있었다.

이 부분은 삼항연산자를 배웠지만 아직 익숙하지 못해 활용할 생각을 못했다.

물론 if문을 사용한 것이 틀린 것은 아니지만 배운 것을 떠올리지 못했다는 것에 조금 아쉬움을 느꼈다.

계속 코딩해가면서 배운 것들도 복습하며 다시 활용해볼 수 있도록 신경써야겠다는 생각을 했다.

 

2. 위에서와 비슷하지만 나는 absolutes[i]의 부호를 판별해내고 그것을 +=를 활용하여 다 더해야지. 라고 문제에 맞춰서 글자 그대로 구현하는 것만 생각했는데, 조건에 따라 += 와 -=로 나누어 조건을 준 부분을 보고 또 한번 아쉬움을 느꼈다.

그저 글자그대로 구현하는 것도 좋지만 이렇게 응용하여 뜻이 통할 수 있도록 구현하면 더 짧고 예쁘게 코딩할 수 있다는 것을 알 수 있었다.

 

결국 두 번의 코딩문제를 풀어보며 물론 이제 시작이지만 코딩을 많이 경험해보고 많은 코드를 보는 것이 중요하다는 것을 느꼈고, 너무 틀에 박힌 코딩보다 조금 더 문제를 유연하게 보는 시선도 길러야 겠다는 생각을 했다.