<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator><link href="https://returnrudi.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://returnrudi.github.io/" rel="alternate" type="text/html" /><updated>2024-02-23T11:28:24+09:00</updated><id>https://returnrudi.github.io/feed.xml</id><title type="html">ReturnRudi</title><subtitle>ReturnRudi의 블로그</subtitle><author><name>ReturnRudi</name></author><entry><title type="html">[DU벅이] 그래프화</title><link href="https://returnrudi.github.io/dubeogi/007/" rel="alternate" type="text/html" title="[DU벅이] 그래프화" /><published>2024-02-20T00:00:00+09:00</published><updated>2024-02-20T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/007</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/007/"><![CDATA[<h2 id="데이터화"><span style="color: #008000">데이터화</span></h2>
<p>길을 탐색하기 위해서는 학교의 모든 길을 데이터화해야 한다.<br />
처음에는 모든 데이터를 DB에 넣고 SQL을 활용하여 앱을 운용할 생각도 했지만<br />
DB를 구성할 경우 나중에 유지 비용이 발생했을 때 서비스를 지속할 자신이 없었다.<br /></p>

<p>교내의 모든 길을 찾고 그 길에 대한 여러 가중치를 데이터화하는 복잡한 과정을 거친 후<br />
비용 때문에 서비스를 못한다는 것은 너무나도 아쉬운 일이 될 것 같아서<br />
모든 데이터를 그냥 코드 내에 녹여내기로 했다.</p>

<h2 id="데이터화-1"><span style="color: #008000">데이터화</span></h2>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[동국대학교를 그래프로 변환하는 과정]]></summary></entry><entry><title type="html">[DU벅이] GPS 구현</title><link href="https://returnrudi.github.io/dubeogi/006/" rel="alternate" type="text/html" title="[DU벅이] GPS 구현" /><published>2024-02-18T00:00:00+09:00</published><updated>2024-02-18T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/006</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/006/"><![CDATA[<h2 id="gps"><span style="color: #008000">GPS</span></h2>
<p>DU벅이는 API를 사용하지 않기 때문에 개발 초기에 GPS는 당연히 사용하지 못할 것이라고 생각했었다.<br />
하지만 어느 날 저녁 문득 생겨난 아이디어로 간단하게나마 제작을 하게 되었다.<br /></p>

<p>우선 휴대폰에서 GPS 요청을 보내면 어떤 정보를 반환하는지를 찾아보았다.</p>

<p>GPS 요청 결과 위도, 경도를 소수점 아래 6번째 자리까지 표시된 숫자로 반환해 준다.<br />
이 때 소수점 아래 6번째 자리, 즉 0.000001 이 실제 1m를 의미한다.</p>

<p>DU벅이는 고정된 지도 이미지를 사용하므로 이미지 <strong>좌측 상단</strong>의 경도/위도, <strong>우측 하단</strong>의 경도/위도를 알면<br />
<strong>비례식</strong>을 통해 지도 이미지 위에 현재 위치를 나타낼 수 있을 것 같았다.</p>

<p><img src="/../images/2024-02-18-006/설명1.jpg" alt="explanation1" style="zoom:60%;" /></p>

<p>위 사진과 같이 <strong>좌측 상단</strong>의 경도/위도가 ( $A_x$, $A_y$ ) = ( 126.996208, 37.564249 ) 이고<br />
<strong>우측 하단</strong>의 경도/위도가 ( $B_x$, $B_y$ ) = ( 127.004660, 37.552279 ) 일 때</p>

<p><strong>현재 위치(C)</strong>에서 GPS 요청을 보내서 받은 경도/위도가  ( $C_x$, $C_y$ ) = ( 127.002549, 37.560259 ) 라면<br />
아래와 같은 비례식 계산을 통해 C의 위치 ( $dx$, $dy$ )를 구할 수 있다.</p>

<p>$dx = 3000 \times \frac{(C_x - A_x)}{(B_x - A_x)}$<br /><br />
$dx = 3000 \times \frac{0.006341}{0.008452} = 2250.709891$</p>

<p>$dy = 5333 \times \frac{(A_y - C_y)}{(A_y - B_y)}$<br /><br />
$dy = 5333 \times \frac{0.00399}{0.01197} = 1777.666667$</p>

<p>즉 점 C의 위치는 이미지 픽셀 ( 2250, 1777 ) 이 된다.</p>

<h2 id="geolocator를-통한-구현"><span style="color: #008000">Geolocator를 통한 구현</span></h2>
<p>위의 아이디어를 실제로 구현하기 위해서 Geolocator 플러그인을 사용했다. <a href="https://pub.dev/packages/geolocator">[Geolocator 링크]</a><br />
Geolocator는 현재 위치 정보 반환, 위치 변경 감지, 위치 권한 관리, 위치 정보 저장 등과 같은<br />
여러 기능을 제공해주는 Flutter 플러그인이다. <br /></p>

<p>버전은 개발 당시 최신 버전이었던 7.6.2 버전을 적용했다.</p>

<p>GPS 기능은 아래 4가지 함수와 isTrackingLocation 변수를 통해 동작된다.</p>

<ul>
  <li><strong>isTrackingLocation 변수(bool)</strong><br />
현재 GPS 기능이 활성화 상태인지, 비활성화 상태인지 true/false로 나타내는 변수<br />
이 변수가 가지는 값에 따라 GPS 기능 버튼의 로고를 다르게 표시한다.</li>
</ul>

<ol>
  <li>
    <p><strong>requestLocationPermission 함수</strong>: 위치 권한을 요청하는 함수<br /><br />
Permission.location.request() 메서드를 이용해서 위치 권한을 요청하며<br />
만약 권한 자체가 부여되지 않은 경우에는 사용자에게 권한 요청을 보낸다.</p>
  </li>
  <li>
    <p><strong>toggleLocationTracking 함수</strong>: GPS 기능을 활성화/비활성화 하는 함수<br /><br />
isTrackingLocation이 true라면, 즉 활성화 상태라면 positionStream?.cancel()을 통해<br />
비활성화 시키고 isTrackingLocation를 false로 만든다.<br />
isTrackingLocation이 false라면, 즉 비활성화 상태라면 startLocationStream 함수를 호출하여<br />
활성화 시키고 isTrackingLocation를 true로 만든다.<br /></p>
  </li>
  <li>
    <p><strong>startLocationStream 함수</strong>: 위치 스트림을 받아오는 함수<br /><br />
우선 requestLocationPermission 함수를 호출하여 위치 권한을 요청한다.<br />
그 후 Geolocator.getPositionStream 메서드를 사용하여 위치 스트림을 받아온다.<br />
(위치 스트림이란 사용자의 현재 위치를 지속적으로 업데이트하는 데이터 스트림을 말한다.)<br /><br />
정확도는 LocationAccuracy.high로 높은 정확도를 가지도록 설정했으며<br />
사용자가 일정 거리를 이동할 때마다 또는 일정 시간마다 위치를 업데이트할 수 있는데<br />
전자의 경우 적용해 본 결과 반응이 느리고 부정확한 면이 있어<br />
1초마다 위치 정보를 업데이트하도록 설정했다.<br /><br />
받아온 경도/위도 정보를 gpsToPixel 함수를 통해 Offset으로 변환 후 nowLocationPixel 변수에 저장한다.</p>
  </li>
  <li>
    <p><strong>gpsToPixel 함수</strong>: 비례식을 통해 경도/위도를 이미지 내 위치(Offset)로 변환하는 함수<br /><br />
위 내용에 설명했던 비례식을 그대로 코드 구현해놓은 함수이다.</p>
  </li>
</ol>

<h2 id="지도-이미지-위에-표시"><span style="color: #008000">지도 이미지 위에 표시</span></h2>
<p>기능적 구현을 완료했으므로 이제 반환한 이미지 픽셀 좌표에 나의 위치임을 나타내는 도형을 띄우기만 하면 된다.</p>

<p>나의 위치는 GPS 기능이 활성화된 상태에서만 보여야 하므로 isTrackingLocation = true 일 때만 보이도록 설정했다.<br />
도형은 DU벅이의 테마색인 주황색을 활용하여 아래와 같이 만들었다.<br /><br />
<img src="/../images/2024-02-18-006/도형.jpg" alt="figure" style="zoom:60%;" /><br /><br />
두 개의 원으로 이루어져 있으며 외부의 원은 투명도를 높였고 내부의 원은 흰색 테두리를 가지도록 만들었다.</p>

<p>해당 도형은 이미지를 띄운 것이 아니고 레이아웃 클래스 <strong>Positioned</strong>를 통해 만들었기 때문에<br />
두 개의 원을 원하는 곳에 위치시키려면 약간의 수학 계산이 필요하다.</p>

