Project Euler 022
5000個以上の名前が書かれている46Kのテキストファイルnames.txtを用いる. まずアルファベット順にソートせよ.
のち, 各名前についてアルファベットに値を割り振り, リスト中の出現順の数と掛け合わせることで, 名前のスコアを計算する.
たとえば, リストがアルファベット順にソートされているとすると, COLINはリストの938番目にある. またCOLINは 3 + 15 + 12 + 9 + 14 = 53 という値を持つ. よってCOLINは 938 × 53 = 49714 というスコアを持つ.
ファイル中の全名前のスコアの合計を求めよ.
->次の問題
初め「アルファベットに値を割り振り〜」ってなんだろうと思いましたが、A=1 B=2 C=3のようにアルファベット順に値をつけるって意味でした。
考え方
まず、与えられたテキストを確認してみたところ、
- 改行なし。1行に全ての名前が記載。
- 名前は前後に
"
あり。 -
,
区切り、スペースなし。
という形式でした。まずはテキストを読み込んでリストに変換します。
# ファイルを開いてtxtに読み込み
with open('names.txt') as file:
txt = file.readline()
# 不要な"を除去
txt = txt.replace('"', '')
# ,区切りでリストに変換
names = txt.split(',')
# ソート
names.sort()
ついでにソートしています。もしかしたら問題としてはソートするアルゴリズムを自分で作って欲しいのかもしれませんが、組み込みで入っているものは使ってよいのだの精神で行きます。
nameのアルファベットスコアを出す部分は関数として定義しました。
ordを使うことで文字コードに変換できるのでそれぞれの文字コードから「A-1の文字コード」を引いています。
def name_to_score(name: str) -> int:
"""
nameの文字列をスコアに変換する
A = 1, B = 2,...として和を返す
ordで文字コードに変換 ord('A')=65なのでそれぞれの文字コードから64を引いている
:param name: str
:return: int
"""
base = ord('A') - 1
return sum([(ord(char) - base) for char in name])
あとは算出したアルファベットスコアに順番をかけて合計すればOKです。
enumulateを使用してインデックスとリストの中身を同時に取得しています。
コード
def main():
with open('names.txt') as file:
txt = file.readline()
txt = txt.replace('"', '')
names = txt.split(',')
names.sort()
scored_names = [(i + 1) * name_to_score(name) for i, name in enumerate(names)]
print(sum(scored_names))
def name_to_score(name: str) -> int:
"""
nameの文字列をスコアに変換する
A = 1, B = 2,...として和を返す
ordで文字コードに変換 ord('A')=65なのでそれぞれの文字コードから64を引いている
:param name: str
:return: int
"""
base = ord('A') - 1
return sum([(ord(char) - base) for char in name])
if __name__ == '__main__':
main()
Mac book proにて実行
結果 871198282 main処理時間: 0.00870203971862793 sec.