안녕하세요, 여행벌입니다.

C++ Standard Library에서 기본적으로 제공하는 자료구조 헤더파일의 함수들을 정리해보려고 합니다!


1. Queue(큐)란?

queue(큐)는 FIFO(First in First Out) 구조로 운영됩니다.

즉, 먼저 들어온 데이터들이 먼저 삭제되는 구조입니다!

앞 쪽에서는 Pop(삭제)가 이루어지고, 뒤에서는 Push(추가)가 이루어집니다.

2. Queue(큐) Library 기본 함수

#include <queue> //queue 헤더파일을 불러온다.

using namespace std;

먼저, 기존의 C언어와는 조금 다른 방식으로 queue 헤더파일을 불러와야 함을 확인할 수 있습니다!

또, 밑에 using namespace std; 라는 처음 보는 코드가 있죠?

'Standard Library라는 namespace(공간)에 있는, 명령어들을 사용하겠다!' 라고 생각하시면 될 것 같습니다!

 

다음은 큐 헤더 파일 안에 있는 기본 함수들입니다!

 

큐 기본 함수

선언
- queue <자료형> 이름 :

추가 및 삭제

- push(element) : 큐에 element(원소)를 추가한다.

- pop() : 큐에 있는 원소를 삭제 / 반환 값은 없다.

서칭

- front() : 큐 제일 앞에 있는 원소를 반환한다.

- back() : 큐 제일 뒤에 있는 원소를 반환한다.

기타

- empty() : 큐가 비어있으면 treu 아니면 false를 반환한다.

- size() : 큐의 사이즈를 반환한다. ( 원소가 몇 개 들어 있는지 )

오늘은 6가지 기본 함수에 대해서만 공부해보겠습니다.

#include<iostream>
#include<queue>

using namespace std;

int main(void) {
	queue<int> que1; //int형 que1를 선언한다.
	que1.push(1); //que1 에 1을 넣는다.
	que1.push(2); //que1 에 2를 넣는다.
	que1.push(3); //que1 에 3을 넣는다.
    	que1.push(4); //que1 에 4를 넣는다.
    	que1.pop(); //que1의 원소 하나를 삭제한다. FIFO 구조이므로, 
                	//맨 처음에 들어온 원소 '1'이 삭제된다.
	cout << que1.front() << endl;
	cout << que1.back() << endl;
	cout << que1.size() << endl;
    	cout << que1.empty() << endl;
    return 0;
}

int형 원소들을 넣을 큐, que1을 선언하고, que1에 1,2,3,4를 넣어봤습니다!

그 뒤, pop 함수를 이용해 원소를 하나 삭제했는데요! 

queue는 FIFO 구조로 돌아가므로, 당연히 front는 원소 '2'을 가리키고, back은 원소 '4'을 가리키고,

3개의 원소를 넣었으므로, size는 '3'인 것을, empty는 false인 '0'이 출력될 것을 기대할 수 있습니다.

출력값 :
2
4
3
0
계속하려면 아무 키나 누르십시오...

기본 함수지만 가장 중요한 6가지 함수를 제대로 숙지하셨다면,

queue(큐) 자료구조를 활용하는 알고리즘을 푸는데 문제가 없을 겁니다.

다음에는 queue를 이용한 다른 알고리즘 기법에 대해서 다뤄보도록 하겠습니다.

안녕하세요.

여행벌입니다.

오늘은 백준 16360번 Go Latin 문제풀이를 해보려고 합니다.

ACM-ICPC 2018 본선 문제로 ACM-ICPC 문제 치고는 되게 쉬웠던 것 같습니다.

https://www.acmicpc.net/problem/16360


문제는 'n개의 단어가 주어졌을 때,  pseudo-latin 단어로 바꿔서 출력해주는 알고리즘을 구현하라.' 입니다.

단어의 끝 문자가 위의 테이블에 해당되면, pseudo-latin 문자로 바꿔서 출력해주면 되는데요.

다른 더 좋은 알고리즘이 있을 수도 있지만, 저는 간단한 문제라 더 생각 안 하고 if 문을 통해

간단하게 알고리즘 구현할 수 있었습니다.

 

[알고리즘설계]

1. switch 문을 통해 입력받은 string의 끝 문자 들을 다 체크한다. 이때, Pseudo-Latin으로 바꿔줘야 하는 문자가 있다면, 바꿔주면서 출력한다. 다만 -n, -ne를 제외하고 모두 원래의 단어에 글자를 추가해주면 되므로 원래의 string을 출력하고 뒤에 추가로 char을 출력해준다.

 

 

