백준 1474번
  • 이 문제는 다 풀어놓고 js 특유의 입력값을 받는 방식을 잘못설정하여 한참을 헤맸던 문제이다...

https://www.acmicpc.net/problem/1475

 

1475번: 방 번호

첫째 줄에 다솜이의 방 번호 N이 주어진다. N은 1,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

맨처음 제출한 코드
let fs = require('fs');
let input = fs.readFileSync('/dev/stdin').toString().split(' ');

//입력값 가공
let target = [];
for(let i = 0;i < input[0].length;i++){
    target.push(input[0][i]);
}


//각각의 번호가 몇번필요한지 종합할 배열 생성
let numbers = [0,0,0,0,0,0,0,0,0,0];
for(let i = 0; i < target.length; i++){
    numbers[Number(target[i])]++;
}

//6과 9는 하나로 생각해도 되므로 둘을 합친뒤 /2 그리고 반올림
let sixNine = Math.ceil(((numbers[6] + numbers[9])/2));
numbers[6] = sixNine;
numbers[9] = sixNine;

let set = Math.max(...numbers);

console.log(parseInt(set));

 

처음 이 문제를 보았을때 떠올린 풀이방법은 위 아래와 같다.

 

1. 입력받은값을 배열로 변환한다.

2. 필요한 0~9의 개수를 저장할 배열을 만든다.

3. 입력받은값을 for문을 통하여 2에서 만든 배열에 각 숫자에 해당하는 index를 ++ 해준다.

4. 6과 9는 서로 바꾸어 쓸 수 있으므로 둘을 합친뒤 / 2 그리고 반올림을 해준다.(반올림 하는 이유는 6과 9의 합이 홀수

    경우 .5 가 생기지만 이는 세트 하나를 더 챙겨야하기 때문)

5. 2에서 만든 배열의 최댓값을 구해주면 끝

 

나는 위 코드를 만들고 모든 반례가 정상적으로 정답이 나오지만 코드를 제출할때마다 입구컷을 당하는 상황을 보고 정신이 나가는줄 알았다..코드는 아무리 봐도 잘못된 부분이 없었고 이 근거로 어떠한 반례를 찾을 수가 없었다. 

 

 

 

 

정답으로 제출한 코드
const fs = require('fs');
const input = fs.readFileSync("/dev/stdin").toString().trim();

let word = input.toString();

let target = [];
for(let i = 0;i < word.length;i++){
    target.push(word[i]);
}

let numbers = [0,0,0,0,0,0,0,0,0,0];
for(let i = 0; i < target.length; i++){
    numbers[Number(target[i])]++;
}

let sixNine = Math.ceil(((numbers[6] + numbers[9])/2));
numbers[6] = sixNine;
numbers[9] = sixNine;

let set = Math.max(...numbers);

console.log(set);

결과

 

 

 

기존코드가 입구컷을 당하는 문제는 입력값을 받는 방식에 있었다. js는 입력값을 받는것이 다른 언어들에 비해 어렵다. 백준을 처음 시작한만큼 아직 입력값을 받는데 익숙치 않아서 많이 헤맸던거 같다.

 

기존코드가 입구컷을 당하는 이유는 입력값을 받는 부분에서 .trim() 을통해 공백을 지워주지 않아 숫자형으로 처리해야하는 데이터에 오류가 발생했던거 같다. 제출할때는 따로 출력값을 볼 수 없어 확신할 수 없지만 그것이 코드제출에서 입구컷을 당한 이유에 가장 가능성이 높아보인다. 

'백준' 카테고리의 다른 글

백준 2018번 "수들의 합 5"  (0) 2024.04.15
백준 1384번 "메시지"  (1) 2024.04.14
백준 1316번 "그룹 단체 체커"  (0) 2024.04.13
백준 2563번 "색종이"  (0) 2024.04.12
백준 1312번 "소수"  (0) 2024.04.11
  • 백준 2563번 문제는 색종이가 여러번 겹쳤을경우 해당 겹친부분을 여러번 계산하여 결과값이 음수가 되는 현상을 해결하지 못하여 오래 해멨던 문제이다.

https://www.acmicpc.net/problem/2563

 

2563번: 색종이

가로, 세로의 크기가 각각 100인 정사각형 모양의 흰색 도화지가 있다. 이 도화지 위에 가로, 세로의 크기가 각각 10인 정사각형 모양의 검은색 색종이를 색종이의 변과 도화지의 변이 평행하도록

www.acmicpc.net

 

 

 

 

맨 처음 제출한 코드
const fs = require('fs');
const input = fs.readFileSync("/dev/stdin").toString().trim().split("\n");

let paperNum = +input[0];
let paperXy = [];
let result = 100 * paperNum;
let sameRec = 0;

