<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Talking Potato</title>
        <link>https://velog.io/</link>
        <description>https://source-coding.tistory.com/</description>
        <lastBuildDate>Tue, 21 Nov 2023 12:21:24 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Talking Potato</title>
            <url>https://images.velog.io/images/my_youth99/profile/ff686a55-538d-4fd6-9a99-11ab5f16de33/giphy (3).gif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Talking Potato. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/my_youth99" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[안드로이드 토이프로젝트 (1)]]></title>
            <link>https://velog.io/@my_youth99/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</link>
            <guid>https://velog.io/@my_youth99/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%ED%86%A0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1</guid>
            <pubDate>Tue, 21 Nov 2023 12:21:24 GMT</pubDate>
            <description><![CDATA[<p>전공 수업에서 final project로 간단히 앱을 만드는 과제를 받았다. <del>(3주만에 PPT랑 플젝을 다 끝내야하는데 ..)</del>
토이 프로젝트 겸 추후에 배포도 하면 여러모로 좋은 경험일 것같다.</p>
<h1 id="주제-선정">주제 선정</h1>
<p>우선 주제를 먼저 고민해보았다.
3주 안에 만들어야하기때문에 복잡한 구현이 필요한 주제는 쓰질 못한다. (물론 플젝에만 시간을 갈면 어떻게 될 수도 있긴하지만 졸업을 위해 해야할게 너무 많다 ㅎㅎ)</p>
<p>고민을 해본 것은 <strong>&#39;카드깡&#39; 어플리케이션.</strong>
내가 직접 해본 적은 없지만 사람들이 보통 밥 값 내기를 하기 위해서 직원분들께 자신들의 카드를 보여주곤 직접 뽑으라고 한다. 그렇게 해서 뽑힌 카드로 결제하는 방식.. (요즘도 이런게 있는진 모르겠다.)
이걸 그냥 어플리케이션으로 지정해주면 좋지않을까 싶다. 구현도 random으로 돌리면 쉬울 것같기도 하고 ..
그리고 n빵 계산하는 기능도 넣으면 좀 더 그럴듯하지 않을까 싶었다.</p>
<h1 id="디자인-선정">디자인 선정</h1>
<p>시간도 없고 디자인을 그렇게 잘하는 편은 아니다. 그래서 토스처럼 깔끔하게 ui를 만드는 것이 목표.
피그마를 통해 앱 아이콘과 기본 디자인을 만들어본다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/28df62db-4cfd-4d39-b5a0-8322e84e2ff9/image.png" alt=""> 직관적으로 그냥 카드 이미지와 어플리케이션 이름, 그리고 시작 버튼을 넣어보았다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5f6611ea-3cb5-4174-a384-e1c09d6bc3c0/image.png" alt=""> 안드로이드 스튜디오 직접 넣어보니까 나쁘지 않은 것 같긴 한데.. 좀 허전해보인다. 카드 이미지를 다시 만들던지 해야할 듯. 일단 지금은 이걸로 함.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/d9d1f151-cc76-4cb0-a771-52b024abb357/image.png" alt=""> <img src="https://velog.velcdn.com/images/my_youth99/post/5ed1aa30-1282-4fa8-9673-5cc85f554cb5/image.png" alt=""> 대강 디자인을 마쳤다. 이제 개발을 시작해보자.</p>
<h1 id="개발">개발</h1>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/f8e06e41-439c-4bc8-9a0a-74f1255e6ed6/image.png" alt="">
한번 framgent로 도전해보자..! </p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/47341b65-80fa-4b93-ad70-26d6f5244d29/image.png" alt=""></p>
<p>Fragment는 framLayout으로 감싸져있어서 constriantLayout으로 바꿔주었다. </p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/1adb2f17-55d4-4f8f-a56f-1478e6ceb521/image.png" alt=""> fragment 간의 이동이 안돼서 1시간동안 끙끙 앓았는데 name의 문제였다..^^ NavHostFragment로 해줬어야함 ㅎㅎ... 나 이제껏 뭐함?</p>
<p><img src="blob:https://velog.io/b89fe8a8-b356-4778-a802-2696424fc7b9" alt="업로드중.."> 피그마에 나온 대로 fragment를 추가하고 디자인하고.. 기능을 연결하였다. action 태그 달다가 헷갈려서 뇌정지 올뻔했다.</p>
<p>애니메이션을 넣어주면 더 퀄리티 있을 것같아서 </p>
<pre><code>implementation (&quot;nl.dionsegijn:konfetti-xml:2.0.3&quot;)
</code></pre><p>를 gradles에 추가한 후, 오픈소스의 애니메이션도 넣어주었다.
그래도 하루만에 진도를 빨리 나가서 다행이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[티스토리 블로그도 운영중]]></title>
            <link>https://velog.io/@my_youth99/%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%8F%84-%EC%9A%B4%EC%98%81%ED%95%98%EA%B3%A0-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@my_youth99/%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EB%B8%94%EB%A1%9C%EA%B7%B8%EB%8F%84-%EC%9A%B4%EC%98%81%ED%95%98%EA%B3%A0-%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Thu, 19 Oct 2023 07:44:27 GMT</pubDate>
            <description><![CDATA[<p>최근에 다시 Tistory 에도 포스팅을 하기 시작했습니다!
velog는 러프한 글들이 많았다면 Tistory에는 좀 기본적인 개념이나 헷갈리는 부분들을 많이 정리해놓으려고 합니다 :) </p>
<p><a href="https://source-coding.tistory.com/">https://source-coding.tistory.com/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS/BFS - 단어 변환]]></title>
            <link>https://velog.io/@my_youth99/DFSBFS-%EB%8B%A8%EC%96%B4-%EB%B3%80%ED%99%98</link>
            <guid>https://velog.io/@my_youth99/DFSBFS-%EB%8B%A8%EC%96%B4-%EB%B3%80%ED%99%98</guid>
            <pubDate>Fri, 06 Oct 2023 06:24:38 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43163">https://school.programmers.co.kr/learn/courses/30/lessons/43163</a>
<img src="https://velog.velcdn.com/images/my_youth99/post/7d116423-4097-445e-87f5-7b8cbd7a2425/image.png" alt=""></p>
<p>호기롭게 BFS로 접근하였지만 흠.. 일단 의식의 흐름대로 한번 써봤다</p>
<pre><code>from collections import deque

def bfs(graph, words, begin, ct, target):
    count, c, i = 0, 0, 0
    queue = deque([words[i]]) # [&quot;hot&quot;]
    answer = []
    v = queue.popleft()
    while True:
        for w in v:
            if w in begin:
                count+=1
        if count == (ct-1):
            begin = v
            answer.append(begin)

        if len(set(target) - set(begin)) == 1:
            answer.append(target)
            break

        count = 0
        i += 1
        if i == len(words):
            break
        queue.append(words[i])
        v = queue.popleft()
    return len(answer)

def solution(begin, target, words):
    if not target in words:
        return 0
    visited = [False]*len(words)
    answer = bfs(words, words, begin, len(begin), target)
    return answer</code></pre><p>만약 target과의 문자 차이가 1개일 경우, (그리고 target의 단어가 words안에 있으면) 바로 while문을 나가기. +1 만 해주면 과정은 차피 끝이니까 ㅇㅇ... 
제출해보니 의외로 선방하긴했다..^^</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/bc295b1f-707a-4961-b05e-30853f7476ec/image.png" alt=""></p>
<p>의외로 시간초과가 안떴다. 그러면 내가 테스트케이스 무언가를 지금 고려 안했다는 것같은데.. 
구글링을 해보니까 내가 <strong>words의 순서가 고정되어있다고 생각했던 것이 문제였다</strong> 그럼 이거 다 갈아엎어야 하나..? ㅎ
아님 그냥 리버스한걸 뒤에 하나 더 붙여서 해볼까 싶었다.</p>
<pre><code>from collections import deque

def bfs(graph, words, begin, ct, target):
    count, c, i = 0, 0, 0
    queue = deque([words[i]]) # [&quot;hot&quot;]
    answer = []
    v = queue.popleft()
    while True:
        if len(set(begin) - set(v)) == 1:
            begin = v
            answer.append(begin)        
        elif begin == target:
            break

        if len(set(target) - set(begin)) == 1:
            answer.append(target)
            break

        count = 0
        i += 1
        if i == len(words):
            break
        queue.append(words[i])
        v = queue.popleft()
    return len(answer)

def solution(begin, target, words):
    if not target in words:
        return 0
    words += words[::-1]
    answer = bfs(words * len(words), words, begin, len(begin) * 2, target)

    return answer</code></pre><p>응 안돼~ 돌아가..
일단 set으로 비교하는 게 틀렸음
함수를 하나 더 만들어서 비교를 했고
하나의 자리에서만 차이가 나는거니까 인덱스도 확인해줬어야함</p>
<pre><code>from collections import deque

def find(target, begin):
    count = 0
    for i in range(len(begin)):
        if begin[i] == target[i]:  
            count+=1
    return count

def bfs(words, begin, target):

    count= 0
    obj = len(begin)-1

    queue = deque(words) # [&quot;hot&quot;, &quot;dot&quot;, &quot;dog&quot;, &quot;lot&quot;, &quot;log&quot;, &quot;cog&quot;]
    goal = target[:]
    answer = []
    v = queue.popleft()

    while queue:
        # 현재 단어랑 바꿀 단어랑 알파벳 비교
        # 만약 1개밖에 차이가 안나면 걔로 바꿈

        print(&quot;현재&quot;, begin, v, find(begin, v), obj)
        if v == target and find(begin,v) == obj:
            count += 1
            return count

        if find(begin, v) == obj:
            begin = v
            count += 1 # 바꾼 횟수
            # 근데 만약 바꾼 begin이랑 target이 차이가 1개 밖에 안나면
            # 한번만 더 바꾸면 되니까 끝내기
            if find(target, begin) == obj:
                count += 1
                return count
        else: 
            queue.append(v)
        v = queue.popleft()
    return count

def solution(begin, target, words):
    if not target in words:
        return 0
    answer = bfs(words, begin, target)
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/e2eab2af-1981-48d9-9b2b-28546e3008d3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS/BFS - 게임 맵 최단거리]]></title>
            <link>https://velog.io/@my_youth99/DFSBFS-%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</link>
            <guid>https://velog.io/@my_youth99/DFSBFS-%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</guid>
            <pubDate>Fri, 06 Oct 2023 01:22:40 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/1844">https://school.programmers.co.kr/learn/courses/30/lessons/1844</a></p>
