CEDEC2009行ってきた

9/1〜3と有給休暇をとって、CEDEC2009に行ってきた。
仕事ではなく、個人の立場で。


目的は気分転換と、他の業界のソフト開発体制のお勉強。
いつも仕事でソフトウェア開発をしているのだけれども、
他社・他の業界でのソフト開発はどんな風なのか興味があったので。
# 私は情報・通信サービス/機器メーカ勤務


聴講したセッションは下記の通り。


9/1

  • 情報技術はどこへ行くのか?―主役は交代している―
  • ゲーム開発技術の歴史を編纂する〜ゲームデザインからAIまで〜
  • 画像認識技術とゲーム・インターフェイス
  • 米国の産学連携成功事例
  • 工学としてのAI、理学としてのAI―――RoboCupを題材として―――
  • UnrealEngine UI構築


9/2

  • 慣れたら死ぬぞ
  • ハイパフォーマンスコンピューティングとゲームの"深い関係"
  • プログラマー10名でのPS3タイトル開発
  • 海外ゲーム会社の入社問題傾向と対策
  • スクウェア・エニックスの、ちょっといいプログラム


9/3

  • 国民的ゲームとは何か? 〜ドラゴンクエストの場合〜
  • モーションコントローラ(仮称)はこうして開発した!
  • SIGGRAPH ASIAとゲーム技術の展望
  • Natural Expressionへの挑戦
  • IMAGIRE DAY: 3Dゲーム開発マニアックス
  • ゲームAIを横浜で語る


まず、いずれのセッションもとても面白かった。
敢えて濃淡をつけるとすれば、やはり自分の普段の業務から、遠い話題の方が興味をかき立てられた。
9/1では2コマ目と6コマ目、9/2では1・3・4コマ目、9/3では1・2・4・6コマ目が、個人的にはエキサイティングだった。


来年も仕事の都合をつけて、何とか参加したいところ。

mavenプロジェクトのテストパッケージでプロファイルの取得が可能に

NetBeans 6.7で、mavenプロジェクト中のテストパッケージに含まれるファイルについて、
簡単にプロファイルがとれるようになっている。


具体的には、テストコードのファイルを右クリックして「ファイルをプロファイル」を選べば良い。
# 私が確認したのは、JUnit対応のテストコード


NetBeans 6.5では、「プロファイルを開始できません。 プロジェクトの種類がサポートされていること、または選択したファイルを実行できること、あるいはその両方を確認してください。」と表示されてしまい、テストコードのプロファイルをとることができなかった。
# mavenプロジェクトではなく、NetBeansプロジェクトならば6.5でもテストコードのプロファイル取得が可能だったことを、今確認した。


個人的にはこれはかなりうれしい。うれしい理由は、プロファイルを見る機会が増えそうなこと。私はあまりプロファイルを見る癖がないので、これを機会にプロファイルと仲良くしてみようかなぁ。本来ならば、テストコードとプロファイル取得用のコードは別物なのだろうけど、プロファイルを見慣れておくだけでも、いざ実行速度で困ったときに役立つかもしれない。


ところで、私は今までプロファイルを見る癖が無かったのだけれども、普通のプログラマはいつも見ているものなのだろうか?
今調べたところ、mavenにはtestゴールはあっても、profileゴールは無いみたい。
NetBeansを通さずにmavenとそのプラグインだけでプロファイルをとる方法はあるのだろうか。
# ぐぐってみたけどsettings.xmlに記述するprofileばかりが検索にかかり、実行パフォーマンス測定の方はうまく探せない


ユニットテストと比べると、プロファイルは縁遠いというのが私の感覚だけど、どうなんだろう。
普段見慣れていないと「うまくプロファイルをとるノウハウ」みたいなものが、習得できないような。
# 少なくとも、私はできていない…

モグボナンザ

先ほど、ボナンザマーブルを20個ほど購入した。


ボナンザマーブルというのは、つまるところFFXI(ファイナルファンタジー11。オンラインゲームです)の世界での宝くじ。
5/31が最終販売日だったので、駆け込み購入したというわけである。
とあるゲームサイトを見ていたら、販売期間終了間近であることに気づかされてしまったので、つい。


実のところ、FFXIにはしばらく(半年程度)ログインしていなかった。
さらに言うと、その前には3年近くログインしていなかったことがある。


それをわざわざ宝くじ買うためにログインするのか、というのがこのエントリの問題意識である。


何故、バーチャルワールドにまで出かけて、宝くじ購入などという小市民ぶりを発揮せねばならんのか。


しかも、理由が理由な上に、思いっきり幽霊部員なので、LS(リンクシェル。つまりFFXIの世界でのサークルです)のメンバに見つからないように、ものすごく速攻で購入した。
どこで発売しているのか、直前にWebで調査までして、最短距離で売り場に向かった。


