코딩 테스트

[코딩테스트 30일차] BAEKJOON 1032번 : 명령 프롬프트, 9093번 : 단어 뒤집기

sunlight-dby 2025. 6. 17. 00:59

[BAEKJOON 1032번 : 명령 프롬프트]

[문제]


[고찰]

해당 문제에 대해 한 번에 제출해서 정답이었긴 하지만, 다른 풀이를 살펴봤을 때 구조적으로나 효율성 측면에서 좀 더 정돈이 필요하다고 느껴져 정리하고자 합니다.

 

아래의 코드는 제가 작성한 코드입니다.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;

	vector<string> files(t);
	bool bCorrect = false;


	for (int i = 0; i < t; i++)
	{
		cin >> files[i];

		if (t == 1)
		{
			cout << files[i];
			return 0;
		}
	}

	vector<string> findFile(files[0].size());

	for (int i = 0; i < files[0].size(); i++)
	{
		for (int j = 1; j < t; j++)
		{
			if (files[j - 1][i] == files[j][i])
				bCorrect = true;
			else
			{
				bCorrect = false;
				findFile[i] = '?';

				break;
			}

			if (bCorrect == true)
			{
				findFile[i] = files[j][i];
			}
		}
	}

	for (int i = 0; i < findFile.size(); i++)
	{
		cout << findFile[i];
	}

	return 0;
}

[개념]

해당 문제의 아이디어는 각 파일 이름의 같은 위치를 비교하는 것을 어떻게 풀어갈 것인가가 중요한 문제입니다.


for (int i = 0; i < files[0].size(); i++)
{
    for (int j = 1; j < t; j++)
    {
        if (files[j - 1][i] == files[j][i])
            bCorrect = true;
        else
        {
            bCorrect = false;
            findFile[i] = '?';

            break;
        }

        if (bCorrect == true)
        {
            findFile[i] = files[j][i];
        }
    }
}

 

제 코드에서는 findFile[ i ]의 값이 ?였다가 다시 files[ j ][ i ]로 덮여쓰여지는 일이 발생합니다.

즉, 한 번에 비교되지 못했다는 소리이기에 효율적이지 않습니다.

 

사실 생각해보면, 파일 이름의 길이는 모두 같고, 첫 번째 파일 이름을 기준으로 잡아 다른 파일 이름들을 비교해도 문제에서 원하는 비교가 가능합니다.

첫 번째 파일 이름을 기준으로 잡아도 비교가 가능한 이유는, 만약 비교했을 때 아니더라도 all_same이 false가 되고, 모두 맞으면 true가 되면 되기 때문에 상관이 없는 것입니다.

 

이 아이디어를 기반으로, char 타입의 current 변수를 files[ 0 ][ i ]로 설정하여, 이를 기준으로 files[ j ][ i ]를 비교하면 됩니다.

그리고 all_same을 아예 true로 해두고, 아닐 때 false로 설정한 후, break로 반복을 탈출해준다면 i 번째 비교는 끝이 난 것입니다.

 

이후 all_same을 조건으로 하는 if문을 통해 result에 current를 더해주거나, ?를 더해주면 됩니다.

string result = "";

for (int i = 0; i < files[0].size();; i++)
{
    char current = files[0][i];
    bool all_same = true;

    for (int j = 1; j < t; j++)
    {
        if (files[j][i] != current)
        {
            all_same = false;
            break;
        }
    }

    if (all_same)
        result += current;
    else
        result += '?';
}

for (int i = 0; i < t; i++)
{
    cin >> files[i];

    if (t == 1)
    {
        cout << files[i];
        return 0;
    }
}

 

또한 제 코드는 t가 1일 때는 files[ 0 ]을 바로 출력해줍니다.

제 코드에서는 문자열 비교 루프에서 j가 있는 for을 살펴보면, j가 1부터 시작하고 t가 1일 때는 반복문이 아예 실행되지 않기 때문에 예외 처리를 해준 것입니다.

 