for(let i = 1; i< input.length;i++){
    paperXy.push(input[i].trim().split(' '));
    paperXy[i-1][0] = parseInt(paperXy[i-1][0]);
    paperXy[i-1][1] = parseInt(paperXy[i-1][1]); 
}

//겹치는 부분 계산후 결과값에서 감소
const checkArea = (leftRec,rightRec) => {
    if((leftRec[0] + 10) > rightRec[0]){
        let bottom = (leftRec[0]+10) - rightRec[0];
        let left = 0;
        if(leftRec[1] > rightRec[1]){
            left = (rightRec[1]+10) - leftRec[1];
        }
        else{
            left = (leftRec[1] + 10) - rightRec[1];
        }
        result -= bottom*left;
    }
}

//겹치는지 확인후 겹쳤을경우 checkArea 함수 호출
for(let i = 0; i < paperXy.length; i++){
    for(let j = i+1; j < paperXy.length; j++){
    	//같은 위치의 도형일경우 인덱스에서 제거
        if((paperXy[i][0] == paperXy[j][0]) && (paperXy[i][1] == paperXy[j][1])){
            paperXy.splice(j,1);
            sameRec++;
            j--;
        }
        else if(paperXy[i][0] > paperXy[j][0]){
            checkArea(paperXy[j],paperXy[i]);
        }
        else{
            checkArea(paperXy[i],paperXy[j]);
        }
    }
}

console.log(result - (sameRec*100));

 

위 코드를 작성하면서 내가 생각했던 풀이 방식은 아래와 같다.

 

일단 색종이가 서로 겹치지 않았을경우의 최댓값을 결과값으로 정해놓는다.

예를들어 색종이 4장을 놓는다면 결과값이 400으로 정해놓는것이다.

 

그 이후 이중포문을 활용하여 사각형끼리 겹치는 부분이 있는지 확인한다.

이때 완전히 겹치는 도형이 들어올 수 있다.

이럴경우 이 겹치는 도형을 제거하지 않을경우 결과값을 중복감소하여 데이터 오류로 이어질 수 있기때문에 이를 조건문을 통해 인덱스에서 제거해주고 sameRec 이라는 변수를 증가시켜 나중에 결과값에 적용시켜주었다.

 

이렇게하면 될줄 알았지만 하나의 반례를 넘지 못했다.

4

1 1

1 2

2 1

2 2

 

위 반례에서 4개의 사각형이 서로 겹치는 구조인데 위 코드로는 중복된 구역을 계산하여 결과값에서 감소만 시키기때문에 결과값이 음수가 나온다. 따라서 위 방법으로는 문제를 풀지 못한다는걸 알았다. 이때 맨땅에 헤딩하는 식으로 좌표값을 일일히 계산해야하는건가 라는 생각에 머리가 아찔했다. 

 

 

 

정답으로 제출한 코드
const fs = require('fs');
const input = fs.readFileSync("/dev/stdin").toString().trim().split("\n");

let paperNum = +input[0];
let paperXy = [];

//색칠
let filled = false;
let result = 0;

//큰사각형
let wholeRec = new Array(101);

//큰 사각형에게 2차원배열을 추가
for(let i = 0;i<wholeRec.length;i++){
    wholeRec[i] = new Array(101);
}

//2차원배열안을 채움
for(let i = 0; i < wholeRec.length; i++){
    for(let j = 0;j < wholeRec.length;j++){
        wholeRec[i][j] = [i,j,filled];
    }
}

//입력받은값 가공
for(let i = 1; i< input.length;i++){
    paperXy.push(input[i].trim().split(' '));
    paperXy[i-1][0] = parseInt(paperXy[i-1][0]);
    paperXy[i-1][1] = parseInt(paperXy[i-1][1]); 
}

//입력받은 사각형에해당되는 범위 색칠
for(let i = 0; i < paperXy.length; i++){
    let x = paperXy[i][0];
    let y = paperXy[i][1];
    for(let j = x; j < x+10; j++){
        for(let k = y; k < y+10; k++){
            wholeRec[j][k][2] = true;
        }
    }
}

//색칠이 되어있을경우(true 일경우) result++
for(let i = 0; i < wholeRec.length; i++){
    for(let j = 0;j < wholeRec.length;j++){
        if(wholeRec[i][j][2]){
            result++;
        }
    }
}
console.log(result);

 

결과

 

 

 

 

머리를 싸매고 고민에 고민을 하던중 이 문제를 색칠놀이 라고 생각하면 어떨까 라는 아이디어가 떠올랐다.

 

일단 문제에서 큰 사각형의 크기를 100 * 100으로 지정해놓았으므로 위 크기를 가지는 이중배열을 만들고 각 칸에 boolean false값을 저장한다.

 

