https://www.acmicpc.net/problem/4396

 

4396번: 지뢰 찾기

첫 번째 줄에는 10보다 작거나 같은 양의 정수 n이 입력된다. 다음 n개의 줄은 지뢰의 위치를 나타낸다. 각각의 줄은 n개의 문자를 사용하여 한 행을 나타낸다. 온점(.)은 지뢰가 없는 지점이며 별

www.acmicpc.net

 

문제를 보고 반복문으로 지뢰를 탐색하면 되겠지라고 생각했는데,

문제를 잘 읽어보니 폭탄을 열었을 때 조건을 추가해주지 않아서 틀렸었다.

폭탄이 터졌을 때는 한 번만 필요하므로, flag 변수를 세워서 한 번만 실행되도록 했다.

 

import sys

input = sys.stdin.readline

n = int(input())
dx = [1,1,1,0,0,-1,-1,-1]
dy = [1,0,-1,1,-1,1,0,-1]

real = [list(input().rstrip()) for _ in range(n)]
check = [list(input().rstrip()) for _ in range(n)]
flag = True

def change(x,y):        
    cnt = 0
    
    for i in range(8):
        a = x + dx[i]
        b = y + dy[i]

        if 0<=a <n and 0<=b<n:
            if real[a][b] == '*':
                cnt += 1

    return str(cnt)
#지뢰가 있는 칸을 열었을 때
def bomb():
    for i in range(n):
        for j in range(n):
            if real[i][j] == "*":
                check[i][j] = "*"
        
for i in range(n):
    for j in range(n):
        if check[i][j] == 'x':
            if real[i][j] == ".":
                check[i][j] = change(i,j)
            elif real[i][j] == "*" and flag:
                bomb()
                flag==False

for i in check:
    print("".join(i))

https://www.acmicpc.net/problem/4970

 

4970번: 디지털 회로 개론

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있고, 식을 나타낸다. 식은 0, 1, 2, P, Q, R, -, *, +, (, )로만 이루어져 있다. 식의 BNF형 문법은 다음과 같다.

www.acmicpc.net

이 문제는 식이 주어졌을 때 3차 논리에서 2로 만드는 (P,Q,R) 쌍의 개수를 찾는 문제이다.

 

3차 논리에서 0,1,2 밖에 없고, P,Q,R 쌍을 찾는 것이므로 브루트포스를 진행했을 때

반복문을 9번만 돌려도 되어서, 브루트 포스 방법을 사용했다.

 

우선 주어진 식을 정리하였는데,

 

자료구조 시간에 배운 후위표기법이 생각나서 스택을 사용하여 후위표기법으로 바꾸었다.

이 때, 단항 연산자인 Not을 먼저 계산해줘야 하므로 우선 순위를 높게 잡았다.

 

후위 표기법으로 바꾼 후에, 다시 스택을 이용하여 3차 논리에 맞춰서 식을 계산해주었다.

 

import sys
input = sys.stdin.readline

#단항연산자가 우선순위가 큼
prec = {'-':3,'+':2,'*':2,'(':1}

#3차 논리
NOT = [2,1,0]
AND = [[0,0,0],[0,1,1],[0,1,2]]
OR = [[0,1,2],[1,1,2],[2,2,2]]

#후위 표기법
def postfix(s):
    stack = []

    answer = ''

    for c in s:
        if c not in "()+*-":
            answer += c
        elif c == "(":
            stack.append(c)
        elif c == ")":
            while stack[-1] != "(":
                answer += stack.pop()
            stack.pop()
        elif stack and prec[c] <= prec[stack[-1]]:
            answer += stack.pop()
            stack.append(c)
        else:
            stack.append(c)
    while stack:
        answer += stack.pop()

    return answer

#후위표기법 계산
def cal(s):
    stack = []
    for t in s:
        if t == "*":
            stack.append(AND[stack.pop()][stack.pop()])
        elif t == "+":
            stack.append(OR[stack.pop()][stack.pop()])
        elif t == "-":
            stack.append(NOT[stack.pop()])
        else:
            stack.append(int(t))
    return stack.pop()

