업데이트(2018.03.14): 함수 사용법을 분리하여 조금 더 상세하게 작성하였습니다.

C++에서 next_permutation 함수 혹은 prev_permutation 함수를 통해서 순열을 구해보는 방법


환경 및 선수조건

  • C++ 및 STL의 사용법(iterator)


함수

STL에 algorithm 헤더파일을 추가하면(#include <algorithm>) 다음 아래 함수를 통해서 순열을 구할수가 있다.

함수에 벡터iterator 혹은 배열의 주소를 넣으면 다음 순열(1-2-3-4의 다음 순열은 1-2-4-3) 혹은 이전 순열(1-2-4-3의 이전 순열은 1-2-3-4)의 결과가 벡터나 배열에 적용된다.

  • next_permutation: 현재 나와 있는 수열에서 인자로 넘어간 범위에 해당하는 다음 순열을 구하고 true를 반환한다. 다음 순열이 없다면(다음에 나온 순열이 순서상 이전 순열보다 작다면) false를 반환.
  • prev_permutation: 현재 나와 있는 수열에서 인자로 넘어간 범위에 해당하는 이전 순열을 구하고 true를 반환한다. 이전 순열이 없다면(다음에 나온 순열이 순서상 이전 순열보다 크다면) false를 반환.


next_permutation 함수

기본 구조


// 첫번째 인자가 구하고자 하는 순열의 시작, 두번째 인자가 순열의 끝
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last);

// 아래처럼 직접 비교함수를 넣어줘도 됩니다.
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, Compare comp);


사용법

순열을 구하고 싶은 1-2-3-4의 배열이 있다고 가정을 하면 next_permutation의 함수를 사용하면 배열의 값들이 다음 순열인1-2-4-3로 바뀌고 함수는 true를 반환합니다.


구현 코드

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){

	// 1부터 4까지 저장할 벡터 선언
	// 배열도 가능!
	vector<int> v(4);

	// 1부터 4까지 벡터에 저장
	for(int i=0; i<4; i++){
		v[i] = i+1;
	}

	// next_permutation을 통해서 다음 순열 구하기
	do{

		for(int i=0; i<4; i++){
			cout << v[i] << " ";
		}

		cout << '\n';

	}while(next_permutation(v.begin(),v.end()));

	return 0;

}


구현 결과

1 2 3 4
1 2 4 3
1 3 2 4

...

4 2 3 1
4 3 1 2
4 3 2 1


prev_permutation 함수

기본 구조


// 첫번째 인자가 구하고자 하는 순열의 시작, 두번째 인자가 순열의 끝
bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last);

// 아래처럼 직접 비교함수를 넣어줘도 됩니다.
bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last, Compare comp);


사용법

순열을 구하고 싶은 4-3-2-1의 배열이 있다고 가정을 하면 prev_permutation의 함수를 사용하면 배열의 값들이 다음 순열인4-3-1-2로 바뀌고 함수는 true를 반환합니다.


구현 코드

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){

	// 1부터 4까지 저장할 벡터 선언
	// 배열도 가능!
	vector<int> v(4);

	// 4부터 1까지 벡터에 저장
	for(int i=0; i<4; i++){
		v[i] = 4-i;
	}

	// prev_permutation을 통해서 이전 순열 구하기
	do{

		for(int i=0; i<4; i++){
			cout << v[i] << " ";
		}

		cout << '\n';

	}while(prev_permutation(v.begin(),v.end()));

	return 0;

}


구현 결과

4 3 2 1
4 3 1 2
4 2 3 1

...

1 3 2 4
1 2 4 3
1 2 3 4


참고자료

clipboard.js를 이용해 웹에서 클립보드에 내용을 복사해보자

내용은 공식문서를 참고하여 제작하였습니다.


환경 및 선수조건

  • HTML, CSS, Javascript에 대한 기본 이해


설치

npm을 통한 설치 or 다운로드를 통해서 설치합니다.

$ npm install clipboard --save

파일 링크: https://github.com/zenorocha/clipboard.js/archive/master.zip

