<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kim_sunnnny.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 25 Oct 2023 00:49:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kim_sunnnny.log</title>
            <url>https://velog.velcdn.com/images/kim_sunnnny/profile/1de40ea6-e671-43fc-99a6-a98c67de61bd/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kim_sunnnny.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kim_sunnnny" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[CT] 토스트 계란틀]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%ED%86%A0%EC%8A%A4%ED%8A%B8-%EA%B3%84%EB%9E%80%ED%8B%80</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%ED%86%A0%EC%8A%A4%ED%8A%B8-%EA%B3%84%EB%9E%80%ED%8B%80</guid>
            <pubDate>Wed, 25 Oct 2023 00:49:10 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://www.codetree.ai/training-field/frequent-problems/problems/toast-eggmold/description?page=1&amp;pageSize=20&amp;order=tier">문제</a></h3>
<ul>
<li><p>n * n 격자에 담긴 1 * 1의  계란틀</p>
<ul>
<li>정사각형 모양 계란틀에 담긴 계란의 양 제공</li>
<li>계란틀을 이루는 4개의 선은 분리 가능</li>
</ul>
</li>
<li><p>규칙</p>
<ol>
<li><p>계란의 양이 너무 차이나지 않게 하기 위해 하나의 선을 맞대고 있는 두 계란틀의 양의 차이가 L이상 R이하라면 계란틀의 해당 선 분리</p>
</li>
<li><p>모든 계란틀에 대해 검사 실시, 1 규칙에 해당하는 모든 계란틀의 선 분리</p>
</li>
<li><p>선의 분리를 통해 합쳐진 계란틀의 계란은 하나로 합치고 이후에 다시 분리</p>
</li>
<li><p>합쳤다 다시 분리한 이후의 계란틀 별 계란의 양은 (합쳐진 계란 총 합)/(합쳐진 계란틀 수), 편의상 소수점 버림</p>
 <img src = https://velog.velcdn.com/images/kim_sunnnny/post/89803c37-72e0-403b-b8de-cf2d3549d037/image.png width = 80%>


</li>
</ol>
</li>
</ul>
<pre><code>- 위 과정이 1번의 계란 이동이며, 더 이상 이동이 필요 없을 때까지 과정 반복

**⇒  n*n 격자의 계란 틀에 있는 계란의 양 주어질 때, 계란의 이동이 몇 번 일어나는지 출력**</code></pre><h3 id="2-풀이">2. 풀이</h3>
<ul>
<li>BFS!<ul>
<li>더이상 계란의 이동이 일어나지 않을 때까지 이동할 계란이 있는 칸을 찾고 계란을 이동하기 (반복문)<ul>
<li>이 때 이동할 계란이 있는 칸을 찾기 위해 매 탐색마다 격자의 각 칸의 방문 여부를 확인하며, 방문하지 않은 칸은 BFS를 통해서 주변에 계란틀의 양의 차이가 L이상 R이하인 칸들을 모두 찾아 group변수에 저장한다</li>
<li>탐색이 끝난 후 group의 길이가 2이상이면 (==BFS탐색을 시작한 칸 주변에 계란을 이동할 칸이 존재한다면) 해당 계란들을 이동시킨다.</li>
</ul>
</li>
<li>만약 전체 격자에 대해 탐색 후에 계란이 이동했다면 결과 변수 answer += 1하며, 탐색을 했음에도 이동할 계란이 아예 없었다면 반복문을 중단시키고 결과를 출력한다</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">from collections import deque
n, L, R = map(int, input().split())
eggs = [ list(map(int, input().split())) for _ in range(n)]
answer = 0

dr = [1, -1, 0, 0]
dc = [0, 0, 1, -1]

def bfs(r, c):
    group = [(r,c)]
    queue = deque()
    queue.append((r,c))

    while queue:
        cr, cc = queue.popleft()
        for i in range(4):
            nr = cr + dr[i]
            nc = cc + dc[i]

            if 0 &lt;= nr &lt; n and 0 &lt;= nc &lt; n and not visited[nr][nc]:
                if L &lt;= abs(eggs[nr][nc] - eggs[cr][cc]) &lt;= R: 
                    visited[nr][nc] = True
                    group.append((nr, nc))
                    queue.append((nr, nc))
    return group 

while True:
    # find groups that have L &lt; diff &lt; R
    stop = True
    visited = [[False for _ in range(n)] for _ in range(n)]
    for i in range(n):
        for j in range(n):
            if not visited[i][j]:                
                visited[i][j] = True
                group = bfs(i, j)

                if len(group) &gt; 1:
                    stop = False
                    egg = sum([eggs[r][c] for r,c in group]) // len(group)
                    for r, c in group:
                        eggs[r][c] = egg
    if stop:
        break

    answer += 1

