2010-08-23 (Monday) [長年日記] この日を編集
■ DevQuiz for Google Developers Day 2010 Japan
さて、Google Developers Day 2010 Japanに参加するためにはDevQuizの問題を解く必要があったわけですが、そのDevQuizの回答の締切りが今日でした。 ちゅうわけで、さっそくですが、感想戦。
今回のDevQuizはガチ開発者向け Super Hackers枠、Googleコミュニティ開発者向けTop Favorites枠、熱意のあるヤツ向けNext Generation枠というみっつの枠があった。
Super Hackers枠は純粋にプログラミングの勝負に近く、Top Favorites枠はGoogleのプロダクトに関する貢献などが特典に左右されるらしい。Next Generation枠では200文字の小論文というか、Twitterに毛が生えたような長さの文章で熱意を表現すると得点されるんだとか。
Googleに貢献してるかとか、よくわかんないスピリチュアルな文章で挑戦とかガラじゃないので、Super Hackers枠にて参戦。
■ ウォーアップ問題
もう何が出題されたのか忘れた。 簡単な三択とかでググったり、Webアプリケーション使ったら解けました。 おしまい。
■ ラウンド 1: HTML5 間違い探し
すみません、 "HTML5 validator" で検索してでてきたサイトでバリデーションチェックに引っかかったところをそのまんま入力しました。
仕様書とか読んでません。
■ ラウンド 2: 2-legged OAuth
選択問題。もうひとつは「ラウンド 2: Google Maps API」でした。問題文みた瞬間に「あー、これは難しい問題だけど、Maps API使うと解けるってやつか。」とオモイマシタガ、OAuthのほうがソースコードの提出とか必要ないみたいだし、ラクそうなので一撃でクリアーしました。
#!/usr/bin/env ruby
require 'net/http'
require 'digest/md5'
require 'openssl'
require 'uri'
http = Net::HTTP.new('gdd-2010-quiz-japan.appspot.com')
def base64(value)
[ value ].pack('m').gsub(/\n/, '')
end
def digest_hmac_sha1(value)
OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, secret(), value)
end
def secret
"xxxxx" + '&' + ""
end
oauth_headers = {
'oauth_consumer_key' => "xxxxx",
'oauth_nonce' => "#{Digest::MD5.hexdigest(Time.now.to_f.to_s)}",
'oauth_signature_method' => "HMAC-SHA1",
'oauth_timestamp' => "#{Time.now.to_i}",
}
require 'cgi'
oauth_base = oauth_headers.sort.map do |key, value|
"#{key}=#{value}"
end.join('&')
uri = URI.parse('http://gdd-2010-quiz-japan.appspot.com/oauth/xxxxx')
p signature = "POST&" + CGI.escape(uri.to_s) + "&" + CGI.escape('hello=world&'+ oauth_base)
oauth_headers['oauth_signature'] = base64(digest_hmac_sha1(signature))
headers = {
'Authorization' => <<-EOA,
OAuth realm="devquiz",
oauth_consumer_key="#{oauth_headers['oauth_consumer_key']}",
oauth_signature_method="#{oauth_headers['oauth_signature_method']}",
oauth_signature="#{oauth_headers['oauth_signature']}",
oauth_nonce="#{oauth_headers['oauth_nonce']}",
oauth_timestamp="#{oauth_headers['oauth_timestamp']}"
EOA
}
response = http.post(uri.path, 'hello=world', headers)
puts response.body
よく専用のライブラリも使わずに標準ライブラリで解く気になりましたね。 っていうか、ライブラリ探したけど使い方がよくわかんなくて 2-legged OAuth の仕様書読んだほうがはやく解決できました。
おしまい。
■ Super Hackers:Shiritori
Super Hackers枠ねらいの人は回答が必須の問題。 デタラメな英字列でしりとりをする。
レベルは三段階でだんだんとサーバの回答が定型的なハメでプレイヤーをやっつけるパターンになってくるカンジ。要するに特定の英字ではじまる単語を要求し続けることができるような辞書の組み合わせになっている。
辞書からこちらから発言するとハメパターンに陥る語の末尾候補を grep で抜き出して、単語単位で見る必要などないので cut, uniq してキケンなワードは目視で無視して、パターンに陥らないようにしていたら、サーバがハマるワードを回答したのでこっち側がハメパターン回答したら勝てた。
すべての勝利パターンを数え上げるソースコード書いたんだがな・・・レベル3ではメモリ2GBからスラッシング起こしはじめて使えず。まぁ、数え上げできてもわざわざ探すの面倒そうなのでコード書いた意味なかったよ。
#!/usr/bin/env ruby1.9 class Shiritori attr_reader :answers, :words def initialize(words, answers = []) @words = words @answers = answers end def followers(word) @words.map do |w| if word[-1..-1] == w[0..0] then w else nil end end.compact end def answer(word) Shiritori.new(@words - [word], @answers + [word]) end end words = %w(qcazn nzmoc nfndmz nfxjqzfx ckajaeftuz crspflkyyx cmpqthtojp zlsmbux zbgssfqzp zupqplnq xyggruolxp xxowgiq xgripmcunm prkgvipfjq pjgdvfgwm pgiolvwbtfk qjnzgrm qcgbepdkrk qvygdtjfwu muodhdk mfolvctu mmsmjytqnbn kqurxiu kbxpdrnfun kebisc ujkjean ubafnsc ugqaljz nllvwh hvrymqjuuo hxuwevbmnj hfubde csvvdnr rkefyf rkxlzwi rwnlnb zjepxcs sqzqyxfdy spbmuuwg srrqszjhd xvcxh pyclr qyscs mysgh kuvtjr uwxsxzs olzvqgpejf odizhfy ovlkfj ombxpqei odistxbwbpg obijoe otwagogqib ohjcbd okdja omynhtyl osicrjxxkw fuxnpjhqio fkdcy fhoegbaij fwszai febcpqxjpyg fqpnaxoe fydmqosmb ftryiwrhfd ffdxna fewbl fufukxurw ykhippo ybtynsojvnf ydtmj yttohtbci yvxeg ytcme yowuvqkqgsb ygxsijjupd ytjvaala ypnnewwimil ywnffbjyhw jqvqzlo jxtjkqaaumf jhbsydy jedfeuti jnbeelalg jytwe jjpzbypmizb jtgnlad jlmnrca jvahmwl jojfnwasw iosgo iefwyowkcf ixihlcy iuyhqaj ibomxiqqng iybcgyhbe ipgbb iszid ifzba ixjgasssl inektww gkrgo gjmmbfuqvf gafocatxsy glfciweoivj gssji gkgsftpadye gwkernqb gvtvclgxkd gjhxa grttl ghsgdpoiaw eyniowomxho eeyuntf eoafry ejbpnfj eremnehi ehwkg edwdlxgcb ewaofd engra ebizruwzl ewizww bvjkzxuejo bzjbf beqiy bwkdmohqluj bhcmjuji bufsyzg bblke bphlfemcnsd bnhoea baxvwppppl bbsctaublww dbbnhyveboo duncwilf dgidhretxy deaeszcfj dgcuzfi duharynhog dsahqtergge dlfyydsrb dvyfjzjsaa dunvdavrxjl dreazshw arrfeo amxmodf aypeunsy ayrvhczj ahdpbjkni aimwvouazug abxvqgofe aqyib ahxpcabpd aegvvl aljmw llzsmeo lluscekzf luiwy lvrwfilgodj lrvci lpyvtlqgyg lkihxielive lmvylfdlb lxhvkikad lrmqdsohda llzcw wyruzto wijpf wvimevizdy whacj wlqscni wmqsbskg wubkeihe whhcb wbqglevyd wnana wcnjrnhl aghon axkzx atkhimqrm lzewc lynbsp logkfmqwk wjzeygwz wvktvyvyq wtdakfvphu) answers = %w(qcazn) s = Shiritori.new(words - answers, answers - [answers.last]) def solve(shiritori, word, win_patterns = [], lose_patterns = []) followers = shiritori.followers(word) if followers.empty? then if shiritori.answers.size.even? then win_patterns << shiritori else lose_patterns << shiritori end end followers.each do |w| solve(shiritori.answer(word), w, win_patterns, lose_patterns) end return win_patterns, lose_patterns end win_patterns, lose_patterns = solve(s, answers.last) win_patterns.map do |win_pattern| lose_patterns.map do |lose_pattern| if win_pattern.answers.include?(lose_pattern.answers) then nil else win_pattern end end end.flatten.uniq.each do |pattern| p pattern.answers end
■ Super Hackers: PAC-MAN
どう考えても Super Hackers枠の本番ですね。 シミュレータを書いて手動で動かし、その結果を送信する形で得点・・・ が、敵数匹の動きがバグってるみたいで、微妙にしか動かなかったわ。 たぶん、途中でテストも書いてないのに豪快にリファクタリングしたのが原因ですね。 なんとか今までの得点を越えるくらいは得点できていたが。
てか、いま気づいたけど敵の一種類は実装がカラじゃねーの。ダメじゃねーか。 書いたソースコードはこんな感じ。 ヒアドキュメントできれいにマップを表現できた時点で8割くらい満足してしまった気がする。参考になる部分てそこらへんだけかもしれない。
あ。キレイで正常な動きにしてくれる diff 募集中・・・
#!/usr/bin/env ruby1.9
class Map
attr_reader :dots, :player, :now
def initialize(t, w, h, map)
@time = t
@now = 0
@width = w
@height = h
@map = map.split("\n")
@dots = []
@enemies = []
@inputs = []
search_character
end
def search_character
for x in 1..@width do
for y in 1..@height do
case get(x, y)
when '@'
@player = Player.new(self, x, y)
when 'V'
@enemies << EnemyV.new(self, x, y)
@dots << Dot.new(self, x, y)
when 'H'
@enemies << EnemyH.new(self, x, y)
@dots << Dot.new(self, x, y)
when 'L'
@enemies << EnemyL.new(self, x, y)
@dots << Dot.new(self, x, y)
when 'R'
@enemies << EnemyR.new(self, x, y)
@dots << Dot.new(self, x, y)
when 'J'
@enemies << EnemyJ.new(self, x, y)
@dots << Dot.new(self, x, y)
when '.'
@dots << Dot.new(self, x, y)
end
end
end
end
def dump
puts @map
end
def get(x, y)
@map[y - 1][x - 1]
end
def set(x, y, v = ' ')
@map[y - 1][x - 1] = v
end
def available(target, direction)
x = target.x
y = target.y
case direction
when :down
y += 1
when :left
x -= 1
when :up
y -= 1
when :right
x += 1
end
unless get(x, y) == '#' then
true
else
false
end
end
def input(ch)
@inputs << ch
player_pos = [@player.x, @player.y]
case ch
when 'h'
@player.left
when 'j'
@player.down
when 'k'
@player.up
when 'l'
@player.right
when '.'
when 'q'
game_end
end
@enemies.each do |enemy|
if @now == 0 then
enemy.first_move
else
enemy.move
end
end
@dots.each do |dot|
if dot.enable? and get(dot.x, dot.y) then
dot.write
end
end
@enemies.each do |enemy|
enemy.write
next unless enemy.x == @player.x
next unless enemy.y == @player.y
next unless enemy.swap?(@player)
game_end
end
@player.write
@now += 1
end
def game_end
@inputs.delete('q')
puts "answer: #{@inputs.join}"
puts "time: #{@inputs.join.size}"
exit
end
end
class Dot
attr_reader :x, :y
def initialize(map, x, y)
@map = map
@x = x
@y = y
@enable = true
end
def enable?
@enable
end
def disable
@enable = false
end
def write
@map.set(@x, @y, '.')
end
end
class Character
def swap?(target)
return false unless self.x == target.xx
return false unless self.yy == target.y
return true
end
end
class Player < Character
attr_reader :x, :y, :xx, :yy
def initialize(map, x, y)
@map = map
@xx = @x = x
@yy = @y = y
end
def left
pre_walk
@xx = @x
@x -= 1
walk
end
def down
pre_walk
@yy = @y
@y += 1
walk
end
def up
pre_walk
@yy = @y
@y -=1
walk
end
def right
pre_walk
@xx = @x
@x += 1
walk
end
def pre_walk
@map.set(@x, @y, ' ')
end
def walk
@map.dots.each do |dot|
if dot.x == @x and dot.y == @y then
dot.disable
end
end
end
def write
@map.set(@x, @y, '@')
end
end
class Enemy < Character
attr_reader :x, :y, :xx, :yy
def initialize(map, x, y)
@map = map
@xx = @x = x
@yy = @y = y
end
def down
@direction = :down
@yy = @y
@y += 1
end
def left
@direction = :left
@xx = @x
@x -= 1
end
def up
@direction = :up
@yy = @y
@y -= 1
end
def right
@direction = :right
@xx = @x
@x += 1
end
def first_move
pre_move
case true
when @map.available(self, :down)
down
return true
when @map.available(self, :left)
left
return true
when @map.available(self, :up)
up
return true
when @map.available(self, :down)
down
return true
end
end
def pre_move
@map.set(@x, @y, ' ')
end
def auto_move
case ways
when 1
case @direction
when :down
up
when :left
right
when :up
down
when :right
left
end
return true
when 2
if @map.available(self, :down) and @y + 1 != @yy then
down
return true
end
if @map.available(self, :left) and @x - 1 != @xx then
left
return true
end
if @map.available(self, :up) and @y - 1 != @yy then
up
return true
end
if @map.available(self, :right) and @x + 1 != @xx then
right
return true
end
when 3
when 4
end
return false
end
def ways
ways = 0
ways += 1 if @map.available(self, :down)
ways += 1 if @map.available(self, :left)
ways += 1 if @map.available(self, :up)
ways += 1 if @map.available(self, :right)
return ways
end
def move
pre_move
end
def write
@map.set(@x, @y, self.to_s)
end
def to_s
"E"
end
end
class EnemyV < Enemy
def move
pre_move
return if auto_move
return if d_move
case true
when @map.available(self, :down)
down
return true
when @map.available(self, :left)
left
return true
when @map.available(self, :up)
up
return true
when @map.available(self, :right)
right
return true
end
end
def d_move
dx = @map.player.x - @x
dy = @map.player.y - @y
y = 0 < dy ? :down : :up
x = 0 < dx ? :right : :left
if dy != 0 and @map.available(self, y) then
y == :down ? down : up
return true
end
if dx != 0 and @map.available(self, x) then
x == :right ? right : left
return true
end
return false
end
def to_s
"V"
end
end
class EnemyH < EnemyV
def d_move
dx = @map.player.x - @x
dy = @map.player.y - @y
y = 0 < dy ? :down : :up
x = 0 < dx ? :right : :left
if dx != 0 and @map.available(self, x) then
x == :right ? right : left
return true
end
if dy != 0 and @map.available(self, y) then
y == :down ? down : up
return true
end
return false
end
def to_s
"H"
end
end
class EnemyL < Enemy
def turn_left_and_go
case @direction
when :down
if @map.available(self, :right) then
right
return true
end
when :left
if @map.available(self, :down) then
down
return true
end
when :up
if @map.available(self, :left) then
left
return true
end
when :right
if @map.available(self, :up) then
up
return true
end
end
return false
end
def turn_right_and_go
case @direction
when :down
if @map.available(self, :left) then
left
return true
end
when :left
if @map.available(self, :up) then
up
return true
end
when :up
if @map.available(self, :right) then
right
return true
end
when :right
if @map.available(self, :down) then
down
return true
end
end
return false
end
def go_straight
case @direction
when :down
if @map.available(self, :down) then
down
return true
end
when :left
if @map.available(self, :left) then
left
return true
end
when :up
if @map.available(self, :up) then
up
return true
end
when :right
if @map.available(self, :right) then
right
return true
end
end
return false
end
def move
pre_move
return if auto_move
l_move
end
def l_move
return if turn_left_and_go
return if go_straight
return if turn_right_and_go
end
def to_s
"L"
end
end
class EnemyR < EnemyL
def move
pre_move
return if auto_move
r_move
end
def r_move
return if turn_right_and_go
return if go_straight
return if turn_left_and_go
end
def to_s
"R"
end
end
class EnemyJ < EnemyR
def move
pre_move
end
def to_s
"J"
end
end
map1 = Map.new(50, 11, 7, <<'EOM')
###########
#.V..#..H.#
#.##...##.#
#L#..#..R.#
#.#.###.#.#
#....@....#
###########
EOM
map2 = Map.new(300, 20, 17, <<'EOM')
####################
###.....L..........#
###.##.##.##L##.##.#
###.##.##.##.##.##.#
#.L................#
#.##.##.##.##.##.###
#.##.##L##.##.##.###
#.................L#
#.#.#.#J####J#.#.#.#
#L.................#
###.##.##.##.##.##.#
###.##.##R##.##.##.#
#................R.#
#.##.##.##.##R##.###
#.##.##.##.##.##.###
#@....R..........###
####################
EOM
map3 = Map.new(700, 58, 17, <<'EOM')
##########################################################
#........................................................#
#.###.#########.###############.########.###.#####.#####.#
#.###.#########.###############.########.###.#####.#####.#
#.....#########....J.............J.......###.............#
#####.###.......#######.#######.########.###.#######.#####
#####.###.#####J#######.#######.########.###.## ##.#####
#####.###L#####.## ##L## ##.## ##.###.## ##.#####
#####.###..H###.## ##.## ##.########.###.#######J#####
#####.#########.## ##L## ##.########.###.###V....#####
#####.#########.#######.#######..........###.#######.#####
#####.#########.#######.#######.########.###.#######.#####
#.....................L.........########..........R......#
#L####.##########.##.##########....##....#########.#####.#
#.####.##########.##.##########.##.##.##.#########.#####.#
#.................##............##..@.##...............R.#
##########################################################
EOM
#map1.dump
#p map1.get(1, 1)
#p map1.set(1, 1)
#map1.dump
map1.dump
while input = gets do
input.scan(/[hjkl.q]/).each do |ch|
map1.input(ch)
map1.dump
end
end
インデントずれてるんだが、オレのシマの vim では正常に表示できていた。 デバッグすんのがくそめんどうだけど、設計レベルの崩壊はあんまなさそうなので、もっかいかけば正しいものが書けそう。 たぶん、もうやらんけどな。
2010-08-19 (Thursday) [長年日記] この日を編集
■ USP友の会 第1回いたこ会 で話します
今月は8月の28日に開催される USP友の会の第1回いたこ会にて「シェルスクリプトで頭の体操」というテーマでお話させていただきます。
「有識者」「いたこ」とは恐縮です・・・
いたこ
イタコは、日本の東北地方などで口寄せ(神仙や死者・行方不明者の霊などを自身に乗り移らせてその言葉を語ること)を行う巫女で巫の一種。 シャーマニズムに基づく信仰習俗上の職である。
イタコには霊的な力を持つとされる人もいるが、実際の口寄せは心理カウンセラー的な面も大きい。死者あるいは音信不通者との縁を忘れられないでいる、あるいは時々思い出し供養に訪れる人々に対し、それらの気持ちを汲み取り、話を聞くことによってその心を和らげるのが、イタコとその信仰の本来の姿なのかも知れない。ただそうしてあげるためにはクライアントの心情を読み取る力(一種のコールドリーディング)は必須である。
出展:ウィキペディア日本語版
開催概要は以下のとおりです。よろしければどうぞご参加ください。 # とはいっても、スラッシュドットにも掲載されていたので、すでに空きがあるのかよく把握できていません・・・
Read More ...■ RubyKaigiの懇親会に参加するか考えてる
そんなこんなで、今年のRubyKaigiは三日目のみの参加になりそうです。 しかも、個人スポンサーなのに懇親会出れないかも・・・
どなたか二日目の夜につくばの床を貸してくださる方とかいらっしゃいましたらうれしいです。 同じふとんでキャッキャウフフするのもやぶさかでは・・・
という冗談はさておき、もしよろしければコメントとかくださいな。 いたこ会のあとに直行します。逆に懇親会のチケット買いあげてやんよ、というコメントも歓迎です。その場合はUSP友の会の方々とキャッキャウフフします。
ああー。そういえば、引越しやら転職やらでゴタゴタしておったりするわけで、Ruby周りの活動できてなくてすみません。 落ち着いたら早く ia64.s の "mov r8 = ar.bsp" のあたりが正しいのか調べたい・・・っていうか、軽く調べたらアプリケーションからはread-onlyとかでてきたのでこの領域にポインタセットして上書きしてるMEMCPYは爆発し・・・じゃなくて修正するべきっぽい。と思ったら、bspの値は書き換え不可でbspが示す先はいいのか。ややこしい!
"br.ret.sptk.many" の br って汎用レジスタの名前かと思ったら ブランチレジスタ のことだった! けっこー、気合いりそうだな。









◆ takai [#01の公開をやめていただきたいのですが、お願いできますか?]
◆ takano32 [あ。すみません。やめます。]
◆ takai [ありがとうございます]