言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。
第1章: 準備運動
###04.元素記号
"Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."という文を単語に分解し,1, 5, 6, 7, 8, 9, 15, 16, 19番目の単語は先頭の1文字,それ以外の単語は先頭に2文字を取り出し,取り出した文字列から単語の位置(先頭から何番目の単語か)への連想配列(辞書型もしくはマップ型)を作成せよ.
出来上がったコード:
# coding: utf-8
num_first_only = (1, 5, 6, 7, 8, 9, 15, 16, 19)
target = 'Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can.'
result = {}
words = target.split(' ')
for (num, word) in enumerate(words, 1):
if num in num_first_only:
result[word[0:1]] = num
else:
result[word[0:2]] = num
print(result)
実行結果:
{'K': 19, 'S': 16, 'He': 2, 'Al': 13, 'B': 5, 'Mi': 12, 'C': 6, 'O': 8, 'Li': 3, 'N': 7, 'Na': 11, 'H': 1, 'Si': 14, 'P': 15, 'Ne': 10, 'Ca': 20, 'Ar': 18, 'F': 9, 'Be': 4, 'Cl': 17}
あれ?原子番号12のMg(マグネシウム)だけおかしいですね。Miになっています。でも、該当する位置の単語はMightなので、プログラムは正しそう。
enumerate()
が開始番号を指定できるのは便利。進んでしまったイテラブルの途中から列挙したい場合などに、コードがシンプルになりそうです。
###実行する度に結果が変わる!?
このプログラム、実行する度に結果が変化することに気づきました。
{'B': 5, 'Al': 13, 'Be': 4, 'Cl': 17, 'P': 15, 'Si': 14, 'Ca': 20, 'Ne': 10, 'O': 8, 'K': 19, 'S': 16, 'Li': 3, 'He': 2, 'Na': 11, 'C': 6, 'Ar': 18, 'Mi': 12, 'H': 1, 'F': 9, 'N': 7}
{'B': 5, 'He': 2, 'H': 1, 'C': 6, 'Be': 4, 'Si': 14, 'O': 8, 'F': 9, 'P': 15, 'Ca': 20, 'Al': 13, 'Ne': 10, 'Li': 3, 'K': 19, 'S': 16, 'Ar': 18, 'Cl': 17, 'Mi': 12, 'Na': 11, 'N': 7}
{'Cl': 17, 'Si': 14, 'Al': 13, 'C': 6, 'Ca': 20, 'O': 8, 'He': 2, 'N': 7, 'F': 9, 'Ar': 18, 'Na': 11, 'Mi': 12, 'H': 1, 'P': 15, 'Be': 4, 'Ne': 10, 'Li': 3, 'B': 5, 'S': 16, 'K': 19}
辞書への格納順序は全く同じなので、なかなか興味深い挙動です。実行の度にハッシュ関数が変化しているのでしょうか。でも何のために?あ、もしかしたらprint()
時に、使用アドレスの影響を受けて順番が変わるとか?
余談ですが、Cのプログラマ時代、辞書の実装で、衝突によるパフォーマンス悪化と、その回避によるハッシュテーブルのメモリ消費量増大のトレードオフに胃を痛めてきた経験があるので、内部実装が気になります。PythonはCで実装されていると聞いたので、時間に余裕ができたらちょっと覗いてみたいところです。
5本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。