프로젝트 오일러 022

영문이름의 점수 합계 구하기

프로젝트 오일러 022
Photo by CHUTTERSNAP / Unsplash

문제

22번 문제
영문 이름 점수 합계 구하기

전체적으로 평이한 문제입니다. 이름의 정렬이야, sorted() 함수가 있으니 간단하고, 이름의 점수를 매기는 함수 역시 간단합니다. 각 알파벳과 그 점수에 대한 맵핑을 만들어도 좋겠지만, 아스키코드에서 알파벳은 순서대로 나열되어 있으니, X라는 문자의 코드값에 'A'의 문자 코드값을 빼고 1을 더하면 문자 X의 점수값이 나옵니다.

따지고보면 이 문제에서 어려운 부분은, 텍스트 파일을 다운로드 받을 부분일까요? 참고로 데이터의 URL은 아래와 같습니다.

https://euler.synap.co.kr/files/names.txt

그 외에는 특별히 난해할 것 없는 코드입니다.

from urllib.request import urlopen

url = "https://euler.synap.co.kr/files/names.txt"
text = urlopen(url).read().decode()
names = [name.strip('"') for name in text.split(',')]

res = 0

score = lambda x: ord(x) - ord('A') + 1
for (i, x) in enumerate(sorted(names)):
    res += (i + 1) * sum(map(score, x))

print(res)

문제의 이름 데이터에는 콤마로 구분된 이름들이 따옴표로 싸여있습니다. 따라서 데이터를 콤마 단위로 끊은 후, 각각의 데이터에서 겹따옴표를 제거했습니다. 굳이 이렇게 하지 않더라도 점수 계산하는 함수에서 A ... Z 범위 사이의 문자가 아니면 0점으로 처리하는 것도 방법이 될 수 있습니다.

정렬

정렬을 구현하거나 정렬에 관련되 문제가 프로젝트 오일러에 얼마나 나올지 모르겠습니다만, 어쩌면 이 문제는 정렬을 직접 구현해보라는 취지에서 만들어졌을 수 있습니다.

왜냐하면 이름 데이터를 살펴보면 정렬되지 않은 순서로 배치된 단어가 전체의 80% 가까이 됩니다. 이는 자연적인 데이터에서는 흔하지 않은 경우에 해당합니다. (많은 경우 데이터는 특정한 기준에 따라 쌓이는 경향이 있기 때문에 기본적으로는 어느 정도 정렬되어 있는 경우가 많습니다.)

그래서 최악의 경우에 효율이 좋지 않은 정렬 알고리듬도 실제로는 그렇게 나쁘지만은 않은 경우도 종종 있습니다.

정렬 알고리듬의 구현은 여기서 다루고픈 내용은 아니니까 넘어가겠습니다.