CodeWars 09: Salesman's Travel

김기욱·2021년 5월 27일
0

코딩테스트

목록 보기
46/68
post-custom-banner

문제설명

A traveling salesman has to visit clients. He got each client's address e.g. "432 Main Long Road St. Louisville OH 43071" as a list.
방문판매 세일즈맨은 방문할 고객들의 주소를 가지고 있습니다.

The basic zipcode format usually consists of two capital letters followed by a white space and five digits. The list of clients to visit was given as a string of all addresses, each separated from the others by a comma, e.g. :
기본적으로 우편번호의 형식은 보통 두 개의 대문자, 한 칸 공백, 5개의 숫자로 이루어져 있습니다. 또한 방문할 고객리스트는 콤마로 구분되어 있는 하나의 긴 문자열로 되어있습니다.

"123 Main Street St. Louisville OH 43071,432 Main Long Road St. Louisville OH 43071,786 High Street Pollocksville NY 56432".
위와 같은 형식으로 말이죠.

To ease his travel he wants to group the list by zipcode.
방문판매 효율을 높이기 위해서 세일즈맨은 우편번호를 바탕으로 리스트를 수정하기를 원합니다.

Task
The function travel will take two parameters r (addresses' list of all clients' as a string) and zipcode and returns a string in the following format:
당신의 임무는 travel이라는 함수를 만드는 것입니다. 이 함수는 r(고객주소)와 zipcode(우편번호) 두 개의 파라미터를 받으며, 다음과 같은 형식의 새로운 고객주소 형식을 반환해줍니다.

zipcode:street and town,street and town,.../house number,house number,...
우편번호:고객주소/상세주소(집번호) <- 요런 형식으로 이루어져있죠.

The street numbers must be in the same order as the streets where they belong.
집 주소는 반드시 정확하게 우편번호랑 일치해야 합니다.
If a given zipcode doesn't exist in the list of clients' addresses return "zipcode:/"
만일 우편번호가 고객 주소리스트에 없다면 "zipcode:/" 형식으로 반환해줘야 합니다.

제한사항

zipcode와 address는 빈 값이 입력될 수 있음

입출력 예시

r = "123 Main Street St. Louisville OH 43071,432 Main Long Road St. Louisville OH 43071,786 High Street Pollocksville NY 56432"

travel(r, "OH 43071") --> "OH 43071:Main Street St. Louisville,Main Long Road St. Louisville/123,432"

travel(r, "NY 56432") --> "NY 56432:High Street Pollocksville/786"

# 우편번호가 '정확하게' 일치하지 않음 
travel(r, "NY 5643") --> "NY 5643:/"

풀이

import re

def get_num(_string, zipcode):
    return re.findall("\d+", _string.replace(zipcode, ''))[0]


def travel(r, zipcode):
    numb = "/"
    string_set = ""
    if zipcode:
        for v in r.split(','):
            # 문자열 일치여부 확인(in은 부분일치 판정이므로 endswith 사용)
            if v.endswith(zipcode):
                # 문자에서 zipcode 제거
                modifiedStr = v.replace(zipcode, '')
                # 문자에서 집 번호만 추출
                num = get_num(v, zipcode)
                # 문자에서 집 번호 제거, 양쪽 공백 제거
                modifiedStr = modifiedStr.replace(num, '').strip()
                # 문자 조합
                string_set = string_set + "," \
                    + modifiedStr if len(
                        string_set) > 0 else string_set + modifiedStr
                # 숫자 조합
                numb = numb + ',' + num if len(numb) > 1 else numb+num

    return f"{zipcode}:{string_set}{numb}" 
  1. 코드가 좀 너저분하네요. 간결하게 풀 로직이 생각안나서 하드코딩에 가깝게되었는데,
    개인적으로 제 풀이지만 저도 싫은 코드입니다.
  2. 우선 정규식을 활용해서 주어진 고객주소에서 숫자만 빼오는 함수를 만듭니다. 숫자는 집 주소에도 있지만 zipcode에도 존재하기 때문에 고객주소에서 zipcode를 뺀 문자열에서 숫자만 빼오는 로직을 구축했습니다.
  3. 이후로 계속 문자열을 다듬는 로직이 나옵니다. 코드에 적어놓은 주석을 확인해주세요.
  4. 최종적으로 하나씩 다듬은 문자열을 fstring을 써서 포맷팅을 해줍니다.

다른풀이

def travel(r, zipcode):
    streets = []
    nums = []
    addresses = r.split(',')
    for address in addresses:
        if ' '.join(address.split()[-2:]) == zipcode:
            streets.append(' '.join(address.split()[1:-2]))
            nums += address.split()[:1]
    return '{}:{}/{}'.format(zipcode, ','.join(streets), ','.join(nums))
  1. 최종적으로 포매팅 하는것만 똑같고, 간결함에서 많이 차이가 나네요 😓
  2. 고객주소에서 zipcode 추출을 위해 split()과 [-2:] 슬라이싱을 활용했습니다. 문자열에서 zipcode형식이 고정되어있기 때문에 가능한 방법입니다.
  3. 숫자를 추출할 때도 마찬가지로 split()과 슬라이싱을 활용합니다.
  4. 여기서 포인트는 ','.join 형식입니다. 저도 처음에 엇 집주소나 숫자가 하나일경우 콤마가 있으면 안되는거 아닌가 생각했는데 ','.join은 문자가 하나면 콤마없이 붙여줍니다. 그러므로 깔끔하게 문제가 해결이 되네요. 👍
profile
어려운 것은 없다, 다만 아직 익숙치않을뿐이다.
post-custom-banner

0개의 댓글