배열 안에 요소들이 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
문은 while
문과 함께 대표적인 반복문이다. while
문은 주로 조건이 없어 몇 번 반복되어야 하는지 알지 못할 경우에 주로 사용되며, for
문의 경우 반복횟수가 정해져 있을 때 주로 사용된다. while
문의 경우 코드를 잘못 실행하게 될 경우 무한 루프에 빠질 수도 있게 되니 반복횟수가 정해져 있다면, for
문을 활용하는 것이 안정적이다.
for
문의 기본적인 형태는 다음과 같다.
for(초기화부분; 조건; 추가동작부분){
동작코드
}
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);
푼 문제 중에서 에러를 마주한 문제, 기억에 남는 문제들은 따로 기록해놓으려고 한다.
내가 작성한 코드
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')
로 작성하여 오랫동안 에러와 마주하였다..
코드를 보면 화살표 함수를 활용했는데, 문제를 효과적으로 풀기 위해서 구글링을 통해 알게 되었는데 함수 관련 포스팅을 할 때 다뤄볼 예정이다.
내가 작성한 코드
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
의 값을 초기화해주는 것이 문제 풀이의 주요한 점이라고 생각했다.
내가 작성한 코드
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 언어에 아직 익숙치 않다보니 여러 오류들과 마주하기도 했고 구현하는데까지 오랜 시간이 걸렸던 것 같다. 그래도 시간이 오래 걸리더라도 모르는 부분, 궁금한 부분을 스스로 찾아보거나 해결된 문제들도 어떻게 하면 조금 더 효과적인 코드로 변환시킬 수 있을까에 대한 고민을 해보았다는 점에서 고무적이었다. 이런 긍정적인 부분을 계속해서 습관화할 수 있도록 해야겠다.