<p>백트래킹?? dfs?? bfs?? 
일단 2차원배열 동서남북이니까 x,y 이동을 따로 리스트로 만들어야겠다고 생각
처음엔 무조건 dfs로 풀어봐야지~ 하고 해봤는데 답이 잘 안나오는 듯했다. 질문하기를 보니 BFS를 푸는 것같다.
맵의 최단경로같은거 구할 때는 BFS 생각해보기...</p>
<p>근데 bfs 툴은 외워서 쓰겠는데 그래서 이걸 어떻게하지? 생각 뿐</p>
<pre><code>from collections import deque

def bfs(graph, start, visited):
    queue = dequeue([start])
    visited[start] = True
    while queue:
        v = queue.popleft()
        for i in graph[v]:
            if not visited[i]:
                queue.append(i)
                visited[i] = True

def solution(maps):
    answer = 0
    # 최단 경로, 백트래킹?
    n,m = len(maps), len(maps[0])

    dx = [-1,1,0,0] # 동 서 남 북
    dy = [0,0,1,-1] # 동 서 남 북

    visited = [[False] * m for _ in range(n)]


    return answer</code></pre><p>   결국 구글링의 도움 ㄱㄱㄱㄱ...
   2차원배열이라 튜플형태를 활용하는 듯했다.</p>
<pre><code>from collections import deque # queue 라이브러리 삽입

def bfs(maps, visited, n, m):

    if not maps[n - 2][m - 1]: #다 막혀있는 곳이면
        return -1

    queue = deque([(0, 0)]) # 현재 위치
    visited[0][0] = True # 방문 처리

    dx = [-1,1,0,0] # 동 서 남 북
    dy = [0,0,1,-1] # 동 서 남 북

    while queue:
        y, x = queue.popleft()

        for i in range(4):  # 동서남북

            nx = x + dx[i] # 가게 될 위치를 계산 (열)
            ny = y + dy[i] # 행

            # 갈 수 있는 방향이고 면적을 벗어나지 않는 경우
            if 0 &lt;= nx &lt; m and 0 &lt;= ny &lt; n and maps[ny][nx]:

                if not visited[ny][nx]:
                    visited[ny][nx] = True # 방문처리

                    queue.append((ny, nx)) # 큐 삽입
                    maps[ny][nx] = maps[y][x] + 1 # 최단경로 갱신


    return maps[n - 1][m - 1]

def solution(maps):
    n,m = len(maps), len(maps[0])

    visited = [[False] * m for _ in range(n)]
    answer = bfs(maps, visited, n, m)
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/e83f486a-b013-43b9-98a6-a562086a7441/image.png" alt="">
근데 무엇인가  통과가 안되고있다...
일단 효율성에서도 통과가 안되었고  ㅠ
결과에서도 실패가 떠서 단순히 시간초과 문제가 아닌듯</p>
<p>벽에 다 막혀있는 경우를 제대로 고려하지않아서인가 싶어서 좀 더 고쳐보았다.</p>
<pre><code>from collections import deque # queue 라이브러리 삽입

def bfs(maps, visited, n, m):

    if (not maps[n - 2][m - 1]) and 
    (not maps[n-2][m-2]) and (not maps[n-1][m-2]): #다 막힘
        return -1

    queue = deque([(0, 0)]) # 현재 위치
    visited[0][0] = True # 방문 처리

    dx = [-1,1,0,0] # 동 서 남 북
    dy = [0,0,1,-1] # 동 서 남 북

    while queue:
        y, x = queue.popleft()

        for i in range(4):  # 동서남북

            nx = x + dx[i] # 가게 될 위치를 계산 (열)
            ny = y + dy[i] # 행

            # 갈 수 있는 방향이고 면적을 벗어나지 않는 경우
            if 0 &lt;= nx &lt; m and 0 &lt;= ny &lt; n and maps[ny][nx]:

                if not visited[ny][nx]:
                    visited[ny][nx] = True # 방문처리

                    queue.append((ny, nx)) # 큐 삽입
                    maps[ny][nx] = maps[y][x] + 1 # 최단경로 갱신


    return maps[n - 1][m - 1]

def solution(maps):
    n,m = len(maps), len(maps[0])

    visited = [[False] * m for _ in range(n)]
    answer = bfs(maps, visited, n, m)
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/5374bc65-896e-42bc-9576-27fa740355d4/image.png" alt=""></p>
<p>효율성은 다 통과가 되었으나 실행평가에서 아직도 막혔음
질문하기를 보니까 상대측 진영에서 벽으로 다 막히지않아도 도달하지못할 수도 있는 것을 고려해야함</p>
<p>그러면 내 쪽에서 벽이 생겼나??? 너무 단순하게 (0,1), (1,0) 쪽만 막히면 되나? 싶어서 조건을 걸었는데 런타임 에러나는 테스트 케이스도 있었다.</p>
<p>근데 조건을 보니까 <strong>n,m이 1인 경우는 없다</strong>고 한다.
<strong>그러면 최단경로의 거리는 최소 1보단 커야한다. (동서남북이니까 대각선은 못할테고)</strong>
그래서 만약 구한 경로의 길이가 1이면 안된다고 생각하고 return -1로 해볼까? 했는데 통과가 되었다;;; 이게 되네</p>
<p>코드를 더 다듬으려고 보니, 그럼 굳이 상대측 진영 근처도 막혀있는지 확인안해도 될 것같아서 지우고 돌려보니 통과가 된다.</p>
<pre><code>from collections import deque # queue 라이브러리 삽입

def bfs(maps, visited, n, m):

    queue = deque([(0, 0)]) # 현재 위치
    visited[0][0] = True # 방문 처리

    dx = [-1,1,0,0] # 동 서 남 북
    dy = [0,0,1,-1] # 동 서 남 북

    while queue:
        y, x = queue.popleft()

        for i in range(4):  # 동서남북

            nx = x + dx[i] # 가게 될 위치를 계산 (열)
            ny = y + dy[i] # 행

            # 갈 수 있는 방향이고 면적을 벗어나지 않는 경우
            if 0 &lt;= nx &lt; m and 0 &lt;= ny &lt; n and maps[ny][nx]:

                if not visited[ny][nx]:
                    visited[ny][nx] = True # 방문처리

                    queue.append((ny, nx)) # 큐 삽입
                    maps[ny][nx] = maps[y][x] + 1 # 최단경로 갱신

    return maps[n - 1][m - 1]

def solution(maps):
    n,m = len(maps), len(maps[0])
    visited = [[False] * m for _ in range(n)]
    answer = bfs(maps, visited, n, m)
    if answer == 1 :
        return -1
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/6edd8339-658c-450c-8b98-d361379a5b4f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS/BFS - 네트워크]]></title>
            <link>https://velog.io/@my_youth99/DFSBFS-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@my_youth99/DFSBFS-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Thu, 05 Oct 2023 08:50:46 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/43162">https://school.programmers.co.kr/learn/courses/30/lessons/43162</a>
<img src="https://velog.velcdn.com/images/my_youth99/post/d51e7a1a-bc1c-4dbf-9d68-2780d8b7ba37/image.png" alt=""></p>
<p>dfs중심으로 만들어보았다. 하지만 여기서 어떻게 답을 이끌어낼까 고민을 하는 중..</p>
<pre><code>def dfs(graph, v, visited):
    visited[v] = True
    print(v, end=&#39; &#39;) #graph[v]가 아니다
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)

def solution(n, computers):
    answer = 0
    n = len(computers)

    graph = [[] for _ in range(n+1)] # 그래프 생성

    for i in range(n):
        for j in range(n):
            if i!= j and computers[i][j]:
                graph[i+1].append(j+1)
    visited = [False] * (n+1)
    dfs(graph, 1, visited)    

    return answer</code></pre><p>탐색한 경로는 다음과 같다 <img src="https://velog.velcdn.com/images/my_youth99/post/b1105001-7669-410a-96c2-5b56bef8347c/image.png" alt=""> 근데 내가 원하는건 탐색경로가 아닌 이어진거냐 아니냐인데... <img src="https://velog.velcdn.com/images/my_youth99/post/a20d6532-c668-4a7a-8a5a-64aac13bed17/image.png" alt=""> 이걸 어떻게 활용할수가 없을까..
일단 output은 네트워크 대역을 계산하는거니까 연결되지 않은 것들만 전체 컴퓨터 개수에서 빼면 나오지 않나..</p>
<pre><code>def dfs(graph, v, visited):
    visited[v] = True
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)

