<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>junbro_0708.log</title>
        <link>https://velog.io/</link>
        <description>2D | 3D 프론트엔드 개발자</description>
        <lastBuildDate>Wed, 23 Apr 2025 05:58:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>junbro_0708.log</title>
            <url>https://velog.velcdn.com/images/junbro_0708/profile/ddf117d6-4ee0-4fcd-9220-ce91264623ef/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. junbro_0708.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/junbro_0708" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 땅따먹기 - 구현 (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EB%95%85%EB%94%B0%EB%A8%B9%EA%B8%B0-%EA%B5%AC%ED%98%84-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EB%95%85%EB%94%B0%EB%A8%B9%EA%B8%B0-%EA%B5%AC%ED%98%84-Python3</guid>
            <pubDate>Wed, 23 Apr 2025 05:58:16 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/12913">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="풀이-1">풀이 1</h2>
<pre><code class="language-python">import sys
sys.setrecursionlimit(10000)

answer = 0

def dfs(sum, cIndex, nRow, land):
    global answer

    if nRow == len(land):
        answer = max(answer, sum)
        return

    for i in range(4):
        if i == cIndex: continue
        dfs(sum + land[nRow][i], i, nRow + 1, land)

def solution(land):
    for i in range(4):
        dfs(land[0][i], i, 1, land)

    return answer</code></pre>
<p>처음에는 dfs 재귀함수 방식으로 풀면 되지 않을까 생각했다. 테스트 케이스는 통과하였지만, 이렇게 풀면 범위가 100,000이기 때문에 시간 초과가 생길 수 밖에 없었다. 그래서 다른 방식으로 풀이를 바꾸었다.</p>
<h2 id="풀이-2">풀이 2</h2>
<pre><code class="language-python">def solution(land):
    for i in range(1, len(land)):
        for j in range(4):
            max_value = 0
            for k in range(4):
                if j == k: continue
                max_value = max(max_value, land[i-1][k])
            land[i][j] += max_value
    return max(land[len(land) - 1])</code></pre>