print(answer)</code></pre>
<h3 id="α">+α</h3>
<ul>
<li>유사/동일 문제 : <a href="https://www.acmicpc.net/problem/16234">백준 #16234 인구이동</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 병원 거리 최소화하기]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EB%B3%91%EC%9B%90-%EA%B1%B0%EB%A6%AC-%EC%B5%9C%EC%86%8C%ED%99%94%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EB%B3%91%EC%9B%90-%EA%B1%B0%EB%A6%AC-%EC%B5%9C%EC%86%8C%ED%99%94%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 20 Oct 2023 05:38:39 GMT</pubDate>
            <description><![CDATA[<h3 id="1-----문제">1.     <a href="https://www.codetree.ai/training-field/frequent-problems/problems/min-of-hospital-distance/description?page=1&amp;pageSize=20&amp;order=tier">문제</a></h3>
<ul>
<li><p>도시 n * n</p>
<ul>
<li><p>각 칸 : 사람, 병원, 빈칸</p>
</li>
<li><p>각 사람의 병원 거리 = 가장 가까운 병원까지 거리   : <code>|x2 - x1| + |y2 - y1|</code></p>
</li>
<li><p>m개의 병원 남겨두고 나머지 폐업</p>
<ul>
<li>m개의 병원 대한 각 사람들의 병원거리가의 총 합이 최소가 되도록</li>
</ul>
</li>
<li><p><em>⇒  m개의 병원을 잘 골라 병원 거리의 총 합을 최소화하는 프로그램 작성*</em></p>
</li>
</ul>
</li>
</ul>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>백트래킹</p>
</li>
<li><p>주어진 병원들 중 m개를 골라서 병원거리 측정</p>
<p>  ⇒ dfs함수, visited배열을 통해서 depth == m일 때만 병원 거리 계산</p>
</li>
<li><p>비슷한 문제 : <a href="https://velog.io/@kim_sunnnny/CT-%EC%A1%B0%EC%82%BC%EB%AA%A8%EC%82%AC">조삼모사</a></p>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">n, m = map(int, input().split())
graph = [list(map(int,input().split())) for _ in range(n)]
 # 0:blank, 1:person, 2:hospital
people = []
hospital = []

for r in range(n):
    for c in range(n):
        if graph[r][c] == 1:
            people.append((r,c))
        elif graph[r][c] == 2:
            hospital.append((r,c))

len_h = len(hospital)
visited = [False] * len_h
result = float(&quot;INF&quot;)

def calc():
    res = 0
    for pr,pc in people:
        minh = 2 * n
        for i in range(len_h):
            if visited[i]:
                hr, hc = hospital[i][0], hospital[i][1]
                h = abs(pr - hr) + abs(pc - hc)
                minh = min(minh, h)
        res += minh
    return res


def dfs(depth, last_idx):
    global result, remain
    if depth == m:
        result = min(result, calc())
        return

    for i in range(last_idx + 1, len_h):
        visited[i] = True
        dfs(depth + 1, i)
        visited[i] = False

dfs(0, -1)

print(result)</code></pre>
<h3 id="α">+α</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 자율주행 자동차]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EC%9E%90%EC%9C%A8%EC%A3%BC%ED%96%89-%EC%9E%90%EB%8F%99%EC%B0%A8</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EC%9E%90%EC%9C%A8%EC%A3%BC%ED%96%89-%EC%9E%90%EB%8F%99%EC%B0%A8</guid>
            <pubDate>Fri, 13 Oct 2023 02:55:18 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://www.codetree.ai/training-field/frequent-problems/problems/autonomous-driving/description?page=1&amp;pageSize=20&amp;order=tier">문제</a></h3>
<ul>
<li><p>도로 : n * m</p>
</li>
<li><p>자동차 : 1 * 1</p>
</li>
<li><p>다음 규칙에 따라서 이동</p>
<ol>
<li><p>현재 방향을 기준으로 왼쪽으로 간 적이 없으면 <strong>좌회전 + 1칸 전진</strong></p>
 <img src=https://velog.velcdn.com/images/kim_sunnnny/post/36dc19f3-dcdb-4b8a-a697-681522e4d082/image.png width=50%>


</li>
</ol>
</li>
</ul>
<pre><code>2. 왼쪽이 인도/이미 방문한 경우 **좌회전 + 1번 과정 시도**

    &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/32cdd171-a191-4715-b864-1167e034f29d/image.png width=50%&gt;


3. 2번에 대해 4방향 모두 확인해도 전진 불가하다면 
    1. 현재 방향 유지한 채로 **1칸 후진 + 1번 과정**

        &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/5fade859-6227-4dfe-b38d-3aae2a8efd06/image.png width=50%&gt;


    2. 후진을 못하는 상황이면 작동 **stop** 

        &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/3accb752-abc6-45d2-88f3-b13aa180168f/image.png width=25%&gt;


- 입력
    - 도로의 세로 크기 `n,` 가로 크기 `m`
    - 자율주행 자동차의 초기 위치 (`x`, `y`)와 바라보는 방향 d
        - `d` :  0부터 3까지 숫자로 주어지고, 순서대로 북쪽, 동쪽, 남쪽, 서쪽
        - `x` : 위쪽에서부터 아래쪽까지 0부터 n-1까지 차례대로 번호
        - `y` : 왼쪽에서 오른쪽까지 차례대로 번호
    - 셋째줄부터 n+2번째 줄까지는 도로의 상태가 주어집니다. 도로는 0, 인도는 1으로 주어집니다.
    - 3 ≤ n, m ≤ 50
    - 자율주행 자동차가 있는 칸은 도로일 것이라 가정해도 좋습니다.
    - 격자의 첫번째 행과 마지막 행, 첫번째 열과 마지막 열은 항상 인도일 것이라고 가정해도 좋습니다.</code></pre><p><strong>⇒  자율주행 자동차가 작동을 멈췄을 때 거쳐갔던 도로의 총 면적? (처음 위치의 도로 포함)</strong></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li>simulation</li>
<li><code>while</code> 반복문 내에서 좌회전 가능 여부 후 이동 및 후진 진행</li>
<li>좌회전 시 방향은 N(0) → W(3), W(3) → S(2), S(2) → E(1), E(1) → W(0) 이므로, 좌회전 후 방향은 <code>d = (d + 3) % 4</code> 와 같다</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">n, m = map(int, input().split()) #  n = height, m = width
x, y, d = map(int, input().split())                             # d = 0 ~ 3 : N E S W
roads = [ list(map(int, input().split())) for _ in range(n)]    # 0 : road, 1: sidewalk
visited = [[0]*m for _ in range(n)]

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

def can_move(x, y):
    move = False 
    if  0 &lt;= x &lt; n and 0 &lt;= y &lt; m and roads[x][y] == 0 and not visited[x][y]:
        move = True
    return move

visited[x][y] = 1
trial = 0
while True:
    d = (d + 3) % 4
    nx = x + dx[d]
    ny = y + dy[d]
    trial += 1

    if can_move(nx, ny): # if can move, (in range, is a road, not visited),  move (change x, y, reset trial, change visited)#  
        x, y = nx, ny
        trial = 0
        visited[x][y] = 1

    else:   # if can&#39;t move, (already visited, out of range)
        if trial == 4 :     #   if trial == 4 
            nx = x - dx[d]
            ny = y - dy[d]            
            if 0 &lt;= nx &lt; n and 0 &lt;= ny &lt; m and roads[nx][ny] == 0:  #if can go backwards, go backwards(change x, y, reset trial)
                x = nx
                y = ny
                visited[x][y] = 1
                trial = 0                
            else:       # if can&#39;t move backwards, (already visited, out of range)
                break

        else:       # if trial &lt;4 
            continue

answer = 0
for i in range(n):
    for j in range(m):
        answer += visited[i][j]
print(answer)</code></pre>
<h3 id="α">+α</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT]놀이기구 탑승]]></title>
            <link>https://velog.io/@kim_sunnnny/CT%EB%86%80%EC%9D%B4%EA%B8%B0%EA%B5%AC-%ED%83%91%EC%8A%B9</link>
            <guid>https://velog.io/@kim_sunnnny/CT%EB%86%80%EC%9D%B4%EA%B8%B0%EA%B5%AC-%ED%83%91%EC%8A%B9</guid>
            <pubDate>Thu, 12 Oct 2023 01:46:07 GMT</pubDate>
            <description><![CDATA[<h3 id="1------문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20"></a>    문제</h3>
<ul>
<li><p>놀이기구 : n * n</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/01804aff-9213-4b32-8ec8-6f256fffae63/image.png width = 50%>


</li>
</ul>
<ul>
<li><p>학생 : n * n  명</p>
<ul>
<li><p>각 학생별로 좋아하는 학생 4명씩 (동일한 학생에 대해 좋아하는 학생 번호 중복 가능</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/c65969b2-b3c9-4821-ae9b-21345bdbabd7/image.png width = 15%>


</li>
</ul>
</li>
</ul>
<pre><code>- 입력으로 주어진 학생들의 순서대로 다음 조건에 따라 가장 우선순위가 높은 칸으로 탑승  ( 항상 비어있는 칸으로만 이동)
    1. 격자를 벗어나지 않는 4방향으로 인접한 칸 중 앉아있는 좋아하는 친구의 수가 가장 많은 위치로
    2. 1번 조건을 만족하는 칸이 여러 곳이라면 인접한 칸 중 비어있는 칸의 수가 가장 많은 위치로
    3. 2번 조건을 만족하는 칸이 여러 곳이라면 행 번호가 가장 작은 위치로
    4. 3번 조건을 만족하는 칸이 여러 곳이라면 열 번호가 가장 작은 위치로 

    &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/541d32cb-2da7-4951-a612-3433d9b1cc84/image.png width = 90%&gt;


- 최종 점수 계산
    - 각 학생의 인접한 곳에 앉아있는 좋아하는 친구의 수

        &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/4a102877-4265-4aef-9c8c-2af851f57ef1/image.png width=40%&gt;</code></pre><p><strong>⇒  들어오는 학생의 순서와 각 학생마다 좋아하는 4명의 학생 번호가 주어졌을 때, 최종 점수?</strong></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><code>like_info</code> : 입력으로 주어진 학생-좋아하는 친구에 대한 리스트</li>
<li><code>ride</code> : n * n 크기의 놀이기구 탑승 공간</li>
<li>자리에 앉는 기준 : 주변에 좋아하는 친구 수 &gt; 빈칸 수 &gt; 행 번호 &gt; 열 번호</li>
<li>like_info를 한 행씩 읽으면서, 각 학생이 앉을 자리를 탐색<ul>
<li>ride의 각 칸마다 탐색하며 candidates 리스트를 채우기<ul>
<li>칸이 비어 있다면 해당 칸 위, 아래, 왼쪽, 오른쪽 탐색하며 빈칸 수와 좋아하는 학생의 수를 확인함</li>
<li>(좋아하는 친구 수, 탐색한 빈칸 수, 행번호, 열번호) 를 candidates리스트에 넣음</li>
<li>candidates를 정렬한 뒤 맨 첫번째 원소에 해당되는 위치에 학생 정보 입력</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">def look_around(r, c, favorites):
    fav, blanks = 0, 0
    for i in range(4):
        nr = r + dr[i]
        nc = c + dc[i]

        if 0 &lt;= nr &lt; n and 0 &lt;= nc &lt; n:
            if ride[nr][nc] in favorites:
                fav += 1
            elif ride[nr][nc] == 0:
                blanks += 1
    return fav, blanks

n = int(input())
like_info = [ list(map(int, input().split())) for _ in range(n*n) ]

ride = [ [0]*(n) for _ in range(n)]

dr = [1, -1, 0, 0]
dc = [0, 0, 1, -1]

for i in range(n * n):
    student = like_info[i][0]
    favorites = like_info[i][1:]

    candidates = []

    for r in range(n):
        for c in range(n):

            if ride[r][c] == 0:
                fav, blanks = look_around(r, c, favorites)
                candidates.append([fav, blanks, r, c])

    candidates.sort(key= lambda x: (-x[0], -x[1], x[2], x[3]))
    seat = candidates[0]
    ride[seat[2]][seat[3]] = student

students = [x[0] for x in like_info]

answer = 0
for i in range(n):
    for j in range(n):
        student_idx = students.index(ride[i][j])
        fav, blanks = look_around(i, j, like_info[student_idx][1:])
        if fav &gt; 0:
            answer += 10 ** (fav - 1)
print(answer)</code></pre>
<h3 id="α">+α</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 14891 톱니바퀴]]></title>
            <link>https://velog.io/@kim_sunnnny/BOJ-14891-%ED%86%B1%EB%8B%88%EB%B0%94%ED%80%B4</link>
            <guid>https://velog.io/@kim_sunnnny/BOJ-14891-%ED%86%B1%EB%8B%88%EB%B0%94%ED%80%B4</guid>
            <pubDate>Mon, 09 Oct 2023 14:12:29 GMT</pubDate>
            <description><![CDATA[<h3 id="1------문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20"></a>    <a href="https://www.acmicpc.net/problem/14891">문제</a></h3>
<ul>
<li><p>총 8개의 톱니를 가지고 있는 톱니바퀴 4개</p>
<ul>
<li>톱니의 N극은 0, S극은 1</li>
</ul>
</li>
<li><p>톱니바퀴에는 번호가 매겨져 있음</p>
<ul>
<li>가장 왼쪽 톱니바퀴가 1번, 그 오른쪽은 2번, 그 오른쪽은 3번, 가장 오른쪽 톱니바퀴는 4번</li>
</ul>
</li>
<li><p>톱니바퀴 A를 회전할 때,</p>
<ul>
<li><p>그 옆에 있는 톱니바퀴 B와 서로 맞닿은 톱니의 극이 다르다면, B는 A가 회전한 방향과 반대방향으로 회전</p>
</li>
<li><p>서로 맞닿은 톱니의 극이 같다면, B는 회전하지 않음</p>
  <img src =https://velog.velcdn.com/images/kim_sunnnny/post/81deab4f-ccd9-4c8d-9c2b-31fb4ee6122e/image.png width = 70%>


</li>
</ul>
</li>
</ul>
<pre><code>    - 입력:
        - 4줄에 걸쳐 각 톱니바퀴 상태 입력 (N극은 0, S극은 1, 12시방향부터 시계 방향 순서대로)
        - 회전횟수 K (1≤ K ≤ 100)
        - K개 줄 동안 회전시킨 방법
            - 각 방법은 두 개의 정수 :
                - 회전시킨 톱니바퀴 번호
                - 방향 (1: 시계방향, -1: 반시계 방향)

    **⇒  톱니바퀴의 초기 상태와 톱니바퀴를 회전시킨 방법이 주어졌을 때,**  K번 회전시킨 이후에 네 톱니바퀴의 점수의 합?

    - 점수 계산
        - 1번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 1점
        - 2번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 2점
        - 3번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 4점
        - 4번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 8점</code></pre><h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>회전한다 == “기준이 바뀐다”</p>
<ul>
<li><p>12시 방향을 나타내는 배열 <code>top</code> 을 활용 (4개의 톱니바퀴지만, 1번부터 처리하므로 길이를 5로 설정)</p>
</li>
<li><p>시계 방향 : -1</p>
</li>
<li><p>반시계 방향 : +1</p>
  <img src =https://velog.velcdn.com/images/kim_sunnnny/post/e8955c64-e129-42b0-939a-795210e3f467/image.png width = 80%>





</li>
</ul>
</li>
</ul>
<ul>
<li>주어진 회전 정보 마다 (회전 톱니바퀴 idx, 회전방향)<ul>
<li>idx 톱니바퀴의 오른쪽과 왼쪽으로 나누어서,  idx의 회전에 따라 회전하는 톱니들을 조사<ul>
<li>idx 톱니와 거리가 홀수만큼 차이나는 톱니는 반대방향으로 회전, 짝수만큼 차이나는 톱니는 같은 방향으로 회전</li>
<li>회전할 톱니들은 tlst 배열에 담아서 오른쪽 왼쪽 조사를 모두 마친 뒤 한번에 회전</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">N = 4

arr = [[0] * 8] + [list(map(int, input())) for _ in range(N)]
K = int(input())

top = [0] * (N+1)

for _ in range(K):
    idx, dr = map(int, input().split())     #dr : cw = 1, ccw = -1 
    tlst = [(idx, 0)]                       # =&gt; but when rotating, ccw has to add to top[idx], cw has to subtract

    # right side of idx wheel
    for i in range(idx + 1, N + 1):        
        if arr[i-1][(top[i - 1] + 2) % 8] != arr[i][(top[i] + 6) % 8] :
            tlst.append((i, (i - idx) % 2))
        else:
            break
    #left side of idx wheel
    for i in range(idx-1, 0, -1):
        if arr[i][(top[i] + 2) % 8] != arr[i + 1][(top[i+1] + 6) % 8] :
            tlst.append((i, (idx - i)%2 ))
        else:
            break

    for i, rot in tlst:
        if rot == 0:    #rotate same direction ( abs(idx - i) % 2 == 0 )
            top[i] = (top[i] - dr + 8) % 8
        else:
            top[i] = (top[i] + dr + 8) % 8

answer = 0
calc = [0, 1, 2, 4, 8]

for i in range(1, N+1):
    answer += arr[i][top[i]] * calc[i]

print(answer)</code></pre>
<h3 id="α">+α</h3>
<ul>
<li>참고<ul>
<li><a href="https://www.youtube.com/watch?v=0VfhMu6s21w&amp;t=1s">https://www.youtube.com/watch?v=0VfhMu6s21w&amp;t=1s</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 나무 타이쿤]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EB%82%98%EB%AC%B4-%ED%83%80%EC%9D%B4%EC%BF%A4</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EB%82%98%EB%AC%B4-%ED%83%80%EC%9D%B4%EC%BF%A4</guid>
            <pubDate>Sat, 07 Oct 2023 10:49:46 GMT</pubDate>
            <description><![CDATA[<h3 id="1----문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20"></a>  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/tree-tycoon/description?page=2&amp;pageSize=20">문제</a></h3>
<ul>
<li><p>n * n 격자에 서로 다른 높이를 가진 리브로수 나무 키우기</p>
<ul>
<li><strong>특수 영양제</strong>  : 나무 키우기 위해 필요<ul>
<li>1 * 1 땅에 있는 나무 높이를 + 1</li>
<li>씨앗만 있으면 높이 1의 나무 생성</li>
<li>초기 특수 영양제 : n * n 격자 최하단 4개의 칸</li>
<li>이동 규칙에 따라 움직임 : 이동 방향 + 이동 칸 수<ul>
<li>이동방향 : 1~8번 ➡️ ↗ ⬆️ ↖ ⬅️ ↙ ⬇️ ↘</li>
<li>n번 열에서 오른쪽으로 이동 : 1번열로 이동</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>1년 동안 다음 단계를 거쳐 성장</p>
<ol>
<li>특수 영양제를 이동 규칙에 따라 이동</li>
<li>특수 영양제를 이동 시킨 후 해당 땅에 특수 영양제를 투입<ul>
<li>투입 후 땅에 있던 특수 영양제는 소멸</li>
</ul>
</li>
<li>특수 영양제를 투입한 리브로수의 대각선으로 인접한 방향에 높이가 1 이상인 리브로수가 있는 만큼 높이가 더 성장<ul>
<li>대각선으로 인접한 방향이 격자를 벗어나는 경우에는 세지 않음</li>
</ul>
</li>
<li>특수 영양제를 투입한 리브로수를 제외하고 높이가 2 이상인 리브로수는 높이 2를 베어서 잘라낸 리브로수로 특수 영양제를 사고, 해당 위치에 특수 영양제를 올려둡니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/kim_sunnnny/post/f17b67bb-5794-46ef-b79f-74752d91172a/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<p><strong>⇒  n x n 격자의 칸에 리브로수의 각자 다른 높이와 각 년도의 이동 규칙이 주어질 때, 해당 년수가 모두 지나고 난 뒤 남아있는 리브로수 높이들의 총 합?</strong></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>이동규칙에 따라 이동했을 때 행과 열이 격자 범위 밖을 나갔을 때</p>
<ul>
<li>if idx &lt; 0 ⇒ idx += n</li>
<li>if idx &gt; n ⇒ idx %= n</li>
</ul>
</li>
<li><p>시간 복잡도 줄이기</p>
<ul>
<li>매년 기존의 특수 영양제는 제거하고 특수 영양제가 이동하는 과정에서 위치 정보값을 저장하는 구조를 list보다 set으로 저장하여 중간에 생기는 중복 값을 제거하며 진행!!</li>
</ul>
</li>
</ul>
<pre><code>    - 시간 복잡도 줄이기 전 코드 (list)

        ```python
        n, m = map(int, input().split())

        trees = [ list(map(int, input().split())) for _ in range(n) ]
        moves = [ tuple(map(int, input().split())) for _ in range(m) ]

        #     → ↗  ↑  ↖  ← ↙ ↓ ↘
        dr = [0, -1, -1, -1, 0, 1, 1, 1]
        dc = [1, 1, 0, -1, -1, -1, 0, 1]

        sur_r = [-1, -1, 1, 1]
        sur_c = [-1, 1, -1, 1]

        def moved(x):
            if x &lt; 0:
                x =  x + n
            elif x &gt;= n:
                x = x % n
            return x

        nutri = [[n-1, 0], [n-1, 1], [n-2, 0], [n-2, 1] ]

        for move in moves:
            d_idx, leng = move[0]-1, move[1]

            for i in range(len(nutri)):
                nutri[i][0] = moved(nutri[i][0] + dr[d_idx] * leng)
                nutri[i][1] = moved(nutri[i][1] + dc[d_idx] * leng)

            for i in range(len(nutri)):
                trees[nutri[i][0]][nutri[i][1]] += 1

            for n_r, n_c in nutri:
                surround = 0
                for i in range(4):
                    r = n_r + sur_r[i]
                    c = n_c + sur_c[i]
                    if 0 &lt;= r &lt; n and 0 &lt;= c &lt; n and trees[r][c] &gt;= 1:
                        surround += 1
                trees[n_r][n_c] += surround

            new_nutri = []
            for i in range(n):
                for j in range(n):
                    if [i,j] not in nutri and trees[i][j] &gt;= 2:
                        trees[i][j] -= 2
                        new_nutri.append([i,j])

            nutri = new_nutri

        answer = 0
        for row in trees:
            answer += sum(row)

        print(answer)
        ```

        ![](https://velog.velcdn.com/images/kim_sunnnny/post/d6efa60b-69ad-4178-a9c8-20cdba971685/image.png)</code></pre><h3 id="3-최종-코드">3. 최종 코드</h3>
<pre><code class="language-python">n, m = map(int, input().split())

trees = [ list(map(int, input().split())) for _ in range(n) ]
moves = [ tuple(map(int, input().split())) for _ in range(m) ]

#     → ↗  ↑  ↖  ← ↙ ↓ ↘
dr = [0, -1, -1, -1, 0, 1, 1, 1]
dc = [1, 1, 0, -1, -1, -1, 0, 1]

sur_r = [-1, -1, 1, 1]
sur_c = [-1, 1, -1, 1]

def moved(x):
    if x &lt; 0:
        x =  x + n
    elif x &gt;= n:
        x = x % n
    return x

nutri = [[n-1, 0], [n-1, 1], [n-2, 0], [n-2, 1] ]

for move in moves:
    d_idx, leng = move[0]-1, move[1]

    for i in range(len(nutri)):
        nutri[i][0] = moved(nutri[i][0] + dr[d_idx] * leng)
        nutri[i][1] = moved(nutri[i][1] + dc[d_idx] * leng)

    for i in range(len(nutri)):
        trees[nutri[i][0]][nutri[i][1]] += 1

    for n_r, n_c in nutri:
        surround = 0
        for i in range(4):
            r = n_r + sur_r[i]
            c = n_c + sur_c[i]
            if 0 &lt;= r &lt; n and 0 &lt;= c &lt; n and trees[r][c] &gt;= 1:
                surround += 1
        trees[n_r][n_c] += surround

    new_nutri = []
    for i in range(n):
        for j in range(n):
            if [i,j] not in nutri and trees[i][j] &gt;= 2:
                trees[i][j] -= 2
                new_nutri.append([i,j])

    nutri = new_nutri

answer = 0
for row in trees:
    answer += sum(row)

print(answer)</code></pre>
<p><img src="https://velog.velcdn.com/images/kim_sunnnny/post/f15096c6-c624-4765-a905-3e09caeb732a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 불안한 무빙워크]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EB%B6%88%EC%95%88%ED%95%9C-%EB%AC%B4%EB%B9%99%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EB%B6%88%EC%95%88%ED%95%9C-%EB%AC%B4%EB%B9%99%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Mon, 02 Oct 2023 11:23:10 GMT</pubDate>
            <description><![CDATA[<h3 id="1---문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20"></a> <a href="https://www.codetree.ai/training-field/frequent-problems/problems/unstable-moving-walk/description?page=2&amp;pageSize=20">문제</a></h3>
<ul>
<li><p>1~3 과정 중 n번 칸 위치에 사람이 위치하면 즉시 하차</p>
</li>
<li><p>각 칸의 안정성은 시간이 지남에 따라 다시 상승하지 않음</p>
</li>
<li><p>ex) 각 칸의 안정성 = 2, 0인 칸이 1 이상일 때 실험 종료</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/7f9f0d10-6c82-4446-aa37-535a5832d400/image.png width=70%>


</li>
</ul>
<pre><code>- 위 과정이 1번의 실험

**⇒  과정이 종료될 때 몇 번째 실험을 하고 있었는지?**</code></pre><p><br><br/></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>시뮬레이션 : 조건문과 엣지 케이스를 고려하자</p>
<ul>
<li><p>무빙워크의 각 위치별 안정도를 담은 배열 <code>stability</code></p>
<ul>
<li><code>stability[0]</code> : 0번째 위치의 안정도</li>
</ul>
</li>
<li><p>실험에 참여한 사람에 대한 정보를 담은 배열 <code>people</code></p>
<ul>
<li><code>people[0]</code> : 0번째 위치에 사람이 있으면 1, 없으면 0</li>
</ul>
</li>
<li><p>zeros 변수로 안정도가 0인 위치의 개수를 추적하여 simulate가 끝난 후 zeros가 k이상이 되면 실험 종료 (while 반복문 탈출)</p>
</li>
</ul>
<p><br><br/></p>
<ul>
<li><p>simulate 함수 1회 = 실험 1회</p>
<ul>
<li><p>무빙워크를 이동시킨 후, (<code>stability</code> 배열, <code>people</code> 배열 모두 회전)</p>
</li>
<li><p>n번칸에 사람이 있으면 ( <code>people[n-1] == 1</code>) 하차시키기</p>
</li>
<li><p>사람 이동 시키기</p>
<ul>
<li>현재 index 전에 사람이 있고, 현재 위치에 사람이 없고, 안정도가 0보다 클 경우 이동</li>
<li>이동 :<ul>
<li><code>stability[index] -=1</code></li>
<li><code>people[index] = 1</code></li>
<li><code>people[index-1] = 0</code></li>
<li><code>stability[index] == 0</code>이면 <code>zeros+1</code></li>
</ul>
</li>
</ul>
</li>
<li><p>이동 후에도 n번칸에 사람이 있으면 내리기</p>
</li>
<li><p>0번째 칸에 (사람은 이동해서 비어있을 것이므로) 안정도가 0보다 크면 사람 새롭게 올리기</p>
<ul>
<li>이 행위로 0번째 칸의 안정도가 0이 되면  <code>zeros + 1</code>
<br><br/><h3 id="3-코드">3. 코드</h3>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code class="language-python">from collections import deque

n, k = map(int, input().split())
stability = deque(list(map(int, input().split())))
people = deque([0 for i in range(n)])

zeros = 0

def simulate():
    global zeros

    # 무빙워크 이동
    stability.appendleft(stability.pop())
    people.appendleft(people.pop())

    # n번칸 사람 내리기
    if people[n - 1]:
        people[n - 1] = 0

    # 사람 이동
    for i in range(n - 1, 0, -1):
        # 현재 위치에 사람이 없고 내구도는 남아 있으면서 이전 위치에 사람이 있는 경우
        if people[i] == 0 and people[i - 1] and stability[i]:
            people[i] = 1
            people[i - 1] = 0

            stability[i] -= 1

            if stability[i] == 0:
                zeros += 1
    # n번칸 사람 내리기
    if people[n - 1]:
        people[n - 1] = 0

    # 사람 올리기
    if stability[0]:
        stability[0] -= 1
        people[0] = 1

        if stability[0] == 0:
            zeros += 1

answer = 0
while True:
    simulate()
    answer += 1

    if zeros &gt;= k:
        break

print(answer)</code></pre>
<p><br><br/><br><br/></p>
<h3 id="α">+α</h3>
<ul>
<li><p>1차 시도 : 실패 - 시간 초과, 문제 해석 오류</p>
<ul>
<li><p>people이라는 빈 list에 사람을 append하는 방식, people[0]은 1번째 사람의 위치</p>
<pre><code class="language-python">  n, k = map(int, input().split())
  stability = list(map(int, input().split()))
  zeros = stability.count(0)

  people = [] # people[0] = location on moving walk of 1st person

  exp = 0
  stop = False

  while True:
      exp += 1
      #rotate
      stability = [stability[-1]] + stability[1:2*n-1]

      #move people on moving walk
      for idx, p in enumerate(people):
          if p == n-1:
              people.pop(i)
          elif p + 1 in people or stability[p+1] == 0:
              continue
          else:
              people[idx] += 1
              stability[p+1] -= 1
              if stability[p+1] == 0:
                  zeros +=1 

          if zeros &gt;= k:
              stop = True
              break

      if not stop and 0 not in people:
          people.append(0) 
          stability[0] -= 1
          if stability[0] == 0:
              zeros += 1
      if zeros &gt;= k:
          stop = True

      if stop:        
          break

  print(exp)</code></pre>
</li>
</ul>
</li>
</ul>
<p><br><br/>
참고</p>
<ul>
<li><a href="https://tight-sleep.tistory.com/38">https://tight-sleep.tistory.com/38</a></li>
<li><a href="https://velog.io/@jimeaning/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EB%B6%88%EC%95%88%ED%95%9C-%EB%AC%B4%EB%B9%99%EC%9B%8C%ED%81%AC">https://velog.io/@jimeaning/코드트리-불안한-무빙워크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 연산자 배치하기]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 15 Sep 2023 08:32:00 GMT</pubDate>
            <description><![CDATA[<h3 id="1--문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/arrange-operator/description?page=1&amp;pageSize=20&amp;order=tier">문제</a></h3>
<ul>
<li><p>n개의 정수 순서대로 (순서 바꿀 수 없음)</p>
</li>
<li><p>n-1개의 연산자 배치</p>
<ul>
<li><p>덧셈, 뺄셈, 곱셈</p>
</li>
<li><p>연산자 간 우선 순위 무시, 앞에서부터 차례대로 연산</p>
</li>
<li><p><em>⇒  가능한 식의 최솟값, 최댓값?*</em></p>
</li>
</ul>
</li>
</ul>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>1차 시도: 백트래킹을 시도해 봄…</p>
<ul>
<li>조삼모사를 백트래킹으로 했던 것처럼 순열을 구하는 함수 구조를 이용해서 dfs/백트래킹과 연산값을 구하는 함수를 이용해서 풀어보려고 함</li>
<li>입력받은 연산자의 개수를 기반으로 연산자 배열을 만들고, 해당 배열의 인덱스에 대해 순열을 만들어서 해결해보려고 하였으나 연산자 순서의 중복을 고려하지 않아서 연산횟수도 쓸데없이 많아지고 점점 산으로 가버림..!</li>
</ul>
</li>
<li><p>정답 코드 해설:</p>
<ul>
<li>dfs를 이용한 백트래킹을 할 때 depth와 연산자 개수에 대한 변수를 함께 이용<ul>
<li>depth는 입력으로 받은 정수 배열의 인덱스와 동일함</li>
<li>연산자 조합을 만들 때 개수를 1개씩 차감하고 depth를 1개씩 더해가며, 바로 연산을 하면서 최솟값과 최댓값을 구함!</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">def dfs(depth, total, plus, sub, multi):
    global MIN, MAX
    if depth == n:
        MIN = min(MIN, total)
        MAX = max(MAX, total)

    if plus:
        dfs(depth + 1, total + num[depth], plus - 1, sub, multi)

    if sub:
        dfs(depth + 1, total - num[depth], plus, sub - 1, multi)

    if multi:
        dfs(depth + 1, total * num[depth], plus, sub, multi - 1)

n = int(input())

num = list(map(int, input().split()))
plus, sub, multi = map(int, input().split())

MIN, MAX = float(&quot;INF&quot;), -float(&quot;INF&quot;)
dfs(1, num[0], plus, sub, multi)
print(MIN, MAX)</code></pre>
<h3 id="α">+α</h3>
<p>정답 코드가 아주 예술적이고 예쁘다… :)</p>
<p>언젠가 저런 코드를 내 손으로 작성할 수 있기를,,,ㅠ_ㅠ</p>
<ul>
<li>참고 : <a href="https://velog.io/@jimeaning/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0">https://velog.io/@jimeaning/%EC%BD%94%EB%93%9C%ED%8A%B8%EB%A6%AC-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</a> </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 조삼모사]]></title>
            <link>https://velog.io/@kim_sunnnny/CT-%EC%A1%B0%EC%82%BC%EB%AA%A8%EC%82%AC</link>
            <guid>https://velog.io/@kim_sunnnny/CT-%EC%A1%B0%EC%82%BC%EB%AA%A8%EC%82%AC</guid>
            <pubDate>Fri, 15 Sep 2023 01:20:55 GMT</pubDate>
            <description><![CDATA[<h3 id="1--문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20"></a><a href="https://www.codetree.ai/training-field/frequent-problems/problems/three-at-dawn-and-four-at-dusk/description?page=1&amp;pageSize=20&amp;order=tier">문제</a></h3>
<ul>
<li><p><code>n</code>개의 일 → 아침/저녁으로 <code>n/2</code>씩 처리</p>
</li>
<li><p>업무 강도 / 업무 간 상성 Pij</p>
<ul>
<li><p>ex)</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/778e8450-57f5-4832-88fc-b79e5f643c8d/image.png width="40%" height = "40%">


</li>
</ul>
</li>
</ul>
<pre><code>    - 1, 2번 일을 아침 +  3, 4번 일을 저녁
        - 아침에 하는 일의 총 업무 강도는 *P*12 + *P*21 = 8
        - 저녁의 경우 *P*34 + *P*43 = 13
    - 1,4번 일을 아침 + 2, 3번 일을 저녁
        - 아침의 경우 *P*14 + *P*41 = 2
        - 저녁의 경우 *P*23 + *P*32 = 9

    ⇒ 1,2번 일과 3, 4번의 일로 나누어서 하는 것이 힘듦의 합의 차이가 5로 최솟값</code></pre><p><strong>⇒  아침의 하는 일의 업무 강도와 저녁에 하는 일의 업무 강도의 차이의 최솟값?</strong></p>
<h3 id="2-풀이">2. 풀이</h3>
<ol>
<li><p>구현… → </p>
<ul>
<li><p>아침/저녁에 작업할 일의 조합을 구해서 각각에 대한 업무 강도를 모두 계산</p>
</li>
<li><p>조합을 구하고 정렬을 할 경우, i번째 원소가 아침에 작업할 일이라면 -i-1번째 원소가 저녁에 작업할 일이다</p>
<ul>
<li>ex) [1,2,3,4] 에서 일의 조합을 구한다면<ul>
<li>[ [1,2] , [1,3], [1,4] [2,3], [2,4], [3,4] ] 이므로</li>
<li>아침 저녁의 조합은 [1,2] + [3,4], [1,3] + [2,4], [1,4] + [2,3] 일 것이다</li>
</ul>
</li>
</ul>
</li>
<li><p>너무나도 당연히 시간복잡도가 엄청나다</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/4f7747d3-4789-45b6-adf0-73c4393e9056/image.png width="20%">


</li>
</ul>
</li>
</ol>
<ol start="2">
<li>DFS / 백트래킹 <ul>
<li>조합을 다 구하고 일의 강도를 계산하는 것이 아니라, 조합을 구하면서 강도를 계산하고, 업무 강도 차이의 최솟값을 구한다!<ul>
<li>1부터 n까지의 업무들에 대한 배열의 index를 이용해서</li>
<li>업무 강도를 구하는 함수에서 depth 변수를 이용하여 아침 업무가 n//2개 될 때만 저녁의 업무를 조건문으로 구하고 각각의 업무의 강도를 계산한다</li>
<li>아침/저녁 업무 조합에 대한 업무의 강도 차이를 현재의 최솟값 ans와 비교하여 최종적으로 가장 작은 값을 최종적으로 반환한다</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="3-코드">3. 코드</h3>
<ol>
<li><p>조합 구현 </p>
<pre><code class="language-python"> def combinations(arr, r):
     for i in range(len(arr)):
         if r == 1:
             yield [arr[i]]
         else:
             for next in combinations(arr[i+1:], r-1):
                 yield [arr[i]] + next

 def solution():
     n = int(input())
     half = n//2

     work = [ list(map(int, input().split())) for _ in range(n) ]

     task = [i for i in range(n)]
     combo = sorted(list(combinations(task, half)))

     balance = []

     for jobs in combo:
         intensity = 0
         intensities = list(combinations(jobs, 2))

         for i, j in intensities:
             intensity += work[i][j]
             intensity += work[j][i]

         balance.append(intensity)

     min_diff = abs(balance[0] - balance[-1])

     for i in range(1, len(balance)//2):
         diff = abs(balance[i] - balance[-i-1])
         if min_diff &gt; diff : 
             min_diff = diff

</code></pre>
</li>
</ol>
<pre><code>    print(min_diff)

solution()
```</code></pre><ol>
<li><p>DP/백트래킹</p>
<pre><code class="language-python"> # 일의 양 (2의 배수)
 n = int(input())

 # 업무 간의 상성 Pij
 work = [list(map(int, input().split())) for _ in range(n)]

 def work_intensity(day):
     res = 0
     for i in range(n//2):
         for j in range(i+1, n//2):
             res += work[day[i]][day[j]]
             res += work[day[j]][day[i]]
     return res

 def dfs(idx, depth):
     global ans
     if depth == n//2:
         temp2 = [i for i in range(n) if i not in temp]
         ans = min(ans, abs(work_intensity(temp) - work_intensity(temp2)))

     for i in range(idx + 1, n): #idx = 0 부터 시작하면 
         temp.append(i)
         dfs(i, depth+1)
         temp.pop()

 total = set(range(n))
 temp = [0]
 ans = float(&quot;INT&quot;)
 dfs(0,1)

 print(ans)</code></pre>
</li>
</ol>
<h3 id="α">+α</h3>
<ul>
<li><p>동일 문제 : <strong><a href="https://www.acmicpc.net/problem/14889">백준 14889 스타트와 링크</a></strong></p>
</li>
<li><p>참고</p>
<ul>
<li><a href="https://developer-ellen.tistory.com/50">https://developer-ellen.tistory.com/50</a></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[python] yield vs return (feat. generator)]]></title>
            <link>https://velog.io/@kim_sunnnny/python-yield-vs-return-feat.-generator</link>
            <guid>https://velog.io/@kim_sunnnny/python-yield-vs-return-feat.-generator</guid>
            <pubDate>Wed, 13 Sep 2023 08:36:04 GMT</pubDate>
            <description><![CDATA[<h3 id="yield">yield</h3>
<ul>
<li>generator를 만드는데 사용</li>
</ul>
<p><br><br/></p>
<h3 id="return-yield">return? yield?</h3>
<ul>
<li>함수의 반환 : <code>return</code>  or <code>yield</code></li>
<li>예제<ul>
<li>A, B, C 반환하는 함수</li>
</ul>
<ol>
<li><pre><code class="language-python"> def return_abc() :
     return list(&quot;ABC&quot;)
    print(return_abc()</code></pre>
</li>
<li><pre><code class="language-python"> def yield_abc():
     yield (&quot;A&quot;)
     yield (&quot;B&quot;)
     yield (&quot;C&quot;)
  print(yield_abc())</code></pre>
</li>
</ol>
<ul>
<li>출력 결과
1 : [&#39;A&#39;, &#39;B&#39;, &#39;C&#39;]
2 : &lt;<strong>generator</strong> object yield_abc at 0x7f4ed03e6040&gt;</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="generator">Generator</h2>
<ul>
<li>여러 개의 데이터를 미리 만들어 놓지 않고 필요할 때마다 즉석해서 하나씩 만들어낼 수 있는 객체</li>
</ul>
<ul>
<li><p>ex) time.sleep() 이용한 예제</p>
<pre><code class="language-python">    import time

    # ------------------------ 1: return 출력 -----
    def return_abc():
      alphabets = []
      for ch in &quot;ABC&quot;:
        time.sleep(1)
        alphabets.append(ch)
    return alphabets  

    for ch in return_abc():
        print(ch)

    # ------------------------ 2: yield 출력 -----

    def yield_abc():    # yield from [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;]와 동일
      for ch in &quot;ABC&quot;:
        time.sleep(1)
        yield ch


</code></pre>
</li>
</ul>
<pre><code>  for ch in yield_abc():
      print(ch)
```</code></pre><ul>
<li>1 출력 : 3초 경과 후 A, B, C 차례대로 출력</li>
<li>2 출력 : 1초 후 A 출력, 1초 후 B 출력, 1초 후 C 출력</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="generator의-효율성">generator의 효율성</h3>
<ul>
<li><p>제너레이터를 통해서는 결과값을 나누어서 얻을 수 있기 때문에 성능 측면에서 큰 이점</p>
</li>
<li><p>memory 측면 </p>
<ul>
<li>return 키워드를 사용할 때는 모든 결과 값을 메모리에 올려놓아야 함</li>
<li>yield 키워드를 사용할 때는 결과 값을 하나씩 메모리에 올려놓음</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/><br><br/></p>
<ul>
<li>출처
<a href="https://www.daleseo.com/python-yield/">https://www.daleseo.com/python-yield/</a> </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CT] 바이러스 검사]]></title>
            <link>https://velog.io/@kim_sunnnny/LC-%EB%B0%94%EC%9D%B4%EB%9F%AC%EC%8A%A4-%EA%B2%80%EC%82%AC</link>
            <guid>https://velog.io/@kim_sunnnny/LC-%EB%B0%94%EC%9D%B4%EB%9F%AC%EC%8A%A4-%EA%B2%80%EC%82%AC</guid>
            <pubDate>Wed, 13 Sep 2023 06:20:25 GMT</pubDate>
            <description><![CDATA[<h1 id="ct-바이러스-검사">[CT] 바이러스 검사</h1>
<h3 id="1--문제">1.  <a href="https://www.codetree.ai/training-field/frequent-problems/problems/virus-detector/description?page=1&amp;pageSize=20">문제</a></h3>
<ul>
<li><p>총 n개의 층 식당 고객 체온 측정</p>
</li>
<li><p>각 층 : 검사 팀장 + 검사 팀원</p>
<ul>
<li><p>1가게당 팀장 1명 (필수), 팀원 여러명 (각 층 검사원은 해당 층만 검사)</p>
</li>
<li><p><em>⇒ n개의 식당 고객들의 체온을 측정하기 위해 필요한 검사자 수의 최솟값?*</em></p>
</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li>설명대로 구현</li>
<li><strong><a href="https://www.acmicpc.net/problem/13458">백준 시험감독</a>과 동일한 문제!</strong>
<br><br/></li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">import math

n = int(input())
clients = list(map(int, input().split()))
lead, member = map(int, input().split())

answer = 0

for client in clients:
    if lead &gt;= client :
        answer += 1

    else:
        answer += 1 + math.ceil((client - lead)/member)

print(answer)</code></pre>
<h3 id="α">+α</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 14501 퇴사 ]]></title>
            <link>https://velog.io/@kim_sunnnny/BOJ-14501-%ED%87%B4%EC%82%AC</link>
            <guid>https://velog.io/@kim_sunnnny/BOJ-14501-%ED%87%B4%EC%82%AC</guid>
            <pubDate>Tue, 22 Aug 2023 07:17:33 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://www.acmicpc.net/problem/14501">문제</a></h3>
<ul>
<li><p>N+1일 째 퇴사</p>
</li>
<li><p>남은 N일 동안 최대한 많은 상담</p>
</li>
<li><p>상담 기간 Ti</p>
</li>
<li><p>상담 시 받을 수 잇는 금액 Pi</p>
<ul>
<li><p>예</p>
<p> <img src="https://github.com/seoyeonK/Algo/assets/50603274/34706396-f3d0-4fe5-80c1-b5f555b0aeff" alt="image"></p>
</li>
</ul>
</li>
</ul>
<pre><code>    - 1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다. 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다.
    - 상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다. 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다.
    - 또한, N+1일째에는 회사에 없기 때문에, 6, 7일에 있는 상담을 할 수 없다.

    퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 이때의 이익은 10+20+15=45이다.


**⇒ 상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성**</code></pre><ul>
<li>입력 :<ul>
<li>N   (1 ≤ N ≤ 15)</li>
<li>Ti  Pi   (1일부터 N일까지 순서대로,  1 ≤ Ti ≤ 5, 1 ≤ Pi ≤ 1,000)</li>
</ul>
</li>
<li>출력 : 백준이 얻을 수 있는 최대 이익</li>
</ul>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>DP</p>
<ul>
<li><p>n번째 일에 최대 이익을 구하기 위해서는 (i일 전날의 최대 이익 + i일의 금액) 중 최대 이익을 구해야 함</p>
</li>
<li><p>1~7일을 차례대로 선택해서 그날의 수익을 받았을 때의 최대 수익들을 차례대로 구하면 N+1째 날에 얻을 수 있는 최대 수익을 구할 수 있다.</p>
<p>  <img src="https://github.com/seoyeonK/Algo/assets/50603274/34706396-f3d0-4fe5-80c1-b5f555b0aeff" alt="image"></p>
<table>
<thead>
<tr>
<th></th>
<th>1일</th>
<th>2일</th>
<th>3일</th>
<th>4일</th>
<th>5일</th>
<th>6일</th>
<th>7일</th>
</tr>
</thead>
<tbody><tr>
<td>1일 상담 진행시</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>10</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1일 + 4일</td>
<td></td>
<td></td>
<td></td>
<td>10</td>
<td>30</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>1일 + 4일 + 5일</td>
<td></td>
<td></td>
<td></td>
<td>10</td>
<td>30</td>
<td>0</td>
<td>45</td>
</tr>
<tr>
<td>1일 + 5일</td>
<td></td>
<td></td>
<td></td>
<td>10</td>
<td>10</td>
<td>0</td>
<td>25</td>
</tr>
</tbody></table>
</li>
<li><p>1일 + 6일 상담 진행 시  상담이 끝나면 6 + 4일  = 10일이므로 해당 조합으로는 상담 진행이 불가하다</p>
</li>
<li><p>이런 방식으로 i번째 일의 상담을 진행할 경우, 현재 날짜+i일 이후부터 n일까지의 최댓 수익을 순차적으로 구하여 최종적으로 백준이가 얻을 수 있는 최대 수익을 구할 수 있다.</p>
</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">def solution():

  N = int(input())
  T = []
  P = []

  for _ in range(N):
    t, p = map(int, input().split())
    T.append(t)
    P.append(p)

  day = [0] * (N + 1)

  for i in range(N):
    for j in range(i + T[i], N + 1):
      if day[j] &lt; day[i] + P[i]:
        day[j] = day[i] + P[i]

  print(day[-1])

solution()</code></pre>
<h3 id="α">+α</h3>
<ul>
<li>DP 다시 연습하기</li>
<li>재귀적 + 반복적인 구조를 찾고 그것을 코드로 구현하는 것 연습하기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS SAA : EC2]]></title>
            <link>https://velog.io/@kim_sunnnny/AWS-SAA-EC2</link>
            <guid>https://velog.io/@kim_sunnnny/AWS-SAA-EC2</guid>
            <pubDate>Tue, 25 Jul 2023 08:11:56 GMT</pubDate>
            <description><![CDATA[<h2 id="ec2--elastic-compute-cloud--iaas">EC2 = Elastic Compute Cloud : IaaS</h2>
<ul>
<li><em>Virtual machines</em> = EC2</li>
<li><em>Virtual drives</em> = EBS (Elastic Block Store)</li>
<li><em>Distributing load</em> across machines = ELB (Elastic Load Balancer)</li>
<li><em>Auto-Scaling Group</em> = ASG </li>
</ul>
<p><br><br/></p>
<h4 id="sizing--configuration-options">Sizing / Configuration options</h4>
<ul>
<li><p><strong>OS</strong> : Linux / Windows / Mac</p>
</li>
<li><p><strong>CPU</strong> : Compute power &amp; cores</p>
</li>
<li><p><strong>RAM</strong></p>
</li>
<li><p>Storage space</p>
<ul>
<li>Network-Attached : <strong>EBS</strong>, <strong>EFS</strong> </li>
<li>HW : <strong>EC2 Instance Storage</strong></li>
</ul>
</li>
<li><p>Network card : public IP address, speed of card</p>
</li>
<li><p>Firewall rules : <strong>Security Group</strong></p>
</li>
<li><p>Bootstrap script : *<em>EC2 User Data : run with root user *</em></p>
<ul>
<li>run only once at instance&#39;s first start, to <strong>automate boot tasks</strong></li>
</ul>
</li>
<li><p>ssh connection</p>
<ul>
<li><code>.pem</code> : OpenSSH - mac, linux, Windows10</li>
<li><code>.ppk</code> : PuTTy - Windows 7,8</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="ec2-instance-types">EC2 instance types</h2>
<ul>
<li><p>aws의 작명규약
  ex) m5.2xlarge</p>
<ul>
<li>m : <em>instance class</em></li>
<li>5 : generation (continuously updated)</li>
<li>2xlarge : size within instance class ( more memory, ...)</li>
</ul>
</li>
<li><p>Instance Class</p>
<table>
<thead>
<tr>
<th>Class</th>
<th>purpose</th>
<th>use cases</th>
</tr>
</thead>
<tbody><tr>
<td><strong>General Purpose</strong></td>
<td>for diversity of workloads, good balance btwn compute, memory, networking)</td>
<td><br>•web servers<br/><br>• code repositories<br/></td>
</tr>
<tr>
<td><strong>Compute Optimized</strong></td>
<td>for compute-intensive tasks</td>
<td><br>• Batch processing workloads<br/><br> • Media transcoding<br/><br>• High performance web server<br/><br>• High performance computing (HPC)<br/><br>• Dedicated gaming servers<br/></td>
</tr>
<tr>
<td><strong>Memory Optimized</strong></td>
<td>for workloads that process large data sets in memory</td>
<td>• High performance, relational/non-relational databases<br/><br>• Distributed web scale cache stores<br/><br>• In-memory databases optimized for BI (Business Intelligence)<br/><br>• Applications performing real-time processing of big unstructured data <br/></td>
</tr>
<tr>
<td><strong>Storage Optimized</strong></td>
<td>for tasks that require high,sequential read/write access to large data sets on local storage</td>
<td>• High frequency OLTP systems<br/><br>  • Relational &amp; NoSQL DB <br/><br>  • Cache for in-memory DB (ex: Redis)<br/><br>  • Distributed file systems</td>
</tr>
<tr>
<td>Accelerated Computing</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td>HPC Optimized</td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<p>  <br><br/><br><br/></p>
<h2 id="ec2-instance-purchasing-options">EC2 Instance Purchasing options</h2>
<h3 id="1-on-demand">1. On-Demand</h3>
<ul>
<li><p>사용한 만큼 가격 발생 </p>
</li>
<li><p>Linux / Windows : 첫 1분 이후 초단위로 청구</p>
</li>
<li><p>다른 OS : 1시간 단위로 청구</p>
<pre><code>  **⇒ 가장 비싼 plan, 선불 요금 X 장기 렌탈 필요 x (X Commitment)**</code></pre></li>
<li><p>[추천] 짧고 방해받지 않으며, 예측 가능한 workload</p>
</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="2-reserved-instance">2. Reserved Instance</h3>
<ul>
<li><p>1 &amp; 3년 단위로 렌탈</p>
</li>
<li><p><strong>Reserved Instances</strong></p>
<ul>
<li><p>On-demand 대비 약 72% 할인가</p>
</li>
<li><p>Instance Type, Region, Tenancy, OS 등 명시하여 대여</p>
</li>
<li><p>요금결제 : 후불 / 부분 선불 / 전부 선불 (먼저 많이 지불할 수록 할인)</p>
</li>
<li><p>scope : Regional  / Zonal</p>
</li>
<li><p>Buy &amp; Sell in the reserved instance marketplace</p>
</li>
<li><p>[추천] : 안정적인 앱 사용 / 장기적인 workload</p>
</li>
</ul>
</li>
<li><p><strong>Convertible Reserved Instances</strong></p>
<ul>
<li>장기적인 workload + flexible한 instance type</li>
<li>변경 가능 : EC2 instance type, instance family, OS, scope, tenancy</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="3-savings-plans">3. Savings Plans</h3>
<ul>
<li><p>장기사용에 따른 할인</p>
</li>
<li><p>특정 사용량에 따라 약정<br>  (ex: 1년 혹은 3년 간 $10/시간)</p>
</li>
<li><p>약정 기간 이후 사용량은 On-Demand 가격으로 책정</p>
</li>
<li><p>고정 : instance family, Region</p>
</li>
<li><p>변경 가능 : </p>
<ul>
<li>Instance size   (ex:  m5.xlarge, m5.2xlarge)</li>
<li>OS (ex: Linux, Windows, …)</li>
<li>Tenancy (Host, Dedicated, Default)</li>
</ul>
<p><br><br/><br><br/></p>
</li>
</ul>
<h3 id="dedicated-host">*Dedicated Host</h3>
<ul>
<li><p><strong>물리적 서버 자체에 접근</strong> 가능, HW의 lovw level까지 가시성 확보 ⇒ 가장 비쌈!</p>
</li>
<li><p>compliance 요구사항 만족 가능</p>
</li>
<li><p>서버를 경계로 하는 자체 라이센스 사용 가능 
 (socket 단위, core 단위, VM 단위 라이센스 등)</p>
</li>
<li><p>instance placement 지정 가능</p>
</li>
<li><p>구매 옵션</p>
<ul>
<li>On-Demand : active한 host 초단위로 계산</li>
<li>Reserved  : 1년 혹은 3년 - 후불 / 부분 선불 / 전체 선불</li>
</ul>
</li>
<li><p>[추천]</p>
<ul>
<li>복잡한 라이센싱 모델을 가진 sw (BYOL license)</li>
<li>강한 regulatory/compliance가 요구되는 회사</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h3 id="dedicated-instances">*Dedicated Instances</h3>
<ul>
<li>Instances run on HW dedicated to you</li>
<li>같은 계정 내 다른 instance와 HW 공유 가능</li>
<li>instance placement 지정 불가 </li>
</ul>
<p><br><br/></p>
<h3 id="capacity-reservations">*Capacity Reservations</h3>
<ul>
<li>특정 AZ 내 &quot;On-Demand&quot; instances capacity를 예약 (for any duration)</li>
<li>필요할 때 언제든 EC2 capacity에 접근 가능</li>
<li>time commitment 필요 없음 (언제든 생성/중단)</li>
<li>instance 작동여부와 상관없이 On-Demand rate으로 과금</li>
<li>Regional Reserved Instance와 Savings Plans과 함꼐 사용 시 할인</li>
<li>[추천] 단기간, 특정 AZ에 있어야하는 안정적인 workload</li>
</ul>
<p><br><br/></p>
<h3 id="-spot-instances">* Spot Instances</h3>
<ul>
<li><p>중요한 작업이나 DB의 목적의 workload로는 부적합</p>
</li>
<li><p>아주 싸다~! 단기간 workload로 좋음</p>
</li>
<li><p><strong>Max spot price (budget) 지정</strong></p>
</li>
<li><p>hourly spot price는 수요와 공급에 의해 변동</p>
<ul>
<li>current spot price가 max spot price보다 낮으면 instance 보유</li>
<li>current spot price가 더 비싸지면 2분 간 유예 시간 동안 instance 상태를 결정해야 함<ul>
<li><strong>stop instance</strong> : hourly spot price가 max spot price 보다 내려가면 다시 instance 시작</li>
<li><strong>terminate instance</strong> :  아예 종료</li>
<li><strong>Spot Block **: (2021년 7월 기준 신규 고객에게는 Spot Block 서비스 제공 x, 시험에는 나올 수 있음!)</strong><ul>
<li>시간을 정해서 지정한 용량을 유지해주는 옵션 - 해당 시간 동안은 Reserved Instance보다 유리</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>[추천] failure에 강한 작업</p>
<ul>
<li>ex) Batch Jobs / Data analysis / Image Processing / Any distributed workloads</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h4 id="spot-instance-request-과금없이-종료하는-법">Spot Instance Request 과금없이 종료하는 법!</h4>
<ul>
<li><p>Spot Instance request 종류 : One-time / persistent</p>
<img src = https://velog.velcdn.com/images/kim_sunnnny/post/907d9971-a13c-4dd6-8f7d-5f56ac2ecabd/image.png width=90%>
</li>
<li><p>Spot Instance 종료시키기 when persistent request</p>
<ol>
<li>request 상태가 <code>open</code> / <code>active</code> / <code>disabled</code> 중 하나 
(<code>failed</code>, <code>cancelled</code>, <code>closed</code>는 종료 불가)</li>
<li>Cancel spot instance</li>
<li>동작 중인 instance를 별도로 직접 terminate
(request 취소 ≠ instance 종료)</li>
</ol>
</li>
</ul>
<p><br><br/><br><br/>    </p>
<h3 id="spot-fleets">Spot Fleets</h3>
<ul>
<li><p>최저가에 Spot Instance를 request하는 것을 자동화</p>
<ol>
<li><p><strong>Budget, capacity, launch pool</strong> 정의</p>
<ul>
<li>launch pool : Instance type, OS, AZ 지정</li>
</ul>
</li>
<li><p>가격 제한과 Target capacity를 만족하도록 instance를 구축</p>
</li>
<li><p>budget 한도에 도달했을 때 instance 구축 중단
<br><br/></p>
</li>
</ol>
</li>
<li><p>Spot instance 구축 위한 구성 전략</p>
<ol>
<li>최저가 : pool 내 가장 최저가 
(가격 최적화, 단기 workload용)</li>
<li>diversified : 모든 pool에 걸쳐 분산 구축
(good availability, 장기 workload용)</li>
<li>capacity Optimized : 필요한 instance들을 수용할 수 있는 적합한 capacity를 가진 pool 선택</li>
</ol>
</li>
</ul>
<p><br><br/><br><br/>    </p>
<h2 id="security-groups">Security Groups</h2>
<ul>
<li>방화벽 역할 : EC2를 오고 가는 트래픽 관리</li>
<li><strong><code>Allow</code></strong> 규칙 정의<ul>
<li>관리 대상 : <ul>
<li>Access to Ports</li>
<li>Authorized IP ranges - IPv4, IPv6</li>
<li>Inbound network    (default : all blocked)</li>
<li>Outbound network  (default : all authorized)</li>
</ul>
</li>
</ul>
</li>
<li>IP 참조 가능</li>
<li>여러 Instance들에 attach 가능</li>
<li>region/VPC 내에서만 유효</li>
<li>SSH 접근 관련 SG 별도로 관리하는 것이 유리함</li>
</ul>
<p><br><br/><br><br/>    </p>
<h3 id="classic-ports"><strong>Classic Ports</strong></h3>
<table>
<thead>
<tr>
<th>22</th>
<th>SSH    (Secure Shell)</th>
<th>log into a Linux instance</th>
</tr>
</thead>
<tbody><tr>
<td>21</td>
<td>FTP     (File Transfer Protocol)</td>
<td>upload files into a file share</td>
</tr>
<tr>
<td>22</td>
<td>SFTP   (Secure FTP)</td>
<td>upload files using SSH</td>
</tr>
<tr>
<td>80</td>
<td>HTTP</td>
<td>access unsecured websites</td>
</tr>
<tr>
<td>443</td>
<td>HTTPS</td>
<td>access secured websited</td>
</tr>
<tr>
<td>3389</td>
<td>RDP    (Remote Desktop Protocol)</td>
<td>lgo into a Windows instance</td>
</tr>
</tbody></table>
<p><br><br/><br><br/> </p>
<h3 id="ssh--secure-shell">SSH  (Secure SHell)</h3>
<table>
<thead>
<tr>
<th></th>
<th>SSH</th>
<th>Putty</th>
<th>EC2 Instance Connect (web browser @ AWS)</th>
</tr>
</thead>
<tbody><tr>
<td>Mac</td>
<td>O</td>
<td></td>
<td>O</td>
</tr>
<tr>
<td>Linux</td>
<td>O</td>
<td></td>
<td>O</td>
</tr>
<tr>
<td>Windows &lt; 10</td>
<td></td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>Windows ≥ 10</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
</tbody></table>
<p><br><br/><br><br/> </p>
<h2 id="-ip---ipv4--ipv6-private-ip--public-ip">※ IP - IPv4 / IPv6, Private IP / Public IP</h2>
<ul>
<li><p><strong>IPv4</strong> : 32bit , still most common format   (강좌에서 주로 다룰 주소)</p>
<ul>
<li>[0-255].[0-255].[0-255].[0-255]</li>
</ul>
</li>
<li><p>IPv6 : 128bit, 고정header, 암호화 기능 기본</p>
</li>
<li><p>Public IP</p>
<ul>
<li>can be identified on the internet</li>
<li>must be unique</li>
<li>can be geo-located easily</li>
</ul>
</li>
<li><p>Private IP</p>
<ul>
<li>can only be identified on a private network</li>
<li>unique accross the private network</li>
<li>2 diff private networks can have same private IPs</li>
<li>machines connect to internet by NAT + internet gateway (as a proxy)</li>
<li>only a certain range of IPs can be used as private IP</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/> </p>
<h3 id="elastic-ip">Elastic IP</h3>
<p>: fixed public IPv4 for your instance (only 1 instance)</p>
<ul>
<li><p>with Elastic IP address, you can mask the failure of an instance/software by rapidly remapping the address to another instance in your account</p>
</li>
<li><p>5개 제한 있지만, AWS에 늘려달라고 요청할 수 있음</p>
</li>
<li><p>AVOID ELASTIC IP : often reflect poor architectural decision</p>
<p>  ⇒ use a random public IP and register a DNS name to it</p>
<p>  ⇒ or use a Load Balancer &amp; don’t use a public IP</p>
</li>
</ul>
<p><br><br/><br><br/> </p>
<h3 id="ec2-placement-groups">EC2 Placement Groups</h3>
<ul>
<li>control over the EC2 Instances are going to be placed within the AWS infrastructure</li>
<li>when creating a placement group, specify 1 of 3 strategies for the group :</li>
</ul>
<pre><code>1. **Cluster**    

    - grouped together in a low-latency HW setup within the same rack within a single AZ
    - Use Case :
        - Big Data job that needs to complete fast
        - Application that needs extremely **low latency, high network** throughput

     **⨁**   high performance  : 10 Gbps bandwidth btwn instances

     **Θ**    high  risk  : If the rack fails, all instances fails at the same time
    &lt;br&gt;&lt;br/&gt;
2. **Spread**   

   - spreads instances across underlying HW    ( Instances on diff physical HW )
    - Use Case :
        - applications that needs **high availability**
        - critical application where instances must be isolated from failure from one another

     **⨁**   span across AZs  , Reduced risk of simultaneous failure

     **Θ**   limited to **max 7 instances per AZ per placement group**   
           (ex: 1 region w/ 3 AZ ⇒ 7 instances in each AZ ⇒ total 21 instances in that region) 
    &lt;br&gt;&lt;br/
3. **Partition**  : spread instances across many diff partitions within an AZ
 (rely on diff sets of racks of HW, EC2 ) 
  - EC2 instances get access to partition information as meta data
  - spread groups are just single individual instances spread through different racks or AZs, partition placement group : made of several instances on each partition)
  - Use Cases : HDFS, HBase, Cassandra, Kafka

     **⨁**   can span across multiple AZs in the same region

     **⨁**   Scales to 100s of EC2 instances per group     

     **Θ**   partition failure can affect many EC2, but won’t affect other partitions</code></pre><p><br><br/><br><br/> </p>
<h3 id="elastic-network-interfaces-eni">Elastic Network Interfaces (ENI)</h3>
<ul>
<li><p>logical component in a VPV that represents <strong>virtual network card 
⇒ gives EC2 access to the network               (</strong>EC2 밖에서도 사용됨)</p>
</li>
<li><p>ENI can have following attributes:</p>
<ul>
<li><strong>Primary private IPv4 , 1개 이상의 secondary IPv4</strong></li>
<li><strong>1 Elastic IP (IPv4) per private IPv4</strong></li>
<li><strong>1 public IPv4</strong></li>
<li><strong>1개 이상의 security groups</strong></li>
<li><strong>Mac 주소</strong></li>
</ul>
</li>
<li><p>bound to specific AZ</p>
</li>
<li><p><strong>Failover</strong>를 위해 ENI를 독립적으로 생성하여 다른 instance로 옮길 수 있음 (“attach them on the fly” )</p>
<ul>
<li><strong>Failover</strong> : the redirection of traffic from a primary system to a secondary system
(백업 목적) 원래 등록되어있던 instance에 문제 발생 시 private IP가 다른 instance로 이동함</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/> </p>
<h3 id="ec2-hibernate">EC2 Hibernate</h3>
<ul>
<li>Stop &amp; Terminate<ul>
<li>Stop      :  data on EBS (disk) is <em>kept intact(not injured)</em> in the next start</li>
<li>Terminate  :  if you set root volume to be destroyed w/ instance, it will be destroyed<pre><code>               (if not set to be destroyed, it will be kept)</code></pre></li>
</ul>
</li>
<li>Start<ul>
<li>1st start : OS boots up  ⇒  User Data script is run</li>
<li>following starts : OS boots up  ⇒  applications start  /  caches get warmed up
⇒ takes time</li>
</ul>
</li>
</ul>
<ul>
<li><strong>EC2 Hibernate</strong><ul>
<li>write in-memory (RAM) state to a file in the <em>root EBS volume</em>  ⇒  RAM state preserved!</li>
</ul>
</li>
</ul>
<pre><code>    - *when launching instance*
    - *root EBS volume must be encrypted*

- Use cases:
    - long-running processing
    - saving RAM state   (RAM ≤ 150GB)
    - Services that take up time to initialize

- good to know,,,,,, :
    - Hibernate supports many kinds of instance families, instance RAM Sizes, Instance Sizes, all kinds of instances(on-demand, reserved, spot)
    - Root Volume must be a large &amp; encrypted EBS
    - can not be hibernated more than 60 days</code></pre><p><br><br/><br><br/> </p>
<h2 id="-ec2-instance-storage-section--ebs-ec2-instance-store-efs">※ EC2 Instance Storage Section : EBS, EC2 Instance store, EFS</h2>
<h3 id="ebs-volume--elastic-block-store">EBS Volume  (Elastic Block Store)</h3>
<p>:  <strong>network drive</strong> you can attach to your instance while they run    </p>
<ul>
<li><p>uses network to communicate the instance  ⇒  latency might occur</p>
</li>
<li><p>can be detached from an instance and attached to another one quickly</p>
</li>
<li><p>allows your instance to <strong>persist data even after termination</strong></p>
</li>
<li><p>some EBS <strong>can be “multi-attached”</strong> to more than 1 instances<br>(mostly mounted at 1 instance at a time)</p>
</li>
<li><p><strong>bound to AZ</strong>   ⇒   use <strong>snapshots</strong>  to move volume across AZ</p>
</li>
<li><p><strong>provisioned capacity</strong>  : size in GBs and IOPS (<em>I/O Ops Per Second - 저장장치의 속도 측정 단위)</em>
⇒ EBS Volume의 용량을 provision할 때 명시해야 하지만 나중에 늘릴 수 있음</p>
</li>
<li><p>Free tier : 30 GB of free EBS storage of type General Purpose(SSD) or Magnetic per month
<br><br/><br><br/> </p>
<h3 id="ebs--delete-on-termination-attribute"><strong>EBS : Delete on Termination</strong> attribute</h3>
</li>
<li><p>controls the EBS behavior when an EC2 instance terminates, by  <strong>AWS console / AWS CLI</strong></p>
</li>
<li><p><code>Delete on Termination</code> by Default :</p>
<ul>
<li><strong>root EBS volume : enabled</strong>    (deleted on termination)</li>
<li><strong>any other attached EBS volume : disabled</strong>  (not deleted on termination)</li>
</ul>
</li>
<li><p>Use case : <strong>preserve root volume when instance is terminated (exam scenario)</strong></p>
</li>
</ul>
<p><br><br/><br><br/> </p>
<h2 id="ebs-snapshots">EBS Snapshots</h2>
<ul>
<li><p>backup (snapshot) of EBS volume at a point in time</p>
</li>
<li><p>X necessary to detach volume to do snapshot, but recommended</p>
</li>
<li><p>Can copy snapshots across AZ or Region</p>
</li>
<li><p>Features :</p>
</li>
</ul>
<pre><code>1. EBS **Snapshot Archive** 
    - move snapshot to “archive tier”  :  75% cheaper
    - takes 24~72 hours for restoring   (restore :  *to bring back existence*)

1. **Recycle Bin** for EBS Snapshots
    - setup rules to retain deleted snapshots so you can recover after accidental deletion
    - specify retention from 1 day ~ 1 year    (retention :  ******************************the ability to keep and hold)******************************


1. **Fast Snapshot Restore (FSR)**
    - Force full initialization of snapshot to have x latency on the first use (cost $$$)
        - good when snapshot is very big and need a quick instance initialization</code></pre><p><br><br/><br><br/><br><br/> </p>
<h2 id="ebs-volume-types">EBS Volume Types</h2>
<ul>
<li>SSD (Solid State Drive)  vs  HDD (Hard Disk Drive)</li>
</ul>
<ul>
<li><p>Types - depending on Size / Throughput / IOPS</p>
<ol>
<li><p><strong>st1  (Low cost HDD)</strong> :  for frequently accessed, throughput-intensive workloads
<br><br/></p>
</li>
<li><p><strong>s1 (Lowest cost HDD)*</strong> : for less frequently accessed  workloads  </p>
<ul>
<li><p>HDD EBS features</p>
<p>⇒ <strong>only gp2/gp3, io1/io2 can be used as boot volumes</strong>
<br><br/></p>
</li>
</ul>
</li>
<li><p><strong>gp2 / gp3 (SSD)</strong>   : <strong>General Purpose</strong> SSD volume</p>
<ul>
<li>cost effective &amp; low latency  ⇒  balance price &amp; performance</li>
<li>1 GiB ~ 16Tib</li>
<li>ex) system boot volumes, virtual desktops, Development and test env’ts</li>
<li>gp3 (newer ver.)<ul>
<li>Baseline of 3,000 IOPS and throughput of 125 MiB/s</li>
<li>Can increase IOPS up to 16,000 and throughput up to 1000 MiB/s independently</li>
</ul>
</li>
<li>gp2 (older ver.)<ul>
<li>Small gp2 volumes can burst IOPS to 3,000</li>
<li>Size of the volume and IOPS are linked, max IOPS is 16,000</li>
<li>3 IOPS per GB, means at 5,334 GB we are at the max IOPS
<br><br/></li>
</ul>
</li>
</ul>
</li>
<li><p><strong>io1 / io2 (SSD)  : Provisioned IOPS -</strong> Highest-performance SSD volume</p>
<ul>
<li>for mission-critical low-latency or high-throughput workloads<ul>
<li>Critical business applications with sustained IOPS performance</li>
<li>applications that need more than 16,000 IOPS</li>
</ul>
</li>
<li>Great for databases workloads (sensitive to storage perf and consistency)</li>
<li>Supports <strong>EBS Multi-attach</strong></li>
<li><strong>io1/io2</strong> (4 GiB - 16 TiB)<ul>
<li>Max PIOPS: 64,000 for Nitro EC2 instances &amp; 32,000 for other</li>
<li>Can increase PIOPS independently from storage size</li>
<li>io2 have more durability and more IOPS per GiB (at the same price as io1)</li>
</ul>
</li>
<li><strong>io2 Block Express</strong> (4 GiB – 64 TiB):<ul>
<li>Sub-millisecond latency</li>
<li>Max PIOPS: 256,000 with an IOPS:GiB ratio of 1,000:1</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<p><br><br/></p>
<h3 id="ebs-multi-attach----io1io2-family"><strong>EBS Multi-Attach</strong>  - io1/io2 family</h3>
<ul>
<li><p>Attach the <strong>same EBS volume</strong> to <strong>multiple EC2 instances</strong> <strong>in the same AZ</strong></p>
<p>  ⇒ Each instance has full Read &amp; Write permissions to high-performance volume</p>
</li>
<li><p><strong>Up to 16 EC2 Instances at a time</strong></p>
</li>
<li><p>Must use a file system that’s cluster-aware (not XFS, EX4, etc…)</p>
</li>
<li><p>Use Cases:</p>
<ul>
<li>Achieve higher application availability in clustered Linux applications (ex: Teradata)</li>
<li>Applications must manage concurrent write operations</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/> </p>
<h2 id="ebs-encryption">EBS Encryption</h2>
<ul>
<li>list of encryption in an encrypted EBS volume :<ul>
<li>Data at rest inside the volume</li>
<li>All data flow btwn the instance and the volume</li>
<li>All snapshots</li>
<li>All volumes created from the snapshot</li>
</ul>
</li>
<li>Encryption and decryption are handled transparently (user has nothing to do)</li>
<li>minimal impact on latency</li>
<li><strong>EBS Encryption leverages keys from KMS (AES-256)</strong></li>
<li>Copying an unencrypted snapshot allows encryption</li>
</ul>
<p><br><br/><br><br/> </p>
<h2 id="encrypt-an-unencrypted-ebs-volume">Encrypt an unencrypted EBS volume</h2>
<ol>
<li><strong>Create EBS Snapshot</strong> of the volume</li>
<li>Using copy, <strong>encrypt the EBS snapshot</strong></li>
<li><strong>create new EBS volume</strong> from the encrypted snapshot <strong>⇒ encrypted snapshot</strong></li>
<li><strong>attach encrypted volume</strong> to original instance</li>
</ol>
<p><br><br/><br><br/> <br><br/><br><br/> </p>
<h2 id="ami--amazon-machine-image">AMI = Amazon Machine Image</h2>
<p>: customization of an EC2 instance - </p>
<ul>
<li><p>add your own software, configuration, OS, monitoring, …</p>
</li>
<li><p>all software is pre-packaged   ⇒  <strong>faster boot / faster configuration time</strong></p>
</li>
<li><p>built for specific region   &amp;   can be copied across regions</p>
</li>
<li><p>types</p>
<ol>
<li>Public AMI   :   AWS provided</li>
<li>Your own AMI   :   you make and maintain them yourself</li>
<li>AWS Marketplace AMI  :  AMI someone else made (and potentially sells)</li>
</ol>
</li>
<li><p>Creating  AMI   from an EC2 instance</p>
<ol>
<li>Start an EC2 instance and customize it</li>
<li>stop the instance for data integrity</li>
<li>Build an AMI  :  this will also create EBS snapshots</li>
<li>Launch instance from AMI</li>
</ol>
</li>
</ul>
<p><br><br/></p>
<h2 id="ec2-instance-store---high-performance-hw-attached-volume">EC2 Instance Store :  high-performance HW attached volume</h2>
<ul>
<li>EBS volumes : network drives → “limited performance”</li>
<li>Features :<ul>
<li>Better I/O performance</li>
<li>lose storage if stopped (ephemeral - <strong>lasting for a very short time)</strong></li>
<li>good for <strong>buffer / cache / scratch data / temporary content</strong></li>
<li>risk of data loss if HW fails</li>
<li>Backups / Replication are your responsiblity</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="amazon-efs--elastic-file-system">Amazon EFS : Elastic File System</h2>
<p>: Managed NFS (Network File System) that can be mounted on many EC2</p>
<ul>
<li><p>work w/ EC2 instance in multi-AZ</p>
</li>
<li><p>Highly available, scalable, pay per use, expensive (3 * gp2)</p>
</li>
<li><p><code>NFSv4.1</code> protocol</p>
</li>
<li><p>use Security to control access to EFS</p>
</li>
<li><p><strong>compatible w/ Linux based AMI  (<del>Windows</del>)</strong></p>
</li>
<li><p>Encryption at rest using KMS</p>
</li>
<li><p>standard file system on Linux - POSIX - has standard file API</p>
</li>
<li><p>X plan capacity in advance - File system scales automatically</p>
</li>
<li><p><strong>Scale</strong></p>
<ul>
<li>1000s of concurrent NFS clients, 10 GB+ /s throughput</li>
<li>Grow to Petabyte-scale network file system, automatically</li>
</ul>
</li>
<li><p>Use cases :</p>
<ul>
<li>Content management</li>
<li>web serving</li>
<li>data sharing</li>
<li>wordpress
<br><br/><h3 id="efs----storage-classes-at-efs-creation-time">EFS -  Storage Classes at EFS creation time</h3>
</li>
</ul>
</li>
<li><p><strong>Availability and Durability</strong></p>
<ol>
<li>Standard (구 Regional)  :  Multi-AZ<ul>
<li>great for prod</li>
</ul>
</li>
<li>One Zone : One AZ<ul>
<li>great for development</li>
<li>backup enabled by default</li>
<li>compatible with IA (EFS One Zone-IA)</li>
<li>Over 90% in cost s뜐avings</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Storage Classes -</strong> Tiers   :  move files to a different tier after a few days   (lifecycle management feature)</p>
<ol>
<li><p><strong>Standard</strong> Tier : for frequently accessed files</p>
</li>
<li><p><strong>EFS-IA</strong>  (Infrequent Access Tier) : cost to retrieve files, lower price to store</p>
<ul>
<li><p>Must use Lifecycle Policy to enable EFS-IA</p>
<p>  <br><br/></p>
</li>
</ul>
</li>
</ol>
</li>
<li><p><strong>Performance Modes</strong></p>
<ol>
<li><strong>General Purpose</strong> (default)  :  latency-sensitive use cases (web server, CMS, etc…)</li>
<li><strong>Max I/O</strong> – higher latency, throughput, highly parallel (big data, media processing)
<br><br/></li>
</ol>
</li>
<li><p><strong>Throughput Mode</strong></p>
<ol>
<li><strong>Bursting</strong> :   growing in throughputs as we have more storage </li>
<li><strong>Provisioned</strong>  : set your throughput regardless of storage size </li>
<li><strong>Elastic</strong>  :  automatically scales throughput up or down based on your workloads<ul>
<li>Used for unpredictable workloads
<br><br/><br><br/><h3 id="ebs-vs-efs">EBS vs EFS</h3>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<table>
<thead>
<tr>
<th></th>
<th>EBS</th>
<th>EFS</th>
</tr>
</thead>
<tbody><tr>
<td>Attachment &amp; Availability</td>
<td>1 instance  (Except multi-attach io1/io2 Bound to AZ</td>
<td>Mounting 100s of instances across AZ</td>
</tr>
<tr>
<td>IO</td>
<td><br>gp2 : IO increases if disk size increases<br/><br>io1 : can increase IO independently</td>
<td>- share website files (WordPress)<br/><br>- only for Linux Instances (POSIX)</td>
</tr>
<tr>
<td>Feature</td>
<td><strong>Migrate EBS across AZ</strong> :<br/><br>take snapshot<br/><br>→restore snapshot to another AZ<br/><br><strong>EBS backups use IO</strong><br/><br>⇒ shouldn’t run backups while your application is handling a lot of traffic)<br/><br><strong>Termination</strong> : <br/><br>Root EBS Volumes of instances get terminated by default if the EC2 instance gets terminated.</td>
<td>- EFS has a higher price point than EBS<br/><br>- Can leverage EFS-IA for cost savings</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OS] process and thread]]></title>
            <link>https://velog.io/@kim_sunnnny/OS-process-and-thread</link>
            <guid>https://velog.io/@kim_sunnnny/OS-process-and-thread</guid>
            <pubDate>Wed, 19 Jul 2023 12:11:59 GMT</pubDate>
            <description><![CDATA[<h1 id="1-프로세스와-쓰레드">1. 프로세스와 쓰레드</h1>
<h2 id="program-vs-process">Program vs Process</h2>
<table>
<thead>
<tr>
<th>Program</th>
<th>Process</th>
</tr>
</thead>
<tbody><tr>
<td>저장장치 (HDD, SSD)에 저장된 명령문의 집합체  (App/ Application,  .exe )</td>
<td>실행 중인 프로그램 = 하드디스크에 저장된 프로그램이 메모리 (RAM)에 올라갔을 때</td>
</tr>
<tr>
<td>“수동적 존재”  =  하드디스크/저장장치만 사용</td>
<td><br>“능동적 존재 “  = <br/><br>  - 메모리 사용 <br/><br>- OS의 CPU 스케줄링 알고리즘에 따라 CPU도 사용<br/><br>- 필요에 따라 입출력 작업<br/></td>
</tr>
</tbody></table>
<img src=https://velog.velcdn.com/images/kim_sunnnny/post/1caaeb97-cd93-4131-8de8-d9c37ca4062b/image.png width=70%>


<ul>
<li><strong>Code</strong>  :  자신을 실행하는 코드 저장</li>
<li><strong>Data</strong>  :  전역 변수와 정적(static)변수 저장</li>
<li><strong>Stack</strong>  :  지역 변수와 함수 호출 시 필요한 정보 (매개변수와 돌아갈 주소) 저장</li>
<li><strong>Heap</strong>  :  동적 메모리 할당 시 사용<ul>
<li>ex) c 언어  -  <code>malloc()</code> <code>free()</code></li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h2 id="코드-→-메모리-→-프로세스-과정">코드 → 메모리 → 프로세스 과정</h2>
<ul>
<li><p>code</p>
<pre><code class="language-c">  #include &lt;stdio.h&gt;
  void main()
  {
      int a = 1;
      int b = 2;
      int c = a + b
      }</code></pre>
<ul>
<li><p><code>.c</code> file  →  컴파일</p>
<ol>
<li><p>c언어는 compile언어이므로 컴파일이 되어야 실행가능</p>
</li>
<li><p>전처리기  :  매크로로 정의한 숫자를 치환, 필요한 파일 로딩 
⇒ 파일 확장자 : <code>.i</code></p>
</li>
<li><p>컴파일러 : compile  - C언어 ⇒ assembly language (명령어 : 기계어 = 1: 1) 
⇒ 파일 확장자 : <code>.s</code></p>
</li>
<li><p>Assembler  :  Assembly language ⇒ machine language(0,1)
⇒ 파일 확장자 : <code>.o</code></p>
</li>
<li><p>Linker  :  linking - 여러 library나 다른 source code들 연결</p>
<p> ⇒ 파일 확장자 : <code>.exe</code></p>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<pre><code>- `exe.` 파일 실행 → 하드 디스크에 있는 해당 파일이 메모리에 올라감  ⇒  “**Process”**</code></pre><p><br><br/><br><br/></p>
<h2 id="cpu-관점-os의-전략에-따른-process의-관리">CPU 관점) OS의 전략에 따른 Process의 관리</h2>
<ul>
<li><p>CPU : 0,1로 이루어진 Machine language만 실행  ⇒ Assembly Language로 고려해보기  (for 가독성)</p>
<ol>
<li>CPU 내의 <strong>Control Unit</strong>이 숫자 5와 7을 <strong>memory</strong>에 저장</li>
<li>방금 메모리에 저장한 값을 <code>**edx</code> , <code>eax</code> Register**로 가져옴</li>
<li><strong>Control Unit</strong>이 “<strong>Register</strong>에 저장된 5와 7을 더하라”는 명령을 하면</li>
<li><strong>ALU</strong>(산술논리연산장치)가 연산을 한 뒤, <strong><code>eax</code> Register</strong>에 저장</li>
<li><strong>Control Unit</strong>이 <strong><code>eax</code> Register</strong>에 저장된 12를 가져와 <strong>memory</strong>에 저장
<br><br/><br><br/></li>
</ol>
</li>
</ul>
<h2 id="uni-programming--vs--multi-programming--vs-multi-processing">Uni-Programming  vs  Multi-Programming  vs Multi-Processing</h2>
<table>
<thead>
<tr>
<th>Uni-Programming</th>
<th>Multi-Programming</th>
<th>Multi-Processing</th>
</tr>
</thead>
<tbody><tr>
<td>1 process on memory</td>
<td>multiple process on memory</td>
<td>CPU managing multiple processes</td>
</tr>
<tr>
<td>pov  of  memory</td>
<td>pov  of  memory</td>
<td>pov  of  CPU</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Time sharing process</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- <strong>Swapping</strong>  :   memory에 있는 data를 다른 저장장치로 보내고 다른 저장장치에서 memory올리는 것</td>
<td></td>
<td></td>
</tr>
<tr>
<td><br><br/><br><br/></td>
<td></td>
<td></td>
</tr>
<tr>
<td>## PCB  (Process Control Block)</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<ul>
<li><p>Process가 만들어지면 OS는 해당 process의 정보를 갖고 있는 <strong>PCB</strong>를 만들고 저장</p>
</li>
<li><p>Linked List 형태로 저장    (각 데이터가 다음 데이터를 연결)</p>
<ul>
<li><p>Process 종료 시 Linked List에서 해당 Process의 PCB 제거</p>
</li>
<li><p>이전의 PCB가 방금 제거된 PCB를 가리키도록 수정하여 Linked List 구조 유지</p>
<img src=https://velog.velcdn.com/images/kim_sunnnny/post/05224762-70c4-4cf5-8990-2ba9993a4053/image.png width=70%>
출처 : https://yoongrammer.tistory.com/52

<table>
<thead>
<tr>
<th>PCB</th>
<th>저장 데이터</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Pointer</strong></td>
<td><br>- 부모와 자식 process에 대한 pointer, 할당된 자원에 대한 pointer 등 <br/><br> - process의 한 상태에서 다른 상태로 전환될 때 저장하는 pointer 보유  ( for 효율적인 접근)<br/></td>
</tr>
<tr>
<td><strong>Process State</strong></td>
<td><br>현재 process의 5가지 상태  (생성, 준비, 실행, 대기, 완료)<br/></td>
</tr>
<tr>
<td><strong>PID (Process ID)</strong></td>
<td>Process를 식별하기 위한 숫자</td>
</tr>
<tr>
<td><strong>Program Counter</strong></td>
<td><br>다음에 실행될 명령어의 주소를 포함하는 Program Counter <br/><br>시분할 처리로 여러 프로세스를 짧은 시간씩 번갈아 실행하기 때문에, 해당 프로세스로 다시 전환됐을 때 실행할 명렁어를 알아둬야 함)<br/></td>
</tr>
<tr>
<td><strong>Registers</strong></td>
<td><br>process가 실행될 때 사용했던 Register 값들이 저장<br/><br>(Program Counter와 마찬가지로 CPU를 뺏기고 다시 시작할 때 이전에 사용하던 값을 복구하기 위한 용도) <br/></td>
</tr>
<tr>
<td><strong>Memory Limits</strong></td>
<td>process가 memory에 있는 위치 정보, memory 침범을 막기 위한 경계 register값 등</td>
</tr>
<tr>
<td><strong>Open File Lists</strong></td>
<td>=CPU  스케쥴링 정보 : 우선순위, 최종 실행시간, CPU 점유시간 등이 저장</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="process-state">Process State</h2>
<ul>
<li><p><strong>CPU의  시분할 시스템</strong>   ⇒   process의 5가지 상태</p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/cd63e2e6-7700-47f8-8842-0997254853c6/image.png width=70%>



