diff --git a/problem-1-1/problem-1-1.test.js b/problem-1-1/problem-1-1.test.js index 6ab9348..3fe0021 100644 --- a/problem-1-1/problem-1-1.test.js +++ b/problem-1-1/problem-1-1.test.js @@ -1,4 +1,35 @@ class Bag { + #items = []; + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.#items.length; + } + + add(item) { + this.#items.push(item); + } + + [Symbol.iterator]() { + let index = 0; + const data = [...this.#items]; + + return { + next() { + if (index >= data.length) { + return { done: true }; + } + + const value = data[index]; + index += 1; + + return { done: false, value }; + }, + }; + } } test('백은 비어있는 상태로 생성된다', () => { diff --git a/problem-1-2/problem-1-2.test.js b/problem-1-2/problem-1-2.test.js index f2956b6..2691b65 100644 --- a/problem-1-2/problem-1-2.test.js +++ b/problem-1-2/problem-1-2.test.js @@ -1,4 +1,54 @@ +class Bag { + #items = []; + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.#items.length; + } + + add(item) { + this.#items.push(item); + } + + sum(operator = (acc, item) => acc + item, initialValue = 0) { + return this.#items.reduce(operator, initialValue); + } + + [Symbol.iterator]() { + let index = 0; + const data = [...this.#items]; + + return { + next() { + if (index < data.length) { + const value = data[index]; + index += 1; + + return { + done: false, + value, + }; + } + + return { done: true }; + }, + }; + } +} + const solution = (numbers) => { + const scores = new Bag(); + + numbers.forEach((number) => { + scores.add(number); + }); + + const operator = (acc, item) => acc + item; + + return Math.floor(scores.sum(operator, 0) / scores.size()); }; test('숫자 배열의 평균을 반환한다', () => { diff --git a/problem-2-1/problem-2-1.test.js b/problem-2-1/problem-2-1.test.js index 17412df..08efb7a 100644 --- a/problem-2-1/problem-2-1.test.js +++ b/problem-2-1/problem-2-1.test.js @@ -1,4 +1,70 @@ +class NodeItem { + item; + + next; + + constructor(item) { + this.item = item; + } +} + class Stack { + #first; + + #size = 0; + + isEmpty() { + return this.#first === undefined; + } + + size() { + return this.#size; + } + + push(item) { + const oldFirst = this.#first; + + this.#first = new NodeItem(item); + + this.#first.next = oldFirst; + + this.#size += 1; + } + + pop() { + if (this.isEmpty()) { + throw new Error('스택이 비어있습니다'); + } + + const popped = this.#first; + + this.#first = this.#first.next; + + this.#size -= 1; + + return popped.item; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next() { + if (current !== undefined) { + const value = current.item; + + current = current.next; + + return { + value, + done: false, + }; + } + + return { done: true }; + }, + }; + } } test('스택을 생성하면 비어있다', () => { diff --git a/problem-2-2/problem-2-2.test.js b/problem-2-2/problem-2-2.test.js index dab5212..35cde39 100644 --- a/problem-2-2/problem-2-2.test.js +++ b/problem-2-2/problem-2-2.test.js @@ -1,4 +1,100 @@ -const solution = (string) => { +class Stack { + #n = -1; + + #items; + + #capacity; + + constructor(capacity = 0) { + this.#capacity = capacity; + this.#items = Array(capacity).fill(undefined); + } + + isFull() { + return this.size() === this.#capacity; + } + + isEmpty() { + return this.#n === -1; + } + + size() { + return this.#n + 1; + } + + push(item) { + this.#n += 1; + this.#items[this.#n] = item; + } + + pop() { + if (this.isEmpty()) { + throw new Error('스택이 비어있습니다'); + } + + const item = this.#items[this.#n]; + + this.#items[this.#n] = undefined; + + this.#n -= 1; + + return item; + } + + get length() { + return this.#capacity; + } + + [Symbol.iterator]() { + let index = this.#items.length - 1; + const data = [...this.#items]; + + return { + next() { + if (index >= 0) { + const value = data[index]; + index -= 1; + + return { + done: false, + value, + }; + } + + return { done: true }; + }, + }; + } +} + +const bracketPairs = { + ')': '(', + '}': '{', + ']': '[', +}; + +const solution = (bracekts = '') => { + const stack = new Stack(bracekts.length); + + for (let i = 0; i < bracekts.length; i++) { + const bracket = bracekts.charAt(i); + + if (bracket === '}' || bracket === ')' || bracket === ']') { + if (stack.isEmpty()) { + return false; + } + + const popped = stack.pop(); + + if (bracketPairs[bracket] !== popped) { + return false; + } + } else { + stack.push(bracket); + } + } + + return true; }; test('문자열에 포함된 괄호의 짝이 맞을 때 true를 반환한다', () => { diff --git a/problem-3-1/problem-3-1.test.js b/problem-3-1/problem-3-1.test.js index 6ae251f..3f57e34 100644 --- a/problem-3-1/problem-3-1.test.js +++ b/problem-3-1/problem-3-1.test.js @@ -1,4 +1,83 @@ +class LinkedNode { + item; + + next; + + constructor(item, next) { + this.item = item; + + if (next) { + this.next = next; + } + } +} + class Queue { + #first; + + #last; + + #size = 0; + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.#size; + } + + enqueue(item) { + const node = new LinkedNode(item); + + if (this.isEmpty()) { + this.#first = node; + this.#last = node; + } else { + const oldLast = this.#last; + + this.#last = node; + oldLast.next = this.#last; + } + + this.#size += 1; + } + + dequeue() { + if (this.isEmpty()) { + throw new Error('큐가 비어있습니다'); + } + + const { item } = this.#first; + + this.#first = this.#first.next; + + this.#size -= 1; + + if (this.isEmpty()) { + this.#last = undefined; + } + + return item; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next() { + if (!current) { + return { done: true }; + } + + const value = current.item; + + current = current.next; + + return { done: false, value }; + }, + }; + } } test('큐를 생성하면 비어있다', () => { diff --git a/problem-3-2/problem-3-2.test.js b/problem-3-2/problem-3-2.test.js index 21bd836..46076ad 100644 --- a/problem-3-2/problem-3-2.test.js +++ b/problem-3-2/problem-3-2.test.js @@ -1,4 +1,103 @@ +class LinkedNode { + item; + + next = null; + + constructor(item) { + this.item = item; + } +} + +class Queue { + #first; + + #last; + + #size = 0; + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.#size; + } + + enqueue(item) { + const node = new LinkedNode(item); + + const oldLast = this.#last; + + this.#last = node; + + if (this.isEmpty()) { + this.#first = node; + } else { + oldLast.next = this.#last; + } + + this.#size += 1; + } + + dequeue() { + if (this.isEmpty()) { + throw new Error('큐가 비어있습니다'); + } + + const { item } = this.#first; + + this.#first = this.#first.next; + + this.#size -= 1; + + if (this.isEmpty()) { + this.#last = undefined; + } + + return item; + } + + [Symbol.iterator]() { + let current = this.#first; + + return { + next() { + if (!current) { + return { done: true }; + } + + const value = current.item; + + current = current.next; + + return { done: false, value }; + }, + }; + } +} + +const finalPosition = (queue, M) => { + if (queue.size() === 1) { + return queue.dequeue(); + } + + for (let i = 0; i < M - 1; i += 1) { + 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((number) => { + queue.enqueue(number); + }); + + return finalPosition(queue, M); }; test('N명의 사람이 있을 때 M번째 사람을 없앨 때 마지막에 죽는 사람의 순서를 반환한다', () => {