while True:
    sent = input().strip()
    
    if sent == ".": break

    #-- => 없애기
    sent = sent.replace("--","")

    #후위 표기법으로 바꾸기
    pos = postfix(sent)

    cnt = 0

    for p in ['0','1','2']:
        new_1 = pos.replace('P',p)
        for q in ['0','1','2']:
            new_2 = new_1.replace('Q',q)
            for r in ['0','1','2']:
                new_3 = new_2.replace('R',r)

                ans = cal(new_3)
                if ans == 2: cnt += 1
    print(cnt)

 

 

 

 

포스코 다니는 선배가 Recruiting 홍보로 학교에 오셔서, IT 기획팀에 대해 여쭤보았다.

 

 

포스코 IT 기획팀에서 하는 일은 다음과 같다.

  • 전사시스템 개선
  • 신규 개발 ( 개발 기획 )
  • 업그레이드
  • IT운영기준관리
  • IT자산관리/투자/심의
  • 전사 보안 체계기획, 관리, 전사 보안감사

 

아래는 해당 팀에 계시는 분의 답변이다. 

 

직접 개발을 하는나요?

 

직접 개발을 "하려면 할 수 있다"

 

코드를 짜서 개발하는 것은 포스코 그룹사인 ICT 팀에서 진행하고, 사내 업무 시스템을 모바일로도 개발 기획을 한다.

 

기획을 우선하지만 컴퓨터 코딩이나 능력이 있으면

기술 개발, 과제시에 자체 개발을 진행하거나 좀 더 수월할 수 있는 정도이고 그냥 개인적인 능력차이라고 느껴진다.

 

만약에 그런 능력에 따라서 적절한 부서 배치가 된다면,

EIC 기술부에서 제어, 통신 네트워크 관련 섹션, 정보 기획실 보안쪽으로 간다. 

 

현실적으로 발휘하고 싶은 능력에 대응되게 가더라도 도메인은 일치하는 정도고 하는 업무는

엔지니어들의 공통 업무를 하게 될 것 같다.

이후 2~3년 순환 근무를 관련 없는 다른 섹션으로 가는 상황이 생길 수도 있겠다.

 

대졸 채용 직군 엔지니어들은 특정 전공이라서 , 특정 일을 하는 건 아니고

어떤 섹션에 속하느냐에따라 해당 섹션에서 하는 일을 한다고 생각된다.

즉, 섹션에서 해야하는 일을 하는 것일 뿐이다.

 

=> 정보 기획실 : 개발 "기획" // ICT or 외주 : 직접 개발 

스마트 과제 같은 것들은 직접 자체 개발하는 경우도, 기획 정도까지만 하는 경우도 있다.

 

 

스마트 과제란?

포스코에서는 스마트 팩토리 추진을 하는데, 이것은 자동화를 의미하고, IT 인프라는 정보를 의미한다.

스마트 과제는 포스코 스마트 경진 대회에서 관련 주제를 알 수 있다.


답변해주시는 분이 AI 빅데이터 직무로 들어오셔서 관련된 내용을 여쭤보았다.

 

포스코 AI 아카데미 추천 채용으로 취업을 하셨고

 

포스코 AI, Big Data 아카데미는 다음과 같다.

https://youth.posco.com/posco/edu/index.php?mod=academy&pag=academy01 

 

포스코 청년 취업 창업 지원 프로그램

포스코 청년 취업 창업 지원 프로그램

youth.posco.com

청년 AI·Big Data 아카데미 : 여름방학, 겨울방학에 6주

6주동안 진행하하며, 인턴으로 일하면서 해당 부서에서 일해볼 수 있고, 

이후 채용 과정에 합격하면 바로 면접을 볼 수 있다.

 

해당 부서에서 하는 일은 섹션 엔지니어 공통 업무, 개인 과제 진행 (AI 모델 개발)을 하신다.

 

❓석사만 뽑는가?

 

다른 회사는 모르겠지만 포스코 기준에서는 석사 이상만 뽑는 건 아니고,

 

엔지니어를 뽑아서 공정이해한 후 AI 기술을 적용시키는 형태를 가진다.

 

❓하는 일 예시

컴퓨터 비전을 통해 표면 품질 검사할 때 카메라로 인식해서 품질 이상있는지 없는지 판별하는 식으로 많이 적용 된다.


 