그 다음 입력받은 사각형의 범위를 true로 바꾸는 방식이면 복잡한 계산을 거치지 않고 겹치는 부분도 색칠위에 색칠을 하는것이므로 까다롭게 생각해줄 필요가 없다고 생각했다.

 

겹치는부분은 상관하지않고 그저 입력받은 사각형 범위를 모두 색칠만 해주면 되는것이다. 

'백준' 카테고리의 다른 글

백준 2018번 "수들의 합 5"  (0) 2024.04.15
백준 1384번 "메시지"  (1) 2024.04.14
백준 1316번 "그룹 단체 체커"  (0) 2024.04.13
백준 1475번 "방번호"  (0) 2024.04.12
백준 1312번 "소수"  (0) 2024.04.11
백준 1312번
  • 1312번 문제는 처음에 풀이방법을 완전히 잘못잡아 한참 헤맸던 문제이다. 

 

https://www.acmicpc.net/problem/1312

 

1312번: 소수

피제수(분자) A와 제수(분모) B가 있다. 두 수를 나누었을 때, 소숫점 아래 N번째 자리수를 구하려고 한다. 예를 들어, A=3, B=4, N=1이라면, A÷B=0.75 이므로 출력 값은 7이 된다.

www.acmicpc.net

 

맨 처음으로 작성한 코드
let fs = require('fs');
let input = fs.readFileSync('./input.txt').toString().split(' ');

let num = Number(input[0]) / Number(input[1]);
let target = Number(input[2]);

let left = Math.floor(num * Math.pow(10,target));
let right = Math.floor(num * Math.pow(10, target-1));


let result = Math.floor(left - right*10);
console.log(result);

 

처음엔 이 문제가 굉장히 쉽다고 생각했다. 내가 생각한 문제의 풀이방법은 아래와 같다.

 

입력이 25 7 5 일경우

25 / 7 = 3.571428571428571 

이때 5번째 소수점을 구해야하는것이므로 한 변수는 10^5를 곱하고 나머지 한변수에는 그보다 하나 낮은 10^4를 곱하여

 

357142 - (35714 * 10) 의 형태를 만들어서 계산하면 원하는 답인 2가 나온다.

 

 

하지만 위 방법으로 수많은 반례를 마주했다. 이 문제는 부동소수점으로부터 시작된다. 위 방법에대한 반례는 아래와 같다.

 

입력이 1 3 19 일경우

1 / 3 = 0.3333333333333333 이라는 무한 소수가 생성된다. 

이때 위 방법대로 계산하게 되면 3 이 아닌 0이라는 값을 얻게된다. 

이는 컴퓨터가 계산하면서 미세한 오차가 발생하기 때문이다.

하나의 예시로 계산하는 중간과정에서 left와 right의 값을 출력해보면 아래와 같은 상태가된다.

결과값

 

즉, 위 풀이방법과 같이 한번에 나눠서 계산을 하고자 하면 넘치는 무한소수로인해 제대로된 데이터를 얻어낼 수 없게된다. 풀이방법이 처음부터 틀렸다는것을 모르고 많은 시간을 저 방대한 양의 데이터를 어떻게 처리할지 고민했다..

 

 

 

정답으로 제출한 코드
  • 문제 해결방안의 핵심 키는 나머지연산에 있다. 한번에 나누는것이 아닌 하나씩 차례대로 갉아먹는 느낌으로 처리하는 것이다. 우리가 높은 수의 나눗셈을 수기로 계산한다고 생각해보자. 우리는 10자리를 구하고 그 나머지를 나누어 1의자리를 구하고,또 그것을 나누어 첫번째 소수를 구하고,또 반복하며 2번째,3번째 소수 등등 순차적으로 구해나간다. 그것이 이 문제 풀이법의 핵심이다. 아래는 필자가 작성한 정답코드이다.
let fs = require('fs');
let input = fs.readFileSync('./input.txt').toString().split(' ');

let target = Number(input[2]);
let left = Number(input[0]);
let right = Number(input[1]);
let result = left;

for(let i = 0; i < target; i++){
    result %= right;
    result *= 10;    
}

console.log(Math.floor(((result/10)/right)*10));

 

정답!

 

 

하나의 예시를 잡고 천천히 코드를 따라가보자. 

아까의 반례였던 1 3 19를 예시로 들겠다.

 

1 % 3 = 1이다.

여기서 몫은 0 나머지가 1인것이다.

우린 1의자리의 숫자를 구한것이다. 이제 소수점 첫번째자리를 구하려면 *10을 해준뒤 다시 나누어주면된다.

 

10 % 3 = 1

몫은 3, 나머지는 1

이때 소수점 첫번째 자리가 3인것이다. 이 작업을 총 19번 반복해주면 된다.

 

19번의 반복이 끝나면 이제 우리는 나머지가 아닌 몫을 구해주면된다.

