<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>yjkim.log</title>
        <link>https://velog.io/</link>
        <description>We may throw the dice, but the Lord determines how they fall</description>
        <lastBuildDate>Tue, 17 Dec 2024 15:26:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. yjkim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/manofmen_yj" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[애플리케이션 재배포 및 DB 조회 없이 변경된 외부의 값을 가져와서 코드에 반영하는 법]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%9E%AC%EB%B0%B0%ED%8F%AC-%EB%B0%8F-DB-%EC%A1%B0%ED%9A%8C-%EC%97%86%EC%9D%B4-%EB%B3%80%EA%B2%BD%EB%90%9C-%EC%99%B8%EB%B6%80%EC%9D%98-%EA%B0%92%EC%9D%84-%EA%B0%80%EC%A0%B8%EC%99%80%EC%84%9C-%EC%BD%94%EB%93%9C%EC%97%90-%EB%B0%98%EC%98%81%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@manofmen_yj/%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%9E%AC%EB%B0%B0%ED%8F%AC-%EB%B0%8F-DB-%EC%A1%B0%ED%9A%8C-%EC%97%86%EC%9D%B4-%EB%B3%80%EA%B2%BD%EB%90%9C-%EC%99%B8%EB%B6%80%EC%9D%98-%EA%B0%92%EC%9D%84-%EA%B0%80%EC%A0%B8%EC%99%80%EC%84%9C-%EC%BD%94%EB%93%9C%EC%97%90-%EB%B0%98%EC%98%81%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Tue, 17 Dec 2024 15:26:02 GMT</pubDate>
            <description><![CDATA[<p>Spring Cloud Config
Amazon Systems Manager
Redis
그리고 AWS S3도 써도 가능할 것 같음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[소공 - 객체지향]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%86%8C%EA%B3%B5-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@manofmen_yj/%EC%86%8C%EA%B3%B5-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Wed, 27 Nov 2024 15:43:46 GMT</pubDate>
            <description><![CDATA[<p>d</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCB]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%99%80-%EB%82%98-TCB%EB%9D%BC%EB%8A%94%EA%B1%B0-%EC%B2%A8-%EB%93%A4%EC%96%B4%EB%B4%84</link>
            <guid>https://velog.io/@manofmen_yj/%EC%99%80-%EB%82%98-TCB%EB%9D%BC%EB%8A%94%EA%B1%B0-%EC%B2%A8-%EB%93%A4%EC%96%B4%EB%B4%84</guid>
            <pubDate>Thu, 14 Nov 2024 17:25:22 GMT</pubDate>
            <description><![CDATA[<p>면접 준비로 운영체제를 공부하던 중에 갑자기 몇가지 궁금한 점이 생겨버림</p>
<blockquote>
<ol>
<li>아니 PCB는 Process의 상태를 저장하고 복원하는데 쓰이는 자료구조인데, 만약에 같은 Process에 존재하는 Thread간에 Context Switching이 발생하는 경우에는 어떻게 상태를 추적할 것인가?<br></li>
<li>실행되는 작업의 최소 단위는 Process가 아니라 Thread라는 것을 보면 Context Switching의 실질적인 기준이 되는 것도 Thread 여야 되는 것 아닌가? <br></li>
<li>근데 PCB가 이러한 것들을 다 감당하는 자료구조인가?</li>
</ol>
</blockquote>
<p><strong>그래서 검색해본 결과 TCB라는 새로운 자료구조를 알게되었음</strong></p>
<h4 id="tcb---thread-control-block">TCB - Thread Control Block</h4>
<p>Thread의 상태를 저장하는 자료구조
다음과 같이 PCB에 연결된 리스트에 존재함
<img src="https://velog.velcdn.com/images/manofmen_yj/post/f60e4c8e-ecc1-466b-a6dc-82613926df94/image.png" alt=""></p>
<p>Thread Context Switching이 발생하면</p>
<blockquote>
<p>Thread A가 CPU 사용중
Thread A의 상태 정보를 TCB A에 저장
Thread A가 속한 Process A의 상태 정보 PCB A에 저장
Thread B가 속한 Process B의 상태 정보 PCB B 로드
Thread B의 TCB B 로드
Thread B가 CPU 사용</p>
</blockquote>
<p>과 같은 과정이 실행된다고 한다 그리고 gpt한테 물어봤는데 Context Switching의 실질적인 기준이 되는것도 Thread가 맞다 함 아 근데 먼가 확실ㄹ하지 않고 애매한거 같아서 더 찾아보고 공부해바야 될듯</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[비트마스킹]]></title>
            <link>https://velog.io/@manofmen_yj/%EB%B9%84%ED%8A%B8%EB%A7%88%EC%8A%A4%ED%82%B9</link>
            <guid>https://velog.io/@manofmen_yj/%EB%B9%84%ED%8A%B8%EB%A7%88%EC%8A%A4%ED%82%B9</guid>
            <pubDate>Thu, 31 Oct 2024 15:35:12 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-py">from collections import deque
n = int(input())
graph=[]
for i in range(n):
    graph.append(list(map(int , list(input()))))

q = deque()

visited_mask = 1

visited_dict={}
visited_dict[1]=1
q.append([0,visited_mask,1,0])
answer= 0

while q:
    cur = q.pop()
    seller = cur[0]
    mask = cur[1]
    count = cur[2]
    amount = cur[3]
    answer = max(answer,count)
    for i in range(n):
        if graph[seller][i]&gt;=amount and mask &amp; (1&lt;&lt;i)==0:
            new_mask = mask | (1&lt;&lt;i)
            q.append([i,new_mask,count+1,graph[seller][i]])

print(answer)
</code></pre>
<p>방문 상태를 저장 할 경우 배열로 선언하는 것보다 비트마스킹 형태의 정수로 저장하면 공간복잡도 측면에서 효율적으로 코드 작성 가능</p>
<ul>
<li>추가 
파이썬에서 딕셔너리의 특정 키 존재 유무 파악할 때 그냥 in 연산자 적어주면 된다. 시간복잡도 o(1)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[딕셔너리로 비트스트림 구현]]></title>
            <link>https://velog.io/@manofmen_yj/%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC%EB%A1%9C-%EB%B9%84%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%A6%BC-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@manofmen_yj/%EB%94%95%EC%85%94%EB%84%88%EB%A6%AC%EB%A1%9C-%EB%B9%84%ED%8A%B8%EC%8A%A4%ED%8A%B8%EB%A6%BC-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Tue, 22 Oct 2024 07:44:56 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-py">arr =[[{k:0 for k in range(3)} for i in range(3)] for j in range(3)]
</code></pre>
<p>비트스트림에서 i번째 인덱스의 값을 딕셔너리의 키가 i일때 value 값을 구하는 방식으로 구현</p>
<p>훨씬 직관적인듯</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[소공]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%86%8C%EA%B3%B5</link>
            <guid>https://velog.io/@manofmen_yj/%EC%86%8C%EA%B3%B5</guid>
            <pubDate>Mon, 21 Oct 2024 02:37:09 GMT</pubDate>
            <description><![CDATA[<h4 id="가용도">가용도</h4>
<p>mtbf = 고장률의 역수</p>
<ul>
<li>고장률 = 고장건수 / 총가동시간</li>
</ul>
<p>mttf = 총가동시간 / 고장시간</p>
<p>mttr = 총고장시간 / 고장건수</p>
<p>가용도 = mttf / mtbf</p>
<h4 id="cpm-네트워크">cpm 네트워크</h4>
<h4 id="타당성-3가지">타당성 3가지</h4>
<p>기술적 타당성 = 프로젝트가 기술적으로 가능한지
경제적 타당성 = 프로젝트가 경제적으로 가능한지 (이익을 창출할 수 있을지)
운영적 타당성 = 프로젝트가 실제로 사용 가능한지 (조직과 잘 맞음? 클라이언트가 사용 가능?)</p>
<h4 id="유스케이스-다이어그램">유스케이스 다이어그램</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/212382b1-b1fc-456a-80c9-97a9f1898f42/image.png" alt=""></p>
<h4 id="통신-다이어그램">통신 다이어그램</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/9a820af2-86b1-4c44-bfd8-c866d9513f7b/image.png" alt=""></p>
<ul>
<li>직사각형 : 객체</li>
<li>선 : 관계</li>
<li>화살표 : 메세지가 흐르는 방향</li>
<li>번호 : 메세지 전송 순서</li>
</ul>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/5268d768-5726-4019-912f-d51bab5009e9/image.png" alt=""></p>
<h4 id="순차-다이어그램">순차 다이어그램</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/85a30600-eb3a-4e42-bf9a-32d0c4cd4177/image.png" alt=""></p>
<h4 id="비용-산정-기법">비용 산정 기법</h4>
<ul>
<li>상향식<ul>
<li>loc = 라인 / (생산성 * 프로그래머)</li>
<li>cocomo<ul>
<li>조직형 = 조직형 (소규모 소프트웨어, 비즈니스 로직)</li>
<li>반분리형 = 30만 라인 이하</li>
<li>내장형 = 30만 라인 이상 (운영체제, 대규모 트랜잭션)</li>
</ul>
<hr>
<ul>
<li>기본형 = 라인 수와 개발 유형 사용해서 비용 산정</li>
<li>중간형 = 제품, 컴퓨터, 개발자 특성 고려해 비용 산정</li>
<li>발전형 = 개발 공정별로 더욱 자세하게 비용 산정</li>
</ul>
<hr>
<ul>
<li>보정 후 기능 점수 = 기본 점수 * 보정 인자</li>
</ul>
</li>
</ul>
</li>
<li>하향식 (전문가들)</li>
</ul>
<h4 id="dfd">dfd</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/a18242f2-127a-488f-8668-29268da69bfa/image.png" alt=""></p>
<ul>
<li>data store = db테이블</li>
<li>terminator = 대상</li>
<li>process = 수행</li>
<li>data flow = 데이터 이동</li>
</ul>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/2a324679-ea32-4af3-9f2c-13674980fa2f/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터뷰 키워드 - 운영체제]]></title>
            <link>https://velog.io/@manofmen_yj/cs-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C</link>
            <guid>https://velog.io/@manofmen_yj/cs-%EB%A9%B4%EC%A0%91-%EB%8C%80%EB%B9%84-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C</guid>
            <pubDate>Wed, 16 Oct 2024 16:02:44 GMT</pubDate>
            <description><![CDATA[<p>프로세스
프로세스 제어블록
코드 데이터 힙 스택
스레드
멀티 프로세스
문맥교환
IPC
멀티 스레드
동기화
공유 자원과 경쟁조건</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정렬된 배열의 대소 비교를 할 시 이분탐색]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%A0%95%EB%A0%AC%EB%90%9C-%EB%B0%B0%EC%97%B4%EC%9D%98-%EB%8C%80%EC%86%8C-%EB%B9%84%EA%B5%90%EB%A5%BC-%ED%95%A0-%EC%8B%9C-%EC%9D%B4%EB%B6%84%ED%83%90%EC%83%89</link>
            <guid>https://velog.io/@manofmen_yj/%EC%A0%95%EB%A0%AC%EB%90%9C-%EB%B0%B0%EC%97%B4%EC%9D%98-%EB%8C%80%EC%86%8C-%EB%B9%84%EA%B5%90%EB%A5%BC-%ED%95%A0-%EC%8B%9C-%EC%9D%B4%EB%B6%84%ED%83%90%EC%83%89</guid>
            <pubDate>Fri, 11 Oct 2024 11:41:46 GMT</pubDate>
            <description><![CDATA[<p>a 배열의 특정 값이 b 배열의 값들 중 몇개의 값보다 더 큰 지 알고싶을때 이분탐색 ㄱ
그러면 특정 값에서 break가 걸리는 순간에, 해당 값의 index를 읽어주면 됨</p>
<p>bisect 라이브러리 추가 공부 ㄱ</p>
<p><a href="https://school.programmers.co.kr/learn/courses/30/lessons/258709">https://school.programmers.co.kr/learn/courses/30/lessons/258709</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Node.js는 어떻게 비동기 작업을 하는거임]]></title>
            <link>https://velog.io/@manofmen_yj/Node.js%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85%EC%9D%84-%ED%95%98%EB%8A%94%EA%B1%B0%EC%9E%84</link>
            <guid>https://velog.io/@manofmen_yj/Node.js%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85%EC%9D%84-%ED%95%98%EB%8A%94%EA%B1%B0%EC%9E%84</guid>
            <pubDate>Wed, 25 Sep 2024 20:19:27 GMT</pubDate>
            <description><![CDATA[<p>Node.js는 싱글스레드 기반으로 동작함. 싱글스레드로 동작한다는 소리는 한 번에 하나의 작업만 실행할 수 있다는 것을 의미함. 하지만 async/await 구문과 promise 객체의 존재를 보면 알 수 있듯이 우리의 javascript 친구는 비동기작업을 아주 기가막히게 처리해줌. 대체 어떻게 하는걸까?</p>
<h3 id="이벤트-루프">이벤트 루프</h3>
<p>자바 스크립트 코드 실행은 스레드에서 담당하고 비동기작업은 이벤트 루프에 등록되어 백그라운드엣에서 실행됨 이벤트 루프는 요청을 처리하면서 블로킹 작업을 피하고 (non-blocking), 작업이 완료될 때까지 기다리는 대신 다른 작업을 계속 진행할 수 있게 함. 콜 스택 과 태스크 큐를 사용</p>
<blockquote>
<h4 id="콜-스택-call-stack">콜 스택 (call stack)</h4>
<p>자바스크립트 코드가 실행되는 공간. 코드가 동기적이면 콜 스택에서 순차적으로 처리됨</p>
<h4 id="태스크-큐-task-queue">태스크 큐 (task queue)</h4>
<p>비동기 작업(예: 네트워크 요청, 파일 읽기, 데이터베이스 접근 등)은 콜 스택에서 바로 처리되지 않고 백그라운드에서 실행. 백그라운드에서 실행된 작업이 완료되면 그 결과가 태스크 큐에 담김
*<em>태스크 큐에 쌓인 작업은 콜 스택이 비어 있을 때 이벤트 루프가 이를 콜 스택으로 다시 가져와 실행함
*</em></p>
</blockquote>
<br>
<br>
<br>
습관적으로 사용하던 것의 원리를 개념적으로 이해하게 되는 순간은 언제나 즐거운 것 같습니다.
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 통신 vs Socket 통신]]></title>
            <link>https://velog.io/@manofmen_yj/HTTP-%ED%86%B5%EC%8B%A0-vs-Socket-%ED%86%B5%EC%8B%A0</link>
            <guid>https://velog.io/@manofmen_yj/HTTP-%ED%86%B5%EC%8B%A0-vs-Socket-%ED%86%B5%EC%8B%A0</guid>
            <pubDate>Sat, 07 Sep 2024 16:51:37 GMT</pubDate>
            <description><![CDATA[<p>운영체제 공부하던 중 다음과 같은 내용을 알게됨 </p>
<blockquote>
<p>소켓 통신은 서로 다른 컴퓨터에 있는 프로세스 사이에 데이터를 주고 받기위해 사용되는 기술이다. 소켓 통신은 클라이언트와 서버가 실시간으로 데이터를 주고 받을 수 있는 양방향 통신으로 채팅, 실시간 스트리밍 등에 사용된다. 소켓 통신은 IP와 포트번호를 통해 어떤 컴퓨터의 어떤 프로세스와 통신할지 구별한다</p>
</blockquote>
<p>근데 갑자기 다음과 같은 궁금증이 생겨버림</p>
<blockquote>
<p><em>아니 근데 내가 알기로는 HTTP 통신도 서버랑 클라이언트가 실시간으로 데이터 주고 받는 기술이고, HTTP 통신도 IP와 포트번호를 통해 어떤 컴퓨터의 어떤 프로세스와 통신할지 구별하는데, 둘이 같은거 아님?</em></p>
</blockquote>
<p>그래서 찾아보니까 HTTP 통신은 소켓 통신이 맞음. TCP 계층에 올라간 HTTP 또한 소켓 통신과 같은 방식을 사용함. 즉 HTTP 통신은 소켓 통신에 일종이라고 볼 수 있으나, 소켓 통신은 HTTP 통신이 아님</p>
<h4 id="추가">추가</h4>
<ul>
<li>HTTP 통신은 클라이언트의 요청이 들어왔을 때 서버가 응답하는 단방향 통신, 서버는 응답하면 클라이언트와 커넥션을 끊어버림. 즉 *<em>실시간 통신이 아님 *</em> -&gt; 그러나 현재는 Keep Alive 옵션을 통해 커넥션 유지 가능 즉 근본자체는 실시간 통신이 아니기 때문에 내가 기존에 알고있던 내용은 틀린 내용</li>
<li>초기에는 HTML 파일만 전송하였으나, 현재는 JSON, 이미지 파일 등도 전송 가능</li>
</ul>
<br>
<br>

<p>아 퇴사하고 오랜만에 공부하니까 개재밌네 ㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 구현 대비 달력]]></title>
            <link>https://velog.io/@manofmen_yj/%EB%B0%B1%EC%A4%80-%EA%B5%AC%ED%98%84-%EB%8C%80%EB%B9%84-%EB%8B%AC%EB%A0%A5</link>
            <guid>https://velog.io/@manofmen_yj/%EB%B0%B1%EC%A4%80-%EA%B5%AC%ED%98%84-%EB%8C%80%EB%B9%84-%EB%8B%AC%EB%A0%A5</guid>
            <pubDate>Fri, 27 Oct 2023 07:58:15 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-py">cal=[[0 for i in range(367)] for i in range(1000)]
dict={}
for i in range(2,14):
  dict[i]=0

# 여기에는 놓일 위치
work=[]
n=int(input())
for i in range(n):
  s,e=map(int, input().split())
  work.append([s,e])

work.sort(key=lambda x:(x[0],-x[1]))
for w in work:
  s,e=w[0],w[1]
  count=0
  for j in range(s,e+1):
    while cal[count][j]==1:
      count+=1
  for j in range(s,e+1):
    cal[count][j]=1

answer=0
ga,se=0,0
for j in range(367):
  flag=True
  count=0
  for i in range(1000):
    if cal[i][j]==1:
      flag=False
      count=i
  se=max(count,se)
  if flag:
    answer+=ga*(se+1)
    ga,se=0,0
  else:
    ga+=1


print(answer)





</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 연습문제 아이템줍기]]></title>
            <link>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%97%B0%EC%8A%B5%EB%AC%B8%EC%A0%9C-%EC%95%84%EC%9D%B4%ED%85%9C%EC%A4%8D%EA%B8%B0</link>
            <guid>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%97%B0%EC%8A%B5%EB%AC%B8%EC%A0%9C-%EC%95%84%EC%9D%B4%ED%85%9C%EC%A4%8D%EA%B8%B0</guid>
            <pubDate>Mon, 23 Oct 2023 09:30:51 GMT</pubDate>
            <description><![CDATA[<p>문제 : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/87694">https://school.programmers.co.kr/learn/courses/30/lessons/87694</a></p>
<h3 id="접근">접근</h3>
<p>사각형을 하나씩 순회하면서 모서리 부분은 1, 안쪽 부분이거나 다른 사각형의 안쪽부분이라면 0으로 그래프 초기화</p>
<h3 id="코드">코드</h3>
<pre><code class="language-py">from collections import deque


def solution(rectangle, characterX, characterY, itemX, itemY):

    leng=max(list(map(max, rectangle)))*2
    graph=[[5 for i in range(leng+1)] for j in range(leng+1)]
    visited=[[0 for i in range(leng+1)] for j in range(leng+1)]
    answer=10000
    movelist=[[1,0],[-1,0],[0,-1],[0,1]]
    for re in rectangle:
        re=list(map(lambda x:x*2,re))
        for i in range(re[1],re[3]+1):
            for j in range(re[0],re[2]+1):
                if graph[i][j]!=0 and (i==re[1] or i==re[3] or j==re[0] or j==re[2]):
                    graph[i][j]=1
                else:
                    graph[i][j]=0

    curx,cury=characterX*2, characterY*2
    visited[cury][curx]=1
    itemx,itemy=itemX*2, itemY*2
    queue=deque()
    queue.append([curx,cury,0])

    while queue:
        curx,cury,curd=queue.popleft()
        if curx==itemx and cury==itemy:
            answer=min(answer,curd//2)

        for mo in movelist:
            nx,ny=curx+mo[0],cury+mo[1]
            if 0&lt;=nx&lt;leng+1 and 0&lt;=ny&lt;leng+1 and visited[ny][nx]==0 and graph[ny][nx]==1:
                queue.append([nx,ny,curd+1])
                visited[ny][nx]=1

    return answer</code></pre>
<h3 id="참고">참고</h3>
<p>실제 문제의 좌표평면을 그래프상의 숫자 0과1로 옮길떄 주의해야 할 점은 다음과 같다</p>
<p>좌표평면의 ㄷ자 모양과 ㅁ자 모양을 그래프로 옮길 경우 두 그래프의 형태 모두
1 1
1 1
로 표현된다. 그렇기 떄문에 위와같은 문제를 해결할 떄는 그래프의 좌표를 2배로 늘려주는 방식 또한 고려해야한다. 만약 위 경우를 그래프를 두배로 늘렸을 경우로 표현한다면 </p>
<p>1 1 1
0 0 1
0 0 0 과
1 1 1
1 1 1
1 1 1로 정상적으로 구별이 가능해진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개인프로젝트 1차 리팩토링 ]]></title>
            <link>https://velog.io/@manofmen_yj/%EA%B0%9C%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%B0%A8-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81</link>
            <guid>https://velog.io/@manofmen_yj/%EA%B0%9C%EC%9D%B8%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%B0%A8-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81</guid>
            <pubDate>Tue, 17 Oct 2023 15:13:03 GMT</pubDate>
            <description><![CDATA[<h2 id="config">Config</h2>
<h3 id="security-config">Security Config</h3>
<h4 id="success-handler-추가">Success handler 추가</h4>
<h4 id="session-management">Session Management</h4>
<ul>
<li>최대 로그인 세션 1개로 제한 -&gt; 중복 로그인 제한<h4 id="formlogin">formLogin</h4>
</li>
<li>defaultsuccessurl 방식에서 successHandler 방식으로 변경, 
이게 인증,인가 다룰때 더 좋은듯<h4 id="oauth-login-속성-추가">oauth login 속성 추가</h4>
</li>
<li>사실 이번 리팩토링의 가장 큰 이유인 부분. 구글 로그인 연동 기능 추가 , -&gt;DB에도 정상적으로 연동된것 확인<h4 id="logout-handler-추가">logout handler 추가</h4>
</li>
</ul>
<h2 id="controller">Controller</h2>
<h4 id="main">Main</h4>
<ul>
<li>메인 컨트롤러에서 authenticated 또는 authorized된사용자 정보 1차적으로 불러오게끔 변경</li>
</ul>
<h4 id="member">Member</h4>
<ul>
<li>authenticated 유무에 따라서 redirect 되는 결과 변경</li>
</ul>
<h4 id="route">route</h4>
<ul>
<li>이번 리팩토링의 핵심 2, 이제 매 실행마다 이전 데이터 clear하고 실행되기 때문에 연속된 서비스 실행 가능</li>
</ul>
<h2 id="dto">DTO</h2>
<ul>
<li>이건 별거 없음 그냥 oauth 종속성 추가함에 따라 기존 DTO에 column 추가하고 oauth속성이랑 세션멤버 dto 생성한거?</li>
</ul>
<h2 id="entity">Entity</h2>
<ul>
<li>이것도 마찬가지 </li>
</ul>
<h2 id="service">Service</h2>
<ul>
<li>이거 진짜 개 큰일날뻔 한게 전체 프로젝트의 가장 중요한 부분 담당하는 service 두개가 bean으로 등록이 안되어있었음... 바로 어노테이션 추가함...지금까지 어떻게 정상적으로 실행되었는지는 잘 모르겠으나 되게 기특하다ㅠ</li>
</ul>
<h3 id="추가">추가</h3>
<p>이번에는 감사하게도 로컬상에서 커밋한 내용 그대로 배포단에서 정상적으로 실행이 됐다.. 잠깐 구글oauth 측에서 redirect uri mismatch 에러가 나긴 했는데 이것도 리디렉션 uri 조금 조물조물 거리니까 되었음. 아마 자바스크립트 원본에 ec2주소 안넣고 배포 주소 넣어서 그런듯?</p>
<p><br><br><br><br>
프론트는 변경한거 작성안함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[authentication instanceof OAuth2AuthenticationToken 그리고 authentication instanceof UsernamePasswordAuthenticationToken ]]></title>
            <link>https://velog.io/@manofmen_yj/authentication-instanceof-OAuth2AuthenticationToken-%EC%99%80authentication-instanceof-OAuth2AuthenticationToken</link>
            <guid>https://velog.io/@manofmen_yj/authentication-instanceof-OAuth2AuthenticationToken-%EC%99%80authentication-instanceof-OAuth2AuthenticationToken</guid>
            <pubDate>Mon, 16 Oct 2023 11:13:37 GMT</pubDate>
            <description><![CDATA[<p>ㅎㅇ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[카카오 기출 - 기둥과 보 설치]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B8%B0%EC%B6%9C-%EA%B8%B0%EB%91%A5%EA%B3%BC-%EB%B3%B4-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@manofmen_yj/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B8%B0%EC%B6%9C-%EA%B8%B0%EB%91%A5%EA%B3%BC-%EB%B3%B4-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Mon, 16 Oct 2023 06:48:01 GMT</pubDate>
            <description><![CDATA[<p>문제 : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/60061">https://school.programmers.co.kr/learn/courses/30/lessons/60061</a></p>
<h3 id="접근">접근</h3>
<p>기둥배열과 보 배열을 각 각 따로 이차원 배열로 생성해주었고. 기둥과 보의 시작점과 끝점을 각각 1로 설정해준후 구현하였음. </p>
<h3 id="1차-수정">1차 수정</h3>
<p>0ㅡ0ㅡ0 보가 이렇게 지어져있을 때나,
0ㅡxㅡ0 이렇게 지어져있을 때나 이차원 배열의 값은 같기 떄문에 구별이 안된다. 그리하여 시작점만 1로 설정해주는 식으로 변경하였다</p>
<h3 id="처음-코드">처음 코드</h3>
<pre><code class="language-py">def solution(n, build_frame):
    # 기둥은 바닥위에 있거나 보의 한 쪽 끝 부분 위에 있거나 다른 기둥위
    # 보는 한쪽 끝이 기둥 위 or 양쪽 끝부분이 다른 보
    gi=[[0 for i in range(n+1)] for j in range(n+1)]
    bo=[[0 for i in range(n+1)] for j in range(n+1)]

    for bu in build_frame:
        x,y,a,b=bu
        # x y는 교차점 좌표고 교차점 기준으로 보는 오른쪽 기둥은 위쪽
        if a==0:
            # 기둥
            if b==0:
                flag=True
                # first 위에 기둥
                if gi[y+1][x]==1:
                    if not (bo[y+1][x]==1 or bo[y+1][x-1]==1):
                        flag=False

                # second 오른쪽에 보
                if bo[y+1][x]==1:
                    if not(gi[y][x+1]==1 or (bo[y+1][x-1]==1 and bo[y+1][x+1]==1)):
                        flag=False

                # third 왼쪽에 보
                if bo[y+1][x-1]==1:
                    if not(gi[y][x]==1 or (bo[y+1][x-2]==1 and bo[y+1][x]==1)):
                        flag=False

                if flag:
                    gi[y][x]=0

            else:
                # 설치
                if y==0 or gi[y-1][x]==1 or bo[y][x]==1 or bo[y][x-1]==1:
                    # 바닥이거나 기둥위거나 보 위에
                    gi[y][x]=1
        else:
            if b==0:
                flag=True
                # 삭제
                # first 왼쪽에 기둥
                if gi[y][x]==1:
                    if not(bo[y][x]==1 or bo[y][x-1]==1 or y==0):
                        flag=False

                # second 오른쪽에 기둥
                if gi[y][x+1]==1:
                    if not(bo[y][x+1]==1 or bo[y][x]==1 or y==0):
                        flag=False

                # third 오른쪽에 보
                if bo[y][x+1]==1:
                    if not(gi[y-1][x+1]==1 or gi[y-1][x+2]==1):
                        flag=False

                # fourth 왼쪽에 보
                if bo[y][x-1]==1:
                    if not(gi[y-1][x-1]==1 or gi[y-1][x]==1):
                        flag=False
                if flag:
                    bo[y][x]=0
            else:
                if (bo[y][x+1]==1 and bo[y][x-1]==1) or gi[y-1][x+1]==1 or gi[y-1][x]==1:
                    # 다른 기둥의 한 쪽 위거나 양쪽이 보
                    bo[y][x]=1



    answer = []

    for i in  range(n+1):
        for j in range(n+1):
            if gi[i][j]==1:
                answer.append([j,i,0])
            if bo[i][j]==1:
                answer.append([j,i,1])
    answer.sort()
    return answer</code></pre>
<p>예제는 모두 통과하였으나 실 테스트 케이스는 반타작</p>
<h3 id="2차-수정">2차 수정</h3>
<p>초기코드에는 기둥 혹은 보를 삭제해줄때 해당 보 혹은 기둥많이 영향을 끼치는 부분만 고려하여 코드를 구현하였으나, 이부분에서 문제가 있었다.</p>
<p>인접 보와 기둥은 유지가 가능하더라도, 연쇄적으로 확장해봤을때 조건에 부합하지 않는 보와 기둥이 생길 수 도 있기때문에, 삭제 연산이 들어올 때마다 전체 기둥과 보의 적합성을 판단해야함</p>
<h3 id="수정된-코드">수정된 코드</h3>
<pre><code class="language-py">def delete(i,j,gb,gi,bo,n):
    if gb==0:
        # 기둥
        gi[i][j]=0
    else:
        # 보
        bo[i][j]=0
    count=0
    for y in range(n+1):
        for x in range(n+1):
            if gi[y][x]==1:
                if not(y==0 or gi[y-1][x]==1 or bo[y][x]==1 or bo[y][x-1]==1):
                    return False
            if bo[y][x]==1:
                if not((bo[y][x+1]==1 and bo[y][x-1]==1) or gi[y-1][x+1]==1 or gi[y-1][x]==1):
                    return False


    return True



def solution(n, build_frame):
    # 기둥은 바닥위에 있거나 보의 한 쪽 끝 부분 위에 있거나 다른 기둥위
    # 보는 한쪽 끝이 기둥 위 or 양쪽 끝부분이 다른 보
    gi=[[0 for i in range(n+1)] for j in range(n+1)]
    bo=[[0 for i in range(n+1)] for j in range(n+1)]

    for bu in build_frame:
        x,y,a,b=bu
        # x y는 교차점 좌표고 교차점 기준으로 보는 오른쪽 기둥은 위쪽
        if a==0:
            # 기둥
            if b==0:
                # 기둥 삭제
                if not delete(y,x,a,gi,bo,n):
                    gi[y][x]=1

            else:
                # 설치
                if y==0 or gi[y-1][x]==1 or bo[y][x]==1 or bo[y][x-1]==1:
                    # 바닥이거나 기둥위거나 보 위에
                    gi[y][x]=1
        else:
            if b==0:
                if not delete(y,x,a,gi,bo,n):
                    bo[y][x]=1
            else:
                if (bo[y][x+1]==1 and bo[y][x-1]==1) or gi[y-1][x+1]==1 or gi[y-1][x]==1:
                    # 다른 기둥의 한 쪽 위거나 양쪽이 보
                    bo[y][x]=1



    answer = []

    for i in  range(n+1):
        for j in range(n+1):
            if gi[i][j]==1:
                answer.append([j,i,0])
            if bo[i][j]==1:
                answer.append([j,i,1])
    answer.sort()
    return answer</code></pre>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/702d2df3-81b4-408a-8da0-d1215317a21e/image.png" alt=""></p>
<h3 id="참고">참고</h3>
<p>사고 확장하기
데이터 그래프로 표현할때는 정확하게 되었는지 확인</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쿠키 세션 캐시가뭐임]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98-%EC%BA%90%EC%8B%9C-%ED%86%A0%ED%81%B0%EC%9D%B4%EB%AD%90%EC%9E%84</link>
            <guid>https://velog.io/@manofmen_yj/%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98-%EC%BA%90%EC%8B%9C-%ED%86%A0%ED%81%B0%EC%9D%B4%EB%AD%90%EC%9E%84</guid>
            <pubDate>Sat, 14 Oct 2023 11:42:12 GMT</pubDate>
            <description><![CDATA[<p>JWT에 대해서 알아보고자 깔짝깔짝 구글링을 하던 중 쿠키/세션/캐시에 대한 개념을 알아두면 좋을 것 같아서 정리함</p>
<h3 id="이것들-왜씀">이것들 왜씀?</h3>
<p>http는 기본적으로 통신이 완료되면 클라이언트와 관계를 냅다 끊어버림. 즉 데이터가 유지되지 않는다. 그래서 웹에서 뭐 작성하다 새로고침하면 다 날라가는거임ㅋㅋ.</p>
<blockquote>
<p> 그러나, 어떤 데이터들은 유지되어야 할 필요가 있다.</p>
</blockquote>
<p>예를들어, 우리가 특정 사이트에 로그인을 했는데, 새로고침 한번 했다고 로그아웃이 된다면 굉장히 어처구니가 없을것</p>
<p>그래서 이러한 데이터들을 브라우저등에 &quot;임시로 저장&quot; 하기 위해 사용되는 것이 바로 쿠키/세션/캐시/토큰이라고 할 수 있다~</p>
<h3 id="쿠키">쿠키</h3>
<blockquote>
<p>쿠키는 웹사이트 접속시 내 컴퓨터 혹은 웹 브라우저에 저장되는 작은 텍스트 조각이다.
(크롬일 경우 브라우저에, IE일 경우 내컴퓨터에 저장됨)</p>
</blockquote>
<p>쿠키에는 서버에서 유저를 식별할 수 있는 데이터들이 저장되며, 지정된 만료일이 지나면 삭제된다.</p>
<p>쿠키는 사용자가 수정및 삭제할 수 있고, 제 3자가 조회할 수 있기 때문에 가벼운 정보들이 저장되며 보안상 민감한 정보는 저장되지 않는다. 예를 들어 검색내역, 장바구니 내역등은 제3자에게 보여져도 보안상 큰 타격이 없지만, 사용자의 개인정보 내용등은 타인에게 보여지면 안된다.</p>
<h3 id="캐시">캐시</h3>
<blockquote>
<p>캐시란 자주 사용하는 데이터나 값을 미리 복사해놓는 임시 장소</p>
</blockquote>
<ul>
<li>(캐시는 인터넷 환경 뿐만 아니라 다양한 곳에서 사용되는 개념. 컴퓨터 하드웨어 안에서도 정보를 더 빨리 가져오기 위한 cpu캐시등이 있음)</li>
</ul>
<p>데이터를 서버에 요청하는 과정에는 시간 및 자원이 소모된다. 그러므로 반복적으로 쓰이는 데이터는 매번 서버에 요청하는 것 보다 저장해놨다가 쓰는 것이 효율적. 이때 쓰이는 것이 캐시. 예를 들어 프로필 사진같은 경우는 짧은 시간 단위로 변화하지 않기 때문에, (여기서 짧은 시간은 밀리초 혹은 초 단위) 매번 서버에 요청하는 것 보다는 캐시에서 가져오는 것이 더 효율적임. 그래서 가끔 프로필 사진 바꿔도 새로고침 광클해야 변하는 경우 있는데 그게 프로필 사진이 캐싱돼서 그런거임 ㅇㅇ</p>
<h3 id="세션">세션</h3>
<blockquote>
<p>세션은 서버가 유저를 구분하기 위해 사용되는 방법이다.</p>
</blockquote>
<p>우리가 특정 사이트에 접속하여 글을 쓰기 위해 로그인을 하였다고 가정하자. 그러나 기본적으로 사이트는 로그인을 하기 이전의 사용자와 로그인을 한 이후의 사용자가 동일 인물이라는 것을 알지 못한다. </p>
<p>그렇기 때문에 새로은 글을 작성할 때마다 로그인을 해야한다. 하지만 실제로 우리가 사이트를 이용할때 그런 번거로운 과정을 다 거치지 않는다. 그이유가 바로 &quot;세션&quot;때문이다.</p>
<p>유저가 로그인에 성공하면 서버는 세션 아이디를 사용자에게 전달하고, 사용자는 세션아이디를 쿠키에 저장한다.(그래서 크롬 종료해도 로그인 유지되는거) 서버가 유저로부터 요청을 받을 때 마다 이 세션아이디를 통해 누구의 계정인지 확인하고 요청을 수행함. (영화관에서 티켓내면 보관용만 찢어서 다시 주는거처럼)</p>
<h3 id="토큰">토큰</h3>
<p>이건 나중에 JWT하면서 ㄱ</p>
<h3 id="참고">참고</h3>
<p><a href="https://hongong.hanbit.co.kr/">https://hongong.hanbit.co.kr/</a>
<a href="https://devbirdfeet.tistory.com/203">https://devbirdfeet.tistory.com/203</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2020 카카오 기출 - 외벽점검]]></title>
            <link>https://velog.io/@manofmen_yj/2020-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B8%B0%EC%B6%9C-%EC%99%B8%EB%B2%BD%EC%A0%90%EA%B2%80</link>
            <guid>https://velog.io/@manofmen_yj/2020-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B8%B0%EC%B6%9C-%EC%99%B8%EB%B2%BD%EC%A0%90%EA%B2%80</guid>
            <pubDate>Fri, 13 Oct 2023 10:39:13 GMT</pubDate>
            <description><![CDATA[<p>문제 : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/60062">https://school.programmers.co.kr/learn/courses/30/lessons/60062</a></p>
<h3 id="접근">접근</h3>
<p>각각의 데이터의 크기가 크지 않아 완전탐색 알고리즘으로 접근하였다. n짜리의 원형의 외벽을 크기 2n짜리 배열을 생성하고, range(0,n)까의 반복문을 돌면서 i~i+n부분을 파싱하고 dist배열을 permutaations 한 값을 하나씩 순회하면서 최소갯수를 갱신해주었으나 몇몇 테스트 케이스에서 시간초과가 발생하였다.</p>
<h3 id="수정">수정</h3>
<p>외벽이 원형의 형태로 주어졌기 때문에 이를 두배로 늘려 배열 형태로 변환하는 것은 맞다. 그러나 기준이 잘못되었음.</p>
<p>굳이 크기가 2n짜리인 배열을 선언하는 것이 아니라, weak의 크기 *2 만큼만 선언하여도 충분하다. 어차피 중요한것은 weak의 위치 보다는, 각 weak사이의 거리가 더 중요하기 때문에,</p>
<pre><code class="language-py">    for we in weak:
        newweak.append(we)
        newweak.append(we+n)
    newweak.sort()
</code></pre>
<h3 id="전체-코드">전체 코드</h3>
<pre><code class="language-py">from itertools import permutations
from collections import deque
def solution(n, weak, dist):
    minlength=100000
    newweak=[]
    check=len(weak)
    for we in weak:
        newweak.append(we)
        newweak.append(we+n)
    newweak.sort()
    dist_permu=list(permutations(dist,len(dist)))

    for i in range(check):
        for dist in dist_permu:
            cur_newweak=deque(newweak[i:i+check])
            dist=deque(dist)
            count=1
            curweak=cur_newweak.popleft()
            curdist=dist.popleft()
            flag=False
            while len(cur_newweak)&gt;0:
                if cur_newweak[0]-curweak&lt;=curdist:
                    cur_newweak.popleft()
                else:
                    curweak=cur_newweak.popleft()
                    if dist:
                        curdist=dist.popleft()
                        count+=1
                    else:
                        flag=True
                        break
            if flag:
                continue
            else:
                minlength=min(minlength,count)
    if minlength==100000:
        return -1
    return minlength
</code></pre>
<h3 id="참고">참고</h3>
<p>원형은 배열로 변환, 데이터 적으면 완탐 먼저 생각</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 연습문제 - 거스름돈]]></title>
            <link>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%97%B0%EC%8A%B5%EB%AC%B8%EC%A0%9C-%EA%B1%B0%EC%8A%A4%EB%A6%84%EB%8F%88</link>
            <guid>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%97%B0%EC%8A%B5%EB%AC%B8%EC%A0%9C-%EA%B1%B0%EC%8A%A4%EB%A6%84%EB%8F%88</guid>
            <pubDate>Tue, 10 Oct 2023 12:01:15 GMT</pubDate>
            <description><![CDATA[<p>문제 : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/12907">https://school.programmers.co.kr/learn/courses/30/lessons/12907</a></p>
<h3 id="접근">접근</h3>
<p>동적계획법을 활용한 bootom-up 방식으로, 값이 올라갈수록 해당 경우의 수를 갱신하여 계산하고자 함</p>
<h3 id="시행착오---금액을-기준으로-접근">시행착오 - 금액을 기준으로 접근</h3>
<p>처음에는 dp[n] 배열을 선언하고, 다음과 같이 money배열을 순회하면서 해당 배열의 인덱스값을 갱신해주는 방법을 선택하였다</p>
<pre><code class="language-py">for m in money:

    dp[i]+=dp[i-m]
    # 왜냐하면 동전이 1,2,5원이 있다고 가정할때, 
    #10원을 내는 경우의 수는 5원을 만드는 경우의 수에 5원짜리를 낸것+ 
    #8원짜리 경우의 수에 2원짜리 낸것 + 
    #9원짜리 경우의 수에 1원짜리 낸 것과 같기 때문
    #근데 이 생각은 굉장히 안일한 생각이었다.</code></pre>
<p>하지만 위 로직은 잘못 되었는데, 왜냐하면 각각의 경우마다 중복된 경우를 제거하지 않았기 때문이다. 예를들어 1원 2원을 활용하여 4원을 만든다고 할때, 해당 로직은 dp[3]+dp[2]로 계산된다. 하지만 각각의 경우를 살펴보면 </p>
<h4 id="3을-만드는-경우의-수">3을 만드는 경우의 수</h4>
<p>1,1,1 +1
1,2 +1
2,1 +1</p>
<h4 id="2를-만드는-경우의-수">2를 만드는 경우의 수</h4>
<p>1,1 +2
2 +2</p>
<p>위 경우처럼 중복이 발생한다. 즉 이 방법은 폐기되어야 함</p>
<h3 id="해결---동전-갯수를-기준으로-접근">해결 - 동전 갯수를 기준으로 접근</h3>
<blockquote>
<p>중복인 경우를 배제하면서, 이전 결과에서 현재 결과를 도출하는 식을 찾아야한다</p>
</blockquote>
<p>먼저 1원 동전만을 사용해서 1원~n원을 거슬러주는 경우의수는 모두 1이다
1
1,1
1,1,1
1,1,1,1....</p>
<p>여기서 2원 동전을 포함하여 거스름돈을 주는 경우의수는 다음과 같다
1원 : 1
2원 : 1+1, 2
3원 : 1+2, 1+1+1
4원 : 1+1+1+1, 2+1+1, 2+2
5원 : 1+1+1+1+1, 2+1+1+1, 2+2+1</p>
<p>즉 n원을 1원과 2원으로 거슬러주는 경우의 수는,
n을 1원만으로 거슬러주는 경우의 수 + n-2원을 1원만으로 거슬러주는 경우의 수 + n-4를 1원만으로 거슬러주는 경우의 수.... 등으로 표현할 수 있다</p>
<p>여기에 5가 추가된다면
이와 비슷하게 n원을 1원과 2원만으로 거슬러주는 걍우의 수+ n-5원을 1원과 2원만으로 거슬러주는 경우의 수, ..으로 표현할 수 있다.</p>
<p>이를 코드로 옮기면 다음과 같아짐</p>
<h3 id="전체-코드">전체 코드</h3>
<pre><code class="language-py">def solution(n, money):
    dp=[0]*(n+1)
    for mo in money:
        for i in range(1,n+1):
            if i==mo: # money에 포함되는건 일단 1을 더해주어야함
                dp[i]+=1
            elif i&gt;mo:
                dp[i]+=dp[i-mo]
            dp[i]=dp[i]%1000000007

    return dp[-1]</code></pre>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/f32663b0-540b-4f47-b03b-f1032bca9533/image.png" alt=""></p>
<h3 id="참고">참고</h3>
<p>구글 각종 글</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[운영체제 - 쓰레드]]></title>
            <link>https://velog.io/@manofmen_yj/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%93%B0%EB%A0%88%EB%93%9C</link>
            <guid>https://velog.io/@manofmen_yj/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%93%B0%EB%A0%88%EB%93%9C</guid>
            <pubDate>Mon, 09 Oct 2023 12:56:40 GMT</pubDate>
            <description><![CDATA[<h1 id="ch4-쓰레드">Ch4 쓰레드</h1>
<h2 id="쓰레드란">쓰레드란</h2>
<blockquote>
<ul>
<li>실질적인 실행의 기본 단위<ul>
<li>Linux, Windows등 대부분의 커널에서 실행의 실질적인 단위는 프로세스가 아니라 스레드임!!</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li><p>스케쥴링의 단위</p>
</li>
<li><p>쓰레드들은 각자 자신의 stack 영역을 보유함(최소한 자신의 레지스터 상태를 보유함)</p>
</li>
<li><p>쓰레드는 프로세스 내에서 heap, data, code 영역을 공유</p>
<blockquote>
<p>쓰레드는 해당 프로세스 안의 메모리를 공유해서 사용할 수 있다.
일반적으로 프로세스는 최소한 하나의 쓰레드를 가지고 있다. 둘 이상의 스레드를 가지고 있다면 이는 멀티스레드라고함.
<img src="https://velog.velcdn.com/images/manofmen_yj/post/4af45a99-34d3-4532-937f-4f6141a96bb4/image.png" alt=""></p>
</blockquote>
</li>
</ul>
<h3 id="쓰레드의-이점">쓰레드의 이점</h3>
<ul>
<li><p>Responsiveness(응답성) : 프로세스의 일부가 차단되었음에도 나머지 스레드는 계속해서 실행될 수 있음. ex) UI같이 응답성이 중요한 부분에서 사용자와의 상호작용을 계속해서 유지하여야 하기 때문</p>
</li>
<li><p>Resource Sharing(자원 공유) : 쓰레드는 하나의 프로세스 내에서 실행되므로 프로세스의 자원을 공유 할 수 있고 이는 공유 메모리나 메세지패싱보다 효과적이다.</p>
</li>
<li><p>Economy(경제성) : 쓰레드를 생성하는 것이 프로세스를 생성하는 것보다 더 적은 자원을 소비하며, 쓰레드 전환은 프로세스간 전환보다 오버헤드가 낮다. 이로인해 스레드를 경량 프로세스라고 부르기도 함.</p>
</li>
<li><p>Scalability(확장성) : 멀티프로세서 아키텍처에서 여러 스레드가 동시에 실행될 수 있으므로 프로세스는 다중 프로세서 환경에서 성능을 향상시킬 수 있다.</p>
<h4 id="멀티프로세스-vs-멀티스레드">멀티프로세스 vs 멀티스레드</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/7cb720e1-5e55-4fe3-af0c-86e43c06d5b7/image.png" alt=""></p>
</li>
<li><p>멀티 프로세스 : 하나의 응용프로그램을 여러개의 프로세스로 구성하여 각 프로세스가 작업을 처리하도록 하는것.</p>
</li>
<li><p>멀티 스레드 : 하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시키는 것. 이 경우 각각의 스레드는 독립적인 작업을 수행해야 하기 때문에 각자의 스택과 PC 레지스터 값을 갖고 있다.</p>
</li>
</ul>
<blockquote>
<h4 id="예시">예시</h4>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/1d21f2f7-4301-4d2b-85f9-64ae215826f0/image.png" alt=""></p>
</blockquote>
<ul>
<li>Google Docs가 프로세스고, 문서에 참여하는 사용자들을 스레드라 가정</li>
<li>만약 멀티 프로세스라면 사용자 한 명당 하나의 Google Docs</li>
<li>만약 멀티 스레드라면 여러 사람들이 각자의 임무를 하나의 Google Docs에서 동시에 마무리</li>
</ul>
<hr>
<ul>
<li>사용자 수만큼의 Google Docs -&gt; 1개의 Google Docs</li>
<li>-&gt; 사용 자원 감소</li>
<li>작업 후 여러개의 Google Docs 취합 -&gt; 함께 임무 수행 (취합필요x)</li>
<li>-&gt; 통신 비용 감소</li>
</ul>
<h4 id="멀티스레딩의-장점">멀티스레딩의 장점</h4>
<ul>
<li><p>메모리 공간과 시스템 자원의 절약 (당연함)</p>
</li>
<li><p>스레드간 통신을 할 때에도 별도의 자원을 이용하는 것이 아니라 프로세스의 전역변수나 동적으로 할당된 공간인 Heap영역을 사용하면 됨(프로세스간 통신인 IPC에 비해 간단)</p>
</li>
<li><p>또한 스레드의 문맥교환은 프로세스의 문맥교환과 달리 캐시메모리를 비울 필요가 없어 더 빠름</p>
<h4 id="멀티스레딩의-문제점">멀티스레딩의 문제점</h4>
</li>
<li><p>공유 자원에 접근할 때 스레드간 동기화 작업이 필요하다. 하지만 이러한 동기화 작업으로 인해 병목현상이 발생하여 성능이 저하될 수도 있다.</p>
</li>
<li><p>멀티프로세스는 하나의 프로세스가 죽더라도 다른 프로세스에는 영향을 끼치지 않고 수행된다는 장점이 있지만 (카톡하다 오류 발생했다고 틀어놓은 멜론 노래가 꺼지진 않듯이) 멀티스레드는 하나의 스레드가 죽으면 전체 스레드가 죽을 수 도 있음.</p>
</li>
</ul>
<blockquote>
<p>멀티스레딩과 멀티프로세싱 이 두가지는 동시에 여러가지를 수행한다는 점은 같지만 시스템에 따라서 적합 부적합이 갈린다 --&gt; 적합한 방식 선택 ㄱㄱ</p>
</blockquote>
<h3 id="멀티코어프로그래밍">멀티코어프로그래밍</h3>
<blockquote>
<p>하나의 작업을 위해 여러개의 cpu 코어를 활용하기 위해 코드를 작성하는 작업</p>
</blockquote>
<h4 id="parellelism병렬성-vs-concurrency동시성">Parellelism(병렬성) vs Concurrency(동시성)</h4>
<ul>
<li>동시성 : 동시에 실행되는 것 &quot;처럼 보이는것&quot;<ul>
<li>싱글코어, 멀티코어에서 가능</li>
</ul>
</li>
<li>병렬성 : 실제로 동시에 실행되는 것<ul>
<li>멀티코어에서 가능</li>
<li>Data 병렬성, Task 병렬성<h4 id="동시성">동시성</h4>
<img src="https://velog.velcdn.com/images/manofmen_yj/post/40375ce1-a591-4a54-adb6-a3bf931602d3/image.png" alt=""><h4 id="병렬성">병렬성</h4>
<img src="https://velog.velcdn.com/images/manofmen_yj/post/08596e73-bee3-4649-8c0c-95f4bde35d61/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="싱글스레드-프로세스--멀티스레드-프로세스">싱글스레드 프로세스 &amp; 멀티스레드 프로세스</h3>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/1e7e7c0d-9488-47df-b104-526b03a3f58c/image.png" alt=""></p>
<p>다음은 번외로 프로세스, 스레드, 멀티태스킹, 멀티스레딩, 멀티프로세싱, 멀티프로그래밍 총정리 ㄱ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 1차 - 추석트래픽]]></title>
            <link>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1%EC%B0%A8-%EC%B6%94%EC%84%9D%ED%8A%B8%EB%9E%98%ED%94%BD</link>
            <guid>https://velog.io/@manofmen_yj/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1%EC%B0%A8-%EC%B6%94%EC%84%9D%ED%8A%B8%EB%9E%98%ED%94%BD</guid>
            <pubDate>Mon, 09 Oct 2023 10:44:29 GMT</pubDate>
            <description><![CDATA[<p>문제 : <a href="https://school.programmers.co.kr/learn/courses/30/lessons/17676">https://school.programmers.co.kr/learn/courses/30/lessons/17676</a></p>
<h3 id="접근">접근</h3>
<h3 id="시행착오-1">시행착오 1</h3>
<p>처음에 문제를 보자마자 그전의 기출을 통해 그리디 알고리즘으로 해결해야 하는 문제인것은 캐치하였으나, 그 이후로 나아가질 못하였다. N의 최대 크기가 2000인 점에서 완전탐색도 어느정도 염두해 두고 문제를 해결해나갔어야 했는데, 그 부분까지 도달하지 못하여 작업을 하나씩 꺼내서 순회하는것을 생각하지 못하였고, 이틀에 걸쳐서 문제를 풀게 되었다. 쉬운 문제라고 생각했는데 역시 카카오 문제가 쉬울리 없지 ㅠ</p>
<h3 id="시행착오-2">시행착오 2</h3>
<pre><code class="language-py">for i in range(len(N)):
    count=0
    pres,pree=N[i][0],N[i][1]
    for j in range(len(N)):
        ns,ne=N[j][0],N[j][1]
        if ns&lt;pree+1000:
            count+=1</code></pre>
<p>안일하게 완전탐색으로 N*N으로 계산하였으나 저렇게 작성하면 오류가 발생함. 후반 인덱스로 갈수록 e가 커지기 때문에. ns&lt;pree+1000 이부분이 무조건적으로 참을 반환할 확률이 다분하게 커지기 때문에, 다음과 같이 수정해주어야한다.</p>
<pre><code class="language-py">for i in range(len(N)):
    count=0
    pres,pree=N[i][0],N[i][1]
    for j in range(i,len(N)):
        ns,ne=N[j][0],N[j][1]
        if ns&lt;pree+1000:
            count+=1</code></pre>
<h3 id="시행착오-3">시행착오 3</h3>
<p>배열을 순회하는 과정에서 겹치는 작업을 계산할 때 부등호를 ns&lt;=pree+1000 로 작성하였었는데 해당 부분에 오류가 있었다. 왜냐하면 작업은 시작시간과 끝 시간이 포함이므로, 어떤 작업이 끝나자마자 다시 시작한다고 하였을때 count는 1이 되어야 하는것이 정상이지만, 해당 ns&lt;=pree+1000 로직으로 계산하였을 경우 count가 2가 되기때문에 다음과 같이 ns&lt;pree+1000로 수정해 주어야 한다.</p>
<h3 id="전체-코드">전체 코드</h3>
<pre><code class="language-py">def solution(lines):
    N=[]
    maxval=0
    for line in lines:
        line=line.split()
        hms=line[1]
        hms=hms.split(&quot;:&quot;)
        tosec=int(hms[0])*3600+int(hms[1])*60+float(hms[2])
        tomil=int(tosec*1000)
        spent=int(float(line[2][:-1])*1000)
        start,end=tomil-spent+1,tomil
        N.append([start,end])
    for i in range(len(N)):
        count=0
        pres,pree=N[i][0],N[i][1]
        for j in range(i,len(N)):
            ns,ne=N[j][0],N[j][1]
            if ns&lt;pree+1000:
                count+=1
        maxval=max(maxval,count)
    return maxval</code></pre>
<p><img src="https://velog.velcdn.com/images/manofmen_yj/post/ca1f3840-a587-4e86-a2e6-203c1c4cc762/image.png" alt=""></p>
<h3 id="참고">참고</h3>
<p>데이터의 갯수가 충분히 작을때는 항상 브루트포스 염두해 두길</p>
]]></description>
        </item>
    </channel>
</rss>