Codewars 문제 풀이 : Salesman's Travel

문제

Salesman's Travel

세일즈맨이 한 동네에서 할 일을 한번에 처리할 수 있도록, 주소를 재정리하는 일입니다. 즉 그 동네에 도착했을때 방문해야하는 주소를 모두 가져와서 보기 쉽게 정리하는 작업인거죠.

Input

주소들과 요청받은 우편번호입니다.

Output

우편번호에 해당하는 주소를 가져다 다음의 포맷으로 정리합니다.
zipcode:street and town,street and town,.../house number,house number,...

해결방안

이해하고보니 단순 String 처리 문제인데, 이해가 어렵습니다. 꼼꼼히 읽어보고 나서야 이해가 되네요. 원본 주소들을 재정리해서 출력 포맷에 맞게 재정리 하면 되는겁니다.

자료구조

std::string ad = "123 Main Street St. Louisville OH 43071,432 Main Long Road St. Louisville OH 43071,786 High Street Pollocksville NY 56432,"
    "54 Holy Grail Street Niagara Town ZP 32908,3200 Main Rd. Bern AE 56210,1 Gordon St. Atlanta RE 13000,"
    "10 Pussy Cat Rd. Chicago EX 34342,10 Gordon St. Atlanta RE 13000,58 Gordon Road Atlanta RE 13000,"
    "22 Tokyo Av. Tedmondville SW 43098,674 Paris bd. Abbeville AA 45521,10 Surta Alley Goodtown GG 30654,"
    "45 Holy Grail Al. Niagara Town ZP 32908,320 Main Al. Bern AE 56210,14 Gordon Park Atlanta RE 13000,"
    "100 Pussy Cat Rd. Chicago EX 34342,2 Gordon St. Atlanta RE 13000,5 Gordon Road Atlanta RE 13000,"
    "2200 Tokyo Av. Tedmondville SW 43098,67 Paris St. Abbeville AA 45521,11 Surta Avenue Goodtown GG 30654,"
    "45 Holy Grail Al. Niagara Town ZP 32918,320 Main Al. Bern AE 56215,14 Gordon Park Atlanta RE 13200,"
    "100 Pussy Cat Rd. Chicago EX 34345,2 Gordon St. Atlanta RE 13222,5 Gordon Road Atlanta RE 13001,"
    "2200 Tokyo Av. Tedmondville SW 43198,67 Paris St. Abbeville AA 45522,11 Surta Avenue Goodville GG 30655,"
    "2222 Tokyo Av. Tedmondville SW 43198,670 Paris St. Abbeville AA 45522,114 Surta Avenue Goodville GG 30655,"
    "2 Holy Grail Street Niagara Town ZP 32908,3 Main Rd. Bern AE 56210,77 Gordon St. Atlanta RE 13000";
이렇게 주고 뭘 어쩌라는건지....는 문제를 꼼꼼히 읽었다면 알 수 있습니다.
each separated from the others by a comma
저 ad를 ,로 분리하면 address가 나옵니다. address는 다음의 구조로 되어있습니다.
House number Street and town Zipcode
House number : 숫자
Street and town : 영문 주소
Zipcode : 영문<space>숫자

일정한 규칙으로 되어있습니다. 

해결

알고리즘이라고 할 만한게 없으므로 그냥 바로 해결로 넘어갑니다.
  • 복잡한 예외처리는 하지 않기
  • space로 구분되므로 정규표현식까지 할 필요 없음
  • Street and town과 House number를 연속적으로 저장
  • 루프 종료후 포맷에 맞게 string으로 만들어서 리턴

결과

std::string SalesmanTravel::travel(const std::string& orgr, std::string zipcode)
{
    std::stringstream ss(orgr);
    std::string address;
    std::string streettown;
    std::string housenum;
    int32_t num;
    while (std::getline(ss, address, ',')) {
        size_t pos = address.find(zipcode);
        if (pos == std::string::npos) {
            continue; // if not contains zipcode
        }
        if (zipcode != address.substr(pos)) {
            continue; // not same zipcode
        }
        // detach zipcode from full address
        address = address.substr(0, pos-1);
        pos = address.find(" ");
        // street town
        streettown += (streettown.length() != 0?",":"") + address.substr(pos+1);
        // house number
        housenum += (housenum.length() != 0?",":"") + address.substr(0, pos);
    }
    return zipcode + ":" + streettown + "/" + housenum;
}
꽤 헤맸는데 c++std 의 string 을 거의 다뤄본적 없어서 메소드와 특성 하나하나 찾아가면서 처리했기때문입니다. c로 하면 tockenizer 와 몇가지 함수만 쓰면 쉽게 될것을... 어쨌든 그렇게 c++std의 string에 조금 익숙해졌습니다.

테스트

string의 세부적인 내용을 모르기때문에 조금씩 테스트해가다보니 문제의 테스트 말고 다른 테스트도 조금 추가되었습니다.
    // substr test
    std::string address = "123 Main Street St. Louisville OH 43071";
    std::string zipcode = "OH 43071";
    size_t pos = address.find(zipcode);
    address = address.substr(0, pos-1);
    EXPECT_EQ(address, "123 Main Street St. Louisville");
    pos = address.find(" ");
    std::string housenum = address.substr(0, pos);
    EXPECT_EQ(housenum, "123");
    std::string streettown = address.substr(pos+1);
    EXPECT_EQ(streettown, "Main Street St. Louisville");
    EXPECT_EQ(SalesmanTravel::travel(ad, "AA 45522"), "AA 45522:Paris St. Abbeville,Paris St. Abbeville/67,670");
    EXPECT_EQ(SalesmanTravel::travel(ad, "EX 34342"), "EX 34342:Pussy Cat Rd. Chicago,Pussy Cat Rd. Chicago/10,100");
    EXPECT_EQ(SalesmanTravel::travel(ad, "EX 34345"), "EX 34345:Pussy Cat Rd. Chicago/100");
    EXPECT_EQ(SalesmanTravel::travel(ad, "AA 45521"), "AA 45521:Paris bd. Abbeville,Paris St. Abbeville/674,67");
    EXPECT_EQ(SalesmanTravel::travel(ad, "AE 56215"), "AE 56215:Main Al. Bern/320");
    EXPECT_EQ(SalesmanTravel::travel(ad, "NY 5643"), "NY 5643:/");

codewars에 submit 하고 다른 코드를 보니 역시 정규표현식을 사용한 알고리즘이 눈에 띕니다. 문제를 꼼꼼히 읽어보라는 교훈을 얻게되는 문제였습니다.

댓글

이 블로그의 인기 게시물

WSL2 Ubuntu 20.04 및 네트워크 설정

리눅스 멀티코어를 사용하는 tar 압축/해제

git pull 을 했더니 branch가 갈라지는 경우