<p>Positioned는 top, bottom, left, right과 같은 속성을 지정해서 부모 위젯 내에서 어디에 위치할지를 결정한다.<br />
이때 지정해 준 위치에 Positioned의 중앙이 위치하는 것이 아니라 <strong>좌측 상단이 위치</strong>하게 된다.<br /></p>

<p>GPS 기능을 통해 반환한 이미지 픽셀 위치에 정확히 원이 위치해야 하므로<br />
그 도형의 크기에 맞게 좌표를 수정해야 한다.</p>

<p><img src="/../images/2024-02-18-006/설명2.jpg" alt="explanation2" style="zoom:40%;" /></p>

<p>위 그림과 같이 큰 원은 ( -9, -9 ) 만큼, 작은 원은 ( -5, -5 ) 만큼 각각 빼주어야<br />
내 위치가 각각의 원의 중앙에 오도록 이동시킬 수 있다.<br /></p>

<p>더 나아가 가독성을 위해 줌 레벨에 따라 크기가 일정하기 하기 위해서 빼주는 만큼에서 줌 레벨 정도를 나눠줘야 한다.</p>

<p>즉 큰 원은 ( - 9 * 1.3 / mapvalue.scale, - 9 * 1.3 / mapvalue.scale ) 만큼, <br />
작은 원은 ( - 5 * 1.3 / mapvalue.scale, - 5 * 1.3 / mapvalue.scale ) 만큼 빼주어야 한다.</p>

<p>결과는 아래와 같다.</p>

<p><img src="/../images/2024-02-18-006/설명3.gif" alt="explanation3" style="zoom:60%;" /></p>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[GPS 구현 과정]]></summary></entry><entry><title type="html">[DU벅이] 층 선택 리스트 뷰( floor_view.dart )</title><link href="https://returnrudi.github.io/dubeogi/999/" rel="alternate" type="text/html" title="[DU벅이] 층 선택 리스트 뷰( floor_view.dart )" /><published>2024-02-11T00:00:00+09:00</published><updated>2024-02-11T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/999</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/999/"><![CDATA[<h2 id="리스트-뷰"><span style="color: #008000">리스트 뷰</span></h2>
<p>실내 정보를 포함하는 길 안내를 하기 위해서는 각 건물마다 사용자가 원하는 층을 볼 수 있는 기능을 구현해야 했다.<br />
이를 위해서 건물마다 터치가 가능하게 만든 후 원하는 건물을 터치 시 선택 가능한 층수가 한 번에 보이게 하고 싶었다.<br /></p>

<p>따라서 나열이 가능하고 너무 많을 시에 스크롤 또한 가능한 리스트 뷰를 선택했다.</p>

<h2 id="트리거"><span style="color: #008000">트리거</span></h2>
<p>원하는 건물을 터치 시에 리스트 뷰가 보여야 하므로 _showButton 이라는 String 변수를 활용했다.<br />
아무 건물도 터치하지 않을 시에 초기값 _showButton = “기본” 을 저장하고 있다.</p>

<p>건물이 터치될 경우 _showFloorButton 함수를 통해 _showButton 변수가 터치한 건물명으로 변경된다.</p>
<ul>
  <li><span style="color: #0000FF">학술관 터치 → _showButton = “학술관”</span></li>
</ul>

<p>_showButton이 “기본” 이 아니게 되면 리스트 뷰를 출력한다.<br /><br />
<img src="/../images/2024-02-11-999/기본.png" alt="showButton" style="zoom:100%;" /></p>

<h2 id="빌드-과정"><span style="color: #008000">빌드 과정</span></h2>
<ol>
  <li>경로 ‘assets/images/floor/’ 에서 _showButton 값으로 파일 이름을 검색 후 결과를 리스트(fileNames)로 반환한다.<br />
이 때 리스트에 들어가는 순서는 사전식 순서(대문자 → 소문자 → 숫자)이다.
    <ul>
      <li><span style="color: #0000FF">_showButton = “학술관” → fileNames = [ “학술관B1.png”, “학술관1.png”, “학술관4.png” ]</span></li>
    </ul>
  </li>
  <li>fileNames 리스트를 정규 표현식을 통해 숫자만 뽑아내서 비교 후 순서대로 정렬한다.
    <ul>
      <li><span style="color: #0000FF">[ “학술관B1.png”, “학술관1.png”, “학술관4.png” ]</span></li>
    </ul>
  </li>
  <li>fileNames 리스트를 뒤집고 앞에 “시설”, “기본”을 삽입한다.
    <ul>
      <li><span style="color: #0000FF">[ “시설”, “기본”, “학술관4.png”, “학술관1.png”, “학술관B1.png” ]</span></li>
    </ul>
  </li>
  <li>리스트 뷰 상단에 현재 터치된 건물명(showButton)을 표시한다.</li>
  <li>replaceToBuildingInfo 함수를 통해 fileNames 리스트의 건물 이미지 파일명을 층 수 표기로 변환한다.
    <ul>
      <li><span style="color: #0000FF">[ “시설”, “기본”, “4F”, “1F”, “B1” ]</span></li>
    </ul>
  </li>
  <li>변환한 층 수 표기를 바탕으로 리스트 뷰를 표시한다.</li>
</ol>

<h2 id="층-수-터치-시"><span style="color: #008000">층 수 터치 시</span></h2>
<p>리스트 뷰에서 특정 층이 터치된 경우 onValueChanged를 통해 메인 화면에 아래 두가지를 반환한다.</p>
<ol>
  <li>floorToFilePath 함수를 통해 터치된 층의 이미지 파일의 경로(String)를 반환
    <ul>
      <li><span style="color: #0000FF">“B1” 터치 → “assets/images/floor/학술관B1.png” 반환</span></li>
      <li><span style="color: #0000FF">“기본” 터치 → showButton 반환</span></li>
      <li><span style="color: #0000FF">“시설” 터치 → “시설” 반환</span></li>
    </ul>
  </li>
  <li>floorToInt 함수를 통해 터치된 층의 층 수(int)를 반환
    <ul>
      <li><span style="color: #0000FF">“B1” 터치 → -1 반환</span></li>
      <li><span style="color: #0000FF">“기본” or “시설” 터치 → 0 반환</span></li>
    </ul>
  </li>
</ol>

<p><br />
B1을 터치 했다면 <span style="color: #0000FF">( “assets/images/floor/학술관B1.png”, -1 )</span> 을 반환</p>

<p>반환한 값을 바탕으로 nowFloorData(map 자료형: 현재 표시되는 건물의 층 수 저장)의 _showButton을 갱신</p>
<ul>
  <li><span style="color: #0000FF">nowFloorData [“학술관”] = -1</span></li>
</ul>

<p>만약 “시설”을 반환했다면 gotoBuildingInfo 함수를 통해 시설 정보 화면을 띄움<br />
“시설”이 아니라면 buildingFilePath(map 자료형: 현재 건물의 단면도 파일 경로 저장)의 _showButton을 갱신</p>
<ul>
  <li><span style="color: #0000FF">buildingFilePath[“학술관”] = “assets/images/building/학술관B1.png”</span></li>
</ul>

<p>이후 해당 층 단면도에 표시되야할 경로가 있는 경우 경로 표시 → 다른 포스팅을 통해 설명 예정</p>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[층을 선택해서 해당하는 층의 단면도를 보여주는 리스트 뷰 구현(floor_view.dart)]]></summary></entry><entry><title type="html">[DU벅이] 화면에 지도 띄우기, 줌, 드래그 구현</title><link href="https://returnrudi.github.io/dubeogi/005/" rel="alternate" type="text/html" title="[DU벅이] 화면에 지도 띄우기, 줌, 드래그 구현" /><published>2024-02-08T00:00:00+09:00</published><updated>2024-02-08T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/005</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/005/"><![CDATA[<h2 id="지도-이미지-띄우기"><span style="color: #008000">지도 이미지 띄우기</span></h2>
<p>지도 제작은 완료했으니 이제 지도를 화면에 띄우기만 하면 된다.<br />
그냥 지도 이미지를 띄우는 것은 어렵지 않으나 지도 앱의 역할을 하기 위해선<br />
줌, 드래그와 같은 기능을 가지고 있어야 했다. 따라서 위젯 트리를 아래와 같은 순서로 구성했다.</p>

<p><strong><span style="color: #0000FF">MaterialApp</span></strong>: Material Design을 사용할 수 있게 하는 클래스<br />
<strong><span style="color: #0000FF">Scaffold</span></strong>: Material Design 구조를 구현하는데 사용되는 위젯<br />
<strong><span style="color: #0000FF">GestureDetector</span></strong>: 줌, 드래그와 같은 제스처를 감지하는 위젯<br />
<strong><span style="color: #0000FF">Transform.scale</span></strong>: 자식 위젯의 크기를 확대 또는 축소 시켜주는 위젯 (줌)<br />
<strong><span style="color: #0000FF">Transform.translate</span></strong>: 자식 위젯의 위치를 이동시켜주는 위젯 (드래그)<br />
<strong><span style="color: #0000FF">CustomPaint</span></strong>: 경로를 표시하기 위해 위젯에 선을 그려주는 클래스<br />
<strong><span style="color: #0000FF">Image.asset</span></strong>: 지도 이미지</p>

