Skip to content

Commit 8cff27b

Browse files
[재귀와 스택] 과제 번역
- 3,4,5번 해답 번역
1 parent 474ad8d commit 8cff27b

File tree

4 files changed

+50
-50
lines changed

4 files changed

+50
-50
lines changed
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
The first solution we could try here is the recursive one.
1+
가장 먼저 떠올릴 수 있는 방법은 재귀를 사용하는 것입니다.
22

3-
Fibonacci numbers are recursive by definition:
3+
정의에서도 알 수 있듯이 피보나치 수열은 재귀를 사용해 구현할 수 있습니다.
44

55
```js run
66
function fib(n) {
@@ -12,11 +12,11 @@ alert( fib(7) ); // 13
1212
// fib(77); // will be extremely slow!
1313
```
1414

15-
...But for big values of `n` it's very slow. For instance, `fib(77)` may hang up the engine for some time eating all CPU resources.
15+
그런데 이렇게 구현하면 `n`이 클 경우 속도가 느려집니다. `fib(77)`를 호출하면 CPU 리소스를 다 잡아먹어서 잠시 엔진이 멈출 수 있습니다.
1616

17-
That's because the function makes too many subcalls. The same values are re-evaluated again and again.
17+
이는 함수 호출 도중에 수많은 서브 호출이 일어나기 때문입니다. 같은 값들이 여러 번 평가되면서 이런 일이 발생하죠.
1818

19-
For instance, let's see a piece of calculations for `fib(5)`:
19+
`fib(5)`의 계산 과정을 살펴보며 자세히 알아봅시다.
2020

2121
```js no-beautify
2222
...
@@ -25,68 +25,68 @@ fib(4) = fib(3) + fib(2)
2525
...
2626
```
2727

28-
Here we can see that the value of `fib(3)` is needed for both `fib(5)` and `fib(4)`. So `fib(3)` will be called and evaluated two times completely independently.
28+
`fib(3)``fib(5)``fib(4)`를 계산할 때 모두 필요합니다. 그렇기 때문에 `fib(3)`은 완전히 다른 두 곳에서 독립적으로 호출되고 평가되죠.
2929

30-
Here's the full recursion tree:
30+
재귀 트리를 직접 살펴봅시다.
3131

3232
![fibonacci recursion tree](fibonacci-recursion-tree.svg)
3333

34-
We can clearly notice that `fib(3)` is evaluated two times and `fib(2)` is evaluated three times. The total amount of computations grows much faster than `n`, making it enormous even for `n=77`.
34+
그림을 보니 `fib(3)`은 두 번 평가된다는 것이 좀 더 명확히 보이네요. `fib(2)`는 세 번이나 평가되기까지 합니다. `n`이 증가하는 속도보다 전체 연산 횟수가 더 빨리 증가한다는 것을 아실 수 있겠죠? `77`은 그리 큰 숫자가 아니지만 `n=77`일 경우 엄청난 수의 연산이 일어난다는 것을 알 수 있습니다.
3535

36-
We can optimize that by remembering already-evaluated values: if a value of say `fib(3)` is calculated once, then we can just reuse it in future computations.
36+
이런 단점을 극복하기 위해 이미 평가된 값을 어딘가에 저장해놓는 식으로 최적화를 할 수 있습니다. `fib(3)`의 계산이 끝나면 이 결과를 어딘가에 저장해 놓았다가 같은 값이 필요할 때 저장된 값을 불러오는 식으로 말이죠.
3737

38-
Another variant would be to give up recursion and use a totally different loop-based algorithm.
38+
또 다른 방법으론 재귀가 아닌 반복문을 기반으로 하는 알고리즘을 짜는 것입니다.
3939

40-
Instead of going from `n` down to lower values, we can make a loop that starts from `1` and `2`, then gets `fib(3)` as their sum, then `fib(4)` as the sum of two previous values, then `fib(5)` and goes up and up, till it gets to the needed value. On each step we only need to remember two previous values.
40+
`n`부터 시작해 숫자를 하나씩 줄이며 원하는 값을 구하는 대신 `1``2`로 시작하는 반복문으로 `fib(3)`을 구하고, 이를 기반으로 `fib(4)`를 구하고, 또 이를 기반으로 `fib(5)`를 구하는 식으로 알고리즘을 구현할 수 있을 겁니다. 이렇게 알고리즘을 구현하면 이전 두 항의 값만 저장하면 되죠.
4141

42-
Here are the steps of the new algorithm in details.
42+
반복문을 기반으로 하는 알고리즘을 좀 더 자세히 살펴보겠습니다.
4343

44-
The start:
44+
시작은 다음과 같습니다.
4545

4646
```js
47-
// a = fib(1), b = fib(2), these values are by definition 1
47+
// a = fib(1), b = fib(2), 처음 두 항은 1이라는 정의에 의해 이렇게 값을 할당하였습니다.
4848
let a = 1, b = 1;
4949

50-
// get c = fib(3) as their sum
50+
// c = fib(3), 세 번째 항은 첫 번째 항과 두 번째 항의 합입니다.
5151
let c = a + b;
5252

53-
/* we now have fib(1), fib(2), fib(3)
53+
/* fib(1), fib(2), fib(3)을 구했습니다.
5454
a b c
5555
1, 1, 2
5656
*/
5757
```
5858

