diff --git a/problem-1-1/README.md b/problem-1-1/README.md index 2b698ce..973c07f 100644 --- a/problem-1-1/README.md +++ b/problem-1-1/README.md @@ -4,7 +4,9 @@ | 함수 시그니처 | 설명 | | ----------- | ----------- | -| sample(string): number | 문자열을 입력으로 받아 숫자로 변환해서 반환합니다 | +| isEmpty(): boolean | 값이 비어있는지 여부를 boolean으로 리턴합니다. | +| add(item: string): void | Bag안에 item을 추가합니다 | +| size(): number | 현재 Bag의 길이를 반환합니다. | 2. 다음 값들을 백에 추가했을 때 어떻게 되는지 그림으로 그려보세요. diff --git a/problem-1-1/problem-1-1.test.js b/problem-1-1/problem-1-1.test.js index 6ab9348..91408e4 100644 --- a/problem-1-1/problem-1-1.test.js +++ b/problem-1-1/problem-1-1.test.js @@ -1,4 +1,50 @@ +class Node { + item; + next; +} + class Bag { + #first; + #n; + + constructor() { + this.#n = 0; + } + + isEmpty() { + return this.#n === 0; + } + + add(item) { + const oldFirst = this.#first; + + this.#first = new Node(); + this.#first.item = item; + this.#first.next = oldFirst; + + this.#n += 1; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next() { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { done: false, value }; + }, + }; + } } test('백은 비어있는 상태로 생성된다', () => { @@ -7,6 +53,14 @@ test('백은 비어있는 상태로 생성된다', () => { expect(bag.isEmpty()).toBe(true); }); +test('백은 비어있지 않으면 false를 반환한다.', () => { + const bag = new Bag(); + + bag.add('A'); + + expect(bag.isEmpty()).toBe(false); +}); + test('백에 값을 추가하면, 개수가 증가한다', () => { const bag = new Bag(); diff --git a/problem-1-2/problem-1-2.test.js b/problem-1-2/problem-1-2.test.js index f2956b6..7b9d453 100644 --- a/problem-1-2/problem-1-2.test.js +++ b/problem-1-2/problem-1-2.test.js @@ -1,4 +1,62 @@ +class Node { + item; + next; +} + +class Bag { + #first; + #n; + + constructor() { + this.#n = 0; + } + + isEmpty() { + return this.#n === 0; + } + + add(item) { + const oldFirst = this.#first; + + this.#first = new Node(); + this.#first.item = item; + this.#first.next = oldFirst; + + this.#n += 1; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next() { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { done: false, value }; + }, + }; + } +} + const solution = (numbers) => { + const bag = new Bag(); + + numbers.forEach((number) => bag.add(number)); + + let sum = 0; + for (const number of bag) { + sum += number; + } + return Math.floor(sum / bag.size()); }; test('숫자 배열의 평균을 반환한다', () => { diff --git a/problem-2-1/README.md b/problem-2-1/README.md index 2f9a3e6..f40b9fc 100644 --- a/problem-2-1/README.md +++ b/problem-2-1/README.md @@ -4,7 +4,10 @@ | 함수 시그니처 | 설명 | | ----------- | ----------- | -| sample(string): number | 문자열을 입력으로 받아 숫자로 변환해서 반환합니다 | +| Stack() | 스택을 생성합니다 | +| push(item): void | 스택을 값을 추가합니다 | +| pop(): item | 스택을 값을 출력합니다 | +| itemEmpty(): boolean | 스택이 비어있으면 true, 아니면 false를 반환합니다 | 2. 다음 값들을 스택에 추가했을 때 어떻게 되는지 그림으로 그려보세요. `(-)`은 값을 꺼내는 것을 의미합니다. diff --git a/problem-2-1/problem-2-1.test.js b/problem-2-1/problem-2-1.test.js index 17412df..8ed9219 100644 --- a/problem-2-1/problem-2-1.test.js +++ b/problem-2-1/problem-2-1.test.js @@ -1,4 +1,62 @@ +class Node { + item; + next; +} + class Stack { + #first; + #n; + + constructor() { + this.#n = 0; + } + + push(item) { + const oldFirst = this.#first; + + this.#first = new Node(); + this.#first.item = item; + this.#first.next = oldFirst; + + this.#n++; + } + + pop() { + if (this.#first === undefined) { + throw new Error('스택이 비어있습니다'); + } + + const item = this.#first.item; + this.#n--; + this.#first = this.#first.next; + + return item; + } + + isEmpty() { + return this.#first === undefined; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next: () => { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { done: false, value }; + }, + }; + } } test('스택을 생성하면 비어있다', () => { @@ -7,6 +65,14 @@ test('스택을 생성하면 비어있다', () => { expect(stack.isEmpty()).toEqual(true); }); +test('isEmpty 스택에 아이템이 있으면 false를 반환한다.', () => { + const stack = new Stack(); + + stack.push('D'); + + expect(stack.isEmpty()).toEqual(false); +}); + test('스택에 값을 추가하면 개수가 증가한다', () => { const stack = new Stack(); diff --git a/problem-2-2/problem-2-2.test.js b/problem-2-2/problem-2-2.test.js index dab5212..ff9a9f3 100644 --- a/problem-2-2/problem-2-2.test.js +++ b/problem-2-2/problem-2-2.test.js @@ -1,12 +1,128 @@ +class Node { + item; + next; +} + +class Stack { + #first; + #n; + + constructor() { + this.#n = 0; + } + + push(item) { + const oldFirst = this.#first; + + this.#first = new Node(); + this.#first.item = item; + this.#first.next = oldFirst; + + this.#n++; + } + + pop() { + if (this.#first === undefined) { + throw new Error('스택이 비어있습니다'); + } + + const item = this.#first.item; + this.#n--; + this.#first = this.#first.next; + + return item; + } + + isEmpty() { + return this.#first === undefined; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next: () => { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { done: false, value }; + }, + }; + } +} + +const pairs = { + '(': ')', + '{': '}', + '[': ']', +}; +const isPair = (item, other) => pairs[item] === other; + +const isCloseBracket = (char) => [')', '}', ']'].some((it) => it === char); + const solution = (string) => { + const stack = new Stack(); + + while (true) { + if (string === '') { + return stack.isEmpty(); + } + + const char = string[0]; + + if (isCloseBracket(char)) { + if (stack.isEmpty()) { + return false; + } + const item = stack.pop(); + if (!isPair(item, char)) { + return false; + } + } else { + stack.push(char); + } + + string = string.slice(1); + } }; +test('문자가 닫힌 괄호면 true를 반환한다', () => { + expect(isCloseBracket(')')).toBe(true); + expect(isCloseBracket('}')).toBe(true); + expect(isCloseBracket(']')).toBe(true); +}); + +test('문자가 닫힌 괄호가 아니면 false를 반환한다', () => { + expect(isCloseBracket('(')).toBe(false); +}); + +test('빈 문자열은 true를 반환한다', () => { + expect(solution('')).toBe(true); +}); + +test('괄호가 열린채로 끝나면 false를 반환한다.', () => { + expect(solution('()(')).toBe(false); +}); + +test('열지 않았는데 닫으면 false를 반환한다.', () => { + expect(solution(')')).toBe(false); +}); + test('문자열에 포함된 괄호의 짝이 맞을 때 true를 반환한다', () => { expect(solution('{([])}')).toBe(true); }); test('문자열에 포함된 괄호의 짝이 맞지 않을 때 false를 반환한다', () => { expect(solution(')[](')).toBe(false); + expect(solution('[)')).toBe(false); }); test('문자에 여는 괄호만 있고 닫는 괄호는 없을 때 false를 반환한다', () => { diff --git a/problem-3-1/README.md b/problem-3-1/README.md index 4d27b95..7254bd9 100644 --- a/problem-3-1/README.md +++ b/problem-3-1/README.md @@ -4,7 +4,10 @@ | 함수 시그니처 | 설명 | | ----------- | ----------- | -| sample(string): number | 문자열을 입력으로 받아 숫자로 변환해서 반환합니다 | +| Queue() | 큐를 생성합니다. | +| enqueue(item: any): void | 큐에 아이템을 삽입합니다. | +| dequeue(): item | 큐에서 값을 출력합니다. | +| isEmpty(): boolean | 큐에 값이 비어있으면 true, 아니면 false를 반환합니다. | 2. 다음 값들을 큐에 추가했을 때 어떻게 되는지 그림으로 그려보세요. `(-)`은 값을 꺼내는 것을 의미합니다. diff --git a/problem-3-1/problem-3-1.test.js b/problem-3-1/problem-3-1.test.js index 6ae251f..88acf91 100644 --- a/problem-3-1/problem-3-1.test.js +++ b/problem-3-1/problem-3-1.test.js @@ -1,4 +1,72 @@ +class Node { + #item; + #next; +} + class Queue { + #first; + #last; + #n; + + constructor() { + this.#n = 0; + } + + enqueue(item) { + const oldLast = this.#last; + + this.#last = new Node(); + this.#last.item = item; + + if (this.isEmpty()) { + this.#first = this.#last; + } else { + oldLast.next = this.#last; + } + this.#n++; + } + + dequeue() { + if (this.isEmpty()) { + throw new Error('큐가 비어있습니다'); + } + + const item = this.#first.item; + this.#first = this.#first.next; + + if (this.isEmpty()) { + this.#last = undefined; + } + + this.#n--; + + return item; + } + + isEmpty() { + return this.#n === 0; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next: () => { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { value, done: false }; + }, + }; + } } test('큐를 생성하면 비어있다', () => { @@ -7,6 +75,14 @@ test('큐를 생성하면 비어있다', () => { expect(queue.isEmpty()).toEqual(true); }); +test('큐가 비어있지 않으면 false를 반환한다.', () => { + const queue = new Queue(); + + queue.enqueue('D'); + + expect(queue.isEmpty()).toEqual(false); +}); + test('큐에 값을 추가하면 개수가 증가한다', () => { const queue = new Queue(); diff --git a/problem-3-2/problem-3-2.test.js b/problem-3-2/problem-3-2.test.js index 21bd836..f341062 100644 --- a/problem-3-2/problem-3-2.test.js +++ b/problem-3-2/problem-3-2.test.js @@ -1,4 +1,94 @@ +class Node { + #item; + #next; +} + +class Queue { + #first; + #last; + #n; + + constructor() { + this.#n = 0; + } + + enqueue(item) { + const oldLast = this.#last; + + this.#last = new Node(); + this.#last.item = item; + + if (this.isEmpty()) { + this.#first = this.#last; + } else { + oldLast.next = this.#last; + } + this.#n++; + } + + dequeue() { + if (this.isEmpty()) { + throw new Error('큐가 비어있습니다'); + } + + const item = this.#first.item; + this.#first = this.#first.next; + + if (this.isEmpty()) { + this.#last = undefined; + } + + this.#n--; + + return item; + } + + isEmpty() { + return this.#n === 0; + } + + size() { + return this.#n; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next: () => { + if (current === undefined) { + return { done: true }; + } + + const value = current.item; + current = current.next; + + return { value, done: false }; + }, + }; + } +} + +const finalPosition = (queue, M) => { + if (queue.size() === 1) { + return queue.dequeue(); + } + + for (let i = 0; i < M - 1; i++) { + queue.enqueue(queue.dequeue()); + } + + queue.dequeue(); + + return finalPosition(queue, M); +}; + const solution = (N, M) => { + const queue = new Queue(); + + Array.from({ length: N }, (_, i) => i + 1).forEach((i) => queue.enqueue(i)); + + return finalPosition(queue, M); }; test('N명의 사람이 있을 때 M번째 사람을 없앨 때 마지막에 죽는 사람의 순서를 반환한다', () => {