취직과 관련 하여

위에서 언급한

청년 AI·Big Data 아카데미 뿐만 아니라

POSCO Steel Bridge 라는 프로그램도 있으니 눈 여겨 보면 좋을 듯하다.

 

공채와 관련해서는 다음 과정이 있다.

 

> 서류 + 자격증

> 인적성

> 1차 면접(직무 역량평가)

인성면접 : 지원 동기나, 자기 소개, 마지막 할 말 
직무  : 학교에서 배우거나, 기사 자격증 등에 대한 내용
그룹 activity : 쉬는시간에 PPT 발표자료, 레고 만들기, 퍼즐 맞추기 => 사람들과의 협업, 반응 (결과물은 약간 중요)
분석 발표  : 자료를 분석하고 대안을 발표하는 것. 선택지를 주고 근거를 대는, 발표를 잘해야함.
에세이 2개 (P/F) : 책읽고 독후감, 한국사

> 2차 면접(가치적합성평가) 

>> 최종 발표, 입사

 

 

 

 

 

https://www.acmicpc.net/problem/3360

 

3360번: 깡총깡총

CTP마을에 사는 토끼 아람이는 3,2,1미터씩 뛰어서 n미터를 지난다. 람토끼가 지나야하야 하는 길이가 주어졌을 때 점프 길이가 증가하지 않는 순서로 지나가는 방법은 총 몇 가지가 있을까? 찾

www.acmicpc.net

 

 

토끼가 3,2,1 미터씩 N 미터를 지난다.

이 때 길이가 증가하지 않는 순서로 지나가는 방법을 구하는 문제이다.

 

처음에는 재귀함수로 하려고 했는데 메모리가 초과되었다.

 

재귀함수보다 직접 계산하는 방법은 3을 맨 왼쪽으로 고정시키는 것이다.

그리고 2를 나눠줘서 2가 들어있는 갯수를 구해준다.

마지막에 +1 을 하는 이유는 1만으로 이뤄진 식을 고려하는 것이다.

이거 안해줘서...(っ °Д °;)っ

import sys
sys.setrecursionlimit(10**6)
N = int(sys.stdin.readline())

num = 0
def count(x,last):
    global num
   
    if x == 0:
        num += 1
        return 
    elif x<0:
        return
    else:
        if last == 3:
            count(x-3,3)
            count(x-2,2)
            count(x-1,1)
        elif last == 2:
            count(x-2,2)
            count(x-1,1)
        elif last == 1:
            count(x-1,1)

count(N,3)
print(num)

 

Python 으로 제출했더니 시간초과가 떠서, Pypy로 했다.

import sys

N = int(sys.stdin.readline())

#왼쪽을 고정시키기
num = 0

#3을 고정하면, 나머지는 1,2로 이뤄짐
#+1 은 1만 있는 경우
for i in range(N):
    if N >= 3*i:
        #2로 나눈 이유는 2가 맨 앞에 있을 수 있는 갯수
        num += (N-3*i)//2 + 1
        
print(num% 1000000)

 

https://www.acmicpc.net/problem/22993

 

22993번: 서든어택 3

좋은 전투 순서가 존재해서 준원이만 생존하고 나머지 플레이어가 모두 죽게 만들 수 있다면 Yes를, 반대로 전투가 어떤 순서로 이루어져도 준원이가 절대 최후의 생존자가 될 수 없다면 No를

www.acmicpc.net

 

준원이가 끝까지 이기는 최고의 방법은

나머지 사람들의 공격력을 오름차순으로 정렬하고,

준원이보다 공격력이 작은 사람들이랑만 싸움을 하면서 준원이의 공격력을 키우는 것이다.

 

import sys

input = sys.stdin.readline

N = int(input())
P = list(map(int,input().split()))

x = P.pop(0)

P.sort()

flag = False

for i in range(N-1):
    if x > P[i]:
        x += P[i]
    else:
        flag = True

if flag:
    print("No")
else:
    print("Yes")

https://www.acmicpc.net/problem/1907

 

1907번: 탄소 화합물