하지만 필자는 반복문에서 *10을 한채 마무리되기떄문에 19번의 반복이 끝났을때  result의 값이 10이된다.

따라서 이를 10을 다시 나눠준뒤 3과 나누어주면 0.333333.. 이 될것이다. 이때 소수점 첫번째 자리가 19번째 소수이므로 *10을 해주고 Math.floor를 사용하여 나머지 소수를 버려주면 우리가 원하는 값을 얻을 수 있다.

 

 

느낀점
  • 해당 문제를 풀면서 방향을 잘못잡았다는걸 몰랐을때 많이 당황스러웠고 어떤 방법을 써도 항상 데이터의 오차로인한 문제가 발생하는걸 막을 수 없었다. 그래서 부동소수점에대한 많은 구글링을 하는 도중에 toFixed() 를 사용해도 100번째 소수점까지 밖에 처리를 못한다는것을 알았을때 무언가 잘못되었다는걸 알았다. 찾아야되는 물건이 들어있는 박스를 한번에 뒤집어놓고 그안에서 물건을 찾으려 했다는걸 알았고 하나씩 천천히 꺼내면서 찾아보면 어떨까 하는 생각이 들었다. 그 결과 데이터의 오차는 없었고 보다 깔끔한 코딩을 할 수 있었다. 이 문제로부터 데이터를 처리하는 순서에대한 중요성을 알게된거 같다.

'백준' 카테고리의 다른 글

백준 2018번 "수들의 합 5"  (0) 2024.04.15
백준 1384번 "메시지"  (1) 2024.04.14
백준 1316번 "그룹 단체 체커"  (0) 2024.04.13
백준 1475번 "방번호"  (0) 2024.04.12
백준 2563번 "색종이"  (0) 2024.04.12
글꼴과 관련된 스타일링이란?
  • 글꼴과 관련된 css 스타일링에는 가장 대표적으로 fonts 가 있다. 이 스타일링은 폰트의 크기, 굵기, 글꼴등을 설정할 수 있다. 

 

 

font-size
  • font-size는 폰트의 크기를 조절하는 스타일링이다.  font-size의 단위는 여러가지 있지만 px단위를 제일 많이 사용한다.
//코드 양식
font-size: 단위;


//코드 사용 예시
//html 부분
<p class="size1">15px 입니다.</p>
<p class="size2">20px 입니다.</p>
<p class="size3">25px 입니다.</p>

//css 부분
.size1{
    font-size: 15px;
}

.size2{
    font-size: 20px;
}

.size3{
    font-size: 25px;
}

 

결과

 

 

 

 

 

font-weight
  • font-weight는 글꼴의 굵기를 조절하는 css이다. 
//코드 양식
font-weight: 단위;

//코드사용 예시
//html 부분
<p class="weight1">100 입니다.</p>
<p class="weight2">600 입니다.</p>


//css 부분

.weight1{
    font-weight: 100;
}

.weight2{
    font-weight: 600;
}

'CSS' 카테고리의 다른 글

CSS 선택자에대해 알아보자.  (0) 2024.03.21
CSS란 무엇인가  (0) 2024.03.20

내장함수란?

  • 내장함수란 함수의 일종으로 js에 기본적으로 생성되있는 함수들을 의미한다. 이러한 내장함수를 활용하여 개발자는 그 기능을 직접 만들지 않아도 함수를 호출하는것만으로도 해당 기능을 사용할 수 있게된다. js가 제공하는 내장함수는 다양하지만 이번시간에는 그중에서 많이 쓰이는 내장함수들에대해 알아보고자 한다.

 

 

 

setTimeout()
  • setTimeout() 함수는 시간을 설정하여 해당 시간뒤에 지정한 함수를 실행하는 함수이다. 시간을 설정할때의 단위는 ms 이며 1초는 1000ms이다.
//함수의 양식
setTimeout(함수,시간);

//함수 사용 예시
setTimeout(function(){
	console.log("hello");
},1000);

 

 

 

 

setInterval()
  • setInterval() 함수는 setTimeout() 과 동일하지만 지정한 시간을 간격으로 무한 반복된다는 점에서 다르다. 시간 단위는 ms로 동일하며 1초는 1000ms 이다.
//함수 양식
setInterval(함수,시간);

//함수 사용 예시
setInterval(function(){
    console.log("hello");
},1000);

//1초 단위로 hello 가 계속 출력

 

 

 

clearInterval()
  • clearInterval() 함수는 setInterval() 함수와 짝꿍이며 setInterval() 함수를 중지하는 함수이다.
//코드 양식
clearInterval(중지할interval값);

//코드 사용 예시
let hello = setInterval(function(){
    console.log("hello");
},1000)

//일정시간뒤에 1번실행되는 코드
setTimeout(function(){
    stopInterval();
},4001)

