[03장. 자바스크립트 개발환경과 실행방법]

</br>

✏️ JS의 실행환경


  JS의 실행 환경은 크게 브라우저 / 브라우저 외의 환경으로 나눌 수 있다. 초기에 웹페이지를 동작시키기 위해 제작된 목적과는 다르게, 많은 사용자를 통해 성장하여서 현대에서는 다양한 곳에 사용되어지고 있기 때문이다.

</br>

✏️ 혼자 할 수 있는 일은 아무 것도 없다.


  JS가 브라우저에서 동작하게 될 때, JS의 코어 자바스크립트가 혼자 일하는게 아니라 Web API와 협업하게 된다.

자바스크립트는 싱글 스레드 언어(언어에서 명령을 수행해줄 노동 요정이 한 명이다)로 입력된 명령을 순서대로 하나씩 실행할 수 밖에 없는데, Web API는 이를 도와주어 멀티 스레드 언어처럼 동작할 수 있게 해준다.

이것뿐만 아니라, Web API는 웹페이지를 핸들링하기 위해 많은 기능을 제공해서 코어 자바스크립트를 도와주게 된다.

어떤 사람도, 기술도 혼자할 수 있는 것에는 한계가 있다. 유연함을 통해 협력하는 자세가 더 중요한 것 같다.

</br>

✏️ Node.js의 실행환경


 

Node.js 같은 경우는 실행환경이 브라우저가 아니기 때문에, Web API를 사용하지 못하게 된다.

백준에서 문제풀이를 할 때, 웹페이지를 구현할 때 사용하던 몇 몇의 기능을 사용하려고 하면 에러가 발생하는 원인이 여기에 있다.


[05장. 표현식과 문]

</br>

✏️ 사용할 말이 쓰기 어렵다면, 쉽게 쓸 수 있도록 사회적인 합의를 거칩시다.


  컴퓨터는 데이터를 0과 1로만 이해할 수 있다. 이러한 0과 1을 통해 문자, 숫자, 기호등을 모두 표현하게 된다.

사람들이 이렇게 데이터를 표현하는 것은 효율적이지 못하기 때문에, 사회적인 합의를 거쳐서 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하게 된다.

이것을 리터럴이라고 부른다.

</br>

✏️ 값과 표현식과 문


  표현식은 값으로 평가될 수 있는 문(문장)이다.

은 프로그램에게 주는 명령이다. 이것은 프로그램을 구성하는 기본 단위이자 최소 실행 단위이다.

은 식(표현식)이 평가되어 생성된 결과이다.

이 세 가지 정의를 통해서 내용을 정리해보자면, 프로그래머는 을 통해서 명령을 하고, 그 중에 이 될 수 있는 것은 표현식이라고 한다.

‘모든 문은 값이 될 수 있는 것 아닌가?’라는 의문이 들 수 있는데, var x;와 같이 변수를 선언하는 선언문도 이지만, 값으로 평가될 수는 없다. 이런 경우 표현식이 아닌 문이 된다.

그러니, 컴퓨터에게 주는 말 중에 변수에 할당할 수 있는 것은 값이 되는 것이다.

‘사과’라는 말은 변수라는 바구니에 담을 수 있다. 그런데 ‘if (사과의 개수 > 8)’이라는 ‘조건’은 바구니에 담을 수 없을 것이다.

값, 표현식, 문은 조금 헷갈릴 수 있는 것 같은데, 알아볼 수 있는 가장 간단한 방법은 변수에 할당해보는 것이다.

</br>

✏️ 편리함에는 책임이 따른다.


  자바스크립트는 여러가지 편리한 기능을 제공하는데, 그 중 하나는 세미콜론 자동 삽입 기능이다.

세미콜론은 문의 종료를 나타내는 기호인데, 자바스크립트 엔진은 문의 끝이라고 예측되는 지점에 세미콜론을 자동으로 붙여주는 기능이 암묵적으로 실행된다.

암묵적이라는 말에서 느낄 수 있듯이, 종종 이 동작은 프로그래머의 예측과 일치하지 않는 경우가 생긴다.

세미콜론을 사용하는가, 사용하지 않는가에 대해서는 종종 논란이 있지만, ECMAScript 기술 위원회에서는 세미콜론 사용을 권장하는 분위기이다.


[CS50] Chapter 4. 알고리즘


1) 검색 알고리즘

2) 알고리즘 표기법

3) 선형 검색

4) 버블 정렬

5) 선택 정렬

6) 정렬 알고리즘의 실행시간

7) 재귀

8) 병합 정렬


[CS50] Chapter 3. 배열


1) 컴파일링

2) 디버깅

3) 코드의 디자인

4) 배열(1)

5) 배열(2)

6) 문자열과 배열

7) 문자열의 활용

8) 명령행 인자


[백준 문제풀이] 14890번 경사로


14890번 경사로 (Gold 3)

문제

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

크기가 N×N인 지도가 있다. 지도의 각 칸에는 그 곳의 높이가 적혀져 있다.