<h2 id="줌-드래그-구현"><span style="color: #008000">줌, 드래그 구현</span></h2>

<p>지도를 확대/축소하고 드래그하기 위해 GestureDetector, Transform.scale, Transform.translate를 이용했다.</p>

<h3 id="동작-감지-gesturedetector"><span style="color: #008000">동작 감지: GestureDetector</span></h3>

<p>GestureDetector 위젯은 <strong>사용자의 제스처를 감지</strong>한다.<br />
줌을 했다면 어느 정도 줌을 했는지, 드래그를 했다면 어느 정도 드래그를 했는지 <strong>정보를 담아주는 역할</strong>을 한다.<br />
지도 이미지 위젯을 줌/드래그하기 위해서 GestureDetector의 아래에 지도 이미지 위젯을 위치시켰다.<br />
GestureDetector의 콜백 함수인 onScaleStart, onScaleUpdate를 이용하여 여러 기능들을 구현하는 것이 가능하다.<br /></p>

<h3 id="위젯-이동-시키기-transform"><span style="color: #008000">위젯 이동 시키기: Transform</span></h3>

<p>Transform은 자식 위젯의 <strong>형태, 사이즈, 위치를 변경해 주는 위젯</strong>이다.<br />
Transform.scale의 <strong>scale 속성의 값</strong>을 변경하면 위젯의 크기를 수정 가능하고(<strong>줌 인/줌 아웃</strong>)<br />
Transform.translate의 <strong>Offset 속성의 값</strong>을 변경하면 위젯의 위치를 변경이 가능하다(<strong>드래그</strong>)<br /></p>

<p>scale 속성의 값과 Offset 속성의 값을 각각 변수로 지정하면 내가 원하는 때에 원하는 만큼 줌/드래그가 가능해진다.</p>

<p>원래 translate의 Offset은 위젯 중심을 기준으로 Offset(0, 0)을 갖는다.<br />
Offset(50, 0)으로 설정하면 <strong>오른쪽</strong>으로 50만큼 위젯이 이동하고<br />
Offset(0, 50)으로 설정하면 <span style="color: red"><strong>아래쪽(주의)</strong></span>으로 50만큼 위젯이 이동한다.</p>

<p>하지만 DU벅이는 큰 지도 이미지를 사용하고 대부분 위젯의 크기가 화면에 보이는 부분의 크기보다 큰 상황(줌)이 많을 것이므로<br />
개발의 편의를 위해 Offset의 <strong>중심점(원점)</strong>을 위젯의 중심이 아닌 이미지의 좌표 기준과 동일하게 <strong>좌측 상단</strong>으로 이동시켰다.<br />
이렇게 하면 Offset을 마치 이미지 상의 현재 <strong>위치(좌표)</strong>처럼 사용이 가능하다.</p>

<p>아래 내용은 중심점을 변환시키는 코드이다.</p>