#include<stdio.h>
#include<string.h>

int main(void) {
	int total_number;
	scanf("%d", &total_number);
	while (total_number > 0) {
		char list1[31];
		scanf("%s", list1);
		switch (list1[strlen(list1) - 1]) {
		case 'a':
			printf("%ss\n", list1); break;
		case 'i':
			printf("%sos\n", list1); break;
		case 'y':
			list1[strlen(list1) - 1] = '\0';
			printf("%sios\n", list1); break;
		case 'l':
			printf("%ses\n", list1); break;
		case 'n':
			list1[strlen(list1) - 1] = '\0';
			printf("%sanes\n", list1); break;
		case 'e':
			if (list1[strlen(list1) - 2] == 'n') {
				list1[strlen(list1) - 1] = '\0';
				list1[strlen(list1) - 1] = '\0';
				//조심! 위에서 마지막 글자를 이미 날려서, strlen이 하나 줄었음!
				printf("%sanes\n", list1);
			}
			else
				printf("%sus\n", list1);
			break;
		case 'o':
			printf("%ss\n", list1); break;
		case 'r':
			printf("%ses\n", list1); break;
		case 't':
			printf("%sas\n", list1); break;
		case 'u':
			printf("%ss\n", list1); break;
		case 'v':
			printf("%ses\n", list1); break;
		case 'w':
			printf("%sas\n", list1); break;
		default:
			printf("%sus\n", list1); break;
		}
		total_number--;
	}
}

너무 간단한 문제라 여기서 해설 마치겠습니다.

안녕하세요

여행벌입니다.

오늘은 백준 14954번 ACM 2017 본선 D번 문제 풀이를 해보겠습니다.

https://www.acmicpc.net/problem/14954


문제는 '어떤 숫자가 주어졌을 때, HappyNumber인지 아닌지 구분해주는 알고리즘을 구현하라.' 입니다.

이 때, HappyNumber 란 숫자가 주어졌을 때, 각 자릿수의 제곱을 더해나가고 이 과정을 거쳐 최종적으로 1에 도달할 수 있는 수를 뜻합니다.

예를 들어,

3이란 숫자가 주어지면 19 -> 82 -> 68 -> 100 -> 1 로 HappyNumber인 것을 확인할 수 있습니다.

4라는 숫자는 4 -> 16 -> 37 -> 56 -> 61 -> 37 순환(Cycle) 고리가 생겨 UnHappyNumber인 것을 볼 수 있습니다.

따라서, 우리는 다음과 같이 알고리즘을 설계할 수 있습니다.

 

[알고리즘 설계]

1. 어떤 숫자가 주어졌을 때, 각 자릿수를 구하고 제곱해서 더한 값을 return 해주는 함수.

2. 각 자리수를 구하고 제곱해서 더해나가다가 순환(recycle) 고리가 생기는지 체크해주는 함수. 

3. 순환 고리가 생긴다면 UNHAPPY / 순환 고리가 생기지 않고 1이란 숫자가 나타나면 HAPPY 를 출력해주는 함수.

 

총 3가지 작업이 필요하다는 것을 확인할 수 있습니다.

설계한 알고리즘을 구현해보겠습니다.

#include<iostream>

using namespace std;

int nlist[10] = {};
int repeat[10000000] = {};

int divide(int);
bool check_repeat(int, int);

int main(void) {
	int ninput, count = 0;
	cin >> ninput;
	while (1) {
		repeat[count] = ninput;
		if (ninput == 1) {
			cout << "HAPPY";
			break;
		}
		if (check_repeat(ninput, count) || count == 9999999) {
			cout << "UNHAPPY";
			break;
		}
		ninput = divide(ninput);
		//cout << count << "번 째 : " << ninput << endl;
		count++;
	}
}

/* 자리수별로 자른다. */
/* 자리수별로 제곱해서 더한 값을 return해준다. */
int divide(int ninput) {
	/* 이 부분 예외처리 안해서 틀렸음.*/
	if (ninput < 10) {
		return ninput * ninput;
	}
	int out = 0;
	nlist[0] = ninput / 1000000000;
	nlist[1] = (ninput % 1000000000) / 100000000;
	nlist[2] = (ninput % 100000000) / 10000000;
	nlist[3] = (ninput % 10000000) / 1000000;
	nlist[4] = (ninput % 1000000) / 100000;
	nlist[5] = (ninput % 100000) / 10000;
	nlist[6] = (ninput % 10000) / 1000;
	nlist[7] = (ninput % 1000) / 100;
	nlist[8] = (ninput % 100) / 10;
	nlist[9] = (ninput % 10);
	for (int i = 0; i < 10; i++) {
		if (nlist[i] != 0)
			out += nlist[i] * nlist[i];
	}
	return out;
}

