자료구조 실습 프로젝트(2) - 하천쓰레기 수집 문제_FINAL

한선경·2022년 12월 4일
post-thumbnail


1. 문제 소개

하천 부유 쓰레기들의 최종 목적지인 서해의 한 포인트(위도: 37.843449, 경도: 126.426413) 에서부터 각 데이터를 수집한 하천들까지의 거리를 측정하고, 그 거리가 짧은 위치부터 쓰레기를 처리하는 문제이다.
추가적으로 분해 기간이 긴 쓰레기가 포함되어 있을수록 처리를 더 빨리 하도록 한다.
(현재 분류한 쓰레기의 종류는 일반쓰레기, 플라스틱, 캔, 유리, 종이 5가지이다. 이 중 분해 기간이 긴 순서는 유리, 캔, 플라스틱, 일반쓰레기, 종이 로 보고 각 가중치를 5, 4, 3, 2, 1 로 둔다.)

코드구성은 다음과 같다.
1) 데이터 불러오기 -> ifstream, getline 함수 이용 & 나머지 연산자와 switch-case 문 이용하여 각 열의 값들 구분
2) 데이터의 위,경도 값을 배열로 넣어, 위,경도를 이용한 거리를 구하는 함수 만들고 이용
-> math.h 포함하여 위, 경도로 거리 측정하는 공식 구현
3) 데이터의 쓰레기 종류 구분 값들에 따라 가중치를 더해주는 함수 만들고 이용
-> switch-case 문을 통해 1이 있으면 쓰레기 종류에 따른 가중치 배열의 값을 증가 시키는 함수 정의
4) 최소힙-우선순위 큐로 거리가 짧은 위치부터 배열로 출력
-> 수업시간에 배운 Minheap 클래스 활용

  1. 데이터 소개
    문제에서 필요한 데이터의 조건: 수도권에 위치하는 하천이어야 하고, 하천의 위치에 따라 데이터의 개수가 동일해야 한다.
    ->수도권에 위치하는 7곳의 하천 데이터를 50개씩 맞춰서 총 350개의 데이터를 사용했다.

    데이터 수집 방법:
    1) 나의 데이터에서 개수가 50개가 안되는 하천들의 위치를 확인한다.
    2) 교수님께서 올려주신 학우들의 포토폴리오 링크에 들어가 해당하는 하천들의 데이터가 있는 경우 다운받는다. 해당 하천이 없는 경우 수도권에 위치하고 데이터가 충분한 하천을 선택하여 파일을 다운받았다.
    3) 7가지의 하천 데이터를 각 학우들의 데이터에서 위도와 경도를 확인하여 수집하고 최종 데이터에 하천의 이름을 데이터 이름에 반영하여 산출하였다.
    (Ex. 탄천 – tan_1, 안양천 - an_1)

-> 7곳의 하천: 탄천, 청계천, 양재천, 안양천, 홍제천, 성복천(용인), 성북천 (본인 제외 총 31명의 데이터 사용)
데이터 csv 파일: https://github.com/sunkyoung19/DSP_Proj_data.git

  1. 구현 코드 및 결과
#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <typeinfo>
#include <queue>
#include <functional>
#include <map>


using namespace std;

#define pi 3.14159265358979323846

double deg2rad(double deg) {
  return (deg * pi / 180);
}
double rad2deg(double rad) {
  return (rad * 180 / pi);
}

double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
    double theta, dist;
    if ((lat1 == lat2) && (lon1 == lon2)) {
        return 0;
    }
    else {
        theta = lon1 - lon2;
        dist = sin(deg2rad(lat1)) * sin(deg2rad(lat2)) + cos(deg2rad(lat1)) * cos(deg2rad(lat2)) * cos(deg2rad(theta));
        dist = acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60 * 1.1515;
        switch(unit) {
            case 'M':
                break;
            case 'K':
                dist = dist * 1.609344;
                break;
            case 'N':
                dist = dist * 0.8684;
                break;
    }
        return (dist);
    }
}

vector<int> trashType(vector<int>& trType, string buffer, int lotat, int type){
    vector<int> zero(0);
    switch (lotat)
            {
            case 0:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                else{
                    break;
                }
            case 1:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            case 2:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            case 3:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            case 4:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            case 5:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            case 6:
                if (stoi(buffer) == 1){
                    trType[type] += 1;
                }
                break;
            
            default:
                break;
            }
            return trType;
            
}