59-
Now we want to get `fib(4) = fib(2) + fib(3)`.
59+
이제 `fib(2)``fib(3)`을 더해 `fib(4)`를 구해봅시다.
6060

61-
Let's shift the variables: `a,b` will get `fib(2),fib(3)`, and `c` will get their sum:
61+
`a`에 기존 `b`를, `b`에 기존 `c`를 할당하고, `c``a``b`의 합이 되도록 합시다.
6262

6363
```js no-beautify
64-
a = b; // now a = fib(2)
65-
b = c; // now b = fib(3)
64+
a = b; // a = fib(2)
65+
b = c; // b = fib(3)
6666
c = a + b; // c = fib(4)
6767

68-
/* now we have the sequence:
68+
/* 다음과 같은 수열을 얻을 수 있습니다.
6969
a b c
7070
1, 1, 2, 3
7171
*/
7272
```
7373

74-
The next step gives another sequence number:
74+
같은 과정을 반복해 다음 수를 얻어봅시다.
7575

7676
```js no-beautify
7777
a = b; // now a = fib(3)
7878
b = c; // now b = fib(4)
7979
c = a + b; // c = fib(5)
8080

81-
/* now the sequence is (one more number):
81+
/* 다음과 같은 수열을 얻을 수 있습니다.
8282
a b c
8383
1, 1, 2, 3, 5
8484
*/
8585
```
8686

87-
...And so on until we get the needed value. That's much faster than recursion and involves no duplicate computations.
87+
목표로 하는 값을 얻을 때까지 위와 같은 과정을 반복하면 되겠죠? 이렇게 하면 재귀를 사용하는 방법보다 연산 속도도 빠르고 중복되는 계산도 없다는 장점이 있습니다.
8888

89-
The full code:
89+
반복문을 사용한 전체 코드는 다음과 같습니다.
9090

9191
```js run
9292
function fib(n) {
@@ -105,6 +105,6 @@ alert( fib(7) ); // 13
105105
alert( fib(77) ); // 5527939700884757
106106
```
107107

108-
The loop starts with `i=3`, because the first and the second sequence values are hard-coded into variables `a=1`, `b=1`.
108+
반복문 내 `i``3`부터 시작합니다. 피보나치 수열의 첫 번째 항과 두 번째 항은 `a=1`, `b=1`로 하드코딩 했기 때문입니다.
109109