ありえない。


闇の王をも倒す冒険者のはずなのに、やってることは宝くじダッシュである。
自分でやっておいて、意味が分からない。
しかも見事に当たって、すごいアイテムを手に入れたとしても何の役にも立たない。
これは「ゲームの世界でアイテムとか手に入れても現実には意味ないよね〜」とかしょっぱいことを言っているのではない。
ログインしないのだからアイテムを手に入れても楽しみようが無いのである。


しかしまあ、現実の私は小市民な訳で、バーチャルには「事実上の、実質上の」という意味があるとのこと(wikipedia:バーチャル)なので、これはこれで、とても正しくバーチャルなのかもしれない。
MMO(Massive Multiplayer Online。大勢で楽しむオンライン)である以上、中の人の大多数は小市民なのであり、その結果として、その辺りをうろついているキャラクターも、ほとんどが小市民である。
数少ない(卓越した演技力を持つ)例外は、勇者さまと呼ばれるらしいが、私は目撃したことがないし、その必要もない。
運営側がわざわざヒーローユニット(中の人が居ない、コンピュータ制御の勇者さま)を配置して野次馬根性を満足させてくれるからである。


OK。私はバーチャルワールドで宝くじダッシュをしても良いんだ。
おかしくない。それが普通なんだ。踊らされてる。安心した。


というわけで、モンハン(MHP2G、ソロ)に戻ります。

Project Euler (Problem ID 35..40)

ID35から40は、割とあっさり解けた。


実行時間が長いのはID35、ID37、ID39で、それぞれ約4秒、2秒、5秒。
Project Eulerの問題は全て30秒以内に解けるようにできているとのこと。
一応30秒以内には解けているけれども、ID35..40の出題時期は2003年なので、その当時のPCだと30秒を超えてしまうかもしれない。

ID 35..40

import Char
import List

isPrime n
	| n < 0 = False
	| n == 1 = False
	| otherwise = all (\p -> (rem n p) /= 0) ps
		where ps = takeWhile (\p -> p * p <= n) primes

primes = [2] ++ sieve [3,5..]
	where sieve (p:ns) = [p] ++ (sieve $ filter (\n -> rem n p /= 0) ns)

toInts n = toIntsWithRadix 10 n
theNum ns = foldl (\x y -> (10 * x) + y) 0 ns

toIntsWithRadix r n = toIntsRec r 1 n
	where toIntsRec r d n
		| r > n = [n]
		| otherwise = (toIntsRec r (d + 1) (div n r)) ++ [rem n r]

prog035 = length $ filter isCircularPrime $ map toInts [2..1000000]
	where
		isCircularPrime ns = all isPrime $ map theNum $ rotates ns
		rotates xs = map (rotate xs) [0..(length xs - 1)]
			where rotate xs n = (drop n xs) ++ (take n xs)

prog036 = sum $ filter palindromic2 $ filter palindromic10 $ [1,3..(1000 * 1000 -1)]
	where
		palindromic2 n = (==) (toBins n) (reverse $ toBins n)
		palindromic10 n = (==) (show n) (reverse $ show n)
		toBins n = toIntsWithRadix 2 n

prog037 = sum $ take 11 $ filter truncatablePrime [11,13..]
	where
		truncatablePrime n = all isPrime $ truncates n
		truncates n = map theNum $
			((truncsLeft $ toInts n) ++ (truncsRight $ toInts n))
		truncsLeft [] = []
		truncsLeft (n:ns) = [(n:ns)] ++ truncsLeft ns
		truncsRight ns = map reverse $ truncsLeft $ reverse ns

prog038 = head $ reverse $ sort $ map theNum $ filter pandigital $ concatMap concatProds [2..9]
	where
		concatProds n = takeWhile (\ns -> length ns <= 9) $ map (concatProd n) [1..]
		concatProd n m = concatMap toInts $ [(m * i) | i <- [1..n]]
		pandigital ns = (sort ns) == [1..9]

prog039 = elemIndex maxTriangles triangles
	where
		maxTriangles = maximum triangles
		triangles = map length $ map pythag [0..1000]
		pythag p = [(a,b,c) |
			c <- [(div (4 * p) 10)..(div p 2)],
			b <- [((div (p - c) 2) + 1)..(c - 1)],
			a <- [p - (b + c)],
			a^2 + b^2 == c^2]

prog040 = product $ map dn $ map ((^)10) [0..6]
	where
		dn n = theFraction !! (n - 1)
		theFraction = concatMap toInts [1..]

main = putStrLn $ show $ prog040

Project Euler (Problem ID 33..34)

ID33は、消去される数をcとして、特に問題無く完了。


