[C++] 백준 11719,2748,11050,1259,1032

7892 단어 C브론즈백준C

11719번 그대로 출력하기2

입력 받은 대로 출력하는 프로그램을 작성
입력은 최대 100줄로 이루어져 있고, 알파벳 소문자, 대문자, 공백, 숫자로만 이루어져 있다. 각 줄은 100글자를 넘지 않으며, 빈 줄이 주어질 수도 있고, 각 줄의 앞 뒤에 공백이 있을 수도 있다.

EOF까지 입력받아 출력하여야 하는 문제였다. 윈도우에서 EOF는 콘솔창에 ctrl+z를 입력하면 된다. 해당문제가 입력 최대 100줄이라 i<100 조건을 넣었다.

#include<iostream>
#include<string>
using namespace std;

int main(void) {

	string str;
	string res;

	for (int i = 0; i<100 && !cin.eof(); i++)
	{
		getline(cin, str);
		
		if (i > 0)
			res += "\n";
		res += str;
	}
	cout << res;
}

cin.eof()

입력값의 범위를 주어지지 않은 경우 파일이 종료될 때까지 입력을 받아라는 의미이므로 cin.eof()를 이용하면 된다.
bool 타입으로 EOF를 읽게 되면 true값을 가지게 된다.

while (!cin.eof()) {    //EOF를 만날때까지 무한 입력
        cin >> n;
    }

2748번 피보나치 수2

피보나치 수는 0과 1로 시작한다. 0번째 피보나치 수는 0이고, 1번째 피보나치 수는 1이다. 그 다음 2번째 부터는 바로 앞 두 피보나치 수의 합이 된다. 이를 식으로 써보면 Fn = Fn-1 + Fn-2 (n ≥ 2)가 된다.
n=17일때 까지 피보나치 수를 써보면 다음과 같다.
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597
n이 주어졌을 때, n번째 피보나치 수를 구하는 프로그램을 작성.
n은 90보다 작거나 같은 자연수이다.

int의 표현범위를 벗어나서, 90번째 피보나치수를 체크하지 않아서 두 번 틀렸던 문제이다.

자료형

int : –2,147,483,648 ~ 2,147,483,647
unsigned int : 0 ~ 4,294,967,295
long long : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

int는 4바이트이고 long long은 8바이트라고 한다.
보통 long long 자료형은 int 연산에서 초과되는 범위를 다룰 때 사용한다.
참고로 double 역시 8바이트이지만 소수점 아래 표현을 더 많이 할 수 있어 소수를 구해야 하는 연산에서는 double 자료형이 적절하다.

90번째 피보나치 수는 0번째부터 시작한 90번째 숫자이다. fibo[90]이므로 배열은 91개의 원소를 가져야한다. 이 문제는 1학년 시절 예전에 순환함수를 이용해서 푼 예제를 본적이 있었다. 그래도 90개의 피보나치 수를 미리 저장해놓는게 더 쉽다고 생각하여 배열을 만들어넣고 저장을 하였다.

#include<iostream>
using namespace std;

int main(void) {

	long long fibo[91] = {0,1};
	
	for (int i = 2; i < 91; i++) {
		fibo[i] = fibo[i - 1] + fibo[i - 2];
	}
	int n;
	cin >> n;
	cout << fibo[n];
}

11050번 이항계수1

자연수 n과 정수k가 주어졌을 때 이항계수 nCk를 구하는 프로그램을 작성.
n,k는 최대 10으로 제한되어있다.

사담이지만 약간 피보나치문제부터 이항계수 문제는 추억 돋았다. 1학년 시절 C언어에 함수부분 배울 때 하도 책예제로 자주 등장했기 때문이다,, 그럼에도 불구하고 이항계수? 식이 생각나질 않았다. 시간이 지나면 수능을 쳐도 다 소용이 없구만 싶었다. (내머리 인증이요 빡빡)

#include<iostream>
using namespace std;

int factorial(int);

int main(void) {

	int n, k;
	cin >> n >> k;

	cout << (double)factorial(n) / (factorial(n - k) * factorial(k));
}

int factorial(int num) {

	int result=1;
	for (int i = num; i >= 1; i--) {
		result *= i;
	}
	return result;
}

1259번 팰린드롬수

수의 숫자들을 뒤에서부터 읽어도 같다면 그 수는 팰린드롬수다. 121, 12421 등은 팰린드롬수다. 123, 1231은 뒤에서부터 읽으면 다르므로 팰린드롬수가 아니다. 입력은 여러줄 입력의 마지막은 0이다. 팰린드롬수이면 yes 아니면 no를 출력한다.

이렇게 여러줄을 입력받고 결과를 출력하는 문제들을 보면 나는 백준 예제와 동일해야한다고 생각하여서 입력값과 출력값을 모두 배열 혹은 벡터에 저장했었다. 근데 다른 사람들의 코드가 궁금해서 보니 그렇지 않고 입력받자마자 결과를 출력하더라. 동일하게 채점이 되는 듯하다. 괜히 코드만 길어진 것 같아 조금 그랬지만, 이보다 중요한건 팰림드롬수를 구하는 방식의 차이이다.