</li>
</ul>
<pre><code>출처 : https://medium.com/@sohailk1999/five-state-process-model-6e83d7428c8c</code></pre><table>
<thead>
<tr>
<th>status</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>생성/ New</strong></td>
<td>PCB 생성 후 memory에 program 적재를 요쳥한 상태  (적재 승인 후 준비 상태)</td>
</tr>
<tr>
<td><strong>준비  / Ready</strong></td>
<td>CPU를 사용하기 위해 기다리는 상태</td>
</tr>
<tr>
<td><strong>실행 / Running</strong></td>
<td><br>- 준비 상태의 process가 cpu scheduler에 의해 CPU 할당 받아 실행 중인 상태<br/><br>- 실행 상태의 process의 수 == CPU 개수<br/><br>- 부여된 시간 초과시 CPU scheduler가 할당된 CPU 탈환 → 다시 준비 상태<br/></td>
</tr>
<tr>
<td><strong>대기 / Waiting</strong></td>
<td><br>- process가 입출력 요청 시 완료될 때까지 기다리는 상태<br/><br>    - 입출력 작업 완료 시 대기 상태에 있던 process에게 CPU 할당 기회 부여</td>
</tr>
<tr>
<td><strong>완료 / Terminated</strong></td>
<td><br>- Process가 종료된 상태<br/><br> - Process가 사용했던 data  &amp; PCB  메모리에서 제거<br/></td>
</tr>
<tr>
<td><br><br/><br><br/></td>
<td></td>
</tr>
</tbody></table>
<h2 id="context-switching">Context Switching</h2>
<ul>
<li><p>Process를 실행하는 중에 다른 process를 실행하기 위해 실행 중인 process의 상태를 저장하고 다른 process의 상태 값으로 교체하는 작업</p>
</li>
<li><p>cause of Context switching</p>
<ol>
<li>CPU 점유시간 초과</li>
<li>I/O 요청</li>
<li>다른 종류의 Interrupt가 있을 때 발생</li>
</ol>
</li>
<li><p>if)  <strong>Process A  →  Process B</strong></p>
<ul>
<li><p>PCB의 내용 변경!  : <code>Process state</code>,  <code>Program Counter</code>, <code>Registers</code> , <code>Memory Limits</code></p>
<ul>
<li><p>실행중인 process의 작업 내용을 PCB에 저장</p>
<ul>
<li>현재 CPU의 register값 등을 PCB A에 저장</li>
</ul>
</li>
<li><p>실행될 process의 PCB 값으로 CPU가 다시 세팅</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="process-생성과-종료">Process 생성과 종료</h2>
<ul>
<li><strong>0번 Process 생성 과정</strong>   :  <strong>OS 부팅 후 딱 1번 실행</strong><ol>
<li><code>.exe</code> 파일 실행</li>
<li>OS가 해당 프로그램의 Code 영역과 Data 영역을 memory에 load, 빈 Stack &amp; 빈 Heap을 만들어 공간 확보</li>
<li>해당 Process를 관리하기 위한 PCB를 만들어 값을 초기화</li>
</ol>
</li>
</ul>
<p><strong>⇒ 나머지 프로세스는 새로 생성하지 않고 0번 process를 복사해서 사용  :  <code>fork()</code> 함수 이용</strong></p>
<ul>
<li><p>∵ process 복사하여 이용하는 것이 생성하는 것보다 빠름</p>
</li>
<li><p>0번 process를 복사 ⇒ 부모 process(0번)  &amp; 자식 process</p>
<ul>
<li><p>부모 process의 code영역, data 영역, stack 영역, PCB의 내용 전부 복사</p>
</li>
<li><p>복사한 0번 process와 다르게, 원하는대로 작동하도록  <strong><strong><strong><strong>**</strong></strong></strong></strong><code>exec()</code>)함수 이용**</p>
<p>  ⇒ 부모를 복사한 자식 프로세스의 코드와 데이터 영역을 원하는 값으로 덮어씀</p>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>부모 process &amp; 자식 process</p>
<pre><code class="language-c">
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;

  int main()
  {
      int pid;
      pid = fork();    // 자식 process에게는 0, 부모 process에게는 0이 아닌 값 반환

    // 이 후 2개의 process는 cpu scheduling에 따라 실행, 
    //어느 것이 먼저 실행될지는 OS의 결정에 따름

      if (pid == 0) // 자식 process
      {
          // InternetBrowser 프로그램에서 코드와 데이터 영역을 가져와 자식 process를 덮어씀
          execlp(&quot;InternetBrowser&quot;, &quot;0&quot;, NULL); 
          exit(0); // InternetBrowser 프로그램 실행에 실패하면 exit()함수 호출 후 종료
      }
      else // 부모 process
      {
          wait(NULL);// 자식 process에게서 exit()신호를 받으면 자식 process를 완전히 종료 시킴
          printf(&quot;인터넷 브라우저 닫힘&quot;); 
          exit(0);
      }
  }</code></pre>