//interval을 중지시키는 함수
let stopInterval = () => {
    clearInterval(hello);
}


//위 코드의 출력결과

hello
hello
hello

//프로그램 종료

 

 

 

 

parseInt()
  • parseInt() 함수는 문자열을 정수로 변환해주는 함수이다. 사용자에게 값을 입력받을때 
// //함수 양식
parseInt(문자열);

//함수 사용 예시
let number = parseInt("93" + "12");

console.log(number);
// 9312 출력

 

 

 

 

prompt()
  • prompt() 는 사용자로부터 입력값을 받을 수 있도록 해주는 함수이다. 이를 통해 사용자와 상호작용하는 프로그램을 개발할 수 있다.

 

 

 

하지만 prompt() 함수를 사용할때의 주의점은 사용자로부터 받은 입력값은 문자열로 처리된다는 점이다. 예를 들어 사용자로부터 2개의 숫자를 입력받고 서로 더한값을 출력하는 코드를 작성했을때 코드 및 결과는 아래와 같다.

 

let number1 = prompt("첫번째 번호를 입력해주세요");	//12 입력
let number2 = prompt("두번째 번호를 입력해주세요");	//34 입력
document.write("두 숫자를 더한 값: " + (number1+number2));

 

결과

 

 

12와 34를 더한값은 46이다. 하지만 1234가 출력되었다. 이는 산술연산자가 데이터를 문자열로서 처리했기때문이다. 따라서 46이라는 값을 얻으려먼 parseInt() 함수를 이용하여 데이터타입을 변형해주면 된다.

 

let number1 = parseInt(prompt("첫번째 번호를 입력해주세요"));	//12 입력
let number2 = parseInt(prompt("두번째 번호를 입력해주세요"));	//34 입력
document.write("두 숫자를 더한 값: " + (number1+number2));

 

결과

 

 

isNaN()
  • isNaN() 함수는 매개변수로 받은 값이 NaN 값인지 아닌지를 판단해 참 혹은 거짓을 리턴해주는 함수이다. 조건문과 같이 쓰여져 예외처리로도 사용할 수 있다.
let nan_ture = NaN;
let nan_false = 10;

console.log(isNaN(nan_ture));	//true 출력
console.log(isNaN(nan_false));	//false 출력

 

 

 

 

isFinite()
  • isFinite() 함수는 매개변수로 받은값이 무한한값인지 아닌지를 판단해 참 혹은 거짓을 리턴해주는 함수이다.
let finite = 10;
let infinite = Math.pow(2,1024);

console.log(isFinite(finite));		//true 출력
console.log(isFinite(infinite));	//false 출력

 

 

 

 

 

 

eval()
  • eval() 함수는 문자열로 구성된 연산식의 결과값을 반환해주는 함수이다. 
//코드 양식
eval(값);

//코드 사용예시
console.log(eval(10 + 10));	// 20 출력
console.log(eval(10 * 10));	// 100 출력
console.log(eval(10 - 10));	// 0 출력

//코드 응용
let leftNum = parseInt(prompt("좌변을 입력하시오"));
let rightNum = parseInt(prompt("좌변을 입력하시오"));
let cal = prompt("연산기호를 입력하시오");
document.write("결과값: " + eval((leftNum + cal + rightNum)))

 

사용자 입력
결과창

 

 

 

confirm()
  • confirm() 함수는 사용자에게 확인 또는 취소 중 입력값을 받아 참 또는 거짓을 리턴해주는 함수이다.
//코든 양식
confirm(값);

//코드 사용 예시
if(confirm("동의하시겠습니까")){
	document.write("동의하셨습니다.");
}
else{
	document.write("비동의하셨습니다.");
}

확인창
확인을 누른경우(왼쪽사진) 와 취소를 누른경우(오른쪽사진)

 

 

 

 

 

alert()
  • alert() 함수는 매개변수안에있는 문자열을 경고창으로 출력해주는 함수이다. 
//코드 양식
alert(문자열);

//코드 사용 예시
alert("hello");

 

함수란?
  • 함수란 어떠한 기능을 위해 모인 코드의 집합이다. 함수는 여러번 재사용이 가능하고 개발자가 필요한 기능을 만들 수 있다는 점에서 개발에서 빼놓을 수 없는 필수적인 요소중에 하나이다. 이러한 함수를 선언하는 방법에는 여러방법이 있다. 함수에대해 간략히 설명하자면 함수는 자판기이다. 우리는 자판기에서 무언가를 사먹을때 돈을 넣고 물건을 받는다. 이때 돈이 매개변수이고 물건이 리턴값이다. 즉, 함수는 매개변수를 받고 코드를 실행하여 리턴값을 주는 하나의 집합인것이다. 이때 주의할점이 매개변수와 리턴값은 각각 필수적인 요소가 아닌 선택적 요소이다.  