첫째 줄에 세 정수 X1, X2, X3 (1 이상 10 이하)를 빈 칸을 사이에 두고 순서대로 출력한다. 이는 각각 M1, M2, M3의 계수가 된다. 만일 해가 둘 이상이라면 답을 세 자연수로 이루어진 수열으로 생각해

www.acmicpc.net

  1. 우선 +, = 을 없앤다.
  2. split으로 x1, x2, x3를 구한다.
  3. 분자의 단어를 하나씩 보면서,
    단어가 CHO 중에 있으면 1을 추가하고,
    숫자라면 변경 단어를 직전에 있는 단어에 숫자만큼 더해준다.
  4. 그리고 계수는 1~9까지 이므로, 9*9*9 번의 반복문을 통해서 답을 찾는다.

 

import sys

input = sys.stdin.readline


def count(x):
    l = [0,0,0] #c,h,o
    for i in range(len(x)):
        num = 1
        ele = x[i]
        if ele.isdigit():
            num = int(ele) -1 
            ele = x[i-1]

        if ele=="C": l[0] += num
        elif ele=="H" : l[1] += num
        elif ele=="O" : l[2] += num

    return l

word = input().strip()

#+,= 지우기
symbols = ['+','=']

for i in symbols:
    word = word.replace(i,' ')

x1,x2,x3 = word.split()

#개수 세기
x1 = count(x1)
x2 = count(x2)
x3 = count(x3)

#계수 찾기
flag = False
for i in range(1,10):
    for j in range(1,10):
        for k in range(1,10):
            
            x = [m*i for m in x1]
            y = [m*j for m in x2]
            z = [m*k for m in x3]

            new = [x_t + y_t for x_t,y_t in zip(x,y)]
            
            if new == z:
                print(i,j,k)
                flag = True
                break
        if flag: break
    if flag: break

https://www.acmicpc.net/problem/10868

 

10868번: 최솟값

N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100,000)개 주어졌을 때는

www.acmicpc.net

 

 

 

직전에 풀었던 최솟값 과 최댓값 구하기와 같았다.

2022.03.15 - [알고리즘 공부] - [백준/세그먼테이션 트리] 2357 최솟값과 최댓값

 

[백준/세그먼테이션 트리] 2357 최솟값과 최댓값

https://www.acmicpc.net/problem/2357 2357번: 최솟값과 최댓값 N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일..

minstudy.tistory.com

import sys
from math import *

def init(node,start,end):
    if start == end:
        tree[node] = arr[start]
        return tree[node]

    mid = (start+end)//2
    tree[node] = min(init(node*2,start,mid),init(node*2+1,mid+1,end))
    return tree[node]

def find(node,start,end,left,right):
    if start>right or end < left:
        return 1000000001

    if left<=start and end <= right:
        return tree[node]

    mid = (start+end)//2
    return min(find(node*2,start,mid,left,right),find(node*2+1,mid+1,end,left,right))

input =sys.stdin.readline
n,m = map(int,input().split())
arr = [int(input()) for _ in range(n)]

h = int(ceil(log2(n)))
t_size = 1<<(h+1)

tree = [0] * t_size

init(1,0,n-1)

for _ in range(m):
    a,b = map(int,input().split())
    print(find(1,0,n-1,a-1,b-1))

https://www.acmicpc.net/problem/2357

 

2357번: 최솟값과 최댓값