<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Transform</span><span class="o">.</span><span class="na">scale</span><span class="p">(</span>
    <span class="nl">scale:</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">scale</span><span class="p">,</span>
    <span class="nl">child:</span> <span class="n">Transform</span><span class="o">.</span><span class="na">translate</span><span class="p">(</span>
        <span class="nl">offset:</span> <span class="n">Offset</span><span class="p">(</span><span class="n">_imageWidth_du</span> <span class="o">/</span> <span class="mi">2</span> <span class="o">-</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">position</span><span class="o">.</span><span class="na">dx</span><span class="p">,</span> <span class="n">_imageHeight_du</span> <span class="o">/</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">scr_img_diff</span> <span class="o">/</span> <span class="mi">2</span> <span class="o">-</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">position</span><span class="o">.</span><span class="na">dy</span><span class="p">)</span><span class="o">.</span><span class="na">scale</span><span class="p">(</span><span class="n">scale_offset</span><span class="p">,</span> <span class="n">scale_offset</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>_imageWidth_du</strong>, <strong>_imageHeight_du</strong>는 지도 이미지의 너비, 높이이다.</p>

<p>현재 DU벅이는 3000 x 5333 이미지를 사용 중이므로<br />
_imageWidth_du = 3000<br />
_imageHeight_du = 5333 이다.</p>

<p><strong>scr_img_diff</strong>는 지도 이미지 위젯의 높이와 디바이스 전체 화면 높이 간의 차이이다.<br />
scr_img_diff / 2 를 더해 지도 이미지 위젯의 중앙과 디바이스 화면 중앙을 맞춰주었다.<br />
(scr_img_diff를 어떻게 구하는지는 하단에 설명 예정)</p>

<p><strong>mapvalue.position.dx</strong>, <strong>mapvalue.position.dy</strong>는 줌/드래그 기능을 위해 지정한 변수이다.</p>

<p>아래 사진을 통해 변환 과정을 나타냈다.</p>

<p><img src="/../images/2024-02-08-005/설명1.jpg" alt="explanation1" style="zoom:40%;" /></p>

<p>이를 통해 mapvalue.position.dx, mapvalue.position.dy에 원하는 값을 넣으면<br />
위젯을 알맞게 이동시키며 해당 값에 해당하는 지도 이미지 픽셀을 화면 중앙에 표시하게 된다.</p>

<p>ex)<br />
mapvalue.position.dx = 500<br />
mapvalue.position.dy = 1300<br />
갤럭시 S23의 경우 scr_img_diff = 1167</p>

<p>Offset(_imageWidth_du / 2 - mapvalue.position.dx,<br />　　　　
_imageHeight_du / 2 + scr_img_diff / 2 - mapvalue.position.dy)<br />
= Offset( 3000 / 2 - 500, 5333 / 2 + 1167 / 2 - 1300 )<br />
= Offset( 1000, 1950 )<br />
= 지도 이미지 위젯을 x축 1000만큼, y축 1950만큼 이동시킨다.</p>

<p><img src="/../images/2024-02-08-005/설명2.jpg" alt="explanation2" style="zoom:40%;" /></p>

<p>위 사진과 같이 화면 중앙에 이미지의 ( 500, 1300 ) 픽셀이 잘 위치하게 된다는 것을 확인할 수 있다.</p>

<h3 id="줌-드래그-기능-구현하기-onscalestart-onscaleupdate"><span style="color: #008000">줌, 드래그 기능 구현하기: onScaleStart, onScaleUpdate</span></h3>
<p>위에서도 설명했듯이 onScaleStart, onScaleUpdate는 GestureDetector의 콜백함수이다.</p>

<p><strong>onScaleStart</strong>는 사용자가 제스처를 시작할 때 호출되는 함수이다.<br />
매개변수로 ScaleStartDetails details를 받는데<br />
이 details는 줌/드래그가 <strong>시작된 위치</strong>와 <strong>시간</strong> 등의 정보를 가진다.<br /></p>

<p>아래와 같이 <strong>제스처가 시작</strong>되는 순간의 줌 정도와 현재의 위치를 저장하도록 했다.</p>

<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="c1">// 줌/드래그 가 시작되는 시점의 줌 레벨과 위치를 저장하는 함수 _onScaleStart</span>
  <span class="kt">void</span> <span class="n">_onScaleStart</span><span class="p">(</span><span class="n">ScaleStartDetails</span> <span class="n">details</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">mapvalue</span><span class="o">.</span><span class="na">previousScale</span> <span class="o">=</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">scale</span><span class="p">;</span>
    <span class="n">mapvalue</span><span class="o">.</span><span class="na">previousPosition</span> <span class="o">=</span> <span class="n">details</span><span class="o">.</span><span class="na">focalPoint</span><span class="p">;</span>
  <span class="p">}</span>
</code></pre></div></div>
<p><br />
<strong>onScaleUpdate</strong>는 사용자가 <strong>제스처를 진행 중</strong>일 때 호출되는 함수이다.<br />
역시 매개변수로 ScaleUpdateDetails details를 받고<br />
이 details는 <strong>줌 변화량</strong>과 <strong>중심 위치</strong>등의 정보를 가진다.<br /></p>

<p>먼저 아래와 같이 줌 레벨의 정도를 업데이트한다.</p>

<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mapvalue</span><span class="o">.</span><span class="na">scale</span> <span class="o">=</span> <span class="p">(</span><span class="n">mapvalue</span><span class="o">.</span><span class="na">previousScale</span> <span class="o">*</span> <span class="n">details</span><span class="o">.</span><span class="na">scale</span><span class="p">)</span><span class="o">.</span><span class="na">clamp</span><span class="p">(</span><span class="mf">1.3</span><span class="p">,</span> <span class="mf">12.0</span><span class="p">);</span>
</code></pre></div></div>
<p>onScaleStart에서 저장해둔 이전의 줌 레벨 값에 바뀐 줌 레벨 정도를 곱해서 새로운 줌 레벨을 저장한다.</p>

<p>다음은 <strong>드래그</strong> 기능이다.</p>

<p>드래그는 사용자가 화면을 드래그하는 정도와 위젯이 이동하는 변화량이 같게 만들면 구현이 가능하다.<br />
즉 details가 가지고 있는 중심 위치(사용자가 화면을 드래그해서 바뀐 중심 위치)에서<br />
기존의 위치 좌표를 빼면 화면을 이동한 정도가 나오고 그 값을 좌표 변수에 빼주면 된다.<br />
(위젯을 50만큼 이동시키기 위해서는 좌표가 -50이 되어야 하므로 ‘-=’ 연산자를 사용)</p>

<p>하지만 주의해야 할 점은 <strong>줌 레벨에 따라 드래그의 변화량도 변한다</strong>는 것이다.<br />
화면이 확대되어 있는 상태와 확대되어 있지 않은 상태에서 한 번의 드래그 변화량은 차이가 크다.<br />
따라서 그 변화량을 반드시 줌 레벨 값으로 나누어서 보정을 해주어야한다.<br /></p>

<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mapvalue</span><span class="o">.</span><span class="na">position</span> <span class="o">-=</span> <span class="p">(</span><span class="n">details</span><span class="o">.</span><span class="na">focalPoint</span> <span class="o">-</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">previousPosition</span><span class="p">)</span> <span class="o">/</span> <span class="n">mapvalue</span><span class="o">.</span><span class="na">previousScale</span> <span class="o">/</span> <span class="n">scale_offset</span><span class="p">;</span>
</code></pre></div></div>

<p>scale_offset은 좌표를 이미지의 픽셀 단위와 같도록 보정해 주는 비율값이다.<br />
이미지 위젯을 화면 너비에 꽉 차도록 설정했기 때문에 디바이스 해상도 너비에서 이미지의 너비를 나누어서 비율을 계산했다.<br /></p>

<p><strong>디바이스 너비 / 이미지 너비 = scale_offset</strong> 이고 이는<br />
<strong>디바이스 너비 / scale_offset = 이미지 너비</strong> 와 같으므로</p>

<p><strong>실제 디바이스 드래그 변화량 / scale_offset = 이미지 좌표 변화량</strong>이 된다.</p>

<h3 id="드래그로-이미지-위젯-밖을-벗어나지-않도록-만들기-clamp"><span style="color: #008000">드래그로 이미지 위젯 밖을 벗어나지 않도록 만들기: clamp</span></h3>

<p>현재 DU벅이는 3000 x 5333 지도 이미지를 사용 중이다.</p>

<p>이 지도 이미지 위젯을 화면에 띄우고 드래그 기능을 사용하면 한 가지 문제가 발생한다.<br />
계속 한 방향으로 드래그를 지속하면 결국 지도 이미지 영역 밖으로 벗어나고<br />
위젯의 범위를 벗어나면 GestureDetector 영역 밖이기 때문에 어떠한 터치도 인식하지 못하게 된다.</p>

<p>따라서 드래그를 통해 이미지 범위 밖을 벗어나지 못하도록 좌표 위치에 <strong>제한</strong>을 두어야 한다.<br />
이러한 제한을 가능하게 하는 것이 <strong>clamp</strong> 이다.</p>

<p><strong>clamp</strong>는 Flutter에서 제공하는 메서드이며 숫자를 지정된 범위 내로 제한할 수 있게 해준다.<br />
아래는 사용 예시이다.</p>

<div class="language-dart highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">double</span> <span class="n">value</span> <span class="o">=</span> <span class="mf">15.0</span><span class="p">;</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="na">clamp</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">10.0</span><span class="p">);</span>
<span class="n">print</span><span class="p">(</span><span class="n">value</span><span class="p">);</span> <span class="c1">// 10.0 출력</span>
</code></pre></div></div>
<p><br /></p>

<p>화면에서 이미지 위젯이 벗어날 수 있는 경우의 수는 2가지이다.</p>

<ol>
  <li>
    <p><strong>보여지는 화면이 이미지 위젯보다 작으며 드래그를 통해 이미지 영역 밖으로 벗어나는 경우</strong><br />
<br /><img src="/../images/2024-02-08-005/설명3.jpg" alt="explanation3" style="zoom:40%;" /><br /><br />
위 사진과 같은 경우이다. 이 경우에 현재 보여지는 화면의 크기가 dx, dy의 최대/최소값을 결정한다.<br />
좌상단이 Offset(0, 0) 이므로<br /><br />
<strong>최소 Offset( dx, dy )</strong> = Offset( 화면 너비 / 2, 화면 높이 / 2 )<br />
<strong>최대 Offset( dx, dy )</strong> = Offset( _imageWidth_du - 화면 너비 / 2, _imageHeight_du - 화면 높이 / 2 )<br /><br />
이때 보이는 화면의 크기는 너비를 통해 계산할 수 있다.<br /><br />
위에서도 언급했지만 줌 레벨이 1.0일 경우 이미지 위젯을 화면 너비에 꽉 차도록 설정했기 때문에<br />
_imageWidth_du를 줌 레벨 정도로 나누면 현재 화면에 보이는 너비를 픽셀 단위로 알 수 있다.<br />
높이는 실제 해상도의 너비, 높이 비율을 구한 후 너비에 곱해주면 구할 수 있다.<br /><br />
실제 해상도의 너비, 높이 비율은 <strong>MediaQuery.of(context)</strong> 를 사용해서 구할 수 있다.<br /><br />
<strong>MediaQueryData</strong>는 디바이스의 화면 크기, 픽셀 비율, 텍스트 스케일 팩터,<br />
픽셀 밀도, 상단 및 하단 패딩, 화면 방향 등의 정보를 제공하는 클래스이다.<br />
위에서 언급한 <strong>scr_img_diff</strong> 또한 MediaQuery.of(context).padding.top 을 통해 구한 값이다.</p>
  </li>
  <li>
    <p><strong>보여지는 화면이 이미지 위젯보다 커서 이미 화면에 이미지 영역 밖이 보여지는 경우</strong><br />
<br />사실 일어나서는 안되는 경우이다.<br />
이미지 위젯의 밖 영역은 Flutter에서 흰색 배경(아마 디폴트 색상)으로 표현해 주기 때문에<br />
이러한 상황이 벌어지는 순간 앱의 완성도가 확연히 떨어져 보이게 된다.<br /><br />
줌 레벨에도 clamp를 걸어서 최대한 일어나지 않도록 했지만<br />
디바이스에 따라 일어날 수도 있는 경우이기 때문에 고려하지 않을 수는 없었다.<br /><br />
이 경우에는 그래도 지도 이미지가 최대한 중간에 위치하는 것이 제일 좋은 방법이라고 생각했고<br />
그것에 맞게 clamp를 설정했다.<br />
쉽게 생각하면 dx, dy 각각의 최소값의 최대값, 최대값의 최소값을 지정해준 것이라고 생각하면 된다.<br />
<br /><img src="/../images/2024-02-08-005/설명4.jpg" alt="explanation4" style="zoom:40%;" /><br /><br />
중앙을 유지하기 위해서 dx의 최소값이 최대 _imageWidth_du / 2, 최대값이 최소 _imageWidth_du / 2 이도록 설정했고<br />
dy도 마찬가지로 최소값이 최대 _imageHeight_du / 2, 최대값이 최소 _imageHeight_du / 2 값을 갖도록 했다.</p>
  </li>
</ol>

<p>이와 같은 과정으로 지도 이미지를 띄우고 줌, 드래그 기능을 구현했다.<br />
실제 개발을 할 때도 제일 시간이 많이 걸렸던 작업이기도 하고<br />
오랜만에 보면 또 까먹는 구간이기도 해서 좀 더 자세하게 기록으로 남긴다.</p>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[지도 앱의 기본 기능 구현]]></summary></entry><entry><title type="html">[DU벅이] 지도(캠퍼스맵) 제작</title><link href="https://returnrudi.github.io/dubeogi/004/" rel="alternate" type="text/html" title="[DU벅이] 지도(캠퍼스맵) 제작" /><published>2024-02-06T00:00:00+09:00</published><updated>2024-02-06T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/004</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/004/"><![CDATA[<h2 id="지도에-대한-고민"><span style="color: #008000">지도에 대한 고민</span></h2>
<p>지도를 이용한 앱을 만들 때에는 사용할 지도 API를 먼저 선정하는 것이 일반적이다.<br />
이전에 진행한 식단 관리 어플리케이션을 만들 때에도 구글 맵 API를 통해 식사를 한 곳의 위치를<br />
지도상에서 찾아 그 위도, 경도를 Firebase DB에 저장했었던 경험이 있다.</p>

<p>하지만 기획한 DU벅이의 경우 그 어떤 지도 API도 사용이 불가능했다.<br />
Google Maps, KakaoMap, 네이버 지도 모두 교내의 모든 길이 표현되어 있지 않았으며<br />
최종 목표였던 실내 경로 탐색 또한 불가능했다. (네이버 지도는 일부 대형몰에 한해서 층별 안내 제공)<br /></p>

<p>여러 방법들을 찾아봤지만 결국 지도 API가 제공하는 여러 기본 기능들을 모두 처음부터 만들어야 한다는 결론에 도달했다.</p>

<h2 id="지도-제작"><span style="color: #008000">지도 제작</span></h2>
<p>API를 사용하지 않고 지도를 만들기 위한 첫걸음으로 먼저 지도 이미지를 화면 상에 띄우는 것을 목표로 삼았다.<br />
화면 상에 이미지를 띄우는 것은 어려운 일이 아니었으나 그것이 학교 지도 이미지라는 것이 큰 문제였다.<br /></p>

<p>아래 이미지는 우리나라에서 자주 사용되는 3개의 지도 어플이 표현한 동국대학교 지도이다.</p>

<ul>
  <li>
    <p>네이버지도<br /><br />
<img src="/../images/2024-02-06-004/네이버지도.png" alt="navermap" style="zoom:60%;" />
<br /><br /></p>
  </li>
  <li>
    <p>카카오맵<br /><br />
<img src="/../images/2024-02-06-004/카카오맵.png" alt="kakaomap" style="zoom:64%;" />
<br /><br /></p>
  </li>
  <li>
    <p>구글맵<br /><br />
<img src="/../images/2024-02-06-004/구글맵.png" alt="googlemap" style="zoom:60%;" />
<br /><br /></p>
  </li>
</ul>

<p>동국대학교를 한 달이라도 다녀본 학생이라면 이 3개의 지도는 캠퍼스맵으로는 정말 쓸모가 없다는 사실을 알 수 있다.</p>

<p>네이버 지도와 구글맵은 차량이 이동 가능한 경로만 표시되어있고<br />
카카오맵은 그것보다는 조금 낫지만 여전히 너무나 많은 경로가 표시되어있지 않다.<br /></p>

<p>따라서 우리 팀은 지도 API의 기본 기능 구현뿐만 아니라 지도 이미지 마저 만들어야한다는 절망적인 상황에 놓였다.<br />
(존경합니다 지도 앱 제작자 여러분들…)</p>

<p>그래도 카카오맵의 지도가 그 중 제일 나았기 때문에 우리 팀은 카카오맵의 지도를 캡쳐해서 태블릿에 켜두고<br />
학교 구석구석을 다니며 추가해야할 길을 표시했다.<br /></p>

<ul>
  <li>당시 표시 내용 캡처<br /><br />
<img src="/../images/2024-02-06-004/route.jpg" alt="route" style="zoom:40%;" />
<br /><br /></li>
</ul>

<p>그나마 카카오맵의 지도가 깔끔하고 표시된 길도 많았기 때문에<br />
카카오맵의 지도를 일반적인 스마트폰 비율에 맞게 캡쳐한 후 (<a href="https://www.goohwan.net/entry/information">[큰 지도 캡처(점아저씨의 까칠한 하루)]</a>)<br />
그림판을 이용해 태블릿에 표시한 길을 한땀한땀 그렸다.(<em><del>포토샵이 뭐죠</del></em>)<br /></p>

<p>아래는 그 결과 완성된 동국대학교의 지도이다.</p>

<ul>
  <li>완성된 동국대학교 지도(실제 DU벅이에 적용 중)<br /><br />
<img src="/../images/2024-02-06-004/du.png" alt="du" style="zoom:20%;" />
<br /><br /></li>
</ul>

<p>처음에는 줌, 드래그 기능을 생각해서 더 큰 크기의 지도를 사용하고자 했었지만<br />
실제 적용해본 결과 이미지가 커질수록 용량이 커져서 로드하는 시간이 너무 오래걸려<br />
최종적으로 3000 x 5333 픽셀 크기의 이미지를 사용하게 되었다.</p>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[지도 제작에 대한 고민]]></summary></entry><entry><title type="html">[DU벅이] 프레임워크 선정 - Flutter</title><link href="https://returnrudi.github.io/dubeogi/003/" rel="alternate" type="text/html" title="[DU벅이] 프레임워크 선정 - Flutter" /><published>2024-02-04T00:00:00+09:00</published><updated>2024-02-04T00:00:00+09:00</updated><id>https://returnrudi.github.io/dubeogi/003</id><content type="html" xml:base="https://returnrudi.github.io/dubeogi/003/"><![CDATA[<h2 id="프레임워크-선정"><span style="color: #008000">프레임워크 선정</span></h2>
<p>캠퍼스맵 어플리케이션을 개발하기로 정하고 나서 제일 먼저 고민한 것은 ‘어떤 어플리케이션 프레임워크를 사용할 것인가?’ 이다.<br />
3학년 때 전공 과목 ‘모바일 소프트웨어’를 수강하면서 식단관리 앱을 개발했을 때는 자바를 이용했었는데<br />
배포가 목적인 DU벅이의 경우 자바를 이용하면 안드로이드 유저만 사용 가능하다는 점이 마음에 걸렸다.<br />
거의 절반 혹은 그 이상의 학생들이 아이폰을 사용하기 때문에 자연스럽게 크로스 플랫폼 앱 개발 프레임워크에 관심이 갔고<br />
그 결과 Flutter를 사용하기로 했다.</p>

<h2 id="flutter"><span style="color: #008000">Flutter</span></h2>
<p><br />
<img src="/../images/2024-02-04-003/flutter.png" alt="flutter" style="zoom:40%;" /></p>

<p><br />
Flutter는 Google에서 개발한 어플리케이션 개발 프레임워크이며<br />
총 6가지(iOS, Android, 웹, Windows, MacOS, Linux) 플랫폼에서 동작하는 앱을 개발할 수 있다.</p>

<p>멀티 플랫폼에서 동작하는 앱을 위해 구글이 디자인한 Dart라는 프로그래밍 언어를 사용한다.<br />
Dart는 기본적으로 C언어의 문법과 거의 같은 수준이며 기존 프로그래밍 언어들의 특징들을 많이 가지고 있다.<br />
이러한 점 때문에 다른 언어를 경험해본 사람이라면 정말 쉽게 접할 수 있다는 장점이 있다.</p>

<p>또한 ‘Hot Reload’라는 기능을 제공하여 코드를 수정하면서 실시간으로 앱을 테스트하는 것이 가능하다.<br />
네이티브 앱을 개발할 때처럼 어플리케이션의 크기가 커질수록 기하급수적으로 증가하는 빌드 시간을 거치지 않고<br />
변경사항을 즉각적으로 확인하는 것이 가능하여 빠른 개발 주기를 제공한다.</p>

<p>즉 Flutter는 매우 개발자 친화적인 프레임워크라고 볼 수 있다.</p>]]></content><author><name>ReturnRudi</name></author><category term="dubeogi" /><category term="flutter" /><category term="dart" /><summary type="html"><![CDATA[크로스 플랫폼 앱 개발 프레임워크 Flutter]]></summary></entry><entry><title type="html">시간복잡도 계산</title><link href="https://returnrudi.github.io/strategy/time/" rel="alternate" type="text/html" title="시간복잡도 계산" /><published>2024-01-08T00:00:00+09:00</published><updated>2024-01-08T00:00:00+09:00</updated><id>https://returnrudi.github.io/strategy/time</id><content type="html" xml:base="https://returnrudi.github.io/strategy/time/"><![CDATA[<p><br /></p>
<h1 id="시간복잡도"><span style="color: #008000">시간복잡도</span></h1>

