質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

5回答

1717閲覧

見栄え無視!とにかく軽くしたい

torisan

総合スコア678

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

1クリップ

投稿2016/03/19 03:43

編集2016/03/23 11:59

rubyです。
0以上且つ9桁以下の整数値データを渡すと、加工して返す関数を作成しました。
行っている処理は

①送り値の数値を一桁ずつ調べていき、
1.その桁の数値が『1』 且つ
2.左右隣二ケタが『0』 の時、その桁の値を0にする。 (20011001 -> 20011000)
②数値の一の位が『0』の時、その桁が0にならなくなるまで削除する(10で割る) (20011000 -> 20011)

です。

一応動くには動くのですが、
エンターキー一つで100回くらい呼び出されることもあるので
出来る限り処理を軽くしたいです。

お知恵を拝借できればと思います。
よろしくお願いいたします。

尚、関係することはないと思いますが
各桁の数値は最高4で、5以上の数値は入りません。

ruby

1def mj_arano(arano) 2 maisu = [0,0,0,0,0,0,0,0,0,0,0,0,0] # 0 to 12 3 maisu[2] = arano / 100000000 4 maisu[3] = (arano / 10000000) % 10 5 maisu[4] = (arano / 1000000) % 10 6 maisu[5] = (arano / 100000) % 10 7 maisu[6] = (arano / 10000) % 10 8 maisu[7] = (arano / 1000) % 10 9 maisu[8] = (arano / 100) % 10 10 maisu[9] = (arano / 10) % 10 11 maisu[10] =(arano / 1) % 10 12 i = 2 13 while i <= 10 14 if maisu[i]==1 then 15 if maisu[i-2]==0 && maisu[i-1]==0 && maisu[i+1]==0 && maisu[i+2]==0 then 16 maisu[i] = 0 17 i = i + 2 #少しでもループを短くする 18 end 19 end 20 i = i + 1 21 end 22 arano = 0 23 arano = arano + (maisu[2] * 100000000) 24 arano = arano + (maisu[3] * 10000000) 25 arano = arano + (maisu[4] * 1000000) 26 arano = arano + (maisu[5] * 100000) 27 arano = arano + (maisu[6] * 10000) 28 arano = arano + (maisu[7] * 1000) 29 arano = arano + (maisu[8] * 100) 30 arano = arano + (maisu[9] * 10) 31 arano = arano + (maisu[10] * 1) 32 33 #後ろ0の削除(2011200 -> 20112) 34 while (arano % 10) == 0 && arano != 0 35 arano = arano / 10 36 end 37 38 return arano 39end 40 41okuri=1010001 #数値は一例 42mj_arano(okuri) # 101 43 44okuri=200010100 45mj_arano(okuri) # 200010100 46 47okuri=10010001 48mj_arano(okuri) # 0

▼▼追記10/03/21 17:46▼▼
▼▼改定10/03/23 20:57▼▼
下に長くなったのでまとめたコードを記載しておきます。

ruby

1def mj_arano(arano) 2 if "00#{arano}00".index('00100') 3 if arano < 1000000 then 4 arano = "00#{arano}00".gsub(/001(?=00)/, '000').to_i 5 else 6 maisu = [0,0,0,0,0,0,0,0,0,0,0,0,0] # 0 to 12 7 maisu[2] = arano / 100000000 8 maisu[3] = (arano / 10000000) % 10 9 maisu[4] = (arano / 1000000) % 10 10 maisu[5] = (arano / 100000) % 10 11 maisu[6] = (arano / 10000) % 10 12 maisu[7] = (arano / 1000) % 10 13 maisu[8] = (arano / 100) % 10 14 maisu[9] = (arano / 10) % 10 15 maisu[10] =(arano / 1) 16 i = 2 17 while i <= 10 18 if maisu[i]==1 then 19 if maisu[i-2]==0 && maisu[i-1]==0 && maisu[i+1]==0 && maisu[i+2]==0 then 20 maisu[i] = 0 21 i += 2 22 end 23 end 24 i += 1 25 end 26 arano = 0 27 arano += maisu[2] * 100000000 28 arano += maisu[3] * 10000000 29 arano += maisu[4] * 1000000 30 arano += maisu[5] * 100000 31 arano += maisu[6] * 10000 32 arano += maisu[7] * 1000 33 arano += maisu[8] * 100 34 arano += maisu[9] * 10 35 arano += maisu[10] 36 end 37 end 38 #後ろ0の削除(2011200 -> 20112) 39 arano /= 10 while (arano % 10) == 0 && arano != 0 40end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NCC1701