N(1 ≤ N ≤ 100,000)개의 정수들이 있을 때, a번째 정수부터 b번째 정수까지 중에서 제일 작은 정수, 또는 제일 큰 정수를 찾는 것은 어려운 일이 아니다. 하지만 이와 같은 a, b의 쌍이 M(1 ≤ M ≤ 100

www.acmicpc.net

처음에는 list를 잘라서 min, max를 구했는데 시간초과가 떴다.

import sys

input = sys.stdin.readline

N,M = map(int,input().split())

arr = [int(input()) for _ in range(N)]

for _ in range(M):
    a,b = map(int,input().split())

    print(min(arr[a-1:b]),max(arr[a-1:b]))

 

 

트리를 최솟값, 최댓값을 따로 만든다.

 

풀이 방법은 세그멘테이션 트리의 코드와 같음.

 

import sys
from math import *

input = sys.stdin.readline

def initMin(node,start,end):
    if start == end:
        treeMin[node] = arr[start]
        return treeMin[node]

    mid = (start+end)//2
    treeMin[node] = min(initMin(node*2,start,mid),initMin(node*2+1,mid+1,end))
    return treeMin[node]

def initMax(node,start,end):
    if start == end:
        treeMax[node] = arr[start]
        return treeMax[node]

    mid = (start+end)//2
    treeMax[node] = max(initMax(node*2,start,mid),initMax(node*2+1,mid+1,end))
    return treeMax[node]

#최소 구하기
def findMin(node,start,end,left,right):
    if start > right or end < left:
        return 1000000001
    
    if left<=start and end <= right:
        return treeMin[node]

    mid = (start+end)//2
    return min(findMin(node*2,start,mid,left,right),findMin(node*2+1,mid+1,end,left,right))

def findMax(node,start,end,left,right):
    if start > right or end < left:
        return 0
    if left<=start and end <= right:
        return treeMax[node]

    mid = (start+end)//2
    return max(findMax(node*2,start,mid,left,right),findMax(node*2+1,mid+1,end,left,right))


N,M = map(int,input().split())

arr = [int(input()) for _ in range(N)]

h = int(ceil(log2(N)))
t_size = 1<<(h+1)

treeMax = [0] * t_size
treeMin = [0] * t_size
#세그멘트 트리만들기
initMin(1,0,N-1)
initMax(1,0,N-1)

for _ in range(M):
    a,b = map(int,input().split())

    print(f'{findMin(1,0,N-1,a-1,b-1)} {findMax(1,0,N-1,a-1,b-1)}')

https://www.acmicpc.net/problem/1956

 

1956번: 운동

첫째 줄에 V와 E가 빈칸을 사이에 두고 주어진다. (2 ≤ V ≤ 400, 0 ≤ E ≤ V(V-1)) 다음 E개의 줄에는 각각 세 개의 정수 a, b, c가 주어진다. a번 마을에서 b번 마을로 가는 거리가 c인 도로가 있다는 의

www.acmicpc.net

 

[풀이 방법]

 

조건

  1. 일방 통행 edge
  2. 왕복하는 경우도 사이클로 포함

원하는 답

  • 도로의 길이의 합이 가장 작은 사이클을 찾기

알고리즘 수업 들을 때, 교수님이 이건 그다지 좋지 않다고 했지만.. 생각하기는 편한 것 같다.

시작, 도착, 거치는 지점 모든 가능성을 다 해봐서

노드의 모든 연결점들의 길이를 구하는 것이다.

 

그리고 여기서는 사이클을 보기로 했으므로 [i][i] 중에서 최소 길이를 찾아서, 가장 작은 사이클을 구한다.

 

import sys

input = sys.stdin.readline
INF = sys.maxsize

V, E = map(int,input().split())
arr = [[INF] * V for _ in range(V)]

for _ in range(E):
    s,e,w= map(int,input().split())
    arr[s-1][e-1] = w

for k in range(V):#거침
    for i in range(V): #시작
        for j in range(V): #도착
            arr[i][j] = min(arr[i][j], arr[i][k] + arr[k][j])

ans = INF

for i in range(V):
    ans = min(ans,arr[i][i]) #본인으로 돌아오는 것중에 최소

if ans == INF:
    print(-1)
else:
    print(ans)

https://www.acmicpc.net/problem/20010

 

20010번: 악덕 영주 혜유

FT온라인 게임에서 치열한 경쟁을 통해 영주가 된 혜유는 퀘스트를 받았다. 퀘스트의 내용은 자신이 관리하고 있는 마을 사이에 교역로를 건설하여 마을 간 교류를 활성화시키는 것이다. 이때,

www.acmicpc.net

 

문제를 요약하면 양방향 이동 가능한 길을 통해, 도달이 불가능한 마을이 없도록 길을 만드는 것이다.

 

구해야하는 답은,

  1. 마을을 연결하는 최소의 비용 계산
  2. 마을과 마을을 이동하는 가장 최악의 비용 계산

 

1번. 최소한의 비용으로 연결하기 위해 최소 신장 트리 (minumum spanning tree)를 사용했다.

  1. 간선을 비용이 적은 순으로 정렬 시킨다.
  2. 적은 순서 부터 길을 확정한다. 확정하기 위해서는
    1) 가려는 노드와 현재 노드의 root 가 같으면 회전이 되서 안된다. 그러므로 root를 확인한다.
    2) Root가 다르면, 그 길을 확정하고 , 두 노드가 연결되었으므로 두 노드의 Root를 같은 것으로 만든다.

 2번. 결정된 길에서 최악의 길의 비용 구하기