def solution(n, computers):
    answer = 0
    n = len(computers)

    graph = [[] for _ in range(n+1)] # 그래프 생성

    for i in range(n):
        for j in range(n):
            if i!= j and computers[i][j]:
                graph[i+1].append(j+1)
    visited = [False] * (n+1)
    dfs(graph, 1, visited)

    answer = [ 1 for bol in visited if bol]
    answer = len(computers) - (len(answer)-1)
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/525d76a8-ba4f-4a70-8bd3-53a23e233839/image.png" alt=""></p>
<p>머리가 빠개질것같다 ...... 결국 구글링의 힘을 썼다.</p>
<p><a href="https://daeun-computer-uneasy.tistory.com/70">참고 링크</a></p>
<pre><code>

def solution(n, computers):
    answer = 0
    n = len(computers)

    visited = [False] * (n+1)

    def dfs(v):
        visited[v] = True
        for com in range(n):
            if not visited[com] and computers[v][com]:
                dfs(com)

    count = 0
    for i in range(n):
        if not visited[i]:
            dfs(i)
            count += 1

    return count</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/0b602bf2-f91c-44d6-8a90-188d02f8154e/image.png" alt=""> 맞긴했는데.. 내 힘으로 푼게 아니라서 너무 찝찝하다..</p>
<p>그니까 처음 0번째 컴퓨터에서 연결된 네트워크들을 확인한다.
visited[0] and ~ 하기도 전에 visited[0] 은 이미 지나갔으니 패스
visited[1] and computers[0][1] =&gt; dfs(1)
=&gt; visited[1] = True =&gt; visited[2] and computers[2][1] =&gt; dfs(2) =&gt; visited[2] = True =&gt; None =&gt; dfs(2) 완료 (여기서 count 가 1 증가)=&gt; visited[2] and computers[2][2] =&gt; dfs(2) 완료 =&gt; count 1 증가..? </p>
<p>*<em>DFS로 최대한 탐색하고 빠져나가면 그것이 하나의 네트워크라고 한다.
*</em></p>
<p>조금 더 찾아보니 아까 dfs 코드로 짠거랑 비슷한 코드가 있어서 다시 한번 써본다.</p>
<p><a href="https://muhly.tistory.com/88">참고한 링크</a></p>
<pre><code>def dfs(computers, visited, n, com):
    visited[com] = True
    for c in range(n):
        if c != com and computers[com][c] == 1:
            if not visited[c]:
                dfs(computers, visited, n, c)

def solution(n, computers):
    answer = 0
    n = len(computers)
    visited = [False] * (n+1)
    count = 0

    for i in range(n):
        if not visited[i]:
            dfs(computers, visited, n, i)
            count += 1

    return count
</code></pre><p>  굳이 그래프를 따로 만드려고 고군분투하지 않아도 된다.. .그냥 있는거 잘 써보자. 그리고 이차원 배열 접근을 너무 어색해하지말고 ㅠㅠ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[완전 탐색 - 카펫]]></title>
            <link>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%B9%B4%ED%8E%AB</link>
            <guid>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%B9%B4%ED%8E%AB</guid>
            <pubDate>Thu, 05 Oct 2023 07:08:42 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42842">https://school.programmers.co.kr/learn/courses/30/lessons/42842</a></p>