<p>코딩테스트에 나오는 문제는 항상 <strong>시간 제한</strong>과 <strong>메모리 제한</strong>이 존재한다.<br />
이 중 시간 제한을 만족시키기 위해서는 <strong>시간복잡도</strong>라는 개념을 알아야 한다.</p>

<p>시간복잡도란 <strong>입력값과 연산 수행 시간의 상관 관계를 나타내는 척도</strong>이다.</p>

<p>알고리즘 문제에서 시간이라는 것은 사용자가 작성한 코드 외에도 너무나 많은 요소에 영향을 받는다.<br />
따라서 절대적인 시간을 측정하기보다 <strong>주요 로직의 반복 횟수</strong>를 통해 대략적인 시간을 예측할 수 있어야 한다.</p>

<p>아래는 예시코드이다.</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">n</span><span class="p">;</span>

	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>				<span class="c1">//10번 반복</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>			<span class="c1">// n번 반복</span>
			<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>		<span class="c1">// n번 반복</span>
				<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"hello world"</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>	<span class="c1">// 1</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>				<span class="c1">// n번 반복</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"i"</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>				
	<span class="p">}</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>얼마나 반복되는지를 통해서 시간복잡도를 계산할 수 있다.<br />
반복문이 위와 같이 단순히 중첩되면 곱하고, 나열되어 있으면 더하면 된다.</p>