이를 위해 1번에서 길을 확정할 때, 그 길들을 따로 저장한다.

그리고 끝에서 끝으로 연결된 것들만 볼 것이므로, 연결된 길이 1개인 노드들만을 시작점으로한다.

BFS를 통해 최대 길이를 찾는다.

 

 

import sys
from collections import deque

input = sys.stdin.readline

N,M=map(int,input().split())

root = [i for i in range(N)]
edge = [list(map(int,input().split())) for _ in range(M)]

#비용이 가장 적은 순으로 나열
edge.sort(key = lambda x:x[2])

#root를 계속 찾기
def find(x):
    if x!= root[x]:
        root[x] = find(root[x])

    return root[x]

ans = 0
adj = [[] for _ in range(N)]

for s,e,w in edge:
    sRoot = find(s)
    eRoot = find(e)
    if sRoot!=eRoot:
        if sRoot>eRoot:
            root[sRoot] = eRoot
        else:
            root[eRoot] = sRoot
        adj[s].append((e,w))
        adj[e].append((s,w))
        ans += w
        
#BFS
max_ans = 0
for i in range(N):
    if len(adj[i]) == 1: #끝에서 끝이므로, 연결된 노드가 하나인 것만 확인
        visit = [False] * N
        q = deque([(i,0)])
        visit[i] = True

        temp = 0

        while q:
            now, dist = q.pop()
            temp = max(dist,temp)
            for go, w in adj[now]:
                if not visit[go]:
                    visit[go] = True
                    q.appendleft((go,dist+w))

        max_ans = max(temp,max_ans)
        

print(ans)
print(max_ans)

 

현재 컴퓨터는 window 11 이고 운영체제 수업을 위해 virtual box에 ubuntu 20.04 LTS를 설치했다.

설치방법은 다음 유튜브를 통해 알았고

https://www.youtube.com/watch?v=Z9KVJnsFWKo&t=435s 

 

이것을 영상 후반부에 있는 것인데 ubuntu를 큰 창으로 보기 위함이다.

crtl+alt+T 를 눌러서 창을 열고
sudo apt update
sudo apt install build-essential dkms linux-headers-$(uname -r)
sudo mkdir -p /mnt/cdrom
sudo mount /dev/cdrom /mnt/cdrom <- 1번
cd /mnt/cdrom
sudo sh ./VBoxLinuxAdditions.run --nox11 <- 2번
sudo shutdown -r now

저 화살표 있는 줄에서 1번에서

mount : no medium found on /dev/sr0 local mount error 가 뜬다.

 

df -hTP 

를 치면 /dev/sr0가 없는 것을 볼 수 있고

 

lsscsi 를 치면 /dev/sr0를 볼 수 있다.

 

Oracle에 설정 > 저장소 > 컨트롤러 를 보면 비어있음으로 되어있을 것이다.

그러면 거기서 virtual을 추가한다는 것을 눌러서, 다운 받은 우분투를 설정하면 된다.

그럼 다음과 같이 나오고 다시 화살표 방향 밑으로 진행하면 된다.

 

다시 2번에서 ./VBoxLinuxAdditions.run 을 열 수 없다고 한다.

 

 

https://couplewith.tistory.com/entry/Vbox-Linux-VBoxLinuxAdditionsrun-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0

 

[Vbox] Linux의 VBoxLinuxAdditions.run 설치가 안되는 경우

[Vbox] Linux 의 VBoxLinuxAdditions.run 설치가 안되는 경우 종종 이런 경우가 있을지 모르겠습니다. 저는 종종 리눅스 커널을 업그레이드하거나 테스트를 하는 경우가 있어서 본 글을 작성해 두었습니다

couplewith.tistory.com

 

그래서 이 블로그를 참고했다.

+ Recent posts