4673 Self Number

신우빈·2022년 6월 30일
0

BAEKJOON

목록 보기
1/1
post-thumbnail

이번에 기록할 문제는 셀프 넘버라는 문제다.
백준 4673 : 셀프 넘버

이번 문제에 상당히 많은 시간을 소모했음에도 스스로 힘으로는 풀어내지 못했다.
함수를 많이 사용하지 않은 경험도 있겠지만, 이 문제는 어떤 방식으로 접근해야할지 감도 잡지 못했다.

Memo

코딩 실력 향상을 위해 내가 처음 생각한 방식을 설명한다.
그 생각과 코드를 비교한다.
검색을 통해 얻은 답을 이해하는 과정을 거친다.
새롭게 알게 된 개념이 있다면 새로 포스팅한 이후 링크.

이 부분을 작성하면서 생각한 나의 코딩 방식

  • 앞으로 문제를 읽고 어떻게 코드를 짤 것인지 큰 흐름을 작성한다.
  • 이 문제를 예시로서 참고하자. ( 아래에 작성됨. )
  • 이번 포스팅 같은 경우, 처음 생각을 미리 작성해놓지 않았다.
    그래서 답지를 보고 생각된 흐름이 작성되었다.

First Try

우선 스스로 작성한 코드를 살펴보겠다.

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

using namespace std;

vector<int>org;
vector<int>sub;

int d(string n){
    int length = n.length();
    int numa = stoi(n);
    int sum = numa;
    for(int i = 0; i<length; i++){
        int tmp_num = n[i] - '0';
        sum += tmp_num;
    }
    return sum;
}

int main(void){
    int res;
    for(int i = 1; i<=100; i++) org.push_back(i);
    for(int i = 1; i<=100; i++){ // [0]=1,[1]=2,[2]=3 ...
        int del_idx = d(to_string(i));
        sub.push_back(del_idx);
    }
    vector<int> buff(org.size()+sub.size());
    auto iter = set_difference(org.begin(), org.end(), sub.begin(), sub.end(), buff.begin());
    buff.erase(iter, buff.end());
    for(int i = 0; i<100; i++)
    {
        cout << buff[i] << endl;
    }

    return 0;
}

이 코드가 내가 작성한 전체 코드다. 세세하게 살펴보자.

생각한 방향
1. d(n)을 함수를 이용해 구현
2. d(n)의 결과 값들을 제거.
3. d(n)의 결과가 되지 않는 것들이 'Self Number'
작성하고 보니, 내가 처음헀던 생각은 d(n)의 결과를 하나의 vector에 저장하고,
1~10000의 값을 또 다른 vector에 저장한다.
그리고 이후 그 두 vector의 차집합을 구하고자 했다.

int d(string n)

우선 함수 선언한 부분부터 설명하겠다.

int d(string n){ // 반환값이 int인 d라는 함수 선언. 인자로 string 형태를 받음
    int length = n.length(); // 반복문을 돌리기 위해 string 길이 파악
    int numa = stoi(n); // n의 정수형태 값을 위해 string_to_int 사용
    int sum = numa; // 초기 sum 값에 n을 더해준다.
    for(int i = 0; i<length; i++){ // 길이만큼 반복하는 이유는 인덱스를 이용할 것이기 때문.
        int tmp_num = n[i] - '0'; // 각 인덱스에 접근하여 제일 앞자리 수부터 하나하나 접근
        sum += tmp_num; // 접근한 각 자리수를 sum에 더해준다.
    }
    return sum; // 그런 sum 값을 반환
}

위 문제를 읽어보면 알 수 있겠지만, 이 함수는 d(n)을 표현한 것이다.
자리수를 판별해야하는데 수학적 식을 사용하기에는 일반적이지 못하다는 생각이 들었다.
그래서, string을 사용했다.
하나씩 주석을 통해 살펴보자.

최종적으로 제출한 답과는 형식이 다르다. 하지만, 나만의 힘으로 도출해낸 코드이며, d(n)이라는 형태는 잘 맞혔기 때문에 만족한다.

int main()

이 부분에서 틀렸다. 차근차근 파헤쳐보면서 어느 부분이 틀렸는지 살펴보고, 가능하면 고쳐보고자 한다.

int main(void){
    int res; // 결과값으로 사용
    for(int i = 1; i<=100; i++) org.push_back(i); // 1부터 100까지 가지는 org vector 생성
    for(int i = 1; i<=100; i++){ // [0]=1,[1]=2,[2]=3 ...
        int del_idx = d(to_string(i)); // d(n)함수를 이용해 생성한 숫자들을 del_idx라는 변수에 저장
        sub.push_back(del_idx); // sub라는 vector에 del_index 값을 모두 저장한다.
    }
    vector<int> buff(org.size()+sub.size()); // buff라는 vector를 선언하는데,
    // org와 sub의 크기의 합을 크기로 가진다.
    auto iter = set_difference(org.begin(), org.end(), sub.begin(), sub.end(), buff.begin()); // 차집합
    buff.erase(iter, buff.end()); // 차집합
    for(int i = 0; i<100; i++)
    {
        cout << buff[i] << endl; // 차집합 결과를 출력
    }

    return 0;
}

고치는 과정

  • int res를 가독성이 떨어지는 buff 변수를 삭제함과 동시에, vector 형으로 변경
  • for(int i = 1; i<=100; i++) org.push_back(i) 는 1부터 100까지 가지는 vector 생성하는 것이므로 유지
  • int del_idx = d(to_string(i)) : 1부터 100까지 순서대로 d(n) 실행
  • sub.push_back(del_idx) : 1부터 d(n)한 결과를 100까지 하나씩 대입.
    이렇게하면, 0번 인덱스에 d(1)의 결과인 2가 들어감.
  • 단순히 보기 편하기 위해 sort를 했는데, sort의 유무에 따라 결과값이 변경됨을 확인
    그 이유가 무엇인지 고민해보고 작성할 것!!

수정 완료 코드

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

using namespace std;

vector<int>org;
vector<int>sub;

int d(string n){
    int length = n.length();
    int numa = stoi(n);
    int sum = numa;
    for(int i = 0; i<length; i++){
        int tmp_num = n[i] - '0';
        sum += tmp_num;
    }
    return sum;
}

int main(void){
    vector<int> res;
    for(int i = 1; i<=10000; i++) org.push_back(i);
    for(int i = 1; i<=10000; i++){ // [0]=1,[1]=2,[2]=3 ...
        int del_idx = d(to_string(i));
        sub.push_back(del_idx);
    }
    sort(sub.begin(), sub.end());
    res.resize(org.size()+sub.size());
    auto itr = set_difference(org.begin(), org.end(), sub.begin(), sub.end(), res.begin());
    res.erase(itr, res.end());
    for(int i = 0; i<res.size(); i++) cout << res[i] << endl;
    return 0;
}

다음 포스팅은 vector 와 관련하여 이번 포스팅에 작성된 새롭게 알게 된 헤더파일 개념 등을 작성해서 올릴 것이다.

0개의 댓글