출처: 그림판

 

 

 

 

함수 선언식
  • 함수 선언식은 명시적으로 함수를 선언할 수 있다는 점에서 가장 접근하기 쉽다. 하지만 함수 선언식은 호이스팅 이라는 문제점을 가지고 있기때문에 아래에 나오는 함수 선언방법에 비해서는 덜 사용된다. 호이스팅에대해 간략히 설명하자면 인터프리터가 코드를 실행할때 변수,클래스 등을 맨위로 끌어올리는것을 의미한다. 보통 코드의 유지보수 및 가독성을 위해 호이스팅이 되는 함수선언식은 지양하는 편이다. 함수 선언식의 양식은 아래와 같다.
//함수 선언식의 구조
function 함수이름(매개변수){
	실행코드
    return 리턴값;	//해당 부분은 필수적이지 않음
}

//함수 작성 예시
function hello(){
	console.log("Hello");
}

//매개변수를 사용한 함수의 예시
function hello(name){
	console.log("입력된 이름: " + name);
}


//리턴값을 활용한 경우
function hello(){
	return "hello";
}

let words = hello();



//함수를 호출하는 법
hello();

 

 

 

 

 

 

함수 표현식
  • 함수 표현식은 변수에 함수를 대입하는 모양의 함수 선언방식이다. 이는 호이스팅의 대상이 아니기 때문에 함수의 위치에따라 오류가 발생하기도 한다. 아래는 함수표현식의 예시와 주의점에대한 예제코드이다.
//함수 표현식의 구조
데이터타입 변수명 = function(매개변수){
	실행코드
}

//함수 표현식의 활용 예시
const hello = function(){
	console.log("Hello");
}


//매개변수를 활용한 경우
const hello = function(name) {
	console.log(name);
}


//리턴값을 활용한 경우
const hello = function(){
	return "hello";
}

let words = hello();


//함수 호출방법
hello();



//호이스팅에대한 주의점

//호출이 함수보다 위에 위치할경우
hello();	//오류

const hello = function(){
	console.log("Hello");
}

//호출이 함수보다 아래에 위치할경우

hello();	// "Hello" 출력

 

 

 

 

 

 

화살표 함수
  • 화살표 함수는 함수표현식에서 조금더 간결화한 함수 선언방법이다. 근본적으로 함수표현식과 다르지 않으나 가동석이 떨어지므로 코딩을 처음 접한 사람이 본다면 이게 뭐지 라는 생각이 들것이다. 화살표 함수의 예제는 아래와 같다.
//화살표 함수의 예시
데이터타입 함수이름 = (매개변수) => {
	실행코드;
    return 리턴값;
}

//사용 에시
const hello = () => {
	console.log("hello");
}


//매개변수를 활용한 예시
const hello = (name) => {
	console.log(name);
}


//리턴값을 활용한 예시
const hello = () => {
	return "hello";
}

let words = hello();



//함수 호출 방법
hello();

 

 

위 세가지 방법이 함수를 선언하는 방법은 다 다르지만 함수를 호출하는 방법은 셋모두 동일하다.

내장객체란?
  • 내장객체란 개발자가 따로 객체를 선언하지 않아도 Js에서 기본적으로 제공하는 객체를 의미한다. 이번시간에선 내장객체 중에서 많이 사용되는 객체중에 하나인 Math 객체에대해서 알아보고자 한다.

 

 

Math 객체란?
  • Math 객체는 주로 난수생성, 최대,최소값 구하기 등 숫자와 관련된 역활을 한다. Number객체가 가지고 있는 메소드는 아래와 같다.
Math.max() 최댓값을 반환한다
Math.min() 최소값을 반환한다
Math.random() 0과 1사이의 난를 생성한다
Math.pow(x,y) x 를 y번 제곱하여 반환한다
Math.round() 반올림하여 반환한다
Math.ceil() 올림하여 반환한다
Math.floor() 버림하여 반환한다
Math.sign() 양과 음을 판단하여 해당부호를 반환한다

 

let max = Math.max(10,4,23,4);	// 23 출력
let min = Math.min(10,4,23,4);	// 4 출력
let random = Math.random();	// 0.6186860539712182 출력
let pow = Math.pow(2,5);	// 32 출력
let round = Math.round(10.5);	// 11 출력
let ceil = Math.ceil(10.5);	// 11 출력
let floor = Math.floor(10.5);	// 10 출력
let sign = Math.sign(-10);	// -1 출력


console.log(max,min,random,pow,round,ceil,floor,sign);

//출력결과
23 4 0.6186860539712182 32 11 11 10 -1

 

 

 

 

 