하지만 위의 방식처럼 문자열 비교하는 로직을 수정하면, current는 이미 설정이 되어 있기때문에 따로 예외처리를 하지 않아도 result가 정상적으로 출력이 됩니다.


[정리]

아직 코드를 구조적으로 더 명확하고 효율적이게 작성하는 부분에 대해서는 어려워하는 것 같습니다.

코드를 작성할 때 항상 구조적으로, 효율적으로 작성하는 부분에 집중해서 작성하는 연습을 해야겠습니다.


[Solution]

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;

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

    string result = "";

    for (int i = 0; i < files[0].size();; i++)
    {
        char current = files[0][i];
        bool all_same = true;

        for (int j = 1; j < t; j++)
        {
            if (files[j][i] != current)
            {
                all_same = false;
                break;
            }
        }

        if (all_same)
            result += current;
        else
            result += '?';
    }

    cout << result;

    return 0;
}

[BAKEJOON 9093번 : 단어 뒤집기]

[문제]


[고찰]

저는 reverse를 사용하지 않고, 직접 인덱스를 활용하여 해당 문제를 풀었습니다.

다른 분들의 풀이를 보고, reverse를 사용한 풀이도 함께 올리기 위해 정리합니다.


[개념]

cin.ignore( )

cin.ignore(numeric_limits<streamsize>::max(), '\n');
  • numeric_limits<streamsize>::max() : 무시 가능한 최대 문자 수
  • '\n' : 기본값으로, 무시할 값

cin.ignore( )는 입력 버퍼에 남아 있는 문자 하나를 제거하는 함수입니다.

처음에 숫자를 입력받았을 때, 개행 문자(\n)가 입력 버퍼에 남아있게 되는데, 이 상태에서 getline( )으로 줄 단위 입력을 했을 때 빈 줄이 들어오는 문제가 발생할 수 있습니다.

이를 위해 cin.ignore( )로 개행을 제거합니다.

 

stringstream

#include <sstream>

stringstream ss("문자열");
  • stringstream 객체를 만들 때 문자열을 넣으면, 마치 cin처럼 작동합니다.

std::stringstream은 문자열을 마치 cin처럼 다룰 수 있게 만들어주는 스트림 클래스입니다.

즉, 문자열에서 공백 단위로 단어를 추출하거나, 숫자 변환 등을 쉽게 할 수 있습니다.

 

while (ss >> word)

ss에서 공백 기준으로 단어들을 하나씩 추출하는 반복문입니다.

ss >> word는 읽을 단어가 있으면 true, 더 이상 읽을 게 없으면 false를 반환합니다.


[정리]

stringstream을 사용할 생각을 못했었는데, 기존에 알고는 있었고 정리도 했던 내용이었습니다.

제가 알고 있었던 것을 어떻게 활용할지도 정리하면서 생각해보고, 복습하는 것도 중요시 여기면서 앞으로 배워나가야겠습니다.


[Solution : 인덱스 활용]

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	cin.ignore();

	string sentence = "";

	int count = 0;

	while (t--)
	{
		getline(cin, sentence);
		sentence += ' ';

		for (int i = 0; i < sentence.size(); i++)
		{

			if (sentence[i] == ' ')
			{
				int k = 1;
				int last = count + (i - count) / 2;

				for (int j = count; j < last; j++)
				{
					char temp = sentence[j];
					sentence[j] = sentence[i - k];
					sentence[i - k] = temp;

					k++;
				}

				count = i + 1;
			}
		}

		cout << sentence << "\n";
		count = 0;
	}

	return 0;
}

[Solution : reverse( ) 활용]

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	cin.ignore();

	while (t--)
	{
		string sentence;
		getline(cin, sentence);

		stringstream ss(sentence);
		string word;

		while (ss >> word)
		{
			reverse(word.begin(), word.end());
			cout << word << ' ';
		}
		cout << '\n';
	}

	return 0;
}