海野秀之(うんのひでゆき)の外部記憶
Twitter (twilog) / RSS / アンテナ / ぶくま
◆ 当初答えを Web 公開するつもりなかったので、すっかり出遅れました。 Webに公開されたみなさんのを見ていると、 なんかみんなと答えが違うみたいなんですが。まちがったかな。
投稿には間に合わなかった Haskell 版:
sample_gems = [('a', 3), ('b', 1), ('c', 2)] gems = zip "abcdefg" [1, 4, 1, 4, 2, 1, 3] generate prefix gems len = let letters = gems >>= \(c, n) -> if n > 0 then [c] else [] gems' c gs = gs >>= \(c', n) -> if c == c' then [(c', n - 1)] else [(c', n)] in if len > 0 then prefix : (letters >>= \c -> generate (prefix ++ [c]) (gems' c gems) (len-1)) else [prefix] sample_xs = zip [0..] (generate "" sample_gems 6) xs = zip [0..] (generate "" gems 8) lookup_string goal ((i,s):xs) = do putStrLn $ (show i) ++ ":" ++ s if s /= goal then lookup_string goal xs else putStr "" main = lookup_string "eagcdfbe" xs
2回目に投稿した Ruby 版:
#!/usr/bin/env ruby class GemGen def initialize(len, prefix, gems) @len = len @prefix = prefix @gems = gems end def i2c(i) "abcdefg"[i] end def each &b b.call(@prefix) if @len > 0 @gems.each_with_index do |n, i| if n > 0 subgems = @gems.dup subgems[i] -= 1 c = i2c(i) newprefix = "#{@prefix}#{c}" g = GemGen.new(@len - 1, newprefix, subgems) g.each {|str| b.call(str)} end end end end end Enumerator.new(GemGen.new(8, "", [1, 4, 1, 4, 2, 1, 3])).each_with_index do |s, i| puts "#{i}:#{s}" break if s == "eagcdfbe" end
1回目の投稿は、長いし汚いので、気が向いたらどこかに貼ります。 いずれも、 850131 って出ました。
長さ 16 までなんですね。なぜか、16 個の宝石で、長さ 8 以下の列をつくると勘違いしてしまってました。
Haskell 版は、 xs = zip [0..] (generate "" gems 16)
Ruby 版は、 GemGen.new(16, "", [1, 4, 1, 4, 2, 1, 3])
に直せばいいだけのはずですが…やってみよう。
→でた:
$ ghc gemgen.hs [1 of 1] Compiling Main ( gemgen.hs, gemgen.o ) Linking gemgen.exe ... $ ./gemgen.exe 5578864439:eagcdfbe
Ruby 版の方はまだ実行結果でてませんが、直したものを GitHub においておきました: https://github.com/unnohideyuki/gemstring/tree/master
Generator っぽく書いたのは割と気に入っていたので、ミスってたのは残念。
あと、警告気になる。Enumerator 見よう見まねで使ってみたのに、deprecated って。
追記: 翌日になってみてみたけど、Ruby 版はまだ間違ってる。
>ruby gemgen.rb gemgen.rb:32: warning: Enumerator.new without a block is deprecated; use Object#to_enum 1283894713:eagcdfbe
なんでだろ。
5578864439 になるはずの結果が 1283894713 になってしまったのは、Fixnum の桁を超えてしまったせいなのかも。
irb(main):007:0> a = 5578864439 - 1283897143 => 4294967296 irb(main):008:0> printf "%x\n", a 100000000 => nil
今回使った Ruby は ruby 2.0.0p353 (2013-11-22) [x64-mingw32] だったのですが。
ちょっと試してみる:
enum = Enumerator.new {|x| i = 0 loop { x << i i += 1 } } zero_occurence = 0 enum.each_with_index {|x, i| if x != i puts "abort: #{x} != #{i}" exit 1 end zero_occurence += 1 if i == 0 if zero_occurence == 2 puts "i == 0 twice" exit 1 end } puts "normal end"
実行結果:
>ruby enum.rb abort: 2147483648 != -
なんか表示が変ですが。31-bit あふれたら wrap around するんかな。 意外。
→既知のバグ (#8010) で、Ruby 2.1.0 ではすでに直っていた。Ruby 2.0, Ruby 1.9 にもバックポートされるみたい。
# うんの [実行中…だけど、3時間くらいかかるのかな。 あと、Ruby の方は Ruby 2.0.0 でやったら警告でた: g..]
# うんの [GitHub にあげようと思ったら、Windows 版 git 1.8.5 のバグではまる。]
# うんの [GitHub アプリをインストールして push しました。]