2016/03/19 05:55 編集

問題文読解力不足のため削除
guest

回答5

0

正規表現を使うのは処理が重そうな気がしたので、
数値計算だけでおこなってみた版 (mj_arano2) をつくりました。
でも質問文のコードより速くはなりませんでした。

そこで質問文にコードを少しだけ変更してみました。
こころもち速くなったかなという程度の変化でした。

以下のコードは 次の3つのメソッドを含んでいます。
mj_arano() // 0m15.652
mj_arano2() // 0m24.595s
mj_arano3() // 0m14.966s
mj_arano4() // 0m31.371s (raccy さんの回答の方法)
(質問ページにあった幾つかの入力と変換結果の例については、結果が一致することを確認するコードも入れてあります)

ruby

1def mj_arano2(val) 2 nums = [] 3 ans = 0 4 5 work = val * 100 6 while true 7 work -= 100 if work % 100000 == 100 8 work, r = [work / 10, work % 10] 9 nums << r 10 break if work == 0 11 end 12 13 # 後ろの 0 の削除(2011200 -> 20112) 14 ans = 0 15 nums.reverse_each do |x| 16 ans = ans * 10 + x 17 end 18 ans /= 10 while (ans % 10) == 0 && ans != 0 19 ans 20end 21 22def mj_arano3(arano) 23 maisu = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] # 0 to 12 24 maisu[2] = arano / 100000000 25 maisu[3] = (arano / 10000000) % 10 26 maisu[4] = (arano / 1000000) % 10 27 maisu[5] = (arano / 100000) % 10 28 maisu[6] = (arano / 10000) % 10 29 maisu[7] = (arano / 1000) % 10 30 maisu[8] = (arano / 100) % 10 31 maisu[9] = (arano / 10) % 10 32 maisu[10] = (arano / 1) % 10 33 i = 2 34 while i <= 10 35 if maisu[i] == 1 36 if maisu[i - 2] == 0 && maisu[i - 1] == 0 && maisu[i + 1] == 0 && maisu[i + 2] == 0 37 maisu[i] = 0 38 i += 2 # 少しでもループ回数を少なくする 39 end 40 end 41 i += 1 42 end 43 44 arano = 0 45 arano += maisu[2] * 100000000 46 arano += maisu[3] * 10000000 47 arano += maisu[4] * 1000000 48 arano += maisu[5] * 100000 49 arano += maisu[6] * 10000 50 arano += maisu[7] * 1000 51 arano += maisu[8] * 100 52 arano += maisu[9] * 10 53 arano += maisu[10] 54 55 # 後ろの 0 の削除 (2011200 -> 20112) 56 arano /= 10 while (arano % 10) == 0 && arano != 0 57 arano 58end 59 60def mj_arano4(i) 61 "00#{i}00".gsub(/001(?=00)/, '000').reverse.sub(/\A0+/, '').reverse.to_i 62end 63 64def mj_arano(arano) 65 maisu = [0,0,0,0,0,0,0,0,0,0,0,0,0] # 0 to 12 66 maisu[2] = arano / 100000000 67 maisu[3] = (arano / 10000000) % 10 68 maisu[4] = (arano / 1000000) % 10 69 maisu[5] = (arano / 100000) % 10 70 maisu[6] = (arano / 10000) % 10 71 maisu[7] = (arano / 1000) % 10 72 maisu[8] = (arano / 100) % 10 73 maisu[9] = (arano / 10) % 10 74 maisu[10] =(arano / 1) % 10 75 i = 2 76 while i <= 10 77 if maisu[i]==1 then 78 if maisu[i-2]==0 && maisu[i-1]==0 && maisu[i+1]==0 && maisu[i+2]==0 then 79 maisu[i] = 0 80 i = i + 2 #少しでもループを短くする 81 end 82 end 83 i = i + 1 84 end 85 arano = 0 86 arano = arano + (maisu[2] * 100000000) 87 arano = arano + (maisu[3] * 10000000) 88 arano = arano + (maisu[4] * 1000000) 89 arano = arano + (maisu[5] * 100000) 90 arano = arano + (maisu[6] * 10000) 91 arano = arano + (maisu[7] * 1000) 92 arano = arano + (maisu[8] * 100) 93 arano = arano + (maisu[9] * 10) 94 arano = arano + (maisu[10] * 1) 95 96 #後ろ0の削除(2011200 -> 20112) 97 while (arano % 10) == 0 && arano != 0 98 arano = arano / 10 99 end 100 101 return arano 102end 103 104(91000000..99000000).each do |x| 105 mj_arano4(x) 106 # mj_arano2(x) 107end 108 109TESTS = [ 110 1010001, 111 200010100, 112 10010001, 113 100100001, 114 100010010 115] 116TESTS.each do |test| 117 p "#{test} -> #{mj_arano(test)}, #{mj_arano2(test)}, #{mj_arano3(test)}, #{mj_arano4(test)}" 118end

