diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/book-edit.html" "b/\354\240\225\354\227\260\354\261\204/ex1/book-edit.html"
index e69de29..2367f71 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex1/book-edit.html"
+++ "b/\354\240\225\354\227\260\354\261\204/ex1/book-edit.html"
@@ -0,0 +1,68 @@
+
+
+
+
+
+ Bookmark Edit
+
+
+
+
+
+
+
+
+ BookMark
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+

+
+
+
+
+
There is no marks.
+
+
+
+
+
+
+
+
+
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/book.png" "b/\354\240\225\354\227\260\354\261\204/ex1/book.png"
new file mode 100644
index 0000000..dfd09d0
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/book.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/bookmark_logo.png" "b/\354\240\225\354\227\260\354\261\204/ex1/bookmark_logo.png"
new file mode 100644
index 0000000..43406c3
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/bookmark_logo.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/index.html" "b/\354\240\225\354\227\260\354\261\204/ex1/index.html"
index e69de29..6c7d351 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex1/index.html"
+++ "b/\354\240\225\354\227\260\354\261\204/ex1/index.html"
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+ Home Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Study
+
+
+
+

+
+
Tailwind CSS
+
Tailwind CSS is a utility-first CSS framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/index2.html" "b/\354\240\225\354\227\260\354\261\204/ex1/index2.html"
new file mode 100644
index 0000000..1f22b40
--- /dev/null
+++ "b/\354\240\225\354\227\260\354\261\204/ex1/index2.html"
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+ Home Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Study
+
+
+
+
+