설치를 하지 않고 html에 cdn을 통한 링크를 이용해서도 사용이 가능합니다:) 즉, 굳이 설치하고 싶지 않으신 분들은 상관이 없습니다.


셋업

js파일 첨부

파일이 아니라 cdn을 통해서 링크를 첨부하고 싶다면 아래 방법처럼 사용하면 됩니다. 저는 아래 방법을 사용하였으며 링크는 다음과 같습니다(CDN Link)

<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>

위에서 받은 파일을 통한 설치는 아래와 같으며(파일의 경로로 해줘야 합니다.)

<script src="dist/clipboard.min.js"></script>


Clipboard 객체 생성

자바스크립트 코드 안에 다음 아래 코드처럼 객체를 생성해야합니다.

생성을 할 때 인자로는 이벤트를 발생시키고자 하는 HTML 태그를 DOM selector,HTML element 또는 HTML element들의 list 형태로 넘겨줘야합니다. 아래 예제들은 clipboard.js에 있는 예시들 3개와 제일 아래는 제가 적용한 예제입니다.

class 지정을 통한 예제

<body>
    <!-- 1. Define some markup -->
    <button class="btn" data-clipboard-text="1">Copy</button>
    <button class="btn" data-clipboard-text="2">Copy</button>
    <button class="btn" data-clipboard-text="3">Copy</button>

    <!-- 2. Include library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>

    <!-- 3. Instantiate clipboard by passing a string selector -->
    <script>
    var clipboard = new Clipboard('.btn');
    clipboard.on('success', function(e) {
        console.log(e);
    });
    clipboard.on('error', function(e) {
        console.log(e);
    });
    </script>
</body>

id 지정을 통한 예제

<body>
    <!-- 1. Define some markup -->
    <div id="btn" data-clipboard-text="1">
        <span>Copy</span>
    </div>

    <!-- 2. Include library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>

    <!-- 3. Instantiate clipboard by passing a HTML element -->
    <script>
    var btn = document.getElementById('btn');
    var clipboard = new Clipboard(btn);
    clipboard.on('success', function(e) {
        console.log(e);
    });
    clipboard.on('error', function(e) {
        console.log(e);
    });
    </script>
</body>

tag 지정을 통한 예제

<body>
    <!-- 1. Define some markup -->
    <button data-clipboard-text="1">Copy</button>
    <button data-clipboard-text="2">Copy</button>
    <button data-clipboard-text="3">Copy</button>

    <!-- 2. Include library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>

    <!-- 3. Instantiate clipboard by passing a list of HTML elements -->
    <script>
    var btns = document.querySelectorAll('button');
    var clipboard = new Clipboard(btns);
    clipboard.on('success', function(e) {
        console.log(e);
    });
    clipboard.on('error', function(e) {
        console.log(e);
    });
    </script>
</body>

제 경우에는 웹페이지가 로드될 때 객체를 생성하기 위해서 $(document).ready()안에다가 작성하였습니다.

<script type="text/javascript" language="javascript">
...
$(document).ready(function(){
    // 모든 이미지 tag들을 list형태로 가져옴
    var imgs = document.querySelectorAll('img');

    // 위에서 가져온 list들을 Clipboard 객체를 생성할 때 넘겨줌
    var clip = new Clipboard(imgs);

    // 클립보드에 복사가 완료되었을 때 실행할 이벤트 함수
    // 성공시
    clip.on('success', function(e) {
      console.log("Success");
      ...
    });
    // 실패시
    clipboard.on('error', function(e) {
      console.log("Error");
      ...
    });
});
...
</script>


사용법

1. data-clipboard-target을 통한 사용법

복사하고자하는 값을 가지고 있는 태그에 id를 부여하고 이벤트를 발생시키고 싶은 태그에 data-clipboard-target 속성을 설정하고 거기에 값을 앞에서 설정한 id로 지정을 해줍니다.

<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">

<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
    <img src="assets/clippy.svg" alt="Copy to clipboard">
</button>

2. data-clipboard-text을 통한 사용법

복사하고자 하는 태그를 설정할 필요없이 현재 태그에서 이벤트를 발생시키고 값도 복사하고 싶다면 아래처럼 data-clipboard-target를 이벤트를 발생시키고 싶은 태그에 넣어서 사용하시면됩니다.

