<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>chxxrin.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 16 Aug 2025 11:56:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>chxxrin.log</title>
            <url>https://velog.velcdn.com/images/bomi__unni/profile/be601073-0771-4f9c-87c8-5f48af3ca531/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. chxxrin.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/bomi__unni" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[네이버 부스트캠프] 웹모바일 10기 베이직 + 챌린지 회고록]]></title>
            <link>https://velog.io/@bomi__unni/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%9B%B9%EB%AA%A8%EB%B0%94%EC%9D%BC-10%EA%B8%B0-%EB%B2%A0%EC%9D%B4%EC%A7%81-%EC%B1%8C%EB%A6%B0%EC%A7%80-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@bomi__unni/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%B6%80%EC%8A%A4%ED%8A%B8%EC%BA%A0%ED%94%84-%EC%9B%B9%EB%AA%A8%EB%B0%94%EC%9D%BC-10%EA%B8%B0-%EB%B2%A0%EC%9D%B4%EC%A7%81-%EC%B1%8C%EB%A6%B0%EC%A7%80-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Sat, 16 Aug 2025 11:56:46 GMT</pubDate>
            <description><![CDATA[<p>25년도, 취준을 하면서 개발자 길이 과연 맞을까 고민을 많이 했었다.
같이 동아리를 했던 친구들은 개발을 정말 즐기고 있었는데 
그에 비해서 나는 사실 개발이 너무 어렵고 어렵고 어려웠다 ㅠㅠ (여전히 어렵다...)
그래서 마지막 기회로 네부캠을 지원해보자는 생각을 했다.</p>
<h2 id="베이직-코스">베이직 코스</h2>
<p>먼저 서류를 작성하고 모든 지원자들 대상으로 베이직 코스가 진행된다. 
2주동안 매일 나오는 과제를 수행하는 방식인데, 
나는 도중에 이사준비를 하느라 주말에 부족한 부분을 채우면서 10개의 과제를 모두 수행했다.
과제는 CS기반 지식과 프로그래밍 지식을 필요로 하는 전공과제같은 느낌이었다.
매일매일 전공과제를 하는 건 좀 빡세긴 했는데
지금 생각해보면 베이직 과제들은 정말 귀여운 수준이었던 것 같다...ㅎㅎ</p>
<h2 id="문제해결력-테스트">문제해결력 테스트</h2>
<p>언어는 자바스크립트로 진행이 되었고 CS지식 문제 + 코딩테스트 문제가 나왔다.
CS지식 문제는 문제를 잘 읽고 풀면 어느정도 맞출 수 있는 문제들이었고 
코딩테스트 문제들은 기업 코테보다는 풀만했다! 
내 기억으로는 CS문제들은 5개 이내로 틀렸을 것 같고 코테는 1.5-2솔 정도였던 것 같다. 
근데 코테 1문제 풀었는데 합격한 사람도 있고 
3문제 모두 풀었는데 불합격한 사람도 있다고 하니(이건 확실하지 않긴함)
베이직과제를 모두 성실히 수행한 것에 더 중점을 두지 않았을까 생각이 든다. </p>
<h2 id="챌린지-코스">챌린지 코스</h2>
<p>그렇게 시작된 챌린지 코스!! 4주동안 월화수목금 진행이 된다. 아래는 내 하루 일과였다. </p>
<pre><code>7:00-10:00 (미완료시 재검토)
9:00 기상
9:00-10:00 과제 최종검토
10:00-11:00 팀원 피드백 작성
11:00-12:00 줌으로 코드리뷰 진행
12:00-13:00 점심식사 + 커피/빵수혈
13:00-14:00 초안작성
14:00-18:00 학습과 설계
18:00-19:00 저녁식사 + 커피 재수혈
19:00-2:00 개발
2:00- 취침
</code></pre><p>정말 좋았던건 무너진 내 루틴을 챌린지 덕분에 잘 잡을 수 있었다. 
무조건 9시 전에 기상하고 하루의 대부분을 컴퓨터 앞에서 보냈다. </p>
<p>4주간 매주 과제 4개씩, 총 16번의 과제를 진행했는데 정말 많이 어려웠다. 
이런 과제들을 한 번도 자바스크립트로 구현해본적이 없었다. 
너무 당연하게 활용하고 있던 시스템들을 아주 낮은 단위부터 개발하려고 하니 
감도 안잡히고 설계도 어떻게 해야하는지 알 수 없었다 ㅠㅠ
그래서 100% 과제를 완성하지 못하는 경우가 많았다.
그래도 최대한 과제 내용을 이해하고 내 손으로 설계해보고 AI에게도 물어보면서 하나하나 해나갔다.
피어 피드백을 통해서 만났던 동료들은 정말 너무너무너무 똑똑한 사람들이 많았고 
이미 찐개발자같은 면모를 보이는 분들도 많았다. 
그에 비해서 나는 모르는 것도 많고 아직도 잘 모르는게 많구나.. 라는 반성을 하게 되었다. </p>
<h2 id="피어피드백">피어피드백</h2>
<p>매일 매일 코드리뷰를 진행하면서 내 코드를 피어분들께 공유하고 설명하는 시간이 걱정되기도 하면서도 설렜다. 
사실 대부분 거의 밤새면서 코드를 구현하느라 아침에는 비몽사몽한 상태여서
내가 쓴 코드도 잘 안읽히고 말도 잘 안나와서 
팀원분들이 바보라고 생각하면 어쩌지라는 걱정도 했다 ㅠㅠ
그래도 다들 응원도 해주시고 피드백도 주시고 질문도 해주시면서 
내가 모르는 부분은 더 채워가려고 했고 아는 부분은 최대한 답하려고 노력했다. 
나 혼자 과제를 진행했던 베이직때는 그냥 과제 구현에만 신경을 썼다면
매일 피드백이 이루어지는 챌린지때는 &quot;아 이걸 어떻게 설명해야하지? 어떤식으로 말을 해야 내가 설계한 방식을 사람들이 이해하지?&quot; 하면서 코드내용을 말로 풀어내는 방법을 고민했던 것 같다. 
여전히 완벽하지 않고 부족한 점 투성이지만, 그래도 처음보다는 조금 더 똘똘하게 내 생각을 말할 수 있게 되지 않았나 싶다. </p>
<h2 id="ai-릴레이-프로젝트">AI 릴레이 프로젝트</h2>
<p>네부캠은 AI 활용을 굉장히 중요시했다. 
이제는 AI와 함께 성장하는 시대이니만큼 AI를 잘 활용하고 또 다양한 방식으로 활용하는걸 권하는 것 같다. 
그래서 매주 금요일에는 AI를 활용한 새로운 미션들을 받고 그 과제를 한 주동안 수행해나갔다. 
AI에게 권한 부여하기, AI에게 운동루틴 추천받기, AI에게 체크포인트 점검받기 등 다양한 미션을 진행했다. 
AI를 활용하면 정말 다양한 일들을 해볼 수 있구나라는 생각이 들면서 
재밌기도 하지만, 너무너무 똑똑해서 이를 잘 다룰 수 있는 실력도 필요하겠구나 싶었다.</p>
<p>그래도 어찌어찌 마지막까지 완주를 했다!!! 완주 기념 내준내상 ㅎㅎㅎ 뿌듯하다
<img src="https://velog.velcdn.com/images/bomi__unni/post/04aaf373-5073-46f8-98dc-13b0bcd9ede2/image.png" alt=""></p>
<p>수료증까지 받고 나니까 홀가분한 마음이 들었다. 
정말 간절히 열심히 했지만 너무 훌륭한 동료들이 많아서 
혹시라도 멤버십이 안되더라도 속상해하지말자며 
5일동안은 집에서 푹 쉬고 마사지도 받고 맛있는것도 먹으면서 휴식을 취했다. </p>
<h2 id="챌린지-입과-확정">챌린지 입과 확정</h2>
<p>딱 5일째 되는날, 내가 좋아하는 초밥집에 혼자 가서 
초밥을 먹고 있는데 갑자기 메일이 와서 읭!? 하고 봤더니 합격 메일이었다!!!</p>
<p>정말 너무 기뻤다
아마 이번 부스트캠프는 내게 마지막 기회일 것이다. 
최선을 다해서 임해서 꼭 좋은 결과를 내자. 
좋은 동료들과 소통도 열심히 하면서 최선의 결과를 내자ㅎㅎ</p>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/423d20d4-b076-47d7-bdf7-20d7b6850b37/image.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript 코딩테스트 테스트케이스 입출력 코드 (소프티어, 백준)]]></title>
            <link>https://velog.io/@bomi__unni/Javascript-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%BC%80%EC%9D%B4%EC%8A%A4-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%BD%94%EB%93%9C-%EC%86%8C%ED%94%84%ED%8B%B0%EC%96%B4-%EB%B0%B1%EC%A4%80</link>
            <guid>https://velog.io/@bomi__unni/Javascript-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%BC%80%EC%9D%B4%EC%8A%A4-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%BD%94%EB%93%9C-%EC%86%8C%ED%94%84%ED%8B%B0%EC%96%B4-%EB%B0%B1%EC%A4%80</guid>
            <pubDate>Mon, 03 Feb 2025 08:39:31 GMT</pubDate>
            <description><![CDATA[<pre><code>const fs = require(&#39;fs&#39;);
const inputFile = fs.readFileSync(&#39;/dev/stdin&#39;, &#39;utf8&#39;).trim()</code></pre><p>입력 구조에 따라서 .split()과 .map()을 사용하면 된다!</p>
<h3 id="입력예시1--첫번째-줄은-테스트케이스-나머지-줄은-한줄에-하나씩-있는-입력값">입력예시1 : 첫번째 줄은 테스트케이스, 나머지 줄은 한줄에 하나씩 있는 입력값</h3>
<pre><code>3
12
1
5</code></pre><pre><code>const fs = require(&#39;fs&#39;);
const inputFile = fs.readFileSync(&#39;/dev/stdin&#39;, &#39;utf8&#39;).trim().split(&#39;\n&#39;).map(Number);
const [T, ...input] = inputFile; // 구조분해할당</code></pre><ol>
<li>fs</li>
<li>inputFile</li>
<li>구조분해할당으로 테스트케이스와 나머지값들을 나눠서 배열로 저장</li>
</ol>
<h3 id="입력예시2--첫번째-줄은-테스트케이스-나머지-줄은-한줄에-두개-이상씩-있는-입력값">입력예시2 : 첫번째 줄은 테스트케이스, 나머지 줄은 한줄에 두개 이상씩 있는 입력값</h3>
<pre><code>4
10 5
6 3
3 2
4 2</code></pre><p>이런형식이면</p>
<pre><code>const fs = require(&quot;fs&quot;);
const inputFile = fs.readFileSync(&quot;/dev/stdin&quot;, &quot;utf8&quot;).trim().split(&quot;\n&quot;);</code></pre><h3 id="입력예시3--한-줄에-입력값이-2개">입력예시3 : 한 줄에 입력값이 2개</h3>
<pre><code>3500 2000</code></pre><pre><code>const fs = require(&quot;fs&quot;);
const inputFile = fs.readFileSync(&quot;/dev/stdin&quot;, &quot;utf8&quot;).trim().split(&quot; &quot;);
const [A, B] = inputFile.map(Number);</code></pre><ul>
<li>주의: inputFile로 들어가면 문자열이 되므로 입력값을 숫자로 변환해줘야 크기비교가 가능하다!</li>
</ul>
<h3 id="입력예시4-">입력예시4 :</h3>
<pre><code>5
1 3 5 8 10</code></pre><p>만약 첫 번째 줄에 테스트케이스, 두 번째 줄에 한줄로 쭉 입력값이 있다면</p>
<ol>
<li>구조분해할당으로 첫 번째 줄과 두 번째 줄을 나누기</li>
<li>테스트케이스를 숫자로 변환하기</li>
<li>문자열을 공백을 기준으로 나누고 다시 각 요소를 숫자로 변환하기</li>
</ol>
<pre><code>const fs = require(&quot;fs&quot;);
const inputFile = fs.readFileSync(&quot;/dev/stdin&quot;, &quot;utf8&quot;).trim().split(&quot;\n&quot;);

let [n, input] = inputFile; // 구조 분해 할당
n = parseInt(n); // 숫자로 변환
input = input.split(&quot; &quot;).map(Number); // 문자열을 공백 기준으로 나누고, 각 요소를 숫자로 변환</code></pre><p>만약 입력이 여러줄이면서 모두 Number로 바꾸고 싶다면</p>
<pre><code>const fs = require(&#39;fs&#39;);
const inputFile = fs.readFileSync(&#39;/dev/stdin&#39;, &#39;utf8&#39;).trim().split(&#39;\n&#39;).map(v =&gt; v.split(&#39; &#39;).map(Number));</code></pre><p>출처 : <a href="https://yunicornlab.tistory.com/18">https://yunicornlab.tistory.com/18</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[python] 사진 배경 제거 기능]]></title>
            <link>https://velog.io/@bomi__unni/python-%EC%82%AC%EC%A7%84-%EB%B0%B0%EA%B2%BD-%EC%A0%9C%EA%B1%B0-%EA%B8%B0%EB%8A%A5</link>
            <guid>https://velog.io/@bomi__unni/python-%EC%82%AC%EC%A7%84-%EB%B0%B0%EA%B2%BD-%EC%A0%9C%EA%B1%B0-%EA%B8%B0%EB%8A%A5</guid>
            <pubDate>Thu, 21 Nov 2024 07:09:36 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.remove.bg/ko/upload">https://www.remove.bg/ko/upload</a></p>
<p>위의 웹서비스는 사진의 배경을 지워서 누끼를 따주는 서비스다. 
동아리 홍보 자료 만들거나 PPT 만들 때 정말 편리하게 사용했는데, 
어떤 코드로 짤 수 있는지 궁금해서 찾아보다가 엄청 간단한 코드를 발견했다!
근데 vscode 에서 짜려고 하니까 왜인지 자꾸 하나씩 에러가 나서 
참고해서 코드를 조금 수정해봤다. 
그리고 처음에는 사진 배경을 삭제를 하는데, 누끼가 아니라 배경이 지워지는 거라서
배경이 검은색이 되는 결과물이 나왔다.</p>
<p>내가 원하는건 그게 아닌데ㅠ
나는 누끼를 따고 싶단 말야!</p>
<p>우선 <code>rembg</code> 라이브러리를 사용하면 완전 간단하게 배경 제거가 된다는 걸 알게 되었다!!
너무 신기해!!</p>
<ul>
<li><code>rembg</code> : 배경제거를 위한 라이브러리다. 여기서 <code>remove() 함수</code>는 이미지에서 배경을 자동으로 제거하는 기능을 수행한다.</li>
<li><code>PIL</code> : 이미지를 열고 저장할 수 있도록 도와주는 Python Imaging Library이다. </li>
<li><code>io</code>: 이미지 데이터를 바이너리 형식으로 처리하기 위해 사용된다.</li>
</ul>
<p>일단 매우매우 간단하게 vscode에서 실험을 해본거기 때문에 아직은 파일 경로를 직접 설정해줘야했다.
이 부분은 나중에 좀 더 개선해서 react랑 연동해서 파일을 drag or drop을 하면 
배경제거가 된 파일을 다운받을 수 있게 해보고 싶다!</p>
<p>배경제거가 된 후의 이미지 데이터는 바이너리 형식으로 되고, 그 다음에는 바이너리 데이터를 이미지로 변환해줘야 한다.
그리고 내 결과 파일은 왜 검은색 배경이 나왔는지 알게 되었다... 
처음에는 <code>JPEG</code> 포맷으로 결과물을 받았는데, <code>JPEG</code>는 투명 배경을 지원하지 않았던 것이었다,, 
그래서 포맷만 <code>PNG</code>로 바꿨떠니 바로 투명 배경으로 다운로드 받을 수 있게 됐다. 
사실 처음 안 사실,,</p>
<h1 id="rembg">rembg</h1>
<p>이 라이브러리는 처음 사용해보았는데, 알고보니 딥러닝 모델을 기반으로 하여 배경을 자동으로 제거해주는 라이브러리였다. 내부적으로 rembg는 U-2-Net이라는 모델을 사용하며 이미지에서 객체와 배경을 구분하는 학습된 신경망을 기반으로 동작한다고 한다.</p>
<p>나는 코드 한줄로 뚝딱했는데, 어떻게 제거가 되는지 궁금해서 찾아보니 다음과 같은 과정으로 진행된다고 한다.</p>
<ol>
<li>입력 이미지가 모델에 전달된다.</li>
<li>모델은 이미지 내에서 주요 객체 (예: 사람, 동물 등)와 배경을 구분한다.</li>
<li>모델은 객체 영역을 유지하고, 배경 부분을 제거하여 투명하게 만든다.</li>
<li>결과적으로, 객체만 남고 배경은 제거된 이미지가 반환된다.</li>
</ol>
<p>다만, 아직 부족한 점은 자동으로 배경을 제거해주긴 하는데, 배경과 비슷한 색상의 객체나 옷같은 경우 그거까지 다 삭제를 해버려서 인생네컷에서 하늘색 배경에서 하늘색 옷을 입고 찍었던 사진은 옷까지 날아가버렸다 ㅠㅠ
이 부분은 추가적인 보정이 필요할듯하다!!</p>
<p>아이폰에서는 그냥 꾸욱 누르면 짠하고 배경제거가 되는게 너무 신기했다ㅠㅠ
게다가 속도도 너무 빨라!!</p>
<p>그래도 넘 재미있는 시간이었다~~
다음엔 또 어떤걸 해보지</p>
<p>아래는 내 코드!!</p>
<pre><code>from rembg import remove
from PIL import Image
import io

# 입력 및 출력 경로 설정
input_path = &#39;손흥민.jpg&#39;
output_path = &#39;손흥민_remove.png&#39;  # PNG 포맷으로 변경해야 투명 배경 가능!

try:
    # 입력 이미지 업로드
    with open(input_path, &#39;rb&#39;) as inp_file:
        input_data = inp_file.read()

    # 배경 제거해서 바이너리 데이터가 나옴
    output_data = remove(input_data)

    # 바이너리 데이터 -&gt; 이미지 데이터 변환
    output_image = Image.open(io.BytesIO(output_data))

    # PNG 형식으로 파일 저장
    output_image.save(output_path, format=&quot;PNG&quot;)
    print(f&quot;Completed: {output_path}&quot;)

except Exception as e:
    print(f&quot;ERROR: {e}&quot;)
</code></pre><p><img src="https://velog.velcdn.com/images/bomi__unni/post/d910cea0-a75d-476c-ac27-b7579a627144/image.jpg" alt="">
<img src="https://velog.velcdn.com/images/bomi__unni/post/e563907c-00ae-4f4e-8bc4-2a8c3b81cc21/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useNavigate() : 페이지 이동 도와주는 훅(함수)]]></title>
            <link>https://velog.io/@bomi__unni/React-useNavigate-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EB%8F%84%EC%99%80%EC%A3%BC%EB%8A%94-%ED%9B%85%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@bomi__unni/React-useNavigate-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EB%8F%84%EC%99%80%EC%A3%BC%EB%8A%94-%ED%9B%85%ED%95%A8%EC%88%98</guid>
            <pubDate>Thu, 21 Nov 2024 05:02:26 GMT</pubDate>
            <description><![CDATA[<aside>
🎤 페이지 이동 도와주는 useNavigate()

</aside>

<p>→ Link 태그 말고 useNavigate() 함수 사용하자~</p>
<h3 id="1-appjs에-import-해오기">1. App.js에 import 해오기</h3>
<pre><code class="language-jsx">import { Routes, Route, Link, **useNavigate**, Outlet } from &#39;react-router-dom&#39;;</code></pre>
<h3 id="2-변수에-저장">2. 변수에 저장</h3>
<pre><code class="language-jsx">let navigate = **useNavigate();**</code></pre>
<h3 id="페이지-이동하는-link-태그를-사용하면-그냥-a태그로-오는거라서-안예쁨">페이지 이동하는 Link 태그를 사용하면 그냥 a태그로 오는거라서 안예쁨</h3>
<p>→ 그래서 react-bootstrap에서 가져온걸로 <strong>useNavigate</strong>를 줘보자</p>
<h2 id="페이지-이동-도와주는-usenavigate">페이지 이동 도와주는 useNavigate()</h2>
<pre><code class="language-jsx">#Link 태그 말고
&lt;Link to=&quot;/&quot;&gt;Home&lt;/Link&gt;
&lt;Link to=&quot;/detail&quot;&gt;Detail&lt;/Link&gt;

#useNavigate 사용
&lt;Nav.Link onClick={()=&gt;**{ navigate(&#39;/&#39;)}**}&gt;Home&lt;/Nav.Link&gt;
&lt;Nav.Link onClick={()=&gt;**{ navigate(&#39;/detail&#39;) }**}&gt;Detail&lt;/Nav.Link&gt;</code></pre>
<h2 id="이전페이지뒤로가기-다음페이지앞으로가기-이동">이전페이지(뒤로가기), 다음페이지(앞으로가기) 이동</h2>
<pre><code class="language-jsx">&lt;Nav.Link onClick={()=&gt;{ navigate(&#39;-1&#39;)}}&gt;뒤로 가기&lt;/Nav.Link&gt;
&lt;Nav.Link onClick={()=&gt;{ navigate(&#39;1&#39;)}}&gt;앞으로 가기&lt;/Nav.Link&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] 2-2. JOIN - 여러 테이블 조립하기]]></title>
            <link>https://velog.io/@bomi__unni/SQL-2-2.-JOIN-%EC%97%AC%EB%9F%AC-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%A1%B0%EB%A6%BD%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@bomi__unni/SQL-2-2.-JOIN-%EC%97%AC%EB%9F%AC-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%A1%B0%EB%A6%BD%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 21 Nov 2024 04:39:43 GMT</pubDate>
            <description><![CDATA[<h1 id="1-joininner-join---내부-조인"><strong>1. JOIN(INNER JOIN) - 내부 조인</strong></h1>
<p>→ 나눈 테이블을 다시 합침!</p>
<ul>
<li><code>양쪽 모두에 값이 있는 행(NOT NULL) 반환</code></li>
<li>&#39;<em>INNER</em> &#39;는 선택사항</li>
</ul>
<pre><code class="language-sql">SELECT * 
FROM Categories C
JOIN Products P 
  ON C.CategoryID = P.CategoryID; </code></pre>
<table>
<thead>
<tr>
<th>CategoryID</th>
<th>CategoryName</th>
<th>Description</th>
<th>ProductID</th>
<th>ProductName</th>
<th>SupplierID</th>
<th>CategoryID</th>
<th>Unit</th>
<th>Price</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>Beverages</td>
<td>Soft drinks, coffees, teas, beers, and ales</td>
<td>1</td>
<td>Chais</td>
<td>1</td>
<td>1</td>
<td>10 boxes x 20 bags</td>
<td>18.00</td>
</tr>
<tr>
<td>1</td>
<td>Beverages</td>
<td>Soft drinks, coffees, teas, beers, and ales</td>
<td>2</td>
<td>Chang</td>
<td>1</td>
<td>1</td>
<td>24 - 12 oz bottles</td>
<td>19.00</td>
</tr>
<tr>
<td>2</td>
<td>Condiments</td>
<td>Sweet and savory sauces, relishes, spreads, and seasonings</td>
<td>3</td>
<td>Aniseed Syrup</td>
<td>1</td>
<td>2</td>
<td>12 - 550 ml bottles</td>
<td>10.00</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT C.CategoryID, C.CategoryName, P.ProductName
FROM Categories C
JOIN Products P 
  ON C.CategoryID = P.CategoryID; 

-- ambiguous 주의!</code></pre>
<table>
<thead>
<tr>
<th>CategoryID</th>
<th>CategoryName</th>
<th>ProductName</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>Beverages</td>
<td>Chais</td>
</tr>
<tr>
<td>1</td>
<td>Beverages</td>
<td>Chang</td>
</tr>
<tr>
<td>2</td>
<td>Condiments</td>
<td>Aniseed Syrup</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT
  CONCAT(
    P.ProductName, &#39; by &#39;, S.SupplierName
  ) AS Product,
  S.Phone, P.Price
FROM Products P
JOIN Suppliers S
  ON P.SupplierID = S.SupplierID
WHERE Price &gt; 50
ORDER BY ProductName;</code></pre>
<table>
<thead>
<tr>
<th>Product</th>
<th>Phone</th>
<th>Price</th>
</tr>
</thead>
<tbody><tr>
<td>Carnarvon Tigers by Pavlova, Ltd.</td>
<td>(03) 444-2343</td>
<td>62.50</td>
</tr>
<tr>
<td>Côte de Blaye by Aux joyeux ecclésiastiques</td>
<td>(1) 03.83.00.68</td>
<td>263.50</td>
</tr>
</tbody></table>
<p>💡 여러 테이블을 <strong>JOIN</strong>할 수 있습니다</p>
<pre><code class="language-sql">SELECT 
  C.CategoryID, C.CategoryName, 
  P.ProductName, 
  O.OrderDate,
  D.Quantity
FROM Categories C

JOIN Products P 
  ON C.CategoryID = P.CategoryID

JOIN OrderDetails D
  ON P.ProductID = D.ProductID

JOIN Orders O
  ON O.OrderID = D.OrderID;</code></pre>
<table>
<thead>
<tr>
<th>CategoryID</th>
<th>CategoryName</th>
<th>ProductName</th>
<th>OrderDate</th>
<th>Quantity</th>
</tr>
</thead>
<tbody><tr>
<td>4</td>
<td>Dairy Products</td>
<td>Queso Cabrales</td>
<td>1996-07-04</td>
<td>12</td>
</tr>
<tr>
<td>5</td>
<td>Grains/Cereals</td>
<td>Singaporean Hokkien Fried Mee</td>
<td>1996-07-04</td>
<td>10</td>
</tr>
</tbody></table>
<p>💡 JOIN한 테이블 GROUP하기</p>
<pre><code class="language-sql">SELECT 
  C.CategoryName,
  MIN(O.OrderDate) AS FirstOrder,
  MAX(O.OrderDate) AS LastOrder,
  SUM(D.Quantity) AS TotalQuantity
FROM Categories C

JOIN Products P 
  ON C.CategoryID = P.CategoryID

JOIN OrderDetails D
  ON P.ProductID = D.ProductID

JOIN Orders O
  ON O.OrderID = D.OrderID

GROUP BY C.CategoryID;</code></pre>
<table>
<thead>
<tr>
<th>CategoryName</th>
<th>FirstOrder</th>
<th>LastOrder</th>
<th>TotalQuantity</th>
</tr>
</thead>
<tbody><tr>
<td>Beverages</td>
<td>1996-07-10</td>
<td>1998-05-06</td>
<td>9532</td>
</tr>
<tr>
<td>Condiments</td>
<td>1996-07-08</td>
<td>1998-05-06</td>
<td>5298</td>
</tr>
<tr>
<td>Confections</td>
<td>1996-07-09</td>
<td>1998-05-06</td>
<td>7906</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT 
  C.CategoryName, P.ProductName,
  MIN(O.OrderDate) AS FirstOrder,
  MAX(O.OrderDate) AS LastOrder,
  SUM(D.Quantity) AS TotalQuantity
FROM Categories C
JOIN Products P 
  ON C.CategoryID = P.CategoryID
JOIN OrderDetails D
  ON P.ProductID = D.ProductID
JOIN Orders O
  ON O.OrderID = D.OrderID
GROUP BY C.CategoryID, P.ProductID;</code></pre>
<table>
<thead>
<tr>
<th>CategoryName</th>
<th>ProductName</th>
<th>FirstOrder</th>
<th>LastOrder</th>
<th>TotalQuantity</th>
</tr>
</thead>
<tbody><tr>
<td>Beverages</td>
<td>Chais</td>
<td>1996-08-20</td>
<td>1998-05-05</td>
<td>828</td>
</tr>
<tr>
<td>Beverages</td>
<td>Chang</td>
<td>1996-07-12</td>
<td>1998-05-06</td>
<td>1057</td>
</tr>
<tr>
<td>Beverages</td>
<td>Guaraná Fantástica</td>
<td>1996-07-11</td>
<td>1998-05-05</td>
<td>1125</td>
</tr>
</tbody></table>
<h1 id="💡-self-join---같은-테이블끼리"><strong>💡 SELF JOIN - 같은 테이블끼리</strong></h1>
<pre><code class="language-sql">SELECT
  E1.EmployeeID, CONCAT_WS(&#39; &#39;, E1.FirstName, E1.LastName) AS Employee,
  E2.EmployeeID, CONCAT_WS(&#39; &#39;, E2.FirstName, E2.LastName) AS NextEmployee
FROM Employees E1 
JOIN Employees E2
ON E1.EmployeeID + 1 = E2.EmployeeID;

-- 1번의 전, 마지막 번호의 다음은? 알수없다. 왜냐하면 INNER JOIN은 NULL값은 가져오지 않으므로</code></pre>
<table>
<thead>
<tr>
<th>EmployeeID</th>
<th>Employee</th>
<th>EmployeeID</th>
<th>NextEmployee</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>Nancy Davolio</td>
<td>2</td>
<td>Andrew Fuller</td>
</tr>
<tr>
<td>2</td>
<td>Andrew Fuller</td>
<td>3</td>
<td>Janet Leverling</td>
</tr>
<tr>
<td>3</td>
<td>Janet Leverling</td>
<td>4</td>
<td>Margaret Peacock</td>
</tr>
</tbody></table>
<h1 id="2-leftright-outer-join---외부-조인"><strong>2. LEFT/RIGHT OUTER JOIN - 외부 조인</strong></h1>
<ul>
<li><code>반대쪽에 데이터가 있든 없든(NULL), 선택된 방향에 있으면 출력</code> - 행 수 결정</li>
<li>&#39;<em>OUTER</em> &#39;는 선택사항</li>
</ul>
<pre><code class="language-sql">SELECT
  E1.EmployeeID, CONCAT_WS(&#39; &#39;, E1.FirstName, E1.LastName) AS Employee,
  E2.EmployeeID, CONCAT_WS(&#39; &#39;, E2.FirstName, E2.LastName) AS NextEmployee
FROM Employees E1
LEFT JOIN Employees E2
ON E1.EmployeeID + 1 = E2.EmployeeID
ORDER BY E1.EmployeeID;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>7</th>
<th>Robert King</th>
<th>8</th>
<th>Laura Callahan</th>
</tr>
</thead>
<tbody><tr>
<td>8</td>
<td>Laura Callahan</td>
<td>9</td>
<td>Anne Dodsworth</td>
</tr>
<tr>
<td>9</td>
<td>Anne Dodsworth</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>→ <code>LEFT JOIN 을 하면 조인하는 곳이 NULL 이더라도 데이터를 가져옴</code></p>
<pre><code class="language-sql">SELECT
  E1.EmployeeID, CONCAT_WS(&#39; &#39;, E1.FirstName, E1.LastName) AS Employee,
  E2.EmployeeID, CONCAT_WS(&#39; &#39;, E2.FirstName, E2.LastName) AS NextEmployee
FROM Employees E1
RIGHT JOIN Employees E2
ON E1.EmployeeID + 1 = E2.EmployeeID
ORDER BY E1.EmployeeID;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>EmployeeID</th>
<th>Employee</th>
<th>EmployeeID</th>
<th>NextEmployee</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
<td>1</td>
<td>Nancy Davolio</td>
</tr>
<tr>
<td>1</td>
<td>Nancy Davolio</td>
<td>2</td>
<td>Andrew Fuller</td>
</tr>
<tr>
<td>2</td>
<td>Andrew Fuller</td>
<td>3</td>
<td>Janet Leverling</td>
</tr>
</tbody></table>
<p>→ RIGHT JOIN 을 하면 조인하는 곳이 NULL 이더라도 데이터를 가져옴</p>
<ul>
<li><code>LEFT JOIN</code>은 <code>E1</code>을 기준으로,</li>
<li><code>RIGHT JOIN</code>은 <code>E2</code>을 기준으로 조인을 수행하여, 조인 기준에 맞지 않는 경우 <code>NULL</code> 값을 반환하게 됩니다.</li>
</ul>
<pre><code class="language-sql">SELECT
  C.CustomerName, S.SupplierName,
  C.City, C.Country
FROM Customers C
LEFT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>Mère Paillarde</th>
<th>Ma Maison</th>
<th>Montréal</th>
<th>Canada</th>
</tr>
</thead>
<tbody><tr>
<td>Ana Trujillo Emparedados y helados</td>
<td></td>
<td>México D.F.</td>
<td>Mexico</td>
</tr>
<tr>
<td>Antonio Moreno Taquería</td>
<td></td>
<td>México D.F.</td>
<td>Mexico</td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT
  C.CustomerName, S.SupplierName,
  C.City, C.Country
FROM Customers C
RIGHT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>Tradição Hipermercados</th>
<th>Refrescos Americanas LTDA</th>
<th>São Paulo</th>
<th>Brazil</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td>Exotic Liquid</td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>New Orleans Cajun Delights</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT
  IFNULL(C.CustomerName, &#39;-- NO CUSTOMER --&#39;),
  IFNULL(S.SupplierName, &#39;-- NO SUPPLIER --&#39;),
  IFNULL(C.City, S.City),
  IFNULL(C.Country, S.Country)
FROM Customers C
LEFT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>Mère Paillarde</th>
<th>Ma Maison</th>
<th>Montréal</th>
<th>Canada</th>
</tr>
</thead>
<tbody><tr>
<td>Ana Trujillo Emparedados y helados</td>
<td>-- NO SUPPLIER --</td>
<td>México D.F.</td>
<td>Mexico</td>
</tr>
<tr>
<td>Antonio Moreno Taquería</td>
<td>-- NO SUPPLIER --</td>
<td>México D.F.</td>
<td></td>
</tr>
</tbody></table>
<pre><code class="language-sql">SELECT
  IFNULL(C.CustomerName, &#39;-- NO CUSTOMER --&#39;),
  IFNULL(S.SupplierName, &#39;-- NO SUPPLIER --&#39;),
  IFNULL(C.City, S.City),
  IFNULL(C.Country, S.Country)
FROM Customers C
RIGHT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country;

-- LEFT를 RIGHT로 바꿔서도 실행해 볼 것</code></pre>
<table>
<thead>
<tr>
<th>Tradição Hipermercados</th>
<th>Refrescos Americanas LTDA</th>
<th>São Paulo</th>
<th>Brazil</th>
</tr>
</thead>
<tbody><tr>
<td>-- NO CUSTOMER --</td>
<td>Exotic Liquid</td>
<td>Londona</td>
<td>UK</td>
</tr>
<tr>
<td>-- NO CUSTOMER --</td>
<td>New Orleans Cajun Delights</td>
<td>New Orleans</td>
<td>US</td>
</tr>
</tbody></table>
<h1 id="왼쪽-오른쪽-join해서-null값-포함-모두-출력하려면">왼쪽, 오른쪽 JOIN해서 NULL값 포함 모두 출력하려면</h1>
<ol>
<li>LEFT JOIN</li>
<li>RIGHT JOIN</li>
<li><code>UNION</code></li>
</ol>
<pre><code class="language-sql">SELECT
  IFNULL(C.CustomerName, &#39;-- NO CUSTOMER --&#39;) AS CustomerName,
  IFNULL(S.SupplierName, &#39;-- NO SUPPLIER --&#39;) AS SupplierName,
  IFNULL(C.City, S.City) AS City,
  IFNULL(C.Country, S.Country) AS Country
FROM Customers C
LEFT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country

UNION

SELECT
  IFNULL(C.CustomerName, &#39;-- NO CUSTOMER --&#39;) AS CustomerName,
  IFNULL(S.SupplierName, &#39;-- NO SUPPLIER --&#39;) AS SupplierName,
  IFNULL(C.City, S.City) AS City,
  IFNULL(C.Country, S.Country) AS Country
FROM Customers C
RIGHT JOIN Suppliers S
ON C.City = S.City AND C.Country = S.Country;
</code></pre>
<ul>
<li><code>UNION</code>은 <code>중복을 제거</code>하여 결과 집합의 고유한 행만 반환합니다.</li>
<li><code>UNION ALL</code>은 <code>모든 행을 반환</code>하여 <code>중복을 허용</code>합니다.</li>
</ul>
<h2 id="3-cross-join---교차-조인"><strong>3. CROSS JOIN - 교차 조인</strong></h2>
<ul>
<li>조건 없이 모든 조합 반환(A * B)</li>
<li>이것저것 모든 조합을 확인해보고 싶을 때 사용 !!</li>
</ul>
<pre><code class="language-sql">SELECT
  E1.LastName, E2.FirstName
FROM Employees E1
CROSS JOIN Employees E2
ORDER BY E1.EmployeeID;</code></pre>
<table>
<thead>
<tr>
<th>LastName</th>
<th>FirstName</th>
</tr>
</thead>
<tbody><tr>
<td>Davolio</td>
<td>Michael</td>
</tr>
<tr>
<td>Davolio</td>
<td>Janet</td>
</tr>
<tr>
<td>Davolio</td>
<td>Robert</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] public 폴더에서 이미지 사용: {process.env.PUBLIC_URL + '/파일명'}]]></title>
            <link>https://velog.io/@bomi__unni/React-public-%ED%8F%B4%EB%8D%94%EC%97%90%EC%84%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%9A%A9-process.env.PUBLICURL-%ED%8C%8C%EC%9D%BC%EB%AA%85</link>
            <guid>https://velog.io/@bomi__unni/React-public-%ED%8F%B4%EB%8D%94%EC%97%90%EC%84%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%9A%A9-process.env.PUBLICURL-%ED%8C%8C%EC%9D%BC%EB%AA%85</guid>
            <pubDate>Wed, 20 Nov 2024 06:16:08 GMT</pubDate>
            <description><![CDATA[<h3 id="q-html-에서-src폴더-이미지-사용할-땐-import부터-해와야하는데-만약-이미지가-100개가-넘어가면-어떻게-할까">Q. html 에서 src폴더 이미지 사용할 땐 import부터 해와야하는데, 만약 이미지가 100개가 넘어가면 어떻게 할까?</h3>
<p>→ <strong>public 폴더</strong>에도 <strong>이미지 보관</strong> 가능</p>
<p>→ 리액트는 사이트발행 전에 html, js, css 파일을 압축함(bundling)</p>
<p>→ public 폴더에 있던건 압축안됨(온전히 파일이름을 보존함)</p>
<p>→ 그래서 <strong>html에서 public폴더 이미지 사용</strong>할 땐 그냥</p>
<pre><code class="language-jsx"> **/이미지경로**</code></pre>
<pre><code class="language-jsx"> &lt;img src=&quot;/logo192.png&quot; width=&quot;80%&quot;/&gt;</code></pre>
<p>→ 현재 이거는 codingapple.com에 발행시 문제 없음</p>
<p>→ 근데 <a href="http://codingapple.com/%EC%96%B4%EC%A9%8C%EA%B5%AC/%EC%97%90">codingapple.com/어쩌구/에</a> 발행시 문제가 생김(서버가 달라지면 문제생김)</p>
<pre><code class="language-jsx"> &lt;img src=&quot;/어쩌구/logo192.png&quot; width=&quot;80%&quot;/&gt;</code></pre>
<p>→ 이렇게 해야할 수도 있음.. ㅠㅠ</p>
<p>→ 이렇게 맨날맨날 수정하기 귀찮으면 public 폴더 이미지 쓰는 권장 방식을 쓰자</p>
<pre><code class="language-jsx">&lt;img src=**{process.env.PUBLIC_URL + &#39;/logo192.png&#39;}** width=&quot;80%&quot;/&gt;</code></pre>
<p>→ {process~~} 는 내 사이트의 현재 경로를 의미함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬코딩테스트] 2단계 : 조건문 (1번~7번)
]]></title>
            <link>https://velog.io/@bomi__unni/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-2%EB%8B%A8%EA%B3%84-%EC%A1%B0%EA%B1%B4%EB%AC%B8-1%EB%B2%887%EB%B2%88</link>
            <guid>https://velog.io/@bomi__unni/%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-2%EB%8B%A8%EA%B3%84-%EC%A1%B0%EA%B1%B4%EB%AC%B8-1%EB%B2%887%EB%B2%88</guid>
            <pubDate>Wed, 20 Nov 2024 06:04:26 GMT</pubDate>
            <description><![CDATA[<h3 id="1단계-문제번호--1330-두-수-비교하기">1단계 (문제번호 : 1330) 두 수 비교하기</h3>
<blockquote>
<p>두 정수 A와 B가 주어졌을 때, A와 B를 비교하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a, b = map(int, input().split())
if a &gt; b :
    print(&quot;&gt;&quot;)
elif a &lt; b :
    print(&quot;&lt;&quot;)
else : 
    print(&quot;==&quot;)</code></pre><ul>
<li>map() : 한 줄로 문자열을 입력받아서 string을 int형의 숫자로 변환해주는 함수. 콤마(,)를 사용해 함수를 작성해줄 수 있다. 반드시 int를 써주는 것을 잊지 말자....</li>
</ul>
<h3 id="2단계-문제번호--9498-시험-성적">2단계 (문제번호 : 9498) 시험 성적</h3>
<blockquote>
<p>시험 점수를 입력받아 90 ~ 100점은 A, 80 ~ 89점은 B, 70 ~ 79점은 C, 60 ~ 69점은 D, 나머지 점수는 F를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>score = int(input())
if score &gt;= 90 : 
    print(&quot;A&quot;)
elif score &gt;= 80 :
    print(&quot;B&quot;)
elif score &gt;= 70 :
    print(&quot;C&quot;)
elif score &gt;= 60 :
    print(&quot;D&quot;)
else : 
    print(&quot;F&quot;)</code></pre><ul>
<li>숫자를 하나만 입력받기 때문에 map()을 쓰지 않고, int(input()) 만 써줌</li>
<li>input() : 문자열을 입력받는 함수. 단, input()으로 입력받은 값은 문자열이기 때문에 숫자로 변환하려면 int()함수를 써줘야함</li>
<li>int() : 문자열을 정수형의 숫자로 바꿔주는 함수</li>
<li>굳이 조건문을 길게 쓸 필요 없고, score &gt;= 90 이거만으로도 해결됨!! 굳이 굳이 논리연산자 안써도된다. 최대한 간결하게 쓰자. </li>
</ul>
<h3 id="3단계-문제번호--2735-윤년">3단계 (문제번호 : 2735) 윤년</h3>
<blockquote>
<p>연도가 주어졌을 때, 윤년이면 1, 아니면 0을 출력하는 프로그램을 작성하시오.
윤년은 연도가 4의 배수이면서, 100의 배수가 아닐 때 또는 400의 배수일 때이다.
예를 들어, 2012년은 4의 배수이면서 100의 배수가 아니라서 윤년이다. 1900년은 100의 배수이고 400의 배수는 아니기 때문에 윤년이 아니다. 하지만, 2000년은 400의 배수이기 때문에 윤년이다.</p>
</blockquote>
<pre><code>year = int(input())
if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0) :
    print(&quot;1&quot;)
else : 
    print(&quot;0&quot;)</code></pre><ul>
<li>year도 입력을 받고, int형의 정수가 되어야 하므로 int(input())을 사용했다.</li>
<li>if~else 조건문을 사용했는데, 이 때 중요한 것은 논리연산자!!</li>
<li>여러개의 논리연산자가 필요할 때는 소괄호를 써서 구분해주자 </li>
<li>python에서는 논리연산자가 and, or 이다!! </li>
<li>배수를 표현할 때는 그 숫자 == 0 을 사용하면 된다.</li>
</ul>
<h3 id="4단계-문제번호--14681-사분면-고르기">4단계 (문제번호 : 14681) 사분면 고르기</h3>
<blockquote>
<p>흔한 수학 문제 중 하나는 주어진 점이 어느 사분면에 속하는지 알아내는 것이다. 사분면은 아래 그림처럼 1부터 4까지 번호를 갖는다. &quot;Quadrant n&quot;은 &quot;제n사분면&quot;이라는 뜻이다.
예를 들어, 좌표가 (12, 5)인 점 A는 x좌표와 y좌표가 모두 양수이므로 제1사분면에 속한다. 점 B는 x좌표가 음수이고 y좌표가 양수이므로 제2사분면에 속한다.
점의 좌표를 입력받아 그 점이 어느 사분면에 속하는지 알아내는 프로그램을 작성하시오. 단, x좌표와 y좌표는 모두 양수나 음수라고 가정한다.</p>
</blockquote>
<pre><code>x = int(input())
y = int(input())
if x&gt;0 and y&gt;0 :
    print(&quot;1&quot;)
elif x&lt;0 and y&gt;0 :
    print(&quot;2&quot;)
elif x&lt;0 and y&lt;0 :
    print(&quot;3&quot;)
else : 
    print(&quot;4&quot;)</code></pre><ul>
<li>x와 y를 입력받는데, 한 줄에 하나씩 입력받아야 하므로 각각 int(input())함수를 사용해주었다.</li>
<li>논리연산자 and를 이용해 2가지의 조건을 한 번에 작성해주었다.</li>
</ul>
<h3 id="5단계-문제번호--2884-알람-시계">5단계 (문제번호 : 2884) 알람 시계</h3>
<blockquote>
<p>상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 바로 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다.
상근이는 모든 방법을 동원해보았지만, 조금만 더 자려는 마음은 그 어떤 것도 없앨 수가 없었다.
이런 상근이를 불쌍하게 보던, 창영이는 자신이 사용하는 방법을 추천해 주었다.
바로 &quot;45분 일찍 알람 설정하기&quot;이다.
이 방법은 단순하다. 원래 설정되어 있는 알람을 45분 앞서는 시간으로 바꾸는 것이다. 어차피 알람 소리를 들으면, 알람을 끄고 조금 더 잘 것이기 때문이다. 이 방법을 사용하면, 매일 아침 더 잤다는 기분을 느낄 수 있고, 학교도 지각하지 않게 된다.
현재 상근이가 설정한 알람 시각이 주어졌을 때, 창영이의 방법을 사용한다면, 이를 언제로 고쳐야 하는지 구하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>Hour, Min = map(int, input().split())
if Min &lt; 45 :
    if Hour == 0 :
        Hour = 23
        Min += 60
    else : 
        Hour -= 1
        Min += 60
print(Hour, Min-45)</code></pre><ul>
<li>우선 hour과 min을 숫자로 입력받기 위해 map(int, input().split())함수를 사용했다.</li>
<li>처음엔 쉽다고 생각했는데,, 이게 기준을 45분으로 잡아야 하는 거였다. 우선 45분보다크면 굳이 hour을 고칠 필요가 없는데, 만약 45분보다 작으면 hour도 건드려 줘야 한다. 45분보다 작을 때, 만약에 0시면 23시로 바꿔야하고, 그게 아니면 그냥 hour-1만 해주면 된다. 그리고 그 min에 60을 더해주면 된다. </li>
<li>생각보다 생각해야 할 점이 많아서 조금 헷갈렸다 ㅠㅠ</li>
</ul>
<h3 id="6단계-문제-번호--2525-오븐-시계">6단계 (문제 번호 : 2525) 오븐 시계</h3>
<blockquote>
<p>KOI 전자에서는 건강에 좋고 맛있는 훈제오리구이 요리를 간편하게 만드는 인공지능 오븐을 개발하려고 한다. 인공지능 오븐을 사용하는 방법은 적당한 양의 오리 훈제 재료를 인공지능 오븐에 넣으면 된다. 그러면 인공지능 오븐은 오븐구이가 끝나는 시간을 분 단위로 자동적으로 계산한다. 
또한, KOI 전자의 인공지능 오븐 앞면에는 사용자에게 훈제오리구이 요리가 끝나는 시각을 알려 주는 디지털 시계가 있다. 
훈제오리구이를 시작하는 시각과 오븐구이를 하는 데 필요한 시간이 분단위로 주어졌을 때, 오븐구이가 끝나는 시각을 계산하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>hour, min = map(int, input().split())
timer = int(input())
hour += timer // 60
min += timer % 60
if min &gt;= 60 :
    hour += 1
    min -= 60
if hour &gt;= 24 :
    hour -= 24
print(hour, min)</code></pre><ul>
<li>개인적으로 시계 문제는 내가 취약한 것 같다... 나 수학 좋아하는데... 싫어하나봐</li>
<li>우선 hour과 min은 한 줄에 한 칸씩 띄어서 출력이 되어야 하므로 map(int, input().split())함수로 입력을 받아주고, 그 다음줄에 timer은 따로 int(input())함수로 받아주었다. </li>
<li>우선, timer 값을 어떻게 사용해주어야 하느냐!!!가 중요하다. </li>
<li>timer는 hour에 대해서는 60의 몫을 사용하고, min에 대해서는 나머지를 사용한다. </li>
<li>왜냐하면 만약에 timer을 20분을 하면 60으로 나눠주면 0이므로 시간은 0시간이 추가되고, 20을 60으로 나눈 나머지는 20분이기 때문에 그냥 20분만 추가되는 것이다. 하지만, timer가 80분이면, 80을 60으로 나눈 몫은 1이고, 나머지는 20이다. 그러므로 1시간 20분이 계산이 되는 것이다. 그래서 timer을 사용해서 미리 hour과 min의 변수에 바뀐 값을 넣어준다!!! 이 때는 값이 넘쳐도 된다. 우리는 아래 if 조건문에서 값을 시간의 값으로 변형해 줄 것이기 때문에!</li>
<li>이를 이용해서 if 조건문을 사용할 것이다. 조건문은 min과 hour에 대해 각각 따로 사용한다. </li>
<li>min 조건문에서는 만약 min이 60보다 클 경우만 따져준다!! 60보다 작으면 상관이 없으니까. 만약 60보다 크면 hour의 값을 하나 증가해주고, min에서는 60을 빼준다. 만약 min에 들어있는 값이 위에서 더해가지고 80이 됐다면 hour에 1을 추가해주고, min이 80-60=20이 된다. </li>
<li>hour 조건문에서는 만약 hour이 24보다 클 경우만 따져준다. 이것도 24보다 작으면 시계의 시간이 맞기 때문에 고쳐줄 필요가 없다. 만약 24보다 크면 min을 조정할 필요는 없고, hour-24를 해서 다시 hour변수에 넣어주면 올바른 hour의 값이 나온다!</li>
<li>결국 출력은 위에서 쫘라르르르 계산을 해주었기 때문에 hour과 min만 출력해주면 된다. </li>
<li>시계문제...........생각할게 많아서 싫다...</li>
</ul>
<h3 id="7단계-문제-번호--2480-주사위-세개">7단계 (문제 번호 : 2480) 주사위 세개</h3>
<blockquote>
<p>1에서부터 6까지의 눈을 가진 3개의 주사위를 던져서 다음과 같은 규칙에 따라 상금을 받는 게임이 있다. 
같은 눈이 3개가 나오면 10,000원+(같은 눈)×1,000원의 상금을 받게 된다. 
같은 눈이 2개만 나오는 경우에는 1,000원+(같은 눈)×100원의 상금을 받게 된다. 
모두 다른 눈이 나오는 경우에는 (그 중 가장 큰 눈)×100원의 상금을 받게 된다.<br>예를 들어, 3개의 눈 3, 3, 6이 주어지면 상금은 1,000+3×100으로 계산되어 1,300원을 받게 된다. 또 3개의 눈이 2, 2, 2로 주어지면 10,000+2×1,000 으로 계산되어 12,000원을 받게 된다. 3개의 눈이 6, 2, 5로 주어지면 그중 가장 큰 값이 6이므로 6×100으로 계산되어 600원을 상금으로 받게 된다.
3개 주사위의 나온 눈이 주어질 때, 상금을 계산하는 프로그램을 작성 하시오.</p>
</blockquote>
<pre><code>a, b, c = map(int, input().split())
if a == b == c:
    print(10000 + (a * 1000))
elif a == b or b == c:
    print(1000 + (b * 100))
elif a == c:
    print(1000 + (a * 100))
else:
    print(max(a, b, c) * 100)</code></pre><ul>
<li>세 수를 동시에 숫자로 입력을 받으므로 map(int, input().split())함수를 사용해 입력값을 받아주고 문자열을 숫자로 바꾸어 주었다. </li>
<li>조건문은 총 4개를 사용했다. 1. a,b,c가 모두 같을 경우, 2. a와 b 혹은 b와 c가 같을 경우 3. a와 c가 같을 경우 그리고 4. 그 이외의 경우.</li>
<li>2개가 같은 경우를 구하는게 조금 헷갈렸다. b를 기준으로 생각했을 때, a와 b, b와 c가 같다면 그 기준인 b를 곱하는 값으로 사용했고 나머지 a와 c가 같을 경우만 따로 구했다. </li>
<li>max() : max()함수는 파이썬 내장함수로 주어진 수들 중에서 최댓값을 구해주는 함수이다. 그래서 다른 if문 써서 하지 않고 바로 max()함수를 이용해서 구했다. 참... 편하다!!</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[파이썬코딩테스트] 1단계 : 입출력과 사칙연산 (1번~13번)]]></title>
            <link>https://velog.io/@bomi__unni/%EB%B0%B1%EC%A4%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1%EB%8B%A8%EA%B3%84-%EC%9E%85%EC%B6%9C%EB%A0%A5%EA%B3%BC-%EC%82%AC%EC%B9%99%EC%97%B0%EC%82%B0-1%EB%B2%8813%EB%B2%88-zumcf46a</link>
            <guid>https://velog.io/@bomi__unni/%EB%B0%B1%EC%A4%80-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1%EB%8B%A8%EA%B3%84-%EC%9E%85%EC%B6%9C%EB%A0%A5%EA%B3%BC-%EC%82%AC%EC%B9%99%EC%97%B0%EC%82%B0-1%EB%B2%8813%EB%B2%88-zumcf46a</guid>
            <pubDate>Wed, 20 Nov 2024 06:01:45 GMT</pubDate>
            <description><![CDATA[<h3 id="1단계-문제번호--2557-hello-world"><strong>1단계 (문제번호 : 2557) Hello World</strong></h3>
<blockquote>
<p>Hello World!를 출력하시오.</p>
</blockquote>
<pre><code>print(&quot;Hello World!&quot;)</code></pre><h3 id="2단계-문제번호--10718-we-love-kriii"><strong>2단계 (문제번호 : 10718) We love kriii</strong></h3>
<blockquote>
<p>두 줄에 걸쳐 &quot;강한친구 대한육군&quot;을 한 줄에 한 번씩 출력한다.</p>
</blockquote>
<pre><code>for i in range(2):
    print(&quot;강한친구 대한육군&quot;)</code></pre><ul>
<li>print(&quot;강한친구 대한육군&quot;)을 연달아 2번 입력해서 출력을 할 수도 있지만, 최대한 간결한 코드를 작성하기 위해 반복되는 코드는 for문을 이용하였다!</li>
<li>for i in range(2) : for문을 이용해 아래의 코드를 2번 반복시켰다</li>
</ul>
<h3 id="3단계-문제번호--10171-고양이">3단계 (문제번호 : 10171) 고양이</h3>
<blockquote>
<p>고양이를 출력한다.</p>
</blockquote>
<pre><code>print(&#39;&#39;&#39;\\    /\\&#39;&#39;&#39;)
print(&#39;&#39;&#39; )  ( &#39;)&#39;&#39;&#39;)
print(&#39;&#39;&#39;(  /  )&#39;&#39;&#39;)
print(&#39;&#39;&#39; \\(__)|&#39;&#39;&#39;)</code></pre><ul>
<li><p>한 번에 출력하고 싶으면 </p>
<pre><code>print(&quot;&quot;&quot;\\    /\\
)  ( &#39;)
(  /  )
\\(__)|&quot;&quot;&quot;)</code></pre><p>&quot;&quot;&quot;을 써서 한 번에 출력하면 된다. 단, 이 때 처음 &quot;&quot;&quot;하고 한 줄을 띄고 입력하면 안되고 &quot;&quot;&quot;이후에 그 줄에 바로 작성을 해야 한다!</p>
</li>
<li><p>백슬래시(\)가 제대로 나오게 하기 위해서는 백슬래시를 두 번 작성해주어야 한다!! </p>
</li>
<li><p>줄바꿈은 이스케이프문자 중 \n을 써주면 된다</p>
</li>
</ul>
<h3 id="4단계-문제번호--25083번-새싹">4단계 (문제번호 : 25083번) 새싹</h3>
<blockquote>
<p>아래 예제와 같이 새싹을 출력하시오.</p>
</blockquote>
<pre><code>print(&#39;         ,r\&#39;\&quot;7&#39;)
print(&#39;r`-_   ,\&#39;  ,/&#39;)
print(&#39; \. \&quot;. L_r\&#39;&#39;)
print(&#39;   `~\/&#39;)
print(&#39;      |&#39;)
print(&#39;      |&#39;)</code></pre><ul>
<li>print문 안에서 작은따옴표(&#39;)와 큰따옴표(&quot;)를 제대로 출력하는 것이 포인트이다. </li>
<li>print문에서 문자열을 작성할 때는 반드시 따옴표를 사용해야하는데, 이 안에서 또 따옴표를 사용한다면 그 때는 <strong><em>따옴표 앞에 백슬래시(\)를 하나 넣어주어야 한다!!</em></strong></li>
</ul>
<h3 id="5단계-문제번호--1000-ab">5단계 (문제번호 : 1000) A+B</h3>
<blockquote>
<p>두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a, b = input().split()
print(int(a) + int(b))</code></pre><ul>
<li>input() : 사용자로부터 문자열을 입력받는 함수. input으로 입력받은 것은 &#39;문자열(string)&#39; 형식이므로 이를 숫자로 바꿔주려면 int()함수를 써줘야 한다!</li>
<li>int() : string을 int형의 숫자로 바꿔주는 함수</li>
<li>split() : input()함수에서 입력받은 문자열을 &#39;공백&#39;을 기준으로 나눠주는 함수</li>
</ul>
<pre><code>a, b = map(int, input().split())</code></pre><ul>
<li>또 다른 방법으로는 map()함수를 이용해 한 줄로 작성해주는 방법이 있다. </li>
<li>map() : 한 줄로 문자열을 입력받아서 string을 int형의 숫자로 변환해주는 함수. 콤마(,)를 사용해 함수를 작성해줄 수 있다. </li>
</ul>
<h3 id="6단계-문제번호--1001-a-b">6단계 (문제번호 : 1001) A-B</h3>
<blockquote>
<p>두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a, b = input().split()
print(int(a) - int(b))</code></pre><ul>
<li>5단계와 사용한 함수는 완전히 동일하고, print문에서 출력할 때 사칙연산 중 빼기를 사용하였다. </li>
</ul>
<h3 id="7단계-문제번호--10998-axb">7단계 (문제번호 : 10998) AxB</h3>
<blockquote>
<p>두 정수 A와 B를 입력받은 다음, A×B를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a, b = input().split()
print(int(a) * int(b))</code></pre><ul>
<li>5,6단계와 사용한 함수는 완전히 동일하고, print문에서 출력할 때 사칙연산 중 곱셈을 사용하였다. 이 때, 곱할 때는 x가 아니라 *을 사용해주어야 한다!</li>
</ul>
<h3 id="8단계-문제번호--1008-ab">8단계 (문제번호 : 1008) A/B</h3>
<blockquote>
<p>두 정수 A와 B를 입력받은 다음, A/B를 출력하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a, b = input().split()
print(int(a) / int(b))</code></pre><ul>
<li>5,6,7단계와 사용한 함수는 완전히 동일하고, print문에서 출력할 때 사칙연산 중 나눗셈을 사용하였다. 이 때, 나눌 때는 나누기 기호가 아니라 /을 사용해주어야 한다!</li>
</ul>
<h3 id="9단계-문제번호--10869-사칙연산">9단계 (문제번호 : 10869) 사칙연산</h3>
<blockquote>
<p>두 자연수 A와 B가 주어진다. 이때, A+B, A-B, A*B, A/B(몫), A%B(나머지)를 출력하는 프로그램을 작성하시오. </p>
</blockquote>
<pre><code>a,b = input().split()
print(int(a) + int(b))
print(int(a) - int(b))
print(int(a) * int(b))
print(int(a) // int(b))
print(int(a) % int(b))</code></pre><ul>
<li>덧셈 : +</li>
<li>뺄셈 : -</li>
<li>곱셈 : *</li>
<li>나눗셈(값) : /</li>
<li>나눗셈(몫) : //</li>
<li>나눗셈(나머지) : %</li>
</ul>
<p>몫을 구하라는 것을 그냥 나눗셈의 값으로 생각해버려서 틀려버렸다.. 은근 이거 헷갈린다ㅠㅠ</p>
<h3 id="10단계-문제번호--10926-">10단계 (문제번호 : 10926) ??!</h3>
<blockquote>
<p>준하는 사이트에 회원가입을 하다가 joonas라는 아이디가 이미 존재하는 것을 보고 놀랐다. 준하는 놀람을 ??!로 표현한다. 준하가 가입하려고 하는 사이트에 이미 존재하는 아이디가 주어졌을 때, 놀람을 표현하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>print(input()+&quot;??!&quot;)</code></pre><ul>
<li>처음에 보고 잘 이해가 안됐는데, python은 문자열을 더할 수 있다!!! input을 넣고 + 해서 문자열을 넣으면 빠밤 된다ㅠㅠ 파이썬 천재야</li>
</ul>
<h3 id="11단계-문제번호--18108-1998년생인-내가-태국에서는-2541년생">11단계 (문제번호 : 18108) 1998년생인 내가 태국에서는 2541년생?!</h3>
<blockquote>
<p>ICPC Bangkok Regional에 참가하기 위해 수완나품 국제공항에 막 도착한 팀 레드시프트 일행은 눈을 믿을 수 없었다. 공항의 대형 스크린에 올해가 2562년이라고 적혀 있던 것이었다. 불교 국가인 태국은 불멸기원(佛滅紀元), 즉 석가모니가 열반한 해를 기준으로 연도를 세는 불기를 사용한다. 반면, 우리나라는 서기 연도를 사용하고 있다. 불기 연도가 주어질 때 이를 서기 연도로 바꿔 주는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>print(int(input()) - 543)</code></pre><ul>
<li>이것도 단순 입출력 문제이다!! 다만 input()에서 입력된 값은 문자열이기 때문에 숫자를 얻으려면 int()함수를 통해 숫자로 변환해주어야 한다. 그래서 int(input())을 하면 그 안에 값을 넣었을 때 문자열 -&gt; int형 숫자로 변환이 된다!</li>
</ul>
<h3 id="12단계-문제번호--10430-나머지">12단계 (문제번호 : 10430) 나머지</h3>
<blockquote>
<p>(A+B)%C는 ((A%C) + (B%C))%C 와 같을까?
(A×B)%C는 ((A%C) × (B%C))%C 와 같을까?
세 수 A, B, C가 주어졌을 때, 위의 네 가지 값을 구하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a,b,c = map(int, input().split())
print((a+b)%c)
print(((a%c)+(b%c))%c)
print((a*b)%c)
print(((a%c)*(b%c))%c)</code></pre><ul>
<li>이번에는 사칙연산이 너무 복잡해서 print문에 하나하나씩 int()를 하지 않고, 아예 처음부터 변수를 map()함수를 이용해 int형으로 만들어 주었다. </li>
<li>map() : 한 줄로 문자열을 입력받아서 string을 int형의 숫자로 변환해주는 함수. 콤마(,)를 사용해 함수를 작성해줄 수 있다. </li>
</ul>
<h3 id="13단계-문제번호--2588-곱셈"><strong>13단계 (문제번호 : 2588) 곱셈</strong></h3>
<blockquote>
<p>(세 자리 수) × (세 자리 수)는 다음과 같은 과정을 통하여 이루어진다.
(1)과 (2)위치에 들어갈 세 자리 자연수가 주어질 때 (3), (4), (5), (6)위치에 들어갈 값을 구하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code>a = int(input())
b = input()
axb2 = a * int(b[2])
axb1 = a * int(b[1])
axb0 = a * int(b[0])
axb = a*int(b)
print(axb2, axb1, axb0, axb, sep=&quot;\n&quot;)</code></pre><ul>
<li>13단계는 조금 어려웠다... 우선 a와 b를 입력을 받는데 이 때, 세 자리수 곱셈 하는 경우를 생각해보자. 첫 번째 입력되는 숫자 전체와 두 번째 입력되는 숫자의 일의 자리, 십의 자리, 백의 자리의 순서로 곱해진다. 그러기 때문에 첫 번째 입력되는 숫자인 a는 int() 함수를 이용해 정수로 변환해 주었지만, 두 번째 입력받은 숫자인 b는 int()로 변환해주지 않고, 문자열로 남겨두었다. 그 이유는 문자열의 리스트를 사용하기 위해!!</li>
<li>문자열의 리스트를 사용해서 일의자리는 int(b[2]), 십의자리는 int(b[1]), 백의자리는 int(b[0])으로 변환해서 a와 곱한 다음 각각의 변수에 담아주었다. 그리고 마지막 (6)번에는 a와 b를 곱한 값을 출력해주어야 하기 때문에 a*int(b)를 해주었다. </li>
<li>sep 파라미터 : print()함수에서 출력할 값이 여러개일경우 각각의 값 사이사이에 삽입할 문자를 지정해주는 파라미터이다. </li>
<li>sep=&quot;\n&quot;은 각각 (3), (4), (5), (6)에 들어갈 값을 하나씩 적어주어야 하므로 이를 이용해 각각의 값들이 줄 넘김을 할 수 있도록 해주었다.</li>
</ul>
<p>오늘부터 백준 알고리즘 천천히 공부해보자..
생각보다 나는 아는게 많이 없던 것이었다.....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[배열 문제2] ]]></title>
            <link>https://velog.io/@bomi__unni/%EB%B0%B0%EC%97%B4-%EB%AC%B8%EC%A0%9C2</link>
            <guid>https://velog.io/@bomi__unni/%EB%B0%B0%EC%97%B4-%EB%AC%B8%EC%A0%9C2</guid>
            <pubDate>Wed, 31 Jul 2024 01:37:43 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<ul>
<li>주어진 배열에서 두 숫자의 합이 100이 되는 경우가 있는지 확인</li>
</ul>
<h3 id="방법-1">방법 1</h3>
<ul>
<li>완전 탐색</li>
<li>0부터 N까지 다 탐색해서 합이 100인게 있는지 다 검사를 해야한다. </li>
<li>O(N^2)<pre><code>int func2(int arr[], int N) {
  for(int i=0;i&lt;N;i++) {
      for(int j=i+1;j&lt;N;j++) {
          if(arr[i] + arr[j] == 100) {
              return 1;
          }
      }
  } return 0;
}
</code></pre></li>
</ul>
<pre><code>
### 방법 2
- 미리 결과값을 저장할 0으로 초기화된 배열을 만든다.
- 함수 func2
    - occur 배열을 사용하여 숫자가 배열에 등장했는지 여부를 기록합니다.
    - 배열을 순회하며 각 숫자 arr[i]에 대해 100 - arr[i]가 이미 등장했는지 확인합니다. 
    - 이미 등장했다면 두 숫자의 합이 100이므로 1을 반환합니다.
    - 현재 숫자를 occur 배열에 기록합니다.
- O(N)
</code></pre><p>#include <iostream>
#include <algorithm></p>
<p>using namespace std;</p>
<p>int func2(int arr[], int N) {
    int occur[101] = {}; // 0으로 초기화된 101 크기의 배열</p>
<pre><code>for (int i = 0; i &lt; N; i++) {
    if (occur[100 - arr[i]] == 1) { // arr[i]와 합해서 100이 되는 수가 존재하는지 확인
        return 1;
    }
    occur[arr[i]] = 1; // 현재 수를 기록
}
return 0; // 합해서 100이 되는 두 수가 없으면 0 반환</code></pre><p>}</p>
<p>int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);</p>
<pre><code>int N;
cout &lt;&lt; &quot;Enter the number of elements in the array: &quot;;
cin &gt;&gt; N;

int arr[N];
cout &lt;&lt; &quot;Enter the elements of the array: &quot;;
for (int i = 0; i &lt; N; i++) {
    cin &gt;&gt; arr[i];
}

int result = func2(arr, N);
if (result == 1) {
    cout &lt;&lt; &quot;There are two numbers in the array that add up to 100.&quot; &lt;&lt; endl;
} else {
    cout &lt;&lt; &quot;There are no two numbers in the array that add up to 100.&quot; &lt;&lt; endl;
}

return 0;</code></pre><p>}</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[10808] 알파벳 개수]]></title>
            <link>https://velog.io/@bomi__unni/10808-%EC%95%8C%ED%8C%8C%EB%B2%B3-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@bomi__unni/10808-%EC%95%8C%ED%8C%8C%EB%B2%B3-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Wed, 31 Jul 2024 01:24:36 GMT</pubDate>
            <description><![CDATA[<h4 id="문제">문제</h4>
<ul>
<li><a href="https://www.acmicpc.net/problem/10808">https://www.acmicpc.net/problem/10808</a><h4 id="해결방법">해결방법</h4>
</li>
<li>입력 문자열의 각 문자(a부터 z까지) 빈도를 계산하는 프로그램이다. </li>
<li>이를 통해 문자열 내에서 각 문자가 몇 번 등장하는지 출력해야한다. </li>
</ul>
<h3 id="방법-1">방법 1.</h3>
<ul>
<li>문자열을 a부터 z까지 총 26번을 모두 돌아야한다</li>
<li>코드가 맞긴 하지만, 쓸데없이 많이 돈다</li>
</ul>
<pre><code class="language-c++">#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;

using namespace std;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    string s;
    cin &gt;&gt; s;

    // 이거는 문자열을 a부터 z까지 총 26번을 모두 돌아야 한다
    for(char a=&#39;a&#39; ; a&lt;=&#39;z&#39;;a++){
        int cnt = 0;
        for (auto c: s){
            if(a==c) {
                cnt++;
            }
        }
        cout &lt;&lt; cnt &lt;&lt; &#39; &#39;;
    }

}</code></pre>
<h3 id="방법2">방법2.</h3>
<ul>
<li>미리 a부터 z까지의 개수를 셀 빈 배열을 하나 만든다 : int freq[26];</li>
<li>이 때, 배열을 전역변수로 선언하면 자동으로 0으로 초기화가 되지만,</li>
<li>만약 지역변수로 선언하면 int freq[26]={}, fill(freq,freq+26,0) 과 같은 처리를 해야함</li>
<li>auto : 변수의 타입을 자동으로 추론, 여기서는 자동으로 char형으로 추론이 된다. </li>
</ul>
<pre><code class="language-c++">#include &lt;iostream&gt;

using namespace std;

// a부터 z까지의 개수를 셀 빈 배열

int freq[26];

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    string s;
    cin &gt;&gt; s;

    // 입력받은 문자열 s의 각 문자를 순회하며, 각 문자의 빈도를 freq 배열에 저장
    // c - &#39;a&#39;는 문자를 &#39;a&#39;부터 0, 1, 2, ..., 25로 변환하는 역할을 합니다. 예를 들어, &#39;a&#39;는 0, &#39;b&#39;는 1, ..., &#39;z&#39;는 25가 됩니다.
    for(auto c: s) { // auto : 변수의 타입을 자동으로 추론
        freq[c -&#39;a&#39;]++; // freq[c - &#39;a&#39;]++를 통해 해당 문자의 빈도를 1씩 증가
    }
    // freq 배열의 모든 원소를 순회하며, 각 알파벳의 빈도를 출력
    for(int i=0;i&lt;26;i++){
        cout &lt;&lt; freq[i] &lt;&lt; &#39; &#39;; // 각 알파벳 빈도를 공백으로 구분하여 출력
    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] 투 포인터 Two Pointer]]></title>
            <link>https://velog.io/@bomi__unni/C-%ED%88%AC-%ED%8F%AC%EC%9D%B8%ED%84%B0-Two-Pointer</link>
            <guid>https://velog.io/@bomi__unni/C-%ED%88%AC-%ED%8F%AC%EC%9D%B8%ED%84%B0-Two-Pointer</guid>
            <pubDate>Tue, 30 Jul 2024 05:24:11 GMT</pubDate>
            <description><![CDATA[<h1 id="투-포인터two-pointer">투 포인터(Two Pointer)</h1>
<p>배열에서 원래 이중 for문으로 O(N^2)에 처리되는 작업을 2개 포인터의 움직임으로 O(N)에 해결하는 알고리즘</p>
<ul>
<li>cursor</li>
</ul>
<pre><code>#include &lt;iostream&gt;
#include &lt;algorithm&gt;

using namespace std;

int n; // 정수의 개수 (배열의 크기)
int s; // 목표 합 or 두 수의 차이
int total; // 현재 부분 배열의 합
int a[100004]; // 정수를 저장할 배열, 수열
int minvalue = 0x7fffffff; // 합이 s 이상인 부분 배열의 최소 길이 (초기값은 최대값으로 설정), 두 수의 차이 중 최소값

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    // 두 수 입력
    cin &gt;&gt; n &gt;&gt; s;

    // 배열 및 수열에 저장
    for (int i=0;i&lt;n;i++) {
        cin &gt;&gt; a[i];
    }    

    // total배열(저장할 새로운 배열) 초기화
    total = a[0]; 

    // binary_search() 사용할 때는 sort()함수로 먼저 배열을 정렬
    sort(a, a+n);

    // 슬라이딩 윈도우(투 포인터 탐색)
    int end = 0;
    // 합이 s 이상이 되는 순간마다 최소 길이를 업데이트하고, start 포인터를 이동시켜 다음 부분 배열을 검사
    for(int start = 0; start&lt;n;start++) {
        while(end &lt; n &amp;&amp; total &lt; s) {
            end++;

            // end가 배열 끝까지 돌 때까지 total에 현재 끝값을 게속 더함
            // if(end != n) {
                total += a[end];
            }
        }
            // end가 범위를 벗어나면 종룔
            if(end == n) {
                break;
            }
            minvalue = min(minvalue, end-start+1);
            // total -= a[start];
        }
        // if(minvalue == 0x7fffffff) {
            minvalue = 0;
        }
            cout &lt;&lt; minvalue;
    }
</code></pre><h1 id="슬라이딩-윈도우-투포인터-탐색-알고리즘">슬라이딩 윈도우 (투포인터 탐색) 알고리즘</h1>
<pre><code>int end = 0;
for(int start=0;start&lt;n;start++) {
    while(end &lt; n &amp;&amp; 조건) {
        end++;
       }

    if (end == n) {
        break;
       }
    minvalue = min(minvalue, 주어진 수식);

    }
    cout &lt;&lt; minvalue;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[삼성코테] 2003 : 부분합2]]></title>
            <link>https://velog.io/@bomi__unni/%EC%82%BC%EC%84%B1%EC%BD%94%ED%85%8C-2003-%EB%B6%80%EB%B6%84%ED%95%A92</link>
            <guid>https://velog.io/@bomi__unni/%EC%82%BC%EC%84%B1%EC%BD%94%ED%85%8C-2003-%EB%B6%80%EB%B6%84%ED%95%A92</guid>
            <pubDate>Tue, 30 Jul 2024 02:46:45 GMT</pubDate>
            <description><![CDATA[<h1 id="문제">문제</h1>
<p>N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i] + A[i+1] + … + A[j-1] + A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.</p>
<h1 id="입력">입력</h1>
<p>첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.</p>
<h1 id="출력">출력</h1>
<p>첫째 줄에 경우의 수를 출력한다.</p>
<h3 id="예제-입력-1">예제 입력 1</h3>
<p>4 2
1 1 1 1</p>
<h3 id="예제-출력-1">예제 출력 1</h3>
<p>3</p>
<h3 id="예제-입력-2">예제 입력 2</h3>
<p>10 5
1 2 3 4 2 5 3 1 1 2</p>
<h3 id="예제-출력-2">예제 출력 2</h3>
<p>3</p>
<pre><code>#include &lt;iostream&gt;

using namespace std;

int N; // 수열의 개수
int M; // 수열의 합

// 투 포인터(슬라이딩 윈도우) 알고리

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin &gt;&gt; N &gt;&gt; M;
    int A[N+1]; // 수열을 저장하는 배열

    // 수열 입력
    for (int i=0;i&lt;N;i++) {
        cin &gt;&gt; A[i];
    }

    int start=0; //슬라이딩 윈도우의 시작 지점
    int end=0; //슬라이딩 윈도우의 끝 지점
    int result = A[0]; // 현재 슬라이딩 윈도우의 합
    int count = 0; //합이 M이 되는 부분 수열의 개수

    // 슬라이딩 윈도우 알고리즘
    while(start &lt;= end &amp;&amp; end &lt; N) { 
        if(result &lt; M) { // 합이 M보다 작을 때
            result += A[++end]; // 윈도우의 끝을 오른쪽으로 이동(++end)하여 result에 새로운 요소를 더함
        } else if(result == M) {  // 합이 M과 같을 때 
            count++; // 부분 수열의 개수를 증가
            result += A[++end]; // 윈도우의 끝을 오른쪽으로 이동하여 result에 새로운 요소를 더함
        } else if(result &gt; M) { // 합이 M보다 클 때 result에서 시작 요소를 뺍니다. 
            result -= A[start++]; // 윈도우의 시작을 오른쪽으로 이동(start++)하여

            if(start&gt;end) { // 만약 start가 end를 넘어가면  
                end=start; // end를 start에 맞추고,
                result=A[start]; // result를 새로운 시작 값으로 설정
            }
        }
    }
    cout &lt;&lt; count; // 합이 M이 되는 부분 수열의 개수를 출력

}
</code></pre><p>출처 : <a href="https://tooo1.tistory.com/143">https://tooo1.tistory.com/143</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] 이진탐색 Binary Search]]></title>
            <link>https://velog.io/@bomi__unni/C-%EC%9D%B4%EC%A7%84%ED%83%90%EC%83%89-Binary-Search</link>
            <guid>https://velog.io/@bomi__unni/C-%EC%9D%B4%EC%A7%84%ED%83%90%EC%83%89-Binary-Search</guid>
            <pubDate>Tue, 30 Jul 2024 02:45:17 GMT</pubDate>
            <description><![CDATA[<pre><code>start=시작값
end=끝값
mid = (start+end)/2</code></pre><p>만약 target값이 A[start] 보다 크면 end = mid-1, 
tartget값이 A[end] 보다 작으면 start = mid + 1</p>
<pre><code>A[mid] &gt; target 이면 end=mid-1
A[mid] &lt; target 이면 start=mid+1
A[mid] == target 이면 답 찾음!</code></pre><p>근데, c++에는 stl 내장함수로 <code>binary_search(start, end, target)</code> 함수가 있기 때문에 매우매우 편리하게 사용할 수 있다. </p>
<ul>
<li>첫 번째, 두 번째 인자는 내가 어디에서 찾고 싶은지 (배열이든 벡터든) 그 자료구조의 <code>시작 주소(start)와 끝나는 주소(end)</code>를 넣어주면 된다.</li>
<li>세 번째 인자는 그 곳에 있는지 없는지 궁금한 <code>내가 찾고 싶은 대상(target)</code>이다. 반환 타입은 <code>bool</code> 타입으로, <code>있으면 1(true), 없으면 0(false)를 반환</code>한다.</li>
</ul>
<p>다만, 이진탐색이라는 것은 <code>데이터가 정렬되어 있다는 전제하에 가능</code>하다.
이 때, <code>정렬</code>을 하려면 <code>sort() 함수</code>를 이용하면 된다.</p>
<p>참고 : <a href="https://breakcoding.tistory.com/188">https://breakcoding.tistory.com/188</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] 피보나치 수열]]></title>
            <link>https://velog.io/@bomi__unni/C-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%97%B4</link>
            <guid>https://velog.io/@bomi__unni/C-%ED%94%BC%EB%B3%B4%EB%82%98%EC%B9%98-%EC%88%98%EC%97%B4</guid>
            <pubDate>Tue, 30 Jul 2024 00:58:27 GMT</pubDate>
            <description><![CDATA[<h1 id="재귀recursive">재귀(recursive)</h1>
<p>-&gt; 너무 느리고, 비효율적으로 계산을 해서 시간초과가 남</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cstdio&gt;
#include &lt;algorithm&gt;

using namespace std;

// 너무 느린 코드!!!

int fibo (int num) {
    int result;

    if (num &lt; 2) {
        return num;
    } else {
        return (fibo(num-1) + fibo(num-2));
    }
    return result;
}

int main() {
    int n;
    scanf(&quot;%d&quot;, &amp;n);
    printf(&quot;%d&quot;, fibo(n));
}
</code></pre><h1 id="memoization">memoization</h1>
<pre><code>#include &lt;iostream&gt;
#include &lt;vector&gt;

using namespace std;

vector&lt;long long&gt; F;

long long fibo (int num) {

    F.push_back(0);
    F.push_back(1);

    if (num &lt; 2) {
        return num;
    } else {
        for (int i=2;i&lt;=num;i++) {
            F.push_back(F[i-1]+F[i-2]);
            //memoization : F[i-1],F[i-2]를 다시 계산하지 않고 저장된 값을 꺼내서 씀

        }
    }
    return F[num];
}

int main() {
    int n;
    cin &gt;&gt; n;
    cout &lt;&lt; fibo(n) &lt;&lt; endl;
}


</code></pre><ul>
<li>왜 오류가 났냐면 최대 input 값이 90인데, 결과값은 2880067194370816120로 엄청 크다</li>
<li>근데 내가 결과값이 나오는 함수 fibo를 int형으로 하면 그 수를 못 담기 때문에 long long fibo(int num)으로 바꿔주어야 한다. </li>
<li>물론 vector도 <code>vector&lt;long long&gt; F;</code>을 써야한다!</li>
<li>수가 너무 컸을 때 시간초과가 나거나 틀렸다면 &#39;long long&#39;을 쓰기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] 코딩테스트에서 cin, cout 에러났을 때 써야하는 코드]]></title>
            <link>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-cin-cout-%EC%97%90%EB%9F%AC%EB%82%AC%EC%9D%84-%EB%95%8C-%EC%8D%A8%EC%95%BC%ED%95%98%EB%8A%94-%EC%BD%94%EB%93%9C</link>
            <guid>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%97%90%EC%84%9C-cin-cout-%EC%97%90%EB%9F%AC%EB%82%AC%EC%9D%84-%EB%95%8C-%EC%8D%A8%EC%95%BC%ED%95%98%EB%8A%94-%EC%BD%94%EB%93%9C</guid>
            <pubDate>Tue, 30 Jul 2024 00:16:00 GMT</pubDate>
            <description><![CDATA[<pre><code>ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
</code></pre><ul>
<li>cin을 cout으로 부터 풀어준다.(untie)</li>
<li>stream을 tie 하면 다른 stream에서 입출력 요청 오기 전에 stream을 먼저 flush 시킨다.</li>
</ul>
<p>출처 : <a href="https://hegosumluxmundij.tistory.com/54">https://hegosumluxmundij.tistory.com/54</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Hooks] useRef]]></title>
            <link>https://velog.io/@bomi__unni/React-Hooks-useRef</link>
            <guid>https://velog.io/@bomi__unni/React-Hooks-useRef</guid>
            <pubDate>Mon, 29 Jul 2024 06:37:33 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-jsx">const ref = useRef(value);</code></pre>
<ul>
<li>ref object를 반환해준다</li>
<li><code>값은 {current:value}</code></li>
<li>ref object는 수정이 가능하다</li>
<li>반환된 ref는 컴포넌트의 전 생애주기를 통해 유지가 된다</li>
<li>컴포넌트가 계속 렌더링되어도 unmount되기 전까지는 값을 유지한다는 뜻</li>
</ul>
<blockquote>
<p>즉, useRef는 변화는 감지해야 하지만 렌더링될때마다 변경이 되지는 않아야 할 때 사용한다</p>
</blockquote>
<pre><code class="language-jsx">const countRef = useRef(0);

&lt;p&gt;Ref : {countRef.current}&lt;/p&gt;
</code></pre>
<p>useRef 변수인 countRef의 값을 가져오려면 <code>{countRef.current}</code></p>
<h2 id="언제-사용해">언제 사용해?</h2>
<h2 id="1-변수관리">1. 변수관리</h2>
<ul>
<li><p>state변화 → 렌더링 → 컴포넌트 내부 변수들 초기화</p>
</li>
<li><p>그래서 원하지 않는 렌더링때문에 곤란해질때가 있다.</p>
</li>
<li><p>ref의 변화 → 렌더링X → 변수들의 값이 유지됨</p>
</li>
<li><p>state변화 → 렌더링 → 그래도 ref의 값은 유지됨</p>
</li>
</ul>
<pre><code class="language-jsx">  const increaseCountState = () =&gt; {
    setCount(count + 1);
  };
  const increaseCountRef = () =&gt; {
    countRef.current++;
  };</code></pre>
<ul>
<li>이 코드를 보면 state올려 버튼을 누르면 화면이 계속 렌더링되기 때문에 숫자가 올라가지만 ref올려 버튼을 누르면 화면이 렌더링되지 않기 때문에 숫자가 올라가지 않는 것처럼 보인다.</li>
<li>근데 실제로 값이 올라가지 않는것일까?</li>
<li>그건 아니다! 사실은 ref를 사용해도 값이 증가하는데 화면이 렌더링되지 않는 것이기 때문에 값이 올라가지 않는 것처럼 보일뿐이다.</li>
<li>이 때, ref버튼을 누르다가 state버튼을 누르면 화면이 렌더링되면서 그제서야 개수가 증가하는 것을 볼 수 있다.</li>
</ul>
<h2 id="ref의-장점은">Ref의 장점은?</h2>
<p>값이 엄청 자주 바뀌는 값을 state에 넣어놓게 되면 계속 렌더링되므로 성능에 매우 안좋아진다. </p>
<p>근데 이 때 ref를 사용하면 렌더링되지 않으므로 성능이 더 좋아진다!!</p>
<h2 id="ref와-변수var의-다른점은">Ref와 변수var의 다른점은?</h2>
<p>변수는 렌더링이 되면 계속해서 0으로 초기화가 되지만 ref는 렌더링이 되어도 초기화가 되지 않는다!</p>
<h2 id="2-dom요소에-접근">2. DOM요소에 접근</h2>
<pre><code class="language-jsx">ref={ref변수명}</code></pre>
<ul>
<li>ref요소를 사용해 focus()를 줄 때</li>
<li><code>손쉽게 input요소에 접근</code>할 수 있음</li>
<li>document.querySelector() 같음</li>
<li>ref는 아무리 수정해도 렌더링은 되지 않기 때문에 화면이 업데이트 되지 않는다.</li>
</ul>
<pre><code class="language-jsx">const ref = useRef(value);

&lt;input ref={ref}/&gt;</code></pre>
<p>⇒ 이렇게 하면 바로 ref 변수에 접근할 수 있다!</p>
<h3 id="새로고침-누르면-바로-로그인-창에-focus되도록-하기">새로고침 누르면 바로 로그인 창에 focus되도록 하기</h3>
<p>그저 <code>ref={ref변수명}</code> 을 쓰면 된다</p>
<pre><code class="language-jsx">  const inputRef = useRef();
  useEffect(() =&gt; {
    inputRef.current.focus();
  }, []);

  const login = () =&gt; {
    alert(`환영합니다. ${inputRef.current.value}`);
    inputRef.current.focus();
  };</code></pre>
<pre><code class="language-jsx">&lt;input ref={inputRef} type=&quot;text&quot; placeholder=&quot;username&quot; /&gt;
&lt;button onClick={login}&gt;login&lt;/button&gt;</code></pre>
<h3 id="전체코드">전체코드</h3>
<pre><code class="language-jsx">import { useState, useRef, useEffect } from &quot;react&quot;;

import &quot;./App.css&quot;;

function App() {
  const [count, setCount] = useState(1);
  const renderCount = useRef(1);

  useEffect(() =&gt; {
    renderCount.current++;
    console.log(&quot;렌더링수:&quot;, renderCount.current);
  });

  const countRef = useRef(0);
  let countVar = 0;
  const [renderer, setRenderer] = useState(0);
  const countRef2 = useRef(0);
  console.log(countRef);
  const increaseCountState = () =&gt; {
    setCount(count + 1);
  };
  const increaseCountRef = () =&gt; {
    countRef.current++;
    console.log(&quot;ref:&quot;, countRef.current);
  };
  const increaseRef = () =&gt; {
    countRef2.current++;
    console.log(`ref: ${countRef2.current}`);
  };

  const increaseVar = () =&gt; {
    countVar++;
    console.log(`var : ${countVar}`);
  };

  const doRender = () =&gt; {
    setRenderer(renderer + 1);
  };
  const printResults = () =&gt; {
    console.log(`ref: ${countRef.current}, var: ${countVar}`);
  };

  const inputRef = useRef();
  useEffect(() =&gt; {
    inputRef.current.focus();
  }, []);

  const login = () =&gt; {
    alert(`환영합니다. ${inputRef.current.value}`);
    inputRef.current.focus();
  };
  return (
    &lt;&gt;
      &lt;p&gt;State: {count} &lt;/p&gt;
      &lt;p&gt;Ref : {countRef.current}&lt;/p&gt;
      &lt;button onClick={increaseCountState}&gt;State 올려&lt;/button&gt;
      &lt;button onClick={increaseCountRef}&gt;Ref 올려&lt;/button&gt;
      &lt;p&gt;Ref : {countRef.current}&lt;/p&gt;
      &lt;p&gt;Var : {countVar}&lt;/p&gt;
      &lt;button onClick={doRender}&gt;render&lt;/button&gt;
      &lt;button onClick={printResults}&gt;Ref, Var 값 출력&lt;/button&gt;
      &lt;button onClick={increaseRef}&gt;Ref 올려&lt;/button&gt;
      &lt;button onClick={increaseVar}&gt;Var 올려&lt;/button&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;올려&lt;/button&gt;

      &lt;div&gt;
        &lt;input ref={inputRef} type=&quot;text&quot; placeholder=&quot;username&quot; /&gt;
        &lt;button onClick={login}&gt;login&lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Hooks] useEffect]]></title>
            <link>https://velog.io/@bomi__unni/React-Hooks-useEffect</link>
            <guid>https://velog.io/@bomi__unni/React-Hooks-useEffect</guid>
            <pubDate>Mon, 29 Jul 2024 04:37:35 GMT</pubDate>
            <description><![CDATA[<h1 id="useeffect">useEffect</h1>
<pre><code class="language-jsx">useEffect(()=&gt;{원하는작업})</code></pre>
<h3 id="1-인자로-하나의-콜백함수">1. 인자로 하나의 콜백함수</h3>
<pre><code class="language-jsx">useEffect(()=&gt;{원하는작업})</code></pre>
<ul>
<li>렌더링될때마다 매번 콜백함수가 실행됨</li>
</ul>
<h3 id="2-첫번째-인자로는-콜백함수-두번째-인자로는-배열dependency-array">2. 첫번째 인자로는 콜백함수, 두번째 인자로는 배열(dependency array)</h3>
<pre><code class="language-jsx">useEffect(()=&gt;{원하는작업}, [value])</code></pre>
<ul>
<li>만약 <code>빈 배열</code>을 전달해준다면 화면에 <code>첫 렌더링</code> 될 때만 실행됨</li>
<li>그게 아니면 <code>value값이 바뀔때</code> 실행됨</li>
</ul>
<pre><code class="language-jsx">const [count, setCount] = useState(0);
  // 렌더링될때마다 매번 실행됨
  useEffect(() =&gt; {
    console.log(&quot;count 변화&quot;);
  }, **[count]**);</code></pre>
<ul>
<li>이렇게 되면 count값이 변경될때만 useEffect가 실행된다!</li>
<li>이게 바로 dependency array</li>
</ul>
<h2 id="clean-up--정리">Clean Up : 정리</h2>
<pre><code class="language-jsx">useEffect(()=&gt;{
    // 구독...
    return () =&gt; {
    // 구독해제...
    }
}, [])</code></pre>
<ul>
<li>정리작업을 해제할 때는 useEffect의 return 값에 콜백함수로 넘겨주면 된다</li>
<li>그러면 Unmount될때 혹은 그 다음 useEffect가 실행되기 전에 해제가 된다</li>
</ul>
<h3 id="timerjsx">Timer.jsx</h3>
<pre><code class="language-jsx">import { useEffect } from &quot;react&quot;;

const Timer = () =&gt; {
  useEffect(() =&gt; {
    // 타이머 컴포넌트가 처음 화면에 렌더링될때
    const timer = setInterval(() =&gt; {
      console.log(&quot;타이머 돌아가는중&quot;);
    }, 1000);

    // 타이머함수 정리작업
    return () =&gt; {
      clearInterval(timer);
      console.log(&quot;timer end&quot;);
    };
  }, []);
  return (
    &lt;div&gt;
      &lt;span&gt;타이머를 시작합니다. 콘솔을 보세요&lt;/span&gt;
    &lt;/div&gt;
  );
};

export default Timer;
</code></pre>
<h3 id="appjsx">App.jsx</h3>
<pre><code class="language-jsx">import { useState, useEffect } from &quot;react&quot;;
import Timer from &quot;./components/Timer&quot;;
import &quot;./App.css&quot;;

function App() {
  const [count, setCount] = useState(0);
  const [name, setName] = useState(&quot;&quot;);
  const handleCountUpdate = () =&gt; {
    setCount(count + 1);
  };

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

  // 렌더링될때마다 매번 실행됨
  useEffect(() =&gt; {
    console.log(&quot;렌더링&quot;);
  });

  // count가 변화될때마다 실행됨
  useEffect(() =&gt; {
    console.log(&quot;count 변화&quot;);
  }, [count]);

  // name이 변화될때마다 실행됨
  useEffect(() =&gt; {
    console.log(&quot;name 변화&quot;);
  }, [name]);

  // 처음 마운팅됐을 때만 실행됨
  useEffect(() =&gt; {
    console.log(&quot;처음 마운팅&quot;);
  }, []);

  const [showTimer, setShowTimer] = useState(false);

  return (
    &lt;&gt;
      &lt;button onClick={handleCountUpdate}&gt;Update&lt;/button&gt;
      &lt;div&gt;count:{count}&lt;/div&gt;
      &lt;input type=&quot;text&quot; value={name} onChange={handleInputChange}&gt;&lt;/input&gt;
      &lt;div&gt;{name}&lt;/div&gt;
      &lt;button onClick={() =&gt; setShowTimer(!showTimer)}&gt;Toggle Timer&lt;/button&gt;
      {showTimer &amp;&amp; &lt;Timer /&gt;}
    &lt;/&gt;
  );
}

export default App;
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React Hooks] useState]]></title>
            <link>https://velog.io/@bomi__unni/React-Hooks-useState</link>
            <guid>https://velog.io/@bomi__unni/React-Hooks-useState</guid>
            <pubDate>Mon, 29 Jul 2024 04:07:19 GMT</pubDate>
            <description><![CDATA[<h2 id="state">State</h2>
<ul>
<li>컴포넌트의 상태</li>
</ul>
<pre><code class="language-jsx">const [state, setState] = useState(초기값);</code></pre>
<ul>
<li><p>state : 현재상태</p>
</li>
<li><p>setState : state 변경함수</p>
</li>
<li><p>state를 <code>배열형태</code>로 반환해준다</p>
</li>
<li><p>setState로 state를 변경하면 <code>컴포넌트가 업데이트(렌더링)</code> 된다</p>
</li>
<li><p>즉, setState 함수로 state를 변경할 때마다 컴포넌트가 <code>리렌더링</code>된다!</p>
</li>
<li><p>state를 변경할 때, 새로 변경될 state 값이 이전 state값과 <code>연관</code>이 있다면 setState의 인자로 <code>새로운 state</code>를 넘겨주는 <code>콜백함수</code>를 넘겨준다</p>
</li>
</ul>
<pre><code class="language-jsx">setState((prevState) =&gt; {
    // 코드
    return newState;
    });</code></pre>
<ul>
<li>초기값을 불러올 때, 엄청 무거운 데이터가 들어온다면 useState()안에 바로 값을 넣는게 아니라 콜백함수를 넣어주면 된다. 그러면 맨 처음 렌더링 될 때만 실행이 된다.</li>
</ul>
<pre><code class="language-jsx">useState(()=&gt;{
    return heavyWorks();
})</code></pre>
<pre><code class="language-jsx">import { useState } from &quot;react&quot;;

import &quot;./App.css&quot;;

const heavyWork = () =&gt; {
  console.log(&quot;엄청 무거운 작업&quot;);
  return [&quot;홍길동&quot;, &quot;김민수&quot;];
};

function App() {
  const [time, setTime] = useState(1);
  const handleClick = () =&gt; {
    let newTime;
    if (time &gt;= 24) {
      newTime = 1;
    } else {
      newTime = time + 1;
    }
    setTime(newTime);
  };

  const [names, setNames] = useState(() =&gt; {
    return heavyWork();
  });
  const [input, setInput] = useState(&quot;&quot;);
  const handleInputChange = (e) =&gt; {
    setInput(e.target.value);
  };
  const handleUpload = () =&gt; {
    setNames((prevState) =&gt; {
      return [input, ...prevState];
    });
  };

  console.log(input);

  return (
    &lt;&gt;
      &lt;div&gt;
        &lt;div&gt;현재시각 : {time}시&lt;/div&gt;
        &lt;button onClick={handleClick}&gt;Update&lt;/button&gt;
        &lt;div&gt;
          &lt;input value={input} onChange={handleInputChange} type=&quot;text&quot; /&gt;
        &lt;/div&gt;
        &lt;button onClick={handleUpload}&gt;Upload&lt;/button&gt;
        {names.map((name, idx) =&gt; {
          return &lt;p key={idx}&gt;{name}&lt;/p&gt;;
        })}
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++ 코딩테스트] 동적 프로그래밍 (동전문제) 구현]]></title>
            <link>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8F%99%EC%A0%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%8F%99%EC%A0%84%EB%AC%B8%EC%A0%9C-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8F%99%EC%A0%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%8F%99%EC%A0%84%EB%AC%B8%EC%A0%9C-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 25 Jul 2024 09:04:55 GMT</pubDate>
            <description><![CDATA[<h1 id="dynamic-programming">Dynamic Programming</h1>
<h3 id="큰-문제를-작은-문제부터-해결하여-계산하기분할-정복-기법--1차원-배열">큰 문제를 작은 문제부터 해결하여 계산하기(분할 정복 기법) : 1차원 배열</h3>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/67000952-11a7-4d72-8a2b-8ed714f44537/image.png" alt=""></p>
<ol>
<li>5원을 먼저 개수를 정하고, 남은 금액에 대해서 3원의 개수를 정하기 -&gt; X </li>
</ol>
<ul>
<li>예외가 발생</li>
</ul>
<ol start="2">
<li><p><img src="https://velog.velcdn.com/images/bomi__unni/post/22ce982c-20ac-4b23-b3e9-eda2e43b5f6e/image.png" alt="">
<img src="https://velog.velcdn.com/images/bomi__unni/post/17425775-72db-419e-a983-88788f12211c/image.png" alt=""></p>
</li>
</ol>
<h3 id="큰-문제를-작은-문제부터-해결하여-계산하기분할-정복-기법--1차원-배열설탕배달">큰 문제를 작은 문제부터 해결하여 계산하기(분할 정복 기법) : 1차원 배열(설탕배달)</h3>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/ab258403-c6f6-4e24-bae0-729da34c792a/image.png" alt=""></p>
<ul>
<li>배열의 크기 : 19</li>
<li>배열의 이름 : dp</li>
<li>N : 18</li>
<li>구하고자 하는 것 : f18 = dp[18]
<img src="https://velog.velcdn.com/images/bomi__unni/post/92f51936-b20f-45bb-8e6c-42c73187f269/image.png" alt=""></li>
</ul>
<p>ex6) dp[6] </p>
<ul>
<li>dp[6-5] = dp[1] = X</li>
<li>dp[6-3] = dp[3] = 1</li>
<li>dp[6] = min(dp[1]+1, dp[3]+1) = dp[3]+1 = 1+1 = 2</li>
<li>dp[6] = 2</li>
</ul>
<p>ex7) dp[7]</p>
<ul>
<li>dp[7-5] = dp[2] = X</li>
<li>dp[7-3] = dp[4] = X</li>
<li>dp[7] = X</li>
</ul>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/40fd4f7c-db19-4835-9af0-f99f76928ae3/image.png" alt=""></p>
<h1 id="dynamic-programming-푸는-방법">Dynamic Programming 푸는 방법</h1>
<ol>
<li>trivial case 찾아내기 (쉽게 알 수 있는 것들 일단 찾기)</li>
<li>non-trivial case 찾아내기 (점화식 필요)</li>
</ol>
<h3 id="코드-v1">코드 v1</h3>
<pre><code>#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;

#define X -1

int dp[5010] = { 0, X, X, 1, X, 1 };
int N;

int main() {
    scanf(&quot;%d&quot;, &amp;N);
    for (int i = 6; i &lt;= N; i++) {
        if (dp[i - 3] == X &amp;&amp; dp[i - 5] == X) {
            dp[i] = X;
            continue;
        }
        if (dp[i - 3] == X || dp[i - 5] == X) {
            dp[i] = max(dp[i - 3] + 1, dp[i - 5] + 1);
            continue;
        }
        dp[i] = min(dp[i - 3] + 1, dp[i - 5] + 1);
    }
    printf(&quot;%d&quot;, dp[N]);
}
</code></pre><h3 id="코드-v2">코드 v2</h3>
<pre><code>#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;

#define X 5000

int dp[5010] = { 0, X, X, 1, X, 1 };
int N;

int main() {
    scanf(&quot;%d&quot;, &amp;N);
    for (int i = 6; i &lt;= N; i++)
        dp[i] = min(dp[i - 3] + 1, dp[i - 5] + 1);

    if (dp[N] &gt;= X) {
        printf(&quot;-1&quot;);
        return 0;
    }

    printf(&quot;%d&quot;, dp[N]);
}
</code></pre><h4 id="조건문-이해">조건문 이해</h4>
<pre><code>if (dp[N] &gt;= X) {
    printf(&quot;-1&quot;);
    return 0;
}
</code></pre><ul>
<li>X는 5000으로 정의되어 있습니다. 이는 임의로 큰 값으로 설정된 것입니다.</li>
<li>dp 배열의 초기화 값으로 사용되며, 특정 정수를 3과 5로 나눌 수 없는 경우에 해당하는 값을 나타냅니다.</li>
<li>dp[N] &gt;= X 조건은 dp[N]이 초기화 값인 5000 이상인 경우, 즉, 입력된 N을 3과 5의 조합으로 나눌 수 없음을 의미합니다</li>
</ul>
<p>따라서, 이 조건이 참이라면:</p>
<ul>
<li>printf(&quot;-1&quot;);로 -1을 출력합니다. 이는 문제의 조건에서 N을 3과 5로 나눌 수 없음을 나타냅니다.</li>
<li>return 0;으로 프로그램을 종료합니다.</li>
<li>만약 dp[N]이 5000 미만이라면, 이는 N을 3과 5의 조합으로 나눌 수 있음을 의미하며, 그 경우 dp[N] 값을 출력합니다.</li>
</ul>
<p>-&gt; 이 조건문은 N을 3과 5로 나눌 수 없는 경우를 처리하는 부분입니다. 초기화 값 X (5000)를 사용하여 특정 값을 3과 5로 나눌 수 없는 경우를 나타내며, dp[N]이 이 값 이상이라면 -1을 출력하고 프로그램을 종료합니다. 그렇지 않다면 dp[N] 값을 출력하여 최소 횟수를 나타냅니다.</p>
<pre><code>-&gt; 위의 for문에서 `dp[i] = min(dp[i - 3] + 1, dp[i - 5] + 1);` 이 코드를 돌려서 dp[i-3]+1도, dp[i-5]+1 모두 X라면 dp[i] = X 이므로 이거를 다 모아서 나중에 if문으로 처리하는 것이다!!!</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[C++ 코딩테스트] 동적프로그래밍과 점화식의 관계]]></title>
            <link>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8F%99%EC%A0%81%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%EC%A0%90%ED%99%94%EC%8B%9D%EC%9D%98-%EA%B4%80%EA%B3%84</link>
            <guid>https://velog.io/@bomi__unni/C-%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%8F%99%EC%A0%81%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%EC%A0%90%ED%99%94%EC%8B%9D%EC%9D%98-%EA%B4%80%EA%B3%84</guid>
            <pubDate>Thu, 25 Jul 2024 07:53:39 GMT</pubDate>
            <description><![CDATA[<h1 id="dynamic-programming-동적-프로그래밍">Dynamic Programming (동적 프로그래밍)</h1>
<ul>
<li>분할 정복 풀이!</li>
<li>어떤 문제를 풀기 쉬운 작은 문제로 분할해서 풀어나가는 법 (순열)</li>
</ul>
<h3 id="수열">수열</h3>
<ul>
<li>수열은 &quot;숫자의 나열&quot;
<img src="https://velog.velcdn.com/images/bomi__unni/post/7a32b94a-a0cf-45ea-848d-6596a30a089e/image.png" alt=""></li>
</ul>
<h3 id="초항a1">초항(a1)</h3>
<ul>
<li>수열의 첫 번째 항</li>
</ul>
<h3 id="점화식an">점화식(an)</h3>
<ul>
<li>초항 이후의 나머지 값을 구하기 위한 규칙</li>
<li>수열의 n번째 값 an을 구하기 위해 따라야 하는 규칙</li>
<li>an을 구하기 위해서는 a1부터 순서대로 계산해야함</li>
</ul>
<h1 id="점화식을-사용한-문제-풀이">점화식을 사용한 문제 풀이</h1>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/410a8ac4-825b-42bb-b891-9f4f8806e8a1/image.png" alt=""></p>
<h3 id="분할-정복-풀이--top-down-접근">분할 정복 풀이 : Top-down 접근</h3>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/f1156d89-8da5-413b-826f-3b8932bad29b/image.png" alt=""></p>
<ul>
<li>a5를 구하기 위해 a4를 구하고, a4를 구하기 위해 a3를 구하고, a3를 구하기 위해 a2를 구하고, a2를 구하기 위해 a1를 구하는데, 우리는 a1을 이미 알고있으니까 다시 위로 올라가면서 a2, a3, a4, a5를 구할 수 있다. </li>
</ul>
<h3 id="분할-정복-풀이--bottom-up-접근-추천">분할 정복 풀이 : Bottom-up 접근 (추천!)</h3>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/13a11418-23b1-4aa3-879f-e4292e21874d/image.png" alt=""></p>
<ul>
<li>가장 작은값부터 계산해서 위로 올라감</li>
<li>a1을 이용해서 a2를 구하고, a2를 이용해서 a3을 구하고, a3를 이용해서 a4을 구하고, a4를 이용해서 a5를 구한다!</li>
</ul>
<h1 id="동적-프로그래밍의-자료구조---배열array">동적 프로그래밍의 자료구조 -&gt; 배열(Array)</h1>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/bd0c8786-a54d-4cdc-92f4-91117a63bee0/image.png" alt=""></p>
<ul>
<li>배열과 수열 사이에는 규칙이 있다</li>
<li>배열의 가장 왼쪽에 있는 index가 1인 원소(arr[1])는 곧 수열의 첫번째 원소 a1, 배열의 가장 오른쪽에 담겨있는 arr[5]는 a5이다.</li>
<li><code>ai == arr[i]</code></li>
</ul>
<p><img src="https://velog.velcdn.com/images/bomi__unni/post/b6124c94-13dd-470c-b7d4-a2a8b4bce0dc/image.png" alt="">
-&gt; 결국 for 반복문으로 구현 가능</p>
<h4 id="pseudo-code">pseudo code</h4>
<pre><code>int arr[5] = {3,0,0,0,0};

for (int i = 2; i &lt;= 5;i++) 
{
    arr[i] = 2*arr[i-1] - 4; // a_n = 2a_n-1 -4
}

print(arr[5])</code></pre>]]></description>
        </item>
    </channel>
</rss>