<p>따라서 예시 코드의 시간복잡도는 $10n^2 + n$ 이 된다.</p>

<h2 id="-빅오-표기법big-o-notation"><span style="color: #008000">🔎 빅오 표기법(Big-O notation)</span></h2>

<p>빅오 표기법이란 복잡도에 가장 영향을 많이 끼치는 항만을 계수를 떼어내고 나타내는 표기법이다.</p>

<p>위의 예시 코드처럼 시간복잡도가 $10n^2 + n$ 이라면<br />
빅오 표기법으로는 가장 영향을 많이 끼치는 항만을($10n^2$) 계수를 떼어내고($n^2$) 나타내 $O(n^2)$ 으로 표기된다.</p>

<p>영향을 가장 많이 끼치는 정도는 아래의 Big-O 복잡도 차트를 이용해 구분할 수 있다.</p>

<p><img src="/../../../images/2024-01-08-time/big-o-1704800162473-2.webp" alt="big-o" /></p>

<p>차트에 따라    $n!$    &gt;   $2^n$    &gt;    $n^2$    &gt;    $n\log{n}$    &gt;    $n$    &gt;    $\log{n}$    &gt;    $1$    순서로 영향이 큰 항만을 계수 없이 표기하면 된다.</p>

<p>(여기서 $\log{n}$은 보통 $\log_{2}{n}$를 뜻한다.)</p>

<p>코딩테스트 문제에서 빅오표기법을 통해 시간 제한을 맞추기 위해서는 위의 순서를 외우는 것이 필수적이다.</p>

<p>$3^n$, $4^n$, $5^n$, …, $n^3$, $n^4$, $n^5$, … 과 같은 알고리즘은 사실상 마주하기가 힘들기 때문에 위의 차트에서 고려되지 않는다.</p>

<h3 id="입력값이-여러-개인-경우"><span style="color: #008000">입력값이 여러 개인 경우</span></h3>

<p>시간복잡도 및 빅오 표기법을 처음 접하면 이러한 의문점이 생긴다.<br />
‘대부분 예시에서는 n을 이용해서 표기하던데 입력값이 여러 개인 경우에는 어떻게 표시할까?’</p>

<p>아래의 예시와 같은 경우이다.</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">;</span>

	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">7</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>				<span class="c1">// 7번 반복</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>			<span class="c1">// n번 반복</span>
			<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>		<span class="c1">// n번 반복</span>
				<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"ReturnRudi"</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>	<span class="c1">// 1</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">m</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>				<span class="c1">// m번 반복</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"ReturnRudi"</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>			<span class="c1">// 1</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>이러한 부분이 헷갈린다면 시간복잡도의 개념을 다시 한 번 생각해보면 된다.</p>

<p>시간복잡도란 입력값과 연산 수행 시간의 상관 관계를 구하는 것이고<br />
이를 통해서 대략적인 처리 시간을 계산하는 것에 목적이 있다.<br /></p>

<p>따라서 위의 예시의 n과 m 은 시간적인 측면에서 상수가 아닌 <strong>변수</strong>가 된다.</p>

<p>즉 단순히 시간복잡도를 $7n^2 + m$과 같이 표시하면 되고<br />
빅오 표기법으로 표기하면 $O(n^2 + m)$이 된다.</p>

<h3 id="각-요소의-예시"><span style="color: #008000">각 요소의 예시</span></h3>
<p>일반적으로 잘 알려진 각 요소들의 예시는 아래와 같다.</p>

<p>$O(1)$: 입력(cin, scanf), 출력(cout, printf), 연산( $+, -, *,$ /, %, … )<br />
           간단한 비교 if문( if( a == 1 ) ), 배열의 인덱스 참조( a[1] = 3; )등 …<br /></p>

<p>$O(\log{n})$: 이진트리, …</p>

<p>$O(n)$: for문(반복문), 정렬되지 않은 배열에서 특정 값 검색…</p>

<p>$O(n\log{n})$: 퀵 정렬, 병합 정렬, 힙 정렬, …</p>

<p>$O(n^2)$: 중첩 for문(반복문), 삽입 정렬, 버블 정렬, 선택 정렬, …</p>

<p>$O(2^n)$: 피보나치 수열, …</p>

<p>$O(n!)$: 완전 탐색, …</p>

<h2 id="-시간복잡도-문제-적용"><span style="color: #008000">🔎 시간복잡도 문제 적용</span></h2>

<p>위의 정보를 바탕으로 시간복잡도를 코딩테스트 문제에 적용해보자.</p>

<p>대부분의 알고리즘 문제는 시간 제한을 ‘$n$ 초’ 와 같이 제시해준다.<br />
알고리즘 문제에서 시간이 많은 요소에 영향을 받는다고는 하지만 보통 대략적으로 1초에 1억줄의 코드를 처리할 수 있다.</p>

<p>이를 바탕으로 빅오표기법을 통해 대략적인 최대 입력 크기를 계산할 수 있다.</p>

<p>$O(n)$: 약 1억</p>

<p>$O(n^2)$: 약 1만 ( $10,000^2 = 100,000,000$ )</p>

<p>$O(n^3)$: 약 500 ( $500^3 = 125,000,000$ )</p>

<p>$O(2^n)$: 약 20	( $2^20 = 1,048,576$ )</p>

<p>$O(n!)$: 약 10	( $10! = 3,628,800$)</p>

<p>이와 같이 보통 외우기 쉽게 단위가 떨어지게 계산해두고 적용한다.</p>

<p>예를 들어 문제의 시간 제한이 1초 일 때<br />
입력값인 n의 크기가 0 ~ 10,000으로 제시되어있다면<br />
$O(n^2)$ 보다 큰 시간복잡도 풀이는 고려하지 않아야 한다.<br /></p>

<p>또한 $O(2^n)$, $O(n!)$의 경우 숫자가 커지는 속도가 너무 빠르므로<br />
$2^{26} = 67,108,864$ 이나 $11! = 39,916,800$ 와 같이 1억으로부터 여유가 있어도<br />
위의 기준을 이미 초과했다면 다른 풀이를 생각해보는 것이 좋다.</p>

<p>시간복잡도를 계산할 때는 정석대로 한다면 입력크기 n에 대한 <strong>점화식</strong>을 완성해야 한다.<br />
하지만 너무 복잡한 경우가 아니라면 cnt 변수를 이용해서 시간복잡도 식을 유추하는 것이 빠르다.<br /></p>

<p>ex) cnt는 함수가 호출될 때마다 ++<br />
  n = 1 → cnt = 1          → 1<br />
  n = 2 → cnt = 3         → 1 + 2<br />
  n = 3 → cnt = 7         → 1 + 2 + 4<br />
  n = 4 → cnt = 15       → 1 + 2 + 4 + 8<br /></p>

<p>  n은 등비수열의 합이구나! 유추</p>

<p>아래는 자주나오는 <strong>등차수열</strong>과 <strong>등비수열</strong>의 <strong>합</strong>을 구하는 공식이다.</p>

<p><strong>등차수열의 합(첫째항이 a, 공차가 d인 경우)</strong></p>

<p>$S_n = \frac{n \{2 a + (n-1)d \} }{2}$</p>

<p><strong>등비수열의 합(첫째항이 a, 공차가 r인 경우)</strong></p>

<p>$S_n = \frac{a(r^n - 1)}{r-1}$</p>]]></content><author><name>ReturnRudi</name></author><category term="strategy" /><category term="cpp" /><summary type="html"><![CDATA[시간복잡도 계산]]></summary></entry><entry><title type="html">조합(Combination) 재귀함수 및 반복문 구현</title><link href="https://returnrudi.github.io/function/comb/" rel="alternate" type="text/html" title="조합(Combination) 재귀함수 및 반복문 구현" /><published>2024-01-07T00:00:00+09:00</published><updated>2024-01-07T00:00:00+09:00</updated><id>https://returnrudi.github.io/function/comb</id><content type="html" xml:base="https://returnrudi.github.io/function/comb/"><![CDATA[<p><br /></p>
<h1 id="조합"><span style="color: #008000">조합</span></h1>

<p>조합이란 유한 개의 원소에서 주어진 수만큼의 원소들을 고르는 방법을 말한다.<br />
n개 중에서 순서에 상관없이 r개를 뽑는 경우에 사용한다.</p>