void heapSortInc(double a[], int n, map<string, double>&map){
    priority_queue<double, vector<double>, greater<double> > minHeap;
    for (int i = 0; i < n; i++){
        minHeap.push(a[i]);
    }
    //오름차순 정렬 반복문
    for (int i = 0; i < n; i++){
        a[i] = minHeap.top();
        cout <<  a[i] << " ";
        minHeap.pop();
    }
}

int main(){
    ifstream is("final_data.csv");
    string buffer;      //데이터 받아올 스트링 변수

    double std_lat = 37.843449;
    double std_lon = 126.426413;

    if(!is){
        cerr << "실패" << endl;
        exit(1);
    }

    //첫번째 줄 분리
    getline(is, buffer);
    getline(is, buffer);
    cout << buffer << endl;         
    cout << "----------------------" << endl;


    int idx = 0;
    int line = -1;
    vector<double> lat_v; 
    vector<double> long_v;
    vector<int> trType(5,0);
    vector<double> weight_v;
    double fin_dis[7] = {0};
    

    while (is.peek() != EOF){           //파일 한 줄씩 읽기
        getline(is, buffer, ',');
        int row = idx % 10;         //열 번호
        int lotat = line / 50;      //위치 구분(50개 기준)
        switch (row)
        {
        case 1:{
            line += 1;
            if (line % 51 == 49){
                double weight = 0;
                cout << "trash: ";
                for (int i = 0; i < trType.size(); i++){
                    if (i == 4){
                        weight += trType[i] * 0.1;
                        cout << trType[i] << endl;
                    }
                    else{
                        weight += trType[i] * (i + 2) * 0.1;
                        cout << trType[i] << " ";
                    }
                }
                trType.assign(5, 0);    // trash 배열 값 초기화
                weight_v.push_back(weight);
            }
            break;
        }
        case 4:{
            double d_lat = stod(buffer);
            //cout << d_lat << " ";
            lat_v.push_back(d_lat);
            break;
        }
        case 5: {
            double d_long = stod(buffer);
            long_v.push_back(d_long);
            break;
        }
        case 6: {
            trType = trashType(trType, buffer, lotat, 0);
            break;
        }
        case 7: {
            trType = trashType(trType, buffer, lotat, 1);
            break;
        }
        case 8: {
            trType = trashType(trType, buffer, lotat, 2);
            break;
        }
        case 9: {
            trType = trashType(trType, buffer, lotat, 3);
            break;
        }
        case 0: {
            trType = trashType(trType, buffer, lotat, 4);
            break;
        }
        default:
            break;
        }  
    

        idx += 1;
    } // while 문 끝
    


    vector<double> dis_v;
    cout << "distance: ";
    for (int i = 0; i < lat_v.size(); i++){
        if (i % 50 == 1){
            double dis = distance(std_lat, std_lon, lat_v[i], long_v[i], 'K');
            cout << dis << " ";
            dis_v.push_back(dis);
        }
    }

    cout << "weight: ";
    for (int i = 0; i < weight_v.size(); i++){
        cout << weight_v[i] << " ";
    } 
    cout << endl;

    for(int i = 0; i < 7; i++){
        fin_dis[i] = dis_v[i] - weight_v[i];
    }

    map<string, double> m;
    m.insert(make_pair("Tancheon", fin_dis[0]));
    m.insert(make_pair("Chunggacheon", fin_dis[1]));
    m.insert(make_pair("Yangjaecheon", fin_dis[2]));
    m.insert(make_pair("Hongjaecheon", fin_dis[3]));
    m.insert(make_pair("Anyangcheon", fin_dis[4]));
    m.insert(make_pair("Seongbokcheon", fin_dis[5]));
    m.insert(make_pair("Seongbookcheon", fin_dis[6]));

    cout << "final distance: ";
    heapSortInc(fin_dis, 7, m);

    return 0;

}

  1. 기대 효과:

1) 더 많은 양의 하천 부유 쓰레기가 해양폐기물로 넘어가는 것을 방지할 수 있다.
-> 수도권의 대부분의 하천은 한강을 통해 서해로 흘러가 해양 쓰레기가 되므로, 서해로부터 거리가 짧은 위치의 쓰레기부터 처리를 한다면 (위치에 상관없이 수집할 때보다) 더 많은 양의 하천 쓰레기가 해양 폐기물이 되는 것을 방지할 수 있다.
2) 분해 기간이 긴 쓰레기를 먼저 수거하여 상대적으로 더 분해 기간을 충분히 주도록 한다.
-> 분해 기간이 긴 쓰레기는 하천 부유 쓰레기로 방치 되어 부패되는 것보다 최대한 빨리 수거하여 분해 기간을 충분히 주는 것이 자연에 도움이 될 것이다.

profile
대학생

0개의 댓글