<p>이거까지 풀고 dfs/bfs를 푼다음 다시 완전 탐색으로 넘어가야하나 고민된다.. 시간이 좀 많이 부족한 듯 ㅠ </p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5043f852-75dc-4ee3-ad2f-4d642907c2f2/image.png" alt=""><del>(혼란 그 자체...)</del></p>
<p>24, 24 테스트 케이스를 골똘히 생각하다가 약수?? 라는 생각을 했다. 그러다가 질문하는 내용들을 보다가 약수로 고려하는 것들이 있길래 접근방법이 맞겠구나 싶어 약수를 구하는 쪽으로 해보았다.</p>
<pre><code>def Div(x):
    div = []
    for i in range(1,(x//2)+1):
        if x%i == 0:
            div.append(i)
    a = div[len(div)//2]
    b = x//a
    return a,b

def solution(brown, yellow):
    answer = []
    bx, by = 0, 0
    if yellow &gt; 1:
        a, b =Div(yellow)
        a += 2
        b += 2
        if a &gt; b:
            bx, by = a, b
        else:
            bx, by = b, a
    else:
        bx = 1 + 2
        by = 1 + 2

    answer.append(bx)
    answer.append(by)</code></pre><p>패기롭게 냈지만 테스트 케이스 몇 개가 통과되질 않는다 ㅠㅠ
<img src="https://velog.velcdn.com/images/my_youth99/post/0f10a50d-6b55-4e62-9711-36c866c50be6/image.png" alt=""></p>
<p>일단 너무 임의로 잡은게 크다;
약수를 꼭 중간자리에서 찝어야해? 
그리고 1이 고정이 아닐 수도 있고.. 쫌 엉망진창이긴 하다;</p>
<p>조건을 설정해주고 brown의 가로는 yellow 가로의 +2 .. 이런식으로 바꿔서 해주자.</p>
<pre><code>def Div(x):
    div = []
    for i in range(1,x+1):
        if x%i == 0:
            div.append(i)
    return div

def solution(brown, yellow):
    answer = []
    yx, yy = 0, 0
    bx, by = 0, 0

    div = Div(yellow)
    for num in div:
        find = ((brown-num*2)//2)-2
        if (find in div) and (find*num == yellow):
            if find &gt; num:
                yx, yy = find, num
            else:
                yx, yy = num, find
            break
    bx = yx + 2
    by = yy + 2

    answer.append(bx)
    answer.append(by)
    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/960134cf-ead5-411e-aff6-9deddb5437f2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[완전 탐색 - 소수 찾기]]></title>
            <link>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Thu, 05 Oct 2023 06:10:06 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42839">https://school.programmers.co.kr/learn/courses/30/lessons/42839</a></p>
<p>일단 라이브러리를 사용해서 조합을 구하는게 제일 첫번째인 것같다.
조합은 itertools에서 permutations을 import하면 사용할 수 있었다.</p>
<pre><code>from itertools import permutations</code></pre><p>만약 3개의 숫자가 있으면 1개만 뽑아서 쓰는 조합, 2개만 뽑아서 쓰는 조합, 3개만 뽑아서 쓰는 조합 이렇게 되니까 for문을 돌려 permutations 함수를 써야한다.</p>
<pre><code>permutat = []
    for n in range(1, len(numbers)+1):
        permutat += list(permutations(numbers, n))
</code></pre><p>처음엔 append를 사용했는데 그러면 좀 드럽게 나온다 ㅡㅡ;
<img src="https://velog.velcdn.com/images/my_youth99/post/e9744553-45d6-421b-a8a1-63f517ce2cb8/image.png" alt=""></p>
<p>그다음은 join함수와 int변환을 통해 곧바로 숫자를 조합해서 정수로 만들도록 한다. 그리고 나선 소수 판별이 관건.</p>
<p>소수 판별이 제일 어렵지않을까 고민했는데 구글링해보니 간단했다.</p>
<p>for문을 돌리면서 2부터 루트(소수판별할 수)까지 나눠지는 경우가 있는지 확인하면 되는 것이다 (%연산자를 통해 0이면 나눠지니까 바로 소수가 아니니 False)</p>
<p>근데 왜 범위가 루트로 씌워서 할까?
일단 계산의 복잡도를 줄이기 위해서라는건 알겠다.
하지만 루트를 씌우면 모든 경우의 수를 고려할 수 있을까?</p>
<p>예를 들어 17를 생각해보자.
17은 1, 17으로만 약수가 나오기때문에 소수.</p>
<p>[9]
1 3 9
1<em>9 = 9
3</em>3 = 9</p>
<p>[10]
1 2 5 10
1<em>10 = 10
2</em>5 = 10
어차피 대칭이라는 특징을 갖고있으니까 반절만 보면 그만이라는 것.
그니까 루트를 잘 사용하자.</p>
<p>루트를 잘 쓸일이 없어 헷갈리니 좀 더 정리하다
math 라이브러리를 불러와야하고 sqrt함수를 사용하면 된다.</p>
<p>최종 코드다.</p>
<pre><code>import math
from itertools import permutations

# 소수인지 판별
def prime(x):
    for i in range(2, int(math.sqrt(x)) + 1):
        if x % i == 0:
            return False
    return True

def solution(numbers):
    answer = 0
    permutat = []
    for n in range(1, len(numbers)+1):
        permutat += list(permutations(numbers, n))
    permutat = [int((&quot;&quot;).join(p)) for p in permutat]
    permutat = list(set(permutat))

    ct = 0
    for num in permutat:
        if num == 0 or num == 1:
            continue
        if prime(num):
            ct += 1
    return ct</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/1b184dce-ccf5-4b2f-b3ee-9307679356d4/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[완전 탐색 - 모의고사]]></title>
            <link>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</link>
            <guid>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</guid>
            <pubDate>Wed, 04 Oct 2023 05:10:10 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42840#">https://school.programmers.co.kr/learn/courses/30/lessons/42840#</a></p>
<p>문제의 개수에 따라 수포자의 답안을 만들어준다.
수포자의 답안 패턴 개수보다 문제의 개수가 많을 경우, 나누기와 나머지를 통해 답안 작성 ..</p>
<p>그 후 루프를 통해 정답이 맞았는지 확인하면서 점수 매긴다.
그 다음은 가장 높은 점수를 얻은 학생들을 리스트에 넣어서 반환한다.</p>
<pre><code># 답안 작성
def sub_answers(answers, s):
    if len(answers) &gt; len(s):
        div = len(answers) // len(s)
        res = len(answers) % len(s)
        sub_s = s[:]
        for i in range(div-1):
            s += s
        s += sub_s[:res]
    return s

# 채점
def grade(answers, s):
    score = 0
    for idx, answer in enumerate(answers):
        if answer == s[idx]:
            score += 1
    return score

def solution(answers):

    s1 = [1,2,3,4,5]
    s2 = [2,1,2,3,2,4,2,5]
    s3 = [3,3,1,1,2,2,4,4,5,5]

    # 1번 수포자 답안
    if len(answers) &gt; len(s1):
        s1 = sub_answers(answers,s1)
        print(s1)
    else:
        s1 = s1[:len(answers)]

    # 2번 수포자 답안
    if len(answers) &gt; len(s2):
        s2 = sub_answers(answers,s2)
    else:
        s2 = s2[:len(answers)]

    # 3번 수포자 답안
    if len(answers) &gt; len(s3):
        s3 = sub_answers(answers,s3)
    else:
        s3 = s3[:len(answers)]

    # 채점 결과
    s1_grade = grade(answers,s1)
    s2_grade = grade(answers,s2)
    s3_grade = grade(answers,s3)


    answer = []
    max_grade = max(s1_grade, s2_grade, s3_grade)
    # 높은 점수 받은 사람이 여럿일 경우 고려
    if max_grade == s1_grade:
        answer.append(1)
    if max_grade == s2_grade:
        answer.append(2)
    if max_grade == s3_grade:
        answer.append(3)

    return answer</code></pre><p>패기롭게 냈지만..</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/4ca73def-6f57-4d0f-9b35-28b7f777ae91/image.png" alt="">
시간초과로 틀리게 되었다. 아슬아슬하긴 했는데.. 진짜 이렇게 되네
어디서부터 시간 초과가 되었을까.. max함수를 없애보았는데 그건 문제가 안되는듯</p>
<p>아무래도 sub_answers 함수에서 시간초과가 되는건가?
한번 오류가 나더라도 sub_answers를 없애고 돌려보았다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/17107001-0692-4463-8497-f2945f992347/image.png" alt=""></p>
<p>이번에는 시간초과가 뜨지않았다. 결국 답안 작성에서 시간초과가 되었다는건데... for문을 돌려서 답안 작성하지않고 그냥 바로 곱하기로 때려박았다.</p>
<pre><code># 답안 작성
def sub_answers(answers, s):
    div = len(answers) // len(s)
    res = len(answers) % len(s)
    sub_s = s[:]
    s = s*(div)
    s += sub_s[:res]
    return s

# 채점
def grade(answers, s):
    score = 0
    for idx, answer in enumerate(answers):
        if answer == s[idx]:
            score += 1
    return score

def solution(answers):

    s1 = [1,2,3,4,5]
    s2 = [2,1,2,3,2,4,2,5]
    s3 = [3,3,1,1,2,2,4,4,5,5]

    # 1번 수포자 답안
    if len(answers) &gt; len(s1):
        s1 = sub_answers(answers,s1)
    else:
        s1 = s1[:len(answers)]

    # 2번 수포자 답안
    if len(answers) &gt; len(s2):
        s2 = sub_answers(answers,s2)
    else:
        s2 = s2[:len(answers)]

    # 3번 수포자 답안
    if len(answers) &gt; len(s3):
        s3 = sub_answers(answers,s3)
    else:
        s3 = s3[:len(answers)]

    # 채점 결과
    s1_grade = grade(answers,s1)
    s2_grade = grade(answers,s2)
    s3_grade = grade(answers,s3)


    answer = []
    max_grade = max(s1_grade, s2_grade, s3_grade)
    # 높은 점수 받은 사람이 여럿일 경우 고려
    if max_grade == s1_grade:
        answer.append(1)
    if max_grade == s2_grade:
        answer.append(2)
    if max_grade == s3_grade:
        answer.append(3)

    return answer</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/405f2f47-da76-4948-9eaa-0c528f2e3f2c/image.png" alt=""></p>
<p>(+) 더 효율적인 방식이 있을까? 하고 찾아봤는데</p>
<pre><code>   for idx, answer in enumerate(answers):
        if answer == pattern1[idx%len(pattern1)]:
            score[0] += 1
        if answer == pattern2[idx%len(pattern2)]:
            score[1] += 1
        if answer == pattern3[idx%len(pattern3)]:
            score[2] += 1</code></pre><p>이런식으로 풀 수도 있었다. 굳이 답안을 만들지않고 그냥 %연산을 통해서만 하면 제일 깔끔했다... ^_^ 넘 슬프고..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[완전 탐색 - 최소 직사각형]]></title>
            <link>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%B5%9C%EC%86%8C-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</link>
            <guid>https://velog.io/@my_youth99/%EC%99%84%EC%A0%84-%ED%83%90%EC%83%89-%EC%B5%9C%EC%86%8C-%EC%A7%81%EC%82%AC%EA%B0%81%ED%98%95</guid>
            <pubDate>Wed, 04 Oct 2023 04:27:07 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/86491">https://school.programmers.co.kr/learn/courses/30/lessons/86491</a></p>
<p>우선 가로 세로 중에 제일 큰 수를 구한다.
가로가 제일 클 경우, 명함들 중 가로보다 세로가 큰 경우를 찾아서 가로 -&gt; 세로, 세로 -&gt; 가로 스왑해준다.
세로가 제일 클 경우, 명함들 중 세로보다 가로가 큰 경우를 찾아서 세로 -&gt; 가로, 가로 -&gt; 세로 스왑해준다.</p>
<p>그 후, 스왑해준 세로(가로) 중에 제일 큰 수를 구한다음, 
처음 구했던 제일 큰 수와 곱해서 면적을 구하면 된다.</p>
<pre><code>def solution(sizes):
    w = [sizes[i][0] for i in range(len(sizes))]
    h = [sizes[i][1] for i in range(len(sizes))]
    max_w, max_h = max(w), max(h)
    if max_w &gt; max_h:
        total_max = max_w   
        for i in range(len(sizes)):
            if sizes[i][1] &gt; sizes[i][0]:
                w[i], h[i] = h[i], w[i]
        max_h = max(h)
        answer = max_h * total_max
    else:
        total_max = max_h
        for i in range(len(sizes)):
            if sizes[i][0] &gt; sizes[i][1]:
                h[i], w[i] = w[i], h[i]
        max_w = max(w)
        answer = max_w * total_max
    return answer</code></pre><p>처음으로 바로 통과가 되었다 ㅠ 
사실 처음에 완전 탐색이라길래 백트래킹을 생각해야하나, dfs를 써야하나 별 생각을 다했는데 그냥 쉽게 생각하면 바로 풀리는 거였다.
<img src="https://velog.velcdn.com/images/my_youth99/post/9f6d5dab-7b32-47bd-956d-94272ad36646/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/df0049e1-3bc0-425e-8364-7f5af89fec6a/image.png" alt=""></p>
<p>(+) 좀 더 코드를 잘 정리할 순 없을까 싶어서 한번 찾아보았다.
굳이 w,h 리스트를 만들어서 max를 찾고...... 이렇게 할 필요는 없다. 해당 과정을 과감히 삭제하고
스왑 과정을 살린 다음, max함수를 때려버리면 된다.</p>
<pre><code>def solution(sizes):
    r, c = 0,0
    for row, col in sizes:
        if row &gt; col:
            row, col = col, row
        r = max(r, row)
        c = max(c, col)
    return r*c</code></pre><p>내가 너무 단순하게 생각했다. 스왑할 때 리스트 요소를 직접 스왑해야한다고 생각했는데, 굳이 직접 스왑안하고 그냥 변수로써 임시저장 느낌으로 스왑을 해주고 max 함수를 통해 최대를 계속 구하기만 하면 되는 거였다. 
이러니 코드가 훨씬 깔끔해졌다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[탐욕법(greedy) - 구명보트]]></title>
            <link>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%EA%B5%AC%EB%AA%85%EB%B3%B4%ED%8A%B8</link>
            <guid>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%EA%B5%AC%EB%AA%85%EB%B3%B4%ED%8A%B8</guid>
            <pubDate>Tue, 03 Oct 2023 08:33:49 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42885">https://school.programmers.co.kr/learn/courses/30/lessons/42885</a></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/78162a2b-a8b5-4d00-bef5-f602b9e8da5a/image.png" alt="">
우선 의식의 흐름대로 코드를 짜보았다.
사람들의 무게 리스트를 정렬해서 제일 먼저 태울 사람들을 묶었다.
그리고 누적된 kg이 초과되면 그룹을 자르고 다시 그룹 묶는 식으로</p>
<pre><code>def solution(people, limit):
    people.sort() # 무게 정렬
    kg = 0 # 누적할 kg

    sub_list = []
    total = []
    idx = 0
    for idx, num in enumerate(people):
        kg += num
        #print(f&quot;num = {num}, {kg}kg, limit = {limit}&quot;)
        if kg == limit:
            sub_list.append(num)
            total.append(sub_list)
            sub_list = []
            kg = 0
        elif kg &gt; limit:
            total.append(sub_list)
            sub_list= []
            sub_list.append(num)
            total.append(sub_list)
            kg = 0
        else:
            if idx == len(people)-1:
                sub_list = []
                sub_list.append(num)
                total.append(sub_list)
                break
            sub_list.append(num)
    return len(total)</code></pre><p>하지만 어림없지</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/ac19fbb2-a862-4bd0-bacc-e7dfcfbef952/image.png" alt=""></p>
