[DAY6] 배열과 반복문

m1njae·2022년 1월 7일
0

22 Basic Challenge

목록 보기
6/25
post-thumbnail

배열 안에 요소들이 1억개 이상이 있다고 가정하자. 1억개 이상의 요소들을 더하거나, 빼는 일종의 계산을 할 때 우리는 한꺼번에 계산하기는 어려울 것이다.
하지만, 우리는 배열의 속성과 반복문을 활용하여 이러한 문제 상황을 해결할 수 있다.

배열의 속성

배열은 3가지 속성을 가지고 있다.

  • constructor: 배열을 생성하는 함수(function)을 나타낸다.
  • length: 배열에 포함된 요소의 길이, 즉 요소의 수를 이용한다.
var arr = ['a','b','c'];
console.log(arr.length);	// 3
  • prototype: 배열에 속성이나 메서드를 추가하여 사용한다.

문제 해결

var arr = [10,15,34,...];	// 1억개 이상의 요소가 있다고 가정

var i = 0;           
var total = 0;
while(i < arr.length){
  total += arr[i];
  i+=1;
}
console.log(total);

for문

for문은 while문과 함께 대표적인 반복문이다. while문은 주로 조건이 없어 몇 번 반복되어야 하는지 알지 못할 경우에 주로 사용되며, for문의 경우 반복횟수가 정해져 있을 때 주로 사용된다. while문의 경우 코드를 잘못 실행하게 될 경우 무한 루프에 빠질 수도 있게 되니 반복횟수가 정해져 있다면, for문을 활용하는 것이 안정적이다.
for문의 기본적인 형태는 다음과 같다.

for(초기화부분; 조건; 추가동작부분){
동작코드
}
  • 초기화부분은 for문이 시작할때 가장 먼저 한번만 실행되는 부분이다.
  • 조건부분: if문과 동일하게 이 부분에 작성된 코드를 Boolean 형태로 평가한 다음, true로 판단되면 동작코드를 실행한다.
  • 추가동작부분: 동작부분이 true로 판단되었을때 동작을 실행하고 그 다음 추가적으로 동작할 것을 작성하는 부분이다.

for문에서 추가동작부분은 무조건적으로 채워야하는 것은 아니며, 초기화부분도 채우지 않아도 상관없지만, 첫번째 세미콜론은 생략할 수 없다. 또한 초기화 부분은 for문의 지역 변수이기 때문에 for문이 다 돌고나서 for문 밖에서 변수를 활용하려고 하면 오류가 발생한다.

우리는 이제 while문이 아닌 for문을 활용해서도 문제를 해결 할 수 있다.

var arr = [10,15,34,...];	// 1억개 이상의 요소가 있다고 가정
          
var total = 0;
for(var i = 0; i < arr.length; i++){
  total += arr[i];
}
console.log(total);

백준 문제 풀이

푼 문제 중에서 에러를 마주한 문제, 기억에 남는 문제들은 따로 기록해놓으려고 한다.

2577번 숫자의 개수


내가 작성한 코드

let fs = require('fs');
let input = fs.readFileSync('/dev/stdin').toString().split('\n').map(x => Number(x));

let num = String(input[0]*input[1]*input[2]);

for(let i = 0; i <= 9; i ++){
    let count = 0;
    
    for(let j = 0; j < num.length; j ++){
        if(i === Number(num[j])){
            count +=1;
        }
    }
    console.log(count);
}

문제 해결 방안은 AxBxC 길이만큼 반복문을 돌리면서 0~9까지 모두 찾아보는 방법을 생각해보았다. AxBxC 길이만큼 반복문을 돌려주고 0~9까지 반복문을 돌려주어야 했기 때문에 이중for을 사용했다. 아이디어와 구현에서는 크게 어려움이 없었지만 split('\n')split('/n')로 작성하여 오랫동안 에러와 마주하였다..
코드를 보면 화살표 함수를 활용했는데, 문제를 효과적으로 풀기 위해서 구글링을 통해 알게 되었는데 함수 관련 포스팅을 할 때 다뤄볼 예정이다.