計測結果が以下です。3回ずつ走らせています。

mj_arano() $ time ruby 1.rb real 0m15.751s user 0m15.447s sys 0m0.175s $ time ruby 1.rb real 0m15.969s user 0m15.652s sys 0m0.179s $ time ruby 1.rb real 0m16.191s user 0m15.837s sys 0m0.190s
mj_arano2 $ time ruby 1.rb real 0m25.015s user 0m24.334s sys 0m0.315s $ time ruby 1.rb real 0m24.865s user 0m23.923s sys 0m0.354s $ time ruby 1.rb time ruby 1.rb real 0m24.595s user 0m23.969s
mj_arano3 time ruby 1.rb real 0m15.448s user 0m15.114s sys 0m0.168s $ time ruby 1.rb real 0m15.261s user 0m14.966s sys 0m0.162s $ time ruby 1.rb real 0m16.440s user 0m15.713s sys 0m0.278s
mj_arano4 $ time ruby 1.rb real 0m33.492s user 0m32.190s sys 0m0.504s $ time ruby 1.rb real 0m31.454s user 0m30.628s sys 0m0.360s $ time ruby 1.rb real 0m31.371s user 0m30.673s sys 0m0.310s

投稿2016/03/21 04:40

編集2016/03/21 11:59
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torisan

2016/03/21 07:46

+= や /= や条件式を右に置く、などの記述は 個人的にあまり使っていなかったので失念していました。 そして、こちらの環境でも若干ながら早く処理が動いていることを確認しました。 調査頂いた計測値についても、似たか寄ったかの値が出ています。 二つ隣り二つ隣り……で考えていたので、計算で結果を出すなど考えてもいませんでした。いろんな記述があるものですね……。 ②の記述を使用させていただきます。 回答ありがとうございました。
katoy

2016/03/21 09:20 編集

work, r = [work / 10, work % 10] nums << r と書くより nums << work % 10 work /= 10 と書いたほうが、すこしだけ速くなりました。(23 秒台になった) 配列のオブジェクトを new する処理がなくなるからと思われます。
torisan

2016/03/21 09:10 編集

こちらでも確認しました。 記載のコードにおいて、処理時間半分……とまでは行きませんでしたが 1000000回の試行において、0.12秒ほどの削減となっています。 私が使用しようとしているコードでは1回につき100回程度ですが 再帰の回数によっては差が出そうですね。
katoy

2016/03/21 10:37

num[] の配列を使う必要がないことがわかりました。 次のコードでは 14秒台がでました。(質問文のコードよりほんの少しだけ速い) def mj_arano21(val) ans = 0 work = val * 100 while true work -= 100 if work % 100000 == 100 ans = ans * 10 + (work % 10) work /= 10 break if work == 0 end ans = "#{ans}.reverse".to_i end
katoy

2016/03/21 12:05

"".to_i は 0 になることも利用して、 break をつかわないようにかきかえたら 13秒台がでました。 def mj_arano22(val) ans = 0 work = val * 100 while work > 0 work -= 100 if work % 100000 == 100 ans = ans * 10 + (work % 10) work /= 10 end ans = "#{ans}".reverse.to_i end
torisan

2016/03/22 12:57

お手数おかけしております。 ここにきて(私の)テスト方法に問題があることがわかりました。 今まで、1から1000000までの数値の処理を実行時間として見ていたのですが 質問文にもありますように最大で9桁の数値が送り値になります。 9桁の数値で1000000回の試行を行った所、 質問文にある最初のコードが一番早いという困ったこと(?)になりました。 なので現在、送り値の値を見て処理をわける、という香ばしいコードになっています。
guest

0

発想自体はraccyさんと全く同じですが、0以上且つ9桁以下の整数値一桁ずつ調べていき という要件からすると一括で変換するのは難しく、発生し得るパターンを考慮しながら順番に "1" を消しこんで行かねばならないのだと思います。