<p>슬라이싱을 통해 코드를 좀더 간결하게 해보았다. </p>
<pre><code>def solution(people, limit):
    people.sort() # 무게 정렬
    kg = 0 # 누적할 kg

    sub_list = []
    total = []
    start = 0    
    for idx, num in enumerate(people):
        kg += num # kg 누적 

        if kg == limit: # 만약 limit에 딱 맞으면 그룹 나누기
            total.append(people[start:idx+1])
            sub_list, kg, start = [], 0, idx+1 # 초기화
        elif kg &gt; limit: # 초과되어도 그룹 나누기
            total.append(people[start:idx])
            start = idx
        if idx == len(people)-1:
            total.append(people[start:])
            break
        sub_list.append(num)
    return len(total)</code></pre><p><img src="https://velog.velcdn.com/images/my_youth99/post/bcf549d7-7b1b-4891-b650-73b69d2b6ac9/image.png" alt="">
깔끔하게 그룹이 나눠지는 듯 함. 하지만 통과가 안되는 것은 여전히 마찬가지 .. 일단 시간초과는 안뜨긴했으니 (효율성에서 통과는 못했지만) 먼저 고려하지못한 테스트케이스에 대해서 생각해보자</p>
<p>질문하기에서 사람들의 질문을 찬찬히 보았다. 근데 아.. ㅋㅋㅋㅋㅋㅋㅋㅋ 다시 읽어보니 단 2명이다 ... 난독증 미쳤고 ㅎㅎ</p>
<p>그러면 왜 가장 큰 무게인 사람과 가장 가벼운 사람인 사람을 넣어야하는지 이해가 된다. 가장 큰 무게인 사람을 보트에 단 한명만 넣으면 너무 손해니까 어떻게든 끼역넣어야겠지..</p>
<p><a href="https://liveloper-jay.tistory.com/139">참고한 링크</a></p>
<p>내 입맛대로 바꾸고있는데 계속 테케가 걸려서
될대로 되라 심정으로 일단 제출을 했는데 다 통과가 되었다. 않이 이게 왜 되는거지?? 
<img src="https://velog.velcdn.com/images/my_youth99/post/84001854-9759-4f5a-a047-69432eda35ae/image.png" alt=""></p>
<pre><code>def solution(people, limit):

    people.sort() # 무게 정렬

    start, end = 0, len(people)-1
    boat = 0

    while (start &lt;= end): # 반절을 넘기면 안됨
        if start == end : 
            boat += 1
            break
        if people[start] + people[end] &lt;= limit:
            start += 1
            end -= 1
            boat += 1
            continue
        else:
            end -= 1
        boat += 1
    return boat</code></pre><p>boat를 추가하는 타이밍이 애매해서 일단 닥치는대로 넣어보았다.</p>
<ol>
<li><p>우선 한도에 맞게 그룹이 짝지어진 경우
boat를 추가해서 넣어주기</p>
</li>
<li><p>만약 한도 초과면 따로 넣어야하니까 boat 추가해서 넣어주기..
뭐야 결국 다 boat 추가 아닌가?;;</p>
</li>
</ol>
<p>코드를 다시 바꿔보았다.</p>
<pre><code>def solution(people, limit):

    people.sort() # 무게 정렬

    start, end = 0, len(people)-1
    boat = 0

    while (start &lt;= end): # 반절을 넘기면 안됨
        boat += 1
        if start == end :
            break
        if people[start] + people[end] &lt;= limit:
            start += 1
            end -= 1
            continue
        else:
            end -= 1

    return boat</code></pre><p><strong style="color:red">어차피 보트는 항상 나가게 되어있고 거기서 인원이 1명이나 2명이냐 그 뿐인 것같다.</strong> </p>
<p>코드가 좀 와닿진 않긴한데.. 튼 그렇다 
찝찝하게 끝났다.. ㅎㅎㅎ Lv3까지 하기엔 시간이 너무 없기때문에 Lv2까지만 풀고 그리디의 고난도 문제 풀이는 끝</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[탐욕법(greedy) - 큰 수 만들기]]></title>
            <link>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%ED%81%B0-%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%ED%81%B0-%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 03 Oct 2023 07:03:58 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42883">https://school.programmers.co.kr/learn/courses/30/lessons/42883</a></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5eac47ff-e666-4334-aa12-90defab6d9fd/image.png" alt=""> 근데 이렇게 하면 문제점이 있다. 마지막 예시에서 걸린다는 점. 어쩐지 너무 단순하게 생각한다 했다.</p>
<p>우선 초기 코드는 다음과 같다. (코드 정리를 제대로 하지않아 필요없는 중복된 변수가 있다던지 .. 좀 엉망이다)</p>
<pre><code>def solution(number, k):

    number = list(map(int, number))
    _number = number[:]
    __number = number[:]
    n = len(number) - k
    answer = list()

    while True: # 제일 앞 자리에 둘 숫자를 구하기
        max_number = max(_number)
        max_idx = number.index(max_number)
        if max_idx &lt;= n:
            answer.append(max_idx)
            break
        else: # 만약 큰 숫자가 중복으로 나올 수 있으니, idx가 잘 안나올 수 있음을 방지
            number[max_idx] = -1
            del _number[max_idx]

    number = __number[:]
    _number = number[max_idx:]
    ct = k - max_idx
    while True: # 제일 작은 숫자 구하기
        if ct == 0:
            break
        min_number = min(_number)
        min_idx = _number.index(min_number)
        answer.append(min_number)
        ct -= 1
        _number[min_idx] = 100


    number = number[max_idx:]
    for i in answer[1:]:
        number.remove(i)  
    return &#39;&#39;.join(str(s) for s in number)
</code></pre><p>일단 실행시간도 걸리는지 확인할 겸 제출을 해보자.
음 당연하듯이 오래걸린다.. 실행시간도 오래 걸린다 ^^ 총체적 난국!
테스트 케이스 1,7,8,10 이 시간 초과로 걸린다.</p>
<p>아 생각해보니 정렬을 안했네. 정렬이 키워드일 것같다.
정렬을 해보고 다시 해보자. ... 라 했지만 잘 안된다.</p>
<p>구글링을 통해 좀더 생각 정리를 해보았다.
스택 이라는 방법이 있었다.
그렇지 ..애초에 리스트를 0번째부터 지나가면서 제거할 숫자를 고르는거니까 스택을 생각하는게 맞겠다 싶었다.</p>
<p><a href="https://velog.io/@soo5717/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%81%B0-%EC%88%98-%EB%A7%8C%EB%93%A4%EA%B8%B0-%ED%8C%8C%EC%9D%B4%EC%8D%AC">참고한 풀이 링크</a></p>
<p>하 진짜 다들 천재인가 싶다.. 내가 너무 복잡하게 생각했음
코드가 확 줄여지는 거 보고 자괴감이 들었다 </p>
<pre><code>def solution(number, k):
    answer = []
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때
        print(answer, num)

        # answer[-1] &lt; num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k &gt; 0 and answer and answer[-1] &lt; num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 =&gt; [1]
        answer.append(num)
    print(answer)
    return &#39;&#39;</code></pre><p>돌아가는 순서는 다음과 같다</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/e448cce9-5531-494d-85dc-c1b38db4204a/image.png" alt=""></p>
<p>가장 최적의 수를 계속해서 stack에 적립을 해주고 만약 더 큰게 있으면 걔를 넣어주고 그런식의 반복
while문을 통해서 만약 ct 범위 내에 가장 큰 수가 나오면 모두 pop해서 없애주는 형식임. ㄹㅇ 천재인가 ㅠ 진짜 왜 저렇게 생각을 못했지</p>
<pre><code>def solution(number, k):
    answer = []
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때        
        # answer[-1] &lt; num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k &gt; 0 and answer and answer[-1] &lt; num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 =&gt; [1]
        answer.append(num)
    return &#39;&#39;.join(num for num in answer)</code></pre><p>근데 이렇게 해주니까 마지막 테스트 케이스에서 걸린다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/d4b8e940-947c-4b6e-9e80-2236d4376b6f/image.png" alt=""></p>