<!-- Trigger -->
<button class="btn" data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
    Copy to clipboard
</button>


이벤트

위에 이미 예제에서 나와 있었지만 생성한 Clipboard 객체를 사용해서 이벤트를 작성합니다.

// 모든 이미지 tag들을 list형태로 가져옴
var imgs = document.querySelectorAll('img');

// 위에서 가져온 list들을 Clipboard 객체를 생성할 때 넘겨줌
var clip = new Clipboard(imgs);

// 클립보드에 복사가 완료되었을 때 실행할 이벤트 함수
// 성공시
clip.on('success', function(e) {
  console.log("Success");
  ...
});
// 실패시
clipboard.on('error', function(e) {
  console.log("Error");
  ...
});


예제코드

https://github.com/TWpower/clipboard.js-example/blob/master/clipboard-js-example.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>clipboard.js simple example</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>

    <!--1. clipboard.js 파일 cdn을 통해서 로드-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>

    <!--2. 스크림트 파일 작성-->
    <script>

        // 3. 웹 문서가 로드되면 클립보드 객체 생성
        $(document).ready(function(){

            var clipboard = new Clipboard('.btn');
            clipboard.on('success', function(e) {
                console.log("Success");

                /*
                아래 함수를 통해서 블록지정을 없앨 수 있습니다.
                */
                var selection = window.getSelection();
                selection.removeAllRanges();
            });
            clipboard.on('error', function(e) {
                console.log("Fail");
            });

            // 아래와 같이 button 태그만 가져오는 방법도 가능하다.
            /*
            var btns = document.querySelectorAll('button');
            var clipboard = new Clipboard(btns);
            */


        });


    </script>
</head>



<body>
    <!--data-clipboard-target 예제-->
    <input id="foo" value="This is Value">
    <button class="btn" data-clipboard-target="#foo">data-clipboard-target example</button>

    <br/>

    <!--data-clipboard-text 예제-->
    <button class="btn" data-clipboard-text="data-clipboard-text test">data-clipboard-text example</button>


</body>
</html>


참고자료

이분 탐색에서 index를 이동할 때 좌우를 어떻게 비교하면서 이동하는지 확인해보자.


환경 및 선수조건

  • C++


원리

  1. 찾고자 하는 값을 x라 하고 배열을 a라 하자.
  2. 배열의 제일 왼쪽 인덱스를 Left 제일 오른쪽 인덱스를 Right라고 하자.
  3. Middle = (Left) + (Right - Left)/2라고 하자.
  4. left <= right를 만족하면 아래를 반복한다.
  5. x > a[Middle] 이면 Left = Middle + 1를 하고 그게 아니면 Right = Middle - 1를 한다.
  6. 다시 3으로 돌아간다.


기본 코드

  • 코드
while(left <= right){

	int middle =  left + (right - left)/2;

	if(a[middle] == x){
		// 배열에서 찾고자 하는 x의 위치가 position에 저장
		positoin = middle;
		break;
	}
	else if(a[middle] > x){
		right = middle - 1;
	}

	else{
		left = middle + 1;
	}
}


예제 코드

  • 코드
#include <stdio.h>

int main (){


	// 정렬이 되어있어야함
	int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};


	int left = 0; // 제일 왼쪽 인덱스
	int right = sizeof(a)/sizeof(int); // 제일 오른쪽 인덱스
	int x = 3; // 값 3이 배열에서 위치한 인덱스를 찾고자 한다면
	int position = -1;

	while(left <= right){

		int middle =  left + (right - left)/2;

		if(a[middle] == x){
			// 배열에서 찾고자 하는 x의 위치가 position에 저장
			position = middle;
			break;
		}
		else if(a[middle] > x){
			right = middle - 1;
		}

		else{
			left = middle + 1;
		}
	}

	printf("%d\n", position);

}


참고자료

업데이트(2018.04.17): memset 함수를 사용하는 이유 및 참고자료 추가

C와 C++에서 memset 함수를 사용해보자


환경 및 선수조건

  • C, C++


