diff --git a/404.html b/404.html index 87efa9b..9a9a17a 100644 --- a/404.html +++ b/404.html @@ -1 +1 @@ -404: This page could not be found

404

This page could not be found.

\ No newline at end of file +404: This page could not be found

404

This page could not be found.

\ No newline at end of file diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/index.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/index.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/index.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/index.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm.json diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.json" diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.json" diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.json" diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive09.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive09.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive09.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive09.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive10.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive10.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive10.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive10.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive11.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive11.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/javascriptdeepdive11.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/javascriptdeepdive11.json diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.json" diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/React.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/React.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/React.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/React.json diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.json" diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.json" diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/all.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/all.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/all.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/all.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/search.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/search.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/search.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/search.json diff --git a/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/Algorithm.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/Algorithm.json new file mode 100644 index 0000000..55a8065 --- /dev/null +++ b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/Algorithm.json @@ -0,0 +1 @@ +{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색"],"currentTag":"Algorithm","posts":[{"slug":"posts/Algorithm/[백준 gold 5] 빌런 호석","title":"[백준 gold 5] 빌런 호석","date":"2024-08-09T17:05:24.000Z","image":"index.png","summary":"dfs을 활용한 프로그래머스 [level 3] 징검다리 건너기 문제 풀이 입니다.","tags":["Algorithm","백준","gold","dfs"],"content":"# [gold 3] 빌런 호석\r\n\r\n## 문제 설명\r\n\r\n치르보기 빌딩은 11층부터 NN층까지 이용이 가능한 엘리베이터가 있다. 엘리베이터의 층수를 보여주는 디스플레이에는 KK 자리의 수가 보인다. 수는 00으로 시작할 수도 있다. 00부터 99까지의 각 숫자가 디스플레이에 보이는 방식은 아래와 같다. 각 숫자는 7개의 표시등 중의 일부에 불이 들어오면서 표현된다.\r\n\r\n![](1.png)\r\n\r\n예를 들어 K=4K=4인 경우에 16801680층과 501501층은 아래와 같이 보인다.\r\n\r\n![](2.png)\r\n\r\n\r\n\r\n빌런 호석은 치르보기 빌딩의 엘리베이터 디스플레이의 LED 중에서 최소 11개, 최대 PP개를 반전시킬 계획을 세우고 있다. 반전이란 켜진 부분은 끄고, 꺼진 부분은 켜는 것을 의미한다. 예를 들어 숫자 11을 22로 바꾸려면 총 5개의 LED를 반전시켜야 한다. 또한 반전 이후에 디스플레이에 올바른 수가 보여지면서 11 이상 NN 이하가 되도록 바꿔서 사람들을 헷갈리게 할 예정이다. 치르보기를 사랑하는 모임의 회원인 당신은 호석 빌런의 행동을 미리 파악해서 혼쭐을 내주고자 한다. 현재 엘리베이터가 실제로는 XX층에 멈춰있을 때, 호석이가 반전시킬 LED를 고를 수 있는 경우의 수를 계산해보자.\r\n\r\n### 입력\r\n\r\n N,K,P,XN,K,P,X 가 공백으로 구분되어 첫째 줄에 주어진다.\r\n\r\n### 출력\r\n\r\n호석 빌런이 엘리베이터 LED를 올바르게 반전시킬 수 있는 경우의 수를 계산해보자.\r\n\r\n## 접근 방법\r\n\r\n숫자에 따른 LED를 먼저 구현하기 위해, \r\n\r\n그림과 같이, 각 LED의 위치에 번호를 매겨, 배열안에 그 번호가 있으면 불이 켜져있는 것으로, 없다면 불이 꺼져 있는 것으로 표현하였다.\r\n\"이미지\r\n\r\n\r\n그림처럼 0을 표현하면 3번자리를 제외한 모든 번호가 켜져있으므로, `[0,1,2,4,5,6]`으로 표현 할 수 있다.\r\n\r\n각 번호를 이와 같이 바꾸어 numbers 배열에 저장하면, 이와 같다.\r\n```python\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n```\r\n이후 만일 현재 번호와 비교할 번호의 LED를 비교하기 위해 서로의 차집합을 더해서 두 번호가 서로를 비교했을 때, 가지고 있는 혹은 없는 번호의 개수를 구한다.\r\n```python\r\ncur_count = len(list(cur.difference(compare))) + len(list(compare.difference(cur)));\r\n```\r\n이와 같은 방식으로 반전시킬 LED의 개수를 구하고, dfs를 활용하여 x의 모든 자릿수를 순회하여 p보다 작거나 같게 LED를 반전하면서, n보다 번호가 작거나 같다면 result를 1 증가 시킨다.\r\n\r\n전체코드는 다음과 같다.\r\n```python\r\nimport sys;\r\ninput = sys.stdin.readline;\r\n\r\nn,k,p,x = map(int, input().split());\r\nresult = 0;\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n\r\nx = list(str(x));\r\nif len(x) != k:\r\n\t# k 보다 자릿수 x가 자릿수가 작다면 작은 만큼 앞에 0을 채워주어야 한다.\r\n for _ in range(k-len(x)):\r\n x.insert(0,'0');\r\n \r\ndef dfs(index,count,st):\r\n global result;\r\n if count>p:\r\n return;\r\n if index == k:\r\n if 0\r\n \r\nrectangle\r\ncharacterX\r\ncharacterY\r\nitemX\r\nitemY\r\nresult\r\n\r\n\r\n \r\n[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]\r\n1\r\n3\r\n7\r\n8\r\n17\r\n\r\n\r\n[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]\r\n9\r\n7\r\n6\r\n1\r\n11\r\n\r\n\r\n[[1,1,5,7]]\r\n1\r\n1\r\n4\r\n7\r\n9\r\n\r\n\r\n[[2,1,7,5],[6,4,10,10]]\r\n3\r\n1\r\n7\r\n10\r\n15\r\n\r\n\r\n[[2,2,5,5],[1,3,6,4],[3,1,4,6]]\r\n1\r\n4\r\n6\r\n3\r\n10\r\n\r\n\r\n \r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nstones\r\nk\r\nresult\r\n\r\n\r\n \r\n[2, 4, 5, 3, 2, 1, 4, 2, 5, 1]\r\n3\r\n3\r\n\r\n\r\n \r\n\r\n##### **입출력 예에 대한 설명**\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/64062.%E2%80%85%EC%A7%95%EA%B2%80%EB%8B%A4%EB%A6%AC%E2%80%85%EA%B1%B4%EB%84%88%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88%EC%97%90-%EB%8C%80%ED%95%9C-%EC%84%A4%EB%AA%85)\r\n\r\n----------\r\n\r\n**입출력 예 #1**\r\n\r\n첫 번째 친구는 다음과 같이 징검다리를 건널 수 있습니다. \r\n![1.png](1.png)\r\n\r\n첫 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n두 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![2.png](2.png)\r\n\r\n두 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n세 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![3.png](3.png)\r\n\r\n세 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n네 번째 친구가 징검다리를 건너려면, 세 번째 디딤돌에서 일곱 번째 디딤돌로 네 칸을 건너뛰어야 합니다. 하지만 k = 3 이므로 건너뛸 수 없습니다. \r\n![4.png](4.png)\r\n\r\n따라서 최대 3명이 디딤돌을 모두 건널 수 있습니다.\r\n\r\n## 접근 방법\r\n브루트 포스로 1명씩 건너기에는, stones 배열의 크기가 최대 200,000이고, stones 배열의 각 원소들의 값 역시 최대 200,000,000이기 때문에, 시간 초과가 날 확률이 높다고 생각했고(사실 그렇게 쉬우면 lv3 일리가 없지), 아니나 다를까 시간초과가 났다. \r\n\r\n고민하다가 도저히 해결책이 안나와서 찾아보니 `이분탐색`을 사용하여 풀 수 있었다.\r\n\r\n- 건널 수 있는 인원의 최소는 1명, 최대는 max(stones)명이다. 모든 돌들의 합이 같거나, 다르다 하더라도 건널수 없는 곳이 k이하면 건널 수 있기 때문이다. \r\n- 따라서 start = 1 end = max(stones)로 이분탐색을 시작할 수 있다.\r\n\r\nmid 값만큼의 사람이 건널 수 있는지 확인하기 위한 check함수는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n\t # 밟을 수 없으므로 건너뛰어야하는 횟수를 늘린다.\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n # 밟을 수 있으므로 최대 건너뛰는 횟수를 초기화시킨다.\r\n else:\r\n cnt = 0;\r\n # 건너뛰는 횟수가 k보다 크거나 같으면 안되므로 False 리턴 \r\n if cnt>=k:\r\n return False;\r\n return True;\r\n```\r\n건널 수 있다면 mid보다 큰 범위에서 값을 찾아야하므로 start를 mid+1로 갱신하고, 반대라면, mid보다 작은 범위에서 값을 찾아야하므로 end를 mid-1로 갱신한다.\r\n \r\ncheck 시간 복잡도는 O(N)이고 이분탐색을 했을 때 O(logN)의 시간복잡도가 나오므로, 총 O(NlogN)의 시간 복잡도가 나오므로, 시간초과가 나지 않는다.\r\n\r\n전체 코드는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n else:\r\n cnt = 0;\r\n if cnt>=k:\r\n return False;\r\n return True;\r\n\r\ndef solution(stones, k):\r\n start,end = 1,max(stones);\r\n answer = 0;\r\n while start<=end:\r\n mid = (start + end) // 2;\r\n if check(stones, mid,k):\r\n start = mid+1;\r\n else:\r\n answer = mid;\r\n end = mid-1; \r\n return answer;\r\n```\r\n\r\n## 느낀 점\r\n이분탐색 문제를 많이는 아니더라도 어느정도는 풀어봤다고 생각했는데, 이 문제에서 이분탐색으로 푸는 아이디어를 떠올리지 못해서 아쉽다. \r\n\r\n또한 처음에 위에 코드의 6번째줄에서 else문을 쓰지않고, 이러한 코드로 제출하여서 시간초과가 났다.\r\n```python\r\nif (stone - mid) <= 0:\r\n\tcnt += 1;\r\nif (stone - mid)>0:\r\n\tcnt = 0;\r\n```\r\nㅎㅎ.. 사실 위와 같은 경우에서 if else문을 쓰는 것이 기본인데, 그래도 시간초과가 날 수 있는 직접적인 원인까지는 되지 않을 거라고 안일하게 생각해서 코드를 짠 게 화근이었다. 기본을 지키자!"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/JavaScript.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/JavaScript.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/JavaScript.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/JavaScript.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/Virtual DOM.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/Virtual DOM.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/Virtual DOM.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/Virtual DOM.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/all.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/all.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/all.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/all.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/lv3.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/bfs.json similarity index 53% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/lv3.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/bfs.json index d7d43c4..4bcf05d 100644 --- a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/lv3.json +++ b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/bfs.json @@ -1 +1 @@ -{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색","all"],"currentTag":"lv3","posts":[{"slug":"posts/Algorithm/[프로그래머스lv3]아이템 줍기","title":"[프로그래머스 level 3] 아이템 줍기","date":"2024-07-12T16:34:24.000Z","image":"index.png","summary":"bfs를 활용한 프로그래머스 [level 3] 아이템 줍기 문제 풀이 입니다.","tags":["Algorithm","프로그래머스","lv3","bfs"],"content":"# [level 3] 아이템 줍기 (BFS/DFS)\r\n## 문제 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EB%AC%B8%EC%A0%9C-%EC%84%A4%EB%AA%85)\r\n\r\n다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.\r\n\r\n![1.png](1.png)\r\n\r\n지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.\r\n\r\n만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.\r\n\r\n![2.png](2.png)\r\n\r\n단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.\r\n\r\n![rect_3.png](3.png)\r\n\r\n즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.\r\n\r\n다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.\r\n\r\n![rect_4.png](4.png)\r\n\r\n한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.\r\n\r\n![rect_5.png](5.png)\r\n\r\n지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.\r\n\r\n##### 제한사항\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%A0%9C%ED%95%9C%EC%82%AC%ED%95%AD)\r\n\r\n- rectangle의 세로(행) 길이는 1 이상 4 이하입니다.\r\n- rectangle의 원소는 각 직사각형의 [좌측 하단 x, 좌측 하단 y, 우측 상단 x, 우측 상단 y] 좌표 형태입니다.\r\n - 직사각형을 나타내는 모든 좌표값은 1 이상 50 이하인 자연수입니다.\r\n - 서로 다른 두 직사각형의 x축 좌표, 혹은 y축 좌표가 같은 경우는 없습니다.\r\n - 문제에 주어진 조건에 맞는 직사각형만 입력으로 주어집니다.\r\n- charcterX, charcterY는 1 이상 50 이하인 자연수입니다.\r\n - 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.\r\n- itemX, itemY는 1 이상 50 이하인 자연수입니다.\r\n - 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.\r\n- 캐릭터와 아이템의 처음 위치가 같은 경우는 없습니다.\r\n\r\n----------\r\n\r\n- 전체 배점의 50%는 직사각형이 1개인 경우입니다. \r\n \r\n- 전체 배점의 25%는 직사각형이 2개인 경우입니다. \r\n \r\n- 전체 배점의 25%는 직사각형이 3개 또는 4개인 경우입니다. \r\n \r\n\r\n----------\r\n\r\n##### 입출력 예\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88)\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
rectanglecharacterXcharacterYitemXitemYresult
[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]137817
[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]976111
[[1,1,5,7]]11479
[[2,1,7,5],[6,4,10,10]]3171015
[[2,2,5,5],[1,3,6,4],[3,1,4,6]]146310
\r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nstones\r\nk\r\nresult\r\n\r\n\r\n \r\n[2, 4, 5, 3, 2, 1, 4, 2, 5, 1]\r\n3\r\n3\r\n\r\n\r\n \r\n\r\n##### **입출력 예에 대한 설명**\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/64062.%E2%80%85%EC%A7%95%EA%B2%80%EB%8B%A4%EB%A6%AC%E2%80%85%EA%B1%B4%EB%84%88%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88%EC%97%90-%EB%8C%80%ED%95%9C-%EC%84%A4%EB%AA%85)\r\n\r\n----------\r\n\r\n**입출력 예 #1**\r\n\r\n첫 번째 친구는 다음과 같이 징검다리를 건널 수 있습니다. \r\n![1.png](1.png)\r\n\r\n첫 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n두 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![2.png](2.png)\r\n\r\n두 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n세 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![3.png](3.png)\r\n\r\n세 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n네 번째 친구가 징검다리를 건너려면, 세 번째 디딤돌에서 일곱 번째 디딤돌로 네 칸을 건너뛰어야 합니다. 하지만 k = 3 이므로 건너뛸 수 없습니다. \r\n![4.png](4.png)\r\n\r\n따라서 최대 3명이 디딤돌을 모두 건널 수 있습니다.\r\n\r\n## 접근 방법\r\n브루트 포스로 1명씩 건너기에는, stones 배열의 크기가 최대 200,000이고, stones 배열의 각 원소들의 값 역시 최대 200,000,000이기 때문에, 시간 초과가 날 확률이 높다고 생각했고(사실 그렇게 쉬우면 lv3 일리가 없지), 아니나 다를까 시간초과가 났다. \r\n\r\n고민하다가 도저히 해결책이 안나와서 찾아보니 `이분탐색`을 사용하여 풀 수 있었다.\r\n\r\n- 건널 수 있는 인원의 최소는 1명, 최대는 max(stones)명이다. 모든 돌들의 합이 같거나, 다르다 하더라도 건널수 없는 곳이 k이하면 건널 수 있기 때문이다. \r\n- 따라서 start = 1 end = max(stones)로 이분탐색을 시작할 수 있다.\r\n\r\nmid 값만큼의 사람이 건널 수 있는지 확인하기 위한 check함수는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n\t # 밟을 수 없으므로 건너뛰어야하는 횟수를 늘린다.\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n # 밟을 수 있으므로 최대 건너뛰는 횟수를 초기화시킨다.\r\n else:\r\n cnt = 0;\r\n # 건너뛰는 횟수가 k보다 크거나 같으면 안되므로 False 리턴 \r\n if cnt>=k:\r\n return False;\r\n return True;\r\n```\r\n건널 수 있다면 mid보다 큰 범위에서 값을 찾아야하므로 start를 mid+1로 갱신하고, 반대라면, mid보다 작은 범위에서 값을 찾아야하므로 end를 mid-1로 갱신한다.\r\n \r\ncheck 시간 복잡도는 O(N)이고 이분탐색을 했을 때 O(logN)의 시간복잡도가 나오므로, 총 O(NlogN)의 시간 복잡도가 나오므로, 시간초과가 나지 않는다.\r\n\r\n전체 코드는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n else:\r\n cnt = 0;\r\n if cnt>=k:\r\n return False;\r\n return True;\r\n\r\ndef solution(stones, k):\r\n start,end = 1,max(stones);\r\n answer = 0;\r\n while start<=end:\r\n mid = (start + end) // 2;\r\n if check(stones, mid,k):\r\n start = mid+1;\r\n else:\r\n answer = mid;\r\n end = mid-1; \r\n return answer;\r\n```\r\n\r\n## 느낀 점\r\n이분탐색 문제를 많이는 아니더라도 어느정도는 풀어봤다고 생각했는데, 이 문제에서 이분탐색으로 푸는 아이디어를 떠올리지 못해서 아쉽다. \r\n\r\n또한 처음에 위에 코드의 6번째줄에서 else문을 쓰지않고, 이러한 코드로 제출하여서 시간초과가 났다.\r\n```python\r\nif (stone - mid) <= 0:\r\n\tcnt += 1;\r\nif (stone - mid)>0:\r\n\tcnt = 0;\r\n```\r\nㅎㅎ.. 사실 위와 같은 경우에서 if else문을 쓰는 것이 기본인데, 그래도 시간초과가 날 수 있는 직접적인 원인까지는 되지 않을 거라고 안일하게 생각해서 코드를 짠 게 화근이었다. 기본을 지키자!"}]},"__N_SSG":true} \ No newline at end of file +{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색","all"],"currentTag":"bfs","posts":[{"slug":"posts/Algorithm/[프로그래머스lv3]아이템 줍기","title":"[프로그래머스 level 3] 아이템 줍기","date":"2024-07-12T16:34:24.000Z","image":"index.png","summary":"bfs를 활용한 프로그래머스 [level 3] 아이템 줍기 문제 풀이 입니다.","tags":["Algorithm","프로그래머스","lv3","bfs"],"content":"# [level 3] 아이템 줍기 (BFS/DFS)\r\n## 문제 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EB%AC%B8%EC%A0%9C-%EC%84%A4%EB%AA%85)\r\n\r\n다음과 같은 다각형 모양 지형에서 캐릭터가 아이템을 줍기 위해 이동하려 합니다.\r\n\r\n![1.png](1.png)\r\n\r\n지형은 각 변이 x축, y축과 평행한 직사각형이 겹쳐진 형태로 표현하며, 캐릭터는 이 다각형의 둘레(굵은 선)를 따라서 이동합니다.\r\n\r\n만약 직사각형을 겹친 후 다음과 같이 중앙에 빈 공간이 생기는 경우, 다각형의 가장 바깥쪽 테두리가 캐릭터의 이동 경로가 됩니다.\r\n\r\n![2.png](2.png)\r\n\r\n단, 서로 다른 두 직사각형의 x축 좌표 또는 y축 좌표가 같은 경우는 없습니다.\r\n\r\n![rect_3.png](3.png)\r\n\r\n즉, 위 그림처럼 서로 다른 두 직사각형이 꼭짓점에서 만나거나, 변이 겹치는 경우 등은 없습니다.\r\n\r\n다음 그림과 같이 지형이 2개 이상으로 분리된 경우도 없습니다.\r\n\r\n![rect_4.png](4.png)\r\n\r\n한 직사각형이 다른 직사각형 안에 완전히 포함되는 경우 또한 없습니다.\r\n\r\n![rect_5.png](5.png)\r\n\r\n지형을 나타내는 직사각형이 담긴 2차원 배열 rectangle, 초기 캐릭터의 위치 characterX, characterY, 아이템의 위치 itemX, itemY가 solution 함수의 매개변수로 주어질 때, 캐릭터가 아이템을 줍기 위해 이동해야 하는 가장 짧은 거리를 return 하도록 solution 함수를 완성해주세요.\r\n\r\n##### 제한사항\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%A0%9C%ED%95%9C%EC%82%AC%ED%95%AD)\r\n\r\n- rectangle의 세로(행) 길이는 1 이상 4 이하입니다.\r\n- rectangle의 원소는 각 직사각형의 [좌측 하단 x, 좌측 하단 y, 우측 상단 x, 우측 상단 y] 좌표 형태입니다.\r\n - 직사각형을 나타내는 모든 좌표값은 1 이상 50 이하인 자연수입니다.\r\n - 서로 다른 두 직사각형의 x축 좌표, 혹은 y축 좌표가 같은 경우는 없습니다.\r\n - 문제에 주어진 조건에 맞는 직사각형만 입력으로 주어집니다.\r\n- charcterX, charcterY는 1 이상 50 이하인 자연수입니다.\r\n - 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.\r\n- itemX, itemY는 1 이상 50 이하인 자연수입니다.\r\n - 지형을 나타내는 다각형 테두리 위의 한 점이 주어집니다.\r\n- 캐릭터와 아이템의 처음 위치가 같은 경우는 없습니다.\r\n\r\n----------\r\n\r\n- 전체 배점의 50%는 직사각형이 1개인 경우입니다. \r\n \r\n- 전체 배점의 25%는 직사각형이 2개인 경우입니다. \r\n \r\n- 전체 배점의 25%는 직사각형이 3개 또는 4개인 경우입니다. \r\n \r\n\r\n----------\r\n\r\n##### 입출력 예\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88)\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n
rectanglecharacterXcharacterYitemXitemYresult
[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]137817
[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]976111
[[1,1,5,7]]11479
[[2,1,7,5],[6,4,10,10]]3171015
[[2,2,5,5],[1,3,6,4],[3,1,4,6]]146310
\r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nrectangle\r\ncharacterX\r\ncharacterY\r\nitemX\r\nitemY\r\nresult\r\n\r\n\r\n \r\n[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]\r\n1\r\n3\r\n7\r\n8\r\n17\r\n\r\n\r\n[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]\r\n9\r\n7\r\n6\r\n1\r\n11\r\n\r\n\r\n[[1,1,5,7]]\r\n1\r\n1\r\n4\r\n7\r\n9\r\n\r\n\r\n[[2,1,7,5],[6,4,10,10]]\r\n3\r\n1\r\n7\r\n10\r\n15\r\n\r\n\r\n[[2,2,5,5],[1,3,6,4],[3,1,4,6]]\r\n1\r\n4\r\n6\r\n3\r\n10\r\n\r\n\r\n \r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nrectangle\r\ncharacterX\r\ncharacterY\r\nitemX\r\nitemY\r\nresult\r\n\r\n\r\n \r\n[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]\r\n1\r\n3\r\n7\r\n8\r\n17\r\n\r\n\r\n[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]\r\n9\r\n7\r\n6\r\n1\r\n11\r\n\r\n\r\n[[1,1,5,7]]\r\n1\r\n1\r\n4\r\n7\r\n9\r\n\r\n\r\n[[2,1,7,5],[6,4,10,10]]\r\n3\r\n1\r\n7\r\n10\r\n15\r\n\r\n\r\n[[2,2,5,5],[1,3,6,4],[3,1,4,6]]\r\n1\r\n4\r\n6\r\n3\r\n10\r\n\r\n\r\n \r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nstones\r\nk\r\nresult\r\n\r\n\r\n \r\n[2, 4, 5, 3, 2, 1, 4, 2, 5, 1]\r\n3\r\n3\r\n\r\n\r\n \r\n\r\n##### **입출력 예에 대한 설명**\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/64062.%E2%80%85%EC%A7%95%EA%B2%80%EB%8B%A4%EB%A6%AC%E2%80%85%EA%B1%B4%EB%84%88%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88%EC%97%90-%EB%8C%80%ED%95%9C-%EC%84%A4%EB%AA%85)\r\n\r\n----------\r\n\r\n**입출력 예 #1**\r\n\r\n첫 번째 친구는 다음과 같이 징검다리를 건널 수 있습니다. \r\n![1.png](1.png)\r\n\r\n첫 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n두 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![2.png](2.png)\r\n\r\n두 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n세 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![3.png](3.png)\r\n\r\n세 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n네 번째 친구가 징검다리를 건너려면, 세 번째 디딤돌에서 일곱 번째 디딤돌로 네 칸을 건너뛰어야 합니다. 하지만 k = 3 이므로 건너뛸 수 없습니다. \r\n![4.png](4.png)\r\n\r\n따라서 최대 3명이 디딤돌을 모두 건널 수 있습니다.\r\n\r\n## 접근 방법\r\n브루트 포스로 1명씩 건너기에는, stones 배열의 크기가 최대 200,000이고, stones 배열의 각 원소들의 값 역시 최대 200,000,000이기 때문에, 시간 초과가 날 확률이 높다고 생각했고(사실 그렇게 쉬우면 lv3 일리가 없지), 아니나 다를까 시간초과가 났다. \r\n\r\n고민하다가 도저히 해결책이 안나와서 찾아보니 `이분탐색`을 사용하여 풀 수 있었다.\r\n\r\n- 건널 수 있는 인원의 최소는 1명, 최대는 max(stones)명이다. 모든 돌들의 합이 같거나, 다르다 하더라도 건널수 없는 곳이 k이하면 건널 수 있기 때문이다. \r\n- 따라서 start = 1 end = max(stones)로 이분탐색을 시작할 수 있다.\r\n\r\nmid 값만큼의 사람이 건널 수 있는지 확인하기 위한 check함수는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n\t # 밟을 수 없으므로 건너뛰어야하는 횟수를 늘린다.\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n # 밟을 수 있으므로 최대 건너뛰는 횟수를 초기화시킨다.\r\n else:\r\n cnt = 0;\r\n # 건너뛰는 횟수가 k보다 크거나 같으면 안되므로 False 리턴 \r\n if cnt>=k:\r\n return False;\r\n return True;\r\n```\r\n건널 수 있다면 mid보다 큰 범위에서 값을 찾아야하므로 start를 mid+1로 갱신하고, 반대라면, mid보다 작은 범위에서 값을 찾아야하므로 end를 mid-1로 갱신한다.\r\n \r\ncheck 시간 복잡도는 O(N)이고 이분탐색을 했을 때 O(logN)의 시간복잡도가 나오므로, 총 O(NlogN)의 시간 복잡도가 나오므로, 시간초과가 나지 않는다.\r\n\r\n전체 코드는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n else:\r\n cnt = 0;\r\n if cnt>=k:\r\n return False;\r\n return True;\r\n\r\ndef solution(stones, k):\r\n start,end = 1,max(stones);\r\n answer = 0;\r\n while start<=end:\r\n mid = (start + end) // 2;\r\n if check(stones, mid,k):\r\n start = mid+1;\r\n else:\r\n answer = mid;\r\n end = mid-1; \r\n return answer;\r\n```\r\n\r\n## 느낀 점\r\n이분탐색 문제를 많이는 아니더라도 어느정도는 풀어봤다고 생각했는데, 이 문제에서 이분탐색으로 푸는 아이디어를 떠올리지 못해서 아쉽다. \r\n\r\n또한 처음에 위에 코드의 6번째줄에서 else문을 쓰지않고, 이러한 코드로 제출하여서 시간초과가 났다.\r\n```python\r\nif (stone - mid) <= 0:\r\n\tcnt += 1;\r\nif (stone - mid)>0:\r\n\tcnt = 0;\r\n```\r\nㅎㅎ.. 사실 위와 같은 경우에서 if else문을 쓰는 것이 기본인데, 그래도 시간초과가 날 수 있는 직접적인 원인까지는 되지 않을 거라고 안일하게 생각해서 코드를 짠 게 화근이었다. 기본을 지키자!"}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/react.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/react.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/react.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/react.json diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/useState.json b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/useState.json similarity index 100% rename from _next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/useState.json rename to _next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/useState.json diff --git "a/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/\353\260\261\354\244\200.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/\353\260\261\354\244\200.json" new file mode 100644 index 0000000..3237158 --- /dev/null +++ "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/\353\260\261\354\244\200.json" @@ -0,0 +1 @@ +{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색","all"],"currentTag":"백준","posts":[{"slug":"posts/Algorithm/[백준 gold 5] 빌런 호석","title":"[백준 gold 5] 빌런 호석","date":"2024-08-09T17:05:24.000Z","image":"index.png","summary":"dfs을 활용한 프로그래머스 [level 3] 징검다리 건너기 문제 풀이 입니다.","tags":["Algorithm","백준","gold","dfs"],"content":"# [gold 3] 빌런 호석\r\n\r\n## 문제 설명\r\n\r\n치르보기 빌딩은 11층부터 NN층까지 이용이 가능한 엘리베이터가 있다. 엘리베이터의 층수를 보여주는 디스플레이에는 KK 자리의 수가 보인다. 수는 00으로 시작할 수도 있다. 00부터 99까지의 각 숫자가 디스플레이에 보이는 방식은 아래와 같다. 각 숫자는 7개의 표시등 중의 일부에 불이 들어오면서 표현된다.\r\n\r\n![](1.png)\r\n\r\n예를 들어 K=4K=4인 경우에 16801680층과 501501층은 아래와 같이 보인다.\r\n\r\n![](2.png)\r\n\r\n\r\n\r\n빌런 호석은 치르보기 빌딩의 엘리베이터 디스플레이의 LED 중에서 최소 11개, 최대 PP개를 반전시킬 계획을 세우고 있다. 반전이란 켜진 부분은 끄고, 꺼진 부분은 켜는 것을 의미한다. 예를 들어 숫자 11을 22로 바꾸려면 총 5개의 LED를 반전시켜야 한다. 또한 반전 이후에 디스플레이에 올바른 수가 보여지면서 11 이상 NN 이하가 되도록 바꿔서 사람들을 헷갈리게 할 예정이다. 치르보기를 사랑하는 모임의 회원인 당신은 호석 빌런의 행동을 미리 파악해서 혼쭐을 내주고자 한다. 현재 엘리베이터가 실제로는 XX층에 멈춰있을 때, 호석이가 반전시킬 LED를 고를 수 있는 경우의 수를 계산해보자.\r\n\r\n### 입력\r\n\r\n N,K,P,XN,K,P,X 가 공백으로 구분되어 첫째 줄에 주어진다.\r\n\r\n### 출력\r\n\r\n호석 빌런이 엘리베이터 LED를 올바르게 반전시킬 수 있는 경우의 수를 계산해보자.\r\n\r\n## 접근 방법\r\n\r\n숫자에 따른 LED를 먼저 구현하기 위해, \r\n\r\n그림과 같이, 각 LED의 위치에 번호를 매겨, 배열안에 그 번호가 있으면 불이 켜져있는 것으로, 없다면 불이 꺼져 있는 것으로 표현하였다.\r\n\"이미지\r\n\r\n\r\n그림처럼 0을 표현하면 3번자리를 제외한 모든 번호가 켜져있으므로, `[0,1,2,4,5,6]`으로 표현 할 수 있다.\r\n\r\n각 번호를 이와 같이 바꾸어 numbers 배열에 저장하면, 이와 같다.\r\n```python\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n```\r\n이후 만일 현재 번호와 비교할 번호의 LED를 비교하기 위해 서로의 차집합을 더해서 두 번호가 서로를 비교했을 때, 가지고 있는 혹은 없는 번호의 개수를 구한다.\r\n```python\r\ncur_count = len(list(cur.difference(compare))) + len(list(compare.difference(cur)));\r\n```\r\n이와 같은 방식으로 반전시킬 LED의 개수를 구하고, dfs를 활용하여 x의 모든 자릿수를 순회하여 p보다 작거나 같게 LED를 반전하면서, n보다 번호가 작거나 같다면 result를 1 증가 시킨다.\r\n\r\n전체코드는 다음과 같다.\r\n```python\r\nimport sys;\r\ninput = sys.stdin.readline;\r\n\r\nn,k,p,x = map(int, input().split());\r\nresult = 0;\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n\r\nx = list(str(x));\r\nif len(x) != k:\r\n\t# k 보다 자릿수 x가 자릿수가 작다면 작은 만큼 앞에 0을 채워주어야 한다.\r\n for _ in range(k-len(x)):\r\n x.insert(0,'0');\r\n \r\ndef dfs(index,count,st):\r\n global result;\r\n if count>p:\r\n return;\r\n if index == k:\r\n if 0 {\r\n const [,triggerRender] = useState()\r\n let state = 'hello'\r\n\r\n function handleButtonClick() {\r\n state = 'hi'\r\n triggerRender()\r\n }\r\n return (\r\n <>\r\n

{state}

\r\n \r\n \r\n )\r\n}\r\n```\r\nuseState 반환값의 두 번째 원소를 실행해 리액트에 렌더링이 일어나게끔 변경했다. \r\n그럼에도 여전히 버튼 클릭시 state의 변경된 값이 렌더링되고 있지 않다. \r\n\r\n그 이유는 리액트의 렌더링은 **함수 컴포넌트에서 반환한 결과물인 return의 값을 비교해 실행되기 때문이다.** \r\n\r\n즉, 매번 렌더링이 발생할 때마다 함수는 새롭게 실행이 되고, 실행한 함수에서 state는 매번 hello로 초기화 되므로 아무리 state를 변경해도 hello로 초기화 되는 것이다. \r\n\r\n근데 렌더링이 될 때마다 초기화되는 변수(값)와는 달리, useState의 결과값은 어떻게 그 값을 유지할까?\r\n\r\nuseState의 결과 값이 유지되도록, state를 함수로 하여 state 값을 호출할 때마다 현재 state를 반환하게 해보자.\r\n```js\r\nfunction useState(initialValue) {\r\n\tlet initialState = initialValue;\r\n\t\r\n\tfunction state() {\r\n\t\treturn initialState\r\n\t}\r\n\tfunction setState(newValue) {\r\n\t\tinitialState = newValue\r\n\t}\r\n\treturn [state, setState];\r\n}\r\nconst [value, setState] = useState(0);\r\nsetValue(1);\r\nconsole.log(value()); // 1\r\n```\r\n위의 코드도 나쁘진 않지만, 우리에게 익숙한 useState훅은 state를 함수가 아닌 상수처럼 사용하고 있다.\r\n\r\n## 클로저를 이용해 상태를 관리하는 useState\r\n이를 위해서 리액트는 **클로저**를 이용한 것이다. \r\nuseState는 클로저를 통해 useState 내부의 선언된 함수(setState)가 함수의 실행이 종료된 이후(useState가 호출된 이후)에도 지역변수인 state를 계속 참조할 수 있다.\r\n\r\nuseState 작동 방식을 대략적으로 흉내 낸 코드는 다음과 같다.\r\n\r\n```js\r\nconst MyReact = (function() {\r\n\tconst global = {}\r\n let index = 0\r\n \r\n function useState(initialState){\r\n \tif(!global.states) {\r\n \t// 애플리케이션 전체의 states 배열 초기화, 최초 접근이면 빈 배열로\r\n \tglobal.states = []\r\n }\r\n // states 정보를 조회해서, 현재 상태값이 있는지 확인\r\n // 없다면 초깃값으로 설정\r\n const currentState = global.states[index] || initialState\r\n // 위에서 조회한 값으로 states의 값 업데이트\r\n global.states[index] = currentState\r\n \r\n // 즉시실행함수로 setter 만듬\r\n const setState = (function() {\r\n \t// 클로저로 index를 가둬두어서 동일한 index에 접근이 가능\r\n \tlet currentIndex = index\r\n return function(value){\r\n \tglobal.states[currentIndex] = value\r\n //컴포넌트 렌더링이 들어가는 부분이다.(실제 코드는 생략)\r\n }\r\n })()\r\n // useState를 쓸 때마다 index를 하나씩 추가하는데, 이는 하나의 state마다\r\n // index가 할당되어있어, 그 index가 배열의 값(global.states)를 가리키고,\r\n // 필요할 때마다 그 값을 가져오게 하는 것이다.\r\n index = index + 1\r\n \r\n return [currentState,setState]\r\n}\r\n\r\nfunction Component() {\r\n\tconst [value, setValue] = useState(0);\r\n}\r\n})();\r\n```\r\n\r\n실제 리액트 코드에서는 useReducer를 이용해 구현되어 있어 약간의 차이가 있다.\r\n\r\n아무튼 여기서 함수의 실행이 끝났음에도 함수가 선언된 환경을 기억할 수 있는 방법이 바로 클로저인 것이다. 만약 클로저가 없다면, `setState`는 항상 `index`의 현재 값에 의존하게 된다. 즉, 컴포넌트가 여러 상태를 갖고 있을 때 마지막 `index`만 참조하므로, `setState`가 올바른 위치를 참조하지 않게 되는 것이다.\r\n\r\n매번 실행되는 함수 컴포넌트 환경에서 state의 값을 유지하고 사용하기 위해 리액트는 클로저를 활용하고 있다.\r\n\r\n`\r\n훅에 대한 구현체를 github에서 타고 올라가다보면 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 라는 문구를 만나게된다(무섭다 ㅋㅋ)\r\n위의 코드는 Preact의 구현을 기준으로 하고 있다. Preact는 react의 경량화 버전으로,\r\n대부분의 리액트 API를 지원하고 있다. \r\n`\r\n## 결론\r\nReact의 `useState`는 클로저를 통해 상태값을 안정적으로 유지하며, 함수 컴포넌트가 여러 번 호출되더라도 **각 상태값이 고유한 위치에 저장**될 수 있게 한다. `useState`가 반환하는 `setState` 함수는 생성 당시의 상태 위치(`index`)를 클로저로 캡처하여, 해당 상태값만 정확히 업데이트하도록 구현되어 있다.\r\n\r\n정리하자면, 클로저는 `setState`가 함수가 선언된 당시의 환경을 유지하게 해주기 때문에 **컴포넌트가 매번 재실행될 때마다 상태가 초기화되는 것을 방지**하고, 상태가 올바르게 유지될 수 있게 해준다.\r\n\r\n**참고**\r\n\r\n[서적] 모던 리액트 Deep Dive\r\n"},{"slug":"posts/Javascript/클로저에 대하여","title":"클로저에 대하여","date":"2024-10-25T20:00:24.000Z","image":"index.png","summary":"자바스크립트의 어렵지만 중요한 클로저의 개념과 활용 이해해보자","tags":["JavaScript","deepdive","클로저","생명주기"],"content":"# 클로저에 대하여\r\n\r\n면접 질문 중 단골이고, 자바스크립트에 관심이 있다면 한번쯤 들어봤을 개념인 **클로저**.\r\n\r\n사실 많이 난해한 개념이기도 하고, 필자 역시 전에 한번 공부를 해보았지만 아직 확실히 와닿지는 않는 개념이다. \r\n\r\n그래서 이번 기회에 제대로 정리하고 넘어가고자 한다. 함께 이 개념이 대체 뭔지 살펴보자.\r\n\r\n## 클로저의 정의\r\n> 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.\r\n\r\n'이게 뭔소리지?' 싶은가? 나도 그러하다. 위의 정의에서 이해하여야 할 핵심 키워드는 **함수가 선언된 렉시컬 환경**이다.\r\n\r\n ```js\r\n const x = 1;\r\n function outerFunc( ) {\r\n\t const x = 10;\r\n\t function innerFunc( ) {\r\n\t\t console.log(x); // 10\r\n\t}\r\n\tinnerFunc( );\r\n}\r\nouterFunc( );\r\n```\r\n`outerFunc` 내부에서 중첩 함수 `innerFunc`가 정의되고 호출되었다. \r\n\r\n따라서 중첩 함수 `innerFunc` 내부에서 자신을 포함하고 있는 `outerFunc`의 x 변수에 접근할 수 있다. **만약 innerFunc 함수가 outerFunc의 내부에서 정의되지 않았다면, 즉 외부에서 별도로 정의 되었다면** innerFunc를 outerFunc 내부에서 호출해도 outerFunc 함수의 변수에 접근이 불가능하다.\r\n\r\n ```js\r\n const x = 1;\r\n function outerFunc( ) {\r\n\t const x = 10;\r\n\t// 안에서 호출되었지만 접근 불가능\r\n\t innerFunc( );\r\n}\r\nfunction innerFunc( ) {\r\n\t// 상위 스코프인 전역에서 선언된 1\r\n\tconsole.log(x); // 1\r\n}\r\nouterFunc( );\r\n```\r\n\r\n위와 같은 현상은 자바스크립트가 **렉시컬 스코프**를 따르기에 발생한다.\r\n\r\n## 렉시컬 스코프\r\n자바스크립트 엔진은 함수를 **어디서 호출했느냐**가 아니라 함수를 **어디서 정의했는지**에 따라 **상위 스코프를 결정** 한다. \r\n\r\n이를 **렉시컬 스코프**라고 한다.\r\n\r\n위의 예제코드를 다시한번 본다면, outerFunc와 innerFunc는 모두 전역에서 정의 되었고, 함수의 상위 스코프는 함수를 어디서 정의했는지에 따라 결정되므로 **두 함수의 상위 스코프는 모두 전역이다.**\r\n\r\n함수의 상위 스코프는 결국, **함수의 정의된 위치에 따라 정적으로 결정**되고, 함수의 호출된 위치는 어떠한 영향도 주지 못한다.\r\n\r\n자바스크립트에서 스코프의 실체는 실행 콘텍스트의 렉시컬 환경이고, 이 렉시컬 환경은 자신의 **외부 렉시컬 환경에 대한 참조**를 통해 상위 렉시컬 환경과 연결이된다.\r\n\r\n>렉시컬환경: **변수를 저장하고 외부 스코프와 연결을 유지하는 객체**라고 생각하면된다. 자바스크립트에서는 함수가 생성될 때마다 렉시컬 환경이 만들어지며, 함수 내부의 변수뿐 아니라 함수가 선언된 위치에 있는 외부 변수도 기억하게된다.\r\n>\r\n> 코드가 위치한 곳에 따라 **변수와 함수를 어디서 찾아볼지 알려주는 일종의 \"지도\"**라고 생각할 수도 있다. \r\n\r\n따라서 함수의 상위 스코프를 결정한다는 것은, 현재 함수의 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다는 것을 의미한다.\r\n\r\n렉시컬 스코프를 다시한번 정의해보자면, 렉시컬 환경의 \"외부 렉시컬 환경에 대한 참조\"에 저장한 참조값, 즉 상위 스코프에 대한 참조는 **함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)**에 의해 결정되는 것이라고 할 수 있다. \r\n\r\n\r\n\r\n**함수는 자신의 내부슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.** \r\n이곳을 참조해서 자신이 호출되었을 때 생성될 함수 렉시컬환경의 \"외부 렉시컬 환경에 대한 참조\"에 저장될 참조값을 보고, 자신이 존재하는 한, 이 [[Environment]] 슬롯에 저장한 렉시컬 환경의 참조, 즉 **상위 스코프**를 기억한다.\r\n\r\n## 클로저와 렉시컬환경\r\n그렇다면 다음의 코드를 살펴보자\r\n```js\r\nconst x = 1 ;\r\nfunction outer() {\r\n\tconst x = 10;\r\n\tconst inner = function ( ) {console.log(x)}\r\n\t//inner함수 반환\r\n\treturn inner;\r\n}\r\n// outer함수를 호출하면 중첩 함수 inner를 반환한다.\r\n// 그리고 outer 함수의 실행 컨텍스트는 제거된다.\r\nconst innerFunc = outer( );\r\ninnerFunc( )// 10\r\n```\r\nouter함수를 호출하면 outer함수는 중첩함수 inner를 반환하고 생명주기를 마감한다. \r\n\r\n즉 outer함수의 실행이 종료되었으므로, 실행컨텍스트가 제거된다. (실행컨텍스트 스택에서 pop된다.)\r\n\r\n이때 outer 함수의 지역변수x 역시 생명주기를 마감했으므로, 실행 컨텍스트가 제거되어 유효하지 않아 보인다.\r\n\r\n그러나 위의 실행 결과는 outer 지역 변수x 의 값인 10을 반환한다. 이미 생명 주기가 종료되어 outer 함수의 지역변수 x가 실행 컨텍스트 스택에서 제거되었는데도 다시 부활이라도 한 것 마냥 말이다. \r\n\r\n이처럼 **외부 함수보다 중첩함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명주기가 종료한 외부함수의 변수를 참조**할 수 있다. \r\n\r\n이러한 **중첩 함수를 클로저**라고 부른다.\r\n\r\n다시 정의로 돌아가보자.\r\n> 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.\r\n\r\n위 정의를 예제에 대입해보자면 `함수`는 반환된 `중첩함수(innerFunc)`를 의미하고 `그 함수가 선언될 때의 렉시컬 환경(Lexical environment)`란 그 `중첩 함수(innerFunc)가 정의됐을 때의 스코프`를 의미하는 것이다.\r\n\r\n즉, **클로저는 반환된 중첩 함수가 자신이 선언됐을 때의 렉시컬 환경 즉, 스코프를 기억하여 자신이 선언됐을 때의 렉시컬 환경 밖에서 호출되어도 그 렉시컬 환경(스코프)에 접근할 수 있는 함수**를 말한다. \r\n\r\n조금 더 간단히 말하면 **클로저는 자신이 생성될 때의 상위 스코프(렉시컬 환경)을 기억하는 함수이다**\r\n\r\n\r\n\r\n\r\n위 그림처럼 inner함수의 [[Environment]] 내부 슬롯에 의해 outer의 렉시컬 환경(outer Lexical Environment)가 참조되어 있다. inner함수는 전역 변수 innerFunc에 의해 참조되어있으므로, 가비지 컬렉터의 가비지 컬렉션의 대상이 되지 않는다.\r\n\r\n\r\n> **가비지 컬렉터(Garbage Collector)는 프로그램이 더 이상 사용하지 않는 메모리를 자동으로 해제해 주는 자바스크립트 엔진의 기능**이다.\r\n> \r\n> 가비지 컬렉터는 특정 메모리 공간이 더 이상 참조되지 않을 때 그 공간을 \"가비지\"로 판단하여 메모리를 해제한다. 반대로, **누군가가 참조하고 있는 메모리 공간은 함부로 해제하지 않는다**.\r\n\r\n클로저는 자바스크립트의 강력한 기능으로, 필요하다면 적극 활용해야 한다. 클로저가 유용하게 사용되는 상황을 살펴보자.\r\n\r\n## 클로저의 활용\r\n\r\n### 상태를 안전하게 변경하고 유지할 때\r\n\r\n클로저는 **상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고, 특정 함수에게만 상태 변경을 허용하여, 상태를 안전하게 변경하고 유지할 수 있도록 사용한다.**\r\n```js\r\nconst counter = (function ( ) {\r\n// 은닉된 상태 (외부에서 접근 불가)\r\nlet num = 0;\r\n// 클로저인 메서드를 갖는 객체를 반환한다.\r\n// 객체 리터럴은 스코프를 만들지 않는다.\r\n// 따라서 아래 메서드들의 상위 스코프는 즉시 실행 함수의 렉시컬 환경이다.\r\nreturn {\r\n\tincrease() {\r\n\t\treturn ++num;\r\n\t}\r\n\tdecrease() {\r\n\t\treturn num>0? --num: 0;\r\n\t}\r\n}());\r\n\r\nconsole.log(counter.increase()); // 1\r\nconsole.log(counter.decrease()); // 2\r\n\r\nconsole.log(counter.decrease()); // 1\r\nconsole.log(counter.decrease()); // 0\r\n```\r\n즉시 실행 함수는 호출된 이후 소멸되지만, 즉시 실행 함수가 반환한 클로저(increase, decrease)는 **자신의 상위 스코프인 즉시 실행함수의 렉시컬 환경을 기억하고 있다**. \r\n\r\n이 코드에서 \r\n- 카운터 상태(num 변수의 값)은 increase, decrease 함수가 호출되기 전까지 변경되지않고 유지되며 **외부에서 접근할 수 없다**.\r\n- 카운터 상태는 오직 **increase, decrease로 정의된 함수로만 변경이 가능**하다.\r\n\r\n\r\n\r\n이처럼 클로저는 **상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고 특정함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용**된다.\r\n\r\n### 전역변수의 사용을 억제할 때\r\n\r\n클로저는 전역 변수 사용을 억제하고 대신 **함수 내부의 변수로 상태를 관리**할 수 있도록 도와준다. 이렇게 하면 전역 변수를 사용하지 않고도 데이터가 안전하게 유지되며, 다른 코드와 충돌하지 않는 이점을 얻을 수 있다.\r\n\r\n```js\r\nlet counter = 0; // 전역 변수\r\n\r\nfunction incrementCounter() {\r\n counter += 1;\r\n return counter;\r\n}\r\n\r\nconsole.log(incrementCounter()); // 1\r\nconsole.log(incrementCounter()); // 2\r\nconsole.log(counter); // 전역 변수에 접근 가능 (위험)\r\n```\r\n위 코드에서는 `counter`가 전역에 선언되어 있기 때문에 어디서든 접근 가능하여, 이러면 다른 코드에서 `counter`를 실수로 변경할 위험이 있다.\r\n```js\r\nfunction createCounter() {\r\n let counter = 0; // 함수 내부 변수로 관리\r\n\r\n return function() {\r\n counter += 1;\r\n return counter;\r\n };\r\n}\r\n\r\nconst incrementCounter = createCounter();\r\n\r\nconsole.log(incrementCounter()); // 1\r\nconsole.log(incrementCounter()); // 2\r\nconsole.log(typeof counter); // 'undefined' - 전역에서 접근 불가\r\n```\r\n\r\n이 코드에서는 `counter` 변수가 **`createCounter` 함수 내부에만 존재**하므로 외부에서 직접 접근하거나 수정할 수 없다. \r\n\r\n대신, `incrementCounter` 함수는 **클로저를 통해 `counter`를 기억**하고 있으므로 호출할 때마다 `counter`를 안전하게 증가시킬 수 있다.\r\n\r\n이처럼, 클로저를 사용하면 함수 내 지역 변수를 통해 상태를 관리하게 되어 **전역 변수를 사용하지 않아도 안전하게 데이터 상태를 유지**할 수 있다.\r\n\r\n### React의 useState\r\n\r\n이런 이점을 활용하여 react의 useState에도 클로저가 활용된다.\r\n\r\n`useState`를 사용하면 컴포넌트 내에서 **상태를 관리**하게 되는데, 이 상태가 **컴포넌트가 렌더링될 때마다 유지**되도록, 또한 `setState` 함수로만 상태가 변경되도록 하는 데에 클로저가 활용되는 것이다.\r\n\r\n이와 관련하여서는 다음 포스팅에서 자세하게 다룰 예정이다.\r\n\r\n\r\n## 결론\r\n\r\n지금까지 자바스크립트의 어렵지만 주요한 개념인 클로저에 대해 살펴보았다.\r\n\r\n**클로저**는 **함수와 그 함수가 선언된 렉시컬 환경의 조합으로, 자바스크립트에서 함수는 자신이 정의된 위치에 따라 상위 스코프를 결정하는 렉시컬 스코프**를 따르므로, \r\n중첩 함수가 외부 함수의 스코프를 참조하여 외부함수가 생명주기가 끝났음에도 그 함수의 변수를 참조할 수 있는 함수를 의미한다."}]},"__N_SSG":true} \ No newline at end of file diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.json" "b/_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.json" similarity index 100% rename from "_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.json" rename to "_next/data/6z_NmOq0sgJymZX5w6fz3/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.json" diff --git a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/Algorithm.json b/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/Algorithm.json deleted file mode 100644 index 3f59bb1..0000000 --- a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/Algorithm.json +++ /dev/null @@ -1 +0,0 @@ -{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색","all"],"currentTag":"Algorithm","posts":[{"slug":"posts/Algorithm/[백준 gold 5] 빌런 호석","title":"[백준 gold 5] 빌런 호석","date":"2024-08-09T17:05:24.000Z","image":"index.png","summary":"dfs을 활용한 프로그래머스 [level 3] 징검다리 건너기 문제 풀이 입니다.","tags":["Algorithm","백준","gold","dfs"],"content":"# [gold 3] 빌런 호석\r\n\r\n## 문제 설명\r\n\r\n치르보기 빌딩은 11층부터 NN층까지 이용이 가능한 엘리베이터가 있다. 엘리베이터의 층수를 보여주는 디스플레이에는 KK 자리의 수가 보인다. 수는 00으로 시작할 수도 있다. 00부터 99까지의 각 숫자가 디스플레이에 보이는 방식은 아래와 같다. 각 숫자는 7개의 표시등 중의 일부에 불이 들어오면서 표현된다.\r\n\r\n![](1.png)\r\n\r\n예를 들어 K=4K=4인 경우에 16801680층과 501501층은 아래와 같이 보인다.\r\n\r\n![](2.png)\r\n\r\n\r\n\r\n빌런 호석은 치르보기 빌딩의 엘리베이터 디스플레이의 LED 중에서 최소 11개, 최대 PP개를 반전시킬 계획을 세우고 있다. 반전이란 켜진 부분은 끄고, 꺼진 부분은 켜는 것을 의미한다. 예를 들어 숫자 11을 22로 바꾸려면 총 5개의 LED를 반전시켜야 한다. 또한 반전 이후에 디스플레이에 올바른 수가 보여지면서 11 이상 NN 이하가 되도록 바꿔서 사람들을 헷갈리게 할 예정이다. 치르보기를 사랑하는 모임의 회원인 당신은 호석 빌런의 행동을 미리 파악해서 혼쭐을 내주고자 한다. 현재 엘리베이터가 실제로는 XX층에 멈춰있을 때, 호석이가 반전시킬 LED를 고를 수 있는 경우의 수를 계산해보자.\r\n\r\n### 입력\r\n\r\n N,K,P,XN,K,P,X 가 공백으로 구분되어 첫째 줄에 주어진다.\r\n\r\n### 출력\r\n\r\n호석 빌런이 엘리베이터 LED를 올바르게 반전시킬 수 있는 경우의 수를 계산해보자.\r\n\r\n## 접근 방법\r\n\r\n숫자에 따른 LED를 먼저 구현하기 위해, \r\n\r\n그림과 같이, 각 LED의 위치에 번호를 매겨, 배열안에 그 번호가 있으면 불이 켜져있는 것으로, 없다면 불이 꺼져 있는 것으로 표현하였다.\r\n\"이미지\r\n\r\n\r\n그림처럼 0을 표현하면 3번자리를 제외한 모든 번호가 켜져있으므로, `[0,1,2,4,5,6]`으로 표현 할 수 있다.\r\n\r\n각 번호를 이와 같이 바꾸어 numbers 배열에 저장하면, 이와 같다.\r\n```python\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n```\r\n이후 만일 현재 번호와 비교할 번호의 LED를 비교하기 위해 서로의 차집합을 더해서 두 번호가 서로를 비교했을 때, 가지고 있는 혹은 없는 번호의 개수를 구한다.\r\n```python\r\ncur_count = len(list(cur.difference(compare))) + len(list(compare.difference(cur)));\r\n```\r\n이와 같은 방식으로 반전시킬 LED의 개수를 구하고, dfs를 활용하여 x의 모든 자릿수를 순회하여 p보다 작거나 같게 LED를 반전하면서, n보다 번호가 작거나 같다면 result를 1 증가 시킨다.\r\n\r\n전체코드는 다음과 같다.\r\n```python\r\nimport sys;\r\ninput = sys.stdin.readline;\r\n\r\nn,k,p,x = map(int, input().split());\r\nresult = 0;\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n\r\nx = list(str(x));\r\nif len(x) != k:\r\n\t# k 보다 자릿수 x가 자릿수가 작다면 작은 만큼 앞에 0을 채워주어야 한다.\r\n for _ in range(k-len(x)):\r\n x.insert(0,'0');\r\n \r\ndef dfs(index,count,st):\r\n global result;\r\n if count>p:\r\n return;\r\n if index == k:\r\n if 0\r\n \r\nrectangle\r\ncharacterX\r\ncharacterY\r\nitemX\r\nitemY\r\nresult\r\n\r\n\r\n \r\n[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]]\r\n1\r\n3\r\n7\r\n8\r\n17\r\n\r\n\r\n[[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]]\r\n9\r\n7\r\n6\r\n1\r\n11\r\n\r\n\r\n[[1,1,5,7]]\r\n1\r\n1\r\n4\r\n7\r\n9\r\n\r\n\r\n[[2,1,7,5],[6,4,10,10]]\r\n3\r\n1\r\n7\r\n10\r\n15\r\n\r\n\r\n[[2,2,5,5],[1,3,6,4],[3,1,4,6]]\r\n1\r\n4\r\n6\r\n3\r\n10\r\n\r\n\r\n \r\n\r\n##### 입출력 예 설명\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/87694.%E2%80%85%EC%95%84%EC%9D%B4%ED%85%9C%E2%80%85%EC%A4%8D%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88-%EC%84%A4%EB%AA%85)\r\n\r\n입출력 예 #1\r\n\r\n![rect_5.png](6.png)\r\n\r\n캐릭터 위치는 (1, 3)이며, 아이템 위치는 (7, 8)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #2\r\n\r\n![rect_7.png](7.png)\r\n\r\n캐릭터 위치는 (9, 7)이며, 아이템 위치는 (6, 1)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n입출력 예 #3\r\n\r\n[![rect_8.png](8.png)]\r\n\r\n캐릭터 위치는 (1, 1)이며, 아이템 위치는 (4, 7)입니다. 위 그림과 같이 굵은 선을 따라 이동하는 경로가 가장 짧습니다.\r\n\r\n## 구현 방법\r\n### 전체 직사각형들을 합친 것의 바깥쪽 테두리만 돌게하려면 어떻게 하는가?\r\n- rectangle을 순회하면서 범위 중 직사각형 내부는 0으로 테두리는 1로 board값을 갱신한다.\r\n- 이 때, 만일 `다른 직사각형의 내부안에 현재 직사각형의 테두리가 있지 않을 경우`에만 board를 1로 갱신한다. \r\n### 예외 사항\r\n![exception.png](exception.png)\r\n좌표가 인접한 경우 위와 같이 의도하지 않은 경우를 초래할 수도 있다.\r\n\r\n따라서 이를 해결하기 위해 모든 좌표의 값을 **2배**씩 해주어야 한다.\r\n\r\n이를 모두 반영하여 board 테이블을 만들면,\r\n\r\n```python\r\nboard = [[-1 for _ in range(102)] for _ in range(102)];\r\nfor r in rectangle:\r\n\t# map 객체를 통해 모든 좌표값에 2배\r\n\tx1,y1,x2,y2 = map(lambda x: x*2,r);\r\n for i in range(x1,x2+1):\r\n for j in range(y1,y2+1):\r\n\t # 직사각형 내부의 경우 0으로 개신\r\n if x1\r\n \r\nstones\r\nk\r\nresult\r\n\r\n\r\n \r\n[2, 4, 5, 3, 2, 1, 4, 2, 5, 1]\r\n3\r\n3\r\n\r\n\r\n \r\n\r\n##### **입출력 예에 대한 설명**\r\n\r\n[](https://github.com/phnml1/CodingTest/blob/master/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/3/64062.%E2%80%85%EC%A7%95%EA%B2%80%EB%8B%A4%EB%A6%AC%E2%80%85%EA%B1%B4%EB%84%88%EA%B8%B0/README.md#%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%98%88%EC%97%90-%EB%8C%80%ED%95%9C-%EC%84%A4%EB%AA%85)\r\n\r\n----------\r\n\r\n**입출력 예 #1**\r\n\r\n첫 번째 친구는 다음과 같이 징검다리를 건널 수 있습니다. \r\n![1.png](1.png)\r\n\r\n첫 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n두 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![2.png](2.png)\r\n\r\n두 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n세 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다. \r\n![3.png](3.png)\r\n\r\n세 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다. \r\n네 번째 친구가 징검다리를 건너려면, 세 번째 디딤돌에서 일곱 번째 디딤돌로 네 칸을 건너뛰어야 합니다. 하지만 k = 3 이므로 건너뛸 수 없습니다. \r\n![4.png](4.png)\r\n\r\n따라서 최대 3명이 디딤돌을 모두 건널 수 있습니다.\r\n\r\n## 접근 방법\r\n브루트 포스로 1명씩 건너기에는, stones 배열의 크기가 최대 200,000이고, stones 배열의 각 원소들의 값 역시 최대 200,000,000이기 때문에, 시간 초과가 날 확률이 높다고 생각했고(사실 그렇게 쉬우면 lv3 일리가 없지), 아니나 다를까 시간초과가 났다. \r\n\r\n고민하다가 도저히 해결책이 안나와서 찾아보니 `이분탐색`을 사용하여 풀 수 있었다.\r\n\r\n- 건널 수 있는 인원의 최소는 1명, 최대는 max(stones)명이다. 모든 돌들의 합이 같거나, 다르다 하더라도 건널수 없는 곳이 k이하면 건널 수 있기 때문이다. \r\n- 따라서 start = 1 end = max(stones)로 이분탐색을 시작할 수 있다.\r\n\r\nmid 값만큼의 사람이 건널 수 있는지 확인하기 위한 check함수는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n\t # 밟을 수 없으므로 건너뛰어야하는 횟수를 늘린다.\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n # 밟을 수 있으므로 최대 건너뛰는 횟수를 초기화시킨다.\r\n else:\r\n cnt = 0;\r\n # 건너뛰는 횟수가 k보다 크거나 같으면 안되므로 False 리턴 \r\n if cnt>=k:\r\n return False;\r\n return True;\r\n```\r\n건널 수 있다면 mid보다 큰 범위에서 값을 찾아야하므로 start를 mid+1로 갱신하고, 반대라면, mid보다 작은 범위에서 값을 찾아야하므로 end를 mid-1로 갱신한다.\r\n \r\ncheck 시간 복잡도는 O(N)이고 이분탐색을 했을 때 O(logN)의 시간복잡도가 나오므로, 총 O(NlogN)의 시간 복잡도가 나오므로, 시간초과가 나지 않는다.\r\n\r\n전체 코드는 다음과 같다.\r\n```python\r\ndef check(stones, mid,k):\r\n cnt = 0;\r\n for stone in stones:\r\n if (stone - mid) <= 0:\r\n cnt += 1;\r\n else:\r\n cnt = 0;\r\n if cnt>=k:\r\n return False;\r\n return True;\r\n\r\ndef solution(stones, k):\r\n start,end = 1,max(stones);\r\n answer = 0;\r\n while start<=end:\r\n mid = (start + end) // 2;\r\n if check(stones, mid,k):\r\n start = mid+1;\r\n else:\r\n answer = mid;\r\n end = mid-1; \r\n return answer;\r\n```\r\n\r\n## 느낀 점\r\n이분탐색 문제를 많이는 아니더라도 어느정도는 풀어봤다고 생각했는데, 이 문제에서 이분탐색으로 푸는 아이디어를 떠올리지 못해서 아쉽다. \r\n\r\n또한 처음에 위에 코드의 6번째줄에서 else문을 쓰지않고, 이러한 코드로 제출하여서 시간초과가 났다.\r\n```python\r\nif (stone - mid) <= 0:\r\n\tcnt += 1;\r\nif (stone - mid)>0:\r\n\tcnt = 0;\r\n```\r\nㅎㅎ.. 사실 위와 같은 경우에서 if else문을 쓰는 것이 기본인데, 그래도 시간초과가 날 수 있는 직접적인 원인까지는 되지 않을 거라고 안일하게 생각해서 코드를 짠 게 화근이었다. 기본을 지키자!"}]},"__N_SSG":true} \ No newline at end of file diff --git "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/\353\260\261\354\244\200.json" "b/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/\353\260\261\354\244\200.json" deleted file mode 100644 index b351142..0000000 --- "a/_next/data/RYnp_NyzrQPZMofDPtHX9/posts/tag/\353\260\261\354\244\200.json" +++ /dev/null @@ -1 +0,0 @@ -{"pageProps":{"tags":["react","JavaScript","deepdive","useState","hook","클로저","생명주기","Virtual DOM","Algorithm","백준","gold","dfs","프로그래머스","lv3","bfs","이분탐색"],"currentTag":"백준","posts":[{"slug":"posts/Algorithm/[백준 gold 5] 빌런 호석","title":"[백준 gold 5] 빌런 호석","date":"2024-08-09T17:05:24.000Z","image":"index.png","summary":"dfs을 활용한 프로그래머스 [level 3] 징검다리 건너기 문제 풀이 입니다.","tags":["Algorithm","백준","gold","dfs"],"content":"# [gold 3] 빌런 호석\r\n\r\n## 문제 설명\r\n\r\n치르보기 빌딩은 11층부터 NN층까지 이용이 가능한 엘리베이터가 있다. 엘리베이터의 층수를 보여주는 디스플레이에는 KK 자리의 수가 보인다. 수는 00으로 시작할 수도 있다. 00부터 99까지의 각 숫자가 디스플레이에 보이는 방식은 아래와 같다. 각 숫자는 7개의 표시등 중의 일부에 불이 들어오면서 표현된다.\r\n\r\n![](1.png)\r\n\r\n예를 들어 K=4K=4인 경우에 16801680층과 501501층은 아래와 같이 보인다.\r\n\r\n![](2.png)\r\n\r\n\r\n\r\n빌런 호석은 치르보기 빌딩의 엘리베이터 디스플레이의 LED 중에서 최소 11개, 최대 PP개를 반전시킬 계획을 세우고 있다. 반전이란 켜진 부분은 끄고, 꺼진 부분은 켜는 것을 의미한다. 예를 들어 숫자 11을 22로 바꾸려면 총 5개의 LED를 반전시켜야 한다. 또한 반전 이후에 디스플레이에 올바른 수가 보여지면서 11 이상 NN 이하가 되도록 바꿔서 사람들을 헷갈리게 할 예정이다. 치르보기를 사랑하는 모임의 회원인 당신은 호석 빌런의 행동을 미리 파악해서 혼쭐을 내주고자 한다. 현재 엘리베이터가 실제로는 XX층에 멈춰있을 때, 호석이가 반전시킬 LED를 고를 수 있는 경우의 수를 계산해보자.\r\n\r\n### 입력\r\n\r\n N,K,P,XN,K,P,X 가 공백으로 구분되어 첫째 줄에 주어진다.\r\n\r\n### 출력\r\n\r\n호석 빌런이 엘리베이터 LED를 올바르게 반전시킬 수 있는 경우의 수를 계산해보자.\r\n\r\n## 접근 방법\r\n\r\n숫자에 따른 LED를 먼저 구현하기 위해, \r\n\r\n그림과 같이, 각 LED의 위치에 번호를 매겨, 배열안에 그 번호가 있으면 불이 켜져있는 것으로, 없다면 불이 꺼져 있는 것으로 표현하였다.\r\n\"이미지\r\n\r\n\r\n그림처럼 0을 표현하면 3번자리를 제외한 모든 번호가 켜져있으므로, `[0,1,2,4,5,6]`으로 표현 할 수 있다.\r\n\r\n각 번호를 이와 같이 바꾸어 numbers 배열에 저장하면, 이와 같다.\r\n```python\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n```\r\n이후 만일 현재 번호와 비교할 번호의 LED를 비교하기 위해 서로의 차집합을 더해서 두 번호가 서로를 비교했을 때, 가지고 있는 혹은 없는 번호의 개수를 구한다.\r\n```python\r\ncur_count = len(list(cur.difference(compare))) + len(list(compare.difference(cur)));\r\n```\r\n이와 같은 방식으로 반전시킬 LED의 개수를 구하고, dfs를 활용하여 x의 모든 자릿수를 순회하여 p보다 작거나 같게 LED를 반전하면서, n보다 번호가 작거나 같다면 result를 1 증가 시킨다.\r\n\r\n전체코드는 다음과 같다.\r\n```python\r\nimport sys;\r\ninput = sys.stdin.readline;\r\n\r\nn,k,p,x = map(int, input().split());\r\nresult = 0;\r\nnumbers = [[0,1,2,4,5,6],[2,5],[0,2,3,4,6],[0,2,3,5,6],[1,2,3,5],[0,1,3,5,6],[0,1,3,4,5,6],[0,2,5],[0,1,2,3,4,5,6],[0,1,2,3,5,6]];\r\n\r\nx = list(str(x));\r\nif len(x) != k:\r\n\t# k 보다 자릿수 x가 자릿수가 작다면 작은 만큼 앞에 0을 채워주어야 한다.\r\n for _ in range(k-len(x)):\r\n x.insert(0,'0');\r\n \r\ndef dfs(index,count,st):\r\n global result;\r\n if count>p:\r\n return;\r\n if index == k:\r\n if 0 {\r\n const [,triggerRender] = useState()\r\n let state = 'hello'\r\n\r\n function handleButtonClick() {\r\n state = 'hi'\r\n triggerRender()\r\n }\r\n return (\r\n <>\r\n

