Kernel#caller なんて初めて使った。
def foo /.*`(.+)'/ =~ caller(1)[0] $1 end def bar; foo; end def baz; foo; end p bar p baz
^o^ >ruby caller.rb "bar" "baz"
takatoh's blog – Learning programming languages.
Kernel#caller なんて初めて使った。
def foo /.*`(.+)'/ =~ caller(1)[0] $1 end def bar; foo; end def baz; foo; end p bar p baz
^o^ >ruby caller.rb "bar" "baz"
HaskellのほうがRubyよりすっきりしてるな。
divisors n = filter ((==0).mod n) [1..(n `div` 2 + 1)] isDoublePerfectNumber n = (sum.divisors) n == (n*2) main = mapM_ (putStrLn.show) $ filter isDoublePerfectNumber [1..10000]
def divisors(n) (1..(n/2+1)).to_a.select{|x| n % x == 0 } end def double_complete_number?(n) divisors(n).inject(0){|a,b| a+b } == 2 * n end (1..10000).to_a.each do |n| puts n if double_complete_number?(n) end
結果は同じ(あたりまえ)だけど,Rubyのほうが速かった。
^o^ >runhaskell dpn.hs 120 672 ^o^ >ruby dpn.rb 120 672
問題文中の top < bottom は間違いじゃないかと書いたら,グラフィックイメージの座標だと考えればOKだとコメントをもらった。なるほど。
判定方法は,要するに一方の長方形の4つある頂点のどれかか,もう一方の長方形の内部にあれば重なってると判定していいわけだ。
今日はRubyで書いた。
class Rect def initialize(left, top, right, bottom) @left = left @top = top @right = right @bottom = bottom end def vertexes [ [@left, @top], [@left, @bottom], [@right, @bottom], [@right, @top] ] end def inner?(x,y) (@left < x && x < @right) && (@top < y && y < @bottom) end def overlap?(rect) rect.vertexes.any?{|x,y| inner?(x,y) } end end r1 = Rect.new( 0, 0, 100, 100) r2 = Rect.new(100, 0, 200, 100) r3 = Rect.new( 50, 50, 150, 100) p r1.overlap?(r2) # => false p r1.overlap?(r3) # => true p r2.overlap?(r3) # => true
このコードだと長方形がX方向とY方向の両方にずれていないと正しく判定できないことに気づいた。極端な話,ぴったりと重なっている長方形が「重なっていない」判定になる。
irb(main):001:0> r1 = Rect.new(0,0,100,100) => #<Rect:0x499f9f4 @top=0, @left=0, @bottom=100, @right=100> irb(main):002:0> r1.overlap?(r1) => false
なんてこったい。
succ でいいじゃん,と思ったらダメだった。
Prelude> succ 'A' 'B' Prelude> succ 'Z' '['
Ruby の String#succ はうまくやってくれるのに。
なら,26進数だと考えて素直に繰り上がりを処理すればいいか……と思ったけどこれもダメ。’A’ は 0 じゃない。要するに 0 が無いんだな。結局繰り上がりのところで汚いコードになってしまった。
module Main ( main ) where import Data.Char ( ord, chr ) import Data.List ( mapAccumR, intersperse ) succS :: [Char] -> Int -> [Char] succS s n = map intToAlpha $ g $ mapAccumR f n $ map alphaToInt s where alphaToInt c = (ord c ) - 64 intToAlpha i = chr (i + 64) f acc x = let (d,m) = (acc+x) `divMod` 26 in if m == 0 then (d-1,26) else (d,m) g (0,b) = b g (a,b) = a:b main :: IO () main = putStr $ concat $ intersperse "," $ take 100 $ iterate (flip succS 1) "A"
実行:
^o^ >runhaskell succS.hs A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,A J,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ, BK,BL,BM,BN,BO,BP,BQ,BR,BS,BT,BU,BV,BW,BX,BY,BZ,CA,CB,CC,CD,CE,CF,CG,CH,CI,CJ,CK ,CL,CM,CN,CO,CP,CQ,CR,CS,CT,CU,CV
module Main (main) where fromDecimal :: (Integral a) => a -> a -> a fromDecimal n x = f 0 x 1 where f r 0 _ = r f r y z = f (r + (y `mod` 10) * z) (y `div` 10) (z * n) main :: IO () main = putStr $ show $ head $ filter (\x -> fromDecimal 13 x `mod` x == 0) [10..]
実行。
^o^ >runhaskell multiple13.hs 1557
正規表現の最短一致を使ってこれでいいはず……だと思うんだけど。
def remove_comment(str) str.gsub(/\/\*.*?(\*\/|\z)/,"") end samples = %w( AAA AAA/*BBB*/ AAA/*BBB AAA/*BBB*/CCC AAA/*BBB/*CCC*/DDD*/EEE AAA/a//*BB*B**/CCC ) samples.each do |str| puts str puts " => #{remove_comment(str)}" end
実行。
^o^ >ruby remove_comment.rb AAA => AAA AAA/*BBB*/ => AAA AAA/*BBB => AAA AAA/*BBB*/CCC => AAACCC AAA/*BBB/*CCC*/DDD*/EEE => AAADDD*/EEE AAA/a//*BB*B**/CCC => AAA/a/CCC
再帰で
uniq [] = [] uniq (x:xs) = x:uniq (filter (/=x) xs)
と書いてから,こんな関数ありそうだなぁと思ったらやっぱりあった。
高階関数版:
uniq2 :: (Eq a) => [a] -> [a] uniq2 = foldl (\a e -> if (elem e a) then a else a ++ [e]) []
型を明示しないとダメ。
Prelude> :l uniq2.hs [1 of 1] Compiling Main ( uniq2.hs, interpreted ) uniq2.hs:2:27: Ambiguous type variable `b' in the constraint: `Eq b' arising from use of `elem' at uniq2.hs:2:27-34 Possible cause: the monomorphism restriction applied to the following: uniq2 :: [b] -> [b] (bound at uniq2.hs:2:0) Probable fix: give these definition(s) an explicit type signature or use -fno-monomorphism-restriction Failed, modules loaded: none.
現実逃避的にアナーキーゴルフ。
cf. anarchy golf – delete blank lines
これで26バイト。どうやったら12バイトでできるんだ?
$><<$<.read.gsub(/^\n/,"")
以前に試したときにはどういうわけだかうまくいかなかってけど,今度はうまくいったので(ちょっとはまったけど),メモ。
はてなダイアリーライター本体はここから(Version 1.4.1)。マニュアルもここ。
まずは試してみる。テスト用の日記ファイルを作って,設定ファイルはなしでやってみたらすんなり成功。ちょっと拍子抜け。
^o^ >perl hw.pl WARNING: Crypt::SSLeay is not found, use non-encrypted HTTP mode. Username: takatoh Password: ******** Login to http://www.hatena.ne.jp/login as takatoh. Login OK. Post 2007-07-08. Post OK. Logout from http://d.hatena.ne.jp as takatoh. Logout OK.
けどちょっと待て。Cyrpt::SSLeayが無いから暗号化しないモードを使うといってる。
……それで思い出した。以前うまくいかなかったのはこのあたりだった。
というわけで,このへんのページを参考に改めてチャレンジ。
まずはOpenSSLから。上のリストの2番目のページからインストーラ(最新版 Win32OpenSSL v0.9.8e)をダウンロードしてインストールするだけ。
Crypt::SSLeay のほうは上のリストの3番目のページにある「LWPで、「https://」で始まるSSL使用サイトにアクセスできますか?」を参考にした。ppmコマンドでインストールするんだけど,モジュール名ではなくPPDファイル名を指定する必要があるらしい(GUI版ppmのリストに出てこない)。ActivePerl 5.8.8 を使っているので:
^o^ >ppm install http://theoryx5.uwinnipeg.ca/ppms/Crypt-SSLeay.ppd
後半,dllをインストールするか聞いてくるので yes と答えてインストールする。デフォルトが[no]になってるので注意。
さて,改めて試してみよう。ついでに設定ファイルも書いておく。
id:takatoh password:******** cookie:cookie.txt proxy:http://proxy:8080/ client_encoding:Shift_JIS server_encoding:EUC_JP
これでOKのはず。
^o^ >perl hw.pl Login to https://www.hatena.ne.jp/login as takatoh. Login OK. Post 2007-07-08. Old cookie. Retry login. Login to https://www.hatena.ne.jp/login as takatoh. Login OK. Old cookie. Retry login. Login to https://www.hatena.ne.jp/login as takatoh. Login OK. ERROR: try_it: Check username/password.
なんでエラーになるんだ!!……orz
えーと。いろいろ試した結果何とか動くようになった。これについてはエントリーを改めて書く。
さきに書いておくと,インストールや設定ファイルは上の通りで大丈夫(たぶん)。問題はcookie.txtだった。--(つづく)
id:takatoh:20070708:hw のつづき。Crypt::SSLeayをインストールしたらエラーになった件。
いろいろ試した結果,クッキーファイル(cookie.txt)の有無と関係が有ることがわかった。表にするとこんな感じ。
cookie.txtあり | cookie.txtなし | |
Crypt::SSLeayなし | OK | OK |
Crypt::SSLeayあり | OK | エラー |
Crypt::SSLeayが無い場合にはcookie.txtの有無に関わらずOKなんだけど,これは暗号化されないってことなんで非推奨。Crypt::SSLeayをインストールするとcookie.txtが無い場合にエラーになる。無けりゃ作ってくれるはずなんだけど,ここで失敗しているように見える(最後から2行目)。……ちがうのかな。
-d オプションをつけて実行した結果:
^o^ >perl hw.pl -d DEBUG: Debug flag on. Hatena Diary Writer Version 1.4.1 Copyright (C) 2004,2005 by Hiroshi Yuki. DEBUG: Loading config file (config.txt). DEBUG: load_config: id:takatoh DEBUG: load_config: password:******** DEBUG: load_config: cookie:cookie.txt DEBUG: load_config: proxy:http://proxy:8080/ DEBUG: load_config: client_encoding:Shift_JIS DEBUG: load_config: server_encoding:EUC_JP DEBUG: main: files: current dir (.): ./2007-07-08.txt ./touch.txt DEBUG: login: proxy for http: http://proxy:8080/ DEBUG: login: proxy for https: http://proxy:8080/ Login to https://www.hatena.ne.jp/login as takatoh. DEBUG: login: 200 OK DEBUG: login: $r = <HTML></HTML> Login OK. DEBUG: login: Making cookie jar. DEBUG: login: $cookie_jar = DEBUG: read_title_body: input: ./2007-07-08.txt DEBUG: Convert from Shift_JIS to EUC_JP. Post 2007-07-08. DEBUG: create_it: 2007-07-08. DEBUG: create_it: 302 Moved DEBUG: create_it: Location: /takatoh/ DEBUG: create_it: returns 0 (ERROR). DEBUG: try_it: update_diary_entry: CREATE. Old cookie. Retry login. DEBUG: login: proxy for http: http://proxy:8080/ DEBUG: login: proxy for https: http://proxy:8080/ Login to https://www.hatena.ne.jp/login as takatoh. DEBUG: login: 200 OK DEBUG: login: $r = <HTML></HTML> Login OK. DEBUG: login: Making cookie jar. DEBUG: login: $cookie_jar = DEBUG: create_it: 2007-07-08. DEBUG: create_it: 302 Moved DEBUG: create_it: Location: /takatoh/ DEBUG: create_it: returns 0 (ERROR). DEBUG: try_it: update_diary_entry: CREATE. Old cookie. Retry login. DEBUG: login: proxy for http: http://proxy:8080/ DEBUG: login: proxy for https: http://proxy:8080/ Login to https://www.hatena.ne.jp/login as takatoh. DEBUG: login: 200 OK DEBUG: login: $r = <HTML></HTML> Login OK. DEBUG: login: Making cookie jar. DEBUG: login: $cookie_jar = ERROR: try_it: Check username/password.
結局,Crypt::SSLeayをインストール/アンインストールしたり,設定ファイルを書き換えてみたりしてるうちにできた(つまりCrypt::SSLeayなしの時にできた)クッキーファイルがあって動くようになったので今回はOKとする。Crypt::SSLeayありの状態でクッキーファイルを作る方法はわからない。
なんだか中途半端だけど時間切れだ。
hyukiさんのアドバイスに従ってproxyの無い環境で試してみたら,正しく投稿できた。どうやら次の3つが重なったときにエラーになるらしい。