<p>이번에도 열심히 구글링..
<img src="https://velog.velcdn.com/images/my_youth99/post/69b9ba0d-0f4d-46b2-93b4-91304e4bb341/image.png" alt=""> k를 중심으로 프린트 해보니까 오류나는 테스트케이스에서 k가 남아있었다. 그럼 걔를 제외해보고 프린트 해보았다.
<img src="https://velog.velcdn.com/images/my_youth99/post/6e906b4d-5c74-478d-adfd-c3e567025474/image.png" alt=""> 답이 나오는 걸 볼 수 있었다. 그럼 다시 return값을 조정해주자.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5a14cafa-a88e-4305-9ebb-e3d0c3f9f035/image.png" alt=""> 드디어 완ㄹ료 ^^.... 나 코테 합격할 수 있을까.. 막막하다</p>
<pre><code>def solution(number, k):
    answer = []
    n = k
    for num in number: #1,9,2,4
        # 남은 자릿수가 있고, 스택이 비어있지 않으며, 
        # 스택의 마지막에 쌓인 것이 현재 num보다 작을 때        
        # answer[-1] &lt; num 일 때 pop 하는 이유는?
        # 최적으로 큰 수를 구해야하는데 지금 나온 숫자가 더 크면 개를 써야지
        while k &gt; 0 and answer and answer[-1] &lt; num:
            answer.pop()
            k -= 1
        # 처음엔 스택이 비어있음 =&gt; [1]
        answer.append(num)
    return &#39;&#39;.join(answer[:len(answer)-k])</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[탐욕법(greedy) - 조이스틱 (보류)]]></title>
            <link>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1-%EB%B3%B4%EB%A5%98</link>
            <guid>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95greedy-%EC%A1%B0%EC%9D%B4%EC%8A%A4%ED%8B%B1-%EB%B3%B4%EB%A5%98</guid>
            <pubDate>Mon, 02 Oct 2023 08:08:54 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42860?language=python3">https://school.programmers.co.kr/learn/courses/30/lessons/42860?language=python3</a></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/4788fb5e-a595-4066-b4e7-90da51ffe030/image.png" alt=""></p>
<p>아스키 코드를 확인해보면 다음과 같았다.
<img src="https://velog.velcdn.com/images/my_youth99/post/1e812fe4-c1b1-4155-b439-877e2c9bd3de/image.png" alt=""></p>
<p>그럼 정렬을 해주고.. 그러면 되지않나?
근데 정렬해주기 전에 원래 위치는 기억을 해야할 것같고.. 그럼 복사를 해줘야할 것같고 ..</p>
<p>대문자 &quot;A&quot;의 아스키코드는 65란다.
&quot;Z&quot;는 90</p>
<p>그러면 65 ~ 77는 A에서 이동
90 ~ 78는 Z에서 이동이 좋을 듯</p>
<p>근데 65에서 뺀 리스트들로 만들어줬으니
0 ~ 12까지가 A에서 이동
13 ~ 25까지가 Z에서 이동하면 되려나</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/421d3edd-1e84-426b-9f7a-a6d17dc22006/image.png" alt=""></p>
<p>그러면 이제 얘네를 중심으로 한번 최소값을 구하면 되지않나? 
같은 애들은 set으로 해주면 나중에 위치 찾을 때 힘드려나? 고민.. 위치는 enumerate를 써서 튜플로 저장하는게 더 좋은가?? 
그럼 dfs 나 bfs 느낌.. 혹은 최단 경로 느낌 나는데??</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5f0b7c06-afa8-4dab-8695-ad71678b619d/image.png" alt=""></p>
<p>일단 위치 제외하고 대략 해봤다.
Z에서부터도 해야하니까 min 함수를 활용하는 법이 있었다. 잘 기억하는게 좋을듯</p>
<p>위치가 제일 어려운 듯
최소한으로 어떻게 이동하냐고 ..?
근데 이게 그리디가 맞냐..?????? 물음표만 가득</p>
<p>내가 기억하는 dfs의 기본형태는 이거</p>
<pre><code>def dfs(graph, v, visited):
    visited[v] = True
    for i in graph[v]:
        if not visited[i]:
            dfs(graph, i, visited)</code></pre><p><del>음... 사용할 수 있나? graph 형태가 이게 아닌 듯 하다. 일단 위치를 왼쪽갔다가 오른쪽 갔다가 해야하는 기준은 A가 얼마나 많이 있느냐의 차이일 것같은데 JAZ같은 경우는 3글자에서 딱 정가운데에 있으니까 왼쪽 오른쪽만 채우면 되니 처음에서 ~ 끝으로 이렇게 이동하는 건데..</del></p>
<p>결국 구글링의 힘을 빌려서 코드를 바꿔보았다.</p>
<pre><code>
def solution(name):
    answer = 0
    alph = [ min(ord(n) - ord(&quot;A&quot;), ord(&quot;Z&quot;) - ord(n) + 1) for n in name]
    idx = 0 # start = 0

    while True:
        answer += alph[idx]
        alph[idx] = 0
        if sum(alph) == 0:
            break

        left, right = 1, 1

        # 왼쪽으로 가니까 -
        while alph[idx - left] == 0:
            left += 1

        # 오른쪽으로 가니까 +
        while alph[idx + right] == 0:
            right += 1

        # left가 최소면 left를 더하고, right가 최소면 right 더하기
        answer += left if left &lt; right else right

        # 그다음 idx 계산하기
        idx += -left if left &lt; right else right

    return answer</code></pre><p>그런데 100점이 안나왔다. 아무래도 테스트케이스가 추가되어서 그런것같은데..