<p>경우의 수를 구하는 공식은 아래와 같다.</p>

<p>       $_nC_r = \frac{n!}{r!(n - r)!}$</p>

<h2 id="-반복문을-이용한-구현"><span style="color: #008000">🔎 반복문을 이용한 구현</span></h2>

<p>중복을 허용하지 않고 순서에 상관이 없으므로 중첩 for문을 통해 쉽게 구현이 가능하다.</p>

<h3 id="코드-구현"><span style="color: #008000">코드 구현</span></h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">k</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
				<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span> <span class="o">&lt;&lt;</span> <span class="n">j</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span> <span class="o">&lt;&lt;</span> <span class="n">k</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="실행-결과"><span style="color: #008000">실행 결과</span></h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
</code></pre></div></div>

<h2 id="-재귀함수를-이용한-구현"><span style="color: #008000">🔎 재귀함수를 이용한 구현</span></h2>

<p>재귀함수를 이용해서도 조합을 구현해 낼 수 있다.</p>

<h3 id="구현-원리"><span style="color: #008000">구현 원리</span></h3>

<p>사실상 중첩 for문과 크게 다른 점이 없다.<br />
앞 자리부터 하나씩 반복문을 통해 순서대로 벡터에 넣으면서<br />
그 다음 자리부터 재귀함수를 호출하고<br />
벡터의 크기가 r이 되면 리턴한다<br />
리턴 후에는 벡터에 넣었던 함수를 다시 뺀다.</p>

<h3 id="코드-구현-1"><span style="color: #008000">코드 구현</span></h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">combi</span><span class="p">(</span><span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">==</span> <span class="n">r</span><span class="p">)</span> <span class="p">{</span>
		<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">i</span> <span class="o">:</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
		<span class="k">return</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">a</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
		<span class="n">combi</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="p">);</span>
		<span class="n">a</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
	<span class="p">}</span>
	<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">b</span><span class="p">;</span>
	<span class="n">combi</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="실행-결과-1"><span style="color: #008000">실행 결과</span></h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
</code></pre></div></div>]]></content><author><name>ReturnRudi</name></author><category term="function" /><category term="cpp" /><summary type="html"><![CDATA[조합(Combination) 재귀함수 및 반복문 구현]]></summary></entry><entry><title type="html">순열 함수 next_permutation(), prev_permutation() 및 재귀함수 구현</title><link href="https://returnrudi.github.io/function/permutation/" rel="alternate" type="text/html" title="순열 함수 next_permutation(), prev_permutation() 및 재귀함수 구현" /><published>2024-01-05T00:00:00+09:00</published><updated>2024-01-05T00:00:00+09:00</updated><id>https://returnrudi.github.io/function/permutation</id><content type="html" xml:base="https://returnrudi.github.io/function/permutation/"><![CDATA[<p><br /></p>
<h1 id="순열"><span style="color: #008000">순열</span></h1>
<p>순열이란 순서가 정해진 임의의 집합을 다른 순서로 섞는 연산을 말한다.<br />
n개 중에서 r개를 뽑아 나열하는 경우에 사용한다.</p>

<p>경우의 수를 구하는 공식은 아래와 같다.</p>

<p>　　　$_nP_r = \frac{n!}{(n - r)!}$</p>

<h2 id="-next_permutation-prev_permutation"><span style="color: #008000">🔎 next_permutation(), prev_permutation()</span></h2>

<p>C++에서는 순열을 수행하는 next_permutation(), prev_permutation() 함수가 존재한다.</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span><span class="err"> </span><span class="n">next_permutation</span><span class="err"> </span><span class="p">(</span><span class="n">BidirectionalIterator</span><span class="err"> </span><span class="n">first</span><span class="p">,</span> <span class="n">BidirectionalIterator</span><span class="err"> </span><span class="n">last</span><span class="p">);</span>
<span class="kt">bool</span><span class="err"> </span><span class="n">prev_permutation</span><span class="err"> </span><span class="p">(</span><span class="n">BidirectionalIterator</span><span class="err"> </span><span class="n">first</span><span class="p">,</span> <span class="n">BidirectionalIterator</span><span class="err"> </span><span class="n">last</span><span class="p">);</span>
</code></pre></div></div>

<p><strong>next_permutation()</strong>: <strong>오름차순</strong>의 배열을 기반으로 순열을 수행하는 함수<br />
<strong>prev_permutation()</strong>: <strong>내림차순</strong>의 배열을 기반으로 순열을 수행하는 함수</p>

<p>[first, last) 범위의 요소들로 순열을 진행한다.</p>

<p>두 함수는 다음 순서가 존재하면 true를 반환하고 다음 순서가 없다면 false를 반환한다.<br />
따라서 while문을 이용해서 순열을 진행할 수 있다.</p>

<h3 id="코드-구현"><span style="color: #008000">코드 구현</span></h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a</span><span class="p">{</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span> <span class="p">};</span>

    <span class="c1">//next_permutation</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"next_permutation</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">sort</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>

    <span class="k">do</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">:</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">next_permutation</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">()));</span>
    
    <span class="c1">//prev_permutation</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">prev_permutation</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">sort</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">greater</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">());</span>
    <span class="k">do</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">:</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">prev_permutation</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">()));</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="실행-결과"><span style="color: #008000">실행 결과</span></h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>next_permutation
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

prev_permutation
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
</code></pre></div></div>

<h2 id="-재귀를-이용한-순열"><span style="color: #008000">🔎 재귀를 이용한 순열</span></h2>

<p>next_permutation(), prev_permutation() 함수를 이용하지 않고 재귀 함수로도 구현이 가능하다.</p>

<h3 id="구현-원리"><span style="color: #008000">구현 원리</span></h3>

<ol>
  <li>현재 위치가 배열의 크기보다 크면 출력하고 리턴한다.</li>
  <li>현재 위치부터 배열의 끝까지 순서대로 현재 위치와 자리를 바꾼 후 현재 위치에 고정한다.</li>
  <li>다음 위치를 매개변수로 넣어 재귀로 함수를 호출한다.</li>
  <li>2에서 고정했던 숫자의 고정을 풀고 바꿨던 자리를 원위치 시킨다.</li>
</ol>

<p>1은 재귀함수의 탈출 조건(기저 사례)이며<br />
2 ~ 4에서 현재 위치부터 배열의 끝까지 반복문 및 재귀함수 호출이 진행된다.<br /></p>

<p>간단하게 이해할 수 있도록 말로 설명하자면 모든 자리의 숫자를 고정시켜서 출력하는 것이 목표이며<br />
이를 위해 앞에서부터 고정되지 않은 숫자들을 순서대로 자리를 바꿔가며 고정시키는 일련의 과정이다.<br />
최하단의 접어둔 디버깅 코드를 보면 더 쉽게 이해가 가능하다.</p>

<h3 id="사용-예시"><span style="color: #008000">사용 예시</span></h3>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span> <span class="p">};</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>

<span class="kt">void</span> <span class="n">permutation</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">r</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
            <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">position</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">position</span><span class="p">]);</span>
        <span class="n">permutation</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">position</span><span class="p">]);</span>
    <span class="p">}</span>
    <span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">permutation</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="실행-결과-1"><span style="color: #008000">실행 결과</span></h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2
</code></pre></div></div>
<p><br /></p>

<details>
<summary> <span style="color: #008000">디버깅 코드 접기/펼치기</span></summary>
<div>

    <h3 id="section"><span style="color: #008000">이해를 돕기 위한 디버깅 코드</span></h3>

    <p>디버깅 코드에서 배열의 자리를 나타낼 때 사용한 ‘N번째’ 라는 표현은 0번째 부터가 아닌 1번째 부터다.</p>

    <p>즉 int a[3] = { 100, 200, 300 }; 에서<br />
1번째 = 100<br />
2번째 = 200<br />
3번째 = 300<br /></p>

    <p>재귀함수이므로 좀 더 단계가 직관적으로 보이도록 단계별로 간격을 맞춰서 작성했다.</p>

    <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">200</span><span class="p">,</span> <span class="mi">300</span> <span class="p">};</span>
<span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span> <span class="c1">//n은 뽑을 수 있는 요소의 개수  //총 뽑을(고정할) 개수</span>

