[0926] C++ 언어의 흐름 이해하기
원래 작성된 코드를 이용하여 student_id 변수에 내 학번 마지막 세 자리 255라는 숫자를 넣고 이 숫자가 나오기 위해서는 함수가 어떻게 동작하는지를 알아야 하는 과제였다. 코드는 위와 같다.
코드의 흐름을 해석해보면 크게 네 부분으로 나눌 수 있다.
1. do-while문
2. puls 만큼 for루프
3. if문에 의한 처리
4. mult 만큼 for루프
recursive 함수가 추가로 구현되어 있지만, main에서 쓰는 함수는 아니므로, 해석 부분에서 제외했다. 코드의 흐름을 알기 위해서는 굳이 사용되지 않는 함수이므로 바로 f함수의 흐름부분을 분석했다.
차례대로 코드 해석을 해보면 아래와 같다. 우선 먼저 함수가 어떠한 동작을 하는지 전체적인 흐름을 알기 위해서는 Main 함수 부분부터 간단하게 본다.
[Main]
이 부분을 보면, int형 result 변수에 f 함수가 리턴한 값을 받고 있는 코드가 보인다. 이 f함수에 인자로는 gen이 들어가는데, 이 gen 값은 983으로 고정되어 있다. 그러면 f(983)이 된 꼴이다. 이렇게 인자를 넣고나서 리턴되는 값이 result인데, 이 값이 student_id 즉 여기서는 255와 같다면 Get Your ID의 문구가 뜨면서 맞는 값을 입력한 것이고, 원하는 값과 일치하지 않는다면 FAIL 문구가 뜨며 실패했음을 알린다.
[1. do-while문]
f 함수에 인자를 넣었다면, 이제 이 인자가 어떠한 동작을 거쳐서 return이 되는지를 파악하기 위해 첫번째 관문인 do-while문을 보자.
우선, do-while문은 while문이긴 하지만, while문을 실행하기 전에 전 조건인 do안에 있는 조건을 수행하고서야 그 다음에야 while문이 실행된다. 이렇다는 전제 하에 코드를 살펴보면, do-while문 앞에 puls라는 변수 안에 사용자가 입력한 값을 넣는다. 이 값이 어떤 값인지는 아직 유추를 하지 못했으므로 이 puls 값이 어떤 값이 들어가야 좋을지를 생각하며 분석해보았다. 다시 돌아가서, do 안에 있는 코드를 해석하자면, g 변수 안에 (g + 17) % mod(정해진 변수의 값들을 대입해보면 식은 g = (983 + 17) % 1091이다.)를 한 값을 우선 한 번 연산하고, puls가 양수면 --를, puls가 음수면 ++를 실행하며 값을 증가시키거나 감소 시킨다. 그러나, while문을 자세히 보면 puls일때 실행한다, 이 말인 즉슨 puls가 0이 될때까지 이 do 문을 반복하여 수행한다는 소리가 된다. 그렇기 떄문에 puls에 숫자가 n이 들어오면 n번 루프를 돌고 while문을 빠져나가게 되는 것이다.
결과적으로, puls == 0이 되면서 while문은 종료하게 된다.
[2. puls 만큼 for루프 ]
for 문을 자세히 보면, 생각보다 복잡해 보였는데 정말 단순한 이야기였다. 아까 전에 while문을 반복하면서, 결국 puls는 0이 된 상태로 다음 for문으로 동작이 넘어온다고 했는데, 이 점을 생각하면 i는 0부터 시작하는데, 0까지 도는 격이 되므로 for 루프 안에 있는 g = (g+31) % mod는 딱 한 번만 실행되는 셈이다. puls가 어떠한 숫자가 되어도 마찬가지이다. puls가 0이 되지 않으면 while문에서 빠져나오지 못해 무한루프가 발생하기 때문이다.
[3. if문에 의한 처리]
결정적인 생각을 하게 된 것은 이 부분의 처리를 보고 생각해냈다. 자세히 보니 우선, 여기서 계산한 g는 student_id 값인 255가 되면 안된다. 그리고, g=0이 되는 경우에는 g가 1090으로 변환된다. 그렇다면 이 부분에서 mult 부분으로 잠시 넘어가서 보면 동작하는 식은 아래와 같음을 알 수 있다.
g를 1090으로 만든 뒤에, mult를 입력받으면 g = (g * gen) %mod 의 연산결과를 255로 만들면, 원하는 값이 나오겠다는 생각이 들었다. 그래서, 함수의 흐름을 파악한 뒤에 어떻게 하면 원하는 값의 결과를 얻을 수 있을지 식을 세워보았다.
원래는 mult 값을 고정시키고 puls 값을 변경시켜가면서 나오는 홀수 짝수 간의 일정한 간격으로의 감소하는 규칙을 이용하여 찾으려고 했으나, 흐름을 파악하기 위해서는 식을 세워서 하는 편이 낫다고 생각하여 이 방법으로 분석을 했다.
앞서 말했단 do-while문 실행시 사용했던 식은 g=(g+17) % mod이다. 이것을 puls 번 실행하여 나온 숫자에 다음 for문을 만나 for문 안에 있는 식이 한 번 실행되면서 +31을 한 값에 %mod 연산을 하게 되는 루트이다.
그럼 이러한 연산을 모두 진행했을 때 g=0이 되거나 g=1091이 되면 된다. g=1091을 가정했을 때 식을 세워 아래와 같이 직접 코드를 구현하여 계산 결과를 얻었다.
do-while에서 말한 식에 정해진 변수들의 값을 대입하였고, 이 while문을 실행하면서 결과적으로 puls번 루프를 돌게 되므로 연산을 반복하는 식을 위와 같이 변형하여 표현하였다. puls 값을 하나씩 증가시켜주면서 g=1059가 되는 값을 찾으려고 하였다. 결과로 197이 나왔다. 여기서 왜 g=1059를 만족시키는 값을 찾으려고 했는가 하면, 이 do-while을 빠져나와서 실행되는 for루프의 식이 g=(g+31)%mod이므로, 여기서 mod는 1091로 모듈러 연산을 한 것으로, g가 1090이 직접 값이 되어 1090이 나오는 조건을 충족시키거나, g=0이 되어 g에 1090을 대입시키는 조건문을 충족하여 대입하는 방법이 두 가지가 있었는데, 같은 방법이기 때문에 한층 더 간단하다고 생각된 g를 바로 1090으로 만들어버리는 방식을 택하였다. 그래서 do-while문에 빠져나온 값에 -31을 했을 때 1090이 되는 값을 구하기 위해 저렇게 조건문을 처리했다.
결과적으로, 197이 나오는 것을 알 수 있다.
이제 원하던대로 1090의 수가 나왔으면, 이 수를 처리하는 것을 알아야 한다. mult에서 수행되는 동작 연산은 g=(g*gen)%mod 이다. 이것을 변형하면, g = (g * 983) % 1091과 같다. 앞의 식과 달리 g를 이번에 1090으로 바꾸지 않은 것은 이것은 누적되는 수이기 때문에 바꿔서 상수를 대입해버린다면 이상한 결과가 나오게 된다. 그래서 앞의 것과 같이 식을 작성한 것이다. 결과적으로 이것이 결국 255의 값을 가져야지만 연산 결과가 true가 성립되는 것인데, 그렇다면 255의 값을 갖는 수를 찾기 위해서 각 숫자를 몇 번 곱해야만 하는지 실행 횟수를 알아야 한다는 뜻이 된다. 그것을 코드로 나타내어 위와 같이 while문을 실행해보았고, mult가 바로 몇 번 연산을 해야하는지 알려주는 지표가 되었다. 255의 원하는 값을 찾으면 break하는 형식으로 결과 값이 802가 나왔다.
위의 계산으로 결론을 내어보면 puls=197 mult=802로 이 숫자를 넣었을 때 나의 학번 뒷자리 255와 일치하여 Get your ID 값을 출력해야 한다. 결과를 기대하며 결과값을 넣어보았다.
예상과 같은 기대 결과가 나온 것을 확인하였다. 사실, 지금 흐름을 따라와 답을 구한 것은 그저 코드의 흐름을 따라가다보니 나온 방식이었고, 추후에 살펴보니 풀이 방법은 여러가지로 해석될 수 있다는 것을 또한 깨달았다. 나는 puls 부분에서 계산되는 값을 1090에 맞추어 생각하여 저러한 결과가 나왔지만, 사실은 puls가 어떤 수를 넣든지간에 마지막 mult 부분만 잘 계산해서 넣으면 원하는 결과를 얻을 수 있다는 것을 알게 되었다. 예를 들어 다른 수로도 실행을 해 보았다.
아까 사용한 마지막 mult 부분 연산 코드를 재활용하여 임의로 입력한 숫자를 넣고 동작해보았다. 결과 값은 43이 나왔으며 구해진 결과를 대입해도 원하는 값이 잘 출력되는 것을 볼 수 있다.
이번 과제를 하면서 C++언어의 전체적인 문법과 흐름을 자세히 분석할 수 있었다.
'Undergraduate Records' 카테고리의 다른 글
[0930] 시스템 프로그래밍 DataLab 5문제 (0) | 2019.10.01 |
---|---|
[0927] Merge Sort & Quick Sort와 시간 복잡도 (1) | 2019.09.27 |
[0926] 알고리즘 정렬 복습 (0) | 2019.09.26 |
[학습튜터링] 네비게이션 바 외 CSS(background-image등) (0) | 2019.09.25 |
[0925] OOP Concept 구체적으로 설명 :: Python 상속 기초 (0) | 2019.09.25 |