<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>doveloper</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 16 Feb 2024 12:11:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>doveloper</title>
            <url>https://velog.velcdn.com/images/dodo_velog/profile/5bd3696d-7ff4-4249-993b-8bf5fdb28664/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. doveloper. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dodo_velog" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[11726.py] 2×n 타일링]]></title>
            <link>https://velog.io/@dodo_velog/11726.py-2n-%ED%83%80%EC%9D%BC%EB%A7%81</link>
            <guid>https://velog.io/@dodo_velog/11726.py-2n-%ED%83%80%EC%9D%BC%EB%A7%81</guid>
            <pubDate>Fri, 16 Feb 2024 12:11:47 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/11726">문제 링크</a>
<br/></p>
<h3 id="문제">문제</h3>
<p>2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오.</p>
<p>아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다.</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 n이 주어진다. (1 ≤ n ≤ 1,000)</p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 2×n 크기의 직사각형을 채우는 방법의 수를 10,007로 나눈 나머지를 출력한다.
<br/>
풀이 코드</p>
<pre><code>n = int(input())
dp = [0] * (n + 1)

dp[1] = 1
dp[2] = 2

for i in range(3, n + 1):
    dp[i] = (dp[i - 1] + dp[i - 2]) % 10007

print(dp[n])</code></pre><p>그냥 냅다 2부터 적어서 보니 너무 익숙한 수열.. 피보나치였다
탑다운으로 풀려했는디.. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[14232.py] 보석 도둑]]></title>
            <link>https://velog.io/@dodo_velog/14232.py-%EB%B3%B4%EC%84%9D-%EB%8F%84%EB%91%91</link>
            <guid>https://velog.io/@dodo_velog/14232.py-%EB%B3%B4%EC%84%9D-%EB%8F%84%EB%91%91</guid>
            <pubDate>Fri, 16 Feb 2024 11:27:55 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/14232">문제 링크</a></p>
<br />
### 문제
희대의 도둑 효빈이는 세계 최고의 보석가게 영선상에 잠입할 계획이다. 이 영선상은 최고의 보석가게답게 최고의 보안장치를 두고 있는데, 이 보안장치를 해제하지 않는다면 보석을 여러 개 훔쳐갈 시, 보석끼리 달라붙으며 무게가 모든 보석들의 곱으로 늘어난다.