<span class="kt">void</span> <span class="n">st</span><span class="p">(</span><span class="kt">int</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">position</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"  "</span><span class="p">;</span>

	<span class="k">if</span> <span class="p">(</span><span class="n">position</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"- [고정된 위치 없음] "</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="k">else</span> <span class="p">{</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"- ["</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">&lt;&lt;</span> <span class="s">"번째까지 고정] "</span><span class="p">;</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">makePermutation</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>  <span class="c1">//position은 현재 고정할 위치</span>
	<span class="k">if</span> <span class="p">(</span><span class="n">r</span> <span class="o">==</span> <span class="n">position</span><span class="p">)</span> <span class="p">{</span>  <span class="c1">//position은 0부터 시작이므로 r == position이라는 것은 이미 r만큼 고정되었다는 의미 -&gt; 리턴</span>
		<span class="n">st</span><span class="p">(</span><span class="n">position</span><span class="p">);</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째는 없으므로 출력 후 리턴한다.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
		<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">r</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
			<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">" "</span><span class="p">;</span>
		<span class="p">}</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
		<span class="k">return</span><span class="p">;</span>
	<span class="p">}</span>
	<span class="n">st</span><span class="p">(</span><span class="n">position</span><span class="p">);</span>
	<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째부터 "</span> <span class="o">&lt;&lt;</span> <span class="n">n</span> <span class="o">&lt;&lt;</span> <span class="s">"번째까지 고정 시작</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
	<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">position</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
		<span class="n">st</span><span class="p">(</span><span class="n">position</span><span class="p">);</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째와 "</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째를 바꾸고 "</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째에 "</span> <span class="o">&lt;&lt;</span> <span class="n">a</span><span class="p">[</span><span class="n">position</span><span class="p">]</span> <span class="o">&lt;&lt;</span> <span class="s">"를 고정한다</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
		<span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">position</span><span class="p">]);</span>
		<span class="n">makePermutation</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
		<span class="n">st</span><span class="p">(</span><span class="n">position</span><span class="p">);</span>
		<span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째와 "</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째를 다시 바꾸고 "</span> <span class="o">&lt;&lt;</span> <span class="n">position</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="s">"번째에 고정을 푼다</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
		<span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">position</span><span class="p">]);</span>
	<span class="p">}</span>
	<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="n">makePermutation</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">r</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
	<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div>    </div>

    <h3 id="section-1"><span style="color: #008000">디버깅 코드 실행 결과</span></h3>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- <span class="o">[</span>고정된 위치 없음] 1번째부터 3번째까지 고정 시작
- <span class="o">[</span>고정된 위치 없음] 1번째와 1번째를 바꾸고 1번째에 100를 고정한다
  - <span class="o">[</span>1번째까지 고정] 2번째부터 3번째까지 고정 시작
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 바꾸고 2번째에 200를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 300를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
100 200 300
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 3번째를 바꾸고 2번째에 200를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 200를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
100 300 200
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 3번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
- <span class="o">[</span>고정된 위치 없음] 1번째와 1번째를 다시 바꾸고 1번째에 고정을 푼다
- <span class="o">[</span>고정된 위치 없음] 1번째와 2번째를 바꾸고 1번째에 100를 고정한다
  - <span class="o">[</span>1번째까지 고정] 2번째부터 3번째까지 고정 시작
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 바꾸고 2번째에 100를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 300를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
200 100 300
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 3번째를 바꾸고 2번째에 100를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 100를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
200 300 100
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 3번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
- <span class="o">[</span>고정된 위치 없음] 2번째와 1번째를 다시 바꾸고 1번째에 고정을 푼다
- <span class="o">[</span>고정된 위치 없음] 1번째와 3번째를 바꾸고 1번째에 100를 고정한다
  - <span class="o">[</span>1번째까지 고정] 2번째부터 3번째까지 고정 시작
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 바꾸고 2번째에 200를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 100를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
300 200 100
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 2번째와 3번째를 바꾸고 2번째에 200를 고정한다
    - <span class="o">[</span>2번째까지 고정] 3번째부터 3번째까지 고정 시작
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 바꾸고 3번째에 200를 고정한다
      - <span class="o">[</span>3번째까지 고정] 4번째는 없으므로 출력 후 리턴한다.
300 100 200
    - <span class="o">[</span>2번째까지 고정] 3번째와 3번째를 다시 바꾸고 3번째에 고정을 푼다
  - <span class="o">[</span>1번째까지 고정] 3번째와 2번째를 다시 바꾸고 2번째에 고정을 푼다
- <span class="o">[</span>고정된 위치 없음] 3번째와 1번째를 다시 바꾸고 1번째에 고정을 푼다
</code></pre></div>    </div>
  </div>
</details>]]></content><author><name>ReturnRudi</name></author><category term="function" /><category term="cpp" /><summary type="html"><![CDATA[순열 함수 next_permutation(), prev_permutation() 및 재귀함수 구현]]></summary></entry><entry><title type="html">accumulate(), max_element(), min_element()</title><link href="https://returnrudi.github.io/function/amm/" rel="alternate" type="text/html" title="accumulate(), max_element(), min_element()" /><published>2024-01-04T00:00:00+09:00</published><updated>2024-01-04T00:00:00+09:00</updated><id>https://returnrudi.github.io/function/amm</id><content type="html" xml:base="https://returnrudi.github.io/function/amm/"><![CDATA[<p><br /></p>
<h2 id="-accumulate"><span style="color: #008000">🔎 accumulate()</span></h2>
<p><strong>배열의 합</strong>을 구해주는 함수이다.</p>

<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">InputIt</span><span class="p">,</span> <span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="n">T</span> <span class="nf">accumulate</span><span class="p">(</span><span class="n">InputIt</span> <span class="n">first</span><span class="p">,</span> <span class="n">InputIt</span> <span class="n">last</span><span class="p">,</span> <span class="n">T</span> <span class="n">init</span><span class="p">);</span>
</code></pre></div></div>

<p>배열 내 [first,last) 범위에 있는 요소들의 합을 구한다.<br />
init: 누적의 시작값 → 보통 0으로 설정</p>

<h3 id="사용-예시"><span style="color: #008000">사용 예시</span></h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span> <span class="p">};</span>
    <span class="kt">int</span> <span class="n">b</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span> <span class="p">};</span>

    <span class="c1">//vector</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"vector의 합은 "</span> <span class="o">&lt;&lt;</span> <span class="n">accumulate</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"init이 100이라면 vector의 합은 "</span> <span class="o">&lt;&lt;</span> <span class="n">accumulate</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">100</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n\n</span><span class="s">"</span><span class="p">;</span>
    <span class="c1">//Array</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"배열의 합은 "</span> <span class="o">&lt;&lt;</span> <span class="n">accumulate</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">b</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"init이 100이라면 배열의 합은 "</span> <span class="o">&lt;&lt;</span> <span class="n">accumulate</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">b</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">),</span> <span class="mi">100</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="출력-결과"><span style="color: #008000">출력 결과</span></h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vector의 합은 55
init이 100이라면 vector의 합은 155

배열의 합은 55
init이 100이라면 배열의 합은 155
</code></pre></div></div>

<h2 id="-max_element-min_element"><span style="color: #008000">🔎 max_element(), min_element()</span></h2>
<p><strong>max_element()</strong>: 배열 내의 가장 <strong>큰</strong> 요소를 찾는 함수<br />
<strong>min_element()</strong>: 배열 내의 가장 <strong>작은</strong> 요소를 찾는 함수</p>

<p>해당 요소가 존재하는 <strong>이터레이터를 반환</strong>하며 같은 값이 2개 이상 존재할 경우<br />
<strong>가장 앞</strong>에 있는 이터레이터를 반환한다.</p>

<p>이터레이터를 반환하므로 해당 값을 사용하고 싶은 경우 <strong>역참조(*)</strong>를 사용하면 된다.</p>

<h3 id="사용-예시-1"><span style="color: #008000">사용 예시</span></h3>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a</span> <span class="p">{</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">8</span> <span class="p">};</span>

    <span class="k">auto</span> <span class="n">max</span> <span class="o">=</span> <span class="n">max_element</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"가장 큰 요소는 "</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">max</span> <span class="o">&lt;&lt;</span> <span class="s">"이며 "</span> <span class="o">&lt;&lt;</span> <span class="n">max</span> <span class="o">-</span> <span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"번째 인덱스에 존재한다.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="k">auto</span> <span class="n">min</span> <span class="o">=</span> <span class="n">min_element</span><span class="p">(</span><span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">a</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"가장 작은 요소는 "</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">min</span> <span class="o">&lt;&lt;</span> <span class="s">"이며 "</span> <span class="o">&lt;&lt;</span> <span class="n">min</span> <span class="o">-</span> <span class="n">a</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">"번째 인덱스에 존재한다.</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>

    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<h3 id="출력-결과-1"><span style="color: #008000">출력 결과</span></h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>가장 큰 요소는 8이며 4번째 인덱스에 존재한다.
가장 작은 요소는 1이며 1번째 인덱스에 존재한다.
</code></pre></div></div>]]></content><author><name>ReturnRudi</name></author><category term="function" /><category term="cpp" /><summary type="html"><![CDATA[배열의 합, 배열에서 가장 큰/작은 요소를 알려주는 함수]]></summary></entry></feed>