ID34では、rangeOfDigitにより解の探索範囲を桁で絞っただけでは、計算時間が30秒を超えてしまった(正解は得られた)。
そこで、さらに枝刈りを追加(condOfNums)し、何とか計算時間を2秒に。
しかし、汚いコードになってしまった…

ID 33..34

prog033 = lowestTerm [pnums, pdenoms]
	where
		pnums = product $ map num $ curiousFracs
		pdenoms = product $ map denom $ curiousFracs
		curiousFracs = filter isCurious $ cnds
		cnds = [[c,n,d] |
			c <- [1..9],
			n <- [1..9],
			d <- [1..9],
			n < d,
			not (c == n && n == d)]

		lowestTerm [n,d] = [div n g, div d g]
			where g = gcd n d

		num [c,n,d] = n * 10 + c
		denom [c,n,d] = c * 10 + d

		isCurious [c,n,d]
			= lowestTerm (curiousFrac [c,n,d]) == lowestTerm [n,d]

		curiousFrac [c,n,d] = [num [c,n,d], denom [c,n,d]]


frac n = product [1..n]

theNum ns = foldl (\x y -> (10 * x) + y) 0 ns

sumOfFrac [] = 0
sumOfFrac (n:ns) = frac n + sumOfFrac ns

rangeOfDigit = takeWhile condOfDigit [2..]
	where
		condOfDigit d = minNum d <= maxSumOfFrac d
		minNum d = 10^(d - 1)
		maxSumOfFrac d = d * frac 9

nums nss d
	| length (head nss) == d = nss
	| mss == [] = []
	| otherwise = nums (concatMap (genNums d) mss) d
		where
			mss = filter (condOfNums d) $ nss
			genNums d ns = [ns ++ [n] | n <- [0..9]]
			condOfNums d ns = theNum (ns0s d ns) <= sumOfFrac ns + (frac 9 * rest)
				where
					ns0s d ns = ns ++ take rest [0..]
					rest = d - length ns

anss d = filter (\ns -> theNum ns == sumOfFrac ns) $ nums [[n] | n <- [1..9]] d

prog034 = sum $ map theNum $ concatMap anss rangeOfDigit

main = putStrLn $ show $ prog034

うちのNetBeansのmavenがsiteプラグインを苦手としている件

NetBeans組み込みのmavenは、siteプラグインの実行が苦手なようである。
手元の環境では、NetBeans 6.1でも6.5でもsite:siteゴールがエラー終了する。


当面の解決策は、NetBeans組み込みのmaven(3.0-SNAPSHOT)ではなく、別途インストールしたmavenを使うことである。
NetBeansのオプション→その他→Mavenにある、External Maven Homeという設定を変更することで、組み込み以外のmavenを使用することができる。


私の場合では、maven-2.0.9を使用することで、無事にsite:siteゴールをNetBeans上から実行できた。


なお、もし既にExternal Maven Homeの入力欄の直下に、「Version: 2.09」などと表示されているならば、NetBeansは組み込み以外のmavenを使用する設定になっている。

Project Euler (Problem ID 31..32)

ID31は、問題文をそのままコードに。


ID32では、ID24で上手く書けなかったpermutationを書き直した。multiplicandとmultiplier、productの桁数の組み合わせをsepsにて絞り込んだつもりだったが、実行時間を計測すると約1.5秒。もう少し速くなりそうな気がする。

ID 31..32

import List

prog031 = ways2pay 200 coins
	where
		ways2pay 0 _ = 1
		ways2pay _ [] = 0
		ways2pay price (c:cs)
			| price < 0 = 0
			| otherwise = (ways2pay (price - c) (c:cs)) + (ways2pay price cs)
		coins = [200,100,50,20,10,5,2,1]

uniq [] = []
uniq (x:[]) = [x]
uniq (x:xs) 
	| x == head xs = uniq xs
	| otherwise = (x:uniq xs)

permutation [] = [[]]
permutation xs = [(y:ys) | y <- xs, ys <- permutation (delete y xs)]

digits2int ds = foldl (\x y -> (10 * x) + y) 0 ds

prog032 = sum $ uniq $ sort $ map (dt2int 5 4) $ filter pandigital $ permutation [1,2,3,4,5,6,7,8,9]
	where
		pandigital ds = any (pand ds) $ seps
		seps = [(dmc, dm, dp) | dmc <- [1..7], dm <- [1..7], dp <- [1..7], dmc <= dm, dm <= dp, dmc + dm + dp == 9, dmc + dm - 2 <= dp, dp <= dmc + dm]
		pand ds sep = mc * m == p
			where
				mc = dt2int 0 dmc ds
				m = dt2int dmc dm ds
				p = dt2int (dmc + dm) dp ds
				(dmc, dm, dp) = sep
		dt2int d t ds = digits2int $ take t $ drop d ds
		digits = permutation [1,2,3,4,5,6,7,8,9]

main = putStrLn $ show $ prog032