오늘은 이 지도에서 지나갈 수 있는 길이 몇 개 있는지 알아보려고 한다. 길이란 한 행 또는 한 열 전부를 나타내며, 한쪽 끝에서 다른쪽 끝까지 지나가는 것이다.

다음과 같은 N=6인 경우 지도를 살펴보자.

이때, 길은 총 2N개가 있으며, 아래와 같다.

길을 지나갈 수 있으려면 길에 속한 모든 칸의 높이가 모두 같아야 한다. 또는, 경사로를 놓아서 지나갈 수 있는 길을 만들 수 있다. 경사로는 높이가 항상 1이며, 길이는 L이다. 또, 개수는 매우 많아 부족할 일이 없다. 경사로는 낮은 칸과 높은 칸을 연결하며, 아래와 같은 조건을 만족해야한다.

경사로는 낮은 칸에 놓으며, L개의 연속된 칸에 경사로의 바닥이 모두 접해야 한다. 낮은 칸과 높은 칸의 높이 차이는 1이어야 한다. 경사로를 놓을 낮은 칸의 높이는 모두 같아야 하고, L개의 칸이 연속되어 있어야 한다. 아래와 같은 경우에는 경사로를 놓을 수 없다.

경사로를 놓은 곳에 또 경사로를 놓는 경우 낮은 칸과 높은 칸의 높이 차이가 1이 아닌 경우 낮은 지점의 칸의 높이가 모두 같지 않거나, L개가 연속되지 않은 경우 경사로를 놓다가 범위를 벗어나는 경우 L = 2인 경우에 경사로를 놓을 수 있는 경우를 그림으로 나타내면 아래와 같다.

경사로를 놓을 수 없는 경우는 아래와 같다.

위의 그림의 가장 왼쪽부터 1번, 2번, 3번, 4번 예제라고 했을 때, 1번은 높이 차이가 1이 아니라서, 2번은 경사로를 바닥과 접하게 놓지 않아서, 3번은 겹쳐서 놓아서, 4번은 기울이게 놓아서 불가능한 경우이다.

가장 위에 주어진 그림 예의 경우에 지나갈 수 있는 길은 파란색으로, 지나갈 수 없는 길은 빨간색으로 표시되어 있으며, 아래와 같다. 경사로의 길이 L = 2이다.

지도가 주어졌을 때, 지나갈 수 있는 길의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

출력

첫째 줄에 지나갈 수 있는 길의 개수를 출력한다.

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const fs = require("fs");
const [[N, L], ...board] = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n")
  .map((line) => line.split(" ").map((el) => el * 1));

let answer = 0;

for (let i = 0; i < N; i++) {
  runRoad(i, "column");
  runRoad(i, "row");
}

console.log(answer);

function runRoad(index, direction) {
  let gapFlag = false;
  let connectCount = 1;

  // 길 한 칸씩 진행
  for (let j = 1; j < N; j++) {
    const gap = getGap(index, j, direction);

    // 단차에 따라 다르게 진행
    if (gap === 0) {
      // 단차가 없는 경우
      // 단차가 없는 평지라면, 계수한다.
      connectCount++;
    } else if (Math.abs(gap) === 1) {
      // 단차가 있는 경우
      // 해결되지 못한 단차가 있었다면 탐색 종료
      if (gapFlag) return;

      if (gap === 1) {
        // 높이가 1 증가한 경우

        // 현재까지 connect 길이가
        // 경사로를 놓을 수 없다면, 탐색을 종료한다.
        if (connectCount < L) return;
      } else {
        // 높이가 1 감소한 경우
        // 단차를 true로 바꿔주고
        // 가능성을 보아 기회를 한 번 더 준다.
        gapFlag = true;
      }

      connectCount = 1;
    } else {
      // 단차가 2 이상이면, 탐색 종료
      return;
    }

    if (gapFlag && connectCount >= L) {
      // 단차가 있었는데 경사로를 둘 길이가 된다면,
      // gapFlag를 false로 바꾸고
      // 연속된 평지 길이를 0으로 초기화한다.
      gapFlag = false;
      connectCount = 0;
    }
  }

  // 마지막으로 단차가 남았는지 확인 후,
  // 모든 역경과 시련을 이겨냈다면
  // 통과시켜준다.
  if (!gapFlag) {
    answer++;
  }
}

function getGap(fixed, variable, direction) {
  if (direction === "column") {
    const gap = board[fixed][variable] - board[fixed][variable - 1];
    if (Math.abs(gap) > 1) {
      return 2;
    } else if (gap === 1) {
      return 1;
    } else if (gap === -1) {
      return -1;
    } else {
      return 0;
    }
  }

  if (direction === "row") {
    const gap = board[variable][fixed] - board[variable - 1][fixed];
    if (Math.abs(gap) > 1) {
      return 2;
    } else if (gap === 1) {
      return 1;
    } else if (gap === -1) {
      return -1;
    } else {
      return 0;
    }
  }
}