ruby初心者なのでコーディング方法には無駄やイケていない点があるかもしれませんが、下記のようにすると一応動作するのではないかと思います。

Ruby

1def mj_arano2(arano) 2 onara = arano.to_s.reverse 3 onara.sub!(/^1$/, '0') 4 onara.sub!(/^01$/, '00') 5 onara.sub!(/^001$/, '000') 6 onara.sub!(/^100/, '000') 7 onara.sub!(/^(.)001$/){"#{$1}000"} 8 onara.sub!(/^0100/, '0000') 9 onara.sub!(/^(..)001$/){"#{$1}000"} 10 onara.sub!(/^00100/, '00000') 11 onara.sub!(/^(...)001$/,){"#{$1}000"} 12 onara.sub!(/^(.)00100/,){"#{$1}000"} 13 onara.sub!(/^(....)001$/,){"#{$1}000"} 14 onara.sub!(/^(..)00100/,){"#{$1}000"} 15 onara.sub!(/^(.....)001$/,){"#{$1}000"} 16 onara.sub!(/^(...)00100/,){"#{$1}000"} 17 onara.sub!(/^(......)001$/,){"#{$1}000"} 18 onara.sub!(/^0+/, '').sub!(/0+$/, '') 19 onara.sub!(/^$/, '0') 20 return onara.reverse.to_i 21end

ひょっとしたら考慮漏れがあるかもしれませんが…
桁数が9桁に満たない場合も含めつつ、reverseすることで下位の桁から順に、条件に当てはまる "1" を消し込んでいます。
処理の終わった下位の桁は、後方参照を利用して保存しています。

結構な行数になってしまったので、どれだけ高速化されるか不明ですが、乗算や除算を何度も繰り返したりループを使用したりするよりは速いのではないかと思います。

投稿2016/03/19 15:17

pi-chan

総合スコア5936

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torisan

2016/03/20 09:57

回答ありがとうございます。 正規表現については今までほとんど使う機会がなかったので 少々解読に時間が掛かっております。取り急ぎ、分かった事だけ記述します。 確認した所、時々不要な1が残る時があるようです。 例) 100100001 ->1 100010010 ->1 また、こちらも条件はわかっていないのですが onara.sub!(/^0+/, '').sub!(/0+$/, '') の行でエラーになる場合があるようです。 こちらについては2行に分ける事で (なぜか)通るようなのでそれで対応しました。 onara.sub!(/^0+/, '') onara.sub!(/0+$/, '') 肝心の時間についてですが、少々掛かってしまう感じでした。 他の方の回答でも書いたのですが sub! という処理が重いのかもしれませんね。
torisan

2016/03/21 07:33

1が残る原因ですが、 onara.sub!(/^(.)00100/,){"#{$1}000"}など 『00100』などの置き換え後の値が『000』になっていた事が原因のようでした。 onara.sub!(/^(.)00100/,){"#{$1}00000"}などに『00000』に修正した所 (10件程度しかテストしていませんが)正しい値を返すようになりました。 記号が入り混じっていて難しい印象ですが、対象となるデータが多い時に 非常に役に立ってくれそうな記述ですね。 勉強になりました、ありがとうございました。
guest

0

ベストアンサー

うーん、動作要件がいまいちわかりませんが、こんなのでしょうか?

Ruby

1def mj_arano2(i) 2 "00#{i}00".gsub(/001(?=00)/, '000').reverse.sub(/\A0+/, '').reverse.to_i 3end

たぶん、これでいけると思います。
【修正箇所】
先読みにすることで、孤立した1が出ないようにしました。
subをreverseすることで、たぶん、遅くなる問題は解決したと思います。(正規表現は後方から探すと遅いけど、前方から探すは早い)

投稿2016/03/19 06:09

編集2016/03/19 12:41
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torisan

2016/03/19 10:16

いろいろ試してみた結果、 subの動きが若干ながら重いようでしたのでgsubの記述だけ引用させて頂きました。 最終的なコードは以下になります。 def mj_arano(arano) arano = "00#{arano}00".gsub(/00100/, '00000').to_i while (arano % 10) == 0 && arano != 0 arano = arano / 10 end return arano end しかしまさか一行とは……すごいですね。。
torisan

2016/03/19 10:24

お礼を言い忘れるとか……。 回答ありがとうございました!
torisan