{state}

\r\n \r\n \r\n )\r\n}\r\n```\r\nuseState 반환값의 두 번째 원소를 실행해 리액트에 렌더링이 일어나게끔 변경했다. \r\n그럼에도 여전히 버튼 클릭시 state의 변경된 값이 렌더링되고 있지 않다. \r\n\r\n그 이유는 리액트의 렌더링은 **함수 컴포넌트에서 반환한 결과물인 return의 값을 비교해 실행되기 때문이다.** \r\n\r\n즉, 매번 렌더링이 발생할 때마다 함수는 새롭게 실행이 되고, 실행한 함수에서 state는 매번 hello로 초기화 되므로 아무리 state를 변경해도 hello로 초기화 되는 것이다. \r\n\r\n근데 렌더링이 될 때마다 초기화되는 변수(값)와는 달리, useState의 결과값은 어떻게 그 값을 유지할까?\r\n\r\nuseState의 결과 값이 유지되도록, state를 함수로 하여 state 값을 호출할 때마다 현재 state를 반환하게 해보자.\r\n```js\r\nfunction useState(initialValue) {\r\n\tlet initialState = initialValue;\r\n\t\r\n\tfunction state() {\r\n\t\treturn initialState\r\n\t}\r\n\tfunction setState(newValue) {\r\n\t\tinitialState = newValue\r\n\t}\r\n\treturn [state, setState];\r\n}\r\nconst [value, setState] = useState(0);\r\nsetValue(1);\r\nconsole.log(value()); // 1\r\n```\r\n위의 코드도 나쁘진 않지만, 우리에게 익숙한 useState훅은 state를 함수가 아닌 상수처럼 사용하고 있다.\r\n\r\n## 클로저를 이용해 상태를 관리하는 useState\r\n이를 위해서 리액트는 **클로저**를 이용한 것이다. \r\nuseState는 클로저를 통해 useState 내부의 선언된 함수(setState)가 함수의 실행이 종료된 이후(useState가 호출된 이후)에도 지역변수인 state를 계속 참조할 수 있다.\r\n\r\nuseState 작동 방식을 대략적으로 흉내 낸 코드는 다음과 같다.\r\n\r\n```js\r\nconst MyReact = (function() {\r\n\tconst global = {}\r\n let index = 0\r\n \r\n function useState(initialState){\r\n \tif(!global.states) {\r\n \t// 애플리케이션 전체의 states 배열 초기화, 최초 접근이면 빈 배열로\r\n \tglobal.states = []\r\n }\r\n // states 정보를 조회해서, 현재 상태값이 있는지 확인\r\n // 없다면 초깃값으로 설정\r\n const currentState = global.states[index] || initialState\r\n // 위에서 조회한 값으로 states의 값 업데이트\r\n global.states[index] = currentState\r\n \r\n // 즉시실행함수로 setter 만듬\r\n const setState = (function() {\r\n \t// 클로저로 index를 가둬두어서 동일한 index에 접근이 가능\r\n \tlet currentIndex = index\r\n return function(value){\r\n \tglobal.states[currentIndex] = value\r\n //컴포넌트 렌더링이 들어가는 부분이다.(실제 코드는 생략)\r\n }\r\n })()\r\n // useState를 쓸 때마다 index를 하나씩 추가하는데, 이는 하나의 state마다\r\n // index가 할당되어있어, 그 index가 배열의 값(global.states)를 가리키고,\r\n // 필요할 때마다 그 값을 가져오게 하는 것이다.\r\n index = index + 1\r\n \r\n return [currentState,setState]\r\n}\r\n\r\nfunction Component() {\r\n\tconst [value, setValue] = useState(0);\r\n}\r\n})();\r\n```\r\n\r\n실제 리액트 코드에서는 useReducer를 이용해 구현되어 있어 약간의 차이가 있다.\r\n\r\n아무튼 여기서 함수의 실행이 끝났음에도 함수가 선언된 환경을 기억할 수 있는 방법이 바로 클로저인 것이다. 만약 클로저가 없다면, `setState`는 항상 `index`의 현재 값에 의존하게 된다. 즉, 컴포넌트가 여러 상태를 갖고 있을 때 마지막 `index`만 참조하므로, `setState`가 올바른 위치를 참조하지 않게 되는 것이다.\r\n\r\n매번 실행되는 함수 컴포넌트 환경에서 state의 값을 유지하고 사용하기 위해 리액트는 클로저를 활용하고 있다.\r\n\r\n`\r\n훅에 대한 구현체를 github에서 타고 올라가다보면 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 라는 문구를 만나게된다(무섭다 ㅋㅋ)\r\n위의 코드는 Preact의 구현을 기준으로 하고 있다. Preact는 react의 경량화 버전으로,\r\n대부분의 리액트 API를 지원하고 있다. \r\n`\r\n## 결론\r\nReact의 `useState`는 클로저를 통해 상태값을 안정적으로 유지하며, 함수 컴포넌트가 여러 번 호출되더라도 **각 상태값이 고유한 위치에 저장**될 수 있게 한다. `useState`가 반환하는 `setState` 함수는 생성 당시의 상태 위치(`index`)를 클로저로 캡처하여, 해당 상태값만 정확히 업데이트하도록 구현되어 있다.\r\n\r\n정리하자면, 클로저는 `setState`가 함수가 선언된 당시의 환경을 유지하게 해주기 때문에 **컴포넌트가 매번 재실행될 때마다 상태가 초기화되는 것을 방지**하고, 상태가 올바르게 유지될 수 있게 해준다.\r\n\r\n**참고**\r\n\r\n[서적] 모던 리액트 Deep Dive\r\n"},{"slug":"posts/Javascript/클로저에 대하여","title":"클로저에 대하여","date":"2024-10-25T20:00:24.000Z","image":"index.png","summary":"자바스크립트의 어렵지만 중요한 클로저의 개념과 활용 이해해보자","tags":["JavaScript","deepdive","클로저","생명주기"],"content":"# 클로저에 대하여\r\n\r\n면접 질문 중 단골이고, 자바스크립트에 관심이 있다면 한번쯤 들어봤을 개념인 **클로저**.\r\n\r\n사실 많이 난해한 개념이기도 하고, 필자 역시 전에 한번 공부를 해보았지만 아직 확실히 와닿지는 않는 개념이다. \r\n\r\n그래서 이번 기회에 제대로 정리하고 넘어가고자 한다. 함께 이 개념이 대체 뭔지 살펴보자.\r\n\r\n## 클로저의 정의\r\n> 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.\r\n\r\n'이게 뭔소리지?' 싶은가? 나도 그러하다. 위의 정의에서 이해하여야 할 핵심 키워드는 **함수가 선언된 렉시컬 환경**이다.\r\n\r\n ```js\r\n const x = 1;\r\n function outerFunc( ) {\r\n\t const x = 10;\r\n\t function innerFunc( ) {\r\n\t\t console.log(x); // 10\r\n\t}\r\n\tinnerFunc( );\r\n}\r\nouterFunc( );\r\n```\r\n`outerFunc` 내부에서 중첩 함수 `innerFunc`가 정의되고 호출되었다. \r\n\r\n따라서 중첩 함수 `innerFunc` 내부에서 자신을 포함하고 있는 `outerFunc`의 x 변수에 접근할 수 있다. **만약 innerFunc 함수가 outerFunc의 내부에서 정의되지 않았다면, 즉 외부에서 별도로 정의 되었다면** innerFunc를 outerFunc 내부에서 호출해도 outerFunc 함수의 변수에 접근이 불가능하다.\r\n\r\n ```js\r\n const x = 1;\r\n function outerFunc( ) {\r\n\t const x = 10;\r\n\t// 안에서 호출되었지만 접근 불가능\r\n\t innerFunc( );\r\n}\r\nfunction innerFunc( ) {\r\n\t// 상위 스코프인 전역에서 선언된 1\r\n\tconsole.log(x); // 1\r\n}\r\nouterFunc( );\r\n```\r\n\r\n위와 같은 현상은 자바스크립트가 **렉시컬 스코프**를 따르기에 발생한다.\r\n\r\n## 렉시컬 스코프\r\n자바스크립트 엔진은 함수를 **어디서 호출했느냐**가 아니라 함수를 **어디서 정의했는지**에 따라 **상위 스코프를 결정** 한다. \r\n\r\n이를 **렉시컬 스코프**라고 한다.\r\n\r\n위의 예제코드를 다시한번 본다면, outerFunc와 innerFunc는 모두 전역에서 정의 되었고, 함수의 상위 스코프는 함수를 어디서 정의했는지에 따라 결정되므로 **두 함수의 상위 스코프는 모두 전역이다.**\r\n\r\n함수의 상위 스코프는 결국, **함수의 정의된 위치에 따라 정적으로 결정**되고, 함수의 호출된 위치는 어떠한 영향도 주지 못한다.\r\n\r\n자바스크립트에서 스코프의 실체는 실행 콘텍스트의 렉시컬 환경이고, 이 렉시컬 환경은 자신의 **외부 렉시컬 환경에 대한 참조**를 통해 상위 렉시컬 환경과 연결이된다.\r\n\r\n>렉시컬환경: **변수를 저장하고 외부 스코프와 연결을 유지하는 객체**라고 생각하면된다. 자바스크립트에서는 함수가 생성될 때마다 렉시컬 환경이 만들어지며, 함수 내부의 변수뿐 아니라 함수가 선언된 위치에 있는 외부 변수도 기억하게된다.\r\n>\r\n> 코드가 위치한 곳에 따라 **변수와 함수를 어디서 찾아볼지 알려주는 일종의 \"지도\"**라고 생각할 수도 있다. \r\n\r\n따라서 함수의 상위 스코프를 결정한다는 것은, 현재 함수의 렉시컬 환경의 외부 렉시컬 환경에 대한 참조에 저장할 참조값을 결정한다는 것을 의미한다.\r\n\r\n렉시컬 스코프를 다시한번 정의해보자면, 렉시컬 환경의 \"외부 렉시컬 환경에 대한 참조\"에 저장한 참조값, 즉 상위 스코프에 대한 참조는 **함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)**에 의해 결정되는 것이라고 할 수 있다. \r\n\r\n\r\n\r\n**함수는 자신의 내부슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.** \r\n이곳을 참조해서 자신이 호출되었을 때 생성될 함수 렉시컬환경의 \"외부 렉시컬 환경에 대한 참조\"에 저장될 참조값을 보고, 자신이 존재하는 한, 이 [[Environment]] 슬롯에 저장한 렉시컬 환경의 참조, 즉 **상위 스코프**를 기억한다.\r\n\r\n## 클로저와 렉시컬환경\r\n그렇다면 다음의 코드를 살펴보자\r\n```js\r\nconst x = 1 ;\r\nfunction outer() {\r\n\tconst x = 10;\r\n\tconst inner = function ( ) {console.log(x)}\r\n\t//inner함수 반환\r\n\treturn inner;\r\n}\r\n// outer함수를 호출하면 중첩 함수 inner를 반환한다.\r\n// 그리고 outer 함수의 실행 컨텍스트는 제거된다.\r\nconst innerFunc = outer( );\r\ninnerFunc( )// 10\r\n```\r\nouter함수를 호출하면 outer함수는 중첩함수 inner를 반환하고 생명주기를 마감한다. \r\n\r\n즉 outer함수의 실행이 종료되었으므로, 실행컨텍스트가 제거된다. (실행컨텍스트 스택에서 pop된다.)\r\n\r\n이때 outer 함수의 지역변수x 역시 생명주기를 마감했으므로, 실행 컨텍스트가 제거되어 유효하지 않아 보인다.\r\n\r\n그러나 위의 실행 결과는 outer 지역 변수x 의 값인 10을 반환한다. 이미 생명 주기가 종료되어 outer 함수의 지역변수 x가 실행 컨텍스트 스택에서 제거되었는데도 다시 부활이라도 한 것 마냥 말이다. \r\n\r\n이처럼 **외부 함수보다 중첩함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명주기가 종료한 외부함수의 변수를 참조**할 수 있다. \r\n\r\n이러한 **중첩 함수를 클로저**라고 부른다.\r\n\r\n다시 정의로 돌아가보자.\r\n> 클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.\r\n\r\n위 정의를 예제에 대입해보자면 `함수`는 반환된 `중첩함수(innerFunc)`를 의미하고 `그 함수가 선언될 때의 렉시컬 환경(Lexical environment)`란 그 `중첩 함수(innerFunc)가 정의됐을 때의 스코프`를 의미하는 것이다.\r\n\r\n즉, **클로저는 반환된 중첩 함수가 자신이 선언됐을 때의 렉시컬 환경 즉, 스코프를 기억하여 자신이 선언됐을 때의 렉시컬 환경 밖에서 호출되어도 그 렉시컬 환경(스코프)에 접근할 수 있는 함수**를 말한다. \r\n\r\n조금 더 간단히 말하면 **클로저는 자신이 생성될 때의 상위 스코프(렉시컬 환경)을 기억하는 함수이다**\r\n\r\n\r\n\r\n\r\n위 그림처럼 inner함수의 [[Environment]] 내부 슬롯에 의해 outer의 렉시컬 환경(outer Lexical Environment)가 참조되어 있다. inner함수는 전역 변수 innerFunc에 의해 참조되어있으므로, 가비지 컬렉터의 가비지 컬렉션의 대상이 되지 않는다.\r\n\r\n\r\n> **가비지 컬렉터(Garbage Collector)는 프로그램이 더 이상 사용하지 않는 메모리를 자동으로 해제해 주는 자바스크립트 엔진의 기능**이다.\r\n> \r\n> 가비지 컬렉터는 특정 메모리 공간이 더 이상 참조되지 않을 때 그 공간을 \"가비지\"로 판단하여 메모리를 해제한다. 반대로, **누군가가 참조하고 있는 메모리 공간은 함부로 해제하지 않는다**.\r\n\r\n클로저는 자바스크립트의 강력한 기능으로, 필요하다면 적극 활용해야 한다. 클로저가 유용하게 사용되는 상황을 살펴보자.\r\n\r\n## 클로저의 활용\r\n\r\n### 상태를 안전하게 변경하고 유지할 때\r\n\r\n클로저는 **상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고, 특정 함수에게만 상태 변경을 허용하여, 상태를 안전하게 변경하고 유지할 수 있도록 사용한다.**\r\n```js\r\nconst counter = (function ( ) {\r\n// 은닉된 상태 (외부에서 접근 불가)\r\nlet num = 0;\r\n// 클로저인 메서드를 갖는 객체를 반환한다.\r\n// 객체 리터럴은 스코프를 만들지 않는다.\r\n// 따라서 아래 메서드들의 상위 스코프는 즉시 실행 함수의 렉시컬 환경이다.\r\nreturn {\r\n\tincrease() {\r\n\t\treturn ++num;\r\n\t}\r\n\tdecrease() {\r\n\t\treturn num>0? --num: 0;\r\n\t}\r\n}());\r\n\r\nconsole.log(counter.increase()); // 1\r\nconsole.log(counter.decrease()); // 2\r\n\r\nconsole.log(counter.decrease()); // 1\r\nconsole.log(counter.decrease()); // 0\r\n```\r\n즉시 실행 함수는 호출된 이후 소멸되지만, 즉시 실행 함수가 반환한 클로저(increase, decrease)는 **자신의 상위 스코프인 즉시 실행함수의 렉시컬 환경을 기억하고 있다**. \r\n\r\n이 코드에서 \r\n- 카운터 상태(num 변수의 값)은 increase, decrease 함수가 호출되기 전까지 변경되지않고 유지되며 **외부에서 접근할 수 없다**.\r\n- 카운터 상태는 오직 **increase, decrease로 정의된 함수로만 변경이 가능**하다.\r\n\r\n\r\n\r\n이처럼 클로저는 **상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고 특정함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용**된다.\r\n\r\n### 전역변수의 사용을 억제할 때\r\n\r\n클로저는 전역 변수 사용을 억제하고 대신 **함수 내부의 변수로 상태를 관리**할 수 있도록 도와준다. 이렇게 하면 전역 변수를 사용하지 않고도 데이터가 안전하게 유지되며, 다른 코드와 충돌하지 않는 이점을 얻을 수 있다.\r\n\r\n```js\r\nlet counter = 0; // 전역 변수\r\n\r\nfunction incrementCounter() {\r\n counter += 1;\r\n return counter;\r\n}\r\n\r\nconsole.log(incrementCounter()); // 1\r\nconsole.log(incrementCounter()); // 2\r\nconsole.log(counter); // 전역 변수에 접근 가능 (위험)\r\n```\r\n위 코드에서는 `counter`가 전역에 선언되어 있기 때문에 어디서든 접근 가능하여, 이러면 다른 코드에서 `counter`를 실수로 변경할 위험이 있다.\r\n```js\r\nfunction createCounter() {\r\n let counter = 0; // 함수 내부 변수로 관리\r\n\r\n return function() {\r\n counter += 1;\r\n return counter;\r\n };\r\n}\r\n\r\nconst incrementCounter = createCounter();\r\n\r\nconsole.log(incrementCounter()); // 1\r\nconsole.log(incrementCounter()); // 2\r\nconsole.log(typeof counter); // 'undefined' - 전역에서 접근 불가\r\n```\r\n\r\n이 코드에서는 `counter` 변수가 **`createCounter` 함수 내부에만 존재**하므로 외부에서 직접 접근하거나 수정할 수 없다. \r\n\r\n대신, `incrementCounter` 함수는 **클로저를 통해 `counter`를 기억**하고 있으므로 호출할 때마다 `counter`를 안전하게 증가시킬 수 있다.\r\n\r\n이처럼, 클로저를 사용하면 함수 내 지역 변수를 통해 상태를 관리하게 되어 **전역 변수를 사용하지 않아도 안전하게 데이터 상태를 유지**할 수 있다.\r\n\r\n### React의 useState\r\n\r\n이런 이점을 활용하여 react의 useState에도 클로저가 활용된다.\r\n\r\n`useState`를 사용하면 컴포넌트 내에서 **상태를 관리**하게 되는데, 이 상태가 **컴포넌트가 렌더링될 때마다 유지**되도록, 또한 `setState` 함수로만 상태가 변경되도록 하는 데에 클로저가 활용되는 것이다.\r\n\r\n이와 관련하여서는 다음 포스팅에서 자세하게 다룰 예정이다.\r\n\r\n\r\n## 결론\r\n\r\n지금까지 자바스크립트의 어렵지만 주요한 개념인 클로저에 대해 살펴보았다.\r\n\r\n**클로저**는 **함수와 그 함수가 선언된 렉시컬 환경의 조합으로, 자바스크립트에서 함수는 자신이 정의된 위치에 따라 상위 스코프를 결정하는 렉시컬 스코프**를 따르므로, \r\n중첩 함수가 외부 함수의 스코프를 참조하여 외부함수가 생명주기가 끝났음에도 그 함수의 변수를 참조할 수 있는 함수를 의미한다."}]},"__N_SSG":true} \ No newline at end of file diff --git a/_next/static/RYnp_NyzrQPZMofDPtHX9/_buildManifest.js b/_next/static/6z_NmOq0sgJymZX5w6fz3/_buildManifest.js similarity index 92% rename from _next/static/RYnp_NyzrQPZMofDPtHX9/_buildManifest.js rename to _next/static/6z_NmOq0sgJymZX5w6fz3/_buildManifest.js index 9fee45f..6f3840e 100644 --- a/_next/static/RYnp_NyzrQPZMofDPtHX9/_buildManifest.js +++ b/_next/static/6z_NmOq0sgJymZX5w6fz3/_buildManifest.js @@ -1 +1 @@ -self.__BUILD_MANIFEST=function(s,c,t,a){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[s,c,t,a,"static/chunks/pages/index-29ef57cf887c10bb.js"],"/_error":["static/chunks/pages/_error-ee5b5fb91d29d86f.js"],"/posts/search":[s,c,t,a,"static/chunks/pages/posts/search-369a7036ab19d85c.js"],"/posts/tag/[tag]":[s,c,t,a,"static/chunks/pages/posts/tag/[tag]-9c29e7860c712dac.js"],"/posts/[category]":[s,c,t,a,"static/chunks/pages/posts/[category]-731f2768a845326a.js"],"/[...detail]":[s,c,t,"static/chunks/393-7217afb82985f4a5.js",a,"static/chunks/pages/[...detail]-8188b3d88e2a5757.js"],sortedPages:["/","/_app","/_error","/posts/search","/posts/tag/[tag]","/posts/[category]","/[...detail]"]}}("static/css/570acc098c248c2f.css","static/css/0407c34f82b3c3db.css","static/chunks/135-4ea70e0295549ad8.js","static/chunks/979-7390dd4fc9e19803.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file +self.__BUILD_MANIFEST=function(s,c,t,a){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[s,c,t,a,"static/chunks/pages/index-29ef57cf887c10bb.js"],"/_error":["static/chunks/pages/_error-ee5b5fb91d29d86f.js"],"/posts/search":[s,c,t,a,"static/chunks/pages/posts/search-369a7036ab19d85c.js"],"/posts/tag/[tag]":[s,c,t,a,"static/chunks/pages/posts/tag/[tag]-9c29e7860c712dac.js"],"/posts/[category]":[s,c,t,a,"static/chunks/pages/posts/[category]-731f2768a845326a.js"],"/[...detail]":[s,c,t,"static/chunks/393-7217afb82985f4a5.js",a,"static/chunks/pages/[...detail]-c311debfc124ca6f.js"],sortedPages:["/","/_app","/_error","/posts/search","/posts/tag/[tag]","/posts/[category]","/[...detail]"]}}("static/css/570acc098c248c2f.css","static/css/0407c34f82b3c3db.css","static/chunks/135-4ea70e0295549ad8.js","static/chunks/979-7390dd4fc9e19803.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/_next/static/RYnp_NyzrQPZMofDPtHX9/_ssgManifest.js b/_next/static/6z_NmOq0sgJymZX5w6fz3/_ssgManifest.js similarity index 100% rename from _next/static/RYnp_NyzrQPZMofDPtHX9/_ssgManifest.js rename to _next/static/6z_NmOq0sgJymZX5w6fz3/_ssgManifest.js diff --git a/_next/static/chunks/pages/[...detail]-8188b3d88e2a5757.js b/_next/static/chunks/pages/[...detail]-c311debfc124ca6f.js similarity index 77% rename from _next/static/chunks/pages/[...detail]-8188b3d88e2a5757.js rename to _next/static/chunks/pages/[...detail]-c311debfc124ca6f.js index 4626e93..4f38bc4 100644 --- a/_next/static/chunks/pages/[...detail]-8188b3d88e2a5757.js +++ b/_next/static/chunks/pages/[...detail]-c311debfc124ca6f.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[492],{6069:function(e,t,r){(window.__NEXT_P=window.__NEXT_P||[]).push(["/[...detail]",function(){return r(17)}])},588:function(e,t,r){"use strict";var s=r(5893),a=r(1664),l=r.n(a);t.Z=e=>(0,s.jsx)(l(),{href:"/posts/tag/".concat(e.name),className:"w-fit h-fit px-2 py-1 transition-all bg-gray-100 rounded-lg md:text-sm sm:text-xs dark:bg-dark-secondary dark:hover:text-white hover:bg-tag-hover dark:hover:bg-tag-dark-hover",children:e.name})},17:function(e,t,r){"use strict";r.r(t),r.d(t,{PostDetailPage:function(){return er},__N_SSG:function(){return et},default:function(){return es}});var s,a,l,n,o=r(5893),i=r(8080),c=r(7294),d=()=>{let[e,t]=(0,c.useState)(0),[r,s]=(0,c.useState)(0),a=(0,c.useCallback)(()=>{let e=window.scrollY;s(e);let r=document.documentElement,a=r.scrollTop||document.body.scrollTop,l=r.scrollHeight||document.body.scrollHeight,n=a/(l-r.clientHeight)*100;t(n)},[r]);return(0,c.useEffect)(()=>(window.addEventListener("scroll",a),()=>{window.removeEventListener("scroll",a)}),[a]),(0,o.jsx)("div",{className:"fixed z-50 top-1 transtion-all -mt-1 left-0 h-1 bg-gradient-to-r from-sky-500 to-indigo-500",style:{width:"".concat(e,"%")}})},u=r(1578),h=r(1664),p=r.n(h),g=e=>(0,o.jsx)(p(),{href:"/posts/".concat(e.text),className:"w-auto px-4 border-indigo-600 text-indigo-600 dark:border-indigo-200 dark:text-indigo-200 border-2 border-solid rounded-lg py-1 h-8 flex justify-center items-center cursor-pointer",children:e.text}),m=r(588),x=r(9727);function f(){return(f=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let t=(0,u.ZP)(new Date(e.date),"yyyy년 MM월 dd일");return(0,o.jsxs)("div",{className:"w-full flex flex-col items-center mt-6",children:[(0,o.jsx)(g,{text:e.category}),(0,o.jsx)("div",{className:"font-bold text-3xl md:text-5xl mt-2 text-center leading-snug md:leading-snug",children:e.title}),(0,o.jsx)("div",{className:"flex gap-4 mt-4 break-words flex-wrap w-full justify-center",children:e.tags.map(e=>(0,o.jsx)(m.Z,{name:e},e))}),(0,o.jsx)("div",{className:"text-md mt-4",children:t}),(0,o.jsxs)("div",{className:"flex text-sm mt-2 items-center gap-1 text-neutral-600",children:[(0,o.jsx)(v,{width:20,height:20}),(0,o.jsxs)("span",{children:[e.readingTime,"분"]})]}),(0,o.jsx)(x.Z,{mt:"6"})]})},j=r(5675),w=r.n(j),y=r(8152),k=r(4283),N=r(2041),D=r(902),E=r(2422);let O={threshold:.5,rootMargin:"-70px 0px -60% 0px"};var T=(e,t)=>{let r=(0,c.useRef)({}),s=(0,c.useCallback)(s=>{r.current={},r.current=s.reduce((e,t)=>(e[t.target.id]=t,e),r.current);let a=[];Object.keys(r.current).forEach(e=>{let t=r.current[e];t.isIntersecting&&a.push(t)});let l=e=>t.findIndex(t=>t.id===e);if(1===a.length)e(a[0].target.id);else if(a.length>1){let t=a.sort((e,t)=>l(e.target.id)-l(t.target.id));e(t[0].target.id)}},[t]);(0,c.useEffect)(()=>{let e=new IntersectionObserver(s,O);return t.map(t=>{e.observe(t)}),()=>{e.disconnect()}},[t])},_=r(6261);function Z(){return(Z=Object.assign?Object.assign.bind():function(e){for(var t=1;t(0,o.jsx)(p(),{href:"/posts/".concat(e.category),className:"w-auto h-auto fill-[#666666] dark:fill-[rgb(181,181,181)] rounded-lg hover:bg-slate-200 dark:hover:bg-slate-800 p-2 transition-colors cursor-pointer text-neutral-700",children:(0,o.jsx)(M,{})}),H=r(1163),L=r.n(H),S=e=>{let t=(0,c.useRef)(null),r=(0,H.useRouter)(),[s,a]=(0,c.useState)(""),[l,n]=(0,c.useState)([]);return console.log(s),(0,c.useEffect)(()=>{let e=Array.from(document.querySelectorAll("h1,h2,h3"));n(e),a("")},[e.slug]),(0,c.useEffect)(()=>{var e;let r=null===(e=t.current)||void 0===e?void 0:e.querySelector(".font-bold.text-indigo-500");if(r&&t.current){let e=t.current.getBoundingClientRect().top,s=r.getBoundingClientRect().top;t.current.scrollTop+=s-e}},[s]),T(a,l),(0,o.jsx)("div",{className:"mt-12 ml-auto relative hidden lg:block",children:(0,o.jsxs)("div",{className:"sticky top-32 w-60 ",children:[(0,o.jsxs)("div",{className:"p-4 max-h-[500px] rounded-t-xl border-solid border-slate-200 border-[0.5px] border-b-0 dark:border-gray-600 items-start gap-6",children:[(0,o.jsx)("div",{className:"font-bold mb-2",children:e.title}),(0,o.jsx)("hr",{className:"w-full border-neutral-400 dark:border-gray-600"}),(0,o.jsx)("div",{ref:t,className:"custom-scroll overflow-y-auto max-h-[380px] mt-2 mb-2 px-2",children:(0,o.jsx)("ul",{className:"mb-2 text-sm flex flex-col gap-2 mt-4 ",children:l.map((e,t)=>{let r=e.nodeName,a=e.innerHTML,l=e.id,n=s==l?"font-bold text-indigo-500":"";return"H1"===r?(0,o.jsx)("li",{className:"".concat(n),children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,className:"".concat(n," py-1 cursor-pointer transition-colors"),offset:-100,children:a})},t):"H2"===r?(0,o.jsx)("li",{children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,offset:-100,className:"".concat(n," py-1 pl-2 whitespace-pre-line cursor-pointer transition-colors block"),children:a})},t):(0,o.jsx)("li",{children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,offset:-50,className:"".concat(n," py-1 pl-6 whitespace-pre-line cursor-pointer transition-colors block"),children:a})},t)})})})]}),(0,o.jsxs)("div",{className:"rounded-b-xl border-[0.5px] px-6 w-full h-12 border-solid bg-slate-100 dark:bg-[#363636] dark:border-gray-600 flex items-center justify-between",children:[(0,o.jsx)(z,{category:r.query.detail[1]}),(0,o.jsx)(P,{onClick:()=>{_.NY.scrollToTop()},className:"w-auto h-auto rounded-lg hover:bg-slate-200 p-2 cursor-pointer text-white transition-colors dark:hover:bg-gray-800 fill-[#666666] dark:fill-[rgb(181,181,181)]"}),(0,o.jsx)(_.rU,{to:"giscus",spy:!0,smooth:!0,duration:400,children:(0,o.jsx)(q,{className:"w-auto h-auto rounded-lg p-2 hover:bg-slate-200 cursor-pointer text-neutral-700 transition-colors dark:hover:bg-slate-800 fill-[#666666] dark:fill-[rgb(181,181,181)]"})})]})]})})},R=r(9943),B=r(7896),U=r(7388);y.Z.registerLanguage("js",N.Z),y.Z.registerLanguage("css",E.Z),y.Z.registerLanguage("python",D.Z);var I=e=>(0,o.jsx)("div",{className:"w-full flex mt-8 mb-8",children:(0,o.jsxs)("div",{className:"w-full gap-8 lg:flex",children:[(0,o.jsx)("div",{className:"prose prose-zinc w-full leading-loose max-w-3xl dark:prose-invert",children:(0,o.jsx)(R.U,{rehypePlugins:[B.Z,U.Z],components:{a:e=>{let{href:t,children:r}=e;return(0,o.jsx)(p(),{href:t,children:r})},pre:e=>{if(e.children.props.className){var t;let r=null===(t=e.children.props.className)||void 0===t?void 0:t.split("-")[1];return(0,o.jsx)(y.Z,{style:k.pJ,PreTag:"pre",language:r,CodeTag:e=>{let{children:t}=e;return(0,o.jsx)("code",{className:"whitespace-pre-wrap",children:t})},children:e.children.props.children})}},img:t=>{console.log(t);let r=t.width?t.width:"600",s=t.height?t.height:"300";return(0,o.jsx)(w(),{src:"/".concat(e.slug,"/").concat(t.src),alt:t.src,width:r,height:s})}},children:e.content})}),(0,o.jsx)(S,{title:e.title,slug:e.slug})]})}),F=r(7103),W=r(7138),K=r(6378),X=()=>(0,o.jsxs)("div",{className:"p-12 flex gap-4 justify-center items-center",children:[(0,o.jsx)("div",{children:(0,o.jsx)(w(),{src:"/profile/profile.png",alt:"my profile photo",width:80,height:80,className:"rounded-full"})}),(0,o.jsxs)("div",{className:"flex flex-col w-auto gap-2",children:[(0,o.jsxs)("div",{children:[(0,o.jsx)("div",{className:"w-full font-bold text-base mb-1",children:"Phnml1"}),(0,o.jsx)("div",{className:"w-full text-sm text-slate-500 dark:text-dark-secondary",children:"더디더라도 조금씩 성장하는 프론트엔드 개발자"})]}),(0,o.jsxs)("div",{className:"w-full flex gap-2",children:[(0,o.jsx)(p(),{href:"".concat(K.b.link),target:"_blank",children:(0,o.jsx)(F.Z,{width:"25",height:"25",className:"fill-slate-300 transition-all cursor-pointer hover:fill-black dark:hover:fill-white"})}),(0,o.jsx)(p(),{href:"mailto:juyung0903@gmail.com",target:"_blank",children:(0,o.jsx)(W.Z,{width:"25",height:"25",className:"fill-slate-300 transition-all cursor-pointer hover:fill-black dark:hover:fill-white"})})]})]})]}),Y=e=>(0,o.jsxs)("section",{className:"w-full flex-col flex gap-8 mt-20 mb-20 lg:flex-row lg:gap-52",children:["object"==typeof e.prevData&&(0,o.jsxs)(p(),{href:"".concat(e.prevData.slug),className:"w-full h-auto rounded-lg border-[1px] break-words border-detailnav cursor-pointer hover:scale-105 transition-all p-8 lg:w-[calc(50%-6.5rem)] dark:border-darkdetailnav",children:[(0,o.jsx)("div",{className:"text-sm mb-2",children:"이전글"}),(0,o.jsx)("div",{className:"font-bold mb-2 text-lg",children:e.prevData.title}),(0,o.jsx)("div",{className:"text-sm line-clamp-2 overflow-hidden overflow-ellipsis text-slate-600 dark:text-dark-secondary",children:e.prevData.summary})]}),"object"==typeof e.nextData&&(0,o.jsxs)(p(),{href:"".concat(e.nextData.slug),className:"w-full h-auto rounded-lg border-[1px] break-words border-detailnav cursor-pointer hover:scale-105 transition-all p-8 lg:w-[calc(50%-6.5rem)] dark:border-darkdetailnav",children:[(0,o.jsx)("div",{className:"text-sm mb-2",children:"다음글"}),(0,o.jsx)("div",{className:"font-bold mb-2 text-lg",children:e.nextData.title}),(0,o.jsx)("div",{className:"text-sm line-clamp-2 overflow-hidden overflow-ellipsis text-slate-600 dark:text-dark-secondary",children:e.nextData.summary})]})]}),G=r(2010);function J(){let e=(0,c.useRef)(null),{resolvedTheme:t}=(0,G.F)(),r="dark"===t?"dark":"light";return(0,c.useEffect)(()=>{if(!e.current||e.current.hasChildNodes())return;let t=document.createElement("script");t.src="https://giscus.app/client.js",t.async=!0,t.crossOrigin="anonymous",t.setAttribute("data-repo","phnml1/phnml1.github.io"),t.setAttribute("data-repo-id","R_kgDOKznePw"),t.setAttribute("data-category","general"),t.setAttribute("data-category-id","DIC_kwDOKzneP84CcqiL"),t.setAttribute("data-mapping","pathname"),t.setAttribute("data-strict","0"),t.setAttribute("data-reactions-enabled","1"),t.setAttribute("data-emit-metadata","0"),t.setAttribute("data-input-position","bottom"),t.setAttribute("data-theme",r),t.setAttribute("data-lang","en"),e.current.appendChild(t)},[]),(0,c.useEffect)(()=>{var e;let t=document.querySelector("iframe.giscus-frame");null==t||null===(e=t.contentWindow)||void 0===e||e.postMessage({giscus:{setConfig:{theme:r}}},"https://giscus.app")},[r]),(0,c.useEffect)(()=>{var e;let t=document.querySelector("iframe.giscus-frame");null==t||null===(e=t.contentWindow)||void 0===e||e.postMessage({giscus:{setConfig:{term:L().asPath}}},"https://giscus.app")},[L().asPath]),(0,o.jsx)("section",{id:"giscus",ref:e})}var Q=e=>(0,o.jsxs)("div",{className:"w-full mt-12",children:[(0,o.jsx)(X,{}),(0,o.jsx)(Y,{prevData:e.prevData,nextData:e.nextData}),(0,o.jsx)(J,{})]});function V(e){return(0,o.jsx)(i.Z,{children:(0,o.jsxs)(c.Fragment,{children:[(0,o.jsx)(d,{}),(0,o.jsxs)("div",{className:"mt-4 w-full md:w-4/5 px-8 flex flex-col items-center mb-16",children:[(0,o.jsx)(b,{title:e.post.title,category:e.category,date:e.post.date,tags:e.post.tags,readingTime:e.post.readingMinutes}),(0,o.jsx)(I,{title:e.post.title,content:e.post.content,slug:e.post.slug}),(0,o.jsx)(x.Z,{mt:"8"}),(0,o.jsx)(Q,{prevData:e.prevData,nextData:e.nextData})]})]})})}var $=r(9008),ee=r.n($),et=!0;function er(e){return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(ee(),{children:[(0,o.jsx)("title",{children:e.post.title}),(0,o.jsx)("meta",{name:"description",content:"".concat(e.post.summary)}),(0,o.jsx)("meta",{property:"og:title",content:e.post.title}),(0,o.jsx)("meta",{property:"og:description",content:e.post.summary}),(0,o.jsx)("meta",{property:"og:image",content:"https://phnml1.github.io/".concat(e.post.slug,"/").concat(e.post.image)}),(0,o.jsx)("meta",{property:"og:url",content:"https://phnml1.github.io/".concat(e.post.slug)}),(0,o.jsx)("meta",{property:"og:type",content:"article"})]}),(0,o.jsx)(V,{post:e.post,category:e.category,prevData:e.prevData,nextData:e.nextData})]})}var es=er}},function(e){e.O(0,[815,135,393,979,774,888,179],function(){return e(e.s=6069)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[492],{6069:function(e,t,r){(window.__NEXT_P=window.__NEXT_P||[]).push(["/[...detail]",function(){return r(17)}])},588:function(e,t,r){"use strict";var s=r(5893),a=r(1664),l=r.n(a);t.Z=e=>(0,s.jsx)(l(),{href:"/posts/tag/".concat(e.name),className:"w-fit h-fit px-2 py-1 transition-all bg-gray-100 rounded-lg md:text-sm sm:text-xs dark:bg-dark-secondary dark:hover:text-white hover:bg-tag-hover dark:hover:bg-tag-dark-hover",children:e.name})},17:function(e,t,r){"use strict";r.r(t),r.d(t,{PostDetailPage:function(){return er},__N_SSG:function(){return et},default:function(){return es}});var s,a,l,n,o=r(5893),i=r(8080),c=r(7294),d=()=>{let[e,t]=(0,c.useState)(0),[r,s]=(0,c.useState)(0),a=(0,c.useCallback)(()=>{let e=window.scrollY;s(e);let r=document.documentElement,a=r.scrollTop||document.body.scrollTop,l=r.scrollHeight||document.body.scrollHeight,n=a/(l-r.clientHeight)*100;t(n)},[r]);return(0,c.useEffect)(()=>(window.addEventListener("scroll",a),()=>{window.removeEventListener("scroll",a)}),[a]),(0,o.jsx)("div",{className:"fixed z-50 top-1 transtion-all -mt-1 left-0 h-1 bg-gradient-to-r from-sky-500 to-indigo-500",style:{width:"".concat(e,"%")}})},u=r(1578),h=r(1664),p=r.n(h),g=e=>(0,o.jsx)(p(),{href:"/posts/".concat(e.text),className:"w-auto px-4 border-indigo-600 text-indigo-600 dark:border-indigo-200 dark:text-indigo-200 border-2 border-solid rounded-lg py-1 h-8 flex justify-center items-center cursor-pointer",children:e.text}),m=r(588),x=r(9727);function f(){return(f=Object.assign?Object.assign.bind():function(e){for(var t=1;t{let t=(0,u.ZP)(new Date(e.date),"yyyy년 MM월 dd일");return(0,o.jsxs)("div",{className:"w-full flex flex-col items-center mt-6",children:[(0,o.jsx)(g,{text:e.category}),(0,o.jsx)("div",{className:"font-bold text-3xl md:text-5xl mt-2 text-center leading-snug md:leading-snug",children:e.title}),(0,o.jsx)("div",{className:"flex gap-4 mt-4 break-words flex-wrap w-full justify-center",children:e.tags.map(e=>(0,o.jsx)(m.Z,{name:e},e))}),(0,o.jsx)("div",{className:"text-md mt-4",children:t}),(0,o.jsxs)("div",{className:"flex text-sm mt-2 items-center gap-1 text-neutral-600",children:[(0,o.jsx)(v,{width:20,height:20}),(0,o.jsxs)("span",{children:[e.readingTime,"분"]})]}),(0,o.jsx)(x.Z,{mt:"6"})]})},j=r(5675),w=r.n(j),y=r(8152),k=r(4283),N=r(2041),D=r(902),E=r(2422);let O={threshold:.5,rootMargin:"-70px 0px -60% 0px"};var T=(e,t)=>{let r=(0,c.useRef)({}),s=(0,c.useCallback)(s=>{r.current={},r.current=s.reduce((e,t)=>(e[t.target.id]=t,e),r.current);let a=[];Object.keys(r.current).forEach(e=>{let t=r.current[e];t.isIntersecting&&a.push(t)});let l=e=>t.findIndex(t=>t.id===e);if(1===a.length)e(a[0].target.id);else if(a.length>1){let t=a.sort((e,t)=>l(e.target.id)-l(t.target.id));e(t[0].target.id)}},[t]);(0,c.useEffect)(()=>{let e=new IntersectionObserver(s,O);return t.map(t=>{e.observe(t)}),()=>{e.disconnect()}},[t])},_=r(6261);function P(){return(P=Object.assign?Object.assign.bind():function(e){for(var t=1;t(0,o.jsx)(p(),{href:"/posts/".concat(e.category),className:"w-auto h-auto fill-[#666666] dark:fill-[rgb(181,181,181)] rounded-lg hover:bg-slate-200 dark:hover:bg-slate-800 p-2 transition-colors cursor-pointer text-neutral-700",children:(0,o.jsx)(M,{})}),H=r(1163),S=r.n(H),L=e=>{let t=(0,c.useRef)(null),r=(0,H.useRouter)(),[s,a]=(0,c.useState)(""),[l,n]=(0,c.useState)([]);return console.log(s),(0,c.useEffect)(()=>{let e=Array.from(document.querySelectorAll("h1,h2,h3"));n(e),a("")},[e.slug]),(0,c.useEffect)(()=>{var e;let r=null===(e=t.current)||void 0===e?void 0:e.querySelector(".font-bold.text-indigo-500");if(r&&t.current){let e=t.current.getBoundingClientRect().top,s=r.getBoundingClientRect().top;t.current.scrollTop+=s-e}},[s]),T(a,l),(0,o.jsx)("div",{className:"mt-12 ml-auto relative hidden lg:block",children:(0,o.jsxs)("div",{className:"sticky top-32 w-60 ",children:[(0,o.jsxs)("div",{className:"p-4 max-h-[500px] rounded-t-xl border-solid border-slate-200 border-[0.5px] border-b-0 dark:border-gray-600 items-start gap-6",children:[(0,o.jsx)("div",{className:"font-bold mb-2",children:e.title}),(0,o.jsx)("hr",{className:"w-full border-neutral-400 dark:border-gray-600"}),(0,o.jsx)("div",{ref:t,className:"custom-scroll overflow-y-auto max-h-[380px] mt-2 mb-2 px-2",children:(0,o.jsx)("ul",{className:"mb-2 text-sm flex flex-col gap-2 mt-4 ",children:l.map((e,t)=>{let r=e.nodeName,a=e.innerHTML,l=e.id,n=s==l?"font-bold text-indigo-500":"";return"H1"===r?(0,o.jsx)("li",{className:"".concat(n),children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,className:"".concat(n," py-1 cursor-pointer transition-colors"),offset:-100,children:a})},t):"H2"===r?(0,o.jsx)("li",{children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,offset:-100,className:"".concat(n," py-1 pl-2 whitespace-pre-line cursor-pointer transition-colors block"),children:a})},t):(0,o.jsx)("li",{children:(0,o.jsx)(_.rU,{to:"".concat(l),spy:!0,smooth:!0,duration:400,offset:-50,className:"".concat(n," py-1 pl-6 whitespace-pre-line cursor-pointer transition-colors block"),children:a})},t)})})})]}),(0,o.jsxs)("div",{className:"rounded-b-xl border-[0.5px] px-6 w-full h-12 border-solid bg-slate-100 dark:bg-[#363636] dark:border-gray-600 flex items-center justify-between",children:[(0,o.jsx)(z,{category:r.query.detail[1]}),(0,o.jsx)(Z,{onClick:()=>{_.NY.scrollToTop()},className:"w-auto h-auto rounded-lg hover:bg-slate-200 p-2 cursor-pointer text-white transition-colors dark:hover:bg-gray-800 fill-[#666666] dark:fill-[rgb(181,181,181)]"}),(0,o.jsx)(_.rU,{to:"giscus",spy:!0,smooth:!0,duration:400,children:(0,o.jsx)(A,{className:"w-auto h-auto rounded-lg p-2 hover:bg-slate-200 cursor-pointer text-neutral-700 transition-colors dark:hover:bg-slate-800 fill-[#666666] dark:fill-[rgb(181,181,181)]"})})]})]})})},R=r(9943),B=r(7896),U=r(7388);y.Z.registerLanguage("js",N.Z),y.Z.registerLanguage("css",E.Z),y.Z.registerLanguage("python",D.Z);var I=e=>(0,o.jsx)("div",{className:"w-full flex mt-8 mb-8",children:(0,o.jsxs)("div",{className:"w-full gap-8 lg:flex",children:[(0,o.jsx)("div",{className:"prose prose-zinc w-full leading-loose max-w-3xl dark:prose-invert",children:(0,o.jsx)(R.U,{rehypePlugins:[B.Z,U.Z],components:{a:e=>{let{href:t,children:r}=e;return(0,o.jsx)(p(),{href:t,children:r})},pre:e=>{if(e.children.props.className){var t;let r=null===(t=e.children.props.className)||void 0===t?void 0:t.split("-")[1];return(0,o.jsx)(y.Z,{style:k.pJ,PreTag:"pre",language:r,CodeTag:e=>{let{children:t}=e;return(0,o.jsx)("code",{className:"whitespace-pre-wrap",children:t})},children:e.children.props.children})}},img:t=>{console.log(t);let r=t.width?t.width:"600",s=t.height?t.height:"300";return(0,o.jsx)(w(),{src:"/".concat(e.slug,"/").concat(t.src),alt:t.src,width:r,height:s})}},children:e.content})}),(0,o.jsx)(L,{title:e.title,slug:e.slug})]})}),F=r(7103),K=r(7138),W=r(6378),X=()=>(0,o.jsxs)("div",{className:"p-12 flex gap-4 justify-center items-center",children:[(0,o.jsx)("div",{children:(0,o.jsx)(w(),{src:"/profile/profile.png",alt:"my profile photo",width:80,height:80,className:"rounded-full"})}),(0,o.jsxs)("div",{className:"flex flex-col w-auto gap-2",children:[(0,o.jsxs)("div",{children:[(0,o.jsx)("div",{className:"w-full font-bold text-base mb-1",children:"Phnml1"}),(0,o.jsx)("div",{className:"w-full text-sm text-slate-500 dark:text-dark-secondary",children:"더디더라도 조금씩 성장하는 프론트엔드 개발자"})]}),(0,o.jsxs)("div",{className:"w-full flex gap-2",children:[(0,o.jsx)(p(),{href:"".concat(W.b.link),target:"_blank",children:(0,o.jsx)(F.Z,{width:"25",height:"25",className:"fill-slate-300 transition-all cursor-pointer hover:fill-black dark:hover:fill-white"})}),(0,o.jsx)(p(),{href:"mailto:juyung0903@gmail.com",target:"_blank",children:(0,o.jsx)(K.Z,{width:"25",height:"25",className:"fill-slate-300 transition-all cursor-pointer hover:fill-black dark:hover:fill-white"})})]})]})]}),Y=e=>(0,o.jsxs)("section",{className:"w-full flex-col flex gap-8 mt-20 mb-20 lg:flex-row lg:gap-52",children:["object"==typeof e.prevData&&(0,o.jsxs)(p(),{href:"".concat(e.prevData.slug),className:"w-full h-auto rounded-lg border-[1px] break-words border-detailnav cursor-pointer hover:scale-105 transition-all p-8 lg:w-[calc(50%-6.5rem)] dark:border-darkdetailnav",children:[(0,o.jsx)("div",{className:"text-sm mb-2",children:"이전글"}),(0,o.jsx)("div",{className:"font-bold mb-2 text-lg",children:e.prevData.title}),(0,o.jsx)("div",{className:"text-sm line-clamp-2 overflow-hidden overflow-ellipsis text-slate-600 dark:text-dark-secondary",children:e.prevData.summary})]}),"object"==typeof e.nextData&&(0,o.jsxs)(p(),{href:"".concat(e.nextData.slug),className:"w-full h-auto rounded-lg border-[1px] break-words border-detailnav cursor-pointer hover:scale-105 transition-all p-8 lg:w-[calc(50%-6.5rem)] dark:border-darkdetailnav",children:[(0,o.jsx)("div",{className:"text-sm mb-2",children:"다음글"}),(0,o.jsx)("div",{className:"font-bold mb-2 text-lg",children:e.nextData.title}),(0,o.jsx)("div",{className:"text-sm line-clamp-2 overflow-hidden overflow-ellipsis text-slate-600 dark:text-dark-secondary",children:e.nextData.summary})]})]}),G=r(2010);function J(){let e=(0,c.useRef)(null),{resolvedTheme:t}=(0,G.F)(),r="dark"===t?"dark":"light";return(0,c.useEffect)(()=>{if(!e.current||e.current.hasChildNodes())return;let t=document.createElement("script");t.src="https://giscus.app/client.js",t.async=!0,t.crossOrigin="anonymous",t.setAttribute("data-repo","phnml1/phnml1.github.io"),t.setAttribute("data-repo-id","R_kgDOKznePw"),t.setAttribute("data-category","Announcements"),t.setAttribute("data-category-id","DIC_kwDOKzneP84CcqiK"),t.setAttribute("data-mapping","pathname"),t.setAttribute("data-strict","0"),t.setAttribute("data-reactions-enabled","1"),t.setAttribute("data-emit-metadata","0"),t.setAttribute("data-input-position","bottom"),t.setAttribute("data-theme",r),t.setAttribute("data-lang","ko"),e.current.appendChild(t)},[]),(0,c.useEffect)(()=>{var e;let t=document.querySelector("iframe.giscus-frame");null==t||null===(e=t.contentWindow)||void 0===e||e.postMessage({giscus:{setConfig:{theme:r}}},"https://giscus.app")},[r]),(0,c.useEffect)(()=>{var e;let t=document.querySelector("iframe.giscus-frame");null==t||null===(e=t.contentWindow)||void 0===e||e.postMessage({giscus:{setConfig:{term:S().asPath}}},"https://giscus.app"),console.log(S().asPath)},[S().asPath]),(0,o.jsx)("section",{id:"giscus",ref:e})}var Q=e=>(0,o.jsxs)("div",{className:"w-full mt-12",children:[(0,o.jsx)(X,{}),(0,o.jsx)(Y,{prevData:e.prevData,nextData:e.nextData}),(0,o.jsx)(J,{})]});function V(e){return(0,o.jsx)(i.Z,{children:(0,o.jsxs)(c.Fragment,{children:[(0,o.jsx)(d,{}),(0,o.jsxs)("div",{className:"mt-4 w-full md:w-4/5 px-8 flex flex-col items-center mb-16",children:[(0,o.jsx)(b,{title:e.post.title,category:e.category,date:e.post.date,tags:e.post.tags,readingTime:e.post.readingMinutes}),(0,o.jsx)(I,{title:e.post.title,content:e.post.content,slug:e.post.slug}),(0,o.jsx)(x.Z,{mt:"8"}),(0,o.jsx)(Q,{prevData:e.prevData,nextData:e.nextData})]})]})})}var $=r(9008),ee=r.n($),et=!0;function er(e){return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(ee(),{children:[(0,o.jsx)("title",{children:e.post.title}),(0,o.jsx)("meta",{name:"description",content:"".concat(e.post.summary)}),(0,o.jsx)("meta",{property:"og:title",content:e.post.title}),(0,o.jsx)("meta",{property:"og:description",content:e.post.summary}),(0,o.jsx)("meta",{property:"og:image",content:"https://phnml1.github.io/".concat(e.post.slug,"/").concat(e.post.image)}),(0,o.jsx)("meta",{property:"og:url",content:"https://phnml1.github.io/".concat(e.post.slug)}),(0,o.jsx)("meta",{property:"og:type",content:"article"})]}),(0,o.jsx)(V,{post:e.post,category:e.category,prevData:e.prevData,nextData:e.nextData})]})}var es=er}},function(e){e.O(0,[815,135,393,979,774,888,179],function(){return e(e.s=6069)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/_next/static/css/e946bf76803169e7.css b/_next/static/css/f4eeca13f57c12b5.css similarity index 80% rename from _next/static/css/e946bf76803169e7.css rename to _next/static/css/f4eeca13f57c12b5.css index 6c1209d..4d89226 100644 --- a/_next/static/css/e946bf76803169e7.css +++ b/_next/static/css/f4eeca13f57c12b5.css @@ -1,3 +1,3 @@ /* ! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com -*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*{scrollbar-color:auto;scrollbar-width:auto}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);text-decoration:underline;font-weight:500}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.25em}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-left-width:.25rem;border-left-color:var(--tw-prose-quote-borders);quotes:"\201C""\201D""\2018""\2019";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:900;color:inherit}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:800;color:inherit}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){display:block;margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-family:inherit;color:var(--tw-prose-kbd);box-shadow:0 0 0 1px rgb(var(--tw-prose-kbd-shadows)/10%),0 3px 0 rgb(var(--tw-prose-kbd-shadows)/10%);font-size:.875em;border-radius:.3125rem;padding:.1875em .375em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:"`"}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:none}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose{--tw-prose-body:#374151;--tw-prose-headings:#111827;--tw-prose-lead:#4b5563;--tw-prose-links:#111827;--tw-prose-bold:#111827;--tw-prose-counters:#6b7280;--tw-prose-bullets:#d1d5db;--tw-prose-hr:#e5e7eb;--tw-prose-quotes:#111827;--tw-prose-quote-borders:#e5e7eb;--tw-prose-captions:#6b7280;--tw-prose-kbd:#111827;--tw-prose-kbd-shadows:17 24 39;--tw-prose-code:#111827;--tw-prose-pre-code:#e5e7eb;--tw-prose-pre-bg:#1f2937;--tw-prose-th-borders:#d1d5db;--tw-prose-td-borders:#e5e7eb;--tw-prose-invert-body:#d1d5db;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#9ca3af;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#9ca3af;--tw-prose-invert-bullets:#4b5563;--tw-prose-invert-hr:#374151;--tw-prose-invert-quotes:#f3f4f6;--tw-prose-invert-quote-borders:#374151;--tw-prose-invert-captions:#9ca3af;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d1d5db;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#4b5563;--tw-prose-invert-td-borders:#374151;font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-left:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-zinc{--tw-prose-body:#3f3f46;--tw-prose-headings:#18181b;--tw-prose-lead:#52525b;--tw-prose-links:#18181b;--tw-prose-bold:#18181b;--tw-prose-counters:#71717a;--tw-prose-bullets:#d4d4d8;--tw-prose-hr:#e4e4e7;--tw-prose-quotes:#18181b;--tw-prose-quote-borders:#e4e4e7;--tw-prose-captions:#71717a;--tw-prose-kbd:#18181b;--tw-prose-kbd-shadows:24 24 27;--tw-prose-code:#18181b;--tw-prose-pre-code:#e4e4e7;--tw-prose-pre-bg:#27272a;--tw-prose-th-borders:#d4d4d8;--tw-prose-td-borders:#e4e4e7;--tw-prose-invert-body:#d4d4d8;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#a1a1aa;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#a1a1aa;--tw-prose-invert-bullets:#52525b;--tw-prose-invert-hr:#3f3f46;--tw-prose-invert-quotes:#f4f4f5;--tw-prose-invert-quote-borders:#3f3f46;--tw-prose-invert-captions:#a1a1aa;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d4d4d8;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#52525b;--tw-prose-invert-td-borders:#3f3f46}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.bottom-12{bottom:3rem}.left-0{left:0}.left-8{left:2rem}.right-0{right:0}.right-8{right:2rem}.top-0{top:0}.top-1{top:.25rem}.top-32{top:8rem}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.mx-12{margin-left:3rem;margin-right:3rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-8{margin-left:2rem;margin-right:2rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.-mt-0{margin-top:0}.-mt-0\.5{margin-top:-.125rem}.-mt-1{margin-top:-.25rem}.mb-1{margin-bottom:.25rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-5{margin-left:1.25rem}.ml-8{margin-left:2rem}.ml-auto{margin-left:auto}.mr-12{margin-right:3rem}.mr-8{margin-right:2rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1{height:.25rem}.h-1\/3{height:33.333333%}.h-12{height:3rem}.h-14{height:3.5rem}.h-2\/3{height:66.666667%}.h-20{height:5rem}.h-3{height:.75rem}.h-40{height:10rem}.h-8{height:2rem}.h-80{height:20rem}.h-96{height:24rem}.h-auto{height:auto}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.max-h-\[380px\]{max-height:380px}.max-h-\[500px\]{max-height:500px}.min-h-screen{min-height:100vh}.w-1\/2{width:50%}.w-32{width:8rem}.w-60{width:15rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.flex-1{flex:1 1 0%}.-translate-y-full{--tw-translate-y:-100%}.-translate-y-full,.translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform-gpu{transform:translate3d(var(--tw-translate-x),var(--tw-translate-y),0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-16{gap:4rem}.gap-2{gap:.5rem}.gap-24{gap:6rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-ellipsis{text-overflow:ellipsis}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border-2{border-width:2px}.border-\[0\.5px\]{border-width:.5px}.border-\[1px\]{border-width:1px}.border-b-0{border-bottom-width:0}.border-r-0{border-right-width:0}.border-solid{border-style:solid}.border-detailnav{--tw-border-opacity:1;border-color:rgb(222 226 230/var(--tw-border-opacity))}.border-indigo-400{--tw-border-opacity:1;border-color:rgb(129 140 248/var(--tw-border-opacity))}.border-indigo-600{--tw-border-opacity:1;border-color:rgb(79 70 229/var(--tw-border-opacity))}.border-neutral-200{--tw-border-opacity:1;border-color:rgb(229 229 229/var(--tw-border-opacity))}.border-neutral-400{--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity))}.bg-\[\#2196f3\]{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-indigo-400{--tw-bg-opacity:1;background-color:rgb(129 140 248/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-opacity-40{--tw-bg-opacity:0.4}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-sky-500{--tw-gradient-from:#0ea5e9 var(--tw-gradient-from-position);--tw-gradient-to:rgba(14,165,233,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-indigo-500{--tw-gradient-to:#6366f1 var(--tw-gradient-to-position)}.fill-\[\#666666\]{fill:#666}.fill-slate-300{fill:#cbd5e1}.fill-slate-500{fill:#64748b}.p-1{padding:.25rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pl-2{padding-left:.5rem}.pl-6{padding-left:1.5rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-8{padding-right:2rem}.text-center{text-align:center}.font-kanit{font-family:var(--kanit)}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-semibold{font-weight:600}.leading-loose{line-height:2}.leading-snug{line-height:1.375}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.text-neutral-700{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-\[background\]{transition-property:background;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}body{margin:0}.custom-scroll::-webkit-scrollbar{width:4px;height:4px;border-radius:12px}.custom-scroll::-webkit-scrollbar-thumb{border-radius:100px;background-color:#6366f1}.custom-scroll::-webkit-scrollbar-track{background-color:#f5f5f5;border-radius:100px}.custom-scroll-dark::-webkit-scrollbar{width:4px;height:4px;border-radius:12px}.custom-scroll-dark::-webkit-scrollbar-thumb{border-radius:100px;background-color:#6366f1}.custom-scroll-dark::-webkit-scrollbar-track{background-color:#262626}:is(.dark .dark\:prose-invert){--tw-prose-body:#a3a3a3;--tw-prose-headings:#e5e5e5;--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:#e5e5e5;--tw-prose-bold:#e5e5e5;--tw-prose-counters:#e5e5e5;--tw-prose-bullets:#e5e5e5;--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:#e5e5e5;--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:bg-\[\#2196f3\]:hover{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}.hover\:bg-slate-200:hover{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.hover\:bg-tag-hover:hover{--tw-bg-opacity:1;background-color:rgb(229 229 229/var(--tw-bg-opacity))}.hover\:fill-black:hover{fill:#000}.hover\:text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hover\:drop-shadow-tag-hover:hover{--tw-drop-shadow:drop-shadow(0px 0px 10px rgba(99,102,241,.5));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-indigo-200:focus{--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}:is(.dark .dark\:border-dark-secondary){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}:is(.dark .dark\:border-darkdetailnav){--tw-border-opacity:1;border-color:rgb(77 77 77/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-indigo-200){--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}:is(.dark .dark\:border-neutral-700){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}:is(.dark .dark\:bg-\[\#2196f3\]){--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}:is(.dark .dark\:bg-\[\#363636\]){--tw-bg-opacity:1;background-color:rgb(54 54 54/var(--tw-bg-opacity))}:is(.dark .dark\:bg-dark-primary){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}:is(.dark .dark\:bg-dark-secondary){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:bg-neutral-800){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:fill-\[rgb\(181\2c 181\2c 181\)\]){fill:#b5b5b5}:is(.dark .dark\:text-\[\#E5E5E5\]){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:text-dark-primary){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:text-dark-secondary){--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-indigo-200){--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity))}:is(.dark .dark\:hover\:bg-\[\#2196f3\]:hover){--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-dark-secondary:hover){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-slate-800:hover){--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-tag-dark-hover:hover){--tw-bg-opacity:1;background-color:rgb(54 54 54/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:fill-white:hover){fill:#fff}:is(.dark .dark\:hover\:text-dark-primary:hover){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-indigo-200:focus){--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}@media (min-width:640px){.sm\:flex-row{flex-direction:row}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}.sm\:text-xs{font-size:.75rem;line-height:1rem}}@media (min-width:768px){.md\:block{display:block}.md\:w-4\/5{width:80%}.md\:flex-row{flex-direction:row}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-5xl{font-size:3rem;line-height:1}.md\:text-base{font-size:1rem;line-height:1.5rem}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-xl{font-size:1.25rem;line-height:1.75rem}.md\:leading-snug{line-height:1.375}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:w-\[calc\(50\%-6\.5rem\)\]{width:calc(50% - 6.5rem)}.lg\:flex-row{flex-direction:row}.lg\:gap-52{gap:13rem}.lg\:text-lg{font-size:1.125rem;line-height:1.75rem}} \ No newline at end of file +*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*{scrollbar-color:auto;scrollbar-width:auto}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);font-size:1.25em;line-height:1.6;margin-top:1.2em;margin-bottom:1.2em}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);text-decoration:underline;font-weight:500}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:disc;margin-top:1.25em;margin-bottom:1.25em;padding-left:1.625em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{font-weight:400;color:var(--tw-prose-counters)}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.25em}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-style:italic;color:var(--tw-prose-quotes);border-left-width:.25rem;border-left-color:var(--tw-prose-quote-borders);quotes:"\201C""\201D""\2018""\2019";margin-top:1.6em;margin-bottom:1.6em;padding-left:1em}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:800;font-size:2.25em;margin-top:0;margin-bottom:.8888889em;line-height:1.1111111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:900;color:inherit}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:700;font-size:1.5em;margin-top:2em;margin-bottom:1em;line-height:1.3333333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:800;color:inherit}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;font-size:1.25em;margin-top:1.6em;margin-bottom:.6em;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;margin-top:1.5em;margin-bottom:.5em;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:700;color:inherit}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){display:block;margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:500;font-family:inherit;color:var(--tw-prose-kbd);box-shadow:0 0 0 1px rgb(var(--tw-prose-kbd-shadows)/10%),0 3px 0 rgb(var(--tw-prose-kbd-shadows)/10%);font-size:.875em;border-radius:.3125rem;padding:.1875em .375em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-weight:600;font-size:.875em}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:"`"}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);overflow-x:auto;font-weight:400;font-size:.875em;line-height:1.7142857;margin-top:1.7142857em;margin-bottom:1.7142857em;border-radius:.375rem;padding:.8571429em 1.1428571em}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){background-color:transparent;border-width:0;border-radius:0;padding:0;font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:none}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){width:100%;table-layout:auto;text-align:left;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.7142857}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);font-weight:600;vertical-align:bottom;padding-right:.5714286em;padding-bottom:.5714286em;padding-left:.5714286em}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);font-size:.875em;line-height:1.4285714;margin-top:.8571429em}.prose{--tw-prose-body:#374151;--tw-prose-headings:#111827;--tw-prose-lead:#4b5563;--tw-prose-links:#111827;--tw-prose-bold:#111827;--tw-prose-counters:#6b7280;--tw-prose-bullets:#d1d5db;--tw-prose-hr:#e5e7eb;--tw-prose-quotes:#111827;--tw-prose-quote-borders:#e5e7eb;--tw-prose-captions:#6b7280;--tw-prose-kbd:#111827;--tw-prose-kbd-shadows:17 24 39;--tw-prose-code:#111827;--tw-prose-pre-code:#e5e7eb;--tw-prose-pre-bg:#1f2937;--tw-prose-th-borders:#d1d5db;--tw-prose-td-borders:#e5e7eb;--tw-prose-invert-body:#d1d5db;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#9ca3af;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#9ca3af;--tw-prose-invert-bullets:#4b5563;--tw-prose-invert-hr:#374151;--tw-prose-invert-quotes:#f3f4f6;--tw-prose-invert-quote-borders:#374151;--tw-prose-invert-captions:#9ca3af;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d1d5db;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#4b5563;--tw-prose-invert-td-borders:#374151;font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-left:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding:.5714286em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-left:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-right:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.prose-zinc{--tw-prose-body:#3f3f46;--tw-prose-headings:#18181b;--tw-prose-lead:#52525b;--tw-prose-links:#18181b;--tw-prose-bold:#18181b;--tw-prose-counters:#71717a;--tw-prose-bullets:#d4d4d8;--tw-prose-hr:#e4e4e7;--tw-prose-quotes:#18181b;--tw-prose-quote-borders:#e4e4e7;--tw-prose-captions:#71717a;--tw-prose-kbd:#18181b;--tw-prose-kbd-shadows:24 24 27;--tw-prose-code:#18181b;--tw-prose-pre-code:#e4e4e7;--tw-prose-pre-bg:#27272a;--tw-prose-th-borders:#d4d4d8;--tw-prose-td-borders:#e4e4e7;--tw-prose-invert-body:#d4d4d8;--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:#a1a1aa;--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:#a1a1aa;--tw-prose-invert-bullets:#52525b;--tw-prose-invert-hr:#3f3f46;--tw-prose-invert-quotes:#f4f4f5;--tw-prose-invert-quote-borders:#3f3f46;--tw-prose-invert-captions:#a1a1aa;--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:255 255 255;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:#d4d4d8;--tw-prose-invert-pre-bg:rgba(0,0,0,.5);--tw-prose-invert-th-borders:#52525b;--tw-prose-invert-td-borders:#3f3f46}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.bottom-12{bottom:3rem}.left-0{left:0}.left-8{left:2rem}.right-0{right:0}.right-8{right:2rem}.top-0{top:0}.top-1{top:.25rem}.top-32{top:8rem}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.mx-12{margin-left:3rem;margin-right:3rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-8{margin-left:2rem;margin-right:2rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.-mt-0{margin-top:0}.-mt-0\.5{margin-top:-.125rem}.-mt-1{margin-top:-.25rem}.mb-1{margin-bottom:.25rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-20{margin-bottom:5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-5{margin-left:1.25rem}.ml-8{margin-left:2rem}.ml-auto{margin-left:auto}.mr-12{margin-right:3rem}.mr-8{margin-right:2rem}.mt-10{margin-top:2.5rem}.mt-12{margin-top:3rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-20{margin-top:5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.mt-8{margin-top:2rem}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-1{height:.25rem}.h-1\/3{height:33.333333%}.h-12{height:3rem}.h-14{height:3.5rem}.h-2\/3{height:66.666667%}.h-20{height:5rem}.h-3{height:.75rem}.h-40{height:10rem}.h-8{height:2rem}.h-80{height:20rem}.h-96{height:24rem}.h-auto{height:auto}.h-fit{height:-moz-fit-content;height:fit-content}.h-full{height:100%}.max-h-\[380px\]{max-height:380px}.max-h-\[500px\]{max-height:500px}.min-h-screen{min-height:100vh}.w-1\/2{width:50%}.w-32{width:8rem}.w-60{width:15rem}.w-auto{width:auto}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.flex-1{flex:1 1 0%}.-translate-y-full{--tw-translate-y:-100%}.-translate-y-full,.translate-y-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.scale-110{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform-gpu{transform:translate3d(var(--tw-translate-x),var(--tw-translate-y),0) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-12{gap:3rem}.gap-16{gap:4rem}.gap-2{gap:.5rem}.gap-24{gap:6rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-ellipsis{text-overflow:ellipsis}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.rounded-t-xl{border-top-left-radius:.75rem;border-top-right-radius:.75rem}.border-2{border-width:2px}.border-\[0\.5px\]{border-width:.5px}.border-\[1px\]{border-width:1px}.border-b-0{border-bottom-width:0}.border-r-0{border-right-width:0}.border-solid{border-style:solid}.border-detailnav{--tw-border-opacity:1;border-color:rgb(222 226 230/var(--tw-border-opacity))}.border-indigo-400{--tw-border-opacity:1;border-color:rgb(129 140 248/var(--tw-border-opacity))}.border-indigo-600{--tw-border-opacity:1;border-color:rgb(79 70 229/var(--tw-border-opacity))}.border-neutral-200{--tw-border-opacity:1;border-color:rgb(229 229 229/var(--tw-border-opacity))}.border-neutral-400{--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity))}.bg-\[\#2196f3\]{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-300{--tw-bg-opacity:1;background-color:rgb(209 213 219/var(--tw-bg-opacity))}.bg-indigo-400{--tw-bg-opacity:1;background-color:rgb(129 140 248/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-opacity-40{--tw-bg-opacity:0.4}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-sky-500{--tw-gradient-from:#0ea5e9 var(--tw-gradient-from-position);--tw-gradient-to:rgba(14,165,233,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.to-indigo-500{--tw-gradient-to:#6366f1 var(--tw-gradient-to-position)}.fill-\[\#666666\]{fill:#666}.fill-slate-300{fill:#cbd5e1}.fill-slate-500{fill:#64748b}.p-1{padding:.25rem}.p-12{padding:3rem}.p-2{padding:.5rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pl-2{padding-left:.5rem}.pl-6{padding-left:1.5rem}.pl-8{padding-left:2rem}.pr-2{padding-right:.5rem}.pr-8{padding-right:2rem}.text-center{text-align:center}.font-kanit{font-family:var(--kanit)}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-semibold{font-weight:600}.leading-loose{line-height:2}.leading-snug{line-height:1.375}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-indigo-400{--tw-text-opacity:1;color:rgb(129 140 248/var(--tw-text-opacity))}.text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-neutral-600{--tw-text-opacity:1;color:rgb(82 82 82/var(--tw-text-opacity))}.text-neutral-700{--tw-text-opacity:1;color:rgb(64 64 64/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-\[background\]{transition-property:background;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}body{margin:0}code{word-break:break-all}.custom-scroll::-webkit-scrollbar{width:4px;height:4px;border-radius:12px}.custom-scroll::-webkit-scrollbar-thumb{border-radius:100px;background-color:#6366f1}.custom-scroll::-webkit-scrollbar-track{background-color:#f5f5f5;border-radius:100px}.custom-scroll-dark::-webkit-scrollbar{width:4px;height:4px;border-radius:12px}.custom-scroll-dark::-webkit-scrollbar-thumb{border-radius:100px;background-color:#6366f1}.custom-scroll-dark::-webkit-scrollbar-track{background-color:#262626}:is(.dark .dark\:prose-invert){--tw-prose-body:#a3a3a3;--tw-prose-headings:#e5e5e5;--tw-prose-lead:var(--tw-prose-invert-lead);--tw-prose-links:#e5e5e5;--tw-prose-bold:#e5e5e5;--tw-prose-counters:#e5e5e5;--tw-prose-bullets:#e5e5e5;--tw-prose-hr:var(--tw-prose-invert-hr);--tw-prose-quotes:#e5e5e5;--tw-prose-quote-borders:var(--tw-prose-invert-quote-borders);--tw-prose-captions:var(--tw-prose-invert-captions);--tw-prose-kbd:var(--tw-prose-invert-kbd);--tw-prose-kbd-shadows:var(--tw-prose-invert-kbd-shadows);--tw-prose-code:var(--tw-prose-invert-code);--tw-prose-pre-code:var(--tw-prose-invert-pre-code);--tw-prose-pre-bg:var(--tw-prose-invert-pre-bg);--tw-prose-th-borders:var(--tw-prose-invert-th-borders);--tw-prose-td-borders:var(--tw-prose-invert-td-borders)}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:bg-\[\#2196f3\]:hover{--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}.hover\:bg-slate-200:hover{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.hover\:bg-tag-hover:hover{--tw-bg-opacity:1;background-color:rgb(229 229 229/var(--tw-bg-opacity))}.hover\:fill-black:hover{fill:#000}.hover\:text-black:hover{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.hover\:drop-shadow-tag-hover:hover{--tw-drop-shadow:drop-shadow(0px 0px 10px rgba(99,102,241,.5));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-indigo-200:focus{--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}:is(.dark .dark\:border-dark-secondary){--tw-border-opacity:1;border-color:rgb(163 163 163/var(--tw-border-opacity))}:is(.dark .dark\:border-darkdetailnav){--tw-border-opacity:1;border-color:rgb(77 77 77/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-indigo-200){--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}:is(.dark .dark\:border-neutral-700){--tw-border-opacity:1;border-color:rgb(64 64 64/var(--tw-border-opacity))}:is(.dark .dark\:bg-\[\#2196f3\]){--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}:is(.dark .dark\:bg-\[\#363636\]){--tw-bg-opacity:1;background-color:rgb(54 54 54/var(--tw-bg-opacity))}:is(.dark .dark\:bg-dark-primary){--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity))}:is(.dark .dark\:bg-dark-secondary){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:bg-neutral-800){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:fill-\[rgb\(181\2c 181\2c 181\)\]){fill:#b5b5b5}:is(.dark .dark\:text-\[\#E5E5E5\]){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:text-dark-primary){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:text-dark-secondary){--tw-text-opacity:1;color:rgb(163 163 163/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-indigo-200){--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity))}:is(.dark .dark\:hover\:bg-\[\#2196f3\]:hover){--tw-bg-opacity:1;background-color:rgb(33 150 243/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-dark-secondary:hover){--tw-bg-opacity:1;background-color:rgb(38 38 38/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-slate-800:hover){--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-tag-dark-hover:hover){--tw-bg-opacity:1;background-color:rgb(54 54 54/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:fill-white:hover){fill:#fff}:is(.dark .dark\:hover\:text-dark-primary:hover){--tw-text-opacity:1;color:rgb(229 229 229/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-indigo-200:focus){--tw-border-opacity:1;border-color:rgb(199 210 254/var(--tw-border-opacity))}@media (min-width:640px){.sm\:flex-row{flex-direction:row}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-lg{font-size:1.125rem;line-height:1.75rem}.sm\:text-xs{font-size:.75rem;line-height:1rem}}@media (min-width:768px){.md\:block{display:block}.md\:w-4\/5{width:80%}.md\:flex-row{flex-direction:row}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-5xl{font-size:3rem;line-height:1}.md\:text-base{font-size:1rem;line-height:1.5rem}.md\:text-lg{font-size:1.125rem;line-height:1.75rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}.md\:text-xl{font-size:1.25rem;line-height:1.75rem}.md\:leading-snug{line-height:1.375}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:w-\[calc\(50\%-6\.5rem\)\]{width:calc(50% - 6.5rem)}.lg\:flex-row{flex-direction:row}.lg\:gap-52{gap:13rem}.lg\:text-lg{font-size:1.125rem;line-height:1.75rem}} \ No newline at end of file diff --git a/index.html b/index.html index 990016e..48637a5 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/Algorithm.html b/posts/Algorithm.html index 63b58b3..bcfacba 100644 --- a/posts/Algorithm.html +++ b/posts/Algorithm.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.html" "b/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.html" index 24d139e..1be60b1 100644 --- "a/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.html" +++ "b/posts/Algorithm/[\353\260\261\354\244\200 gold 5] \353\271\214\353\237\260 \355\230\270\354\204\235.html" @@ -1 +1 @@ -[백준 gold 5] 빌런 호석
\ No newline at end of file +[백준 gold 5] 빌런 호석
\ No newline at end of file diff --git "a/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.html" "b/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.html" index 2095802..abe2f2d 100644 --- "a/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.html" +++ "b/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\225\204\354\235\264\355\205\234 \354\244\215\352\270\260.html" @@ -1 +1 @@ -[프로그래머스 level 3] 아이템 줍기
\ No newline at end of file +[프로그래머스 level 3] 아이템 줍기
\ No newline at end of file diff --git "a/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.html" "b/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.html" index bc5638d..56b6e60 100644 --- "a/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.html" +++ "b/posts/Algorithm/[\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244lv3]\354\247\225\352\262\200\353\213\244\353\246\254\352\261\264\353\204\210\352\270\260.html" @@ -1 +1 @@ -[프로그래머스 level 3] 징검다리 건너기
\ No newline at end of file +[프로그래머스 level 3] 징검다리 건너기
\ No newline at end of file diff --git a/posts/Javascript.html b/posts/Javascript.html index edb8d51..7f9dda0 100644 --- a/posts/Javascript.html +++ b/posts/Javascript.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/Javascript/javascriptdeepdive09.html b/posts/Javascript/javascriptdeepdive09.html index 95fe85f..c8fd85e 100644 --- a/posts/Javascript/javascriptdeepdive09.html +++ b/posts/Javascript/javascriptdeepdive09.html @@ -1 +1 @@ -자바스크립트 딥다이브: 09.타입 변환과 단축평가
\ No newline at end of file +자바스크립트 딥다이브: 09.타입 변환과 단축평가
\ No newline at end of file diff --git a/posts/Javascript/javascriptdeepdive10.html b/posts/Javascript/javascriptdeepdive10.html index 38ece0b..cec1274 100644 --- a/posts/Javascript/javascriptdeepdive10.html +++ b/posts/Javascript/javascriptdeepdive10.html @@ -1 +1 @@ -객체 리터럴
\ No newline at end of file +객체 리터럴
\ No newline at end of file diff --git a/posts/Javascript/javascriptdeepdive11.html b/posts/Javascript/javascriptdeepdive11.html index 42bac3b..2cff5d2 100644 --- a/posts/Javascript/javascriptdeepdive11.html +++ b/posts/Javascript/javascriptdeepdive11.html @@ -1 +1 @@ -원시 값과 객체의 비교
\ No newline at end of file +원시 값과 객체의 비교
\ No newline at end of file diff --git "a/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.html" "b/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.html" index 4921d30..ae83df6 100644 --- "a/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.html" +++ "b/posts/Javascript/\355\201\264\353\241\234\354\240\200\354\227\220 \353\214\200\355\225\230\354\227\254.html" @@ -1 +1 @@ -클로저에 대하여
\ No newline at end of file +클로저에 대하여
\ No newline at end of file diff --git a/posts/React.html b/posts/React.html index 3681406..660ac0c 100644 --- a/posts/React.html +++ b/posts/React.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.html" "b/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.html" index b6a3608..9861301 100644 --- "a/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.html" +++ "b/posts/React/React useState \355\233\205\352\263\274 \355\201\264\353\241\234\354\240\200.html" @@ -1 +1 @@ -React useState 훅과 클로저
\ No newline at end of file +React useState 훅과 클로저
\ No newline at end of file diff --git "a/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.html" "b/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.html" index f6699c2..054ec03 100644 --- "a/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.html" +++ "b/posts/React/[React DeepDive] React\354\235\230 \352\260\200\354\203\201 DOM.html" @@ -1 +1 @@ -[React DeepDive] React의 가상 DOM
\ No newline at end of file +[React DeepDive] React의 가상 DOM
\ No newline at end of file diff --git a/posts/all.html b/posts/all.html index 1637d31..3502a78 100644 --- a/posts/all.html +++ b/posts/all.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/search.html b/posts/search.html index 598d5ee..428772b 100644 --- a/posts/search.html +++ b/posts/search.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/Algorithm.html b/posts/tag/Algorithm.html index 45b03f8..b0c4d69 100644 --- a/posts/tag/Algorithm.html +++ b/posts/tag/Algorithm.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/JavaScript.html b/posts/tag/JavaScript.html index 287927f..77669f7 100644 --- a/posts/tag/JavaScript.html +++ b/posts/tag/JavaScript.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/Virtual DOM.html b/posts/tag/Virtual DOM.html index 8baca5a..718f0e1 100644 --- a/posts/tag/Virtual DOM.html +++ b/posts/tag/Virtual DOM.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/all.html b/posts/tag/all.html index fa8e6b0..5dd4c72 100644 --- a/posts/tag/all.html +++ b/posts/tag/all.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/bfs.html b/posts/tag/bfs.html index a1a414a..b4a80b5 100644 --- a/posts/tag/bfs.html +++ b/posts/tag/bfs.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/deepdive.html b/posts/tag/deepdive.html index 3433d8d..4da7f0b 100644 --- a/posts/tag/deepdive.html +++ b/posts/tag/deepdive.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/dfs.html b/posts/tag/dfs.html index ddf27bc..8e8b58c 100644 --- a/posts/tag/dfs.html +++ b/posts/tag/dfs.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/gold.html b/posts/tag/gold.html index a6ab5b9..d9a3f61 100644 --- a/posts/tag/gold.html +++ b/posts/tag/gold.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/hook.html b/posts/tag/hook.html index 3df7b3a..67ff839 100644 --- a/posts/tag/hook.html +++ b/posts/tag/hook.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/lv3.html b/posts/tag/lv3.html index d8ad4b9..5a77b83 100644 --- a/posts/tag/lv3.html +++ b/posts/tag/lv3.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/react.html b/posts/tag/react.html index ea0bdca..13be719 100644 --- a/posts/tag/react.html +++ b/posts/tag/react.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/posts/tag/useState.html b/posts/tag/useState.html index 2f06776..7860bad 100644 --- a/posts/tag/useState.html +++ b/posts/tag/useState.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/tag/\353\260\261\354\244\200.html" "b/posts/tag/\353\260\261\354\244\200.html" index d9ab371..2c90243 100644 --- "a/posts/tag/\353\260\261\354\244\200.html" +++ "b/posts/tag/\353\260\261\354\244\200.html" @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/tag/\354\203\235\353\252\205\354\243\274\352\270\260.html" "b/posts/tag/\354\203\235\353\252\205\354\243\274\352\270\260.html" index cd823f4..6191b7a 100644 --- "a/posts/tag/\354\203\235\353\252\205\354\243\274\352\270\260.html" +++ "b/posts/tag/\354\203\235\353\252\205\354\243\274\352\270\260.html" @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/tag/\354\235\264\353\266\204\355\203\220\354\203\211.html" "b/posts/tag/\354\235\264\353\266\204\355\203\220\354\203\211.html" index 31f0c2f..ffce5f6 100644 --- "a/posts/tag/\354\235\264\353\266\204\355\203\220\354\203\211.html" +++ "b/posts/tag/\354\235\264\353\266\204\355\203\220\354\203\211.html" @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/tag/\355\201\264\353\241\234\354\240\200.html" "b/posts/tag/\355\201\264\353\241\234\354\240\200.html" index 70083a7..2857caf 100644 --- "a/posts/tag/\355\201\264\353\241\234\354\240\200.html" +++ "b/posts/tag/\355\201\264\353\241\234\354\240\200.html" @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git "a/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.html" "b/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.html" index 82c1122..4d176fd 100644 --- "a/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.html" +++ "b/posts/tag/\355\224\204\353\241\234\352\267\270\353\236\230\353\250\270\354\212\244.html" @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file