<p>효빈이는 이 보안장치를 해제할 수 없기 때문에, 차라리 곱해진 대로 최대한 많은 보석들을 가져오기로 계획했다. 효빈이는 한번에 k라는 무게를 들 수 있으므로, 딱 k만큼의 무게만큼의 보석을 가져오고 싶은데, 그 때 보석들의 최대 개수를 알고싶다.</p>
<p>영선상에는 세계 최고의 보석가게답게 모든 무게의 보석들이 매우 많이때문에, 훔쳐가는 보석이 부족할 일은 없다. 다만 모든 보석들은 무게가 1보다 크다.</p>
<p>효빈이는 이제 영선상에 잡입할 계획을 다 세웠다. 하지만 무슨 보석들을 훔쳐올지 결정하지 못하였는데, 효빈이를 대신하여 훔쳐올 보석들을 결정해주자.</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에는 효빈이가 들 수 있는 무게 k가 주어진다.(2≤k≤1012)</p>
<h3 id="출력">출력</h3>
<p>첫째 줄에는 효빈이가 훔쳐올 보석의 개수를 출력하고, 다음 줄에는 훔쳐올 보석들의 무게를 오름차순으로 출력하시오.</p>
<br />
풀아 코드
```
#k라는 무게를 채울 수 있는 최대 보석 개수
#가장 다양한 방벙브로 곱해서 k가 되는 경우 
#서로소로 나누기?

<p>K = int(input())</p>
<p>answer = []
for i in range(2, int(K**0.5) + 1):
    while K %i == 0:
        answer.append(i)
        K //= i    </p>
<p>if K != 1: answer.append(K) #자체가 소수일때</p>
<p>print(len(answer))
print(*answer)</p>
<pre><code>
단순 소인수 찾기 문제인줄 알았는데 아니였다 ㅠ
2부터 시작해서 K를 계속 나눈 값으로 갱신시키면서 answer에 추가추가
그리고 K가 소수인 경우 주의
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[2304.py] 창고 다각형]]></title>
            <link>https://velog.io/@dodo_velog/2304.py-%EC%B0%BD%EA%B3%A0-%EB%8B%A4%EA%B0%81%ED%98%95</link>
            <guid>https://velog.io/@dodo_velog/2304.py-%EC%B0%BD%EA%B3%A0-%EB%8B%A4%EA%B0%81%ED%98%95</guid>
            <pubDate>Fri, 16 Feb 2024 10:29:27 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/2304">문제 링크</a>
<br /></p>
<h3 id="문제">문제</h3>
<p>N 개의 막대 기둥이 일렬로 세워져 있다. 기둥들의 폭은 모두 1 m이며 높이는 다를 수 있다. 이 기둥들을 이용하여 양철로 된 창고를 제작하려고 한다. 창고에는 모든 기둥이 들어간다. 이 창고의 지붕을 다음과 같이 만든다.</p>
<p>지붕은 수평 부분과 수직 부분으로 구성되며, 모두 연결되어야 한다.
지붕의 수평 부분은 반드시 어떤 기둥의 윗면과 닿아야 한다.
지붕의 수직 부분은 반드시 어떤 기둥의 옆면과 닿아야 한다.
지붕의 가장자리는 땅에 닿아야 한다.
비가 올 때 물이 고이지 않도록 지붕의 어떤 부분도 오목하게 들어간 부분이 없어야 한다.
그림 1은 창고를 옆에서 본 모습을 그린 것이다. 이 그림에서 굵은 선으로 표시된 부분이 지붕에 해당되고, 지붕과 땅으로 둘러싸인 다각형이 창고를 옆에서 본 모습이다. 이 다각형을 창고 다각형이라고 하자.</p>
<p>그림1 . 기둥과 지붕(굵은 선)의 예</p>
<p>창고 주인은 창고 다각형의 면적이 가장 작은 창고를 만들기를 원한다. 그림 1에서 창고 다각형의 면적은 98 ㎡이고, 이 경우가 가장 작은 창고 다각형이다.</p>
<p>기둥들의 위치와 높이가 주어질 때, 가장 작은 창고 다각형의 면적을 구하는 프로그램을 작성하시오.</p>
<h3 id="입력">입력</h3>
<p>첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의 빈 칸을 사이에 두고 주어진다. L과 H는 둘 다 1 이상 1,000 이하이다.</p>
<h3 id="출력">출력</h3>
<p>첫 줄에 창고 다각형의 면적을 나타내는 정수를 출력한다.</p>
<br />
풀이 코드

<pre><code>N = int(input())
block = [list(map(int, input().split())) for _ in range(N)]
block.sort()

max_idx = max(block, key=lambda x:x[0])[0]
min_idx = min(block, key=lambda x:x[0])[0]
new_block = [0 for _ in range(max_idx+1)]

for i in range(len(block)):
    idx = block[i][0]
    new_block[idx] = block[i][1]

for i in range(min_idx+1, max_idx):
    max_left = max(new_block[:i])
    max_right = max(new_block[i+1:])

    if min(max_left, max_right) - new_block[i] &gt; 0:
        new_block[i] += (min(max_left, max_right) - new_block[i])

print(sum(new_block))</code></pre><p>이것도 완탐.. 완탐으로 못풀 문제는 없군여</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[14719.py] 빗물]]></title>
            <link>https://velog.io/@dodo_velog/14719.py-%EB%B9%97%EB%AC%BC</link>
            <guid>https://velog.io/@dodo_velog/14719.py-%EB%B9%97%EB%AC%BC</guid>
            <pubDate>Thu, 15 Feb 2024 18:13:32 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/14719">문제 링크</a></p>
<p>문제
2차원 세계에 블록이 쌓여있다. 비가 오면 블록 사이에 빗물이 고인다.</p>
<p>비는 충분히 많이 온다. 고이는 빗물의 총량은 얼마일까?</p>
<p>입력
첫 번째 줄에는 2차원 세계의 세로 길이 H과 2차원 세계의 가로 길이 W가 주어진다. (1 ≤ H, W ≤ 500)</p>
<p>두 번째 줄에는 블록이 쌓인 높이를 의미하는 0이상 H이하의 정수가 2차원 세계의 맨 왼쪽 위치부터 차례대로 W개 주어진다.</p>
<p>따라서 블록 내부의 빈 공간이 생길 수 없다. 또 2차원 세계의 바닥은 항상 막혀있다고 가정하여도 좋다.</p>
<p>출력
2차원 세계에서는 한 칸의 용량은 1이다. 고이는 빗물의 총량을 출력하여라.</p>
<p>빗물이 전혀 고이지 않을 경우 0을 출력하여라.</p>
<p>풀이 코드</p>
<pre><code>H, W = map(int, input().split())
rain = list(map(int, input().split()))

water = 0

for i in range(1, W-1): #빗물양 계산 , i는 가운데 기준
    left = max(rain[:i]) #왼쪽에서 가장 높은 블록 높이
    right  = max(rain[i+1:]) #오른쪽에서 가장 높은 블록 높이

    # 현재 열에서 고이는 빗물의 양은 
    # 현재 열의 높이보다 왼쪽과 오른쪽에서 가장 높은 블록의 높이 중 작은 값에서
    # 현재 열의 높이를 뺀 값
    water += max(0, min(left, right) - rain[i])

print(water)</code></pre><p>완전 탐색으로 품</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[15655.py] N과 M (6)]]></title>
            <link>https://velog.io/@dodo_velog/15655.py-N%EA%B3%BC-M-6</link>
            <guid>https://velog.io/@dodo_velog/15655.py-N%EA%B3%BC-M-6</guid>
            <pubDate>Thu, 15 Feb 2024 17:36:26 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/15655">문제 링크</a></p>
<p>시간 제한    메모리 제한    제출    정답    맞힌 사람    정답 비율
1 초    512 MB    21308    17864    14474    84.470%
문제
N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오. N개의 자연수는 모두 다른 수이다.</p>
<p>N개의 자연수 중에서 M개를 고른 수열
고른 수열은 오름차순이어야 한다.
입력
첫째 줄에 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)</p>
<p>둘째 줄에 N개의 수가 주어진다. 입력으로 주어지는 수는 10,000보다 작거나 같은 자연수이다.</p>
<p>출력
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.</p>
<p>수열은 사전 순으로 증가하는 순서로 출력해야 한다.
<br /></p>
<p>풀이 코드</p>
<pre><code>def recur(N, M, selected):
    if len(selected) == M:
        print(*selected)
        return

    start = arr.index(selected[-1]) if selected else 0

    for i in range(start, N): #arr = [1,7,8,9]
        if arr[i] not in selected:
            recur(N, M, selected + [arr[i]])


N, M = map(int, input().split())
arr = list(map(int, input().split()))
arr.sort()

recur(N, M, [])</code></pre><p>재귀 사용해서 조건만 살짝 바꾸면서 세뚜문제 다 풀 수 있음!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[19942.py] 다이어트]]></title>
            <link>https://velog.io/@dodo_velog/19942.py-%EB%8B%A4%EC%9D%B4%EC%96%B4%ED%8A%B8</link>
            <guid>https://velog.io/@dodo_velog/19942.py-%EB%8B%A4%EC%9D%B4%EC%96%B4%ED%8A%B8</guid>
            <pubDate>Wed, 14 Feb 2024 18:04:34 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/19942">문제 링크</a></p>
<p>문제
식재료 N개 중에서 몇 개를 선택해서 이들의 영양분(단백질, 탄수화물, 지방, 비타민)이 일정 이상이 되어야 한다. 아래 표에 제시된 6가지의 식재료 중에서 몇 개를 선택해서 이들의 영양분의 각각 합이 최소 100, 70, 90, 10가 되도록 하는 경우를 생각해보자. 이 경우 모든 재료를 선택하면 쉽게 해결되지만, 우리는 조건을 만족시키면서도 비용이 최소가 되는 선택을 하려고 한다.</p>
<p>재료    단백질    지방    탄수화물    비타민    가격
1    30    55    10    8    100
2    60    10    10    2    70
3    10    80    50    0    50
4    40    30    30    8    60
5    60    10    70    2    120
6    20    70    50    4    40
예를 들어, 식재료 1, 3, 5를 선택하면 영양분은 100, 145, 130, 10으로 조건을 만족하지만 가격은 270이 된다. 대신 2, 3, 4를 선택하면 영양분의 합은 110, 130, 90, 10, 비용은 180이 되므로, 앞의 방법보다는 더 나은 선택이 된다.</p>
<p>입력으로 식재료 표가 주어졌을 때, 최저 영양소 기준을 만족하는 최소 비용의 식재료 집합을 찾아야 한다.</p>
<p>입력
첫 줄에 식재료의 개수 
$N$이 주어진다.</p>
<p>다음 줄에는 단백질, 지방, 탄수화물, 비타민의 최소 영양성분을 나타내는 정수 
$mp$, 
$mf$, 
$ms$, 
$mv$가 주어진다.</p>
<p>이어지는 
$N$개의 각 줄에는 
$i$번째 식재료의 단백질, 지방, 탄수화물, 비타민과 가격이 5개의 정수 
$p_i$, 
$f_i$, 
$s_i$, 
$v_i$, 
$c_i$와 같이 주어진다. 식재료의 번호는 1부터 시작한다.</p>
<p>출력
첫 번째 줄에 최소 비용을 출력하고, 두 번째 줄에 조건을 만족하는 최소 비용 식재료의 번호를 공백으로 구분해 오름차순으로 한 줄에 출력한다. 같은 비용의 집합이 하나 이상이면 사전 순으로 가장 빠른 것을 출력한다.</p>
<p>조건을 만족하는 답이 없다면 -1을 출력하고, 둘째 줄에 아무것도 출력하지 않는다.</p>
<p>풀이</p>
<pre><code>def recur(idx, p, f, s, v, price, selected):
    global answer

    if idx == N: # 리스트 다 돌았으면
        if p &gt;= mp and f &gt;= mf and s &gt;= ms and v &gt;= mv:
            if price &lt; answer[0]:
                answer = [price, selected[:]]
            elif price == answer[0] and selected &lt; answer[1]:
                answer = [price, selected[:]]

    else:
        # 재귀로 완전 탐색하는 방법

        # 재료 선택한다면
        recur(idx+1, p+ingre_info[idx][0], f+ingre_info[idx][1], s+ingre_info[idx][2], v+ingre_info[idx][3], price+ingre_info[idx][4], selected + [idx+1])

        # 재료 선택하지 않는다면
        recur(idx+1, p, f, s, v, price, selected)


N = int(input())
# 최소 영양 성분 기준
mp, mf, ms, mv = map(int, input().split())
# 단 지 탄 비 가
ingre_info = [list(map(int, input().split())) for _ in range(N)]
answer = [float(&#39;inf&#39;), []] #비용, [인덱스]]

recur(0, 0, 0, 0, 0, 0, [])

if answer[0] == float(&#39;inf&#39;):
    print(-1)
else:
    print(answer[0])
    print(*answer[1])</code></pre><p>재귀 함수 써서 완전 탐색으로 풀어쓰</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[2247.py] 실질적 약수]]></title>
            <link>https://velog.io/@dodo_velog/2247.py-%EC%8B%A4%EC%A7%88%EC%A0%81-%EC%95%BD%EC%88%98</link>
            <guid>https://velog.io/@dodo_velog/2247.py-%EC%8B%A4%EC%A7%88%EC%A0%81-%EC%95%BD%EC%88%98</guid>
            <pubDate>Mon, 12 Feb 2024 14:35:32 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/2247">문제 링크</a></p>
<p><strong>문제</strong>
두 자연수 A와 B가 있을 때, A = BC를 만족하는 자연수 C를 A의 약수라고 한다. 모든 자연수 N은 1과 자기 자신(N)을 약수로 갖게 된다.</p>
<p>실질적 약수(actual divisor)라는 것이 있다. 자연수 N의 약수들 중에서 1과 자기 자신(N)을 제외한 약수를 실질적 약수라고 한다. 따라서 6의 실질적 약수는 2, 3이며, 13의 실질적 약수는 없다.</p>
<p>SOD(Sum Of Divisor)라는 함수를 정의하자. SOD(n)은 정수 n의 모든 실질적 약수의 합을 가리킨다. 따라서 SOD(6) = 5이며, SOD(13) = 0이다. 한편, CSOD(Cumulative SOD)라는 함수도 정의해 볼 수 있다. CSOD(n)은 SOD(1) + SOD(2) + … + SOD(n)이라고 하자.</p>
<p>CSOD(n)을 구하는 프로그램을 작성하시오.</p>
<p><strong>입력</strong>
첫째 줄에 정수 n이 주어진다.</p>
<p><strong>출력</strong>
첫째 줄에 CSOD(n)을 1,000,000으로 나눈 나머지를 출력한다.</p>
<br>
**단순 접근으로 시간 초과 났던 코드**

<pre><code>
N = int(input())

sod_cache = {}
def SOD(s):
    divisor_list = []
    sum_divisors = 0
    #제곱근까지 범위 줄이기
    for i in range(2, int(s**(1/2))+1):
        if s % i == 0:
            divisor_list.append(i)
            if i**2 != s:
                divisor_list.append(s // i)               
    if divisor_list:
        sum_divisors = sum(divisor_list)
    sod_cache[s] = sum_divisors
    return sum_divisors


def CSOD(num):
    sum_c = 0
    for i in range(1,num+1):
        sum_c += SOD(i)
    return sum_c

print(CSOD(N) % 1000000)
</code></pre><p>진짜 쉽다고 생각해서 접근했는데 시간초과 지옥에 걸림..😱
<br>
<strong>시간 초과 해결법</strong>
1<del>n 까지의 정수들 중에서 1</del>n의 약수를 가지는 것의 개수</p>
<p>ex) n = 16일때 1을 약수로 가진 것의 개수 16
2를 약수로 가진것의 개수 8
3을 약수로 가진것의 개수 5
.....</p>
<p>이렇게 가다보면 결국 i를 약수로 가진 것의 개수는 n//i </p>
<p>참고 자료
<a href="https://velog.io/@yeseul/%EB%B0%B1%EC%A4%80-2247-%EC%8B%A4%EC%A7%88%EC%A0%81-%EC%95%BD%EC%88%98">https://velog.io/@yeseul/%EB%B0%B1%EC%A4%80-2247-%EC%8B%A4%EC%A7%88%EC%A0%81-%EC%95%BD%EC%88%98</a></p>
<p><a href="https://cobokjang.tistory.com/14">https://cobokjang.tistory.com/14</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS 요약]]></title>
            <link>https://velog.io/@dodo_velog/JS-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dodo_velog/JS-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Wed, 10 Jan 2024 06:58:03 GMT</pubDate>
            <description><![CDATA[<h3 id="let--const"><strong>let &amp; const</strong></h3>
<p><code>let</code> 에 대해 더 읽어보기: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let</a></p>
<p><code>const</code>에 대해 더 읽어보기:: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const</a></p>
<p><code>let</code> 과 <code>const</code> 는 기본적으로 <code>var</code> 를 대체합니다. </p>
<p>여러분은 <code>var</code> 대신 <code>let</code> 을 사용하고, <code>var</code>  대신 <code>const</code>를 사용하게 됩니다. </p>
<p>만약 이 &quot;변수&quot;를 다시 할당하지 않을 경우에 말이죠 (따라서 효과적으로 constant로 변환합니다).</p>
<p><code>let</code>으로 선언된 변수는 해당 블록{} 내에서만 사용가능</p>
<p><code>var</code>와 달리 <code>let</code> 변수는 범위 내에서 다시 선언할 수 없습니다. 그러나 동일한 변수가 다른 범위 내에서 정의된다면, 에러는 더 이상 발생하지 않습니다.</p>
<pre><code class="language-jsx">let greeting = &quot;say Hi&quot;;
    if (true) {
        let greeting = &quot;say Hello instead&quot;;
        console.log(greeting); // &quot;say Hello instead&quot;
    }
    console.log(greeting); // &quot;say Hi&quot;</code></pre>
<p><code>const</code>로 선언된 변수는 일정한 상수 값을 유지합니다. <code>const</code> 선언은 선언하는 당시에 초기화되어야 합니다.</p>
<p><code>const</code> 개체는 업데이트할 수 없지만, 개체의 &#39;속성&#39;은 업데이트할 수 있습니다. <code>const</code> 객체를 다음과 같이 선언했다면:</p>
<pre><code class="language-jsx">    const greeting = {
        message: &quot;say Hi&quot;,
        times: 4
    }
</code></pre>
<p>아래와 같은 작업은 불가능하지만:</p>
<pre><code class="language-jsx">    greeting = {
        words: &quot;Hello&quot;,
        number: &quot;five&quot;
    } // error:  Assignment to constant variable.
</code></pre>
<p>다음의 코드는 가능합니다:</p>
<pre><code class="language-jsx">    greeting.message = &quot;say Hello instead&quot;;
</code></pre>
<p>오류를 반환하지 않고 <code>greeting.message</code> 값이 업데이트됩니다.</p>
<p>정리</p>
<ul>
<li><code>var</code> 선언은 전역 범위 또는 함수 범위이며, <code>let</code>과 <code>const</code>는 블록 범위이다.</li>
<li><code>var</code> 변수는 범위 내에서 업데이트 및 재선언할 수 있다. <code>let</code> 변수는 업데이트할 수 있지만, 재선언은 할 수 없다. <code>const</code> 변수는 업데이트와 재선언 둘 다 불가능하다.</li>
<li>세 가지 모두 최상위로 호이스팅된다. 하지만 <code>var</code> 변수만 <code>undefined(정의되지 않음)</code>으로 초기화되고 <code>let</code>과 <code>const</code> 변수는 초기화되지 않는다.</li>
<li><code>var</code>와 <code>let</code>은 초기화하지 않은 상태에서 선언할 수 있지만, <code>const</code>는 선언 중에 초기화해야한다.</li>
</ul>
<h3 id="es6-arrow-functions"><strong>ES6 Arrow Functions</strong></h3>
<p>더 읽어보기: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions</a></p>
<p>Arrow function은 JavaScript 환경에서함수를 생성하는 또 다른 방법입니다. 더 짧은 구문 외에도 <code>this</code> 키워드의 범위를 유지하는데 있 이점을 제공합니다 (<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_this">여기</a>를 보세요).</p>
<p>Arrow function 구문은 낯설게 보일 수 있으나 사실 간단합니다.</p>
<pre><code class="language-jsx">
function callMe(name) { 
    console.log(name);
}</code></pre>
<p>또한 다음과 같이 작성할 수도 있습니다:</p>
<pre><code class="language-jsx">
const callMe = function(name) { 
     console.log(name);
 }</code></pre>
<p>이렇게 됩니다:</p>
<pre><code class="language-jsx">
const callMe = (name) =&gt; { 
     console.log(name);
 }</code></pre>
<p><strong>중요:</strong></p>
<p><strong>arguments가 없는 경우</strong>, 함수 선언시 빈 괄호를 사용해야 합니다:</p>
<pre><code class="language-jsx">
const callMe = () =&gt; { 
     console.log(&#39;Max!&#39;);
 }</code></pre>
<p><strong>정확히 하나의 argument가 있는 경우</strong>, 괄호를 생략할 수 있습니다:</p>
<pre><code class="language-jsx">
const callMe = name =&gt; { 
     console.log(name);
 }</code></pre>
<p><strong>value를 return할 때</strong>, 다음과 같은 숏컷을 사용할 수 있습니다:</p>
<pre><code class="language-jsx">
const returnMe = name =&gt; name</code></pre>
<p>이것은 다음과 같습니다:</p>
<pre><code class="language-jsx">
const returnMe = name =&gt; { 
     return name;
 }</code></pre>
<h3 id="exports--imports"><strong>Exports &amp; Imports</strong></h3>
<p>React 프로젝트에서 (그리고 실제로 모든 최신 JavaScript에서), 모듈이라 불리는 여러 자바스크립트 파일들에 코드를 분할합니다. 이렇게 하면 각 file/ 모듈의 목적을 명확하게 하고 관리가 용이하게 합니다.</p>
<p>다른 파일의 기능에 계속 액세스하려면 <code>export</code>  (available하게 하기 위해) 및 <code>import</code> 엑세스를 확보하기 위해) statements가 필요합니다.</p>
<p>두 가지 유형의 export가 있습니다: <strong>default</strong> (unnamed)와 <strong>named</strong> 입니다.</p>
<p><strong>default</strong> =&gt; <code>export default ...;</code></p>
<p><strong>named</strong> =&gt; <code>export const someData = ...;</code></p>
<p><strong>default exports</strong>를 다음과 같이 import 할 수 있습니다.</p>
<p><code>import someNameOfYourChoice from &#39;./path/to/file.js&#39;;</code></p>
<p>놀랍게도, <code>someNameOfYourChoice</code>  전적으로 여러분에게 달려 있습니다.</p>
<p><strong>Named exports</strong>는 이름으로 import되어야 합니다:</p>
<p><code>import { someData } from &#39;./path/to/file.js&#39;;</code></p>
<p>파일 하나는 오직 하나의 default와 무한한 named exports를 가질 수 있습니다. 하나의 default를 같은 파일 내에서 named exports와 믹스할 수 있습니다.</p>
<p><strong>named exports를 import할 때,</strong> 다음 구문을 이용해 한 번에 모든 named exports를 import할 수 있습니다.</p>
<p><code>import * as upToYou from &#39;./path/to/file.js&#39;;</code></p>
<p><code>upToYou</code> 는 모든 exported 변수/함수를 하나의 자바스크립트 객체에 모읍니다. 예를 들어, <code>export const someData = ...</code>  (<code>/path/to/file.js</code> ) 이와 같이 <code>upToYou</code> 에 액세스 할 수 있습니다: <code>upToYou.someData</code> .</p>
<h3 id="classes"><strong>Classes</strong></h3>
<p>Classes는 constructor 함수와 prototypes를 대체하는 기능입니다. 자바스크립트 객체에 blueprints를 정의할 수 있습니다.</p>
<p>예시:</p>
<pre><code class="language-jsx">
class Person {
     constructor () {
         this.name = &#39;Max&#39;;
     }
 }
  
 const person = new Person();
 console.log(person.name); // prints &#39;Max&#39;</code></pre>
<p>위의 예시에서, class뿐 만 아니라 해당 class의 property (=&gt; <code>name</code>) 이 정의됩니다. 해당 구문은, property를 정의하는 &quot;구식&quot; 구문입니다. 최신 자바스크립트 프로젝트에서는 (이 코스에서 사용된 것처럼), 다음과 같은 보다 편리한 정의 방법을 사용해 class property를 정의합니다:</p>
<pre><code class="language-jsx">
class Person {
     name = &#39;Max&#39;;
 }
  
 const person = new Person();
 console.log(person.name); // prints &#39;Max&#39;</code></pre>
<p>메소드를 정의할 수도 있습니다. 다음과 같이 말이죠:</p>
<pre><code class="language-jsx">
 class Person {
     name = &#39;Max&#39;;
     printMyName () {
         console.log(this.name); // this is required to refer to the class!
     }
 }
  
 const person = new Person();
 person.printMyName();</code></pre>
<p>혹은 이와 같이 할 수도 있습니다:</p>
<pre><code class="language-jsx">
 class Person {
     name = &#39;Max&#39;;
     printMyName = () =&gt; {
         console.log(this.name);
     }
 }
  
 const person = new Person();
 person.printMyName();</code></pre>
<p>두 번째 접근 방식은 all arrow function과 같은 이점이 있습니다: <code>this</code>키워드가 reference를 변경하지 않습니다.</p>
<p>class 사용시 <strong>inheritance</strong>를 사용할 수도 있습니다.</p>
<pre><code class="language-jsx">
 class Human {
     species = &#39;human&#39;;
 }
  
 class Person extends Human {
     name = &#39;Max&#39;;
     printMyName = () =&gt; {
         console.log(this.name);
     }
 }
  
 const person = new Person();
 person.printMyName();
 console.log(person.species); // prints &#39;human&#39;</code></pre>
<h3 id="spread--rest-operator"><strong>Spread &amp; Rest Operator</strong></h3>
<p>Spread 와 rest operator는 사실 같은 구문을 사용합니다: <code>...</code></p>
<p>맞습니다, 연산자입니다 - 점 세개죠. 이것을 사용해 spread로 사용할지 rest operator로 사용할지 결정합니다.</p>
<p><strong>Spread Operator 사용하기:</strong></p>
<p>Spread operator는 배열에서 요소들을 가져오거나 (=&gt; 배열을 요소들의 리스트로 분해) 객체에서 속성을 가져옵니다.</p>
<p>두 가지 예시가 있습니다:</p>
<pre><code class="language-jsx">
 const oldArray = [1, 2, 3];
 const newArray = [...oldArray, 4, 5]; // This now is [1, 2, 3, 4, 5];</code></pre>
<p>객체에 spread operator를 사용한 예시입니다:</p>
<pre><code class="language-jsx">
 const oldObject = {
     name: &#39;Max&#39;
 };
 const newObject = {
     ...oldObject,
     age: 28
 };</code></pre>
<p>그러면 <code>newObject</code>는 다음이 될 것입니다.</p>
<pre><code class="language-jsx">
 {
     name: &#39;Max&#39;,
     age: 28
 }</code></pre>
<p>sperad operator는 <strong>배열과 객체를 복제하는데 매우 유용</strong>합니다. 둘 다  <a href="https://youtu.be/9ooYYRLdg_g">(primitives가 아닌) reference 유형</a>이기 때문에, 안정적으로 복사를 하는게 어려울 수 있습니다. (복사된 원본에 future mutation 발생 방지). Spread operator로, 객체나 배열의 <strong>복사본</strong> (shallow!)을 쉽게 얻을 수 있습니다.</p>
<h3 id="destructuring"><strong>Destructuring</strong></h3>
<p>Destructuring을 사용하면 배열이나 객체의 값에 쉽게 엑세스할 수 있고 변수에 할당할 수 있습니다.</p>
<p>한 배열의 예시입니다:</p>
<pre><code class="language-jsx">
 const array = [1, 2, 3];
 const [a, b] = array;
 console.log(a); // prints 1
 console.log(b); // prints 2
 console.log(array); // prints [1, 2, 3]</code></pre>
<p>다음은 객체의 예시입니다:</p>
<pre><code class="language-jsx">
 const myObj = {
     name: &#39;Max&#39;,
     age: 28
 }
 const {name} = myObj;
 console.log(name); // prints &#39;Max&#39;
 console.log(age); // prints undefined
 console.log(myObj); // prints {name: &#39;Max&#39;, age: 28}</code></pre>
<p>Destructuring은 인자를 가진 함수를 작업할 때 매우 유용합니다. 이 예시를 보시죠:</p>
<pre><code class="language-jsx">
 const printName = (personObj) =&gt; {
     console.log(personObj.name);
 }
 printName({name: &#39;Max&#39;, age: 28}); // prints &#39;Max&#39;</code></pre>
<p>여기서, 함수내 name만을 print하고 싶지만 함수에 완전한 person 객체를 보내고 있습니다. 당연히 이것은 문제가 되지 않지만 personObj.name을 이 함수내에서 호출해야만 합니다. 이 코드를 destructuring으로 압축시켜 보겠습니다.</p>
<pre><code class="language-jsx">
 const printName = ({name}) =&gt; {
     console.log(name);
 }
 printName({name: &#39;Max&#39;, age: 28}); // prints &#39;Max&#39;)</code></pre>
<p>위와 동일한 결과를 얻지만 코드가 줄었습니다. Destructuring을 통해, <code>name</code> property를 가져와 <code>name</code> 이라는 이름의 변수/인수에 저장하고 함수 본문에서 사용할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Solidity] ERC-20]]></title>
            <link>https://velog.io/@dodo_velog/Solidity-ERC-20</link>
            <guid>https://velog.io/@dodo_velog/Solidity-ERC-20</guid>
            <pubDate>Mon, 22 May 2023 04:23:40 GMT</pubDate>
            <description><![CDATA[<p>오늘 순서
(1) ERC-20 transfer 구현
(2) ERC-30 trasnferFrom, Approved 구현
(3) WETH</p>
<p>9개의 method
2개의 event</p>
<p>정의 - event, 실행 - emit</p>
<pre><code>// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

contract Token {
    // 대부분 사용하는 dataType = mapping임

    //9개의 method
    // 1. name(&quot;Wrapped Ether&quot;) = getValue 형식
    // 2. symbol(&quot;WETH&quot;) = getValue
    // 3. decimals(18) // 자릿수
    // 4. totalSupply // 지금까지 얼마나 토큰이 발행되었는가
    // 5. balaceOf()  // 계정마다 얼마나 토큰을 갖고 있는지 input address -&gt; output uint
    // 6. transfer() // 보내는 사람은 무조건 나, 내가 남한테 얼마큼 보낼 것이다 **(중요) 내 토큰 얼마나 전송했어
    // 7. transferFrom() // 대리인이 내 코인을 전송하는 기능, 권한을 주면 유니스왑에서 내 토큰을 알아서 가져가는 것
    // 8. approve() // 권한을 주는 함수 ** (중요)
    // 9. allowance() // 얼마큼 위임되어있냐, 누구에게 얼마큼 권한이 있는지 확인 input: owner, Spender(사용할 사람) -&gt; output amount(uint)


    // name symbol decimals 어떻게 저장되어야 할까?
    // mapping타입의 balances 변수 , 특정 유저가 얼마만큼의 토큰을 보유하고 있는가


    // function name() public view returns (string memory) {
    //     return  &quot;doyeon Token&quot;;
    // } 변수 선언과 같은 의미

    string public name = &quot;doyeon Token&quot;;
    string public symbol = &quot;DYT&quot;;
    uint public decimals = 18;
    uint public totalSupply = 0; //민팅된게 없음

    mapping(address owner =&gt; uint amount) public balances; // key는 주소, value는 갖고있는 토큰의 amount    
    mapping(address owner =&gt; mapping(address spender =&gt; uint amount)) public allowances; 
    //allowances[myEOA][uniswap Pair] = 1000;

    // 이벤트 선언, indexed 하면 더 빨라짐!! value = amount
    event Transfer(address indexed _from, address indexed _to, uint _amout); // transfer(), transferFrom() 에서 emit
    event Approval(address indexed _owner, address indexed _spender, uint _value); //approve() 에서 emit



    // 지갑 안에 토큰이 있는게 아닌가? 
    // 우리 account에는 논스 밸런스 스토리지 코드해시만 있는데, 토큰을 홀딩하고있는 정보는 다른 컨트랙에 있음
    // 컨트랙트 주소에는 스토리지가 있음, [stroage] balances[dokite.eth] = 100; 
    // 느낌상 내 지갑에서 나가는 것 같지만, 나와 상관 없는 컨트랙에서 숫자가 빠져나갈 뿐인 것 ???? 이해가 안 감



    // transfer의 실행 주체는 owner다 : address owner = msg.sender;
    function transfer(address _to, uint _value) public returns (bool success) {
        address owner = msg.sender;
        // 발생하지 말아야 할 예외처리
        // 1. 잔고보다 더 많이 보내려 한다면? : 이 사람이 갖고있는 토큰 개수가 보내려는 토큰보다 많은가? - require 사용
        require( balances[owner] &gt;= _value);
        // 2. 실제 전송: 내 잔액에서 (-) , 받는 사람 잔액 (+)
        balances[owner] -= _value;
        balances[_to] += _value;

        // Transfer Event Emit 실행
        emit Transfer(owner, _to, _value);

        // return true 끝
        return true;



        // **만약**
        // 100개를 전송한다 할때 , 90개는 전송하고 10개는 내가 갖도록 구현(커뮤니티에 주도록)한다면??
        // address feeAccount = 0x ; // 커뮤니티 주소
        // address owner = msg.sender;
        // require( balances[owner] &gt;= _value);
        // balances[owner] -= _value;

        // uint fee = amount / 10;
        // uint amountWithoutFee = amount - fee;

        // balance[feeAccount] += fee;
        // balance[to] += amountWithoutFee;

        // emit Transfer(owner, _to, _value);
        // return true;


    }

    // transferFrom의 실행 주체는 owner가 아닌 spender(uniswap의 weth/pepe exchange(pair) 이 토큰들을 스왑하는 컨트랙트, 
    // exchange의 동작 방식, 유저가 유니스왑 컨트랙트에 스왑하고싶다고 어떤 함수 호츨, 
    // 이 토큰을 직접 보내는게 아닌, 유니스왑 컨트랙이 가져갈 수 있도록 권한을 주는 거임 -&gt; 유니스왑이 transferFrom을 실행함

    // 실행 주체 : sender
    function transferFrom(
        address _from,  // 내 eoa 계정(owner)
        address _to,   // exchange 
        uint _value   // amount
        ) public returns (bool success) {
            // 발생하지 말아야할 예외처리
            // 1. spender에게 권한이 있는가 = owner가 spender한테 권한을 줬는가? = 할당받은 양이 보내려는 amount보다 많아야 한다, 
            require(allowances[_from][_to] &gt;= _value); // spender = msg.sender임, owner가 spender에게 할당한 양이 _value보다 많은가, msg.sender가 함수 실행 주체?? 
            // 2. owner(from)의 잔액이 충분한가? 
            require(balances[_from] &gt;= _value); 

            // 데이터 업데이트
            // 1. 잔고 업데이트 from(-) to(+)
            balances[_from] -= _value;
            balances[_to] += _value;
            // 2. allowances양 변경 - 1000개 권한중 200 개 쓰면 800권한이 남았다
            allowances[_from][_to] -= _value;

            // Event Emit
            emit Transfer(_from, _to, _value);

            // return true
            return true;
    }


    // approve는 언제 씀?
    // 스왑할때 
    // 1. 내 토큰을 eth로 바꿀때, approved -&gt; max값 넣고 next -&gt; approved 완 - uniswap 디앱은 pepe토큰의 approve 함수를 호출한다
    // 2. 유니스왑의 컨트랙트가 pepe의 transferFrom을 호츨해서 내 거에서 pepe를 가져감

    // 실행 주체 : owner
    function approve(
        address _to,
        uint _value
    ) public returns (bool success) {
        address owner = msg.sender;
        allowances[owner][_to] = _value;

        emit Approval(owner, _to, _value);

        return true;
    }

    function balanceOf(
        address _owner
    ) public view returns (uint balance) {
        return balances[_owner];
    }

    function allowance(
        address _owner,
        address _spender
    ) public view returns(uint remaining){
        return allowances[_owner][_spender];
    }


    // WETH - wrapped ether는 왜 나왔는가?  erc-20 + deposit, withdraw
    // deposit 이더리움을 넣으면 민팅한다 - balance오름,이벤트 발생, total supply늘어남
    // withdraw 

    // 이더를 보낸다 address.transfer 뿐
    // erc 20 에서는 contract.transfer, contract.transferFrom

    // ether to token
    // 기본적으로 이더를 받아야하고
    function deposit() public payable returns (bool success) {

        // msg.value = 내가 바꾸고 싶은 값
        // msg.sender = 바꾸는 주체, 토큰을 받을 주체
        uint amount = msg.value;
        address owner = msg.sender;

        // 0.5ETH를 넣으면 0.5WETH를 발행(민팅)
        // 1. 잔액 변경
        balances[owner] += amount; 
        // 2. totalSupply 조정
        totalSupply += amount;
        // 3. 이벤트 발생
        emit Transfer(address(0), owner, amount);
        // 4. Vault Balance 0.5ETH  

        return true;
    }


    // token to ether
    // 특정 개수의 수량으로 이더를 출금하는 함수
    function withdraw(uint amount) public returns (bool success) {

        // amount WETH -&gt; ETH로 바꿈
        // owner의 밸런스가 amount보다 많은가? 
        address owner = msg.sender;
        require(balances[owner] &gt;= amount);
        // 1. WETH를 받는다 = balances 감소됨
            // 선택의 문제
            // WETH를 소각한다는 관점 - owner의 balance를 줄인다 = totalSupply를 줄인다
            // WETH의 소유자를 컨트랙트로 바꾸는 관점 - weth의 소유자를 컨트랙트 자기 자신(address(this))으로 바꾼다, totalSupply는 바뀌지 않음?????
        balances[owner] -= amount;
        // 2. totalSupply 발행량 조절
        totalSupply -= amount;
        // 3. transfer이벤트 발생
        emit Transfer(owner,address(0), amount);
        // 4. ETH 출금 : payable(msg.sender).transfer()
        payable(owner).transfer(amount);
        // 5. return true
        return true;

    }


//ERC-721 구현해보기***
//ERC-1155 코드 보기


}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Solidity] Counter contract 예시]]></title>
            <link>https://velog.io/@dodo_velog/Solidity-Counter-contract-%EC%98%88%EC%8B%9C</link>
            <guid>https://velog.io/@dodo_velog/Solidity-Counter-contract-%EC%98%88%EC%8B%9C</guid>
            <pubDate>Sat, 13 May 2023 12:47:27 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-sol">// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

contract Counter{
    // 1이더를 내면 숫자를 올릴 수 있는 로직
    // 트랜잭션을 최초로 만든 EOA는 리셋하고 출금할 수 있다

    // 1. DATA
    //  * value :  private
    //  * owner - 계정주 : public
    // 2. ACIIONS
    //  * getValue : public 사람들이 온체인에서 데이터를 가져올 수 있도록
    //  * increment - 돈을 내야함, 숫자를 올린 기록 : 상태 변경 함수, 이더를 내면 모두가 호출할 수 있음, 데이터 + payment 둘 다 필요 : public, payable
    //  * reset - value = 0, 리셋했다는 기록, owner만 실행할 수 있는 함수 - 제약조건이 까다로운 누구나 호출할 수 있는 함수 : public, but owner만 호출 가능
        // 컨트랙트를 최초로 만든 사람, 계정주를 알아야 함
        // 컨트랙트의 주인이라는 걸 컨트랙트로 구현필요,
    //  * withdraw - 출금 : public, owner만 호출 가능, private으로 하면 아무도 실행할 수 없게 됨

    // internal external public private 차이

    // 스토리지 저장은 비싸기 때문에 로그에 저장한다
    // 3. EVENTS
    //  * Reset기록을 한 번에 조회할 수 있게 함

    //  함수 종류
    //     view - storage를 읽기만 하고 변경은 안 함
    //     pure - storage를 아예 읽지 않는 함수, 연산, 스토리지와 관련 없음을 의미
    //     constant - 상수를 리턴, 
    //     payable - 함수의 동작 결정, 이더를 받는다~

    // 상태를 변경하는 것 =  view는 아님
    // payable - 받을 수 있다 ㅇ, 받아야 한다 x

    // 이더리움 account 구성
    // address = 0x1, 0x2, ...
    // account =  {nonce, balance, storageRoot, codeHash} 코드 해시가 비어있으면 EOA 있으면 CA

    // 1) global variable : msg(컨트랙트가 컨트랙트를 호출, eoa가 컨트랙트를 호출, .. ) msg.sender(owner가 됨), msg.value(메세지가 담고있는 이더의 양)
    // 2) Error : assert, revert, require (많이 씀)

    // 이더를 전송하는 방법 : address.transfer, address.send, address.call
    // transfer는 오류 생길시 transaction revert
    // send -???
    // call = 함수 실행, {gas: , value: }식으로

    uint private value = 0;
    address public owner;

    // constructor : 컨트랙트 생성시 딱 한 번만 수행됨, 여기서 owner를 지정한다
    constructor() {
        // 이게 생성될 떄 메세지를 보낸 사람 = owner가 됨
        owner = msg.sender; // 이 트랜잭션 매세지를 최초로 서명하기 위한 계정
    }

    modifier onlyOwner() {
        require(msg.sender == owner, &quot;only owner!&quot;);
        _;
    }

    event Reset(address owner, uint currentValue); 

    function getValue() public view returns (uint) {
        return value;
    }

    function increment() public payable { 
        require(msg.value == 1 ether, &quot;1 Ether&quot;); //1 이더일때만 실행 , 에러메세지
        value = value + 1;
    }

    function reset() public onlyOwner {
        emit Reset(msg.sender, value); // 이벤트 로그 보기
        value = 0;
    }

    function withdraw() public onlyOwner {
        // address -&gt; payable address로 변경, 현재 밸런스 값의 이더를 보낸다
        // address(this) 컨트랙트의 주소
        payable(owner).transfer(address(this).balance);
    }


// 트랜잭션 receipt = 트랜잭션 로그가 인코딩 되어 들어


}</code></pre>
<ol>
<li>Data</li>
</ol>
<ul>
<li>단일 값 Single </li>
<li>여러 값 Multiple - mapping,array</li>
<li>복잡한 자료구조 Complex - struct</li>
</ul>
<ol start="2">
<li>Actions</li>
</ol>
<ul>
<li>조건문, 반복문</li>
<li>함수</li>
<li>에러, 예외처리</li>
<li>이벤트(=로그)</li>
<li>modifier, library, contract 상속</li>
</ul>
<p>이더리움에서 데이터 저장하는 방식</p>
<ol>
<li>stroage에 저장 - 컨트랙트 변수 선언하는 경우</li>
<li>로그</li>
</ol>
<p>dune - 온체인 데이터 플랫폼</p>
<p>TX - 트랜잭션</p>
<p>  1) invocation
      트랜잭션을 생성하는 데 데이터가 있는 것
    보통의 함수 호출
  2) payment
    이더 전송, 데이터는 없고 pay만 함</p>
<p>   둘 다 있는 예시 - 민팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] 아이콘 쓰기]]></title>
            <link>https://velog.io/@dodo_velog/React-Native-%EC%95%84%EC%9D%B4%EC%BD%98-%EC%93%B0%EA%B8%B0</link>
            <guid>https://velog.io/@dodo_velog/React-Native-%EC%95%84%EC%9D%B4%EC%BD%98-%EC%93%B0%EA%B8%B0</guid>
            <pubDate>Sun, 12 Mar 2023 16:37:29 GMT</pubDate>
            <description><![CDATA[<p>✔️<code>expo init</code> 으로 프로젝트 만들었을때 방법임</p>
<p><a href="https://icons.expo.fyi/">아이콘 모음 링크</a>
<img src="https://velog.velcdn.com/images/dodo_velog/post/6c76e3bc-a9da-4bc7-820a-de2d7e4821a5/image.png" alt="사용 예시"></p>
<p><strong>아이콘 이름 설정</strong>
API로 불러온 날씨 상태 : 이름(아이콘 실제 이름)</p>
<pre><code class="language-js">const icons = {
  Clouds: &#39;cloudy&#39;,
  Clear: &#39;day-sunny&#39;,
  Snow: &#39;snow&#39;,
  Rain: &#39;rains&#39;,
  Drizzle: &#39;rain&#39;,
  Thunderstorm: &#39;lightning&#39;
}</code></pre>
<p><strong>UI에 적용하기</strong>
&lt;Fontisto~ /&gt; : 사이트에서 복붙해온 부분, name 수정한다</p>
<pre><code class="language-js">&lt;View style={{flexDirection:&#39;row&#39;, alignItems:&#39;center&#39;, width: &#39;100%&#39;,justifyContent:&#39;space-between&#39;}}&gt;
                &lt;Text style={styles.temp}&gt;Temp&lt;/Text&gt;
                &lt;Fontisto name={icons[days.weather[0].main]} size={24} color=&#39;white&#39; /&gt; 
&lt;/View&gt;</code></pre>
<p>쏘간단..!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] CSS]]></title>
            <link>https://velog.io/@dodo_velog/React-CSS</link>
            <guid>https://velog.io/@dodo_velog/React-CSS</guid>
            <pubDate>Sat, 11 Mar 2023 15:57:40 GMT</pubDate>
            <description><![CDATA[<h3 id="1-일반-css">1. 일반 CSS</h3>
<pre><code class="language-javascript">import &#39;./App.css&#39;;</code></pre>
<blockquote>
<p>✔️ CSS Selector :  CSS 클래스가 특정 클래스 내부에 있는 경우에만 사용</p>
</blockquote>
<pre><code class="language-css">.App .logo {
  animation: App-logo-spin infinite 20s linear;
  height: 40vmin;
}</code></pre>
<h3 id="2-css-module">2. CSS Module</h3>
<p>src 폴더에  [파일 이름].module.css 파일 생성</p>
<pre><code class="language-css">.wrapper {
    background: black;
    padding: 1rem;
    color: white;
    font-size: 2rem;
}

.inverted {
    color: black;
    background: white;
    border: 1px solid black;
}

/* 전역으로 선언한 클래스 */
:global .something {
    font-weight: 800;
    color: aqua;
}</code></pre>
<blockquote>
<p>✔️ 두 단위 모두 기준에 따라 값이 유동적으로 바뀐다.
<code>em</code> : 해당 단위가 사용되고 있는 요소의 font-size 속성 값이 기준
<code>rem</code> : r은 root, 즉 최상위 요소의 font-size 속성 값이 기준</p>
</blockquote>
<ul>
<li>클래스 두 개 이상 넣고싶을 때 : <strong>백틱 + $ 사용</strong><pre><code class="language-javascript">import React from &#39;react&#39;;
import styles from &#39;./CSSModule.module.css&#39;;
</code></pre>
</li>
</ul>
<p>const CSSModule = () =&gt; {
    return (
        &lt;div className={<code>${styles.wrapper} ${styles.inverted}</code>}&gt;
            안녕하세요, 저는 <span className='something'>CSS MODULE!</span>
        </div>
    );
};</p>
<p>export default CSSModule;</p>
<pre><code>
&lt;br/&gt;


### 3. styled-components
자바스크립트 파일 안에 스타일을 선언한다. 
_**yarn add styled-components**_
``` js
import React from &quot;react&quot;;
import styled, {css} from &#39;styled-components&#39;;