2016/03/19 12:12

あわただしくてすみません。 どうも時々孤立した1が残る時があるようです。 説明が難しいのですが、置き換えた箇所は判定から外されるようです。 10010001 -> 001001000100 ->左右に00を加える 000001000100 ->一番左の00100を置き換える、          この時点で置き換えた1~5桁目はgsub判定から外され          次は6~10桁目から判定する 000001000000 ->次の対象の8~12桁目を置き換える、最終的に1が残る 6桁目の1も置き換え対象なのですが、 何かいい知恵がありましたら教えていただけると幸いです。
raccy

2016/03/19 12:43

修正しました。先読みにすることでポイントが進まなくなるので、うまくいくと思います。また、subが遅い部分も工夫してみました。どれだけ早くなるかはちょっとわかりませんが…。
torisan

2016/03/21 07:56 編集

お手数おかけしております。 確認しました所、正しい値を返しているようでした。 しかし、subについてはreverse前との変化は残念ながら感じられませんでした。 (尚、for i in 1..1000000 で1000000回の試行のタイムスタンプで判断しています。) ほぼ同じですが今のコードを載せておきます。 def mj_arano(arano) arano = "00#{arano}00".gsub(/001(?=00)/, '000').to_i while (arano % 10) == 0 && arano != 0 arano = arano / 10 end return arano end 追記(16/03/21 16:56:00) {i}になっていたのを{arano}に修正
raccy

2016/03/20 10:55

正規表現ではなくて、標準ライブラリのstrscanを使えばもう少し速くなるかも知れません。ただ、数値計算はかなり速いので単純なところはそちらのコードの方がいいかと思います。
torisan

2016/03/21 08:43

strscanについて調べたのですが require 'strscan' が通らなかったり(ファイルが必要?) 標準ライブラリ???だったり よしんば通ったとしても置き換え方がわからなかったりで今回は見送ることにしました。 教えていただいたのに申し訳ありません。 gsubについては処理時間の3・4割を削減でき、一番効果があったため 再度BAを付けさせていただきます。ありがとうございました。
guest

0

ruby

1#!/usr/bin/env ruby 2# -*- encoding:utf-8 -*- 3 4def mj_arano(arano) 5 arano_a = ["0", "0", "0", "0"] 6 arano_a.insert(2, *arano.to_s.scan(/./)) 7 temp = [] 8 arano_a.each_cons(5) do |item| 9 if item == ["0", "0", "1", "0", "0"] 10 temp << "0" 11 else 12 temp << item[2] 13 end 14 end 15 16 #後ろ0の削除(2011200 -> 20112) 17 arano_s = temp.join.to_s.sub!(/0+$/,'') 18 19 return arano_s.to_i 20end

投稿2016/03/19 05:58

編集2016/03/19 06:11
NCC1701

総合スコア1680

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torisan

2016/03/19 10:21

いろいろ勉強になる記述がたくさんあって興味深い回答でした。 each_consとか初めて見ました。こんなのもあるんですね。 処理的には少々重めのようでしたので、BAはもう一人の方に付けさせていただきます。 ともあれ、回答ありがとうございました。
guest

0

私の以前の回答へのコメントで書いた mj_arano22() より速い版 mj_arano23() ができました。
ループ範囲を (100000000..110000000)にした場合の時間は次のようになりました。

mj_arano: 0m22.408s
mj_arano100: 0m35.629s
mj_arano23: 0m11.107s

ruby