// 지금까지나왔던 값 중에서 현재 값이 있는지 없는지 확인한다.
bool check_repeat(int ninput, int count) {
	for(int i =0 ; i< count; i++){
        if(repeat[i] == ninput)
            return true;
    }
    return false;
}

각 자릿수를 구하는 divide 함수는 https://travelbeeee.tistory.com/4 기존의 포스팅 글을 참고하시면 될 것 같습니다. 

check_repeat 함수는 지금까지 결과로 나왔던 값들을 순회하며 공통된 값이 존재하면 순환(Cycle)고리가 형성된 것이므로 true 아니면 false를 return 해주는 함수입니다.


아마 2017 ACM-ICPC 예선에서 가장 쉬운 문제가 아닐까 싶습니다.

알고리즘 설계하기 굉장히 쉬웠고, 예외만 잘 잡아준다면 쉽게 풀 수 있는 문제인 것 같습니다.

안녕하세요.

여행벌입니다.

오늘은 알고리즘 문제를 풀 때 자주 쓰이는

각 자릿수 구하기 알고리즘에 대해서 포스팅해보도록 하겠습니다.


알고리즘 문제를 풀다 보면, 어떤 정수의 각 자릿수를 구해야 하는 경우가 자주 생깁니다.

 

예를 들어, 5자리 정수 54321이 Input으로 들어온다고 가정해봅시다.

54321이라는 값이 들어오면 우리는 5, 4, 3, 2, 1 이라는 값을 구해야 되는데요.

다음과 같이 구할 수 있습니다.

5 = 54321 / 10000

4 = ( 54321 % 10000 ) / 1000

3 = ( 54321 % 1000 ) / 100

2 = ( 54321 % 100 ) / 10

1 = ( 54321 % 10 )

간단한 규칙이 보이시나요? %와 / 을 이용해 자릿수를 간단하게 다룰 수 있습니다.

 

다른 예시를 하나 더 다뤄볼까요?

9236715 라는 값이 들어오면 위의 알고리즘을 어떻게 변형하면 될까요?

9 = 9236715 / 1000000

2 = ( 9236715 % 1000000 ) / 100000

3 = ( 9236715 % 100000 ) / 10000

6 = ( 9236715 % 10000 ) / 1000

7 = ( 9236715 % 1000 ) / 100

1 = ( 9236715 % 100 ) / 10

5 = ( 9236715 % 10 )

다음과 같이 구할 수 있습니다.

 

지금 예시들은 다 몇 자리 숫자인지 미리 알고 있는 경우인데요.

보통 알고리즘 문제는 Input의 범위가 다음과 같이 정해져 있습니다.

Input : N , 1 ≤ N ≤ 100,000

그렇다면 이런 상황에서는 어떻게 알고리즘을 구현할 수 있을까요?

다음과 같이 코드를 구현할 수 있습니다.

#include<iostream>

using namespace std;

int list[6];

int main(void) {
	// 1 ~ 100,000 사이의 숫자가 Input으로 들어온다.
	int ninput;
	cin >> ninput;
	// 2자리 ~ 6자리 숫자는 각 자릿수를 구해서 출력해준다.
	list[0] = ninput / 100000; // 십만의자릿수
	list[1] = (ninput % 100000) / 10000; //만의자릿수
	list[2] = (ninput % 10000) / 1000; //천의자릿수
	list[3] = (ninput % 1000) / 100; //백의자릿수
	list[4] = (ninput % 100) / 10; //십의자릿수
	list[5] = (ninput % 10); //일의자릿수

	for (int i = 0; i < 6; i++) {
		cout << list[i] << ' ';
	}
}

최대 자릿수를 안다면 항상 다음과 같이 코드를 구현해 배열에 각 자릿수를 저장할 수 있습니다.

하지만 언뜻 보기에는 6자리 숫자가 들어오면 문제가 없지만, 1~5자리 숫자가 들어오면 문제가 있어 보입니다.

다음 예시를 통해서 1 ~ 5 자리 숫자가 들어오면 알고리즘이 어떻게 작동하는지 알아보겠습니다.

4321 이라는 4자리 숫자가 들어왔다고 가정해봅시다.

list[0] = 4321 / 100000 = 0

list[1] = (4321 % 100000) / 10000 = 0

