DY N DY

실력키우기 비밀편지(C++) 본문

PARK/ALGORITHM

실력키우기 비밀편지(C++)

손세지 2016. 6. 29. 16:39

1239 : 비밀편지

제한시간: 1000 ms    메모리제한: 32 MB
해결횟수: 877 회    시도횟수: 1849 회   



병현이는 지은이에게 문자 A, B, C, D, E, F, G, H 로 쓰여진 편지를 날마다 보내는데, 컴퓨터로 보내는 비밀편지로, 한 문자마다 0 또는 1인 숫자 여섯 개를 사용하여 보낸다. 둘 사이의 약속은 다음과 같다.

 

A 000000
B 001111
C 010011
D 011100
E 100110
F 101001
G 110101
H 111010

 

병현이가 어느 날 001111000000011100 을 보내면 지은이는 이것을 BAD로 이해하게 된다. 그런데 둘 사이에 약속이 잘 만들어져 있기 때문에, 통신에 문제가 생겨서 한 문자를 표시하는 여섯 숫자 중 어느 한 숫자만 틀리게 오는 경우, 지은이는 원래 보내려는 문자를 알아 낼 수가 있다.

 

예를 들어 지은이가 000100을 받았을 때, a와 숫자 한자만 다르고, 다른 문자들과는 각각 숫자 두 자 이상이 다르므로 지은이는 이것이 A라고 알아보게 된다.

다만 111111과 같이 모든 문자의 표현과 숫자 두 자 이상이 다른 경우에는 무슨 문자인지 알 수가 없게 된다. 예를 들어 지은이가 011111000000111111000000111111 을 받았을 때, BA 다음에 알아 볼 수 없는 문자가 나오는데. 이 경우 이런 것이 처음 나오는 문자의 위치인 3을 출력한다.

 

지은이가 받은 편지를 보고 문자들을 알아내어 출력하거나, 모르는 문자가 있는 경우, 이것이 처음 나오는 위치를 출력하는 프로그램을 작성하시오.

 

첫줄에는 보낸 문자의 개수(10개 보다 작다.)가 입력된다.
다음 줄에는 문자의 개수의 여섯 배 만큼의 숫자 입력이 주어진다.



주어진 입력에서 지은이가 이해한 문자들을 출력하거나 모르는 문자가 나오는 경우 그런 것이 처음 나오는 위치를 출력한다.


 [Copy]
3
001111000000011100
 [Copy]
BAD



 [Copy]
5
011111000000111111000000111111
 [Copy]
3





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**************************************************************
    Problem: 1239
    User: a132034
    Language: C++
    Result: Success
    Time:1 ms
    Memory:1740 kb
****************************************************************/
 
 
#include    <iostream>
#include    <string>
using namespace std;
 
#define A "000000"
#define B "001111"
#define C "010011"
#define D "011100"
#define E "100110"
#define F "101001"
#define G "110101"
#define H "111010"
 
int main()
{
    int n;
    string str, res;
    string match[8= { A, B, C, D, E, F, G, H };
 
    cin >> n;
    cin >> str;
 
    int pos = 0;
    for (int i = 0; i < n; ++i)
    {
        string word = str.substr(pos, 6);
 
        if (A == word)
            res += "A";
        else if (B == word)
            res += "B";
        else if (C == word)
            res += "C";
        else if (D == word)
            res += "D";
        else if (E == word)
            res += "E";
        else if (F == word)
            res += "F";
        else if (G == word)
            res += "G";
        else if (H == word)
            res += "H";
        else
        {
            bool Match = false;
            int isMatCount;
            for (int j = 0; j < 8++j)
            {
                isMatCount = 0;
                for (int idx = 0; idx < 6++idx)
                {
                    if ((word[idx] == match[j][idx]) != 1)
                        isMatCount++;
                }
                if (isMatCount <= 1)
                {
                    res += 'A' + j;
                    Match = true;
                    break;
                }
            }
 
            if (!Match)
            {
                cout << i + 1 << endl;
                return 0;
            }
        }
        pos += 6;
    }
 
    cout << res;
 
    return 0;
}
cs



처음에 쉽게 생각하고 뭔가 설계같은걸 안하고 그대로 코드를 써내려갔더니 지금보니 참 뭔가 어설프고 정리가 안된 느낌의 코드가 나왔다. 

역시 코드 짜기 전에는 어느정도 설계를 해야 단정한 느낌의 코드가 나오는 것 같다.. 


원리는 간단했다. 

1. 받아온 string을 6개씩 잘른 후 문자열과 비교하였다. 

1-1. 정확히 일치하는 경우에는 바로 결과 스트링(res)에 추가하였다. 

1-2. 정확히 일치하지 않는 경우 문자별로 비교하였다. 

1-2-1. 비교 결과 틀린 갯수가(isMatCount) 1이하일 경우 그때의 문자를 결과 스트링에 추가하였다. 

1-2-2. 1 이상일 경우 모르는 문자가 나온 것이므로 이 때의 위치(i)를 출력하였다. 

'PARK > ALGORITHM' 카테고리의 다른 글

기초다지기 함수3-형성평가3(C++)  (1) 2016.06.30
실력키우기 단어집합(하)(C++)  (0) 2016.06.30
실력키우기 참외밭(C++)  (2) 2016.06.29
실력키우기 타일교체(C++)  (0) 2016.06.28
실력키우기 섞기수열(C++)  (0) 2016.06.28