1PAT = '00100' 2def mj_arano23(val) 3 if "00#{val}00".index(PAT) 4 ans = 0 5 work = val * 100 6 while work > 0 7 work -= 100 if work % 100000 == 100 8 ans = ans * 10 + (work % 10) 9 work /= 10 10 end 11 return "#{ans}".reverse.to_i 12 end 13 14 val /= 10 while (val % 10) == 0 && val != 0 15 val 16end 17 18def mj_arano100(arano) 19 # 孤立の1を削除 20 arano = "00#{arano}00".gsub(/001(?=00)/, '000').to_i 21 # 後ろ0の削除(2011200 -> 20112) 22 arano /= 10 while (arano % 10) == 0 && arano != 0 23 arano 24end 25 26def mj_arano(arano) 27 maisu = [0,0,0,0,0,0,0,0,0,0,0,0,0] # 0 to 12 28 maisu[2] = arano / 100000000 29 maisu[3] = (arano / 10000000) % 10 30 maisu[4] = (arano / 1000000) % 10 31 maisu[5] = (arano / 100000) % 10 32 maisu[6] = (arano / 10000) % 10 33 maisu[7] = (arano / 1000) % 10 34 maisu[8] = (arano / 100) % 10 35 maisu[9] = (arano / 10) % 10 36 maisu[10] =(arano / 1) % 10 37 i = 2 38 while i <= 10 39 if maisu[i]==1 then 40 if maisu[i-2]==0 && maisu[i-1]==0 && maisu[i+1]==0 && maisu[i+2]==0 then 41 maisu[i] = 0 42 i = i + 2 #少しでもループを短くする 43 end 44 end 45 i = i + 1 46 end 47 arano = 0 48 arano = arano + (maisu[2] * 100000000) 49 arano = arano + (maisu[3] * 10000000) 50 arano = arano + (maisu[4] * 1000000) 51 arano = arano + (maisu[5] * 100000) 52 arano = arano + (maisu[6] * 10000) 53 arano = arano + (maisu[7] * 1000) 54 arano = arano + (maisu[8] * 100) 55 arano = arano + (maisu[9] * 10) 56 arano = arano + (maisu[10] * 1) 57 58 #後ろ0の削除(2011200 -> 20112) 59 while (arano % 10) == 0 && arano != 0 60 arano = arano / 10 61 end 62 63 return arano 64end 65 66(100000000..110000000).each do |x| 67 mj_arano23(x) 68 # mj_arano(x) 69end 70 71TESTS = [ 72 0, 73 1, 74 10, 75 100, 76 1010001, 77 200010100, 78 10010001, 79 100100001, 80 100010010, 81 100100001 82] 83TESTS.each do |test| 84 p "#{test} -> #{mj_arano(test)}, #{mj_arano23(test)}, #{mj_arano100(test)}" 85end

実行結果例:

time ruby 2.rb "0 -> 0, 0, 0" "1 -> 0, 0, 0" "10 -> 0, 0, 0" "100 -> 0, 0, 0" "1010001 -> 101, 101, 101" "200010100 -> 2000101, 2000101, 2000101" "10010001 -> 0, 0, 0" "100100001 -> 0, 0, 0" "100010010 -> 0, 0, 0" "100100001 -> 0, 0, 0" real 0m11.107s user 0m10.713s sys 0m0.111s

追記: 2016-03-23 22:40
torisan さんの 2016/03/23 20:54 のコメントへのコメントです。

(100000000..110000000).each do |x| ... end
とした場合は、
00100 のパターンがある数字は10万回に1度しか出現しません。
つまり、00100 の処理の時間ではなく、末尾の0 をとる処理のベンチマークになってします。
従って、いかに 00100 が現れていないかを判定して、末尾の 0 をとるかを工夫するだけでベンチマークの成績は良くなってしまうわけです。

そこで、常に 00100 のパターンが現れるように次のようにループさせて計測してみました。

ruby

1 (1..100).each do |y| 2 (100000000..100100000).each do |x| 3 ... 4 end 5 end

その結果は次のようになりました。
mj_arano: 0m22.990s
mj_aranoX: 0m23.718s # 質問文にある 10/03/22 21:44 のコード
mj_arano100: 1m11.066s
mj_arano23: 0m25.935s
mj_arano22: 0m18.171s

mj_arano23 でつかっている
if "00#{val}00".index(PAT)
はそれなりに重い処理なのです。

純粋に 00100 を 00000 に置換して、さらに末尾の 0 をとる処理として一番速いのは mj_arano2 でした。
念のため anaba22() の内容を書いておきます。

ruby

1def mj_arano22(val) 2 ans = 0 3 work = val * 100 4 while work > 0 5 work -= 100 if work % 100000 == 100 6 ans = ans * 10 + (work % 10) 7 work /= 10 8 end 9 "#{ans}".reverse.to_i 10end

処理するデータの特性 (00100 が現れる割合が判明するば、それに応じてさらに最適化したコードをつくれる気がします)

投稿2016/03/22 21:48

編集2016/03/23 13:38
katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torisan

2016/03/23 11:54

なるほど! 対象でない時は処理を行わないというわけですね、盲点でした。 組み込むプログラム上、テストほど対象でないケースが多いわけではないのですが 処理に組み込ませて頂きます。
katoy

2016/03/27 06:35 編集

コメントに書くと長くなるので、回答に追記として書きました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問