<p>두번째 풀이는 누적합 방식으로 풀었다. 땅을 돌면서 현재 인덱스 값을 이전 땅의 자기 자신과 같은 인덱스 값을 제외하고 나머지 세 값을 비교하고 누적하여 더해주는 방식으로 구현하였다. 이렇게 구현하면 O(N)으로 풀 수 있었다.</p>
<p>_<span style="color: gray">(빅오표기법에서는 상수를 제외하기 때문에 N)</span>_</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>제한 사항을 보며 재귀나 bfs방식을 쓸 수 있는지 확인할 것.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 삼각 달팽이 - 구현 (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%82%BC%EA%B0%81-%EB%8B%AC%ED%8C%BD%EC%9D%B4-%EA%B5%AC%ED%98%84-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%82%BC%EA%B0%81-%EB%8B%AC%ED%8C%BD%EC%9D%B4-%EA%B5%AC%ED%98%84-Python3</guid>
            <pubDate>Wed, 26 Mar 2025 01:27:13 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/68645">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-python">def solution(n):
    num = 1
    type = 1
    idx = 0
    arr = [[] for _ in range(n)]
    answer = []

    while n &gt;= 0:
      if type % 3 == 1:
        for _ in range(0, n):
            arr[idx].insert(type // 3, num)
            num += 1
            idx += 1
        idx -= 1
      elif type % 3 == 2:
        for i in range(1, n + 1):
            arr[idx].insert(type // 3 + i, num)
            num += 1
        idx -= 1
      elif type % 3 == 0:
        for _ in range(0, n):
            arr[idx].insert(len(arr[idx]) - type // 3 + 1, num)
            num += 1
            idx -= 1
        idx += 2
      n -= 1
      type += 1

    for i in arr:
       for j in i:
          answer.append(j)

    return answer</code></pre>
<p>문제를 보고 특정한 알고리즘을 이용해 문제를 풀어야 하겠다기 보다는 단순 구현으로 문제를 풀 수 있을 것이라고 생각하였다. 그 이유는 반복되는 규칙이 많이 보였기 때문이다.</p>
<blockquote>
<ol>
<li>먼저 숫자는 왼쪽 / 아래 / 오른쪽 순으로 채워진다.</li>
<li>숫자가 채워지는 만큼은 N -&gt; N - 1 -&gt; N - 2 순으로 채워진다.</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/06f42288-2d8a-44f3-8980-91cb447ea978/image.png" alt=""></p>
<p>N이 4일 때, 1234로 왼쪽이 채워지고, 567로 아래, 89로 오른쪽, 10으로 왼쪽이 채워지는 형태이다.</p>
<p>그래서 while문으로 반복하면서 N이 0이 될때 벗어나도록 하였고, 왼쪽, 아래, 왼쪽에 대한 분기를 타서 번호를 삽입하도록 진행하였다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>X</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 11724] Silver 2 연결 요소의 개수 - DFS (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-11724-Silver-2-%EC%97%B0%EA%B2%B0-%EC%9A%94%EC%86%8C%EC%9D%98-%EA%B0%9C%EC%88%98-DFS-Python3</link>
            <guid>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-11724-Silver-2-%EC%97%B0%EA%B2%B0-%EC%9A%94%EC%86%8C%EC%9D%98-%EA%B0%9C%EC%88%98-DFS-Python3</guid>
            <pubDate>Tue, 18 Mar 2025 06:53:25 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://www.acmicpc.net/problem/11724">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="py">PY</h2>
<pre><code class="language-python">import sys
input = sys.stdin.readline
sys.setrecursionlimit(10000)

N, M = map(int, input().split())
graph = [[] for _ in range(1001)]
isVisited = [False] * 1001
answer = 0

for i in range(M):
  x, y = map(int, input().split())
  graph[x].append(y)
  graph[y].append(x)

def dfs(node):
  isVisited[node] = True

  for i in graph[node]:
    if not isVisited[i]:
      dfs(i)
  return

for i in range(1, N + 1):
  if not isVisited[i]:
    dfs(i)
    answer += 1

print(answer)</code></pre>
<h1 id="풀이">풀이</h1>
<p>DFS의 기본이 되는 문제이다.</p>
<p>재귀 함수를 이용해서 문제를 풀었고, 
방문이 되어있지 않을 때 정답을 1씩 더해주었다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>파이썬에서는 재귀를 할 때 안정적인 계산을 위해 1000번의 제한을 두고 있다. 처음에는 이러한 환경으로 백준에서 런타임 에러가 발생했는데 sys.setrecursionlimit(10000)을 통해 재귀 횟수를 늘려주어 문제를 해결했다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 11003] Platinum 5 최솟값 찾기 - 슬라이딩 윈도우 (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-11003-Platinum-5-%EC%B5%9C%EC%86%9F%EA%B0%92-%EC%B0%BE%EA%B8%B0-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%94%A9-%EC%9C%88%EB%8F%84%EC%9A%B0-Python3</link>
            <guid>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-11003-Platinum-5-%EC%B5%9C%EC%86%9F%EA%B0%92-%EC%B0%BE%EA%B8%B0-%EC%8A%AC%EB%9D%BC%EC%9D%B4%EB%94%A9-%EC%9C%88%EB%8F%84%EC%9A%B0-Python3</guid>
            <pubDate>Sun, 16 Mar 2025 07:21:55 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://www.acmicpc.net/problem/11003">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="py">PY</h2>
<pre><code class="language-python">from collections import deque
import sys
input = sys.stdin.readline

N, L = map(int, input().split())
numbers = list(map(int, input().split()))
window = deque()

for (i, num) in enumerate(numbers):
  while window and window[-1][1] &gt; num:
    window.pop()
  window.append((i, num))
  if window[0][0] &lt; i - L + 1: window.popleft()
  print(window[0][1], end=&#39; &#39;)</code></pre>
<h1 id="풀이">풀이</h1>
<p>범위가 엄청 크면서 배열 안의 부분을 이동하면서 체크해야할 때는 슬라이딩 윈도우를 사용하는 것이 적합하다.</p>
<blockquote>
<p>12 3
1 5 2 3 6 2 3 7 3 5 2 6</p>
</blockquote>
<p>이렇게 입력을 받았을 때,</p>
<pre><code>[1]
[1, 5]
[1, 5, 2]
[5, 2, 3]</code></pre><p>이런 식으로 범위를 정한 다음에 최솟값을 구해야한다. 다만, 배열의 길이와 슬라이딩 배열의 최대 크기가 5000000이기 때문에 순회하면서 또 최솟값을 구하고 하기에는 무리가 있다.</p>
<p>슬라이딩 윈도우를 사용하면 최솟값을 구하는 반복을 최소화할 수 있다.
해당 부분에서 처음으로 deque를 사용했다.
일반적인 리스트의 pop(0)과 deque의 popleft은 성능차이가 있기 때문이다.</p>
<p>먼저 입력 받은 숫자들을 순회하면서 덱의 끝 숫자와 넣을 숫자를 비교해주고, 덱의 끝 숫자가 더 크면 pop을 한다.</p>
<p>그런 다음에 덱에 숫자를 넣어준다. 이때 인덱스와 함께 튜플의 형태로 넣어주는데 슬라이딩 윈도우의 범위를 가져야하기 때문에 덱의 맨 앞 원소의 인덱스를 검사해주고 범위를 벗어나면 popleft 해주어야 하기 때문이다.</p>
<p>이러한 과정을 거치면서 계속 덱의 맨 앞 원소의 값을 출력해주면 최솟값을 쉽게 찾을 수 있다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>덱을 임포트 할 때 from collections import deque</li>
<li>window = deque()</li>
<li>popleft, appendleft는 모두 시간 복잡도가 O(1)이다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프론트엔드] useInfiniteQuery와 IntersectionObserver를 통한 무한 스크롤 기능 구현하기]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-useInfiniteQuery%EC%99%80-IntersectionObserver%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-useInfiniteQuery%EC%99%80-IntersectionObserver%EB%A5%BC-%ED%86%B5%ED%95%9C-%EB%AC%B4%ED%95%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 15 Mar 2025 11:58:49 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>팀원들과 스터디를 진행하면서 어떤 프로젝트를 진행할 지 고민하였고, 구현 보다는 설계 측면에서 어떻게 api를 연동하고 최적화를 진행할 지에 대한 고민을 하였다.</p>
<p>그래서 구글링을 하던 중 개발자 한 분이 웹툰 정보를 모아서 뿌려주는 api를 개발하셨고, 포스팅 해둔 글을 발견하였고, 이 api를 활용해보자고 결정하였다.</p>
<blockquote>
<p><a href="https://hyeokjaelee.github.io/korea-webtoon-api-update/">https://hyeokjaelee.github.io/korea-webtoon-api-update/</a></p>
</blockquote>
<p>_<span style="color:#3333">(감사합니다 개발자님...)<span/>_</p>
<p>다들 다양하게 api를 활용해서 구현을 진행하였는데, 나는 리액트 쿼리를 활용해서 페이지네이션을 하는데스크롤이 아래쯤으로 내려오면 데이터를 로드해서 무한 스크롤 비슷하게 만들어보면 어떨까 생각하였다.</p>
<p>  그래서 tanstack-qeury의 useInfiniteQuery와 IntersectionObserver를 통한 무한스크롤 기능에 중점을 두고 스터디를 임하였다.</p>
<h1 id="본론">본론</h1>
<h2 id="api-연동">API 연동</h2>
<pre><code class="language-typescript">  // webtoonApi.ts
...

  export const fetchWebtoons = async ({
    keyword,
    provider,
    isFree,
    updateDays,
    isUpdated,
    page,
  }: webtoonQueryType) =&gt; {
    const params = Object.fromEntries(
      Object.entries({ keyword, provider, isFree, updateDays, isUpdated }).filter(
        ([, value]) =&gt; value !== &quot;&quot; &amp;&amp; value !== &quot;ALL&quot; &amp;&amp; value !== false
      )
    );

    const { data } = await axiosInstance.get(&quot;/webtoons&quot;, {
      params: {
        ...params,
        page: page,
      },
    });
    return {
      data: data.webtoons, // 웹툰 리스트 반환
      isLastPage: data.isLastPage, // 마지막 페이지 여부 반환
    };
};
</code></pre>
<p>  API를 보면 쿼리스트링을 통해 데이터를 필터링한 후 가져올 수 있다. 이미 페이지네이션 기능도 제공을 하기 때문에 저렇게 page를 넣어주었다.</p>
<p>  Object를 필터링하는 이유는 사용자가 값을 입력하지 않았다면 쿼리스트링에 포함하지 않기 위해서이다. </p>
<p>  예를 들어서, provider는 KAKAO, KAKAO_PAGE, NAVER 이렇게 인데 사용자가 아무런 입력을 하지 않았다면 ALL로 설정을 해두었다. 하지만 파라미터 값이 들어갈 때 ALL이 들어가면 API에서 제공하는 값이 아니기 때문에 오류가 날 수 있다. 그래서 API를 요청하기 전에 한 번 필터링을 거치는 것이다.</p>
<p>_<span style="color:#3333">(ALL이라는 값은 클라이언트에서 사용하는 값이라 서버 쪽에서는 어떤 값인지 알 수 없다는 뜻)<span/>_</p>
<pre><code class="language-typescript">  // useWebtoonQuery.ts
...

  export const useWebtoonsQuery = (filters: webtoonQueryType) =&gt; {
    const { keyword, provider, isFree, updateDays, isUpdated } = useSearchStore();

    return useInfiniteQuery({
      queryKey: [&quot;webtoons&quot;, keyword, provider, isFree, updateDays, isUpdated],
      queryFn: ({ pageParam = 1 }) =&gt;
        fetchWebtoons({ ...filters, page: pageParam }),
      getNextPageParam: (lastPage, allPages) =&gt; {
        // 마지막 페이지인지 확인 후 증가
        return lastPage.isLastPage ? undefined : allPages.length + 1;
      },
      initialPageParam: 1,
    });
};</code></pre>
<p>  쿼리 부분에서는 기본적인 useQuery를 사용하지 않고, useInfiniteQuery를 사용하였다.</p>
<h2 id="usequery와-useinfinitequery의-차이점">useQuery와 useInfiniteQuery의 차이점</h2>
<p>  <strong>useQuery</strong>는 요청을 한 번 보내는 쿼리이고 <strong>useInfiniteQuery</strong>는 요청을 보낸 다음에 추가 요청을 보낼 수 있는 쿼리이다.</p>
<p>  getNextPageParam 메서드를 통해 추가 요청을 보내고 데이터를 쌓아나갈 수 있다. 또 특이한 점은 useInfiniteQuery는 queryFn에 pageParam을 받아야한다. 그리고 옵션으로 initialPageParam 통해 초기 페이지 값을 정해줄 수 있다.</p>
<pre><code>  |  | `useQuery` | `useInfiniteQuery` |</code></pre><p>|---|---|---|
| <strong>데이터 요청 방식</strong> | 한 번만 가져옴 | 추가 데이터를 계속 요청 가능 |
| <strong>사용 예시</strong> | 유저 정보, 특정 게시물 상세 | 무한 스크롤, 더 보기 버튼 |
| <strong>다음 페이지 로딩</strong> | ❌ (지원 안 함) | ✅ (<code>fetchNextPage</code> 사용) |
| <strong>데이터 저장 방식</strong> | 한 번만 저장 | 여러 페이지 데이터를 누적 |</p>
<h2 id="intersectionobserver를-통한-데이터-로드">IntersectionObserver를 통한 데이터 로드</h2>
<p>  다음 페이지를 가져오도록 쿼리를 사용했으니 트리거를 달아줘야한다.</p>
<p>  스크롤이 끝 지점이 다다랐을 때, <strong>fetchNextPage</strong>를 호출해서 다음 페이지를 불러오는 작업을 진행한다.</p>
<pre><code class="language-typescript">
  ...

  const WebtoonList = () =&gt; {

    ...

    // 스크롤 감지 로직
    useEffect(() =&gt; {
      if (!observerRef.current) return;

      const observer = new IntersectionObserver(
        (entries) =&gt; {
          if (entries[0].isIntersecting) {
            fetchNextPage();
          }
        },
        { threshold: 0.8 } // 80% 지점에서 감지
      );

      observer.observe(observerRef.current);
      return () =&gt; observer.disconnect();
    }, [fetchNextPage, isLoading]);

    if (isLoading) return &lt;p&gt;로딩 중...&lt;/p&gt;;
    if (!webtoons || webtoons.pages.length === 0)
      return &lt;p&gt;검색 결과가 없습니다.&lt;/p&gt;;

    return (
      &lt;&gt;
        &lt;div className=&quot;flex flex-wrap justify-center gap-x-3 gap-y-3&quot;&gt;
          {webtoons.pages.map((page) =&gt;
            page.data.map((webtoon: webtoonType) =&gt; (
              &lt;WebtoonItem key={webtoon.id} webtoon={webtoon} /&gt;
            ))
          )}

          {/* 스크롤 감지 요소 */}
          &lt;div className=&quot;h-[10px]&quot; ref={observerRef} /&gt;
        &lt;/div&gt;
        {/* 로딩 상태 표시 */}
        {isFetchingNextPage &amp;&amp; (
          &lt;p className=&quot;text-center text-gray-500&quot;&gt;로딩 중...&lt;/p&gt;
        )}
      &lt;/&gt;
    );
};

export default WebtoonList;</code></pre>
<p>  IntersectionObserver는 요소가 화면에 보이는지 감지하는 웹 API로, 뷰포트에 감지가 되면 특정한 콜백 함수를 호출하는 기능을 가지고 있다. 그래서 스크롤 이벤트를 하지 않아도 특정 구간에서 함수를 호출할 수 있다. (성능 우위)</p>
<p>  IntersectionObserver는 두 가지 매개 변수를 받는데 콜백 함수와 옵션 값을 받는다. 먼저 콜백함수는 인자로 감지한 요소들의 배열과 옵저버를 받을 수 있다.</p>
<blockquote>
<p>entries → 감지한 요소들의 배열
entry.isIntersecting → 뷰포트에 보이면 true
observer.observe(target) → 감지할 요소 지정
observer.unobserve(target) → 감지 중지 (필요 없으면 해제 가능)</p>
</blockquote>
<p>  위와 같이 특정한 조건에서 감지를 중지할 수도 있고, 감지가 되었는지 판단할 수도 있다.</p>
<pre><code class="language-typescript">const options = {
  root: null, // 뷰포트 기준 (null이면 화면 자체가 기준)
  rootMargin: &quot;0px&quot;, // 감지 범위 확장/축소 가능 (ex. &quot;100px 0px&quot; → 위로 100px 더 감지)
  threshold: 0.5, // 50% 이상 보이면 감지
};</code></pre>
<p>  두번째 매개변수인 옵션은 객체의 형태로 넣어주어야하고 위와 같은 옵션이 있다. threshold를 자주 사용한다.</p>
<h1 id="결론">결론</h1>
<p>  이러한 기술들을 이용하여 무한 스크롤 기능을 구현한 프로젝트는 아래와 같이 동작을 하게 됐다!</p>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/732b3863-6336-4807-abb3-272ee68be541/image.gif" alt=""></p>
<p>_<span style="color:#3333">(디자인은 신경쓰지 말아주세요.. 기능만 고려를 해봤습니다..!)<span/>_</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 1253] Gold 4 좋다 - 투포인터 (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-1253-Gold-4-%EC%A2%8B%EB%8B%A4-%ED%88%AC%ED%8F%AC%EC%9D%B8%ED%84%B0-Python3</link>
            <guid>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-1253-Gold-4-%EC%A2%8B%EB%8B%A4-%ED%88%AC%ED%8F%AC%EC%9D%B8%ED%84%B0-Python3</guid>
            <pubDate>Sat, 15 Mar 2025 05:43:44 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://www.acmicpc.net/problem/1253">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="py">PY</h2>
<pre><code class="language-python">import sys
input = sys.stdin.readline

n = int(input())
numbers = list(map(int, input().split()))
numbers.sort()

cnt = 0
for idx, number in enumerate(numbers):
  start_idx, end_idx = 0, n - 1

  while start_idx &lt; end_idx:
    sum = numbers[start_idx] + numbers[end_idx]

    if sum == number:
      if start_idx == idx: start_idx += 1
      elif end_idx == idx: end_idx -= 1
      else:
        cnt += 1
        break
    elif sum &lt; number:
      start_idx += 1
    else:
      end_idx -= 1

print(cnt)</code></pre>
<h1 id="풀이">풀이</h1>
<p><strong>투 포인터</strong> 알고리즘을 이용하여 문제를 풀었다.</p>
<p>배열을 입력받은 후에 정렬을 한 뒤, 인덱스를 시작 지점과 끝 지점에 두고 해당 인덱스에서의 숫자 합을 비교한다. 하지만 이때 타겟 인덱스가 두 인덱스와 같으면 안되기 때문에 거기에 대한 분기를 타주었다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>투포인터 알고리즘을 사용하여 문제를 푼다고 했을 때는 시작 인덱스와 끝 인덱스를 시작으로 인덱스를 바꿔가면서 수를 비교해야하기 때문에 배열이 정렬되어있어야한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준 10986] Gold 3 나머지 합 구하기 - 구간합 (Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-10986-Gold-3-%EB%82%98%EB%A8%B8%EC%A7%80-%ED%95%A9-%EA%B5%AC%ED%95%98%EA%B8%B0-%EA%B5%AC%EA%B0%84%ED%95%A9-Python3</link>
            <guid>https://velog.io/@junbro_0708/%EB%B0%B1%EC%A4%80-10986-Gold-3-%EB%82%98%EB%A8%B8%EC%A7%80-%ED%95%A9-%EA%B5%AC%ED%95%98%EA%B8%B0-%EA%B5%AC%EA%B0%84%ED%95%A9-Python3</guid>
            <pubDate>Thu, 13 Mar 2025 07:58:57 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://www.acmicpc.net/problem/10986">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="py">PY</h2>
<pre><code class="language-python">import sys
input = sys.stdin.readline

answer = 0
m, n = map(int, input().split())
numbers = list(map(int, input().split()))
spatial_sum = [0] * m
modified_sum = [0] * n

spatial_sum[0] = numbers[0]
for i in range(1, len(numbers)):
  spatial_sum[i] = numbers[i] + spatial_sum[i - 1]

for sum in spatial_sum:
  if sum % n == 0: answer += 1
  modified_sum[sum % n] += 1

for sum in modified_sum:
  answer += sum * (sum - 1) // 2

print(answer)</code></pre>
<h1 id="풀이">풀이</h1>
<blockquote>
<p>5 3
1 2 3 1 2</p>
</blockquote>
<p>위와 같이 입력을 받는다고 하면 먼저 구간합을 구해보자.</p>
<blockquote>
<p>1 3 6 7 9</p>
</blockquote>
<p>이렇게 될 것이다. 이러면 일단 순서대로 더했을 때의 나머지를 구할 수 있다. 나머지를 구해보면</p>
<blockquote>
<p>1 0 0 1 0 -&gt; arr</p>
</blockquote>
<p>이렇게 나온다. 그러면 일단 0인 애들은 나누어 떨어지기 때문에 카운트를 세준다.</p>
<p>그 다음부터는 새롭게 알게 된 사실인데 나머지 값이 같은 애들끼리 <strong>두 개를 조합할 수 있는 경우의 수를 구한다.</strong></p>
<p>나머지를 구한 배열을 arr이라고 하면,
arr[0]과 arr[3]은 1로 원소가 같고,
arr[1], arr[2], arr[4]는 0으로 원소가 같다.</p>
<p>arr[0]의 구간합은 1이고 arr[3]의 구간합은 7이다.
7 - 1은 6으로 나누어 떨어진다.</p>
<p>arr[1], arr[2], arr[4]도 같은 방식이다.
arr[2]의 구간합은 6이고 arr[4]의 구간합은 9이다.
9 - 6은 3으로 나누어 떨어진다.</p>
<p>이런 방식으로 나머지가 같은 애들끼리 두 개를 조합하면 갯수를 확인할 수 있다.
<em>(두 개인 이유는 시작점과 끝점으로 두 개인 것)</em></p>
<p>이렇게 해서 모든 경우의 수를 계산하면 3 + 3 + 1 = 7 이렇게 나온다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li><p>프로그래머스랑 백준이랑 정답 체크 방식이 달라서 입력 출력하는데 신경 쓸 필요가 있다. 원래는 input() 만을 사용해서 풀었었는데 그럴 경우 너무 느려졌는데 다음과 같은 이유가 있었다.</p>
<p>input() 은 매개변수로 prompt message를 받음
입력받은 값의 개행 문자를 삭제시키고 반환함.</p>
<p>그래서 아래처럼 전처리 과정이 필요하다.</p>
<pre><code class="language-python">import sys
input = sys.stdin.readline

m, n = map(int, input().split())
numbers = list(map(int, input().split()))</code></pre>
</li>
<li><p>경우의 수를 구하는 공식은</p>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/1e2bea31-efee-4fcf-8863-3726de5ca7bf/image.png" alt=""></p>
<p>만약에 원소가 세 개 있고 거기서 두 개로 조합을 하면 n = 3, k = 2가 되는 것이다. 그렇게 되면 3 * 2 / 2 = 3이 나온다.</p>
<p>백준 문제는 자바스크립트로 작성하기 너무 귀찮아서 파이썬으로만..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 서버 증설 횟수 - 구현 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%84%9C%EB%B2%84-%EC%A6%9D%EC%84%A4-%ED%9A%9F%EC%88%98-%EA%B5%AC%ED%98%84-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%84%9C%EB%B2%84-%EC%A6%9D%EC%84%A4-%ED%9A%9F%EC%88%98-%EA%B5%AC%ED%98%84-Javascript-Python3</guid>
            <pubDate>Wed, 12 Mar 2025 08:11:09 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/389479">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(players, m, k) {
    let answer = 0;
    let server = [];

    for(const player of players){
        server.forEach((val, idx) =&gt; server[idx]--);
        server = server.filter(val =&gt; val &gt; 0);

        const available_players = server.length * m + m - 1;
        if(player &gt; available_players) {
            let temp = available_players;
            while(temp &lt; player){
                server.push(k);
                temp += m;
                answer++;
            }
        }
    }
    return answer;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def solution(players, m, k):
    answer = 0
    server = []

    for player in players:
        server = [val - 1 for val in server]
        server = [val for val in server if val &gt; 0]

        available_players = len(server) * m + m - 1
        if player &gt; available_players:
            temp = available_players
            while temp &lt; player:
                temp += m
                server.append(k)
                answer += 1
    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>Level2의 문제 치고는 쉬운 편이다.</p>
<p>시간을 돌면서 플레이어와 수용 가능한 플레이어의 수를 비교한 다음,
서버를 추가해야할 경우라면 while 문을 통해 서버를 추가해주고 카운팅을 한다.</p>
<p>이후 for문을 돌면서 서버의 시간을 1씩 줄여주고 0이 되면 배열에서 없애준다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>파이썬에서 리스트 컴프리헨션에 익숙해져야할 필요가 있다.<pre><code class="language-python"> server = [val - 1 for val in server]
 server = [val for val in server if val &gt; 0]</code></pre>
위 방법을 통해서 서버에 새로운 배열을 만들어 줄 수 있다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 조이스틱
 - 그리디 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1-%EA%B7%B8%EB%A6%AC%EB%94%94-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1-%EA%B7%B8%EB%A6%AC%EB%94%94-Javascript-Python3</guid>
            <pubDate>Sun, 09 Mar 2025 07:17:04 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42860">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(name) {
    let answer = 0;
    const dict = {};

    // char 인덱스 정의
    const alphabet = [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39;, &#39;K&#39;, &#39;L&#39;, &#39;M&#39;, &#39;N&#39;, &#39;O&#39;, &#39;P&#39;, &#39;Q&#39;, &#39;R&#39;, &#39;S&#39;, &#39;T&#39;, &#39;U&#39;, &#39;V&#39;, &#39;W&#39;, &#39;X&#39;, &#39;Y&#39;, &#39;Z&#39;];
    alphabet.map((idx, val) =&gt; dict[idx] = val);

    // 알파벳을 앞으로 돌지 뒤로 돌지 판별
    for(const word of name) 
        answer += Math.min(dict[word], Math.abs(26 - dict[word]));

    // 경우의 수 1. 그냥 순회 2. 오른쪽으로 갔다가 뒤로 가기 3. 왼쪽으로 갔다가 오른쪽으로 가기
    let move = name.length - 1; // 1번
    let j = 0;
    for(let i = 0; i &lt; name.length; ++i) {
        j = i + 1; // 현재 인덱스 다음부터 A가 아닌 인덱스
        while(j &lt; name.length &amp;&amp; dict[name[j]] === dict[&#39;A&#39;]) j++;
        move = Math.min(move, Math.min(i + i + (name.length - j), (name.length - j) + (name.length - j) + i))
    }

    return answer + move;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def solution(name):
    answer = 0

    move = len(name) - 1
    y = 0
    for idx, word in enumerate(name):
        answer += min(ord(word) - ord(&#39;A&#39;), abs(ord(&#39;Z&#39;) - ord(word) + 1))
        y = idx + 1
        while y &lt; len(name) and name[y] == &#39;A&#39;: y += 1
        move = min(move, min(idx + idx + len(name) - y, len(name) - y + len(name) - y + idx))

    return answer + move</code></pre>
<h1 id="풀이">풀이</h1>
<p>탐욕법은 너무 어렵다..
먼저 탐욕법은 여러 가지 경우의 수를 생각해서 최소의 경우를 구하는 방법이다.
탐욕법을 풀면서 팁은 여러 가지 경우의 수를 판단한 다음 최솟값 구하는 메서드를 사용하는 것이다.</p>
<p>먼저, 두 개의 과정을 거쳐야한다.</p>
<pre><code>1. 알파벳을 앞으로 카운트할지 뒤로 카운트할지
2. 문자를 오른쪽으로 갈지 왼쪽으로 갈지</code></pre><p>첫 번째 과정은 쉽다.
문자가 26개가 있으니 앞으로 카운트한 것과 뒤로 카운트한 것의 최솟값을 구하는 것</p>
<p>두 번째 과정이 정말 어려웠다.
두 번째 과정은 세 개의 경우의 수가 있다.</p>
<pre><code>1. 가장 쉬운 그냥 순서대로 체크
2. 오른쪽으로 갔다가 왼쪽으로 가는 경우
3. 왼쪽으로 갔다가 오른쪽으로 가는 경우</code></pre><p>모든 문자를 순회하면서 세 가지의 경우의 수를 체크해주어야한다.
일단 현재 인덱스와 현재 인덱스 다음으로 오는 A가 아닌 문자를 체크한다.
그 다음 현재 인덱스에서 위 세 가지의 경우의 수를 구하고 비교를 한다.</p>
<p>그 다음 두 개의 과정에서 얻은 수를 더하면 결과값이 나온다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>자바스크립트에서 아스키코드 값을 얻으려면 charCodeAt, 파이썬에서는 ord 메서드를 사용한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 1 동영상 재생기
 - 구현 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EB%8F%99%EC%98%81%EC%83%81-%EC%9E%AC%EC%83%9D%EA%B8%B0-%EA%B5%AC%ED%98%84-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EB%8F%99%EC%98%81%EC%83%81-%EC%9E%AC%EC%83%9D%EA%B8%B0-%EA%B5%AC%ED%98%84-Javascript-Python3</guid>
            <pubDate>Fri, 07 Mar 2025 06:03:05 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/340213">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(video_len, pos, op_start, op_end, commands) {
  const convertTime = (str) =&gt; {
    const [mm, ss] = str.split(&quot;:&quot;);
    return Number(mm) * 60 + Number(ss);
  };

  const v_len = convertTime(video_len);
  const o_start = convertTime(op_start);
  const o_end = convertTime(op_end);

  let c_pos = convertTime(pos);

  for (const command of commands) {
    if (c_pos &lt; 0) c_pos = 0;
    if (c_pos &gt; v_len) c_pos = v_len;
    if (c_pos &gt;= o_start &amp;&amp; c_pos &lt;= o_end) c_pos = o_end;

    switch (command) {
      case &quot;next&quot;:
        c_pos += 10;
        break;
      case &quot;prev&quot;:
        c_pos -= 10;
        break;
    }
  }

  if (c_pos &lt; 0) c_pos = 0;
  if (c_pos &gt; v_len) c_pos = v_len;
  if (c_pos &gt;= o_start &amp;&amp; c_pos &lt;= o_end) c_pos = o_end;

  const mm = Math.floor((c_pos / 60).toString());
  const ss = (c_pos % 60).toString();

  return String(mm).padStart(2, &quot;0&quot;) + &quot;:&quot; + String(ss).padStart(2, &quot;0&quot;);
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def convertTime(str):
    [mm, ss] = map(int, str.split(&quot;:&quot;))
    return mm * 60 + ss

def solution(video_len, pos, op_start, op_end, commands):
    c_pos = convertTime(pos)
    v_len = convertTime(video_len)
    o_s = convertTime(op_start)
    o_e = convertTime(op_end)

    for command in commands:
        if c_pos &gt;= o_s and c_pos &lt;= o_e: c_pos = o_e
        if command == &quot;next&quot;: c_pos = min(v_len, c_pos + 10)
        elif command == &quot;prev&quot;: c_pos = max(0, c_pos - 10)

    if c_pos &gt;= o_s and c_pos &lt;= o_e: c_pos = o_e

    return str(c_pos // 60).zfill(2) + &quot;:&quot; + str(c_pos % 60).zfill(2)</code></pre>
<h1 id="풀이">풀이</h1>
<p>이 문제도 단순 구현 문제인데 마지막에 0을 채우는 방법이 떠오르지 않아 애를 먹은 문제였다. </p>
<p>자바스크립트를 이용해서 먼저 문제를 풀었는데 코드를 조금 더 간결하게 만들 수 있을 것 같았다. 그래서 파이썬으로는 좀 더 코드를 간결화하는데 집중해서 문제를 풀었다. 저렇게 범위를 넘어가는 경우가 있을 때는 조건문을 통해 처리하기보다는 저렇게 최대, 최소로 비교하는 방법이 훨씬 깔끔한 것 같다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>자바스크립트에서 왼쪽에 문자를 채울 때는 String().padStart(길이, &quot;넣을 문자&quot;)</li>
<li>파이썬에서 왼쪽에 문자를 채울 때는 str().zfill(2) 하면 자동으로 0을 채워준다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 1 붕대 감기 - 구현 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EB%B6%95%EB%8C%80-%EA%B0%90%EA%B8%B0-%EA%B5%AC%ED%98%84-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EB%B6%95%EB%8C%80-%EA%B0%90%EA%B8%B0-%EA%B5%AC%ED%98%84-Javascript-Python3</guid>
            <pubDate>Thu, 06 Mar 2025 11:42:46 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/250137">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(bandage, health, attacks) {
    let answer = health;
    const turn = attacks[attacks.length - 1][0];

    let cnt = 0;
    for(let i = 0; i &lt; turn; ++i) {
        if (i + 1 === attacks[0][0]) {
            answer -= attacks[0][1];
            cnt = 0;
            attacks.shift();
        } else{
            cnt++;
            answer += bandage[1];

            if(cnt === bandage[0]) {
                answer += bandage[2];
                cnt = 0;
            }

            if(answer &gt;= health) answer = health;
        }

        if(answer &lt;= 0) return -1;
    }
    return answer;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def solution(bandage, health, attacks):
    answer = health
    turn = attacks[len(attacks) - 1][0]

    cnt = 0
    for i in range(1, turn + 1):
        if i == attacks[0][0]:
            answer -= attacks[0][1]
            cnt = 0
            del attacks[0]
        else:
            cnt += 1
            answer += bandage[1]
            if cnt == bandage[0]:
                answer += bandage[2]
                cnt = 0
            if answer &gt; health: answer = health

        if answer &lt;= 0: return -1

    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>단순 구현 문제이다.
최대한 반복하는 횟수를 줄여보고 싶었는데 나의 머리로는 잘 생각이 안나서
공격이 끝나는 횟수만큼 한 턴씩 움직이게끔 구현하였다..</p>
<p>처리만 잘해주면 공격하는 횟수만큼만 돌면 될 것 같은데..</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>파이썬에서 앞 원소를 삭제할 때 del 키워드를 사용한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 피로도 - 완전탐색 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%ED%94%BC%EB%A1%9C%EB%8F%84-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%ED%94%BC%EB%A1%9C%EB%8F%84-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89-Javascript-Python3</guid>
            <pubDate>Tue, 04 Mar 2025 07:06:43 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/87946">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(k, dungeons) {
    let answer = Number.MIN_SAFE_INTEGER;
    const visited = new Array(dungeons.length).fill(false);

    const dfs = (health, dungeons, cnt) =&gt; {
        answer = Math.max(answer, cnt);

        for(let i = 0; i &lt; dungeons.length; ++i) {
            if (health &lt; dungeons[i][0] || health - dungeons[i][1] &lt; 0 || visited[i]) continue;
            visited[i] = true;
            dfs(health - dungeons[i][1], dungeons, cnt + 1);
            visited[i] = false;
        }
    }

    dfs(k, dungeons, 0);
    return answer;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">import sys

def solution(k, dungeons):
    answer = -sys.maxsize
    visited = [False for _ in range(len(dungeons))]

    def dfs(health, dungeons, cnt):
        nonlocal answer
        answer = max(answer, cnt)

        for idx, dungeon in enumerate(dungeons):
            if(visited[idx] or health &lt; dungeons[idx][0] or health - dungeons[idx][1] &lt; 0):
                continue
            visited[idx] = True
            dfs(health - dungeons[idx][1], dungeons, cnt + 1)
            visited[idx] = False

    dfs(k, dungeons, 0)
    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>DFS의 정석인 문제</p>
<p>모든 경우의 수를 탐색해야하고 범위가 크지 않을 때 DFS 고려해봐야한다.
재귀함수를 통해 문제를 해결했는데 방문 체크를 하는 것과 동시에 조건에 맞으면 재귀한다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>파이썬에서 함수 내부에서 전역 변수를 수정하려고 하면 nonlocal 키워드가 필요하다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 1 유연근무제 - 2025 프로그래머스 코드챌린지 1차 예선 (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EC%9C%A0%EC%97%B0%EA%B7%BC%EB%AC%B4%EC%A0%9C-2025-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%BD%94%EB%93%9C%EC%B1%8C%EB%A6%B0%EC%A7%80-1%EC%B0%A8-%EC%98%88%EC%84%A0-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EC%9C%A0%EC%97%B0%EA%B7%BC%EB%AC%B4%EC%A0%9C-2025-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%BD%94%EB%93%9C%EC%B1%8C%EB%A6%B0%EC%A7%80-1%EC%B0%A8-%EC%98%88%EC%84%A0-Javascript-Python3</guid>
            <pubDate>Sun, 02 Mar 2025 12:56:44 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/388351">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(schedules, timelogs, startday) {
  let answer = 0;

  timelogs.map((timelog, idx) =&gt; {
    let flag = true,
      day = startday - 1;

    for (const table of timelog) {
      day++;
      if (day === 6 || day === 7) continue;

      const tHour = Math.floor(Number(table) / 100),
        tMinute = Number(table) % 100;
      const sHour = Math.floor(Number(schedules[idx]) / 100),
        sMinute = Number(schedules[idx] % 100);
      const diff = (tHour - sHour) * 60 + (tMinute - sMinute);
      if (diff &gt; 10) flag = false;

      if (day &gt; 7) day = 1;
    }
    if (flag) answer++;
  });
  return answer;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def solution(schedules, timelogs, startday):
    answer = 0

    def convertTime(time):
        h = time // 100
        m = time % 100
        return h * 60 + m

    for idx, timelog in enumerate(timelogs):
        s = startday - 1
        flag = True
        for table in timelog:
            s += 1
            if s in [6, 7]:
                continue
            elif s &gt; 7:
                s = 1

            if convertTime(table) - convertTime(schedules[idx]) &gt; 10:
                flag = False

        if flag:
            answer += 1
    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>구현 문제였는데 실수한 부분이 나눗셈을 할 때 소수부를 신경쓰지 않았던 점이다.
이 부분 때문에 시간이 지체됐다.
조금 더 계산할 때 신경써주어야할 것 같다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li><p>파이썬에서 나눗셈을 할 때 / 이면 소수부까지 // 이면 정수부에 대한 몫만 구하는 것</p>
</li>
<li><p>enumerate를 통해 value, idx를 한 번에 받아올 수 있다.</p>
</li>
<li><p>파이썬에서는 in 배열을 통해서 쉽게 포함되어있는지 확인할 수 있다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 1 개인정보 수집 유효기간 - 2023 KAKAO BLIND RECRUITMENT (Javascript, Python3)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84-2023-KAKAO-BLIND-RECRUITMENT-Javascript-Python3</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84-2023-KAKAO-BLIND-RECRUITMENT-Javascript-Python3</guid>
            <pubDate>Sun, 02 Mar 2025 08:10:30 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/150370">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<h2 id="js">JS</h2>
<pre><code class="language-javascript">function solution(today, terms, privacies) {
  var answer = [];

  privacies.map((privacy, index) =&gt; {
    const [date, type] = privacy.split(&quot; &quot;);
    const [year, month, day] = date.split(&quot;.&quot;);
    const [tYear, tMonth, tDay] = today.split(&quot;.&quot;);

    const duration =
      Number(tYear - year) * 12 * 28 +
      Number(tMonth - month) * 28 +
      Number(tDay - day);

    terms.map((term) =&gt; {
      const [targetType, targetMonth] = term.split(&quot; &quot;);

      if (targetType === type &amp;&amp; duration &gt;= targetMonth * 28) {
        answer.push(index + 1);
      }
    });
  });
  return answer;
}</code></pre>
<h2 id="py">PY</h2>
<pre><code class="language-python">def solution(today, terms, privacies):
    tYear, tMonth, tDay = map(int, today.split(&quot;.&quot;))
    answer = []
    for i in range(len(privacies)):
        target, type = privacies[i].split(&quot; &quot;)
        year, month, day = map(int, target.split(&quot;.&quot;))

        term = (tYear - year) * 12 * 28 + (tMonth - month) * 28 + (tDay - day)
        for j in range(len(terms)):
            tarType, tarTerm = terms[j].split(&quot; &quot;)
            if tarType == type:
                if term &gt;= int(tarTerm) * 28:
                    answer.append(i + 1)
    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>회사 지원을 하면서 JS를 지원하지 않는 기업이 생각보다 많았다.
조금 다양한 풀을 지원하기 위해서 코테용 언어를 하나 배우는게 나을 것 같다고 생각해서 가장 접근이 쉬운 파이썬을 이용해 복습 겸 한번 더 푸는 방식으로 공부하자고 결정하였다.</p>
<p>파이썬으로 새롭게 풀면서 느꼈던 점은 구조분해할당이 JS와 비슷한 방식이어서 편했고, c++이나 java보다는 빠르게 익힐 수 있을 것 같다는 생각을 하였다.</p>
<p>먼저 privacies를 돌면서 split한 다음 타입에 맞춰서 기간을 체크해주면 됐다. 가볍게 풀 수 있는 구현 문제 같았다.</p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li><p>파이썬에서 split을 할 때 타입을 명시하지 않으면 문자열로 만들어지고, 이때 숫자 계산이 어렵기 때문에 map(type, 문자열) 메서드를 통해 타입 자체로 split하는 방법</p>
</li>
<li><p>terms을 for문을 통해 계속 반복하면서 체크하기보다는 JS의 map이나 파이썬의 dict을 통해 저장해놓고 바로 접근하면 이중 포문을 안써도 된다.</p>
<pre><code class="language-python">terms_dict = dict(t.split() for t in terms)</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 3 정수 삼각형 - 동적계획법]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-3-%EC%A0%95%EC%88%98-%EC%82%BC%EA%B0%81%ED%98%95-%EB%8F%99%EC%A0%81%EA%B3%84%ED%9A%8D%EB%B2%95</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-3-%EC%A0%95%EC%88%98-%EC%82%BC%EA%B0%81%ED%98%95-%EB%8F%99%EC%A0%81%EA%B3%84%ED%9A%8D%EB%B2%95</guid>
            <pubDate>Fri, 28 Feb 2025 09:46:28 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43105">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">function solution(triangle) {    
    for(let i = 1; i &lt; triangle.length; ++i) {
        for(let j = 0; j &lt; triangle[i].length; ++j) {
            if(j === 0) triangle[i][j] += triangle[i - 1][0];
            else if(j === triangle[i].length - 1) triangle[i][j] += triangle[i - 1][j - 1];
            else triangle[i][j] += Math.max(triangle[i - 1][j - 1], triangle[i - 1][j])
        }
    }

    return Math.max(...triangle[triangle.length - 1]);
}</code></pre>
<h1 id="풀이">풀이</h1>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/876e9d46-adce-4693-810b-ab6e0cd4ae5c/image.png" alt=""></p>
<p>레벨 3 문제치고는 쉬웠다.</p>
<p>위에서 아래로 내려가면서 더해주는 원리인데, 가장자리(처음, 마지막)에 있는 원소들은 두 가지 숫자를 고를 수 없이 바로 위에 있는 애들을 더해주어야 하고, 중간에 있는 원소들은 위에 두 수 중에 최댓값을 더해주면 된다.</p>
<p>가장 위에 있는 원소는 더해질 필요가 없으니 두번째 라인부터 반복분을 진행하면서 위에있는 원소를 더해주는 작업을 한다. 이때 앞서 말한 규칙대로 더해준다.</p>
<p>마지막으로 리턴할 때 가장 밑에 있는 배열의 최댓값을 구해서 리턴해주면된다.</p>
<h1 id="결과">결과</h1>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/f3827e3c-63c3-4b70-90fb-cb9d0966865b/image.png" alt=""></p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<ol>
<li>Math.max 메서드는 배열을 받지 않기 때문에 스프레드 연산자로 배열을 풀어줘야함.</li>
<li>파이썬은 배열에 -1 인덱스를 넣어서 마지막 원소에 접근이 가능한데 JS는 안되네..</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 전력망을 둘로 나누기 - 완전탐색]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%A0%84%EB%A0%A5%EB%A7%9D%EC%9D%84-%EB%91%98%EB%A1%9C-%EB%82%98%EB%88%84%EA%B8%B0-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%A0%84%EB%A0%A5%EB%A7%9D%EC%9D%84-%EB%91%98%EB%A1%9C-%EB%82%98%EB%88%84%EA%B8%B0-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</guid>
            <pubDate>Fri, 28 Feb 2025 08:55:09 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/86971">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">function solution(n, wires) {
    let answer = Number.MAX_SAFE_INTEGER;

    // 그래프 생성
    const graph = [];
    for(let i = 0; i &lt; n + 1; ++i) graph.push(new Array());
    for(const [a, b] of wires) {
        graph[a].push(b);
        graph[b].push(a);
    }

    const bfs = (rootNum, exceptNum) =&gt; {
        const visit = new Array(n + 1).fill(false);
        const queue = [rootNum];
        let cnt = 0;
        visit[rootNum] = true;

        while(queue.length &gt; 0) {
            const root = queue.pop();
            for(const num of graph[root]){
                if(visit[num] || num === exceptNum) continue;
                visit[num] = true;
                queue.unshift(num);
            }

            cnt++;
        }

        return cnt;
    }

    for(const [a, b] of wires){
        answer = Math.min(answer, Math.abs(bfs(a, b) - bfs(b, a)));
    }

    return answer;
}</code></pre>
<pre><code class="language-python">import sys

def solution(n, wires):
    answer = sys.maxsize
    graph = [[] for _ in range(n + 1)]

    for (a, b) in wires:
        graph[a].append(b)
        graph[b].append(a)

    def bfs(startNode, exceptNode):
        cnt = 0
        visit = [False for _ in range(n + 1)]
        queue = [startNode]
        visit[startNode] = True

        while queue:
            currentNode = queue.pop()

            for node in graph[currentNode]:
                if visit[node] or node == exceptNode:
                    continue
                visit[node] = True
                queue.insert(0, node)

            cnt += 1

        return cnt

    for (a, b) in wires:
        answer = min(answer, abs(bfs(a, b) - bfs(b, a)))

    return answer</code></pre>
<h1 id="풀이">풀이</h1>
<p>어떻게 접근해야할 지 감이 잡히지 않았다.
그나마 다행인 것은 문제를 보고 bfs로 접근해야겠다는 느낌을 받았다.</p>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/d102d9e8-d1d0-4e53-b3d2-201b1b55496e/image.png" alt=""></p>
<p>그래프에서 전력망을 끊으면 해당 간선을 기준으로 두 개의 그래프로 쪼개지게된다.
그러면 그 두 그래프를 bfs로 탐색하면서 몇 개로 구성되어 있는지 검사하면 되겠다고 생각했다.</p>
<p>그래서 먼저 wires를 조금 더 분석하기 쉽게 구조를 수정하였다. 
그 다음에 bfs 함수를 만들어서 큐를 이용해 풀었다.
방문한 노드이거나 끊어진 노드면 처리하지 않도록 했다.</p>
<p>마지막으로 모든 간선을 돌면서 두 개의 그래프 갯수의 차이를 계산하였다.</p>
<h1 id="결과">결과</h1>
<p><img src="https://velog.velcdn.com/images/junbro_0708/post/c1986078-6864-4046-8aac-34159b519188/image.png" alt=""></p>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>JS에서 최댓값은 이렇게 쓸 것</p>
<pre><code class="language-javascript">Number.MAX_SAFE_INTEGER</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 소수찾기 - 완전탐색]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%86%8C%EC%88%98%EC%B0%BE%EA%B8%B0-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EC%86%8C%EC%88%98%EC%B0%BE%EA%B8%B0-%EC%99%84%EC%A0%84%ED%83%90%EC%83%89</guid>
            <pubDate>Thu, 27 Feb 2025 13:11:15 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42839?language=javascript">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">function solution(numbers) {
    let answer = 0;
    const nums = numbers.split(&quot;&quot;);
    const check = new Array(10000000).fill(0);
    const length = new Array(numbers.length).fill(false);

    check[0] = true;
    check[1] = true;
    const dfs = (number, str) =&gt; {
        let num;
        if(number !== &quot;&quot;) num = Number(str);

        if(!check[num]) {
            let flag = true;
            for(let i = 2; i * i &lt;= num; ++i) {
                if (num % i === 0) flag = false;
            }

            if(flag) answer++;
            check[num] = true;
        }
        for(let j = 0; j &lt; number.length; ++j) {
            if(length[j] === false) {
                length[j] = true;
                dfs(number, str + number[j]);
                length[j] = false;
            }
        }
    }

    dfs(nums, &quot;&quot;);
    return answer;
}</code></pre>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>너무 어려웠던 소수찾기 문제</p>
<p>모든 경우의 수를 다 찾아봐야하기 때문에 dfs로 탐색하였다.</p>
<p>중복해서 숫자를 검색할 필요는 없기 때문에 check 배열로 이미 찾은 수를 확인해주었고, 배열의 길이만큼 반복문을 돌려주면서 원소 한 개 넣고 검사하고 한개 더 넣고 검사하는 방식으로 모든 경우의 수를 탐색해주었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 게임 맵 최단거리 - 깊이/너비 우선 탐색(DFS/BFS)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B9%8A%EC%9D%B4%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89DFSBFS</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC-%EA%B9%8A%EC%9D%B4%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89DFSBFS</guid>
            <pubDate>Thu, 27 Feb 2025 12:36:38 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/1844?language=javascript">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">function solution(maps) {
    const m = maps.length;
    const n = maps[0].length;
    const dir = [[-1, 0], [0, 1], [1, 0], [0, -1]];

    const bfs = () =&gt; {
        const queue = [];
        queue.push([0, 0, 1]);
        maps[0][0] = 0;

        while(queue.length &gt; 0) {
            const [row, col, distance] = queue.shift();

            if(row === m - 1 &amp;&amp; col === n - 1) {
                return distance;
            }

            for(let i = 0; i &lt; dir.length; ++i) {
                const [x, y] = dir[i];
                const newRow = row + x;
                const newCol = col + y;

                if(newRow &lt; 0 || newCol &lt; 0 || newRow &gt;= m || newCol &gt;= n || maps[newRow][newCol] === 0) continue;

                queue.push([newRow, newCol, distance + 1]);
                maps[newRow][newCol] = 0;
            }
        }

        return -1;
    }

    return bfs();
}</code></pre>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>너비 우선 탐색의 전형적인 문제인 길찾기를 풀어보았다. 
JS로 BFS 문제를 푸는게 처음이라 조금 헤맸지만 그래도 길찾기 문제는 정해진 양식이 있는 것 같다.</p>
<ol>
<li>방향 만들기</li>
<li>시작점 넣고 while문으로 큐가 비어있을 때까지 돌리기</li>
<li>while문 넣자마자 원소 빼고 목표 설정하기</li>
<li>방향 만큼 반복문으로 돌리면서 큐에 방향 넣어주기</li>
<li>방향 넣어주면 다녀온 처리하기</li>
</ol>
<p>이렇게 외워두자!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 2 타겟 넘버
 - 깊이/너비 우선 탐색(DFS/BFS)]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84-%EA%B9%8A%EC%9D%B4%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89DFSBFS</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-2-%ED%83%80%EA%B2%9F-%EB%84%98%EB%B2%84-%EA%B9%8A%EC%9D%B4%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89DFSBFS</guid>
            <pubDate>Wed, 26 Feb 2025 13:10:51 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43165?language=javascript">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">let answer = 0;

function dfs(numbers, target, sum, cnt) {
    if(numbers.length === cnt) {
        if(sum === target) answer++;
        return;
    }else {
        dfs(numbers, target, sum + numbers[cnt], cnt + 1);
        dfs(numbers, target, sum - numbers[cnt], cnt + 1);
    }
}

function solution(numbers, target) {
    dfs(numbers, target, 0, 0);
    return answer;
}</code></pre>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>오랜만에 코딩테스트를 봐야하는 일이 생겨서 다시 DFS/BFS를 공부중이다..
핵심은 재귀함수로 할 수 있는 경우의 수를 다 검사하는 법이다.</p>
<p>더하는 수와 빼는 수가 있기 때문에 깊이 우선 탐색을 통해 0부터 시작해서 수를 더하는 방법과 빼는 방법의 경우의 수를 하나하나 들어가면서 배열의 길이와 함수의 카운트 수가 같아 졌을 때 타겟 넘버가 일치하면 답을 하나 올려주는 형식으로 구현하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] Level 1 택배 상자 꺼내기 - 2025 프로그래머스 코드챌린지 2차 예선]]></title>
            <link>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%ED%83%9D%EB%B0%B0-%EC%83%81%EC%9E%90-%EA%BA%BC%EB%82%B4%EA%B8%B0-2025-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%BD%94%EB%93%9C%EC%B1%8C%EB%A6%B0%EC%A7%80-2%EC%B0%A8-%EC%98%88%EC%84%A0</link>
            <guid>https://velog.io/@junbro_0708/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Level-1-%ED%83%9D%EB%B0%B0-%EC%83%81%EC%9E%90-%EA%BA%BC%EB%82%B4%EA%B8%B0-2025-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%BD%94%EB%93%9C%EC%B1%8C%EB%A6%B0%EC%A7%80-2%EC%B0%A8-%EC%98%88%EC%84%A0</guid>
            <pubDate>Wed, 26 Feb 2025 09:25:16 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-링크">문제 링크</h1>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/389478">바로가기</a></p>
<h1 id="문제-풀이">문제 풀이</h1>
<pre><code class="language-javascript">function solution(n, w, num) {
    const arr = [];

    for(let i = 0; i &lt; w; ++i){
        arr.push(new Array());
    }

    let j = 0, cnt = 0;
    for(let i = 0; i &lt; n; ++i) {
        if(j === w) {
            j = 0;
            cnt++;
        }

        switch(cnt % 2){
            case 0:
                arr[j].push(i + 1);
                break;
            case 1:
                arr[Math.abs(j-w+1)].push(i + 1);
                break;
        }

        j++;
    }

    let answer = 0;
    arr.map(items =&gt; {
        items.map((item, idx) =&gt; {
            if(item === num){
                answer = items.length - idx;
                return;
            } 
        })
    })

    return answer;
}</code></pre>
<h1 id="새롭게-배운-점">새롭게 배운 점</h1>
<p>처음에는 배열을 초기화할 때</p>
<pre><code class="language-javascript">const arr = new Array(w).fill([]);</code></pre>
<p>이런 식으로 작성을 했는데 for문을 한번 돌리는데도 불구하고 모든 배열에 숫자가 다 들어가는 현상이 발생했다. 
그래서 찾아보니까 모든 빈 배열 요소가 같은 값을 참조해서 생기는 현상이라고 했다.
그래서 새로운 배열 객체를 가질 수 있도록</p>
<pre><code class="language-javascript">const arr = [];

for(let i = 0; i &lt; w; ++i){
  arr.push(new Array());
}</code></pre>
<p>이렇게 변경하였다.</p>
]]></description>
        </item>
    </channel>
</rss>