방법의 차이는 다음과 같다.
1. char[6] 으로 입력받고 (\0포함이어서 6) 팰린드롬 글자를 판별하듯이 자리를 swap하여 결과를 비교하는 방식
2. 문자열 string 으로 입력을 받고 reverse한 결과와 비교하는 방식
3. 뒤집은 숫자의 값과 입력 받은 값이 동일한지 비교하는 방식. 나는 개인적으로 이 방식이 숫자의 특성을 잘 활용했고 깔끔해 보였다.

/*3번 방식 코드
  n/=10 을 하고 %10을 하면 끝자리 하나만 나온다.
  그 전에 구해진 수를 *10 해서 자릿수를 하나씩 올리고 끝자리 하나를 합친다. 
  이를 반복하면 입력된 숫자 n의 역방향의 숫자를 구할 수있다. */
  
while(1) {
		scanf("%d", &n);
		if(n == 0) {
			break;
		}
		m = n;
		l = 0;
		while(n > 0) {
			l = l * 10 + n % 10;
			n /= 10;
		}
		printf(l == m ? "yes\n" : "no\n");
	}

나는 왜 /= 대입 연산자가 생각이 안났던 것인가..
나는 입력값에 자리 제한이 없어도 팰림드롬수 판별이 가능하며 같아야 하는 숫자의 자리를 모두 비교하는 방식을 생각했다.

12321처럼 다섯자리 숫자면?
만의 자리 vs 일의 자리, 천의 자리 vs 십의 자리를 비교하는 것이다.

식으로 표현하면 다음과 같다.(n=10000)
				num/n 	vs	   	num%10
        num/(n/10)%10	vs	(num/10)%10
---------------------------------------------------------------
#include<iostream>
#include<vector>
using namespace std;

int main(void) {

	int n;
	vector<int> input;
    vector<string> result;
    
	do {
		cin >> n;
		if(n!=0)
			input.push_back(n);
	} while (n != 0);


	for (int number : input) {

		int n = 1;		//이 숫자의 자릿수 값 저장 변수

		for (; ;) {			
			if (number / n <= 9)		//나눈 몫의 범위가 1~9 사이이면 자릿수까지 곱해진 것이다
				break;
			else
				n *= 10;
		}

		bool flag;

		for (int i = 1; ; i*=10) {
		
			if (n / i == 0) {	// 몫이 0이면 자릿수를 벗어난 것이므로 break
				break;
			}
				
			if ((number / (n / i)) % 10 == (number / i) % 10)
				flag = true;
			else {
				flag = false;	//하나라도 틀린게 있으면 break 팰린드롬이 아니다
				break;
			}
		}

		if (flag == true)
			result.push_back("yes");
		else
			result.push_back("no");
	}
    
	for (string str : result){
		cout << str <<endl;
    }
}

보다시피 코드가 좀 조악하다. 숫자의 특성을 이용해 3번 방식처럼 합을 구했다면 더 간단했을 것이다. 그냥 이렇게 생각하는 사람이 있구나 하고 보면 될듯하다. 테스트를 해보니 int형이어서 9자릿수로 제한되었고 long long 으로 만들었다면 더 큰 자릿수로 테스트할 수 있을 것이다.

1032번 명령 프롬프트

이 문제는 검색 결과가 먼저 주어졌을 때, 패턴으로 뭘 쳐야 그 결과가 나오는지를 출력하는 문제이다. 패턴에는 알파벳과 "." 그리고 "?"만 넣을 수 있다. 가능하면 ?을 적게 써야 한다. 그 디렉토리에는 검색 결과에 나온 파일만 있다고 가정하고, 파일 이름의 길이는 모두 같다.
?가 와일드키처럼 어떤 알파벳도 올 수있는 것이고 위치만 일치하면 된다.

#include<iostream>
#include <vector>
using namespace  std;

int main() {

	int n;
	cin >> n;

	vector<string> fname(n);
	
	for (int i = 0; i < n; i++) {
		cin >> fname[i];
	}

	if (n == 1) {
		cout << fname[0];
		return 0;
	}

	int fnameLen = fname[0].length();
	char result[51] = {'\0'};		//최대 50개인거 유의 뒤에  널문자 넣어야해서 [51]

	//앞에서부터 비교하다 모두 같으면 넣고 하나라도 다르면 물음표 표시
	//입력값이 하나이면 그대로

	for (int i = 0; i < fnameLen; i++) {

		char before;
		char now= fname[0][i];

		for (int j = 1; j < n; j++) {
			
			before = now;
			now = fname[j][i];

			if (now != before) {
				result[i] = '?';
				break;
			}
			else
				result[i] = now;
		}
	}
	cout << result;
}

좋은 웹페이지 즐겨찾기