<ul>
<li><p><strong><code>execlp()</code></strong>  : 인자로 들어온 프로그램에서 코드와 데이터 영역을 가져와 자식 process를 덮어씀 (from parent’s copied data to the program’s data)</p>
<ul>
<li>실패 시에만 -1 반환하고 성공하면 반환 x</li>
<li>위 예시의 경우 인터넷 브라우저를 실행하면 exit()은 실행하지 않고 실패시에만 exit()함수가 호출</li>
</ul>
</li>
<li><p><strong><code>wait()</code></strong>  : context switching을 거쳐 부모 process에게 cpu가 할당되어도 자식 process에게서 exit()신호가 올 때까지 다른 코드를 실행하지 않고 기다리는 system 함수</p>
</li>
<li><p><strong><code>exit()</code> :</strong> 자식 process가 부모 process에게 정상종료를 알리는 함수</p>
<ul>
<li>부모 process는 자식 process의 exit status를 읽고 자식 process 정리</li>
</ul>
</li>
<li><p><strong>zombie process</strong>  :  자식 process가 정상적으로 종료되지 못해 memory에 계속 살아있는 상태</p>
<ul>
<li>부모 process가 자식 process보다 먼저 종료</li>
<li>자식 process가 비정상적으로 종료돼, <code>exit()</code> 신호를 주지 못해서 <code>exit status</code>를 읽지 못함</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h2 id="thread">Thread</h2>
<ul>
<li><p><strong>Process</strong> : OS가 작업을 처리하는 단위  ⇒ Process 내 Thread</p>
</li>
<li><p><strong>Thread</strong> : Process가 할당받은 자원을 이용하는 실행 단위 / Process의 특정한 수행 경로 / Process 내 실행되는 여러 흐름의 단위</p>
<ul>
<li><p><strong>Main thread</strong> : Process 내 존재하는 최소 1개 thread</p>
</li>
<li><p><strong>독자적인 Stack memory</strong> &amp; <strong>register</strong> 보유</p>
</li>
<li><p><strong>Code, Data, Heap 공유</strong></p>
</li>
<li><p><strong>Process 내의 주소공간/자원들 공유</strong></p>
</li>
<li><p><strong>TCB (Thread Control Block)</strong> 로 관리</p>
</li>
<li><p>1 thread가 process 자원을 변경하면 다른 sibling thread(이웃 thread)도 그 변경 결과를 즉시 볼 수 있다</p>
</li>
<li><p>memory를 공유하기 때문에 <strong>동기화</strong> , <strong>deadlock</strong> 등의 문제 발생 가능</p>
</li>
<li><p>관련 library : <code>POSIX Pthreads</code>, <code>Windows threads</code>, <code>Java threads</code></p>
<table>
<thead>
<tr>
<th></th>
<th>Process</th>
<th>Thread</th>
</tr>
</thead>
<tbody><tr>
<td>정의</td>
<td>실행 중인 program</td>
<td>Process의 실행 단위</td>
</tr>
<tr>
<td>생성/종료시간</td>
<td>많은 시간 소요</td>
<td>적은 시간 소요</td>
</tr>
<tr>
<td>Context Switching</td>
<td>많은 시간 소요</td>
<td>적은 시간 소요</td>
</tr>
<tr>
<td>상호작용</td>
<td>IPC 사용</td>
<td>공유 memory 사용</td>
</tr>
<tr>
<td>자원소모</td>
<td>많음</td>
<td>적음</td>
</tr>
<tr>
<td>메모리 내 독립성</td>
<td>각각 독립적</td>
<td></td>
</tr>
<tr>
<td>안정성 굳!</td>
<td>프로세스 내 stack/register 독립적, 이외 공유</td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/><br><br/><br><br/></p>
<h3 id="multi-processing-vs-multi-threading">multi-processing vs multi-threading</h3>
<table>
<thead>
<tr>
<th></th>
<th>Multi - Processing</th>
<th>Multi - Threading</th>
</tr>
</thead>
<tbody><tr>
<td>정의</td>
<td>응용 프로그램 1 = 여러 개의 process</td>
<td>응용 프로그램 1 = 여러 개의 thread</td>
</tr>
<tr>
<td>장점</td>
<td><br>process에 문제가 발생하면 그것의 자식 proecss만 죽음 <br/><br>(다른 영향 x)</td>
<td>1. System 자원 소모 감소 (자원 효율성 증대)<br/><br>(process를 생성하여 자원 할당하는 system call이 줄어들어 자원을 효율적으로 관리할 수 있음)<br/><br>2. System 처리량 증가  (처리 비용 감소)<br/><br>   ( Thread 간 data 교환이 간단해지고 system 자원 소모 감소,  Thread 사이 작업량이 작아 Context switching이 빠름)<br/><br>3. Program 응답 시간 단축 <br/><br> (Process 내 stack 이외 모든 memory를 공유하므로 통신의 부담 적음)<br/></td>
</tr>
<tr>
<td>단점</td>
<td><br> 1. Context Switching 과정에서 cache memory 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드 발생<br/><br>  -  process 사이에 공유하는 memory가 없음 → Context Switching발생 시 cache에 있는 모든 data를 모두 reset하고 다시 cache 정보를 불러와야 함<br/><br>2. Process 간 IPC 통신할 때, process 간 변수 공유 불가<br/><br>-  process가 각각 독립된 memory 영역을 할당받았기 때문</td>
<td><br>1. 주의 깊은 설계 필요<br/><br>2. 까다로운 디버깅<br/><br>3. single process system 은 큰 효과 X<br/><br>4. process 밖에서 thread 각각 제어 불가<br/><br>5. 자원 공유의 문제 발생  (동기화 문제)<br/><br>6. Thread 1개의 문제가 전체 Process에 영향</td>
</tr>
</tbody></table>
<p><br><br/><br><br/></p>
<h3 id="user-level-thread----kernel-level-thread--httpswwwcrocuscokr1404">User Level Thread  &amp;  Kernel Level Thread  (<a href="https://www.crocus.co.kr/1404">https://www.crocus.co.kr/1404</a>)</h3>
<ul>
<li>스케줄러가 컨텍스트 스위칭 하는 단위는 커널 스레드이고 컨텍스트 스위칭을 당하며 저장되는 정보가 PCB임을 알고 있어야한다.</li>
<li><strong>User Level Thread</strong>  :  programming 과정에서 Thread를 code에 적는 것</li>
<li><strong>Kernel Level Thread</strong>  :  OS가 관리하는 thread들</li>
</ul>
<p><br><br/><br><br/><br><br/></p>
<h1 id="주제와-관련한-cs-질문">주제와 관련한 cs 질문</h1>
<ul>
<li><p>context switching과 시분할 시스템에 대해서 설명하시오.</p>
<ul>
<li><p>시분할 시스템은, 입출력 처리가 끝날 때까지 대기해야 했던 cpu의 사용률을 높일 수 있도록 고안된 시스템</p>
<ul>
<li>메모리에 적재된 여러 프로그램들을 짧은 시간씩 할당하여 처리함으로써, cpu가 대기했어야하는 시간에 다른 작업을 하게 하여 cpu 사용률을 높임</li>
</ul>
</li>
<li><p>Process를 실행하는 중에 다른 process를 실행하기 위해 실행 중인 process의 상태를 저장하고 다른 process의 상태 값으로 교체하는 작업을 context switching이라고 함</p>
<ul>
<li>실행중인 process의 작업 내용을 (현재 CPU의 register값 등) 실행 중인 process의 PCB에 저장하고, 실행될 process의 PCB 값으로 CPU가 다시 세팅됨
<br><br/><br><br/></li>
</ul>
</li>
</ul>
</li>
<li><p>좀비 프로세스가 생기는 이유에 대해서 설명하시오</p>
<ul>
<li><p>부모 프로세스와 자식 프로세스 관계의 프로세스는 부모 프로세스가 자식 프로세스를 온전히 종료시켜야한다.</p>
</li>
<li><p>자식 프로세스가 성공적으로 종료될 경우 exit()신호를 부모 프로세스에 보냄으로써 부모 프로세스가 자식 프로세스를 종료시킬 수 있는데, 만약 부모 프로세스가 자식 프로세스보다 먼저 종료되거나, 자식 프로세스가 비정상적으로 종료되어 exit()신호를 보내지 못할 경우 메모리에 계속 남아있게 되면서 좀비 프로세스가 생성되게 된다</p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS SAA : Region & AZ, IAM & AWS CLI]]></title>
            <link>https://velog.io/@kim_sunnnny/AWS-SAA-Region-AZ-IAM-AWS-CLI</link>
            <guid>https://velog.io/@kim_sunnnny/AWS-SAA-Region-AZ-IAM-AWS-CLI</guid>
            <pubDate>Tue, 18 Jul 2023 08:23:36 GMT</pubDate>
            <description><![CDATA[<h2 id="-region--cluster-of-data-centers">※ Region : Cluster of data centers</h2>
<ul>
<li>when choosing region, you should consider<ol>
<li>Compliance w/ data governance &amp; legal requirements </li>
<li>Proximity to customer - ↓ latency</li>
<li>Services&#39; availability within a region</li>
<li>Pricing</li>
</ol>
</li>
</ul>
<p><br><br/></p>
<h2 id="-az-available-zone--1개-이상의-discrete-center--w--redundant-power-networking-connectivity">※ AZ (Available Zone) : 1개 이상의 discrete center  w/  Redundant power, networking, connectivity</h2>
<ul>
<li><p>같은 region 내 AZ 간에는 high bandwidth + ultra-low latency networking</p>
</li>
<li><p>Region마다 평균 3개의 AZ (min 3, max 6)</p>
</li>
<li><p>Points of Presence (사용자에게 low latency로 전달하는 것에 도움 주는 service)</p>
<ul>
<li>Edge</li>
<li>Regional Cache</li>
</ul>
</li>
</ul>
<ul>
<li>Global service ↮ regional service<ul>
<li>일부 service는 global service로서 region/AZ 선택을 필요로 하지 않음 </li>
<li>ex) IAM, ...</li>
</ul>
</li>
</ul>
<p> <br><br/><br><br/></p>
<h2 id="-iam--identity-and-access-management">※ IAM : Identity and Access Management</h2>
<ul>
<li><strong>Root account</strong> : default 로 생성, 함부로 사용/공유되지 않도록 주의</li>
<li>AWS login option : root user / IAM user<ul>
<li>IAM user :<ul>
<li>Account ID/alias</li>
<li>account user name</li>
<li>password</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="iam-users--조직-내-구성원">IAM Users : 조직 내 구성원</h3>
<ul>
<li>Account ID : 고유값, 번호로만 구성
⇒ Account Alias : 닉네임, 로그인 시 사용 가능</li>
</ul>
<p><br><br/></p>
<h3 id="iam-group---user만-등록-가능-x-contain-other-groups">IAM <strong>Group :  User만 등록 가능 (X contain other groups)</strong></h3>
<p><br><br/></p>
<h3 id="iam-roles--specific-permissions-with-credentials-that-are-valid-for-short-durations"><em>IAM Roles</em> : specific permissions with credentials that are valid for short durations</h3>
<ul>
<li>일반적으로 특정 AWS resource에 권한이 없는 users/applications/services에 권한을 대리 (delegate access)<ul>
<li>perform actions on your behalf</li>
</ul>
</li>
<li>password나 access key를 요구하는 standard long-term credential이 없음<ul>
<li>(user와 유사하지만 특정 사람과  associated될 필요x)</li>
</ul>
</li>
<li>provides you w/ temporary security credentials for your role session</li>
<li>common roles:<ul>
<li>EC2 Instance Roles</li>
<li>Lambda Functions Roles</li>
<li>Roles for CloudFormation</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h3 id="iam-policy">IAM Policy</h3>
<ul>
<li><p><strong>JSON 문서로 user/group의 permission 정의 ⇒ “Grant/apply the least privilege principle” (필요한 권한만 최소한으로 부여해라)</strong></p>
</li>
<li><p>Inheritance : 특정 policy가 부여된 group에 할당/추가되면 해당 policy를 상속받음</p>
<ul>
<li>group에 속해있지 않은 user는 해당 user에 할당된 policy만 보유</li>
<li>속해있던 group에서 배제될 경우 해당 group의 policy 속 권한들을 상실하게 됨</li>
</ul>
</li>
</ul>
<ul>
<li>Policy Structure<ol>
<li><strong>Version</strong> : policy language version - “2012-10-17”</li>
<li><strong>Id</strong> (optional) : 고유값</li>
<li><strong>Statement</strong> : 1개 이상<ul>
<li><strong>Sid</strong> (optional) : statement의 id</li>
<li><strong>Effect</strong> : “Allow” / “Deny”</li>
<li><strong>Principle</strong> : 해당 policy가 적용될 account/user/role의 id</li>
<li><strong>Action</strong> : 해당 policy가 허용/금지할 action의 list</li>
</ul>
</li>
</ol>
<ul>
<li><code>*</code> : all actions<ul>
<li><strong>Resource</strong> : 위 action들이 적용될 resource의 list</li>
</ul>
</li>
<li><code>*</code> : all resources<ul>
<li><strong>Condition</strong> (optional) : 해당 policy가 적용될 조건들
<br><br/></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="iam-defense-mechanism--">IAM Defense mechanism -</h3>
<ol>
<li>Password Policy<ul>
<li>비밀번호가 강력할수록 보안 강화</li>
<li>AWS에서 원하는 password policy를 직접 정할 수 있다 :<ul>
<li>password 최소 길이 정하기</li>
<li>특정 문자 포함시키기 (대문자 / 소문자 / 숫자 / 특수문자)</li>
<li>모든 IAM user들의 비밀번호 변경 허용하기</li>
<li>일정 시간 후 user들의 비밀번호 변경 요청하기 (password expiration)</li>
<li>비밀번호 재사용 방지</li>
</ul>
</li>
</ul>
</li>
</ol>
<ol start="2">
<li><p>Multi Factor Authentication (MFA)</p>
<ul>
<li>Users 가 보유한 권한으로 설정값들을 변경하거나 resource를 삭제할 수 있음</li>
<li>Root account와 IAM user를 보호하기 위한 MFA</li>
<li>MFA = <em>password you know</em> + <em>security device you own</em></li>
<li>최대장점 : <strong>Even if a password is stolen or hacked, the account is not compromised</strong></li>
<li><strong>options</strong><ol>
<li><strong>Virtual MFA device</strong> : support for multiple tokens on a single device</li>
</ol>
<ul>
<li>Google Authenticator (phone only)        </li>
<li>Authy (multi-device)<ol start="2">
<li><strong>U2F Security Key (Universal 2nd Factor)</strong> : support for multiple root and IAM users using a single security key</li>
</ol>
</li>
<li>YubiKey by Yubico (3rd party)</li>
</ul>
</li>
</ul>
<ol>
<li><strong>Hardware Key Fob MFA device</strong><ul>
<li>Gemalto (3rd party)</li>
<li>for AWS GovCloud (US) -  SurePassID (3rd party)</li>
</ul>
</li>
</ol>
</li>
</ol>
<p><br><br/><br><br/></p>
<h2 id="-aws-cli--sdk-access-keys">※ AWS CLI , SDK, Access Keys</h2>
<ul>
<li><strong>AWS에 접속하는 법 3가지</strong><ol>
<li>AWS Management Console  : password + MFA</li>
<li><strong>AWS CLI</strong> : <strong>access keys</strong></li>
<li><strong>AWS SDK</strong> (Software Developer Kit) : for code - <strong>access keys</strong></li>
</ol>
</li>
</ul>
<h3 id="access-keys">Access Keys</h3>
<ul>
<li>AWS Console에서 발급, Users마다 관리, 공유 하지마!!!</li>
<li>Access Key ID ≌ username</li>
<li>Secret Access Key ≌ password<ul>
<li>※ never put Access Key in your EC2 instance’s <code>aws configure</code> ⇒ Use IAM Roles</li>
</ul>
</li>
</ul>
<h3 id="aws-cli">AWS CLI</h3>
<ul>
<li>Command line shell에서 AWS 서비스들과 interact할 수 있도록 하는 tool</li>
<li>direct access to public API of AWS service</li>
<li>develop scripts to manage resources</li>
</ul>
<h3 id="aws-sdk">AWS SDK</h3>
<ul>
<li>software development kit</li>
<li>language-specific APIs (set of libraries) = different SDKs for different programming languages</li>
<li>프로그램적으로 access/manage AWS services - embedded within application</li>
<li>supports</li>
</ul>
<h3 id="aws-cloudshell---다른-terminal-옵션-for-aws-cli">AWS CloudShell - 다른 terminal 옵션 for AWS CLI</h3>
<ul>
<li><p>not yet available in all regions</p>
</li>
<li><p>사용 중인 user의 credentials와 region을 기준으로 응답을 반환</p>
</li>
<li><p>linux server 처럼 파일 생성하면 cloudshell restart해도 유지됨 (download/upload file 도 가능)</p>
</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="iam-security-tools---iam-credentials-report--access-advisor">IAM Security Tools - IAM Credentials Report , Access Advisor</h3>
<ul>
<li><p><strong>IAM Credentials report  (account level)</strong></p>
<pre><code>: account의 user들과 그들의 credential 정보들에 대한 report</code></pre></li>
</ul>
<ul>
<li><p><strong>IAM Access Advisor  (user-level)</strong></p>
<pre><code>: user에 허가된 service permission들과 각 service들의 최근 접속 시간</code></pre><p>  <br><br/><br><br/></p>
</li>
</ul>
<h3 id="iam-가이드라인-best-practices">IAM 가이드라인, best practices</h3>
<ul>
<li>AWS account setup 목적 외에 root 계정 사용하지 않기</li>
<li>1 물리적 사용자 = 1 AWS user</li>
<li>user를 group에 할당, group에 permissions 할당</li>
<li>강한 password policy 정하기</li>
<li>MFA를 사용하고 강조해라</li>
<li>AWS service에 대한 권한 부여는 Roles를 만들어 사용하라</li>
<li>CLI/SDK와 같은 programmatic access에 Access Key를 사용하라</li>
<li>IAM Credentials Report로 account의 권한들을 관리해라 (audit permissions ~`)</li>
<li>Never share IAM users &amp; Access keys</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 2468 안전영역 (복습)]]></title>
            <link>https://velog.io/@kim_sunnnny/BOJ-2468-%EC%95%88%EC%A0%84%EC%98%81%EC%97%AD</link>
            <guid>https://velog.io/@kim_sunnnny/BOJ-2468-%EC%95%88%EC%A0%84%EC%98%81%EC%97%AD</guid>
            <pubDate>Mon, 17 Jul 2023 08:13:02 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://www.acmicpc.net/problem/2468">문제</a></h3>
<ul>
<li>지역의 높이 정보에 따라 비가 왔을 때 <strong>물에 잠기지 않는 “안전영역”의 최대 개수는?</strong><ul>
<li>잠기지 않은 부분들의 최대 영역이 안전지대</li>
</ul>
</li>
</ul>
<pre><code>    - 높이가 4이하가 모두 물에 잠겼을 경우 ⇒ 5개

      &lt;img src =https://velog.velcdn.com/images/kim_sunnnny/post/6120a331-e3f5-4227-af0f-2feab1e2cb36/image.png width=50%&gt;



    - 높이가 6이하인 지점이 모두 잠겼을 경우 ⇒ 4개

        &lt;img src=https://velog.velcdn.com/images/kim_sunnnny/post/cb1cb37f-4bb9-4a3c-af34-e02447bdbe42/image.png width=50%&gt;</code></pre><ul>
<li><p>입력</p>
<pre><code>  1| 행/열의개수</code></pre></li>
</ul>
<pre><code>이후 |  높이 정보</code></pre><ul>
<li>출력 <pre><code>안전한 영역의 최대 개수</code></pre>  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/77ce2f19-b0cf-4235-9246-46dba36ab365/image.png width=70% >

</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>BFS! - queue를 활용해서 안전지대의 개수를 구한다</p>
</li>
<li><p>최대 개수를 구해야하므로, 주어진 높이들 중 최대 높이를 구한 뒤 
0부터 최대높이-1까지 강수량을 설정하여 각 강수량에 따른 안전지대 개수를 구하고, 그 중 최댓값을 찾아 반환한다
<br><br/><br><br/></p>
<h3 id="3-코드">3. 코드</h3>
</li>
<li><p>복습 코드 → 함수, 지역변수로 실행시간 줄이기</p>
<pre><code class="language-python">  import sys
  from collections import deque

  input = sys.stdin.readline

  def bfs(i, j, heights, visited, N, rain):
      dr = [1, -1, 0, 0]
      dc = [0, 0, 1, -1]

      visited[i][j] = True

      queue = deque()
      queue.append((i,j))

      while queue:
          r, c = queue.popleft()
          for i in range(4):
              nr = r + dr[i]
              nc = c + dc[i]

              if 0 &lt;= nr &lt; N and 0 &lt;= nc &lt; N and not visited[nr][nc] and heights[nr][nc] &gt; rain:
                  visited[nr][nc] = True
                  queue.append((nr,nc))

  def solution():
      N = int(input())
      heights = []
      Max_height = 0
      for _ in range(N):
          row = list(map(int, input().split()))
          heights.append(row)
          Max_height = max(Max_height, max(row))

      safe_zone = []

      for rain in range(1,Max_height):
          visited = [ [False for _ in range(N)] for _ in range(N) ]
          zones = 0
          for i in range(N):
              for j in range(N):
                  if not visited[i][j] and heights[i][j] &gt; rain:
                      bfs(i,j, heights, visited, N, rain)
                      zones += 1
          safe_zone.append(zones)

      if not safe_zone:
          print(1)
      else:
          print(max(safe_zone))
      return

  solution()</code></pre>
</li>
</ul>
<p><br><br/></p>
<ul>
<li><p>BFS</p>
<pre><code class="language-python">  from collections import deque

  n = int(input())

  graph = [ [] for _ in range(n)]
  MAX = 0

  for i in range(n):
      graph[i] = list( map( int, input().split()) )
      MAX = max( max(graph[i]), MAX )

  dx = [ -1, 1, 0, 0 ]
  dy = [ 0, 0, -1, 1 ]

  def bfs(x,y,h):
      queue = deque()
      queue.append((x,y))
      visited[x][y] = 1

      while queue:
          x_, y_ = queue.popleft()
          for i in range(4):
              nx = x_ + dx[i]
              ny = y_ + dy[i]
              if 0 &lt;= nx &lt; n and 0 &lt;= ny &lt; n and not visited[nx][ny] and graph[nx][ny] &gt; h:
                  queue.append( (nx, ny) )
                  visited[nx][ny] = 1

  result = 0

  for i in range(MAX):
      count = 0
      visited = [ [0] * n for _ in range(n) ]
      for j in range(n):
          for k in range(n):
              if graph[j][k] &gt; i and visited[j][k] == 0:
                  bfs(j, k, i)
                  count += 1

      result = max(result, count)

  print(result)</code></pre>
</li>
</ul>
<p><br><br/><br><br/></p>
<h3 id="α">+α</h3>
<ul>
<li><p>DFS</p>
<pre><code class="language-python">  import sys
  sys.setrecursionlimit(100000)

  n = int(input())

  graph = [ [] for _ in range(n)]
  MAX = 0

  for i in range(n):
      graph[i] = list( map ( int, input().split() ) )
      MAX = max( max(graph[i]), MAX )

  dx = [ -1, 1, 0, 0 ]
  dy = [ 0, 0, -1, 1 ]

  def dfs(x,y,h):
      visited[x][y] = 1

      for i in range(4):
          nx = x + dx[i]
          ny = y + dy[i]
          if 0 &lt;= nx &lt; n and 0 &lt;= ny &lt; n and not visited[nx][ny] and graph[nx][ny] &gt; h:
              dfs(nx,ny,h)

  result = 0

  for i in range(MAX):
      count = 0
      visited = [ [0] * n for _ in range(n) ]
      for j in range(n):
          for k in range(n):
              if graph[j][k] &gt; i and visited[j][k] == 0:
                  dfs(j, k, i)
                  count += 1

      result = max(result, count)

  print(result)</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PRG] 튜플]]></title>
            <link>https://velog.io/@kim_sunnnny/PRG-%ED%8A%9C%ED%94%8C</link>
            <guid>https://velog.io/@kim_sunnnny/PRG-%ED%8A%9C%ED%94%8C</guid>
            <pubDate>Tue, 11 Jul 2023 10:43:02 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://school.programmers.co.kr/learn/courses/30/lessons/64065">문제</a></h3>
<ul>
<li><p><code>tuple</code>  :  셀 수 있는 수량의 순서있는 열거 / 순서를 따르는 요소들의 모음</p>
<ul>
<li><p><code>n-tuple</code>  :  n개의 요소를 가진 tuple</p>
</li>
<li><p>중복 원소 가능</p>
</li>
<li><p>순서 있음</p>
</li>
<li><p>원소 개수 유한</p>
</li>
<li><p><em>⇒ 특정 튜플을 표현하는 문자열 s가 표현하는 튜플을 배열에 담아 반환*</em></p>
</li>
<li><p>제한 사항</p>
<ul>
<li>s의 길이는 5 이상 1,000,000 이하입니다.</li>
<li>s는 숫자와 &#39;{&#39;, &#39;}&#39;, &#39;,&#39; 로만 이루어져 있습니다.</li>
<li>숫자가 0으로 시작하는 경우는 없습니다.</li>
<li>s는 항상 중복되는 원소가 없는 튜플을 올바르게 표현하고 있습니다.</li>
<li>s가 표현하는 튜플의 원소는 1 이상 100,000 이하인 자연수입니다.</li>
<li>return 하는 배열의 길이가 1 이상 500 이하인 경우만 입력으로 주어집니다.</li>
</ul>
</li>
<li><p>예제 입력</p>
</li>
</ul>
</li>
</ul>
<pre><code>    | s | result |
    | --- | --- |
    | &quot;{{2},{2,1},{2,1,3},{2,1,3,4}}&quot; | [2, 1, 3, 4] |
    | &quot;{{1,2,3},{2,1},{1,2,4,3},{2}}&quot; | [2, 1, 3, 4] |
    | &quot;{{20,111},{111}}&quot; | [111, 20] |
    | &quot;{{123}}&quot; | [123] |
    | &quot;{{4,2,3},{3},{2,3,4,1},{2,3}}&quot; | [3, 2, 4, 1] |</code></pre><p><br><br/></p>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li>파싱 이용하기<ul>
<li>주어진 문자열 s에서 숫자로 이루어진 부분 집합들을 뽑아낸 후,</li>
<li>길이가 1인 것부터  (== 튜플의 가장 첫번째 원소) 부분집합의 길이를 기준으로 튜플의 다음 원소들을 추가
<br><br/></li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">def solution(s):
    s = s[2:-2]
    ls = [ list(map(int,x.split(&#39;,&#39;))) for x in s.split(&#39;},{&#39;) ]
    ls = sorted(ls, key = lambda x: len(x))

    answer = []

    for e in ls:
        for num in e:
            if num not in answer:
                answer.append(num)

    return answer</code></pre>
<img src =https://velog.velcdn.com/images/kim_sunnnny/post/076126de-2c91-4a56-acf8-b7900b1448b4/image.png width=30%>


<h3 id="α">+α</h3>
<ul>
<li><p>파싱 외에 정규표현식을 사용해보자 
  ⇒ 역시…  찾는 origin이 길어지면 드라마틱하게 시간을 줄일 수 있다..!</p>
<pre><code class="language-python">  import re
  from collections import Counter
  def solution(s):    
      answer = []

      nums = dict(Counter(re.findall(&#39;\d+&#39;, s)))

      answer = list(map(int, sorted(nums.keys(), key= lambda x : nums[x], reverse=True)))

      return answer</code></pre>
</li>
</ul>
<img src=https://velog.velcdn.com/images/kim_sunnnny/post/25683b5d-0cc9-41ce-abdd-fbe06ae694a0/image.png width=30%>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ]16928 뱀과 사다리 게임]]></title>
            <link>https://velog.io/@kim_sunnnny/BOJ16928-%EB%B1%80%EA%B3%BC-%EC%82%AC%EB%8B%A4%EB%A6%AC-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@kim_sunnnny/BOJ16928-%EB%B1%80%EA%B3%BC-%EC%82%AC%EB%8B%A4%EB%A6%AC-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Mon, 10 Jul 2023 14:28:43 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://www.acmicpc.net/problem/16928">문제</a></h3>
<ul>
<li>뱀과 사다리 게임 ⇒ 도착점에 도착할 수 있는 최소 횟수?</li>
<li>게임판 10 x 10, 1 ~100까지 수 순서대로 적혀있음<ul>
<li>ex) i번 칸 ⇒ 주사위 4 나옴 ⇒ i+4칸</li>
</ul>
</li>
</ul>
<ul>
<li><p>1번 ⇒ 100번 칸으로 이동</p>
<ul>
<li>주사위 굴린 결과가 100 넘어가면 이동 불가</li>
<li>도착한 칸이 사다리면 사다리 타고 위로 (원래 있던 칸보다 크게)</li>
<li>도착한 칸이 뱀이라면  뱀 타고 아래로 (원래 있던 칸보다 적게)</li>
</ul>
</li>
<li><p>1번 칸과 100번 칸은 뱀과 사다리의 시작 또는 끝이 아님</p>
</li>
<li><p>모든 칸은 최대 하나의 사다리 또는 뱀   →   동시에 두 가지를 모두 가지고 있는 경우는 없다.</p>
</li>
<li><p>항상 100번 칸에 도착할 수 있는 입력만 주어진다.</p>
</li>
</ul>
<p>   <strong>⇒ 게임판의 상태가 주어졌을 때, 100번 칸에 도착하기 위해 주사위를 굴려야 하는 횟수의 최솟값?</strong>
<br><br/></p>
<ul>
<li><p>입력 : 
<code>| 사다리의 수 **N**  뱀의 수 **M**       (1 ≤ N ≤ 15, 1 ≤ M ≤ 15)</code>
<code>| N개 줄 : 사다리의 정보 x, y (x &lt; y)  (x번 칸에 도착하면 y번 칸으로 이동)</code>
<code>| M개 줄 : 뱀의 정보 u, y  (u &gt; v)    (u번 칸에 도착하면 v번 칸으로 이동)</code></p>
</li>
<li><p>출력 : <code>100번 칸에 도착하기 위해 주사위를 굴려야 하는 최소 회수</code></p>
</li>
<li><p>예제 입력 </p>
  <img src=https://velog.velcdn.com/images/kim_sunnnny/post/058e2593-24bf-45f2-afd5-f5cc27094291/image.png width = "50%" height = "50%">


</li>
</ul>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li>BFS<ul>
<li>현재 위치 cur과 주사위를 돌린 횟수 rolls를 queue 에 담아서 이용하며, queue에서 원소를 하나씩 빼서 목적지 100인지 확인하거나 주사위를 굴린다</li>
<li>만약 현재 위치가 목적지 100이라면 여태 주사위를 굴린 횟수 rolls를 출력하고 while문 탈출한다.</li>
<li>아직 목적지에 도달하지 않아, 주사위를 굴린다면 1~6 사이의 숫자를 현재 위치에 더해서,</li>
<li>다음 위치가 100 이하의 숫자라면<ul>
<li>해당 위치가 사다리에 해당된다면 or 뱀에 해당된다면 다음 위치를 다시 갱신</li>
<li>방문하지 않은 위치라면 주사위를 1번 굴렸으므로, queue에 해당 위치와 굴린횟수+1을 추가하고, 방문 처리
<br><br/><br><br/></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">import sys
from collections import deque

def solution():

    input = sys.stdin.readline

    N, M = map(int, input().split())
    ladders = dict()
    snakes = dict()

    for _ in range(N):
        x, y = map(int, input().split())
        ladders[x] = y

    for _ in range(M):
        u, v = map(int, input().split())
        snakes[u] = v

    visited = [False] * 101

    rolls = 0

    #BFS
    cur = 1
    queue = deque()
    queue.append((cur, rolls))
    visited[1] = True

    while queue:
        cur, rolls = queue.popleft()
        if cur == 100:
            print(rolls)
            break

        for dice in range(1,7):
            next = cur + dice

            if next &lt;= 100:
                if next in ladders.keys():
                    next = ladders[next]
                elif next in snakes.keys():
                    next = snakes[next]
                if not visited[next] :
                    queue.append((next, rolls+1))
                    visited[next] = True

solution()</code></pre>
<p><br><br/></p>
<h3 id="α">+α</h3>
<ul>
<li>1차 시도<ul>
<li>문제에 나온 대로 10*10 board를 만들고 번호에 따라 i행 j열을 계산하고,,, 문제를 너무 복잡하게 생각해서 삽질을 많이 함…</li>
<li><ul>
<li>사다리를 타고 이동한 위치가 뱀의 시작 위치일 수도 있다고 문제를 해석해서 ( 단순히 시작 위치만 겹치지 않는 것으로 해석해서) 주사위를 굴린 후 말의 위치를 계산해내는 것만으로도 별도의 함수를 제작해야한다고 생각했다…^__^</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>BFS/DFS 문제 오랜만에 풀었더니 감 다까먹었다.. 열공하자,,</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[OS] OS intro]]></title>
            <link>https://velog.io/@kim_sunnnny/OS-OS-intro-%EC%9E%91%EC%84%B1-%EC%A4%91</link>
            <guid>https://velog.io/@kim_sunnnny/OS-OS-intro-%EC%9E%91%EC%84%B1-%EC%A4%91</guid>
            <pubDate>Sat, 08 Jul 2023 10:38:33 GMT</pubDate>
            <description><![CDATA[<h2 id="운영체제-개요">운영체제 개요</h2>
<ul>
<li>운영체제 없는 컴퓨터?<ul>
<li>동작 가능, but 처음 설계한대로만 동작 ⇒ 다른 기능 추가 불가,  X 유연</li>
</ul>
</li>
</ul>
<h3 id="운영체제가-하는-일">운영체제가 하는 일</h3>
<ol>
<li><p><strong>프로세스 관리</strong> </p>
<ul>
<li>여러 프로세스들을 관리 : 프로세스의 CPU 독차지 방지</li>
<li>사용자 상호작용이 이루어지는 프로세스 외에는 백그라운드로 실행</li>
</ul>
</li>
<li><p><strong>메모리 관리</strong></p>
<ul>
<li>모든 프로그램은 메모리에 올려서 관리하며 동작</li>
</ul>
</li>
</ol>
<ol start="3">
<li><p><strong>하드웨어 관리</strong></p>
<ul>
<li><p>사용자의 하드웨어에 대한 직접적인 접근 방지</p>
</li>
<li><p>하드디스크의 특정 영역에 다른 중요한 데이터 보호</p>
</li>
<li><p><em>⇒*</em> 운영체제의 판단 하에, 적절한 위치에 사용자의 데이터 저장</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><p><strong>파일 시스템 관리</strong></p>
<ul>
<li>하드디스크에 파일들을 효율적으로 저장 &amp; 관리</li>
</ul>
</li>
</ol>
<p><br><br/>
<br><br/></p>
<h2 id="운영체제의-역사">운영체제의 역사</h2>
<ul>
<li><p><strong>1940</strong> : ENIAC</p>
<ul>
<li><p>스위치와 배선 작업  →  HW의 비용 ↑↑</p>
<p>⇒ CPU를 최대한 많이 사용할 수 있는 법?</p>
</li>
</ul>
</li>
<li><p><strong>1950초</strong> : IC (직접 회로)  - 진공관과 전선으로 만들어진 논리 회로를 아주 작은 크기로 만듧</p>
<ul>
<li><p><em>programmer</em> : 펀치카드로 프로그램 작성</p>
</li>
<li><p><em>operator</em> : 컴퓨터에 카드를 넣고 결과가 나오면 프로그래머에게 전달</p>
<p>  <br><br/></p>
</li>
</ul>
</li>
</ul>
<h3 id="1950중후반--single-stream-batch-system"><strong>1950중후반 : Single Stream Batch system</strong></h3>
<ul>
<li><em>programmer</em>가 펀치카드를 여러 개 제작
→ operator가 여러 개를 한 번에 컴퓨터에 전달 
→ 컴퓨터는 여러 개의 프로그램을 순서대로 실행해서 결과를 한번에 확인할 수 있도록 개발</li>
</ul>
<ul>
<li><p><strong>한계 : CPU와 입출력을 분리하여도, 입력을 받기 위한 대기 시간에는 CPU의 사용률이 떨어진다</strong></p>
<ul>
<li><p><strong>I/O Device Controller</strong> (입출력 관리자)</p>
<ul>
<li>입출력 시 CPU를 사용할 수 없는 점을 개선</li>
<li>입출력 작업이 끝나면 CPU에게 interrupt 신호를 발신  ⇒  interrupt 신호 받은 CPU가 처리할 수 있도록</li>
</ul>
</li>
<li><p>CPU와 입출력의 분리했지만 still 1 more problem</p>
<ul>
<li><p><em>입출력에도 CPU를 기다려야 하는 작업 있음</em></p>
<ul>
<li><p>ex) 입력을 처리하는 작업일 때 입력이 전부 완료되어야만 처리할 수 있음</p>
<p>⇒ <strong>이렇게 기다리는 시간에는 CPU의 사용률이 떨어짐</strong></p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h3 id="1960년도--time-sharing-system--시분할-시스템">1960년도 : <strong>Time Sharing System  (시분할 시스템)</strong></h3>
<ul>
<li><p>**memory에 여러 program을 올려두고 시간을 나누어, 각 프로그램을 짧은 시간씩 돌아가며 실행</p>
</li>
<li><p>Single Stream Batch system의 한계 개선</p>
<ul>
<li>프로그램을 순서대로 하나씩 실행 X</li>
<li>매우 빠르게 번갈아가며 실행 ⇒ 사용자에게는 전부 동시에 실행되는 것처럼 보이게 됨</li>
<li>A작업에서 필요한 입력 처리 위해 cpu가 대기할 때 b,c 작업 ⇒ <strong>cpu 사용률 높임</strong></li>
</ul>
</li>
<li><p><strong>Terminal</strong></p>
<ul>
<li>프로그램을 동시에 여러 개 실행할 수 있으니, 당시 비싼 컴퓨터 1대를 여러 사용자가 <strong>Terminal</strong>이라는 단말기를 통해 접근하여 사용</li>
</ul>
</li>
<li><p><strong>File System</strong></p>
<ul>
<li>컴퓨터의 개인화 ⇒ 필요한 문서와 같은 개인 정보를 컴퓨터에 저장 ⇒ file system 등장</li>
</ul>
</li>
<li><p><strong>UNIX</strong></p>
<ul>
<li><p>C언어로 UNIX 운영체제 개발    (AT&amp;벨 연구소)</p>
</li>
<li><p><strong>Multi-programming, Multi-user, File system</strong> 구현</p>
<p><br><br/></p>
<h3 id="time-sharing-system의-한계-base-register의-등장">Time Sharing System의 한계 (Base Register의 등장)</h3>
</li>
</ul>
</li>
</ul>
<ol>
<li><p><strong>메모리 침범</strong></p>
<ul>
<li>한 program이 다른 program 메모리 침범 시  원하지 않는 결과 발생, 
OS영역까지 침범할 경우 치명적인 오류 발생 가능</li>
</ul>
</li>
<li><p><strong>메모리 주소 할당</strong></p>
<ul>
<li><p><strong>기존 1 메모리 : 1 program)</strong> 메모리 주소를 program 1개로 가정하고 개발</p>
</li>
<li><p><strong>Time Sharing System)</strong> program이 어느 메모리 위치에서 실행할지 모름</p>
</li>
</ul>
</li>
</ol>
<p>*<em>⇒ <code>Base Register</code> : program의 시작주소를 저장 *</em>⇒ <em>“모든 프로그램은 0번지에서 실행한다”</em>고 가정</p>
<p><br><br/></p>
<h4 id="1970년도-이후--개인-컴퓨터--→-gui">1970년도 이후 : 개인 컴퓨터  → GUI</h4>
<p><br><br/><br><br/></p>
<h1 id="운영체제의-구조">운영체제의 구조</h1>
<img src =https://velog.velcdn.com/images/kim_sunnnny/post/0e939e04-7c13-4aa5-9fd9-7fe68b1851d2/image.png width=40%>

<p><code>이미지 출처 : https://math-coding.tistory.com/80</code></p>
<ol>
<li><p><strong>Kernel</strong> : <em>process, memory, storage를 관리하는 핵심 기능</em></p>
</li>
<li><p><strong>Interface</strong>  : 사용자는 interface를 통해서 OS의 Kernel에 접근 가능  (직접 접근 불가)  </p>
<ul>
<li>GUI, CLI</li>
</ul>
</li>
</ol>
<p><strong>⇒ user/application - <code>system call</code> - kernel - <code>driver</code> - HW</strong></p>
<ul>
<li><p><strong>system call</strong></p>
<ul>
<li>kernel이 사용자로부터 자신을 보호하기 위한 interface</li>
<li>application은 system call을 통해 Kernel에 접근가능<ul>
<li>kernel에서 제공하는 <strong>write함수</strong>를 사용
→ OS가 알아서 하드디스크의 빈 공간에 정보 저장</li>
</ul>
</li>
</ul>
<ul>
<li><p><strong>driver</strong></p>
<ul>
<li><p>보통 HW 제조사에서 driver 제공
(OS는 많은 종류의 HW를 전부 지원해야 하기 때문에 각각의 하드웨어에 맞는 프로그램을 Kernel이 모두 갖고 있기 어려움)</p>
</li>
<li><p>mouse, keyboard 같은 기본적인 HW 장치들은 kernel에 포함</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h1 id="컴퓨터-하드웨어와-구조-cpu-ramrom-bus">컴퓨터 하드웨어와 구조 (CPU, RAM/ROM, BUS)</h1>
<h4 id="von-neumann-폰-노이만-구조---cpu-----bus-----memoryram-"><strong>von Neumann (폰 노이만 구조)</strong> :  *<em><code>CPU</code>  -  <code>BUS</code>  -  <code>Memory(RAM)</code> *</em></h4>
<ul>
<li><code>BUS</code> : 데이터를 전달하는 통로<ul>
<li>프로그램 내장 방식 : 프로그램을 메모리에 올려서 사용 
(↔️ 하드웨어로 프로그램 만들기 = 프로그램이 달라질 때마다 스위치와 배선 재조정 필요
<br><br/></li>
</ul>
</li>
</ul>
<p>*<em>0. Main Board *</em>: 다른 하드웨어를 연결하는 장치 </p>
<ul>
<li>장치 간 데이터 전송 ⇒ <strong>메인보드의 <code>BUS</code></strong>가 담당
<br><br/></li>
</ul>
<p><strong>1. CPU (중앙처리장치)</strong></p>
<ul>
<li><p><strong>ALU (Arithmetic and Logic Unit)  : 실제 데이터 연산 담당</strong>      (산술논리 연산장치)</p>
</li>
<li><p><strong>Control Unit</strong>  :  모든 장치들의 동작을 지시하고 제어하는 장치</p>
</li>
<li><p><strong>Register :</strong>  CPU 내 계산 위해 임시로 보관하는 장치</p>
<ul>
<li>Program Counter  (PC)</li>
<li>Memory Address Register</li>
<li>Memory Buffer Register</li>
<li>Instruction Register  (IR)<pre><code>    …</code></pre></li>
</ul>
</li>
</ul>
<p>*<em>2. Memory (주기억장치) : RAM &amp; ROM *</em></p>
<table>
<thead>
<tr>
<th>RAM  :  Random Access Memory</th>
<th>ROM  :  Read Only Memory</th>
</tr>
</thead>
<tbody><tr>
<td>데이터 저장된 위치 상관없이, 읽는 속도  동일</td>
<td>데이터 한 번 쓰면 수정 불가</td>
</tr>
<tr>
<td>(데이터 읽기만 가능)</td>
<td></td>
</tr>
<tr>
<td>Main memory로 사용</td>
<td>컴퓨터 부팅과 관련된 BIOS를 저장에 사용</td>
</tr>
<tr>
<td>전력이 끊기면 데이터 유실</td>
<td>전력이 끊겨도 데이터를 계속 보관</td>
</tr>
</tbody></table>
<p> <br><br/></p>
<p>*<em>2-1) Cache Memory *</em>: CPU와 주기억장치 사이의 속도차이 완화 시키기 위한 고속 buffer memory</p>
<p> <br><br/></p>
<p><strong>2-2) 주기억장치(RAM/ROM) &amp; 보조기억장치</strong></p>
<table>
<thead>
<tr>
<th>주기억장치 ( Computer/Primary Memory )</th>
<th>보조기억장치 ( Auxiliary/Secondary Memory )</th>
</tr>
</thead>
<tbody><tr>
<td>PC 내부에서 CPU가 처리하고 있는 내용 저장</td>
<td>저장된 데이터가 사라지지 않고 영구적으로 보관</td>
</tr>
<tr>
<td>용량 큼</td>
<td></td>
</tr>
<tr>
<td>처리속도 빠름</td>
<td>주기억장치보다 느림</td>
</tr>
<tr>
<td>CPU명령에 의해 기억된 장소에 직접 접근하여 읽고 씀</td>
<td>물리적인 디스크가 연결되어 있음</td>
</tr>
<tr>
<td>RAM, ROM</td>
<td>HDD, SSD</td>
</tr>
</tbody></table>
<p><br><br/><br><br/></p>
<h1 id="컴퓨터의-부팅과정">컴퓨터의 부팅과정</h1>
<ul>
<li>전원
 → ROM에 저장된 <strong>BIOS</strong> 실행
 → 하드디스크에 있는 MBR (Master Boot Record)에 저장된 Boot Loader를 RAM으로 가져와 실<br> → OS 2개 이상일 경우 OS 선택
 → OS를 RAM으로 불러와 실행
 → 이후 실행되는 모든 program은 OS가 관리</li>
</ul>
<ul>
<li><p><strong>BIOS</strong>  :  전원, CPU, 메모리, 하드디스크 등 주요 HW에 이상이 없는지 체크</p>
<ul>
<li>이상 발견 시 오류 내며 부팅 X</li>
</ul>
</li>
</ul>
<p><br><br/><br><br/></p>
<h1 id="interrupt----인터럽트">Interrupt    (인터럽트)</h1>
<ul>
<li><p><strong>if)</strong>  CPU가 입출력장치에 데이터를 Read/Write하는 상황</p>
<ul>
<li>CPU : 입출력 작업이 들어오면 → 입출력 관리자에게 입출력 명령</li>
</ul>
<ol>
<li><strong>Polling 방식  :</strong>  CPU 입장에서는 입출력 명령이 언제 완료될 지 알 수 없기 때문에 주기적으로 확인 필요<ul>
<li>단점 : 주기적으로 CPU가 확인해줘야 하기 때문에 성능 좋지 못함</li>
</ul>
</li>
</ol>
</li>
</ul>
<ol start="2">
<li><p><strong>Interrupt 방식  :</strong>  CPU가 입출력 관리자에게 입출력 명령을 내리고 다른 작업 지속</p>
<ul>
<li>입출력 관리자는 입출력이 완료됐을 때 CPU에게 신호를 전송
⇒ CPU는 그 신호를 받아  <strong>ISR (Interrupt Service Routine)</strong>을 실행시켜 작업을 완료함 <ul>
<li><strong>ISR (Interrupt Service Routine) :</strong> 특정 Interrupt가 들어오면 그것을 처리하는 함수</li>
</ul>
</li>
</ul>
</li>
</ol>
<pre><code>- **HW Interrupt  :**  keyboard, 마우스 입력, 디스크 입출력, 프린터

- **SW Interrupt   :**  사용자 program에서 발생한 interrupt
  - ex) 유효하지 않은 메모리 접근, 0으로 나누기</code></pre><p><br><br/><br><br/></p>
<h2 id="α">+α</h2>
<h3 id="q-program-vs-process-vs-thread">Q. Program vs Process vs Thread</h3>
<img src = https://velog.velcdn.com/images/kim_sunnnny/post/f162cc41-1e5b-4444-95cf-45c20d9e9252/image.png width=80%>

<ul>
<li><p><strong>Program</strong>  :  컴퓨터 디스크에 저장된 정적인 file (보조기억 장치)
<br><br/></p>
</li>
<li><p><strong>Process</strong>  :  프로그램이 메모리에 올라가, 실제로 실행 중인 동적인 entity </p>
<ul>
<li><p>Program + <strong><em>실행에 필요한 자원</em></strong> 할당 ⇾ Process</p>
</li>
<li><p><strong>OS로부터 할당 받는 자원 :</strong></p>
<ol>
<li>CPU 시간<ol start="2">
<li>운영되기 위해 필요한 주소 공간</li>
<li>독립된 메모리 영역  (Code/Data/Stack/Heap 구조)</li>
</ol>
<ul>
<li>** 각 Process 별 별도의 주소 공간 &amp; 독자적인 메모리 공간 ⇾ ** 다른 Process의 변수/자료구조에 접근 불가</li>
<li><strong>IPC</strong> (Process간 통신) :  다른 Process의 자원에 접근 허용</li>
<li><strong>Process : min 1 Thread</strong> = Main Thread</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<p>  <br><br/></p>
<ul>
<li><p><strong>Thread</strong> : Process가 할당받은 자원을 이용하는 실행 단위 / Process의 특정한 수행 경로 / Process 내 실행되는 여러 흐름의 단위</p>
<ul>
<li><p><strong>Main thread</strong> : Process 내 존재하는 최소 1개 thread </p>
</li>
<li><p>각 thread 별 <strong>독자적인 register &amp; stack memory</strong> 보유</p>
</li>
<li><p>thread들은 <strong>Code, Data, Heap 공유</strong> </p>
</li>
<li><p><strong>Process 내의 주소공간/자원들 공유</strong></p>
</li>
<li><p>1 thread가 process 자원을 변경하면 다른 sibling thread(이웃 thread)도 그 변경 결과를 즉시 볼 수 있다</p>
</li>
<li><p>memory를 공유하기 때문에 <strong>동기화</strong> , <strong>deadlock</strong> 등의 문제 발생 가능 </p>
</li>
<li><p>관련 library : <code>POSIX Pthreads</code>, <code>Windows threads</code>, <code>Java threads</code></p>
</li>
</ul>
<table>
<thead>
<tr>
<th></th>
<th><strong>Process</strong></th>
<th><strong>Thread</strong></th>
</tr>
</thead>
<tbody><tr>
<td>정의</td>
<td>실행 중인 program</td>
<td>Process의 실행 단위</td>
</tr>
<tr>
<td>생성/종료시간</td>
<td>많은 시간 소요</td>
<td>적은 시간 소요</td>
</tr>
<tr>
<td><strong>Context Switching</strong></td>
<td>많은 시간 소요</td>
<td>적은 시간 소요</td>
</tr>
<tr>
<td>상호작용</td>
<td><strong>IPC</strong> 사용</td>
<td><strong>공유 memory</strong> 사용</td>
</tr>
<tr>
<td>자원소모</td>
<td>많음</td>
<td>적음</td>
</tr>
<tr>
<td>메모리 내 독립성</td>
<td>각각 독립적</td>
<td>프로세스 내 <strong>stack/register 독립적, 이외 공유</strong></td>
</tr>
</tbody></table>
</li>
</ul>
<p><br><br/></p>
<h3 id="q-processor--multi-processing--multi-threading">Q. Processor &amp; Multi-Processing &amp; Multi-Threading</h3>
<ul>
<li><p><strong>Processor  = CPU</strong>   :  computer 내 program을 수행하는 HW Unit (명령어 해석하는 한 부분)</p>
</li>
<li><p>Process의 <strong>동시성</strong> &amp; <strong>병렬성</strong> (Concurrency &amp; Parallelism)</p>
<ul>
<li><p>processor는 한번에 1개의 process만 실행 </p>
</li>
<li><p><strong>동시성 = Context Switching</strong> : processor 하나가 program 1,2,3,4 여러 작업을 돌아가며 일부분씩 수행하는 방식</p>
</li>
<li><p><strong>병렬성</strong> = <strong>Processor 1</strong>에 <strong>Core 여러 개</strong>가 달려서 각각 동시에 작업하는 방식</p>
<ul>
<li>&quot;dual-core&quot;/&quot;quad-core&quot;/&quot;octa-core&quot; 등의 명칭의 processor가 달린 컴퓨터에서만 할 수 있는 방식 </li>
</ul>
</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<ul>
<li><strong>Multi-tasking</strong>  :  동시에 여러 개의 program 실행</li>
<li><strong>Multi-processing</strong> : 응용프로그램을 여러 개의 process로 구성 ⇒ 각 process가 1개의 task 처리하도록 </li>
</ul>
<table>
<thead>
<tr>
<th></th>
<th>Multi - Processing</th>
<th>Multi - Threading</th>
</tr>
</thead>
<tbody><tr>
<td>정의</td>
<td><strong>응용 프로그램 1 → 여러 개의 process</strong></td>
<td><strong>응용 프로그램 1 → 여러 개의 thread</strong></td>
</tr>
<tr>
<td>장점</td>
<td><br> process에 문제가 발생하면 그것의 자식 proecss만 죽음(다른 영향 x) <br/></td>
<td><br><strong>1. System 자원 소모 감소 (자원 효율성 증대)</strong> <br/><br>(process를 생성하여 자원 할당하는 system call이 줄어들어 자원을 효율적으로 관리할 수 있음)  <br/><br><strong>2. System 처리량 증가  (처리 비용 감소)</strong> <br/><br> ( Thread 간 data 교환이 간단해지고 system 자원 소모 감소,  Thread 사이 작업량이 작아 Context switching이 빠름)<br/><br> <strong>3. Program 응답 시간 단축</strong> <br/><br>  (Process 내 stack 이외 모든 memory를 공유하므로 통신의 부담 적음)</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>단점</td>
<td><br><strong>1. Context Switching 과정에서 cache memory 초기화 등 무거운 작업이 진행되고 많은 시간이 소모되는 등의 오버헤드 발생</strong> <br/><br>(  process 사이에 공유하는 memory가 없음 → Context Switching발생 시 cache에 있는 모든 data를 모두 reset하고 다시 cache 정보를 불러와야 함)<br/><br> <strong>2. Process 간 IPC 통신할 때, process 간 변수 공유 불가</strong><br/><br> (process가 각각 독립된 memory 영역을 할당받았기 때문에)</td>
<td><br>1. 주의 깊은 설계 필요 <br/><br>2. 까다로운 디버깅 <br/><br>3. single process system 은 큰 효과 X <br/><br>4. process 밖에서 thread 각각 제어 불가 <br/><br>5. 자원 공유의 문제 발생  (동기화 문제) <br/><br>6. Thread 1개의 문제가 전체 Process에 영향</td>
</tr>
</tbody></table>
<p><br><br/></p>
<h1 id="주제와-관련한-cs-질문">주제와 관련한 cs 질문</h1>
<ul>
<li><p>CPU 사용률 관점에서 시분할 시스템과 입출력 관리자의 역할에 대해 설명하시오</p>
<ul>
<li>시분할 시스템과 입출력 관리자 모두 CPU의 사용률을 높이기 위해 고안된 것</li>
<li>기존의 single stream batch system은 입출력이 모두 끝날 때까지 CPU를 사용할 수 없었기 때문에 입출력 관리자를 통해 입출력을 분리함으로써, cpu의 사용률을 높일 수 있었다</li>
<li>하지만 여전히 입출력이 끝날 때까지 cpu가 대기해야</li>
</ul>
</li>
<li><p>멀티 프로세싱과 멀티 스레딩의 장단점에 대해서 설명하시오</p>
<ul>
<li>멀티 프로세싱의 경우, 프로세스가 독자적인 메모리와 주소 공간을 갖고 있으므로, 하나의 프로세스의 오류가 다른 프로세스에 영향을 주지 않아 안정적이다. 하지만 프로세스 간 메모리가 공유 되지 않아, context switching 비용과과 ipc 비용이 크다</li>
<li>반면 멀티 스레딩의 경우, 스레드들이 stack영역을 제외한 메모리를 공유하여 스레드 간 데이터 교환이나 context switching이 빠르게 이루어질 수 있다. 반면 이것이 단점이 되어 동기화, deadlock 등의 오류가 발생할 수 있다.</li>
</ul>
</li>
</ul>
<p><br><br/></p>
<h3 id="q-interrupt--비동기-방식--⇒-성능에-이점-dma-controller">Q. Interrupt : 비동기 방식  ⇒ 성능에 이점? DMA Controller?</h3>
<h3 id="q-booting---bios-vs-uefi">Q. booting -&gt; BIOS vs UEFI?</h3>
<h3 id="q-core-란">Q. core 란?</h3>
<p><br><br/><br><br/><br><br/><br><br/><br><br/></p>
<ul>
<li>Reference<ul>
<li><a href="https://velog.io/@gparkkii/ProgramProcessThread">https://velog.io/@gparkkii/ProgramProcessThread</a></li>
<li><h2 id="httpschange-wordstistorycomentryed9484eba19ceab7b8eb9ea8eab3bc-ed9484eba19cec84b8ec8aa4ec9d98-ecb0a8ec9db4eca090texted9484eba19ceab7b8eb9ea820ed9484eba19cec84b8ec8aa420ecb0a8ec9db4ec979020ec9e88eb8ba4eab3a020ec9db4ed95b4ed95a020ec889820ec9e88ec8ab5eb8b88eb8ba4"><a href="https://change-words.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EA%B3%BC-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90#:~:text=%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EC%B0%A8%EC%9D%B4,%EC%97%90%20%EC%9E%88%EB%8B%A4%EA%B3%A0%20%EC%9D%B4%ED%95%B4%ED%95%A0%20%EC%88%98%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4">https://change-words.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EA%B3%BC-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90#:~:text=%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EC%B0%A8%EC%9D%B4,%EC%97%90%20%EC%9E%88%EB%8B%A4%EA%B3%A0%20%EC%9D%B4%ED%95%B4%ED%95%A0%20%EC%88%98%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4</a>.</h2>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PRG] 크레인 인형뽑기 게임 ]]></title>
            <link>https://velog.io/@kim_sunnnny/PRG-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0-%EA%B2%8C%EC%9E%84</link>
            <guid>https://velog.io/@kim_sunnnny/PRG-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0-%EA%B2%8C%EC%9E%84</guid>
            <pubDate>Sun, 02 Jul 2023 07:26:40 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제">1. <a href="https://school.programmers.co.kr/learn/courses/30/lessons/64061">문제</a></h3>
<ul>
<li><p>“N x N”크기의 격자에 있는 번호가 부여된 인형들을 바구니에 옮기는 인형뽑기 게임</p>
</li>
<li><p>인형은 바구니의 가장 아래 부터 순서대로 쌓임</p>
</li>
<li><p>같은 모양의 인형이 바구니에 연속해서 쌓이게 되면 두 인형은 바구니에서 사라짐</p>
<p>  <strong>⇒ 크레인을 모두 작동시킨 후 터트려져 사라진 인형의 개수?</strong></p>
</li>
<li><p>입력 :</p>
<ul>
<li>게임 화면의 격자의 상태가 담긴 2차원 배열 board</li>
<li>인형을 집기 위해 크레인을 작동시킨 위치가 담긴 배열 moves</li>
</ul>
</li>
</ul>
<ul>
<li>출력 : 터트려져 사라진 인형의 개수</li>
</ul>
<h3 id="2-풀이">2. 풀이</h3>
<ul>
<li><p>바구니 ⇒ stack!</p>
</li>
<li><p>moves의 원소들을 m이라고 할 때, 입력으로 주어진 board를 그대로 사용하게 된다면,  m번째 위치의 원소를 매번 조회하고, 인형을 뽑게 됐을 경우의 처리 등이 코드적으로 비효율적</p>
</li>
<li><p>따라서 move마다 board에서 m번에 위치한 인형들을 crane이라는 list로 생성하여 사용한다.<br>  <img src="https://velog.velcdn.com/images/kim_sunnnny/post/2d3aaa50-507a-4116-baa5-2d9985330f9b/image.png" alt=""></p>
</li>
<li><p>이 때, crane의 가장 윗부분에 있는 인형을 뽑기 위해 for loop을 이용</p>
<ul>
<li>만약 basket이 비어있거나, basket의 가장 위에 위치한 인형이 방금 뽑은 인형과 다를 경우, basket에 방금 뽑은 인형을 append</li>
<li>만약  basket의 가장 위에 위치한 인형이 방금 뽑은 인형과 같을 경우 인형을 없앤 후 answer +=2</li>
</ul>
</li>
</ul>
<h3 id="3-코드">3. 코드</h3>
<pre><code class="language-python">def solution(board, moves):
    answer = 0

    basket = []

    width = len(board)

    for m in moves:
        crane = [ board[x][m-1] for x in range(width) ] 

        for i in range(width):
            if crane[i] != 0:
                board[i][m-1] = 0

                if not basket or crane[i] != basket[-1]:
                    basket.append(crane[i])
                else:
                    basket.pop(-1)
                    answer += 2
                break

    return answer</code></pre>
<h3 id="α">+α</h3>
]]></description>
        </item>
    </channel>
</rss>