이게 레벨 2라고..^^? 일단 보류해놓기.. 꼭 수욜전까진 해놓는다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[탐욕법 (greedy) - 체육복]]></title>
            <link>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95-greedy-%EC%B2%B4%EC%9C%A1%EB%B3%B5</link>
            <guid>https://velog.io/@my_youth99/%ED%83%90%EC%9A%95%EB%B2%95-greedy-%EC%B2%B4%EC%9C%A1%EB%B3%B5</guid>
            <pubDate>Mon, 02 Oct 2023 06:57:29 GMT</pubDate>
            <description><![CDATA[<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/42862">https://school.programmers.co.kr/learn/courses/30/lessons/42862</a></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/6cfff810-6e06-4e5c-a1fc-ec3bdb5a1862/image.png" alt=""></p>
<p>근데 그래도 정렬해서 주지않을까? 하고 정렬안하고 쭉 풀어봤다.</p>
<p>초기 코드</p>
<pre><code>def solution(n, lost, reserve):
    answer = n - len(lost)
    lost.sort(reverse = True)
    for l in lost:
        for r in reserve:
            if l - r &lt; 0:
                answer+=1
                break
            elif l - r == 0:
                answer-=1  
                break
    return answer</code></pre><p>응 어림없어~ 테케에서 다 걸려짐.
머리 싸매면서 풀이도 보고 하니까 보이는 점.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/88095dd0-49b2-4a8f-947d-acd35b20f18b/image.png" alt="">
문제를 똑바로 읽자..
전에 내 블로그에서 풀었던 방식을 보니까 set 의 연산을 통해 쉽게 끝낼 수 있었다.
국어 좀 잘하자 제발 ^^</p>
<pre><code>def solution(n, lost, reserve):
    lost.sort() # 정렬
    reserve.sort() # 정렬  
    _reserve = list(set(reserve)-set(lost))
    _lost = list(set(lost)-set(reserve))
    for r in _reserve:
        if r+1 in _lost: # 내 뒷번호니까 빌려줌
            _lost.remove(r+1)
        elif r-1 in _lost:
            _lost.remove(r-1)
    return n - len(_lost)</code></pre><p>엥 근데 아직도 100점은 맞지 못하고 있다.
어디 테스트케이스에서 걸리는 듯했다.</p>
<p>reserve를 reverse 했더니 해결</p>
<pre><code>def solution(n, lost, reserve):

    _reserve = list(set(reserve)-set(lost))
    _lost = list(set(lost)-set(reserve))

    _reserve.sort(reverse=True)
    _lost.sort()

    for r in _reserve:
        if r+1 in _lost: # 내 뒷번호니까 빌려줌
            print(r+1, lost) # 확인용
            _lost.remove(r+1)
        elif r-1 in _lost:
            print(r-1, lost) # 확인용
            _lost.remove(r-1)
    return n - len(_lost)</code></pre><p> 5, [4, 2], [3, 5] 를 생각해보자.
그러면 _reserve = [3,5]</p>
<p>3부터 시작하면 4에서 빌려주고 2에서는 못 빌려줌
그다음 5는 아무도 빌려줄 수 없음
오히려 5부터 시작을 하면 4한테 빌려주고
3은 2한테 빌려줄 수 있음.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/da6797ed-12f3-44c1-8bfe-ab78be933ef1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[file-download-1]]></title>
            <link>https://velog.io/@my_youth99/file-download-1</link>
            <guid>https://velog.io/@my_youth99/file-download-1</guid>
            <pubDate>Thu, 20 Jul 2023 15:52:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/my_youth99/post/741f46d5-8cd1-47ce-8ef8-84540e3f5793/image.png" alt="">
Upload My Memo를 통해 파일 이름과 내용을 업로드하면 저장되는 형식이다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/f286dee5-6e24-4b77-ab5f-a74985979190/image.png" alt="">
아까 첫문제로 포스팅한 문제를 생각해보자..
Filename이 링크 이름으로 바뀌니까 이걸 이용해서 flag를 찾을 수 있지 않을까? 라고 생각해보았다.</p>
<p>근데 코드를 아무리봐도 flag를 볼 수 있는 링크가 어디있는지 알 수가 없었다..
결국 이번에도 구글링 ㅠㅠ 근데 문제를 잘 보면 걍 나오는거였다.
flag.py를 다운받는다 이게 힌트였다.
그러면 flag.py로 갈 수 있게 링크 설정을 해주면 되는거였다.</p>
<p>디렉터리 이동이 필요하다. 그렇기 때문에 </p>
<pre><code>../flag.py 
</code></pre><p>이렇게 해주면 된다. 하지만 코드를 살펴보면</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/c43719fd-e831-4d00-8e5c-755d87057d45/image.png" alt="">
특정한 형식의 파일이름은 올라가지 못하게 막아놓았다. 얘를 통해 상위 폴더에 있는 flag.py가 있구나 눈치</p>
<p>그렇다면 url로 직접 조작하면 되지않나?
그래서 url로 직접 ../flag.py로 입력해주었다.
<img src="https://velog.velcdn.com/images/my_youth99/post/ee16219e-ca9f-4b20-b32d-47acf8f75cdb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/d20ef044-d914-41b4-87cc-c43dde9e5dc2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[xss-1]]></title>
            <link>https://velog.io/@my_youth99/xss-1</link>
            <guid>https://velog.io/@my_youth99/xss-1</guid>
            <pubDate>Thu, 20 Jul 2023 15:31:29 GMT</pubDate>
            <description><![CDATA[<p>원본 링크 : <a href="https://dreamhack.io/wargame/challenges/28/">https://dreamhack.io/wargame/challenges/28/</a></p>
<p><strong>문제</strong> 
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스이다.
XSS 취약점을 이용해 플래그를 획득. 플래그는 flag.txt, FLAG 변수에 있다.
<br><br></p>
<p>처음 페이지에 들어가게 되면 다음과 같은 화면을 볼 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/b1332bb5-f4c7-496d-8e0d-2bb6a779733d/image.png" alt=""></p>
<p>vuln(xss) page 먼저 들어가보니 alert(1) 스크립트가 삽입되어 1이라는 내용의 alert을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/5f9928a7-84fb-4b3c-b8ca-e5ad40b77c21/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/b08f69d5-8c9f-46af-9403-ad2969e0f474/image.png" alt=""></p>
<p>memo에 들어가면 hello라는 문자를 볼 수 있다.
나갔다가 다시 들어오면 hello가 복제된다.
<img src="https://velog.velcdn.com/images/my_youth99/post/648106e1-1d80-46d3-9375-9ec0bc888afb/image.png" alt=""></p>
<p>flag 페이지를 들어가니 입력폼이 보인다. 여기서 flag를 입력해야 하는 것같기도 하다.
<img src="https://velog.velcdn.com/images/my_youth99/post/9b155449-4813-489d-9f26-f16c49723ec8/image.png" alt=""></p>
<p>첨부된 app 파일을 분석해본다.
<img src="https://velog.velcdn.com/images/my_youth99/post/a3c00ff2-6e7c-43b4-9c8f-66897bf5812a/image.png" alt=""></p>
<p>저기의 flag.txt의 내용을 알아야한다.
urllib 라이브러리에 쓰이는 함수들은 어떻게 실행되는 걸까
urllib.parse.quote는 글자로 URL 인코딩을 해준다고 한다.</p>
<p>감이 안와서 사람들의 질문을 통해 힌트를 얻어보았다.
read_url에 집중해야한다고 한다. 아무래도 add_cookie가 신경쓰인다.
쿠키를 사용해서 flag를 알아내는건가 싶다.</p>
<p>document.cookie를 콘솔로 찍어내도 아무것도 안뜬다</p>
<p>어거지로 이렇게 넣어보았다
<img src="https://velog.velcdn.com/images/my_youth99/post/eea5ed1c-9df1-450f-aba2-2848ce88408f/image.png" alt="">
<img src="https://velog.velcdn.com/images/my_youth99/post/2bcef021-f749-4ac7-b57c-157587c88ccf/image.png" alt="">
alert 창에 flag.txt 읽은 걸 띄울 순 없을까?
이렇게는 아닌가보다 ..</p>
<p>결국 구글링 찬스 .. ㅠㅠ</p>
<p>flag에서 memo페이지로 이동하여 flag 값이 있는 쿠키값을 출력하도록 해야하는 것이었다.</p>
<p>flag 페이지에서 </p>
<pre><code>&lt;script&gt;location.href=&quot;/memo?memo=&quot;+document.cookie;&lt;/script&gt;</code></pre><p>를 입력후 memo 페이지로 가면 </p>
<p><img src="https://velog.velcdn.com/images/my_youth99/post/d1ca9e31-6dea-4cb9-9b95-711cf96335b6/image.png" alt="">
이렇게 flag 값이 나오는 것을 확인할 수 있다.</p>
<p>넘 어렵다 8-8 이게 왜 레벨 1..?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[보안 기초 지식 (5)]]></title>
            <link>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-5-e9h2kqwx</link>
            <guid>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-5-e9h2kqwx</guid>
            <pubDate>Thu, 20 Jul 2023 13:18:57 GMT</pubDate>
            <description><![CDATA[<h1 id="36-로그-보관-기간">36. 로그 보관 기간</h1>
<p>보통 2년정도 보관 (default)</p>
<h1 id="37-dba">37. DBA</h1>
<p>root와 비슷하다고 생각하면 된다.</p>
<h1 id="38-lfi">38. LFI</h1>
<p><strong>Local File Inclusion</strong></p>
<blockquote>
<p>Local에 있는 파일을 읽는 공격
서버에 FTP나 자료실로 악성 코드를 업로드시켜 include 시킴.</p>
</blockquote>
<h1 id="39-rfi">39. RFI</h1>
<p><strong>Remote File Inclusion</strong></p>
<blockquote>
<p>Remote에 있는 파일을 읽는 공격
외부 서버의 악성 코드를 불러와 include 시킴.</p>
</blockquote>
<h1 id="40-인증-vs-인가">40. 인증 VS 인가</h1>
<blockquote>
<p><strong>인증 :</strong> 신분 확인
<strong>인가 :</strong> 권한 확인</p>
</blockquote>
<h1 id="41-프록시-서버">41. 프록시 서버</h1>
<p>클라이언트가 자신을 통해서 다른 네트워크 서비스에 
간접적으로 접속할 수 있게 해 주는 컴퓨터 시스템이나 응용 프로그램</p>
<h1 id="42-url-vs-uri">42. URL VS URI</h1>
<blockquote>
<p>URI= 식별자, URL=식별자+위치
출처 : <a href="https://www.elancer.co.kr/blog/view?seq=74">https://www.elancer.co.kr/blog/view?seq=74</a></p>
</blockquote>
<h1 id="43-윈도우-운영체제-프로세스">43. 윈도우 운영체제 프로세스</h1>
<p>c:\windows\system32 폴더에 위치함</p>
<ol>
<li>wininit.exe : 윈도우 시작 프로그램</li>
<li>services.exe : 윈도우 서비스 관리</li>
<li>lsm.exe : 시스템 관리,주요 함수 실행, 컴퓨터와 서버 연결 관리</li>
<li>lsass.exe : 로그인 검사, 비밀번호 변경관리 등</li>
<li>svchost.exe : 서비스 관리를 위한 프로세스</li>
<li>conhost.exe : 키보드, 마우스 입력허용 등</li>
</ol>
<h1 id="44-이상적인-비밀번호">44. 이상적인 비밀번호</h1>
<ol>
<li>영문 대소문자 구성된 문자열</li>
<li>숫자</li>
<li>특수문자</li>
</ol>
<p>-&gt; 1~3번 각각 한두개 이상 조합</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[보안 기초 지식 (4)]]></title>
            <link>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-4</link>
            <guid>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-4</guid>
            <pubDate>Wed, 19 Jul 2023 14:17:16 GMT</pubDate>
            <description><![CDATA[<h1 id="28-c2--cc--command--control">28. C2 = C&amp;C = Command &amp; Control</h1>
<p>공격자가 초기 침투에 성공한 장치와의 통신을 유지할 때 사용하는 도구 및 기술들</p>
<h1 id="29-오라클-감사로그-활성화">29. 오라클 감사로그 활성화</h1>
<p>AUDIT_TRAIL 값을 &#39;DB&#39; 또는 &#39;TRUE&#39;로 지정한다</p>
<h1 id="30-오라클-데이터베이스-감사로그의-종류">30. 오라클 데이터베이스 감사로그의 종류</h1>
<ol>
<li>문장 감사 (statement auditing)</li>
<li>권한 감사 (prvilege auditing)</li>
<li>객체 감사 (object auditing)</li>
</ol>
<h1 id="31-lls">31. lls</h1>
<blockquote>
<p><strong>인터넷 정보 서비스 (Internet Information Services</strong>)
마이크로소프트 윈도우를 사용하는 서버들을 위한 인터넷 기반 서비스들의 모임</p>
</blockquote>
<h1 id="32-네트워크-장비의-로그-관리">32. 네트워크 장비의 로그 관리</h1>
<ol>
<li>네트워크 보안 로그 : 방화벽(침입차단시스템), IDS(침입탐지시스템), IPS(침입방지시스템)등이 로그를 생성 | SIEM(Security information and event management)</li>
<li>네트워크 관리시스템 로그 : MRTG(트래픽 모니터링), NMS(네트워크 관리 시스템)</li>
<li>네트워크 인증시스템 로그</li>
</ol>
<h1 id="33-파일-접근-권한--디렉토리-접근-권한">33. 파일 접근 권한 &gt;&gt;&gt; 디렉토리 접근 권한</h1>
<h1 id="34-허용-권한-없음--거부-윈도우">34. 허용 권한 없음 != 거부 (윈도우)</h1>
<p>거부 &gt;&gt;&gt;&gt; 허용 </p>
<h1 id="35-질의문-종류">35. 질의문 종류</h1>
<ol>
<li>DDL (Data Definition Language) : CREATE, DROP, ALTER</li>
<li>DML (Data Manipulation Language) : SELECT, INSERT, UPDATE, DELETE</li>
<li>DCL (Data Control Language) : GRANT, DENY, REVOKE</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[보안 기초 상식 (3)]]></title>
            <link>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%83%81%EC%8B%9D-3</link>
            <guid>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%83%81%EC%8B%9D-3</guid>
            <pubDate>Tue, 18 Jul 2023 15:35:22 GMT</pubDate>
            <description><![CDATA[<h1 id="19-로그">19. 로그</h1>
<p>시스템의 처리 내용이나 이용 상황을 시간의 흐름에 따라 기록한 것
(+) 대량으로 생성 되기 때문에 취약점 관리 시에 중요함</p>
<h1 id="20-로깅">20. 로깅</h1>
<p>로그를 생성하도록 시스템을 작성하는 활동</p>
<h1 id="21-aaa">21. AAA</h1>
<h2 id="span-stylecolorredstrong★-로그-관리를-위해-알아야하는-개념strongspan"><span style="color:red"><strong>★ 로그 관리를 위해 알아야하는 개념</strong></span></h2>
<h3 id="1-authentication-인증">(1) Authentication (인증)</h3>
<p>자신의 신원을 증명한다.</p>
<h3 id="2-authorization-인가">(2) Authorization (인가)</h3>
<p>패스워드 등을 통해 로그인의 허락된 사용자로 판별됨.</p>
<h3 id="3-accounting-책임-추적성">(3) Accounting (책임 추적성)</h3>
<p>로그인 이후 활동에 대한 기록을 남긴다.</p>
<h1 id="22-sendmail">22. SendMail</h1>
<p>유닉스에서 메일을 처리하는 데몬 프로그램</p>
<h1 id="23-데몬">23. 데몬</h1>
<p>오랫동안 실행중인 백그라운드(background) 프로세스 =&gt; 서비스의 요청에 대해 응답을 위함</p>
<h1 id="24-텔넷telnet">24. 텔넷(Telnet)</h1>
<blockquote>
<p>*<em>사용자의 컴퓨터에서 네트워크를 이용하여 원격지에 떨어져 있는 서버에 접속을 통해
자료를 교환할 수 있는 프로토콜.
*</em></p>
</blockquote>
<p>텔넷 = 통신(tel) + 네트워크(net)
인터넷에서 사용되는 주요 네트워크 프로토콜 중 하나이다.</p>
<h1 id="25-윈도우-로그-종류">25. 윈도우 로그 종류</h1>
<ol>
<li>개체 엑세스</li>
<li>계정 관리</li>
<li>계정 로그인 이벤트</li>
<li>권한 사용</li>
<li>로그인 이벤트</li>
<li>디렉토리 서비스 액세스</li>
<li>정책 변경</li>
<li>프로세스  추적</li>
<li>시스템 이벤트</li>
</ol>
<h1 id="26-윈도우-로그-vs-유닉스-로그">26. 윈도우 로그 vs 유닉스 로그</h1>
<p>윈도우 로그 : 중앙 집중화되어 관리된다
유닉스 로그 : 중앙 집중화 X. 로그 저장되는 위치도 각각 다르다.</p>
<h1 id="27-유닉스-로그-종류">27. 유닉스 로그 종류</h1>
<ol>
<li>UTMP : 현재 시스템에 로그인한 사용자의 상태 출력
(<strong>w, who, finger</strong> 명령어 사용)</li>
<li>WTMP : 사용자의 로그인/로그아웃, 시스템 재부팅 정보 출력
(<strong>last</strong> 명령어 사용)</li>
<li>secure : 원격 접속 내역, su 명령어 수행 내역 </li>
<li>history</li>
<li>syslog</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[보안 기초 지식 (2)]]></title>
            <link>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EC%A7%80%EC%8B%9D-2</link>
            <guid>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EC%A7%80%EC%8B%9D-2</guid>
            <pubDate>Tue, 18 Jul 2023 02:14:34 GMT</pubDate>
            <description><![CDATA[<h1 id="11-패스워드-크래킹">11. 패스워드 크래킹</h1>
<p>네트워크 컴퓨터 시스템에 의해 전송된 저장 위치로부터 또는 데이터로부터 패스워드를 복구</p>
<h1 id="12-로그인-계정을-목록화-명령어">12. 로그인 계정을 목록화 명령어</h1>
<blockquote>
<p><strong>(1) who (2) finger (3) w</strong>
(ls-a는 아님!)</p>
</blockquote>
<h1 id="13-nmap">13. nmap</h1>
<ul>
<li>port Scanning 툴이다. </li>
<li>네트워크 스캐너다.</li>
<li>취약점 스캔에서 쓰인다.</li>
<li>열려있는 포트를 확인한다.</li>
<li>컴퓨터와 서비스를 찾을 때 쓰인다.</li>
</ul>
<h1 id="14-윈도우-패스워드-관련-용어">14. 윈도우 패스워드 관련 용어</h1>
<blockquote>
<p><strong>(1) LM(LAM Manager)
(2) SAM (Security Accounts Manager)
(3) NTLM (NT LAN Manager)</strong></p>
</blockquote>
<h1 id="15-접근통제">15. 접근통제</h1>
<h2 id="1-macmandatory-access-control">(1) MAC(Mandatory Access Control)</h2>
<ul>
<li>강제적 통제</li>
<li>해당 장소의 보안 등급은 잘 바뀌지 않는다.</li>
<li>주체는 인가 등급을 부여한다.</li>
<li>주로 군사용/정부에서 사용</li>
</ul>
<h2 id="2-dacdiscrentionary-access-control">(2) DAC(Discrentionary Access Control)</h2>
<ul>
<li>객체중심 통제</li>
<li>다양하게 세팅할 수 있다</li>
<li>파일이나 문서 등에 의해서 각각 퍼미션(CREATE, DELETE 등)을 준다.</li>
<li>주체에게도 권한을 줄 수 있다.</li>
<li>OS에서 활용</li>
</ul>
<h2 id="3-rbac-role-based-access-control">(3) RBAC (Role Based Access Control)</h2>
<ul>
<li>역할단위 통제</li>
<li>조직 내 맡은 &#39;역할&#39;에 기초</li>
<li>팀에 권한을 주고 내가 그곳에 소속이 되면 자동으로 해당 권한을 상속받게 되는 것</li>
<li>기업이나 조직에서 활용</li>
</ul>
<h1 id="16-계층적-방어">16. 계층적 방어</h1>
<p>호스트 보안 E 네트워크 보안 E 물리적 통제 E 기업의 관리적 통제 </p>
<h1 id="17-버퍼오버플로우-방지-함수">17. 버퍼오버플로우 방지 함수</h1>
<ol>
<li>strncpy()</li>
<li>strncat()</li>
<li>fgets()</li>
<li>fscanf()</li>
<li>vfscnaf()</li>
<li>snprintf()</li>
<li>vsnprintf()</li>
</ol>
<h1 id="18-umask">18. umask</h1>
<ul>
<li>모든 권한 소유 : rwx</li>
<li>하나식 빠질경우 : -로 표시</li>
<li>파일 생성시 마다 구너한 부여하는 번거로움을 해결하기 위해 Default 권한값을 가짐</li>
<li>보안상 가장 안전한 umask 설정 값 : umask 077</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[보안 기초 지식 (1)]]></title>
            <link>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-1</link>
            <guid>https://velog.io/@my_youth99/%EB%B3%B4%EC%95%88-%EA%B8%B0%EC%B4%88-%EC%A7%80%EC%8B%9D-1</guid>
            <pubDate>Mon, 17 Jul 2023 08:24:14 GMT</pubDate>
            <description><![CDATA[<h1 id="1-포트-번호">1. 포트 번호</h1>
<p>http : 80
https : 443
ssh : 22</p>
<h1 id="2-osi-7-계층">2. OSI 7 계층</h1>
<p>L7 응용 계층
L6 표현 계층
L5 세션 계층
L4 전송 계층
L3 네트워크 계층
L2 데이터 링크 계층
L1 물리 계층</p>
<h2 id="3-리눅스-라이브러리-관련-명령어">3. 리눅스 라이브러리 관련 명령어</h2>
<p><strong>ldd 명령어</strong>
라이브러리 의존성 확인</p>
<h1 id="4-aaa">4. AAA</h1>
<p>인증(Authentication)
권한부여(Authorization)
계정관리(Accounting)</p>
<h1 id="5-sam">5. SAM</h1>
<p>보안 계정 관리자(SAM: Security Account Manager)</p>
<h1 id="6-물리-페이지-프레임">6. 물리 페이지 프레임</h1>
<p>*<em>4KB == 4096 == 0X1000 == 12bit == 2^12 *</em></p>
<h1 id="7-dos와-ddos의-차이점">7. dos와 DDOS의 차이점</h1>
<ol>
<li>공격자의 수</li>
<li>victim의 수</li>
</ol>
<h1 id="8-랜섬웨어-방어">8. 랜섬웨어 방어</h1>
<ul>
<li>스팸 메일 차단</li>
<li>보안 업데이트</li>
<li>주기적인 백업<blockquote>
<p><strong>(주의) 패스워드 변경으로는 방어하기 어렵다</strong></p>
</blockquote>
</li>
</ul>
<h1 id="9-전자서명">9. 전자서명</h1>
<blockquote>
<p><strong>(1) 은행 금융거래 (2) 문서나 파일 위조여부 확인 (3) 주민등록등본 발급</strong></p>
</blockquote>
<h1 id="10-mfa의-인증수단">10. MFA의 인증수단</h1>
<p>다중 인증 (MFA: Multi-Factor Authentication)</p>
<blockquote>
<p><strong>(1) otp 토큰 (2) 지문 (3) 인증서</strong></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>