const Box = styled.div`
// props로 넣어준 값을 직접 전달하는 부분
background: ${props =&gt; props.color || &#39;blue&#39;};
padding: 1rem;
display: flex;
`;

const Button = styled.button`
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;

&amp;:hover {
    background: rgba(255,255,255,0.9);
}

${ props =&gt;
    props.inverted &amp;&amp;
    css`
    background: none;
    border: 2px solid white;
    color: white;
    &amp;:hover {
        background: white;
        color: black;
    }
    `};
    &amp; + button {
        margin-left: 1rem;
    }
`;

const StyledComponent = () =&gt; (
    // props 전달
    &lt;Box color=&quot;black&quot;&gt; 
        &lt;Button&gt;안녕하세요&lt;/Button&gt;
        &lt;Button inverted={true}&gt;테두리만&lt;/Button&gt;
    &lt;/Box&gt;
);

export default StyledComponent;</code></pre><ul>
<li><p><code>css</code> 단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정해야 하는 경우에는 css를 불러와야 한다.</p>
</li>
<li><p>tagged 템플릿 리터럴 : 백틱을 사용하고, 템플릿 안에 자바스크립트 객체나 함수를 전달할 때 온전히 추출할 수 있다는 장점이 있음. </p>
</li>
<li><p><code>styled.(태그명)</code>: 스타일링된 엘리먼트 만들때 사용</p>
<blockquote>
<p>태그명이 유동적이거나 특정 컴포넌트 자체에 스타일링 해주고 싶다면 
태그 타입을 함수 인자로 전달 하거나 
<code>const MyInput = styled(&#39;input&#39;)`
background: gray;`</code>
  컴포넌트 형식 값을 넣어줌
<code>const StyledLink = styled(Link)` color: &#39;blue&#39;;`</code></p>
</blockquote>
</li>
<li><p>&amp;를 사용해 자기 자신 선택</p>
</li>
</ul>
<br/>


<h4 id="media-쿼리를-사용하여-반응형-구현하기"><strong>media 쿼리를 사용하여 반응형 구현하기</strong></h4>
<pre><code class="language-js">const Box = styled.div`
background: ${props =&gt; props.color || &#39;blue&#39;};
padding: 1rem;
display: flex;
width: 1024px;
margin: 0 auto;
@media (max-width: 1024px){
    width: 768px;
}
@media (max-width: 768px){
    width: 100%;
}
`;</code></pre>
<p>기본적으로 가로 길이 1024px에 가운데 정렬을 하고, 가로 크기가 작아짐에 따라 크기를 줄이고 768미만이 되면 꽉채운다. </p>
<br/>

<p>요약</p>
<blockquote>
<p><code>일반 CSS</code> : 컴포넌트를 스타일링하는 가장 기본적인 방식
<code>Sass</code>: CSS 전처리기 중 하나. 확장된 CSS 문법을 사용하여 CSS 코드를 더욱 쉽게 작성할 수 있도록 해 줌
<code>CSS Module</code>: 파일마다 고유한 이름을 자동으로 생성해주는 옵션. 스타일 작성시 클래스 이름의 충돌을 방지함
<code>styled-components</code>: 스타일을 자바스크립트 파일에 내장시키는 방식으로 작성. 해당 스타일이 적용된 컴포넌트를 만들 수 있게 함</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[1436.py] 영화감독 숌]]></title>
            <link>https://velog.io/@dodo_velog/1436.py-%EC%98%81%ED%99%94%EA%B0%90%EB%8F%85-%EC%88%8C</link>
            <guid>https://velog.io/@dodo_velog/1436.py-%EC%98%81%ED%99%94%EA%B0%90%EB%8F%85-%EC%88%8C</guid>
            <pubDate>Thu, 09 Mar 2023 09:15:27 GMT</pubDate>
            <description><![CDATA[<p><strong>문제</strong>
666은 종말을 나타내는 수라고 한다. 따라서, 많은 블록버스터 영화에서는 666이 들어간 제목을 많이 사용한다. 영화감독 숌은 세상의 종말 이라는 시리즈 영화의 감독이다. 조지 루카스는 스타워즈를 만들 때, 스타워즈 1, 스타워즈 2, 스타워즈 3, 스타워즈 4, 스타워즈 5, 스타워즈 6과 같이 이름을 지었고, 피터 잭슨은 반지의 제왕을 만들 때, 반지의 제왕 1, 반지의 제왕 2, 반지의 제왕 3과 같이 영화 제목을 지었다. 하지만 숌은 자신이 조지 루카스와 피터 잭슨을 뛰어넘는다는 것을 보여주기 위해서 영화 제목을 좀 다르게 만들기로 했다.</p>
<p>종말의 수란 어떤 수에 6이 적어도 3개 이상 연속으로 들어가는 수를 말한다. 제일 작은 종말의 수는 666이고, 그 다음으로 큰 수는 1666, 2666, 3666, .... 이다. 따라서, 숌은 첫 번째 영화의 제목은 &quot;세상의 종말 666&quot;, 두 번째 영화의 제목은 &quot;세상의 종말 1666&quot;와 같이 이름을 지을 것이다. 일반화해서 생각하면, N번째 영화의 제목은 세상의 종말 (N번째로 작은 종말의 수) 와 같다.</p>
<p>숌이 만든 N번째 영화의 제목에 들어간 수를 출력하는 프로그램을 작성하시오. 숌은 이 시리즈를 항상 차례대로 만들고, 다른 영화는 만들지 않는다.</p>
<p><strong>입력</strong>
첫째 줄에 N이 주어진다. N은 10,000보다 작거나 같은 자연수이다.</p>
<p><strong>출력</strong>
첫째 줄에 N번째 영화의 제목에 들어간 수를 출력한다.</p>
<p><strong>내 코드</strong></p>
<pre><code>N = int(input())
idx = 0  # N번째 영화 = 인덱스를 떠올리자
num = 666

# 666 에서 1씩 더한다 - 666이 포함되면 cnt
while True:
     # 666부터 1씩 올리면서 666이 적어도 하나 포함되어있으면 인덱스 ++
    if &#39;666&#39; in str(num): 
        idx += 1
    if idx == N:
        print(num)
        break
    num += 1</code></pre><ul>
<li>브루트포스는 1부터 모든 숫자를 대입해보면서 답을 찾는 것</li>
<li>인덱스를 어떻게 셀까? -&gt; 리스트 만들뻔..</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] CSS 적용하는 법]]></title>
            <link>https://velog.io/@dodo_velog/React-Native-CSS-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@dodo_velog/React-Native-CSS-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Thu, 09 Mar 2023 08:46:10 GMT</pubDate>
            <description><![CDATA[<h3 id="1-stylesheet의-객체를-만들어-코드를-작성한다">1. StyleSheet의 객체를 만들어 코드를 작성한다.</h3>
<pre><code>import React from &quot;react&quot;;
import { View, StyleSheet, Text } from &quot;react-native&quot;;

export default function App() {
  return &lt;View style={styles.container}&gt;
    &lt;View style={styles.city}&gt;
      &lt;Text style={styles.cityName}&gt;Seoul&lt;/Text&gt;
    &lt;/View&gt;
    &lt;View style={styles.weather}&gt;
      &lt;View style={styles.day}&gt;
        &lt;Text style={styles.temp}&gt;27&lt;/Text&gt;
        &lt;Text style={styles.description}&gt;Sunny&lt;/Text&gt;
      &lt;/View&gt;
    &lt;/View&gt;
  &lt;/View&gt;
};


const styles = StyleSheet.create({
  container: {
    flex:1,
    backgroundColor: &quot;tomato&quot;,
  },
  city :{
    flex: 1,
    // backgroundColor: &#39;blue&#39;,
    justifyContent: &quot;center&quot;,
    alignItems: &quot;center&quot;,
  },
  cityName: {
    color: &quot;black&quot;,
    fontSize: 68,
    fontWeight: 500
  },
  weather: {
    flex: 3,
  },
  day: {
    flex: 1,
    // justifyContent: &quot;center&quot;,
    alignItems:&quot;center&quot;,
    // backgroundColor: &quot;teal&quot;,
  },
  temp: {
    marginTop: 50,
    fontSize: 178,
  },
  description:{
    fontSize: 60,
  }
})</code></pre><ul>
<li>StyleSheet 객체를 만들어 사용하면 코드 훨 깔끔</li>
<li>StyleSheet import 해야함</li>
</ul>
<h3 id="2-필요한-props-api를-가져다-쓴다">2. 필요한 props, API를 가져다 쓴다.</h3>
<p><a href="https://reactnative.dev/docs/scrollview#showshorizontalscrollindicator">reactnative.dev</a></p>
<pre><code>import React from &quot;react&quot;;
import { View, StyleSheet, Text, ScrollView, Dimensions } from &quot;react-native&quot;;

// const { width: SCREEN_WIDTH } = Dimensions.get(&#39;window&#39;);
const SCREEN_WIDTH = Dimensions.get(&#39;window&#39;). width;


export default function App() {
  return &lt;View style={styles.container}&gt;
    &lt;View style={styles.city}&gt;
      &lt;Text style={styles.cityName}&gt;Seoul&lt;/Text&gt;
    &lt;/View&gt;
    {/* ScrollView에서도 필요한 props 갖다 쓰기 */}
    &lt;ScrollView 
      horizontal 
      pagingEnabled 
      showsHorizontalScrollIndicator = {false}
      style={styles.weather}&gt;
      &lt;View style={styles.day}&gt;
        &lt;Text style={styles.temp}&gt;27&lt;/Text&gt;
        &lt;Text style={styles.description}&gt;Sunny&lt;/Text&gt;
        &lt;/View&gt;
      &lt;View style={styles.day}&gt;
        &lt;Text style={styles.temp}&gt;27&lt;/Text&gt;
        &lt;Text style={styles.description}&gt;Sunny&lt;/Text&gt;
        &lt;/View&gt;
      &lt;View style={styles.day}&gt;
        &lt;Text style={styles.temp}&gt;27&lt;/Text&gt;
        &lt;Text style={styles.description}&gt;Sunny&lt;/Text&gt;
        &lt;/View&gt;
      &lt;View style={styles.day}&gt;
        &lt;Text style={styles.temp}&gt;27&lt;/Text&gt;
        &lt;Text style={styles.description}&gt;Sunny&lt;/Text&gt;
        &lt;/View&gt;
    &lt;/ScrollView&gt;
  &lt;/View&gt;
};
const styles = StyleSheet.create({
  container: {
    flex:1,
    backgroundColor: &quot;tomato&quot;,
  },
  city :{
    flex: 1,
    // backgroundColor: &#39;blue&#39;,
    justifyContent: &quot;center&quot;,
    alignItems: &quot;center&quot;,
  },
  cityName: {
    color: &quot;black&quot;,
    fontSize: 68,
    fontWeight: 500
  },
  weather: {
    // flex: 3, #스크롤뷰는 flex를 없애야 화면을 넘어 더 큰 사이즈 구현 가능
  },
  day: {
    // flex: 1, 
    width: SCREEN_WIDTH, 
    alignItems:&quot;center&quot;,
  },
  temp: {
    marginTop: 50,
    fontSize: 178,
  },
  description:{
    fontSize: 60,
  }
})</code></pre><ul>
<li>기기 화면 크기를 알려주는 API : <code>Dimensions</code></li>
<li>view는 스크롤할 수 없다. <code>ScrollView</code> 사용!</li>
<li>운영체제에 따라 작동 되지 않은 props도 있을 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Native] Introduction]]></title>
            <link>https://velog.io/@dodo_velog/React-Native</link>
            <guid>https://velog.io/@dodo_velog/React-Native</guid>
            <pubDate>Wed, 08 Mar 2023 07:47:22 GMT</pubDate>
            <description><![CDATA[<h3 id="react-native">React Native</h3>
<p>리액트 네이티브는 운영체제에 명령을 전달한다. bridge 부분 존재
폰 안에 브라우저가 아니다!</p>
<p>(이미지 찾기)</p>
<p><strong>React Native 구성 요소</strong></p>
<ul>
<li>Native 파트 : ios,안드로이드같은 OS 파트</li>
<li>Bridge 파트</li>
<li>Javascript 파트 </li>
</ul>
<p>각 파트가 유저 행동에 대해 메세지를 주고받는 방식으로 동작 - 브라우저가 없다
자바스크립트는 개발자들이 os와 메세지를 주고받기위한 도구일 뿐
이 전 과정을 위해서 시뮬레이터, java, xcode가 필요하다.</p>
<p><strong>react native 특징</strong></p>
<ol>
<li><code>&lt;View&gt;</code> = 컨테이너 = <code>&lt;div&gt;</code></li>
<li>모든 text는 text component <code>&lt;Text&gt;</code> 에 넣어야한다.</li>
<li>일부 style은 사용할 수 없다 - border</li>
<li>StyleSheet, Text, View는 import 해야한다.</li>
</ol>
<p>const styles = Stylesheet.create = {} (자동완성 기능 있음)
리액트에서 하듯이 style = {{~~}}로 따로 쓸 수 있긴 함, 길어지면 미관상 안 좋으니까 따로 쓰는게 좋을 듯 </p>
<blockquote>
<p>✅ 컴포넌트와 API 차이
    <code>컴포넌트</code> - 화면에 렌더링할 항목, return 안에 있음
    <code>API</code> - 자바스크립트 코드, 운영체제와 소통하는 부분, onPress 내용 같은 </p>
</blockquote>
<h3 id="third-party">Third Party</h3>
<p>리액트 네이티브 컴포넌트 자체가 많이 간소화 되었음(asyncstorage, navigation등 없어짐)
<strong>reactivenative.directory</strong>에서 필요한 api나 써드파티 사용함
단점은 커뮤니티에 의존해야 하고 버그가 생겼을 때 기다리거나 직접 고쳐야 함
or <strong>expo 패키지</strong> 쓰자</p>
<h3 id="flexbox">Flexbox</h3>
<pre><code class="language-javascript">import React from &quot;react&quot;;
import { View } from &quot;react-native&quot;;

export default function App() {
  return (
    &lt;View style={{ flex: 1 }}&gt; 
      &lt;View style = {{ flex: 1, backgroundColor: &#39;tomato&#39; }}&gt;&lt;/View&gt; 
      &lt;View style = {{ flex: 1, backgroundColor: &#39;teal&#39;}}&gt;&lt;/View&gt; 
      &lt;View style = {{ flex: 1, backgroundColor: &#39;orange&#39; }}&gt;&lt;/View&gt; 
    &lt;/View&gt;
  );
}</code></pre>
<ul>
<li><p>view는 기본적으로 flex container이다</p>
</li>
<li><p>모바일에서 flexdirection의 기본값은 column이다 (웹에서는 row)</p>
</li>
<li><p>overflow여도 스크롤 불가</p>
</li>
<li><p>&#39;레이아웃&#39;은 width, height로 만들지 말아야함 - 반드시 반응형</p>
</li>
<li><p>이때, 부모에 반드시 flex 속성 넣고, 자식 컴포넌트에 flex:1 (비율로 나타남 1:1:1)</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[10798.py] 세로읽기]]></title>
            <link>https://velog.io/@dodo_velog/10798.py-%EC%84%B8%EB%A1%9C%EC%9D%BD%EA%B8%B0</link>
            <guid>https://velog.io/@dodo_velog/10798.py-%EC%84%B8%EB%A1%9C%EC%9D%BD%EA%B8%B0</guid>
            <pubDate>Tue, 07 Mar 2023 14:16:46 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/10798">10798 문제 링크 </a></p>
<p><strong>문제</strong>
아직 글을 모르는 영석이가 벽에 걸린 칠판에 자석이 붙어있는 글자들을 붙이는 장난감을 가지고 놀고 있다. </p>
<p>이 장난감에 있는 글자들은 영어 대문자 ‘A’부터 ‘Z’, 영어 소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’이다. 영석이는 칠판에 글자들을 수평으로 일렬로 붙여서 단어를 만든다. 다시 그 아래쪽에 글자들을 붙여서 또 다른 단어를 만든다. 이런 식으로 다섯 개의 단어를 만든다. 아래 그림 1은 영석이가 칠판에 붙여 만든 단어들의 예이다. </p>
<p>A A B C D D
a f z z 
0 9 1 2 1
a 8 E W g 6
P 5 h 3 k x
&lt;그림 1&gt;</p>
<p>한 줄의 단어는 글자들을 빈칸 없이 연속으로 나열해서 최대 15개의 글자들로 이루어진다. 또한 만들어진 다섯 개의 단어들의 글자 개수는 서로 다를 수 있다. </p>
<p>심심해진 영석이는 칠판에 만들어진 다섯 개의 단어를 세로로 읽으려 한다. 세로로 읽을 때, 각 단어의 첫 번째 글자들을 위에서 아래로 세로로 읽는다. 다음에 두 번째 글자들을 세로로 읽는다. 이런 식으로 왼쪽에서 오른쪽으로 한 자리씩 이동 하면서 동일한 자리의 글자들을 세로로 읽어 나간다. 위의 그림 1의 다섯 번째 자리를 보면 두 번째 줄의 다섯 번째 자리의 글자는 없다. 이런 경우처럼 세로로 읽을 때 해당 자리의 글자가 없으면, 읽지 않고 그 다음 글자를 계속 읽는다. 그림 1의 다섯 번째 자리를 세로로 읽으면 D1gk로 읽는다. </p>
<p>그림 1에서 영석이가 세로로 읽은 순서대로 글자들을 공백 없이 출력하면 다음과 같다:</p>
<p>Aa0aPAf985Bz1EhCz2W3D1gkD6x</p>
<p>칠판에 붙여진 단어들이 주어질 때, 영석이가 세로로 읽은 순서대로 글자들을 출력하는 프로그램을 작성하시오.</p>
<p><strong>입력</strong>
총 다섯줄의 입력이 주어진다. 각 줄에는 최소 1개, 최대 15개의 글자들이 빈칸 없이 연속으로 주어진다. 주어지는 글자는 영어 대문자 ‘A’부터 ‘Z’, 영어 소문자 ‘a’부터 ‘z’, 숫자 ‘0’부터 ‘9’ 중 하나이다. 각 줄의 시작과 마지막에 빈칸은 없다.</p>
<p><strong>출력</strong>
영석이가 세로로 읽은 순서대로 글자들을 출력한다. 이때, 글자들을 공백 없이 연속해서 출력한다. </p>
<p><strong>내 코드</strong></p>
<pre><code>total = &#39;&#39;
arr = []
length = []

for _ in range(5):
    s = input()
    arr.append(s)
    length.append(len(s))

for i in range(max(length)):
    for j in range(5):
        if i &lt; length[j]:
            total += arr[j][i]

print(total)</code></pre><ul>
<li>split()은 공백 넣으면서 한 줄에 여러 개 입력 받을 때, 그 공백을 제거해서 리스트에 넣기 위해 쓰는 것이다. 여기서는 입력 형식에서 공백 처리는 해줄 필요가 없기 때문에 input()만 사용</li>
<li>문자열의 길이를 문자 개수 대로 세려는데 list에 문자를 다 넣고 len()으로 하니까 1아니면 9나옴([,&#39;,&#39;,] 까지 센듯,,) 암튼 어차피 최대 길이 15밖에 안 되긴 하지만 len 길이를 따로 저장할 length 리스트 생성했다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Binance Academy] DeFi ]]></title>
            <link>https://velog.io/@dodo_velog/Binance-Academy-DeFi</link>
            <guid>https://velog.io/@dodo_velog/Binance-Academy-DeFi</guid>
            <pubDate>Tue, 07 Mar 2023 11:55:08 GMT</pubDate>
            <description><![CDATA[<h3 id="defi-란">DeFi 란?</h3>
<p>블록체인 네트워크에 구축된 오픈소스, 무허가형 및 투명한 금융 애플리케이션 생태계
모든 사람이 사용할 수 있고 중앙 권한 없이 작동한다. 사용자가 자산에 대한 완전한 통제권을 가지고 P2P, DApps를 통해 상호작용한다. </p>
<p><strong>DeFi의 이점</strong></p>
<ul>
<li>중개자가 필요 없고 코드를 통해 모든 분쟁의 해결 방법을 지정한다. 이러한 자동화는 제품을 제공하고 사용하는 것과 관련된 비용을 줄이고 마찰을 줄일 수 있다.</li>
<li>데이터는 블록체인에 기록되고 수천 개의 노드에 분산되므로 검열이나 잠재적인 서비스 종료로부터 안전하다. </li>
<li>금융 서비스에 접근할 수 없는 사람들도 쉽게 접근 가능하도록 한다. 전통적인 금융 시스템은 수익을 창출하는 중개자에 의존하기 때문에 일반적으로 저소득 커뮤니티 지역에서는 서비스를 받기가 힘들다. 그러나 DeFi를 사용하면 비용이 크게 절감되고 저소득 개인도 더 광범위한 금융 혜택을 누릴 수 있다. </li>
</ul>
<p><strong>DeFi의 잠재적 사용 사례</strong></p>
<ol>
<li><p>차용 및 대출
개방적이고 분산된 차용 및 대출은 전통적인 신용 시스템에 비해 더 많은 이점을 가질 수 있다. 예를 들면 즉각적인 거래 정산, 신용 확인 없음, 디지털 자산 담보 기능이 있다. 이러한 대출 서비스는 퍼블릭 블록체인에 구축되어 있기 때문에 필요한 신뢰의 양을 최소화 하고 암호화 검증 방법을 보장한다. 블록체인의 거래 시장은 거래상대방 위험을 줄이고 더 많은 사람들이 더 저렴하고 빠르게 대출 서비스를 이용할 수 있도록 한다.</p>
</li>
<li><p>금융 서비스
블록체인 산업이 성숙함에 따라 스테이블 코인을 만드는데 더 많은 관심이 기울고 있다.
<code>스테이블 코인</code> : 쉽게 디지털로 전송할 수 있는 실제 자산에 고정된 암호화 자산
암호화폐 가격이 급격하게 변동할 수 있기 때문에 분산형 스테이블 코인은 중앙 기관에서 발행 및 모니터링 하지 않는 디지털 화폐로 일상적인 사용에 채택될 가능성이 있다.
또는 블록체인 보험은 중개자의 필요성을 없애고 참여자간 위험을 분산시켜 동일한 서비스 품질에 더 낮은 보험료를 가능하게 한다. </p>
</li>
<li><p>탈중앙 거래소
DEX 플랫폼을 통해 사용자는 중개자(거래소) 없이도 디지털 자산을 거래할 수 있다. 거래는 스마트 컨트랙트를 통해 사용자 지갑 간에 직접 이루어진다. AMM으로 알려진 일부 거래소는 유동성 풀을 사용하여 거래를 일치시킬 상대방을 직접 필요로 하지 않고 거래를 용이하게 한다. Uniswap과 Pancake Swap이 대표적인 예시이다. 유지 관리 작업이 덜 필요하기 때문에 거래 수수료가 낮다. </p>
</li>
<li><p>수율 최적화
DeFi DApp은 스테이킹, 보상 풀 및 기타 이자 관련 제품에서 얻은 수익 복합을 자동화하고 최적화하는 데 사용할 수 있다. 예를 들어 비트코인 채굴, BNB 위임 또는 유동성 제공을 통해 정기적인 보상을 받을 수 있다. 스마트 컨트랙트는 보상을 받고 기본 자산을 더 많이 구매하여 재투자 할 수 있다. 이러한 프로세스는 수익을 높일 수 있으며, 시간을 절약하고 복리를 최적화 할 수 있다. </p>
</li>
</ol>
<p>** DeFi 프로젝트 예시**</p>
<p> StaFi는 암호화폐 생태계에서 스태이킹된 자산의 유동성을 해제하는데 도움이 되는 DeFi 프로젝트이다. 사용자는 다양한 PoS(지분 증명) 토큰을 스테이킹하고 교환 및 양도 가능한 rToken을 받을 수 있다. 
<code>rToken</code>: 스태이킹된 PoS 토큰에 고정된 &#39;합성 스테이킹 파생 상품&#39;</p>
<p> StaFi에는 FIS라는 또 다른 고유의 토큰이 있는데, 이 토큰은 StaFi 및 StaFiHub(Cosmos의 교차 체인 스테이킹 파생 플랫폼)의 네트워크 거래 수수료, StaFi, StaFiHub 및 대상 체인 간의 교차 체인 브리지에서의 중개 수수료에 사용될 수 있고, 합의 매커니즘 및 거버넌스에 참여하기 위해 스테이킹 될 수 있다.</p>
<h3 id="defi와-스마트-컨트랙트">DeFi와 스마트 컨트랙트</h3>
<p> DeFi의  기존 및 잠재적 응용 프로그램의 대부분은 스마트 컨트랙트 생성 및 실행과 관련되어있다. 일반적인 계약은 계약을 체결하는 엔티티 간의 관계 조건을 지정하기 위해 법률 용어를 사용하지만 스마트 컨트랙트는 코드로 자동화 되어있다. 
 스마트 컨트랙트를 사용하는 것이 더 빠르고 쉬우며 엔티티 간의 위험을 줄인다. 하지만 코드 상의 버그와 취약점이 있기 때문에 내부 가치와 기밀 정보가 유출될 수 있는 위험도 가지고 있다.</p>
<h3 id="defi-20">DeFi 2.0</h3>
<p>DeFi는 대중에게 금융을 제공하는 것을 목표로 하지만 확장성, 보안, 중앙 집중화, 유동성 및 정보 접근성에 어려움이 있다. DeFi 2.0은 이러한 문제를 해결하고 보다 사용자 친화적인 경험을 만들고자 생겨나는 프로젝트들의 움직임을 의미한다. </p>
<p><strong>기존 DeFi의 한계</strong></p>
<ul>
<li>확장성 : 트래픽과 가스 요금이 높은 블록체인의 DeFi 프로토콜은 느리고 비싼 서비스를 제공한다. 간단한 작업이 오래걸리고 비용이 비효율적인 문제가 있다. </li>
<li>오라클 및 제 3자 정보 : 외부 세부 정보에 의존하는 금융 상품은 더 높은 품질의 오라클(제 3자 데이터 소스)가 필요하다</li>
<li>중앙화 : 탈중앙화의 양을 늘리는 것이 DeFi의 목표이지만 여전히 많은 프로젝트에서 DAO가 없다.</li>
<li>보안 : 대부분의 사용자는 DeFi에 존재하는 위험이나 스마트 컨트랙트에 대해 알지 못한 채로 수백만 달러를 건다. 보안 감사가 시행됨에도 불구하고 가치가 떨어지는 경향이 있다.</li>
<li>유동성 : 시장과 유동성 풀은 다양한 블록체인과 플랫폼에 분산되어 유동성을 나눈다. 대부분의 경유 유동성 풀에 스테이킹된 토큰은 다른 곳에서는 사용할 수 없기 때문에 자본 비효율이 발생한다.</li>
</ul>
<p><strong>DeFi 2.0 이 중요한 이유</strong>
DeFi는 여전히 이해하기 어렵지만 진입 장벽을 낮추고 암호화폐 보유자를 위한 새로운 수익 기회를 창출하는 것을 목표로 한다. 기존 은행에서 대출을 받을 수 없는 사용자는 DeFi를 사용할 수 있다. 금융 민주화를 위해서는 DeFi가 중요하다. DeFi 2.0에서는 위와 같은 문제를 해결하여 사용자 경험을 개선하려는 시도이다. </p>
<p><strong>DeFi 2.0 사용 사례</strong></p>
<ul>
<li>스테이킹된 자금의 가치 잠금 해제
유동성 풀에 토큰 페어를 스테이킹 한 적 있다면 그 대가로 LP 토큰을 받게 된다. DeFi 1.0에서 yield farm에 LP토큰을 스테이킹하여 수익을 발생시켰다면, DeFi 2.0 에서는 LP토큰을 담보로 사용한다. 정확한 메커니즘은 프로젝트에 따라 다르지만, 아이디어는 APY(연간수익률)를 생성하면서 새로운 기회를 위해 LP 토큰의 가치를 잠금 해제해야 한다.
<code>yield farm</code> : 유동성 채굴 이라고도 하는 yield farm은 암호화폐 보유로 보상을 생성하는 방법이다. 간단히 말해서 암호 화폐를 잠그고 보상을 받는 것</li>
</ul>
<p>외에도  스마트 컨트랙트 보험, 영구 손실 보험, 자기 상환 대출 등의 사례가 있음.</p>
<h3 id="유동성-풀이란">유동성 풀이란?</h3>
<p>유동성 풀이란 스마트 컨트랙트에 잠긴 자금 모음을 의미한다. 유동성 풀은 Uniswap 과 같은 많은 탈중앙화 거래소(DEX)의 중추가 된다. LP(유동성 공급자)라고 칭하는 사용자는 시장을 만들기 위해 풀에 두 개의 동일한 가치의 토큰 쌍을 추가한다. 자금을 제공하는 대가로 풀에서 발생하는 거래에서의 거래 수수료를 받는다. </p>
<p>누구나 LP가 될 수 있기 때문에 AMM은 마켓 메이킹에 보다 쉽게 접근할 수 있도록 했다. 유동성 풀을 사용하는 최초의 프로토콜 중 하나는 Bancor였지만, Uniswap의 대중화와 함께 더 주목받았다. </p>
<p><strong>오더북</strong>
오더북은 전자 거래의 기본 구성 요소로, 특정 시장에 대한 현재 진행 중인 주문의 모음이다. 오더북과의 각 상호작용에는 가스 수수료가 필요해서 거래를 실행하는데 훨씬 더 많은 비용이 든다. 즉, 이더리움과 같은 블록체인에서는 온체인 오더북 교환이 사실상 불가능하기 때문에, 사이드 체인 또는 Layer 2 솔루션을 사용한다. </p>
<p>Binanace DEX의 경우 바이낸스 체인을 기반으로 빠르고 저렴한 거래가 가능하고 솔라나 위의 Project Serum도 있지만, 암호화 공간의 많은 자산이 이더리움에 있기 때문에 일종의 크로스 체인 브리지를 사용하지 않는 한 다른 네트워크에서 거래할 수 없다. </p>
<h3 id="유동성-풀의-작동-방식">유동성 풀의 작동 방식</h3>
<p> AMM에서 거래를 실행할 때는 상대방이 없다. 대신 유동성 풀의 유동성으로 거래를 실행한다. 구매자가 구매하기 위해 특정 순간에 판매자가 있을 필요가 없고 풀에 충분한 유동성만 있으면 된다. Uniswap에서 최신 푸드 코인을 구매할 때, 풀에서 일어나는 일을 제어하는 알고리즘에 의해 가격이 결정된다. </p>
<blockquote>
<p>AMM(Automated Market Maker) : 수학 공식에 의존하여 자산 가격을 책정하는 탈중앙화 거래소(DEX) 프로토콜 유형이다. 전통적인 거래소와 같은 오더북을 사용하는 대신 가격 알고리즘에 따라 자산 가격이 책정된다.</p>
</blockquote>
<h3 id="uniswap">UniSwap?</h3>
<p>Uniswap은 자동화된 유동성 프로토콜로 Ethereum에 구축된 DEX 프로토콜이다. Uniswap은 높은 수준의 탈중앙화 및 검열 저항 덕분에 사용자가 중개자, 오더북 또는 중앙화된 당사자 없이 거래할 수 있도록 한다. Uniswap은 또한 Uniswap GitHub에서 확인할 수 있는 오픈 소스 소프트웨어를 사용한다. </p>
<p><strong>UNI</strong>
UNI는 보유자에게 거버넌스 권한을 부여하는 Uniswap 프로토콜의 기본 토큰이다. UNI 보유자는 프로토콜 변경에 대해 투표할 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Hooks]]></title>
            <link>https://velog.io/@dodo_velog/React-Hooks</link>
            <guid>https://velog.io/@dodo_velog/React-Hooks</guid>
            <pubDate>Mon, 06 Mar 2023 16:18:52 GMT</pubDate>
            <description><![CDATA[<p>Hooks는 함수형 컴포넌트에서도 상태 관리를 할 수 있는 기능을 제공한다. </p>
<p><strong>1. useState</strong>
가장 기본적인 Hooks.
<code>const [ value, setValue] = useState(0);</code>
파라미터에는 상태의 기본값을 넣어준다.</p>
<pre><code>import React from &#39;react&#39;;

const Info = () =&gt; {
    const [name, setName] = useState(&#39;&#39;);
    const [nickname, setNickname] = useState(&#39;&#39;);

    const onChangeName = e =&gt; {
        setName(e.target.value);
    };

    const onChangeNickname = e =&gt; {
        setNickname(e.target.value);
    };

    return (
        &lt;div&gt;
            &lt;div&gt;
                &lt;input value={name} onChange = {onChangeName} /&gt;
                &lt;input value={nickname} onChange = {onChangeNickname} /&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;div&gt;&lt;b&gt;이름:&lt;/b&gt;{name}&lt;/div&gt;
                &lt;div&gt;&lt;b&gt;닉네임:&lt;/b&gt;{nickname}&lt;/div&gt;
            &lt;/div&gt;

        &lt;/div&gt;
    );
};

export default Info;</code></pre><p><strong>2. useEffect</strong>
리액트의 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hooks.</p>
<blockquote>
<ol>
<li>화면에 맨 처음 렌더링될 때만 실행하고, 업데이트될 때는 실행하지 않고 싶을 때</li>
</ol>
</blockquote>
<pre><code>useEffect(() =&gt; {
        console.log({
            name, nickname
        });
    }, []); // useEffect의 두번째 파라미터로 []를 넣어준다</code></pre><pre><code>2. 특정 값이 업데이트 될 때만 실행하고 싶을 때
```
useEffect(() =&gt; {
    console.log({
        name, nickname
    });
}, [name]); // useEffect의 두번째 파라미터로 검사하고싶은 값을 넣어준다
```
3. 컴포넌트의 언마운트 전이나 업데이트 직전에 어떤 작업을 수행하고 싶을 때
```
useEffect(() =&gt; {
    console.log({
        name, nickname
    });
    return () =&gt; { // cleanup 함수를 반환한다
        console.log(&#39;cleanup&#39;); 
        console.log(name); // 업데이트 직전의 값을 반환한다
    }
}, [name]);
```</code></pre><p><strong>3. useReducer</strong>
reducer는 변화를 일으키는 함수이다. 현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 <code>action</code>값을 전달받아 새로운 상태를 반환하는 함수이다. (추후 Redux에서 자세히) 
useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트 하고 싶을 때 사용하는 Hooks
가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 꺼낼 수 있다는 것. </p>
<pre><code>import React, {useReducer} from &#39;react&#39;;

function reducer(state, action) {
    //action.type에 따라 다른 작업 수행
    switch (action.type){
        case &#39;INCREMENT&#39;:
            return {value: state.value + 1};
        case &#39;DECREMENT&#39;:
            return {value: state.value - 1};
        default:
            //아무것도 해당되지 않을 때 기존 상태 반환
            return state;
    }
}

const Counter = () =&gt; {
    const [state, dispatch] = useReducer(reducer, {value:0}); // 리듀서 함수, 리듀서 함수의 기본 값을 넣어줌

    return (
        &lt;div&gt;
            &lt;p&gt;현재 카운터 값은 &lt;b&gt;{state.value}&lt;/b&gt;입니다.&lt;/p&gt;
            &lt;button onClick={() =&gt; dispatch({type:&#39;INCREMENT&#39;})}&gt;+1&lt;/button&gt;
            &lt;button onClick={() =&gt; dispatch({type:&#39;DECREMENT&#39;})}&gt;-1&lt;/button&gt;
        &lt;/div&gt;
    );
};

export default Counter;</code></pre><pre><code>import React, { useReducer } from &#39;react&#39;;

function reducer(state, action) {
    return {
        ...state, 
        [action.name]: action.value
    };
}


const Info = () =&gt; {
    const [ state, dispatch] = useReducer(reducer, {
        name: &#39;&#39;,
        nickname: &#39;&#39;
    });

    const {name, nickname} = state;
    const onChange = e =&gt; {
        //e.target을 action값으로 사용 : 인풋 개수가 많아져도 코드를 깔끔하게 유지할 수 있는 장점이 있다!
        dispatch(e.target); 
    };

    return (
        &lt;div&gt;
            &lt;div&gt;
                &lt;input value={name} onChange = {onChange} /&gt;
                &lt;input value={nickname} onChange = {onChange} /&gt;
            &lt;/div&gt;
            &lt;div&gt;
                &lt;div&gt;&lt;b&gt;이름:&lt;/b&gt;{name}&lt;/div&gt;
                &lt;div&gt;&lt;b&gt;닉네임:&lt;/b&gt;{nickname}&lt;/div&gt;
            &lt;/div&gt;

        &lt;/div&gt;
    );
};

export default Info;</code></pre><p><code>state</code> : 현재 가리키고 있는 상태
<code>dispatch</code> : 액션을 발생시키는 함수. dispatch(action) 형태로 리듀서 함수가 호출되는 구조</p>
<p><strong>4. useMemo</strong>
함수형 컴포넌트 내부에서 발생하는 연산을 최적화 할 수 있다. 렌더링 과정에서 특정 값이 바뀌었을 때만 연산을 실행하고, 원하는 값이 바뀌지 않았다면 이전에 연산했던 결과를 다시 사용한다. </p>
<pre><code>const avg = useMemo(() =&gt; getAverage(list), [list]);</code></pre><p><strong>5. useCallback</strong>
렌더링 성능을 최적화해야 하는 상황에서 사용. 만들어 놨던 함수를 재사용할 수 있다. useCallback의 첫번째 파라미터에는 생성하고 싶은 함수를 넣고, 두 번째 파라미터에는 배열을 넣는다. 이 배열은 어떤 값이 바뀌었을 때 함수를 새로 생성해야 하는 지 명시한다. </p>
<pre><code>import React from &#39;react&#39;;

const getAverage = numbers =&gt; {
    if (numbers.length === 0) return 0;
    const sum = numbers.reduce((a,b)=&gt; a+ b);
    return sum/numbers.length;
}


const Average = () =&gt; {
    const [list, setList] = useState([]);
    const [number, setNumber] = useState(&#39;&#39;);

    const onChange = useCallback ( e =&gt; {
        setNumber(e.target.value);
    }, []); // 컴포넌트가 처음 렌더링 될 때만 함수 실행

    const onInsert = useCallback( e =&gt; {
        const nextList = list.concat(parseInt(number));
        setList(nextList);
        setNumber(&#39;&#39;);
    }, [number, list]); //number,list의 변경이 생기면 함수 실행

    const avg = useMemo(() =&gt; getAverage(list), [list]);

    return (
        &lt;div&gt;
            &lt;input value = {number} onChange = {onChange}/&gt;
            &lt;button onClick={onInsert}&gt;등록&lt;/button&gt;
            &lt;ul&gt;
                {list.map((value, index) =&gt; (
                    &lt;li key={index}&gt;{value}&lt;/li&gt;
                ))}
            &lt;/ul&gt;
            &lt;div&gt;&lt;b&gt;평균값:&lt;/b&gt;{avg}&lt;/div&gt;

        &lt;/div&gt;
    );
};

export default Average;</code></pre><p>함수 내부에서 상태 값에 의존해야 할 때는 그 값을 반드시 두 번째 파라미터 안에 포함시켜 주어야 한다. onChange의 경우 기존의 값을 조회하지 않고 바로 설정만 하기 때문에 배열이 비어있어도 상관 없지만, onInsert의 경우 기존의 numbers와 list를 조회해서 nextlist를 생성하기 때문에 배열 안에 number와 list를 넣어 주어야 한다. </p>
<p><strong>6. useRef</strong>
함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록 해줌. </p>
<pre><code>import React from &#39;react&#39;;

const getAverage = numbers =&gt; {
    if (numbers.length === 0) return 0;
    const sum = numbers.reduce((a,b)=&gt; a+ b);
    return sum/numbers.length;
}

const Average = () =&gt; {
    const [list, setList] = useState([]);
    const [number, setNumber] = useState(&#39;&#39;);
    const inputEl = useRef(null);

    const onChange = useCallback ( e =&gt; {
        setNumber(e.target.value);
    }, []); // 컴포넌트가 처음 렌더링 될 때만 함수 실행

    const onInsert = useCallback( e =&gt; {
        const nextList = list.concat(parseInt(number));
        setList(nextList);
        setNumber(&#39;&#39;);
        inputEl.current.focus() //useRef로 만든 객체 안의 current 값이 실제 엘리먼트를 가리킴
    }, [number, list]); //number,list의 변경이 생기면 함수 실행

    const avg = useMemo(() =&gt; getAverage(list), [list]);

    return (
        &lt;div&gt;
            {/*등록 버튼을 눌렀을 때 포커스가 인풋 쪽으로 넘어간다 */}
            &lt;input value = {number} onChange = {onChange} ref = {inputEl}/&gt;
            &lt;button onClick={onInsert}&gt;등록&lt;/button&gt;  
            &lt;ul&gt;
                {list.map((value, index) =&gt; (
                    &lt;li key={index}&gt;{value}&lt;/li&gt;
                ))}
            &lt;/ul&gt;
            &lt;div&gt;&lt;b&gt;평균값:&lt;/b&gt;{avg}&lt;/div&gt;

        &lt;/div&gt;
    );
};

export default Average;</code></pre><p><strong>7. 커스텀 hooks</strong>
useReducer -&gt; useInputs라는 Hook으로 분리한다.</p>
<pre><code>import {useReducer} from &#39;react&#39;;

function reducer(state, action) {
    return {
        ...state,
        [action.name]: action.value
    };
}

export default function useInputs(initialForm) {
    const [ state, dispatch] = useReducer(reducer, initialForm);
    const onChange = e =&gt; {
        dispatch(e.target);
};
return [state, onChange];
}</code></pre><pre><code>import React from &#39;react&#39;;
//다른 컴포넌트에서 hooks 호출
import useInputs from &#39;./useInputs&#39;;

const Info = () =&gt; {
    const [state, onChange] = useInputs({
        name: &#39;&#39;,
        nickname: &#39;&#39;
    });
    const {name, nickname} = state;

    return (
    ...
    );
 };

 export default Info;</code></pre><ul>
<li>클래스형 컴포넌트를 작성하지 않고도 <code>함수형 컴포넌트 + hooks</code>를 사용하여 대부분의 기능을 구현할 수 있다. 이렇게 쓰는 걸 더 권장합!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[7568.py] 덩치]]></title>
            <link>https://velog.io/@dodo_velog/7568.py-%EB%8D%A9%EC%B9%98</link>
            <guid>https://velog.io/@dodo_velog/7568.py-%EB%8D%A9%EC%B9%98</guid>
            <pubDate>Fri, 03 Mar 2023 17:26:11 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/7568">7568 문제 링크</a></p>
<p><strong>문제</strong>
우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x &gt; p 그리고 y &gt; q 이라면 우리는 A의 덩치가 B의 덩치보다 &quot;더 크다&quot;고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, &quot;덩치&quot;로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.</p>
<p>N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 &quot;큰 덩치&quot;의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다. 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.</p>
<p>이름    (몸무게, 키)    덩치 등수
A    (55, 185)    2
B    (58, 183)    2
C    (88, 186)    1
D    (60, 175)    2
E    (46, 155)    5
위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.</p>
<p><strong>입력</strong>
첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.</p>
<p><strong>출력</strong>
여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.</p>
<p><strong>내 코드</strong></p>
<pre><code># 자신보다 더 큰 덩치의 사람이 k명이라면 
# 그 사람의 덩치 등수는 k+1

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

# 자신보다 더 큰 덩치의 사람 수 = K

arr_k = [0]*N


for i in range(N):
    k = 0
    for j in range(N):
        if data[i][0] &lt; data[j][0] and data[i][1] &lt; data[j][1]:
            k += 1
    arr_k[i] = k+1

for i in range(len(arr_k)):
    print(arr_k[i], end=&#39; &#39;)</code></pre><ul>
<li>디버깅 용 print는 제출 때 꼭 지우자</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[11053.py] 가장 긴 증가하는 부분 수열]]></title>
            <link>https://velog.io/@dodo_velog/11053.py-%EA%B0%80%EC%9E%A5-%EA%B8%B4-%EC%A6%9D%EA%B0%80%ED%95%98%EB%8A%94-%EB%B6%80%EB%B6%84-%EC%88%98%EC%97%B4</link>
            <guid>https://velog.io/@dodo_velog/11053.py-%EA%B0%80%EC%9E%A5-%EA%B8%B4-%EC%A6%9D%EA%B0%80%ED%95%98%EB%8A%94-%EB%B6%80%EB%B6%84-%EC%88%98%EC%97%B4</guid>
            <pubDate>Fri, 03 Mar 2023 17:02:46 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.acmicpc.net/problem/11053">11053 문제 링크</a></p>
<p><strong>문제</strong>
수열 A가 주어졌을 때, 가장 긴 증가하는 부분 수열을 구하는 프로그램을 작성하시오.</p>
<p>예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분 수열은 A = {10, 20, 10, 30, 20, 50} 이고, 길이는 4이다.</p>
<p><strong>입력</strong>
첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.</p>
<p>둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)</p>
<p><strong>출력</strong>
첫째 줄에 수열 A의 가장 긴 증가하는 부분 수열의 길이를 출력한다.</p>
<p><strong>내 코드</strong></p>
<pre><code>N = int(input())
A = list(map(int, input().split()))
# 10 20 10 30 20 50

# 인덱스 돌면서, 그 앞까지의 수열 길이의 최댓값을 저장한다
# dp = 수열 길이
dp = [0]*N 

for i in range(N):                          #기준 인덱스
    for j in range(i):                      #기준 인덱스 이전 값들 모두 돈다
        if A[j] &lt; A[i] and dp[j] &gt; dp[i]:   #자기보다 작은 수인데 수열 값이 나보다 크면 가져와서 내 거에 포함시킨다
            dp[i] = dp[j]
    dp[i] += 1
print(dp)</code></pre><ul>
<li>과거의 결과가 이후에 영향을 준다 = dp</li>
<li>&#39;부분&#39;수열이라는 점, 처음에 너무 단순하게 생각해서 sort하고 set..</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>