Math.random의 사용
  • Math.random은 난수를 생성한다는 점에 있어 개발에 많이 사용된다. 하지만 Math.random 은 0과 1사이의 난수만을 생성하기 때문에 우리가 원하는 수 범위 안에서의 난수를 얻기 어렵다. 따라서 Math.random은 단독으로 쓰이지 않고 다른 기능과 같이 쓰이는 경우가 많다. 
let let random = Math.random() * 100;
console.log(random);	// 97.99585499423324 출력

random = Math.floor(random);
console.log(random);	// 97 출력

 

보통 사용자가 원하는 범위를 설정하기 위해서 Math.random() * n 을 사용한다. n을 곱할경우 0 ~ n-1 까지의 난수를 생성한다. 위 코드에선 100을 곱했으므로 0 ~ 99 까지의 난수가 생성되고 1 ~ 100까지의 난수를 생성하기 위해서는 괄호로 묶고 +1 을 해주면 된다. 

그리고 Math.random() 을 단독으로 사용할경우 뒤의 긴 소수점까지 출력되므로 보통 Math.floor를 사용하여 소수점을 제거해준다. 따라서 보편적으로 사용되는 Math.random의 모습은 아래와 같다.

 

// 0 ~ n-1 까지의 난수 범위를 설정할 경우
let random = Math.floor(Math.random() * n);

// 1 ~ n 까지의 난수 범위를 설정할 경우
let random = Math.floor(Math.random() * n) + 1;
반복문이란?
  • 반복문은 코딩에서 빼놓을 수 없는 필수적인 요소중에 하나이다. 반복문은 for 를 사용하여 실행코드들을 주어진 조건에 따라 여러번 반복시행할 수 있는 문법이다. 이러한 반복문의 활용으로 코드를 획기적으로 줄일 수 있고 또한 반복문을 잘못사용하면 무한루프 또는 프로그램의 오류로 이어질 수 있기때문에 반복문을 잘활용하는 것은 개발자로서 중요하다. 이제 반복문의 사용법에대해 알아보자.

 

 

반복문의 사용
  • 반복문은 for를 활용하여 초기식, 조건식, 증감식 을 설정하여 개발자가 원하는 만큼의 반복횟수를 설정할 수 있다. for문의 기본 양식은 아래와 같다.
for( 초기식; 조건식; 증감식;){
	실행코드;
}

//예시
for(let i = 0; i < 5; i++){
	console.log("Hello");
}

 

for문은 초기식, 조건식, 증감식을 사용한다. 초기식은 반복문이 실행될때 초기 한번만 실행되며 반복문의 시행횟수를 조절하는 변수에대한 정보가 있다. 조건식은 해당 조건문이 참일경우 반복문안에 있는 코드를 실행하게한다. 마지막으로 증감식은 반복될때마다 실행되며 변수에 변화를 준다.

 

for문의 실행구조

 

조건문의 진행구조에대해 설명하기위해 위의 그림을 첨부해봤다. for문이 처음실행되면 초기식이 실행된다(1). 이후 조건식을 체크하고 조건식이 참일경우 실행코드를 실행한다(2). 실행코드가 완료되면 증감식이 실행된다(3). 이후 다시 조건식을 확인하고 참일경우 다시 실행코드, 증감식 순으로 실행된다. 이후 반복을 계속하다가 조건식이 거짓일경우 실행코드를 실행하지 않고 for문을 빠져나오게된다(5). 

 

이를 인지하고 맨위의 예제코드에서 사용된 for문을 보면 for(let i = 0; i  < 5; i++) 라고 적혀있다. 이를 해석하면 for( i = 0 변수 선언; i 가 5보다 작을때까지 반복; 반복후에 i = i+1(i에 1을 더함);) 이된다. 

 

 

 

이중 for문
  • 이중 for문은 for문 안에 for문을 넣는것이다. 사실 for문안에는 개발자가 원하는 만큼의 for문을 넣을 수 있지만 for문은 중첩되면 중첩될수록 반복횟수가 기하급수적으로 많아진다는점에 있어서 프로그램의 최적화에 문제가 될 수 있다. for문을 중첩해서 사용할때의 주의점은 초기식에서 사용하는 변수가 겹치면 안되다는 것이다. 변수의 선언은 자유지만 보통 i,j,k 를 많이 사용한다.
for(초기식; 증감식; 조건식){
	for(초기식;증감식;조건식){
    	실행코드;
    }
}


// 코드 예시
for(let i = 0; i < 5; i++){
	for(let j = 0; j < i; j++){
    	console.log("i값: " + i + " j 값: " + j);
    }
}

//실행 결과
i값: 1 j 값: 0
i값: 2 j 값: 0
i값: 2 j 값: 1
i값: 3 j 값: 0
i값: 3 j 값: 1
i값: 3 j 값: 2
i값: 4 j 값: 0
i값: 4 j 값: 1
i값: 4 j 값: 2
i값: 4 j 값: 3

 