list[2] = (4321 % 10000) / 1000 = 4

list[3] = (4321 % 1000) / 100 = 3

list[4] = (4321 % 100) / 10 = 2

list[5] = (4321 % 10)  = 1

다음과 같이 배열에 저장이 됩니다.

즉 Ninput보다 큰 자릿수에는 0이 저장되는 것을 확인할 수 있습니다.

이 알고리즘을 잘 활용하면 다음과 같은 문제들을 쉽게 해결할 수 있습니다.

https://www.acmicpc.net/problem/14954

 

14954번: Happy Number

Your program is to read from standard input. The input consists of a single line that contains an integer, n (1 ≤ n ≤ 1,000,000,000)

www.acmicpc.net


오늘 포스팅은 여기서 마치겠습니다.

안녕하세요

여행벌

입니다.

 

오늘은 저번 시간 가상 환경 셋팅에 이어서,

장고(Django) 기본 환경 설정을 해보겠습니다.


1. 가상 환경 설정하기.

먼저 가상 환경에서 Django를 시작할 예정이므로, 가상 환경을 셋팅해줍니다.

저번 시간에 이어서 HelloWorld 폴더 안에 travelbeeee라는 가상 환경에서 시작을 해보겠습니다.

여기까지는 안 보고 셋팅 가능하셔야 합니다!

아직 가상 환경 셋팅이 어려우신 분은 아래 포스팅 글을 참고해 주시기 바랍니다.

https://travelbeeee.tistory.com/2

 

2. Django 설치하기

Django를 시작하려면 당연히 install 해야겠죠?

conda install django 
pip install django

위의 두 개 명령어를 이용해 django를 install 할 수 있습니다.

Python에서는 pip install django만 하면 장고 install이 다 완료되는데,

Anaconda에선 conda install 과 pip install 명령어를 다 써줘야만 제대로 설치가 되더라고요...!

이유는 아직 저도 자세히 모르겠습니다 ㅠㅠ

conda install django를 먼저 실행하고 pip install django 명령어를 실행했습니다.

 

3. Django Project 시작하기(1).

이제 Django를 성공적으로 install 했으므로, Django를 이용해서 Project를 시작해봐야겠죠?

django-admin startproject myprojectname

다음과 같은 명령어를 통해 'myprojectname' 이라는 이름을 가진 프로젝트를 생성할 수 있습니다.

이 프로젝트 안에서 우리는 앞으로 작업을 진행하면 됩니다.

myproject라는 이름을 가진 Django Project를 만들어보겠습니다.

다음과 같이 myproject라는 폴더와 그 안에 myproject폴더와 여러 python 파일이 생긴 것을 확인할 수 있습니다.

구분을 하기 위해, 상위 myproject 폴더를 엄마폴더, 하위 myproject 폴더를 아들폴더라고 하겠습니다.

간단하게 설명하면 엄마폴더는 이제 우리가 만들고 싶은 Project가 되고,

하위 아들폴더는 그 Project의 Master 같은 일을 하고 있다고 이해하시면 편할 것 같습니다.

 

4. Run Server

이제 Django Project까지 만들었으니, Server를 켜보겠습니다.

python manage.py runserver

다음과 같은 명령어를 통해 Local Server를 켤 수 있습니다.

당연히 manage.py 파일이 있는 경로에서 저 명령어를 실행해야겠죠?

경로 설정을 제대로 하지 않으면, 다음과 같은 에러코드를 볼 수 있습니다.

지금 제가 설정한 경로는 바탕 화면\HelloWorld 폴더까지인데 manage.py는 엄마폴더안에있죠?

cd foldername

위와 같은 명령어를 통해 foldername을 가진 폴더로 들어갈 수 있습니다.

우리는 myproject 라는 폴더로 들어가야 manage.py를 만날 수 있으므로

'cd myproject' 를 입력해야겠죠?

다음과 같이 C:\User\sochu\OneDrive\바탕 화면\HelloWorld 에서

C:\User\sochu\OneDrive\바탕 화면\HelloWorld\myproject 로 경로가 바뀐 것을 볼 수 있습니다.

이제 python manage.py runserver 명령어를 입력해볼까요?

다음과 같이 http://127.0.0.1:8000/ 라는 주소를 가진 Local Server가 열린 것을 확인할 수 있습니다.

눌러보면 다음과 같이 성공했다는 로켓 사진을 볼 수 있습니다!

여기까지가 가상 환경에 이어 Django를 설치하고, Project를 시작하고, Server를 켜보는 과정이었습니다!

 

+ Recent posts