목적

  • memset함수는 어떤 메모리의 시작점부터 연속된 범위를 어떤 값으로(바이트 단위) 모두 지정하고 싶을 때 사용하는 함수이다.


기본 함수 구조 및 매개변수

void * memset ( void * ptr, int value, size_t num );
  • ptr: 채우고자 하는 메모리의 시작 포인터(시작 주소)
  • value: 메모리에 채우고자하는 값. int형이지만 내부에서는 unsigned char(1 byte)로 변환되어서 저장된다.
  • num: 채우고자 하는 바이트의 수. 즉, 채우고자 하는 메모리의 크기


코드

  • 코드
#include <string.h> // string.h 파일이 필요합니다.
#include <stdio.h>

int main (){

    char a[20];

    // 1바이트마다 모두 65로 초기화
    // 배열을 채울 때는 sizeof()함수를 사용하면 됩니다.
    // sizeof 함수 - 배열의 전체 바이트 크기를 반환합니다.
    memset(a, 65, sizeof(a));

    // 출력을 통해 확인
    for(int i = 0; i < (sizeof(a)/sizeof(char)); i++){
        printf("%c\n", a[i]);
    }

}


memset 함수를 사용하는 이유

  • 대체로 memset함수는 특정 범위에 있는 연속된 메모리에 값을 지정하고 싶을 때 사용하는데 for문보다 더 빠른 속도가 나올수가 있다.
  • 여기서 나올수가 있다라고 표현한 이유는 컴파일러 그리고 컴퓨터 아키텍처에 따라서 다르기 때문이다.
  • 자세한 내용은 아래 두 참고자료를 보면 Quora에는 어셈블리 코드로 비교한게 나와있고 Stack Overflow에는 관련한 내용들이 나와있다.


참고자료

C++에서 list 사용법을 간단하게 알아보자


환경 및 선수조건

  • C++


리스트 기본 함수

iterator(반복자)

  • begin(): beginning iterator를 반환
  • end(): end iterator를 반환

추가 및 삭제

  • push_front(element): 리스트 제일 앞에 원소 추가
  • pop_front(): 리스트 제일 앞에 원소 삭제
  • push_back(element): 리스트 제일 뒤에 원소 추가
  • pop_back(): 리스트 제일 뒤에 원소 삭제
  • insert(iterator, element): iterator가 가리키는 부분 “앞”에 원소를 추가
  • erase(iterator): iterator가 가리키는 부분에 원소를 삭제

조회

  • *iterator: iterator가 가리키는 원소에 접근
  • front(): 첫번째 원소를 반환
  • back(): 마지막 원소를 반환

기타

  • empty(): 리스트가 비어있으면 true 아니면 false를 반환
  • size(): 리스트 원소들의 수를 반환


구현 코드

#include <iostream>
#include <list>

using namespace std;

int main(){

	list<int> l;


	// push_back
	l.push_back(5);
	l.push_back(6);
	l.push_back(7);
	l.push_back(8);
	l.push_back(9);
	l.push_back(10);


	// pop_back
	l.pop_back();


	// push_front
	l.push_front(4);
	l.push_front(3);
	l.push_front(1);
	l.push_front(0);


	// pop_front
	l.pop_front();


	// back and front
	cout << "list front value: " << l.front() << '\n';
	cout << "list end value: " << l.back() << '\n';


	// size
	cout << "list size: " << l.size() << '\n';


	// empty
	cout << "Is it empty?: " << (l.empty() ? "Yes" : "No") << '\n';


	// iterator
	list<int>::iterator begin_iter = l.begin(); // auto begin_iter = l.begin()도 가능
	list<int>::iterator end_iter = l.end(); // auto end_iter = l.end()도 가능


	// insert
	begin_iter++; // 2번째를 가리키는 iterator
	l.insert(begin_iter, 2);


	// erase
	end_iter--; // 마지막 원소를 가리키는 iterator
	l.erase(end_iter);


	// *iterator: 원소 접근
	cout << "list "<< distance(l.begin(), begin_iter)+ 1 << " element: " << *begin_iter << '\n';

	return 0;

}


참고자료