+
+
Tailwind CSS
+
Tailwind CSS is a utility-first CSS framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/kakao.png" "b/\354\240\225\354\227\260\354\261\204/ex1/kakao.png"
new file mode 100644
index 0000000..d802ab5
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/kakao.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/naver.png" "b/\354\240\225\354\227\260\354\261\204/ex1/naver.png"
new file mode 100644
index 0000000..00686ea
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/naver.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/profile.png" "b/\354\240\225\354\227\260\354\261\204/ex1/profile.png"
new file mode 100644
index 0000000..8bc7c79
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/profile.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/register.html" "b/\354\240\225\354\227\260\354\261\204/ex1/register.html"
index e69de29..eeb34d5 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex1/register.html"
+++ "b/\354\240\225\354\227\260\354\261\204/ex1/register.html"
@@ -0,0 +1,57 @@
+
+
+
+
+
+ Register
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/save.png" "b/\354\240\225\354\227\260\354\261\204/ex1/save.png"
new file mode 100644
index 0000000..04df82c
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/save.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/save2.png" "b/\354\240\225\354\227\260\354\261\204/ex1/save2.png"
new file mode 100644
index 0000000..8dc320c
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/save2.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/setting.png" "b/\354\240\225\354\227\260\354\261\204/ex1/setting.png"
new file mode 100644
index 0000000..845c81d
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/setting.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/tailwind.png" "b/\354\240\225\354\227\260\354\261\204/ex1/tailwind.png"
new file mode 100644
index 0000000..7d158f2
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/tailwind.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/undo.png" "b/\354\240\225\354\227\260\354\261\204/ex1/undo.png"
new file mode 100644
index 0000000..923cc05
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/undo.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex1/youtube.png" "b/\354\240\225\354\227\260\354\261\204/ex1/youtube.png"
new file mode 100644
index 0000000..7d2736f
Binary files /dev/null and "b/\354\240\225\354\227\260\354\261\204/ex1/youtube.png" differ
diff --git "a/\354\240\225\354\227\260\354\261\204/ex10.test.ts" "b/\354\240\225\354\227\260\354\261\204/ex10.test.ts"
index 6218a79..19d585b 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex10.test.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex10.test.ts"
@@ -1,4 +1,98 @@
import { ArrayList } from './ex10';
+import assert from 'assert';
+
console.log('🚀 ArrayList:', ArrayList);
-// 여기에 테스트코드를 작성하세요.
+console.log(ArrayList.listToArray({ value: 1, rest: { value: 2, rest: null } }));
+console.log(ArrayList.arrayToList([1, 2]));
+
+const alist = new ArrayList([1, 2]);
+console.log(alist.toString());
+alist.add(3);
+console.log(alist.toString());
+alist.add(5, 1);
+console.log(alist.toString());
+alist.remove(2);
+console.log(alist.toString());
+alist.add(22, 1);
+console.log(alist.toString());
+alist.add(33, 1);
+console.log(alist.toString());
+alist.set(1, 300);
+console.log(alist.toString());
+console.log(alist.get(2));
+console.log(alist.size());
+console.log(alist.indexOf(300));
+console.log(alist.contains(300));
+console.log(alist.contains(301));
+console.log(alist.isEmpty());
+console.log(alist.peek());
+console.log(alist.toArray());
+console.log(alist.iterator().next());
+alist.clear();
+console.log(alist.toString());
+
+
+// const alist = new ArrayList([1, 2]);
+// console.log('list:', alist.toString());
+
+// alist.add(8); // [4, 7, 8]
+// alist.add(15, 1); // [4, 15, 7, 8]
+// assert.deepStrictEqual(alist.toArray(), [4, 15, 7, 8], 'add() 실패');
+
+// alist.add(25, 2); // [4, 15, 25, 7, 8]
+// alist.add(40, 0); // [40, 4, 15, 25, 7, 8]
+// assert.deepStrictEqual(alist.toArray(), [40, 4, 15, 25, 7, 8], 'add() with index 실패');
+
+// // const removedValue = alist.removeByIndex(1); // [40, 15, 25, 7, 8]
+// // assert.strictEqual(removedValue, 4, 'removeByIndex 실패');
+// // assert.deepStrictEqual(alist.toArray(), [40, 15, 25, 7, 8], 'removeByIndex 실패');
+
+// // const removedResult = alist.removeValue(25); // [40, 15, 7, 8]
+// // assert.strictEqual(removedResult, true, 'removeValue 실패');
+// // assert.deepStrictEqual(alist.toArray(), [40, 15, 7, 8], 'removeValue 실패');
+
+// const failedRemove = alist.remove(100); // 값이 없으므로 false
+// assert.strictEqual(failedRemove, false, 'removeValue 실패 2');
+
+// assert.strictEqual(alist.get(0), 40, 'get() 실패');
+// assert.strictEqual(alist.get(2), 7, 'get() 실패');
+// assert.strictEqual(alist.get(10), undefined, 'get() 실패 2');
+
+// alist.set(1, 350); // [40, 350, 7, 8]
+// assert.deepStrictEqual(alist.toArray(), [40, 350, 7, 8], 'set() 실패');
+
+// assert.strictEqual(alist.contains(350), true, 'contains() 실패');
+// assert.strictEqual(alist.contains(301), false, 'contains() 실패');
+
+// assert.strictEqual(alist.indexOf(350), 1, 'indexOf() 실패');
+// assert.strictEqual(alist.indexOf(500), -1, 'indexOf() 실패');
+
+// assert.strictEqual(alist.size(), 4, 'size() 실패');
+
+// assert.strictEqual(alist.isEmpty, false, 'isEmpty() 실패');
+// alist.clear();
+// assert.strictEqual(alist.isEmpty, true, 'isEmpty() 실패2');
+
+// alist.add(45);
+// alist.add(55);
+// alist.add(65);
+// const iterator = alist.iterator();
+
+// const firstIter = iterator.next();
+// assert.deepStrictEqual(firstIter.value, 65, 'iterator() 1 실패');
+// assert.strictEqual(firstIter.done, false, 'iterator() 1 done 실패');
+
+// const secondIter = iterator.next();
+// assert.deepStrictEqual(secondIter.value, 55, 'iterator() 2 실패');
+// assert.strictEqual(secondIter.done, false, 'iterator() 2 done 실패');
+
+// const thirdIter = iterator.next();
+// assert.deepStrictEqual(thirdIter.value, 45, 'iterator() 3 실패');
+// assert.strictEqual(thirdIter.done, false, 'iterator() 3 done 실패');
+
+// const fourthIter = iterator.next();
+// assert.strictEqual(fourthIter.value, undefined, 'iterator() 4 실패');
+// assert.strictEqual(fourthIter.done, true, 'iterator() 실패');
+
+// assert.deepStrictEqual(alist.toArray(), [45, 55, 65], 'toArray() 실패');
\ No newline at end of file
diff --git "a/\354\240\225\354\227\260\354\261\204/ex10.ts" "b/\354\240\225\354\227\260\354\261\204/ex10.ts"
index 1ffaef5..a35e855 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex10.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex10.ts"
@@ -1,71 +1,318 @@
-class Collection {
- private readonly arr = Array();
+// class Collection {
+// private readonly arr = Array();
- constructor(...args: T[]) {
- this.arr.push(...args);
+// constructor(...args: T[]) {
+// this.arr.push(...args);
+// }
+
+// get _arr() {
+// return this.arr;
+// }
+
+// push(...args: T[]) {
+// this.arr.push(...args);
+// return this.arr;
+// }
+
+// get peek(): T | undefined {
+// return this.isQueue() ? this.arr[0] : this.arr.at(-1);
+// }
+
+// get poll(): T | undefined {
+// return this.isQueue() ? this.arr.shift() : this.arr.pop();
+// }
+
+// remove() {
+// return this.poll;
+// }
+
+// get length() {
+// return this.arr.length;
+// }
+
+// get isEmpty() {
+// return !this.arr.length;
+// }
+
+// clear() {
+// this.arr.length = 0;
+// }
+
+// iterator() {
+// return this[Symbol.iterator]();
+// }
+
+// // [1, 2, 3]
+// *[Symbol.iterator]() {
+// for (let i = this.length - 1; i >= 0; i -= 1) {
+// yield this.toArray()[i];
+// }
+// }
+
+// toArray() {
+// return this.isQueue() ? this.arr.toReversed() : this.arr;
+// }
+
+// print() {
+// console.log(`<${this.constructor.name}: [${this.toArray()}]>`);
+// }
+
+// private isQueue() {
+// return this instanceof Queue;
+// }
+// }
+
+// class Stack extends Collection {}
+// class Queue extends Collection {}
+
+// // ArrayList 클래스를 작성하세요.
+// class ArrayList extends Collection {
+// constructor(...args: T[]) {
+// super(...args);
+// }
+
+// add(value: T, index?: number): void {
+// if (index === undefined) {
+// this._arr.push(value);
+// } else {
+// this._arr.splice(index, 0, value);
+// }
+// }
+
+// get(index: number): T | undefined {
+// return this._arr[index];
+// }
+
+// removeValue(value: T): boolean {
+// const index = this.indexOf(value);
+// if (index !== -1) {
+// this._arr.splice(index, 1);
+// return true;
+// }
+// return false;
+// }
+
+// removeByIndex(index: number): T | undefined {
+// if (index >= 0 && index < this.length) {
+// return this._arr.splice(index, 1)[0];
+// }
+// return undefined;
+// }
+
+// set(index: number, value: T): void {
+// if (index >= 0 && index < this.length) {
+// this._arr[index] = value;
+// }
+// }
+
+// contains(value: T): boolean {
+// return this._arr.includes(value);
+// }
+
+// indexOf(value: T): number {
+// return this._arr.indexOf(value);
+// }
+
+// size(): number {
+// return this.length;
+// }
+
+// toArray(): T[] {
+// return [...this._arr];
+// }
+
+// toString(): string {
+// return `ArrayList(${this.size()}) { ${this._arr.map((v) => `value: ${v}`).join(', ')} }`;
+// }
+// }
+
+// export { Stack, Queue, ArrayList };
+
+/********************************************************************************************************************** */
+interface Collection {
+ add(value: T, index?: number): void;
+ remove(index: number): void;
+ clear(): void;
+ contains(value: T): boolean;
+ size(): number;
+ isEmpty(): boolean;
+ toArray(): T[];
+ iterator(): Iterator;
+}
+
+interface ListNode {
+ value: T;
+ rest: ListNode | null;
+}
+
+class ArrayList implements Collection {
+ private head: ListNode | null = null;
+ private length: number = 0;
+
+ constructor(array: T[] = []) {
+ this.clear();
+ if (Array.isArray(array)) {
+ array.forEach((item) => this.add(item));
+ }
}
- get _arr() {
- return this.arr;
+ clear(): void {
+ this.head = null;
+ this.length = 0;
+ }
+
+ add(value: T, index: number = this.size()): void {
+ if (index < 0 || index > this.size()) throw new Error('Index out of bounds');
+
+ const newNode: ListNode = { value, rest: null };
+
+ if (index === 0) {
+ newNode.rest = this.head;
+ this.head = newNode;
+ } else {
+ const prevNode = this._getNode(index - 1);
+ newNode.rest = prevNode.rest;
+ prevNode.rest = newNode;
+ }
+
+ this.length++;
}
- push(...args: T[]) {
- this.arr.push(...args);
- return this.arr;
+ remove(index: number): void {
+ if (index < 0 || index >= this.size()) throw new Error('Index out of bounds');
+
+ if (index === 0) {
+ this.head = this.head!.rest;
+ } else {
+ const prevNode = this._getNode(index - 1);
+ prevNode.rest = prevNode.rest!.rest;
+ }
+
+ this.length--;
}
- get peek(): T | undefined {
- return this.isQueue() ? this.arr[0] : this.arr.at(-1);
+ set(index: number, value: T): void {
+ const node = this._getNode(index);
+ node.value = value;
}
- get poll(): T | undefined {
- return this.isQueue() ? this.arr.shift() : this.arr.pop();
+ get(index: number): T {
+ return this._getNode(index).value;
}
- remove() {
- return this.poll;
+ contains(value: T): boolean {
+ return this.indexOf(value) !== -1;
}
- get length() {
- return this.arr.length;
+ indexOf(value: T): number {
+ let currentNode = this.head;
+ let index = 0;
+ while (currentNode) {
+ if (currentNode.value === value) return index;
+ currentNode = currentNode.rest;
+ index++;
+ }
+ return -1;
}
- get isEmpty() {
- return !this.arr.length;
+ peek(): T | undefined {
+ if (!this.head) return undefined;
+ return this.head.value;
}
- clear() {
- this.arr.length = 0;
+ size(): number {
+ return this.length;
}
- iterator() {
- return this[Symbol.iterator]();
+ isEmpty(): boolean {
+ return this.size() === 0;
}
- // [1, 2, 3]
- *[Symbol.iterator]() {
- for (let i = this.length - 1; i >= 0; i -= 1) {
- yield this.toArray()[i];
+ toArray(): T[] {
+ const result: T[] = [];
+ let currentNode = this.head;
+ while (currentNode) {
+ result.push(currentNode.value);
+ currentNode = currentNode.rest;
}
+ return result;
}
- toArray() {
- return this.isQueue() ? this.arr.toReversed() : this.arr;
+ toString(): string {
+ return `ArrayList(${this.size()}) ${JSON.stringify(this.head)}`;
}
- print() {
- console.log(`<${this.constructor.name}: [${this.toArray()}]>`);
+ iterator(): Iterator {
+ let currentNode = this.head;
+ return {
+ next: (): IteratorResult => {
+ if (!currentNode) {
+ return { value: undefined, done: true };
+ }
+ const value = currentNode.value;
+ currentNode = currentNode.rest;
+ return { value, done: false };
+ }
+ };
}
- private isQueue() {
- return this instanceof Queue;
+ private _getNode(index: number): ListNode {
+ if (index < 0 || index >= this.size()) throw new Error('Index out of bounds');
+ let currentNode = this.head;
+ for (let i = 0; i < index; i++) {
+ currentNode = currentNode!.rest;
+ }
+ return currentNode!;
+ }
+
+ static listToArray(list: ListNode | null): T[] {
+ const array: T[] = [];
+ let current = list;
+ while (current) {
+ array.push(current.value);
+ current = current.rest;
+ }
+ return array;
+ }
+
+ static arrayToList(array: T[]): ListNode | null {
+ let head: ListNode | null = null;
+ for (let i = array.length - 1; i >= 0; i--) {
+ head = { value: array[i], rest: head };
+ }
+ return head;
}
}
-class Stack extends Collection {}
-class Queue extends Collection {}
+export {ArrayList };
+
+// console.log(ArrayList.listToArray({ value: 1, rest: { value: 2, rest: null } })); //⇒ [1,2]
+// console.log(ArrayList.arrayToList([1, 2])); //⇒ { value: 1, rest: { value: 2, rest: null } }
+
+// const alist = new ArrayList([1, 2]);
+// console.log(alist.toString());
+// alist.add(3);
+// console.log(alist.toString());
+// alist.add(5, 1);
+// console.log(alist.toString());
+// alist.remove(2);
+// console.log(alist.toString());
+// alist.add(22, 1);
+// console.log(alist.toString());
+// alist.add(33, 1);
+// console.log(alist.toString());
+// alist.set(1, 300);
+// console.log(alist.toString());
+// console.log(alist.get(2));
+// console.log(alist.size());
+// console.log(alist.indexOf(300));
+// console.log(alist.contains(300));
+// console.log(alist.contains(301));
+// console.log(alist.isEmpty());
+// console.log(alist.peek());
+// console.log(alist.toArray());
+// console.log(alist.iterator().next());
+// alist.clear();
+// console.log(alist.toString());
-// ArrayList 클래스를 작성하세요.
-class ArrayList extends Collection {}
-export { Stack, Queue, ArrayList };
diff --git "a/\354\240\225\354\227\260\354\261\204/ex2.js" "b/\354\240\225\354\227\260\354\261\204/ex2.js"
index 6b95f04..be51e17 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex2.js"
+++ "b/\354\240\225\354\227\260\354\261\204/ex2.js"
@@ -1,4 +1,34 @@
-// range 함수를 작성하세요.
-const range = (start, end, step = start > end ? -1 : 1) => { };
+const range = (start, end, step = start > end ? -1 : 1) => {
+ let result = [];
+
+ const add = (a, b) => {
+ return parseFloat((a + b).toFixed(10));
+ };
-module.exports = { range };
+ if (end === undefined) {
+ if (start === 0)
+ return [0];
+
+ if (start > 0) {
+ end = start;
+ start = 1;
+ } else {
+ end = -1;
+ }
+ }
+
+ if (step === 0)
+ return [start];
+
+ if ((start > end && step > 0) || (start < end && step < 0)) {
+ return result;
+ }
+
+ for (let i = start; step > 0 ? i <= end : i >= end; i = add(i, step)) {
+ result.push(i);
+ }
+
+ return result;
+ };
+
+ module.exports = { range };
\ No newline at end of file
diff --git "a/\354\240\225\354\227\260\354\261\204/ex3.js" "b/\354\240\225\354\227\260\354\261\204/ex3.js"
index b1b0d75..36c57f1 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex3.js"
+++ "b/\354\240\225\354\227\260\354\261\204/ex3.js"
@@ -1,3 +1,26 @@
Array.prototype.sortBy = function (sortProp = '') {
- return this;
-};
+
+ const str = sortProp.split(',').map(s => {
+ const [key, order] = s.split(':');
+ return {
+ key: key.trim(),
+ order: (order && order.trim().toLowerCase()) === 'desc' ? -1 : 1
+ };
+ });
+
+ const compare = (a, b, key, order) => {
+ if (a[key] > b[key]) return order;
+ if (a[key] < b[key]) return (-1) * order;
+ return 0;
+ };
+
+ return this.sort((a, b) => {
+ return str.reduce((result, { key, order }) => {
+
+ if (result !== 0)
+ return result;
+
+ return compare(a, b, key, order);
+ }, 0);
+ });
+};
\ No newline at end of file
diff --git "a/\354\240\225\354\227\260\354\261\204/ex3.test.js" "b/\354\240\225\354\227\260\354\261\204/ex3.test.js"
index 6c27a4d..1628e15 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex3.test.js"
+++ "b/\354\240\225\354\227\260\354\261\204/ex3.test.js"
@@ -8,11 +8,11 @@ const users = [lee, hong, kim];
assert.deepStrictEqual(users.sortBy('id'), [hong, kim, lee]);
assert.deepStrictEqual(users.sortBy('name:desc'), [lee, kim, hong]);
-assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [hong, lee, kim]);
+assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [lee, kim, hong]);
assert.deepStrictEqual(users.sortBy('dept:desc,city:desc'), [kim, lee, hong]);
assert.deepStrictEqual(users.sortBy('name:desc,id:,dept:desc'), [
- kim,
lee,
+ kim,
hong,
]);
-assert.deepStrictEqual(users.sortBy('dept:desc,id'), [hong, kim, lee]);
+assert.deepStrictEqual(users.sortBy('dept:desc,id'), [kim, lee, hong]);
diff --git "a/\354\240\225\354\227\260\354\261\204/ex4.js" "b/\354\240\225\354\227\260\354\261\204/ex4.js"
index 9ede02f..13a52cd 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex4.js"
+++ "b/\354\240\225\354\227\260\354\261\204/ex4.js"
@@ -1,3 +1,61 @@
-function deepCopy(obj) {}
+function objectCopy(obj, wm) {
+ const objCopy = Object.create(Object.getPrototypeOf(obj));
+ wm.set(obj, objCopy);
+
+
+ Object.getOwnPropertyNames(obj).forEach((key) => {
+ objCopy[key] = deepCopy(obj[key], wm);
+ });
+
+ Object.getOwnPropertySymbols(obj).forEach((sym) => {
+ objCopy[sym] = deepCopy(obj[sym], wm);
+ });
+
+ return objCopy;
+}
+
+function arrayCopy(arr, wm) {
+ const arrCopy = [];
+ wm.set(arr, arrCopy);
+ arr.forEach((item, index) => {
+ arrCopy[index] = deepCopy(item, wm);
+ });
+ return arrCopy;
+}
+
+function setCopy(set, wm) {
+ const setCopy = new Set();
+ wm.set(set, setCopy);
+ set.forEach((value) => {
+ setCopy.add(deepCopy(value, wm));
+ });
+ return setCopy;
+}
+
+function mapCopy(map, wm) {
+ const mapCopy = new Map();
+ wm.set(map, mapCopy);
+ map.forEach((value, key) => {
+ mapCopy.set(deepCopy(key, wm), deepCopy(value, wm));
+ });
+ return mapCopy;
+}
+
+function deepCopy(obj, wm = new WeakMap()) {
+ if (obj === null || typeof obj !== "object") return obj;
+
+ if (wm.has(obj)) return wm.get(obj);
+
+ if (Array.isArray(obj))
+ return arrayCopy(obj, wm);
+ if (obj instanceof Set)
+ return setCopy(obj, wm);
+ if (obj instanceof Map)
+ return mapCopy(obj, wm);
+ if (obj instanceof WeakSet || obj instanceof WeakMap)
+ return obj;
+
+ return objectCopy(obj, wm);
+}
module.exports = { deepCopy };
diff --git "a/\354\240\225\354\227\260\354\261\204/ex5.js" "b/\354\240\225\354\227\260\354\261\204/ex5.js"
index 464a05a..e43af8d 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex5.js"
+++ "b/\354\240\225\354\227\260\354\261\204/ex5.js"
@@ -1,3 +1,42 @@
module.exports = {
- searchByKoreanInitialSound: (data, firstSounds) => {},
-};
+ searchByKoreanInitialSound: (data, firstSounds) => {
+ const HangulList = [
+ "ㄱ",
+ "ㄲ",
+ "ㄴ",
+ "ㄷ",
+ "ㄸ",
+ "ㄹ",
+ "ㅁ",
+ "ㅂ",
+ "ㅃ",
+ "ㅅ",
+ "ㅆ",
+ "ㅇ",
+ "ㅈ",
+ "ㅉ",
+ "ㅊ",
+ "ㅋ",
+ "ㅌ",
+ "ㅍ",
+ "ㅎ",
+ ];
+
+ const getHangul = (ch) => {
+ const code = ch.charCodeAt(0) - 0xac00;
+ return code >= 0 && code < 11172 ? HangulList[Math.floor(code / 588)] : ch;
+ };
+
+ const regex = new RegExp(
+ firstSounds
+ .split("")
+ .map((char) => (/[ㄱ-ㅎ]/.test(char) ? char : `(${char})`))
+ .join(".*?")
+ );
+
+ return data.filter((item) => {
+ const hangulStr = item.split("").map(getHangul).join("");
+ return regex.test(hangulStr);
+ });
+ },
+};
\ No newline at end of file
diff --git "a/\354\240\225\354\227\260\354\261\204/ex6.test.ts" "b/\354\240\225\354\227\260\354\261\204/ex6.test.ts"
index 680c5e6..41abbf6 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex6.test.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex6.test.ts"
@@ -8,7 +8,7 @@ import { promiseAllSettled, randTime } from './ex6';
);
})();
-(async function testWithReject() {
+(async function testWithReject() {
assert.deepStrictEqual(
await promiseAllSettled([
randTime(11),
@@ -22,3 +22,4 @@ import { promiseAllSettled, randTime } from './ex6';
])
);
})();
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex6.ts" "b/\354\240\225\354\227\260\354\261\204/ex6.ts"
index 424ca54..29ad355 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex6.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex6.ts"
@@ -1,4 +1,48 @@
export const randTime = (val: T): Promise =>
- new Promise(resolve => setTimeout(resolve, Math.random() * 1000, val));
+ new Promise((resolve) => setTimeout(resolve, Math.random() * 1000, val));
-export function promiseAllSettled(promises: Promise[]) {}
+export function promiseAllSettled(
+ promises: Promise[]
+): Promise[]> {
+ return new Promise((resolve) => {
+ const results: PromiseSettledResult[] = [];
+ let cnt = 0;
+
+ const result = (i: number, v: PromiseSettledResult) => {
+ results[i] = v;
+ cnt++;
+ if (cnt === promises.length) {
+ resolve(results);
+ }
+ };
+
+ promises.forEach((promise, i) => {
+ promise
+ .then((value) =>
+ result(i, { status: "fulfilled", value } as const)
+ )
+ .catch((reason) =>
+ result(i, { status: "rejected", reason } as const)
+ );
+ });
+ });
+}
+
+export function promiseAll(promises: Promise[]): Promise {
+ return new Promise((resolve, reject) => {
+ const results: T[] = [];
+ let cnt = 0;
+
+ const result = (i: number, v: T) => {
+ results[i] = v;
+ cnt++;
+ if (cnt === promises.length) {
+ resolve(results);
+ }
+ };
+
+ promises.forEach((promise, i) => {
+ promise.then((v) => result(i, v)).catch(reject);
+ });
+ });
+}
\ No newline at end of file
diff --git "a/\354\240\225\354\227\260\354\261\204/ex7.test.ts" "b/\354\240\225\354\227\260\354\261\204/ex7.test.ts"
index 62b881d..72b684b 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex7.test.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex7.test.ts"
@@ -65,6 +65,10 @@ async function test(userId: string | number) {
});
// 추가 테스트 코드를 작성하시오.
+
+ const emptyPosts = await getPosts(999);
+ assert.strictEqual(emptyPosts.length, 0);
}
test(1);
+
diff --git "a/\354\240\225\354\227\260\354\261\204/ex7.ts" "b/\354\240\225\354\227\260\354\261\204/ex7.ts"
index 62812ac..4e2d1d8 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex7.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex7.ts"
@@ -1,3 +1,53 @@
+// const POST_URL = 'https://jsonplaceholder.typicode.com/posts';
+
+// export async function getPosts(userId: number | string) {}
+
const POST_URL = 'https://jsonplaceholder.typicode.com/posts';
-export async function getPosts(userId: number | string) {}
+interface Comment {
+ postId: number;
+ id: number;
+ email: string;
+ body: string;
+}
+
+interface Post {
+ postId: number;
+ title: string;
+ comments: Comment[];
+}
+
+export async function getPosts(userId: number | string) {
+ try {
+ // 1. 특정 userId의 게시글 목록을 가져옵니다.
+ const postsResponse = await fetch(`${POST_URL}?userId=${userId}`);
+ const postsData = (await postsResponse.json()) as { id: number; title: string }[];
+
+ // 2. 각 게시글의 댓글 목록을 가져와서 posts 배열에 추가합니다.
+ const postsWithComments: Post[] = await Promise.all(
+ postsData.map(async (post) => {
+ const commentsResponse = await fetch(`${POST_URL}/${post.id}/comments`);
+ const commentsData = (await commentsResponse.json()) as any[];
+
+ // 'name' 필드를 제거하고 새로운 Comment 객체 배열을 생성합니다.
+ const sanitizedCommentsData: Comment[] = commentsData.map(({ postId, id, email, body }) => ({
+ postId,
+ id,
+ email,
+ body,
+ }));
+
+ return {
+ postId: post.id,
+ title: post.title,
+ comments: sanitizedCommentsData,
+ };
+ })
+ );
+
+ return postsWithComments;
+ } catch (error) {
+ console.error('오류1', error);
+ throw new Error('오류2');
+ }
+}
diff --git "a/\354\240\225\354\227\260\354\261\204/ex8.ts" "b/\354\240\225\354\227\260\354\261\204/ex8.ts"
index a67a2d2..a67e90a 100644
--- "a/\354\240\225\354\227\260\354\261\204/ex8.ts"
+++ "b/\354\240\225\354\227\260\354\261\204/ex8.ts"
@@ -1,8 +1,40 @@
-// dummy(mock)입니다. 올바르게 수정하세요.
-const debounce = (cb: any, delay: number) => (i: number) => {};
-const throttle = (cb: any, delay: number) => (i: number) => {};
+// // dummy(mock)입니다. 올바르게 수정하세요.
+// const debounce = (cb: any, delay: number) => (i: number) => {};
+// const throttle = (cb: any, delay: number) => (i: number) => {};
-// function throttle...
+// // function throttle...
+
+// const debo = debounce((a: number) => console.log(a + 1), 500);
+// for (let i = 10; i < 15; i++) debo(i); // 15 출력
+
+// const thro = throttle((a: number) => console.log(a + 1), 500);
+// for (let i = 10; i < 15; i++) thro(i); // 11 출력
+
+
+
+const debounce = (cb: (arg: number) => void, delay: number) => {
+ let time: ReturnType | null = null;
+
+ return (i: number) => {
+ if (time !== null) clearTimeout(time);
+
+ time = setTimeout(() => {
+ cb(i);
+ }, delay);
+ };
+};
+
+const throttle = (cb: (arg: number) => void, delay: number) => {
+ let time = 0;
+
+ return (i: number) => {
+ const now = Date.now();
+ if (now - time >= delay) {
+ cb(i);
+ time = now;
+ }
+ };
+};
const debo = debounce((a: number) => console.log(a + 1), 500);
for (let i = 10; i < 15; i++) debo(i); // 15 출력