ナベアツ問題これは難しい・・・
ナベアツ問題なるものが、紹介されていました。
http://q.hatena.ne.jp/1207585413
これを文字列化もせず、桁に分割したりせず、第3の方法がないかなと思って試しています。
BCD(http://ja.wikipedia.org/wiki/%E4%BA%8C%E9%80%B2%E5%8C%96%E5%8D%81%E9%80%B2%E8%A1%A8%E7%8F%BE)の考え方を利用する方向性で考えています。まだ、うまく行っていませんが、こんな感じです。
#!/bin/env ruby j = 0 (0..100).each do |i| j += 1 if j & 0xf > 9 then j += 0x10 j -= 10 end if j & 0xff > 0x9f then j += 0x100 j -= 0xa0 end k = j k ^= 0x33333333 k = (k * (k >> 16)) & 0xffff k = (k * (k >> 8)) & 0xff k = (k * (k >> 4)) & 0xf printf "%x %x\n", j, k end
この中で次の部分がBCDのカウンタを実現する部分です。
j += 1 if j & 0xf > 9 then j += 0x10 j -= 10 end if j & 0xff > 0x9f then j += 0x100 j -= 0xa0 end
0x9の次は0x10になり、0x99の次は0x100になるように補正します。BCD表現を利用することによって、ビット演算のみで各桁の切り出しができるようになります。
後は、3を含む桁を見つけ出す処理ですが、これがうまく行っていません。もちろん、ナイーブに各桁を切り出していくといいのですが・・・。
追記 2008/4/12 その1
とりあえずナイーブな方法で完成。これだと結局桁ごとに切り出しているのでもうちょっと検討します。
#!/bin/env ruby j = 0 (1..1000).each do |i| j += 1 if j & 0xf > 9 then j += 0x10 j -= 10 end if j & 0xff > 0x9f then j += 0x100 j -= 0xa0 end if j & 0xfff > 0x9ff then j += 0x1000 j -= 0xa00 end if j & 0xffff > 0x9fff then j += 0x10000 j -= 0xa000 end k = j k ^= 0x33333333 l = (k >> 24) & 0xf l *= (k >> 20) & 0xf l *= (k >> 16) & 0xf l *= (k >> 12) & 0xf l *= (k >> 8) & 0xf l *= (k >> 4) & 0xf l *= k & 0xf print i if l == 0 or i % 3 == 0 then print " aho" end if i % 5 == 0 then print " wan" end print "\n" end
追記 2008/4/12 その2
完成しました。
#!/bin/env ruby j = 0 (1..1000).each do |i| j += 1 if j & 0xf > 9 then j += 0x10 j -= 10 end if j & 0xff > 0x9f then j += 0x100 j -= 0xa0 end if j & 0xfff > 0x9ff then j += 0x1000 j -= 0xa00 end if j & 0xffff > 0x9fff then j += 0x10000 j -= 0xa000 end k = j k ^= 0xcccccccc k &= (k >> 1) k &= (k >> 2) k |= (k >> 16) k |= (k >> 8) k |= (k >> 4) k &= 1 print i if k == 1 or i % 3 == 0 then print " aho" end if i % 5 == 0 then print " wan" end print "\n" end