8958번 OX 개수

내가 작성한 코드

const fs = require('fs');
let input = fs.readFileSync('/dev/stdin').toString().split('\n');

let count = Number(input[0]);

for(let i = 1; i <= count; i++){
    let score = 0;
    let sum = 0;
    for(let j =0; j < input[i].length; j++){
        if(input[i][j] === 'O'){
            score += 1;
        }else{
            score = 0;
        }
        sum += score;
    }
    console.log(sum);
}

첫 줄에 케이스의 개수가 주어지고 각 케이스마다 OX문자열이 주어진다. 케이스의 개수만큼의 문자열이 input에 저장되어 있기 때문에 O와 X에 직접적으로 접근하는 input[i][j]를 생각해내는 것과 O가 연속되지 않을 때에는 score의 값을 초기화해주는 것이 문제 풀이의 주요한 점이라고 생각했다.

4344번 평균은 넘겠지

내가 작성한 코드

let fs = require('fs');
let input = fs.readFileSync('/dev/stdin').toString().split('\n');

let num = Number(input[0]);

for (let i = 1; i <= num; i++) {
    let score = input[i].split(' ').map(x => Number(x));
    let students = score[0];
    let highscoreStudents = 0;
    let sum = 0;
    
    for (let j = 1; j <= students; j++){
        sum += score[j];
        }
    let avg = sum / students;

    for (let k = 1; k <= students; k++) {
        if (score[k] > avg) {
            highscoreStudents += 1;
        }
    }
    
    let result = ((highscoreStudents / students) * 100).toFixed(3);
    
    console.log(result + "%");

}

첫 줄은 케이스의 개수가 출력되고, 두번째 줄부터 점수 값들이 주어지는데 학생의 수가 첫 수로 주어져 첫 수를 배제하고 평균을 계산해주는 것이 키포인트였다. 나는 인덱스 값을 활용하여 학생 수를 지정했지만, 배열의 맨 앞 요소를 제거해주는 shift() 메서드를 활용해도 좋을 듯하다.

for문이 너무 많이 들어가서 코드가 지저분했다. 그래서 구글링을 통해 배열의 값을 합하여 누적해주는 reduce()함수를 활용하여 코드를 수정할 수 있었다.

수정한 코드

let fs = require('fs');
let input = fs.readFileSync('/dev/stdin').toString().split('\n');

let num = Number(input[0]);

for (let i = 1; i <= num; i++) {
    let score = input[i].split(' ').map(x => Number(x));
    let students = score[0];
    let highscoreStudents = 0;
    
    let sum= score.reduce((acc, v) => acc += v, -students);
  // 수정된 코드
    
    let avg = sum / students;

    for (let j = 1; j <= students; j++) {
        if (score[j] > avg) {
            highscoreStudents += 1;
        }
    }
    
    let result = ((highscoreStudents / students) * 100).toFixed(3);
    
    console.log(result + "%");
}

정리 및 느낀 점

개념을 가지고 문제풀이를 했는데, 문제들이 for문을 이중으로 활용해야 하는 문제들이 많았다. 문제 풀이의 아이디어는 잘 생각해낸 것 같지만, JavaScript 언어에 아직 익숙치 않다보니 여러 오류들과 마주하기도 했고 구현하는데까지 오랜 시간이 걸렸던 것 같다. 그래도 시간이 오래 걸리더라도 모르는 부분, 궁금한 부분을 스스로 찾아보거나 해결된 문제들도 어떻게 하면 조금 더 효과적인 코드로 변환시킬 수 있을까에 대한 고민을 해보았다는 점에서 고무적이었다. 이런 긍정적인 부분을 계속해서 습관화할 수 있도록 해야겠다.

profile
할 수 있는 것부터 차근차근, 항해자의 공부 기록공간

0개의 댓글