위 예제코드에선 이중for문의 실행순서를 이해하기 쉽도록 코드가 실행될때의 i값과 j값을 출력하도록 했다. 이러한 이중for문은 이중배열을 다룰때 많이 사용된다. 

 

 

 

 

배열과 for문
  • 배열과 for문은 떼어놓기 어려운 단짝이다. for문을 사용하면 배열을 관리하기 쉬워진다.
let score = [90,80,70,60];

for(let i = 0; i < score.length; i++){
	console.log(score[i]);
}

//실행결과
90
80
70
60

 

for문을 반복문과 함께 사용할때는 보통 조건식에 특정한 숫자보다는 배열의 길이를 나타내는 .length 를 사용하는 경우가 많다. 이는 배열에 사용자에게 입력받은 값이 들어가 있을경우 배열의 길이를 특정짓기 힘들고 배열의 길이보다 더 혹은 덜 반복시행될경우 데이터 오류로 이어질 수 있기 때문이다. 위 코드는 그저 배열안에 있는 정보를 출력한것이고 이를 좀더 응용해보면 배열안에 객체를 저장하고 if문을 통해 배열안에 특정 값만 출력해낼 수 있다. 예제는 아래와 같다.

 

let student = [
	{name:"철수", score:80},
	{name:"영희", score:70},
	{name:"맹구", score:60},
	{name:"짱구", score:90}
];

for(let i = 0; i < student.length; i++){
	if(student[i].score >= 80){
		console.log(student[i].name);
	}
}

//실행결과
철수
짱구

 

위 코드에선 student 배열안에 여러개의 객체를 저장했다. 그리고 for문을 통해 배열을 가져오고 조건문을 통해 객체안에 score의 값이 80이상일경우 해당 객체의 name값을 출력하는 코드를 작성했다. 이런식으로 for문을 활용하여 배열안에 원하는 데이터를 추출할 수 있다. 이제 다양한 문제를 통해 for문을 익혀보자. 

 

 

 

 

 

 

" * " 로 그림 그리기(문제)
  • 1번: for문을 활용하여 아래의 그림을 완성해보시오. process.stdout.write(); 을 활용하면 줄바꿈없이 console 출력이 가능하다.
     

 

 

 

  • 2번: for문을 활용하여 아래의 그림을 완성해보시오.(삼각형 상하반전)

 

 

 

 

  • 3번: for문을 활용하여 아래의 그림을 완성해보시오.(삼각형 좌우반전)

 

 

 

  • 4번:for문을 활용하여 아래의 그림을 완성해보시오.(정삼각형 모형)

 

 

  • 5번:for문을 활용하여 아래의 그림을 완성해보시오.(마름모)

 

 

 

 

 

 

" * "로 그림 그리기(예제코드)
  • 먼저 코딩에있어 정답은 없다. 같은 결과여도 다양한 코드가 존재한다. 아래 코드들은 필자가 부족한 지식으로 작성해본 코드들이다. 이 점 유의하길 바라고 코드를 읽고 이해하는것이 중요하다. 반대로 아래 코드를 보고 어떤 형상의 그림이 나올지 유추해보는것도 큰 도움이 될것이다. 

 

  • 1번문제
for(let i = 0; i < 10; i++){
	for(let j = 0; j < i; j++){
		process.stdout.write("*");
	}
	console.log("");
}

 

 

 

  • 2번 문제
for(let i = 10; i > 0; i--){
	for(let j = i; j > 0; j--){
		process.stdout.write("*");
	}
	console.log("");
}

 

 

 

 

  • 3번 문제
for(let i = 10; i > 0; i--){
	for(let j = i; j > 0; j--){
		process.stdout.write(" ");
	}
	for(let k = 10 - i; k > 0; k--){
		process.stdout.write("*");
	}
	console.log("");
}

 

 

  • 4번 문제
for(let i = 0; i < 10; i++){
	for(let j = 10; j > i; j--){
		process.stdout.write(" ");
	}

	for(let j = 0; j < i-1; j++){
		process.stdout.write("*");
	}

	for(let j = 0; j < i; j++){
		process.stdout.write("*");
	}

	console.log();
}

 

 

  • 5번문제
for(let i = 0; i < 10; i++){
	for(let j = 10; j > i; j--){
		process.stdout.write(" ");
	}

	for(let j = 0; j < i-1; j++){
		process.stdout.write("*");
	}

	for(let j = 0; j < i; j++){
		process.stdout.write("*");
	}

	console.log();
}
for(let i = 0; i < 9; i++){
	for(let j = 0; j-1 <= i; j++){
		process.stdout.write(" ");
	}
	for(let j = 8; j > i; j--){
		process.stdout.write("*");
	}
	for(let j = 7; j > i; j--){
		process.stdout.write("*");
	}
	console.log();
}

+ Recent posts