<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>su-ram.log</title>
        <link>https://velog.io/</link>
        <description>녁므</description>
        <lastBuildDate>Sat, 07 Aug 2021 19:02:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>su-ram.log</title>
            <url>https://images.velog.io/images/su-ram/profile/8b222b44-12a2-456c-a62e-126146398d09/B8B27D8B-EC20-4751-B2BA-6324F5BEC8FB.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. su-ram.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/su-ram" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2021오픈소스 컨트리뷰션 아카데미]]></title>
            <link>https://velog.io/@su-ram/2021%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A8%ED%8A%B8%EB%A6%AC%EB%B7%B0%EC%85%98-%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8</link>
            <guid>https://velog.io/@su-ram/2021%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A8%ED%8A%B8%EB%A6%AC%EB%B7%B0%EC%85%98-%EC%95%84%EC%B9%B4%EB%8D%B0%EB%AF%B8</guid>
            <pubDate>Sat, 07 Aug 2021 19:02:12 GMT</pubDate>
            <description><![CDATA[<h2 id="2021-오픈소스-컨트리뷰션-아카데미">2021 오픈소스 컨트리뷰션 아카데미</h2>
<ul>
<li>활동기간 : 약 4개월</li>
<li>프로그램 소개 : 멘토 - 멘티가 하나의 오픈소스 프로젝트를 진행하면서 기여하는 프로그램이다. 작년에 이 프로그램의 존재를 알게 되었고 다음 회차에 참여해보고 싶었는데 공고가 떠서 지원했고 감사하게도 멘티로 선정되어서 이번에 활동할 수 있게 되었다. </li>
<li>홈페이지 : <a href="https://contributionacademy.oopy.io/">2021 오픈소스 컨트리뷰션 아카데미 노션 페이지</a></li>
</ul>
<h2 id="참여하고-싶었던-이유">참여하고 싶었던 이유</h2>
<p>스트레스 없이 개발활동을 할 수 있을 것 같았다. 프로젝트나 과제를 하다보면 해치우는 식으로 코딩을 하게된다. 만약에 내가 A라는 기능을 맡았으면 이 기능이 돌아가기만 하면 되는 식으로 코딩을 하는거다. 거의 99% 구글링으로 이어붙여놓는 식ㅠ 어쨌든 동작만하면 된다는 식의 개발 경험이 많아지다보니 개발을 한다라기 보다는 그냥 타이핑 친다는 느낌이 많이 들었다. 그래서 순수한 개발활동에 집중하고 싶었다. 물론 정해진 기간이 있고 개선해야할 이슈들이 있을거지만 좀 더 자유로운 형태로 개발활동을 할 수 있다는 점이 매력적이었다. </p>
<p>우선 오픈소스 프로젝트를 하기 위해서는 기존의 프로젝트 코드를 이해해야하고 새로운 PR이 생기면 코드리뷰를 하면서 기존의 것에서 어떤 점들이 변경되는지 알아야 한다. 이러한 과정 자체가 개발에 몰두할 수 있는 환경이라고 생각했다. 일단 코드를 뜯어보면서 이해하는 하는 과정이 필수적이기 때문이다. </p>
<h2 id="진행-방식">진행 방식</h2>
<ul>
<li>기존 프로젝트 깃허브 저장소 fork </li>
<li>각자 맡은 이슈 사항들을 토대로 개발 </li>
<li>변경사항 commit</li>
<li>PR 작성</li>
<li>코드리뷰 </li>
<li>merge </li>
</ul>
<p>대략 이런식으로 진행되고, 깃으로 협업하는 것과 크게 다른 점은 없다. </p>
<h2 id="지금까지의-진행-상황">지금까지의 진행 상황</h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> 발대식
<img src="https://images.velog.io/images/su-ram/post/6938671b-6fcd-400a-9d47-13e371f025a9/Untitled%20(1).png" alt=""></li>
<li><input checked="" disabled="" type="checkbox"> 깃허브 저장소 fork </li>
</ul>
<h2 id="앞으로-일정">앞으로 일정</h2>
<ul>
<li>조 배정 </li>
<li>이슈 할당 받기</li>
<li>개발 환경 셋팅 </li>
<li>PR 날리기~</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 코딩테스트 ]]></title>
            <link>https://velog.io/@su-ram/PS-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@su-ram/PS-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Sat, 07 Aug 2021 18:31:37 GMT</pubDate>
            <description><![CDATA[<p>저번 주에 봤던 모 기업의 코딩테스트 문제 중에 시간 안에 못 풀었던 문제를 메모해두었다가 다시 풀었다. </p>
<h2 id="문제-1">문제 1.</h2>
<ul>
<li>분류 : <code>BFS</code></li>
<li>유사문제 : <a href="https://www.acmicpc.net/problem/2251">백준 물통</a></li>
</ul>
<pre><code class="language-python">l1, l2 = map(int,input().split())
from collections import deque
que = deque([(0,0)])
visited =[ [False] * (l2 + 1) for _ in range(l1 + 1)]
visited[0][0] = True
ans = set()

def add_que(node):
    if visited[node[0]][node[1]] == False:
        visited[node[0]][node[1]] = True
        que.append(node)

while que :
    now = que.popleft()

    ans.add(now[0])
    ans.add(now[1])

    add_que((l1,l2))
    add_que((l1, now[1]))
    add_que((now[0], l2))
    add_que((0, now[1]))
    add_que((now[0], 0))
    add_que((0,0))

    amount = min(l2-now[1], now[0])
    add_que((now[0]-amount, now[1]+amount))
    amount = min(l1-now[0], now[1])
    add_que((now[0] +amount, now[1]-amount))

ans.remove(0)
[ print(i, end=&#39; &#39;) for i in sorted(ans)]</code></pre>
<h2 id="풀이과정">풀이과정</h2>
<ul>
<li>두 개의 물통 A와 B가 있다고 가정한다. </li>
<li>가능한 액션<pre><code>  1. 물통 가득 채우기
  2. 물통 다 비우기
  3. 다른 물통으로 물 옮기기 </code></pre></li>
<li>(a물통에 남은 양, b물통에 남은양)으로 상태 체크 여부를 확인한다. </li>
</ul>
<blockquote>
<ol>
<li>(0,0)으로 큐를 초기화한다. </li>
<li>큐에서 꺼낸 노드(현재)에 가능한 액션을 모두 취한다 </li>
<li>visited을 통해 액션을 취한 뒤의 노드가 이미 조회된 노드인지 판별한다. </li>
<li>조회된 적 없으면 큐에 push한다. </li>
<li>pop한 노드의 값들을 set에 add하여 중복을 제거한다. </li>
<li>마지막에 초기화를 위해 셋팅했던 0을 set에서 지우고 정렬하여 출력한다. </li>
</ol>
</blockquote>
<h2 id="문제-2">문제 2.</h2>
<ul>
<li>분류 : <code>투포인터</code>, <code>슬라이딩 윈도우</code></li>
</ul>
<pre><code class="language-python">road = list(input())
road = list(map(int, road))
n = int(input())
start, end = 0, 0
repair = [-1]

for i in range(len(road)):
    if road[i] == 0:
        if len(repair) == n+1:
            repair.pop(0)
        repair.append(i)

    l1 = end - start
    l2 = i+1 - repair[0]

    if l2 &gt; l1 :
        start = repair[0] + 1
        end = i + 1

print(end-start)</code></pre>
<h2 id="풀이과정-1">풀이과정</h2>
<ul>
<li><code>start</code>, <code>end</code>는 가장 긴 배열의 시작과 끝을 가리킨다. </li>
<li><code>repair</code>에는 0 -&gt; 1로 변경된 인덱스가 저장된다. (처음에는 없으므로 -1로 셋팅) </li>
<li><code>l1</code> : 현재 start, end 포인터가 가리키는 배열의 길이 </li>
<li><code>l2</code> : 수정된 0 다음 부터 ~ 현재노드 포함한 길이 </li>
</ul>
<blockquote>
<ol>
<li>현재 노드가 0 이면 repair에 넣는다. 길이가 n+1이면 맨 앞의 노드를 pop한다. (크기가 항상 n+1유지, 왜 n+1이냐면 가장 앞쪽의 수정된 노드를 알고 있어야 하기 때문이다. ) </li>
<li>현재 end- start 길이 vs 가장 왼쪽의 수정된 노드 다음부터 ~ 현재 노드 포함한 길이 비교 </li>
<li>후자가 더 크다면, start, end 갱신 </li>
<li>end가 마지막노드때까지 반복 </li>
<li>end-start하면 가장 큰 부분 배열의 길이를 출력하게 된다.</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#1010 다리 놓기 / 파이썬 ]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801010-%EB%8B%A4%EB%A6%AC-%EB%86%93%EA%B8%B0-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801010-%EB%8B%A4%EB%A6%AC-%EB%86%93%EA%B8%B0-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Sun, 25 Jul 2021 17:47:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/3ac9f60d-6b95-4a9f-a787-9f994206923f/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제-풀이">알고리즘 문제 풀이</h2>
<ul>
<li>문제 : <a href="https://www.acmicpc.net/problem/1010">다리 놓기</a></li>
<li>해결 : <code>solved</code></li>
<li>분류 : 조합, DP</li>
</ul>
<h2 id="풀이-방법1---조합">풀이 방법(1) - 조합</h2>
<ol>
<li>조합 공식을 사용한다</li>
<li>n!이 사용되는데 여기서 DP로 n까지의 n! 각 값들을 배열을 이용해 구해놓는다. </li>
<li>dp로 만들어 놓은 배열을 이용하여 공식에 따라 계산한다. </li>
</ol>
<h2 id="풀이-방법2---dp">풀이 방법(2) - DP</h2>
<ol>
<li>n까지의 배열을 초기화하고 각 인덱스는 x개의 동쪽 사이트가 있을 경우로 정의한다. </li>
<li>dp[i] 는 i번째 사이트를 포함하는 경우의 수 + 포함하지 않는 경우의 수<blockquote>
<p>f(n, k) = f(n-1, k) + f(n-1, k-1) </p>
</blockquote>
</li>
<li>dp 배열의 마지막 원소를 출력한다. </li>
</ol>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">T = int(input())
for _ in range(T):
    N, M = map(int, input().split())
    dp = [[1] * (M+1) for _ in range(N+1)]

    for i in range(1, N+1):
        for j in range(1, M+1):
            if i &gt; j :
                dp[i][j] = 0
            elif i == j :
                dp[i][j] = 1
            else:
                dp[i][j] = dp[i][j-1] + dp[i-1][j-1]
    print(dp[-1][-1])</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#17298 오큰수 / 파이썬]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%8017298-%EC%98%A4%ED%81%B0%EC%88%98-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%8017298-%EC%98%A4%ED%81%B0%EC%88%98-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Sat, 24 Jul 2021 17:05:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/f3813eef-c9e6-42a1-b161-73d12f1fa6ac/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제-풀이">알고리즘 문제 풀이</h2>
<ul>
<li>문제 : <a href="https://www.acmicpc.net/problem/17298">오큰수</a></li>
<li>해결 : <code>unsolved</code> </li>
<li>분류 : 스택 </li>
</ul>
<h2 id="내-풀이-방법">내 풀이 방법</h2>
<ul>
<li><p>일단 스택인 것은 알았다. </p>
</li>
<li><p>배열을 for문으로 순회하면서 스택에는 해당노드보다 더 큰 값들만 있게한다. </p>
</li>
<li><p>top이 현재 노드 보다 크거나 스택이 비었으면 -1 </p>
</li>
<li><p>현재 노드보다더 작은 값이 있다면 smaller 스택에 push </p>
</li>
<li><p>스택을 끝까지 순회하고 스택이 비었으면 smaller의 값들을 다시 넣어줌 </p>
</li>
<li><p>소스코드 </p>
<pre><code class="language-python">import copy
N = int(input())
arr = list(map(int, input().split()))
stack = copy.deepcopy(arr[::-1])
smaller = []
nums = []
for i in range(N-1):
  while stack:
      top = stack[-1]
      if top &lt; arr[i] :
          smaller.append(top)
          stack.pop()
      elif top == arr[i]:
          stack.pop()
          continue
      elif top &gt; arr[i]:
          break

  if stack != []:
      nums.append(str(stack[-1]))
      while smaller:
          smaller.pop()
  else:
      nums.append(str(-1))
      while smaller:
          stack.append(smaller.pop())
</code></pre>
</li>
</ul>
<p>print(&#39; &#39;.join(nums+[&#39;-1&#39;]))</p>
<pre><code>
## 정답 풀이
&gt; - 스택에는 인덱스를 저장한다 
- 현재 노드와 바로 오른쪽 노드만 비교한다. (스택을 순회할 필요x) 
- 비교하여 오큰수를 찾았다면 해당 인덱스를 스택에서 pop 
- 오큰수를 찾지 못했다면 pop하지 않고 계속 인덱스를 push 한다. 
- 만약 스택에 [5,3,4] 가 있고 현재 노드가 6일 때 스택에 있는 모든 수의 오큰수는 6이 된다. 따라서 pop을 해주면서 오큰수를 갱신해준다. 그리고 6을 push한다. 
- 다음(6의 오른쪽) 노드는 스택의 top (=6)을 peek해서 비교하면서 반복한다. 

## 정답 소스코드 
```python

N = int(input())
arr = list(map(int, input().split()))
stack = [0]
nums = [-1]*N

for i in range(1, N):
    while stack and arr[stack[-1]] &lt; arr[i]:
        nums[stack.pop()] = arr[i]
    stack.append(i)

print(*nums)</code></pre><h2 id="놓친-점">놓친 점</h2>
<ul>
<li>스택을 2개를 놓고 현재 노드보다 큰 값들, 현재 노드보다 작은 값들을 저장하려고 했던 점</li>
<li>인덱스가 아니라 값 그자체를 저장했던점. </li>
</ul>
<p>스택 자료구조의 특징을 잘 활용하기가 어렵다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#1766 문제집 / 파이썬]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801766-%EB%AC%B8%EC%A0%9C%EC%A7%91-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801766-%EB%AC%B8%EC%A0%9C%EC%A7%91-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Fri, 23 Jul 2021 12:16:30 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/b9430882-4881-49d6-a14b-6133f111a77e/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제-풀이">알고리즘 문제 풀이</h2>
<ul>
<li>문제 : <a href="https://www.acmicpc.net/problem/1766">문제집</a></li>
<li>해결 : <code>solved</code> </li>
<li>분류 : 위상정렬, 우선순위큐 </li>
</ul>
<h2 id="풀이-과정">풀이 과정</h2>
<ol>
<li>입력 차수를 배열에 저장한다. (자신의 노드로 화살표가 들어오는 횟수) </li>
<li>차수가 0인 노드들을 힙에 push </li>
<li>while문을 순회하면서 pop된 node에 연결된 노드들의 차수를 검사한다. </li>
<li>0인 차수들은 힙에 push, 현재 노드의 연결된 모든 노드들의 차수를 1씩 차감 </li>
<li>힙에서 꺼낸 순서대로 출력한다. <blockquote>
<p>힙에 있는 노드들은 모두 입력 차수가 0임이 보장된다. </p>
</blockquote>
</li>
</ol>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">N, M = map(int, input().split())
degree =[0] * (N+1)
graph =[[] for _ in range(N+1)]

for i in range(M):
    prev, post = map(int, input().split())
    degree[post] += 1
    graph[prev].append(post)

import heapq

heap = []
for i in range(1, N+1):
    if degree[i] == 0:
        heap.append(i)

heapq.heapify(heap)

while heap:

    node = heapq.heappop(heap)
    print(node, end=&#39; &#39;)
    for n in graph[node]:
        degree[n] -= 1
        if degree[n] == 0 :
            heapq.heappush(heap, n)
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#1024 수열의 합 / 파이썬]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801024-%EC%88%98%EC%97%B4%EC%9D%98-%ED%95%A9-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801024-%EC%88%98%EC%97%B4%EC%9D%98-%ED%95%A9-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Wed, 21 Jul 2021 16:29:27 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/2476300b-4d2c-484c-969a-66dc2a709f22/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제풀이">알고리즘 문제풀이</h2>
<ul>
<li>문제 : <a href="https://www.acmicpc.net/problem/1024">수열의 합</a></li>
<li>해결 : <code>solved</code></li>
<li>분류 : 수학(수열) </li>
</ul>
<h2 id="풀이방법">풀이방법</h2>
<ol>
<li>등차수열 공식을 활용하여 식을 만든다. a + (n-1)d</li>
<li>L부터 100까지 순회하면서 수열의 합이 특정값을 만족하는지 검사한다. </li>
<li>결과를 출력한다. </li>
</ol>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">N, L = map(int, input().split())
x = []

def get_arr(length, N):
    x = N - (length * (length+1) // 2)
    return x / length

for i in range(L, 101):

    a = get_arr(i, N)
    if int(a) == a :
        a = int(a)
        sub_sum = sum(range(a+i+1)) - sum(range(a+1))
        if sub_sum == N :
            x = (list(range(a + 1, a + i + 1)))
            x = list(map(str, x))
            break

print(&#39; &#39;.join(x) if x != [] and len(x) &lt;= 100 else -1)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#2943 탑 / 파이썬]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%802943-%ED%83%91-%ED%8C%8C%EC%9D%B4%EC%8D%AC</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%802943-%ED%83%91-%ED%8C%8C%EC%9D%B4%EC%8D%AC</guid>
            <pubDate>Tue, 20 Jul 2021 16:03:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/a55a771f-e407-4176-ba67-ac20d3e7555c/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제풀이">알고리즘 문제풀이</h2>
<ul>
<li>문제 : <a href="https://www.acmicpc.net/problem/2493">탑</a></li>
<li>해결 : 시간초과 </li>
<li>분류 : 스택 </li>
</ul>
<h2 id="초기-풀이방법시간초과">초기 풀이방법(시간초과)</h2>
<ol>
<li>탑 길이들의 배열을 for문으로 돌면서 하나씩 pop한다</li>
<li>각 탑의 길이보다 짧은 요소들은 smaller 스택에 넣는다</li>
<li>계속 pop하면서 더 긴 요소를 찾으면 smaller 스택에 있는 요소들을 다시 원래 리스트에 이어 붙인다. </li>
<li>더 긴 요소의 인덱스를 결과 배열에 저장한다.</li>
</ol>
<blockquote>
<p> <strong>시간 초과 이유</strong> : 해당 요소보다 더 작은 요소들은 그냥 pop해버리고 따로 저장해두지 않아도 된다. 그런데 따로 저장해두고 다시 이어 붙이는 과정이 있어서 시간초과가 발생했다. </p>
</blockquote>
<h2 id="개선-풀이방법">개선 풀이방법</h2>
<ol>
<li>각 요소들을 for문으로 순회한다. 처음부터 </li>
<li>스택에는 이전 요소들의 값들이 저장되어 있다.</li>
<li>스택에 아무것도 없다면 0 출력</li>
<li>스택에 요소가 존재한다면 자신보다 작은 요소들은 pop하여 없앤다. 큰 요소가 존재할 경우 해당 인덱스 출력</li>
<li>현재 요소를 스택에 push </li>
</ol>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">N = int(input())
H = list(map(int, input().split()))
stack = []
for i in range(N):
    while stack:
        top = H[stack[-1]]
        if top &gt; H[i]:
            break
        stack.pop()
    if stack == []:
        print(0)
    else:
        print(stack[-1]+1)
    stack.append(i)</code></pre>
<h2 id="왜-스택-자료구조를-이용해야되는지">왜 스택 자료구조를 이용해야되는지</h2>
<p>문제에서 레이저는 왼쪽으로만 발사된다고 했다. 즉 방향이 하나뿐이다. 
해당 노드 기준으로 왼쪽에 있는 노드들 중에서 가장 가까운 큰 노드가 정답이 된다. 스택의 경우 가장 최신의 노드 (=거리가 가까운 노드)가 최상위 노드에 있다. 또한 스택은 순서가 유지된다. </p>
<h2 id="느낀-점">느낀 점</h2>
<ul>
<li>스택을 사용함으로써 어떤 점을 활용할 수 있는지 모르겠다. </li>
<li>어떤 경우에 스택을 사용해야하는지</li>
<li>문자열, 괄호열 처럼 특정한 한 방향으로 순서가 이루어질 때 스택을 사용한다는 건 알겠는데 내가 스택의 특성을 잘 활용하지 못하고 있는 것 같다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#1406 / 에디터 ]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801406-%EC%97%90%EB%94%94%ED%84%B0</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%801406-%EC%97%90%EB%94%94%ED%84%B0</guid>
            <pubDate>Fri, 16 Jul 2021 13:21:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/ddf23366-e58e-40a8-a485-116bbaa0555b/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h3 id="알고리즘-문제-풀이">알고리즘 문제 풀이</h3>
<ul>
<li>링크 : <a href="https://www.acmicpc.net/problem/1406">에디터</a></li>
<li>유형 : <code>자료구조</code>, <code>스택</code> </li>
<li>해결 : <code>solved</code></li>
</ul>
<h3 id="풀이과정">풀이과정</h3>
<ol>
<li>두 개의리스트를 만들고 A에는 입력받은 초기문자열 B에는 빈 스택.</li>
<li>커서를 왼쪽으로 이동하면 A에서 pop한 데이터를 B 스택에 push</li>
<li>커서를 오른쪽으로 이동하면 반대로 동작</li>
<li>삭제와 삽입은 A에서 일어나도록. </li>
</ol>
<h3 id="놓친-점">놓친 점</h3>
<ul>
<li>처음에는 리스트 하나로 두고 커서의 위치를 저장하는 index 변수를 변경해가는 방식으로 처리했더니 시간초과 발생.</li>
<li><code>이유</code> : 리스트 하나로 처리하다보니 insert를 사용하게 되는데 노드를 하나 삽입시 그 뒤에 모든 노드들이 하나씩 밀려나는 연산이 필요하게 된다. </li>
<li>커서 이전/이후로 나누어서 리스트 두개로 저장한 다음 마지막에 스택부분만 거꾸로 조회해서 이어붙이면 된다. </li>
</ul>
<h3 id="소스코드">소스코드</h3>
<pre><code class="language-python">import sys
input = sys.stdin.readline
str = list(input().rstrip())
N = len(str)
M = int(input())
commands = [ input().rstrip().split() for _ in range(M)]
index = len(str)

def execute(str, stack, cmd, char=None):

    if cmd == &#39;L&#39; and str != []:
        stack.append(str.pop())
    if cmd == &#39;D&#39; and stack != []:
        str.append(stack.pop())
    if cmd == &#39;B&#39; and str != []:
        str.pop()
    if cmd == &#39;P&#39;:
        str.append(char)

stack = []
for c in commands:
    index = execute(str=str, stack=stack, cmd=c[0], char= c[1] if len(c) ==2 else None)

print(&#39;&#39;.join(str+stack[::-1]))</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PS] 백준#3190 / 뱀 ]]></title>
            <link>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%803190-%EB%B1%80</link>
            <guid>https://velog.io/@su-ram/PS-%EB%B0%B1%EC%A4%803190-%EB%B1%80</guid>
            <pubDate>Thu, 15 Jul 2021 13:54:51 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/su-ram/post/bf162997-ebed-48a2-9c38-954051e9fb9f/KakaoTalk_20210716_222042528.jpg" alt=""></p>
<h2 id="알고리즘-문제-풀이">알고리즘 문제 풀이</h2>
<ul>
<li>링크 : <a href="https://www.acmicpc.net/problem/3190">뱀</a></li>
<li>해결 : <code>solved</code></li>
<li>시간복잡도 : O(n)</li>
<li>분류 : <code>구현</code>, <code>덱</code> <h2 id="풀이-과정">풀이 과정</h2>
</li>
</ul>
<ol>
<li>cnt를 증가시키면서 반복한다. </li>
<li>방향을 바꿔야하면 바꾼다. </li>
<li>현재 방향으로 한 칸 이동한다. </li>
<li>종료 조건이면 break </li>
<li>이동가능한 칸이면 deque에 해당 칸을 appendleft 한다. <ul>
<li>사과가 있으면 pop을 하지 않는다. = 꼬리를 옮기지 않는다. </li>
<li>사과가 없으면 pop = 꼬리를 옮긴다.</li>
</ul>
</li>
<li>1~5번을 반복하면서 while문이 종료되면 cnt를 출력한다. </li>
</ol>
<h2 id="메모">메모</h2>
<ul>
<li>*<em>뱀이 위치하고 있는 좌표들을 저장하는 자료구조가 deque이다. *</em></li>
<li>왼쪽이 머리(=appendleft) 오른쪽이 꼬리(=pop)</li>
</ul>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">N = int(input())
A = int(input())
apples = []
for _ in range(A):
    pos = list(map(int, input().split()))
    pos = list(map(lambda x : x-1, pos))
    apples.append(pos)

L = int(input())
shifts = []
for shift in range(L):
    sec, dir = input().split()
    sec = int(sec)
    shifts.append((sec, dir))

board = [[0]*N for _ in range(N)]
for a in apples:
    board[a[0]][a[1]] = 1
D = 1
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
head = (0,0)
cnt = 0

from collections import deque
shifts = deque(shifts)
snake = deque([head])

while True :

    if shifts:
        if cnt == shifts[0][0]:
            sec, dir = shifts.popleft()
            if dir == &#39;L&#39;:
                D -= 1
                if D == -1 :
                    D = 3
            if dir == &#39;D&#39;:
                D += 1
                if D == 4 :
                    D = 0

    nx = head[0] + dx[D]
    ny = head[1] + dy[D]
    cnt += 1

    if nx &lt; 0 or nx &gt;= N or ny &lt; 0 or ny &gt;= N :
        break
    if snake.count((nx, ny)) :
        break

    snake.appendleft((nx, ny))

    if board[nx][ny] == 0 :
        snake.pop()
    if board[nx][ny] == 1 :
        board[nx][ny] = 0
    head = (nx, ny)

print(cnt)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 네이버웹툰 개발 챌린지(프로그래머스)]]></title>
            <link>https://velog.io/@su-ram/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%84%A4%EC%9D%B4%EB%B2%84%EC%9B%B9%ED%88%B0-%EA%B0%9C%EB%B0%9C-%EC%B1%8C%EB%A6%B0%EC%A7%80%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</link>
            <guid>https://velog.io/@su-ram/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%84%A4%EC%9D%B4%EB%B2%84%EC%9B%B9%ED%88%B0-%EA%B0%9C%EB%B0%9C-%EC%B1%8C%EB%A6%B0%EC%A7%80%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</guid>
            <pubDate>Sun, 04 Jul 2021 11:43:16 GMT</pubDate>
            <description><![CDATA[<h1 id="네이버웹툰-개발-챌린지">네이버웹툰 개발 챌린지</h1>
<p><img src="https://images.velog.io/images/su-ram/post/d5fe3105-297d-4907-9e40-1c3a44785edf/%EB%84%A4%EC%9D%B4%EB%B2%84%EC%9B%B9%ED%88%B0_%EA%B0%9C%EB%B0%9C%20%EC%B1%8C%EB%A6%B0%EC%A7%80.png" alt=""></p>
<ul>
<li>일시 : 2021년 7월 4일</li>
<li>플랫폼 : 프로그래머스 </li>
<li>총 문제 : 3문제 </li>
<li>응시 언어 : <code>python</code></li>
</ul>
<blockquote>
<p>연습용으로 보았고, AI application engineer 직군을 지원했다. 이후에 과제 테스트도 있다. </p>
</blockquote>
<h3 id="문제-1-번">문제 1 번</h3>
<p><code>solved</code></p>
<ul>
<li>분류 : 반복문, 배열 </li>
</ul>
<pre><code class="language-python">
lottery = [[1,0],[35,0],[1,0],[100,1],[35,1],[100,1],[35,0],[1,1],[1,1]]

def solution(lottery):
    record = {}
    for user in lottery:
        if record.get(user[0]) is None:
            record[user[0]] = [1, user[1]]
            continue
        value = record.get(user[0])
        if value[1] == 0 :
            value[0] += 1
            value[1] = user[1]
            record[user[0]] = value
    answer = [0,0]

    for user, result in record.items():
        if result[1] :
            answer[0] += result[0]
            answer[1] += 1
    return answer[0]//answer[1] if answer[1] &gt; 0 else 0


print(solution(lottery))</code></pre>
<h3 id="문제-2번">문제 2번</h3>
<p><code>solved</code></p>
<ul>
<li>분류 : BFS </li>
</ul>
<pre><code class="language-python">from collections import deque
import math
row, col = (len(grid), len(grid[0]))
path = [[math.inf]*col for _ in range(row)]
que = deque([(0,0,0)])
dx = [0,1]
dy = [1,0]

while que:
    node = que.popleft()
    x , y = node[:2]
    path[x][y] = min(path[x][y], grid[x][y] + node[-1])

    for i in range(2):
        nx = x + dx[i]
        ny = y + dy[i]

        if 0 &lt;= nx &lt; row and 0 &lt;= ny &lt; col :
            que.append((nx,ny,path[x][y]))

print(path[row-1][col-1])</code></pre>
<h3 id="문제-3번">문제 3번</h3>
<ul>
<li>분류 : DFS
<code>unsolved</code> 시험 끝나고 나서 마저 풀었다.ㅠ<pre><code class="language-python">from copy import  deepcopy
import math
</code></pre>
</li>
</ul>
<p>arr = [5,4,3,2,1]
k = 4
limit = len(arr)
pos = [-1] * (len(arr)+1)
for i in range(len(arr)):
    pos[arr[i]] = i</p>
<p>cnt = 0
answer = math.inf</p>
<p>def DFS(max, arr , cnt,ordered):</p>
<pre><code>if ordered == limit:
    global answer
    answer = min(answer, cnt)
    return

if max == arr.index(max)+1:
    DFS(max-1, arr, cnt,ordered+1)
    return

for i in range(1, k+1):

    index = arr.index(max)

    if index+i &lt; limit - ordered:
        new_arr = deepcopy(arr)
        new_arr[index], new_arr[index + i] = new_arr[index + i], new_arr[index]
        DFS(max, new_arr, cnt + 1, ordered)</code></pre><p>DFS(max(arr), arr, 0, 0)
print(answer)</p>
<p>```</p>
<p><strong>결론</strong>: 구현, DFS 문제를 더 풀어보자. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쿠키와 세션 ]]></title>
            <link>https://velog.io/@su-ram/%EC%BF%A0%ED%82%A4%EC%99%80-%EC%84%B8%EC%85%98</link>
            <guid>https://velog.io/@su-ram/%EC%BF%A0%ED%82%A4%EC%99%80-%EC%84%B8%EC%85%98</guid>
            <pubDate>Mon, 05 Apr 2021 12:47:03 GMT</pubDate>
            <description><![CDATA[<h1 id="등장배경">등장배경</h1>
<ul>
<li><p>HTTP
<code>http</code> 프로토콜은 <code>비연결성</code> 이기 때문에 클라이언트와의 연결은 일회성이며 이후에 계속 유지되지 않는다. 따라서 서버 입장에서는 매번 새로운 클라이언트라고 인식한다. 클라이언트측에서 매번 자신이 누구인지에 대한 정보를 서버에게 보내야 하는 번거로움이 존재한다. 
<code>stateless</code> </p>
</li>
<li><p>클라이언트를 구분 </p>
</li>
</ul>
<h1 id="쿠키">쿠키</h1>
<h1 id="세션">세션</h1>
<h1 id="보안-문제">보안 문제</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 브라우저 동작 방식]]></title>
            <link>https://velog.io/@su-ram/%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@su-ram/%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Mon, 29 Mar 2021 17:54:13 GMT</pubDate>
            <description><![CDATA[<h1 id="브라우저browser">브라우저(Browser)</h1>
<ul>
<li><strong>Browse</strong> <blockquote>
<p>verb. to look at or through something to see what is there</p>
</blockquote>
</li>
</ul>
<p>무엇이 있는지 보는 것, 또는 무언가를 통해 보는 것. 
<code>Browse</code> + <code>er</code>
(웹 페이지를) 볼 수 있게 해주는 것.</p>
<ul>
<li>*<em>브라우저란? *</em> <blockquote>
<p>A web browser (commonly referred to as a browser) is a software application for accessing the World Wide Web. When a user requests a web page from a particular website, the web browser retrieves the necessary content from a web server and then displays the page on the user&#39;s device.</p>
</blockquote>
</li>
</ul>
<p>정확히는 <code>웹 브라우저</code>라고 부르는게 맞다. 웹 브라우저는 웹에 접근할 수 있는 소프트웨어이다. </p>
<ul>
<li><strong>브라우저의 역할</strong> <blockquote>
<p>The purpose of a web browser is to fetch content from the Web and display it on a user&#39;s device.</p>
</blockquote>
</li>
</ul>
<p>사용자가 특정 웹페이지를 요청하면 웹 브라우저는 웹 서버로부터 웹 페이지를 <strong>불러오고</strong> 유저의 화면에 <strong>보여준다.</strong> </p>
<ul>
<li>정리
브라우저는 다른 컴퓨터(서버)에 있는 웹페이지를 요청하여 가져오고 사용자에게 보여주는 프로그램이다. 가져오는 것은 웹페이지 즉 html 파일이다. 주소창에 URL을 입력하면 웹서버가 주는 웹페이지(html)을 가져와서 사용자의 화면에 보여준다. 다른 서버에 있는 웹페이지를 가져오는 다른 방법도 있다. 
<img src="https://images.velog.io/images/su-ram/post/ff1c96f2-1e4c-4341-86a1-f557cb4507ce/curl.PNG" alt="">
curl로 웹페이지를 가져온 경우 텍스트형식의 html문서를 가져온 것을 볼 수 있다. 브라우저는 이를 예쁘게 파싱해서 시각적으로 렌더링해서 보여준다는 차이점이 있다. 브라우저가 받게 되는 html은 동일하다. 
html은 하나의 긴 텍스트 문서라고 생각하면, 내가 특정한 글로된 정보를 보고 싶은데 그 정보는 어딘가 내가 모르는 다른 컴퓨터 내에 저장되어 있음. 브라우저는 나 대신해서 다른 컴퓨터의 위치를 찾아서 그 정보를 달라고 요청하고 정보를 받아와서 내가 잘 볼 수 있게 변환해서 보여준다. </li>
</ul>
<h1 id="브라우저의-구성">브라우저의 구성</h1>
<ul>
<li><strong>브라우저 구성 요소</strong>
출처: <a href="https://d2.naver.com/helloworld/59361">https://d2.naver.com/helloworld/59361</a></li>
</ul>
<p><img src="https://images.velog.io/images/su-ram/post/8584bef6-0634-4ec7-b394-9f28110eea58/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C.png" alt=""></p>
<ol>
<li>사용자 인터페이스<ul>
<li>주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등. 요청한 페이지를 보여주는 창을 제외한 나머지 모든 부분이다.</li>
</ul>
</li>
<li>브라우저 엔진 <ul>
<li>사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어.</li>
</ul>
</li>
<li>렌더링 엔진 <ul>
<li>요청한 콘텐츠를 표시. 예를 들어 HTML을 요청하면 HTML과 CSS를 파싱하여 화면에 표시함.</li>
</ul>
</li>
<li>통신 <ul>
<li>HTTP 요청과 같은 네트워크 호출에 사용됨. 이것은 플랫폼 독립적인 인터페이스이고 각 플랫폼 하부에서 실행됨.</li>
</ul>
</li>
<li>UI 백엔드 <ul>
<li>콤보 박스와 창 같은 기본적인 장치를 그림. 플랫폼에서 명시하지 않은 일반적인 인터페이스로서, OS 사용자 인터페이스 체계를 사용.</li>
</ul>
</li>
<li>자바스크립트 해석기 <ul>
<li>자바스크립트 코드를 해석하고 실행.</li>
</ul>
</li>
<li>자료 저장소 <ul>
<li>이 부분은 자료를 저장하는 계층이다. 쿠키를 저장하는 것과 같이 모든 종류의 자원을 하드 디스크에 저장할 필요가 있다. HTML5 명세에는 브라우저가 지원하는 &#39;웹 데이터 베이스&#39;가 정의되어 있다.</li>
</ul>
</li>
</ol>
<h1 id="브라우저의-동작-방식">브라우저의 동작 방식</h1>
<ul>
<li><p>렌더링 엔진</p>
<ul>
<li>요청한 웹서버가 html을 body에 담아서 돌려줌.</li>
<li>이때 이 html파일은 완전 텍스트로만 이루어져 있음. </li>
<li>텍스트 내의 태그들을 해석하여 특정한 구조를 만든다.</li>
<li>시각적으로 렌더링하여 사용자의 화면에 보여준다. </li>
</ul>
</li>
<li><p>동작 순서</p>
</li>
</ul>
<ol>
<li><p>HTML파일 파싱. Parsing
 html 형식으로 된 텍스트들을 구문 분석한다. </p>
</li>
<li><p>DOM 트리 구축 </p>
<ul>
<li>DOM : document object model. html 문서를 객체 형태의 모델로 변환한 것. 문서 객체 모델. 모든 태그들을 객체로. 
구분 분석 후 각 요소들을 트리형태로 구성한다. 
컨텐트(내용)를 구조화 한다. </li>
</ul>
</li>
<li><p>렌더 트리 구축
 CSS/style 요소들을 파싱하여 트리형태로 구성한다.
 내용을 어떻게 보여줄지(시각적)를 구조화한다. </p>
</li>
<li><p>렌더 트리 배치
 어떤 공간에 위치할지를 정한다. 레이아웃. </p>
</li>
<li><p>렌더 트리 그리기 
 UI 백엔드가 각 노드들을 그린다. </p>
</li>
</ol>
<h1 id="브라우저의-통신">브라우저의 통신</h1>
<ul>
<li>HTTP/ HTTPS<ul>
<li>HTTP : 좀 특별한 문서를 주고 받기 위한 통신 약속</li>
<li>HTTPS : 통신에 들어가는 데이터들이 암호화됨.</li>
</ul>
</li>
<li>DNS<ul>
<li>문자로 된 주소를 숫자로 이루어진 주소로 바꾸기 위해 찾는 작업. DNS 서버에 물어본다. </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Azure 사용하기 ]]></title>
            <link>https://velog.io/@su-ram/Azure-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@su-ram/Azure-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 19 Mar 2021 14:21:52 GMT</pubDate>
            <description><![CDATA[<ol>
<li>Azure VM 사용</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>