110-
The approach is called [dynamic programming bottom-up](https://en.wikipedia.org/wiki/Dynamic_programming).
110+
이런 접근 방법은 [동적 계획법(dynamic programming)](https://en.wikipedia.org/wiki/Dynamic_programming)이라 부릅니다.

1-js/06-advanced-functions/01-recursion/03-fibonacci-numbers/task.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ importance: 5
33
---
44
# 피보나치 수 계산하기
55

6-
[피보나치 수](https://ko.wikipedia.org/wiki/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98_%EC%88%98) 는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인 수열로, <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>이라는 공식으로 표현됩니다.
6+
[피보나치 수](https://ko.wikipedia.org/wiki/%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98_%EC%88%98)는 첫째 및 둘째 항이 1이며 그 뒤의 모든 항은 바로 앞 두 항의 합인 수열로, <code>F<sub>n</sub> = F<sub>n-1</sub> + F<sub>n-2</sub></code>이라는 공식으로 표현됩니다.
77

88
수열의 처음 두 숫자는 `1`이고, 그 다음 항들은 `2(1+1)`,`3(1+2)`,`5(2+3)`가 됩니다(`1, 1, 2, 3, 5 , 8, 13, 21 ...`).
99

10-
피보나치 수는 [황금 비율](https://en.wikipedia.org/wiki/Golden_ratio) 등의 우리 주변을 둘러싼 수많은 자연 현상과 관련이 있습니다.
10+
피보나치 수는 [황금 비율](https://en.wikipedia.org/wiki/Golden_ratio) 우리 주변을 둘러싼 수많은 자연 현상과 관련이 있습니다.
1111

1212
`n 번째` 피보나치 수를 반환하는 함수 `fib(n)`을 작성해보세요.
1313

1-js/06-advanced-functions/01-recursion/04-output-single-linked-list/solution.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Loop-based solution
1+
# 반복문을 기반으로 하는 방법
22

3-
The loop-based variant of the solution:
3+
반복문을 사용한 답안은 다음과 같습니다.
44

55
```js run
66
let list = {
@@ -30,7 +30,7 @@ function printList(list) {
3030
printList(list);
3131
```
3232

33-
Please note that we use a temporary variable `tmp` to walk over the list. Technically, we could use a function parameter `list` instead:
33+
여기서 주목해야 할 점은 리스트를 임시 변수 `tmp`에 저장하고 사용했다는 것입니다. 아래처럼 매개변수 `list`를 그대로 사용해도 되는데 말이죠.
3434

3535
```js
3636
function printList(list) {
@@ -43,15 +43,15 @@ function printList(list) {
4343
}
4444
```
4545

46-
...But that would be unwise. In the future we may need to extend a function, do something else with the list. If we change `list`, then we lose such ability.
46+
그런데 매개변수 `list`를 바로 사용하는 건 그다지 현명한 선택은 아닙니다. 나중에 함수를 확장할 때 `list`를 가지고 뭔가 해야 하는 경우가 생길 수 있기 때문이죠. 어떤 일 때문인지는 몰라도 `while`문 앞에서 `list`가 변경되면 우리가 짠 코드는 제대로 동작하지 않을 겁니다.
4747

48-
Talking about good variable names, `list` here is the list itself. The first element of it. And it should remain like that. That's clear and reliable.
48+
좋은 변수명이 무엇인가를 생각해 봤을 때도 리스트를 임시 변수 `tmp`에 저장하는 게 좋습니다. `list`에는 리스트 그 자체가 저장되어있는 게 좋죠.
4949

50-
From the other side, the role of `tmp` is exclusively a list traversal, like `i` in the `for` loop.
50+
`tmp`는 리스트를 순회하기 위한 용도로 쓰였기 때문에 `tmp`라고 명명하는 게 좋습니다. `for`문의 `i`처럼 말이죠.
5151

52-
# Recursive solution
52+
# 재귀를 기반으로 하는 방법
5353

54-
The recursive variant of `printList(list)` follows a simple logic: to output a list we should output the current element `list`, then do the same for `list.next`:
54+
재귀를 사용해 만든 `printList(list)`는 아주 간단한 로직을 기반으로 합니다. "리스트를 출력할 때는 현재 요소 `list`를 출력하고, 같은 방법을 사용해 `list.next`를 출력한다."라는 로직이죠.
5555

5656
```js run
5757
let list = {
@@ -70,19 +70,19 @@ let list = {
7070

7171
function printList(list) {
7272

73-
alert(list.value); // output the current item
73+
alert(list.value); // 현재 요소를 출력합니다.
7474

7575
if (list.next) {
76-
printList(list.next); // do the same for the rest of the list
76+
printList(list.next); // 같은 방법을 사용해 나머지 요소를 출력합니다.
7777
}
7878

7979
}
8080

8181
printList(list);
8282
```
8383

84-
Now what's better?
84+
이제 두 방법을 비교해봅시다.
8585

86-
Technically, the loop is more effective. These two variants do the same, but the loop does not spend resources for nested function calls.
86+
반복문을 사용하면 리소스를 좀 더 효율적으로 사용합니다. 두 방법의 반환 값은 같지만, 반복문을 사용한 방법에선 중첩 함수를 호출하는데 추가적인 리소스를 쓰지 않기 때문입니다.
8787

88-
From the other side, the recursive variant is shorter and sometimes easier to understand.
88+
반면 재귀를 사용한 방법은 코드 길이가 짧고 이해하기 쉽다는 장점이 있습니다.

1-js/06-advanced-functions/01-recursion/05-output-single-linked-list-reverse/solution.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Using a recursion
1+
# 재귀를 기반으로 하는 방법
22

3-
The recursive logic is a little bit tricky here.
3+
재귀를 사용한 방법은 조금 까다롭습니다.
44

5-
We need to first output the rest of the list and *then* output the current one:
5+
리스트의 나머지 요소들을 출력한 *다음에* 현재 요소를 출력해야 하죠.
66

77
```js run
88
let list = {
@@ -31,13 +31,13 @@ function printReverseList(list) {
3131
printReverseList(list);
3232
```
3333

34-
# Using a loop
34+
# 반복문을 기반으로 하는 방법
3535

36-
The loop variant is also a little bit more complicated then the direct output.
36+
리스트를 원래 순서대로 출력하는 방법보다 역시 까다롭습니다.
3737

38-
There is no way to get the last value in our `list`. We also can't "go back".
38+
`list`의 마지막 값을 바로 구할 수 있는 방법이 없기 때문입니다. 마지막 값을 시작으로 '역행'할 수 없는 상황이죠.
3939

40-
So what we can do is to first go through the items in the direct order and remember them in an array, and then output what we remembered in the reverse order:
40+
따라서 우리는 원래 순서대로 요소들을 하나씩 거슬러 올라가면서 각 요소를 배열에 저장해 놓고, 마지막 요소에 도달했을 때 배열에 저장된 요소들을 거꾸로 출력하는 방법을 사용할 수 있을 겁니다.
4141

4242
```js run
4343
let list = {
@@ -71,4 +71,4 @@ function printReverseList(list) {
7171
printReverseList(list);
7272
```
7373

74-
Please note that the recursive solution actually does exactly the same: it follows the list, remembers the items in the chain of nested calls (in the execution context stack), and then outputs them.
74+
여기서 주목할 점은 재귀를 사용한 방법과 반복문을 사용한 방법이 완전히 동일한 접근 방식을 취했다는 것입니다. 리스트를 앞에서부터 따라가면서 각 요소를 실행 컨텍스트 스택에 저장해 놓았다가 스택 맨 위에서부터 요소를 차례대로 출력하였습니다.

0 commit comments

Comments
 (0)