2012-05-17
逆FizzBuzz問題
近未来、2016年(・・・って、中途半端に近い未来ですね)では、
Googleの入社試験では、逆FizzBuzz問題を解くことになるそうな。
- 逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記
- F#で逆FizzBuzz問題 - Bug Catharsis
- わぁいInverse Fizzbuzz解けたよー - 這い寄るゆろよろ・アンド・ライジングフォース日記
- Inverse Fizzbuzz - scalaとか・・・
- 逆FizzBuzz問題をTrieでトライ - athosの日記
fizzbuzzした結果のリストから、それを生成するような最短の数値の範囲を求める、という問題です。
Pythonでやってみた感想は「やっぱり無名関数が欲しいなぁ」。名前を付けたほうが後々役立つのはそうなんでしょうが、こういった処理ではイマイチ良い名前が浮かばないことも多い。コードで言うと、candidatesとか。
#!python3 # -*- coding: ascii -*- #invertfizzbuzz.py """ >>> from invertfizzbuzz import invert_fizzbuzz >>> invert_fizzbuzz("fizz".split()) range(3, 4) >>> invert_fizzbuzz("buzz".split()) range(5, 6) >>> invert_fizzbuzz("fizz buzz".split()) range(9, 11) >>> invert_fizzbuzz("buzz fizz".split()) range(5, 7) >>> invert_fizzbuzz("fizz buzz fizz".split()) range(3, 7) >>> invert_fizzbuzz("fizz fizz".split()) range(6, 10) >>> invert_fizzbuzz("fizz fizz buzz".split()) range(6, 11) """ from iterutils import unique_everseen, count def fizzbuzz(x): if x % 15 == 0: return "fizzbuzz" elif x % 3 == 0: return "fizz" elif x % 5 == 0: return "buzz" else: return x def fizzbuzz_words_with_length(start, length): words = [] for n in count(start): v = fb(n) if isinstance(v, str): words.append(v) if len(words) == length: return words, n + 1 def invert_fizzbuzz(words): words = list(words) if not words: return range(1,1) start_points = [3, 5, 6, 9, 10, 12, 15] invert_fizzbuzz = {} candidates = [] for begin in start_points: fb, end = fizzbuzz_words_with_length(begin, len(words)) if fb == words: candidates.append(range(begin, end)) return min(candidates, key=len) if __name__ == "__main__": import doctest doctest.testmod()
就職してから1回もブログを更新してないぜ。
2012-03-22
setup.pyについてのいくつかのメモ
モジュールにソースコード以外のファイルを添付する
添付の種類は4種類あります.
(1 - 3) setupの引数として指定する(scripts, package_data, data_files).
setup.py内のsetup関数の引数としてファイルを指定します. scripts, package_data, data_filesの違いは, インストール先です.
- scripts
- Scriptsフォルダ(C:\Python32\Scripts)
- data_files
- パッケージ(C:\Python32\Lib\site-packages\(パッケージ名))
- package_data
- サブパッケージ(C:\Python32\Lib\site-packages\(パッケージ名)\(サブパッケージ))
括弧内はPython 3.2.x Windows版の場合の位置です.
次のようなsetup.pyを書いて, python setup.py installすると…
from setuptools import setup
setup(
#パッケージの定義, 2つのサブパッケージを含む
name="foods",
packages = ["fish", "meat"],
package_dir={'fish':'fish', "meat":"meat"},
#サブパッケージごとのデータファイル
#元々のフォルダ構造を反映する
package_data={
"fish": ["red/tuna.js"],
"meat": ["beaf.js"],
},
#サブパッケージには所属しないデータファイル
#元々のフォルダ構造は無視される
#("配置先フォルダ名", ["ファイル", "ファイル", "ファイル"...]), ... の形式
#配置先フォルダはネストしてよい
data_files = [
("raw-fish", ["salmon.txt"]),
("fishery/processing/kamaboko", "sasa.bmp kamaboko/yaki.rb".split()),
],
#スクリプトファイル
#元々のフォルダ構造は無視される
#配置先もScriptsの直下のみ
scripts = "sashimi.sh sh_files/arajiru.bat".split(),
#zip_safe=Trueにすると, 全てのファイルを単一の.egg(zipファイル)にまとめる
#デフォルトでは, zip_safe=True
zip_safe=False,
)
#ちなみに, str.split を使うと perlやrubyの%w() のように
#空白で区切って, 文字列のリストが作れるので便利
こういうふうに配置されます.
C:\Python32\lib\site-packages\seafoods\EGG-INFO\scripts\arajiru.bat C:\Python32\lib\site-packages\seafoods\EGG-INFO\scripts\sashimi.sh C:\Python32\lib\site-packages\seafoods\fish\red\tuna.js C:\Python32\lib\site-packages\seafoods\fish\__init__.py C:\Python32\lib\site-packages\seafoods\fishery\processing\kamaboko\sasa.bmp C:\Python32\lib\site-packages\seafoods\fishery\processing\kamaboko\yaki.rb C:\Python32\lib\site-packages\seafoods\meat\beaf.js C:\Python32\lib\site-packages\seafoods\meat\__init__.py C:\Python32\lib\site-packages\seafoods\raw-fish\salmon.txt C:\Python32\Scripts\arajiru.bat C:\Python32\Scripts\sashimi.sh
(4) MANIFEST.in
READMEやHISTORYのように, パッケージの使用時には役に立たないが, sdistには含めたいようなファイルは, MANIFEST.inファイルに記述します.
include README include HISTORY include junk/food/*.txt
ワイルドカードも使用可です.
落とし穴
1 - 3 の setupの引数に指定する方法ですが, そのままではpython setup sdistした時に, zipやtarにファイルが追加されません!
少なくとも, 私が試した限りではそうでした. なんてこった!バグか!?
zipやtarに追加するには, MANIFEST.inに含めたいファイルを全て書き下す必要があります. 二度手間ですが, 仕方ありません.
参照
これらについての正確な情報は,
- http://www.python.jp/doc/2.7/distutils/index.html(日本語 2.7)
- http://docs.python.org/release/3.2.2/distutils/index.html(英語 3.2)
などをご覧下さい.
2012-02-04
Python 2.6との後方互換性を保つための4種のTips または, 2.7の新機能紹介
Pythonは2.7が2010年7月にリリースされ, 現在では2.8をリリースするかが問題になっているようですが, 今でも旧バージョンである2.6への需要は存在するようです.
ここでは, 2.6互換にするために注意する点を紹介します.
1. 標準ライブラリ
当たり前ですが, 2.7で新しく入ったライブラリは2.6にはありません. しかし PyPIを探せば, 同等品があるはずです.
例えば, collections.OrderedDictの場合は, ordereddictがあるので,
try:
from collections import OrderedDict
except ImportError
from ordereddict import OrderedDict
とすれば, 2.6でも動きます.
他にも, argparseやunittestの新機能(PyPIではunittest2)などが該当します.
2. with文
2.7(や, 3.x)では, with文に複数の as を書くことができます.
with open("a.txt") as fa, open("b.txt") as fb:
# faとfbを処理…
これは, 2.6にはありません. 代わりに, contextlib.nestedを使います.
from contextlib import nested
with nested(open("a.txt"), open("b.txt")) as (fa, fb):
# faとfbを処理…
3. 辞書内包表記
{i:2**i for i in range(10)}
辞書内包表記は, 2.6用のコードでは, dict()を使うよう気をつけましょう.
dict(i:2**i for i in range(10))
4. 文字列format
2.7では文字列フォーマットの, 番号を省略できます.
'{}-{}.txt'.format(3, 14) # => '3-14.txt'
しかし, 2.6では番号は省略出来ません. 必ず明示的に各必要があります.
#2.6互換な書き方. 番号を明示する.
'{0}-{1}.txt'.format(3, 14) # => '3-14.txt'
辞書内包表記と違って, formatを間違えた時は, シンタックスエラーにならないので注意が必要です.
ただし, そもそも番号で指定するよりも, キーワード引数で指定し, その値が何を表すのか明示したほうが良いかも知れません.
#ベターな書き方. これも2.6互換
'{month}-{day}.txt'.format(month=3, day=14) # => '3-14.txt'
2.5との後方互換
2.5と3.xの両方で動くコードを書くのは困難です.
なぜなら,
from __future__ import unicode_literals
が動かないので, 文字列関係で大規模な変更が必要になるかもしれません.
2.5〜2.7の互換性に限るならば, 2.5では使えないprint関数など避けて, ライブラリもPyPIからインストールすれば可能です.
またwith文も,
from __future__ import with_statement
とすれば, 2.5でも使用可能です.
2012-01-28
グローバル変数は必要です
Life is beautiful: Python Hack : 噛めば噛むほどおいしくなるクロージャの話クロージャと無名関数を使うと、こんな風に実装することができる。
import yaml def _get_from_disk(): data = open('config.yaml').read().decode('utf8') config = yaml.load(data) # クロージャ内に隠蔽・保持されるローカル変数 global get get = lambda : config # 二回目からはconfigを返す無名関数を呼ぶ様に変更 return get() get = _get_from_disk # 初回のみローダーを実行
いやいや、それはいけません!
このコードは、config.py というモジュールの一部で、
import config #config.get()を使って処理
という使い方を想定していますが、こういう使い方も出来てしまいます。
from config import get as config_get #get()を使って処理
こうすると、config_getの参照先は、config.pyの中でどんな処理をしようと、_get_from_diskのままなので、config_getを呼び出すと毎回ファイルを読み込むことになってしまいます。
同じ問題は、メソッドでも発生します。メソッドオブジェクトを変数に代入した場合です。たとえば、
#!python3 # -*- coding: cp932 -*- class Config: def get(self): self.get = lambda : 1 #2回目以降は1を返すつもり return 0 # 初回のみ0を返すつもり c = Config() get = c.get #メソッドを変数に代入 print(c.get()) # => 0 print(c.get()) # => 1 print(get()) # => 0
というわけで、「初回のみ〜する」場合は、諦めてグローバル変数やメンバ変数を使いましょう。
全ての大学は職業教育の場です!
ちょうど気になる記事が紹介されたので、
修士論文の代わりに退学願を提出してきた http://blog.riywo.com/2009/02/27/120733
私自身も、就職活動に七転八倒した口で、昨日修士論文を提出し終わった所なので、思うことを書いてみます。
学問の府?
「やる気がある学生だけ来ればいい」「大学は学問の府」という意見は、しばしば重要な点を見落としています。それは、研究者になるのは学生のうちほんの僅かという点、そして研究者にならないからと言って劣った学生とは限らない点です。
2012-01-20
声に出して読みたい7つのPython用語
冷凍マグロ系スクリプト言語として知られるPythonの、もっともすばらしい用語7点をご紹介します。これらのネーミングセンスを身につけることによって、PHPerやRubyistでは不可能な変態力を身につける事が出来るでしょう(Perl Mongerには負けるかも知れない)。
PyPI(ぱいぱい or ぱいぴいあい)
PyPIはPythonライブラリを誰でも登録・ダウンロードできる、PerlのCPAN・Rubyのgemに当たるものです。4月になったら新人プログラマーに教えてあげましょう。
例:PyPIは基本だ!
PIL(ぴる)
PILは画像処理用のライブラリです。高度な処理はできませんが、手軽に画像を扱う事ができるので、簡単な処理にもフォトショを使っている人を見たらこう言っておきましょう。
例:PILは絶対使っとけ!
なお、Pillow(ぴろー)(英語で枕の意)というforkがあり、インストーラでしかインストール出来ないPILと違い、PillowはPyPIからeasy_installできます。
PyPy(ぱいぱい)
PyPyはPythonの実装の一つです。C言語ではなくRPythonというPythonのサブセットで書かれています。近年JITコンパイラによる高速化で注目されており、PyPyのベンチマークを見たあなたは思わずこう叫ぶはずです。
例:PyPyには感動した!
Pyzuri(ぱいずり)
PyzuriはPythonからpixivを扱うことができるライブラリです。IDから画像やユーザーの情報を取得できます。pixivのデータが欲しい人は、一度Pyzuriを試してみましょう。すると、こんな感想を抱くかも知れません。
例:Pyzuriにトライしたけど、良かったよ!
pypants(ぱいぱんつ)
pypantsはPythonライブラリのPyPIとgithub登録できるWEBサービスです。そんなに流行っているサービスでは無いというか、ぶっちゃけ使い方がよくわからないのですが、コミット頻度などが見れるのが役立つのかも知れません。
例:pypantsは見たのか!?
Pychinko(ぱいちんこ)
PychinkoはRete algorithmのライブラリで、CWMのクローンらしいです。ぶっちゃけ、どう使うライブラリなのかイマイチわかりません。日本ではその印象的な名前のみが知られている状態のようです。でも、きっと、必要な人には必要なのでしょう。SVNは落ちてますけど。
例:Pychinkoを試してみるぞ!
pypan(ぱいぱん)
pypanはPythonのパッケージマネージャーです、以上!distributeやpipとはどう違うのか、とかは分かりません。だって、PyPIにはソースは置いてないし、ホームページも404なんだもん。でも、完成の暁には、思わずこう叫んでしまうでしょう。
例:pypanじゃなきゃダメなんだ!
実践編
明日の朝職場に出たら、これらの例文を大きな声で叫びましょう。あなたが真のPython系(下半身的な意味で)プログラマーとして認められ、名誉の懲戒免職処分が下ること請け合いです。
え?もしクビにならなかったら?むしろ、賛同の声が上がったら?……その職場はもう駄目なのかも知れません。
オマケspam(スパム)
Spamです。SpamはPythonプログラマーのspam力の源泉ですから、直ちにeasy_install spamに失敗した後, spam 3.0 : Python Package Indexでそのspamっぷりを感じるべきスパム。
例:Spamspamspamspamspamspamspamspamspamspamspamspamspamspam

