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

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

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

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

Q&A

解決済

3回答

1087閲覧

競技プログラミング rubyでの処理速度向上

domingojapan

総合スコア26

Ruby

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

0グッド

0クリップ

投稿2021/12/01 15:10

プログラミングの腕を磨くべく、AtCoderといった競技プログラミングの問題に対する解答を実装しています。
(初心者なのでまだACになるのに時間がかかります)

例えばある問題に対して下記の様なコードを提出した結果、
テストケース16シナリオのうち、13シナリオがAC(OK)、3シナリオがタイムオーバーとなります。
(最初はもう少しタイムオーバーシナリオがあったのですが、for文をwhile文にしたりして改善していきました)
ですが、ここらへんで詰まっています。

「ここの書き方をこうすれば改善できるよ!」といった助言を頂ければ幸いです。

ruby

1 2matrix = gets.chomp.split(' ') 3line = readlines 4len = line.length 5 6i = 0 7while i < len 8 line[i] = line[i].split(' ').map(&:to_i) 9 i += 1 10end 11 12answer = Array.new(matrix[0].to_i*matrix[1].to_i, 0) 13h_sum = Array.new(matrix[1].to_i,0) 14tmp_h = 0 15while tmp_h < matrix[1].to_i 16 tmp_w = 0 17 while tmp_w < matrix[0].to_i 18 h_sum[tmp_h] += line[tmp_w][tmp_h] 19 tmp_w += 1 20 end 21 tmp_h += 1 22end 23 24i = 0 25w_sum = 0 26cnt = 0 27while i < line.length 28 h_word = "" 29 w_sum = line[i].sum 30 j = 0 31 while j < line[i].length 32 answer[cnt] = h_sum[j] - line[i][j] + w_sum 33 h_word = "#{h_word} #{answer[(i*matrix[1].to_i)+j]}" 34 cnt += 1 35 j += 1 36 end 37 puts h_word 38 i += 1 39end 40

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

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

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

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

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

guest

回答3

0

競技プログラミングで時間が不足する場合、以下のどれかのようなことが考えられます。

  • なにかのミスで時間を浪費している
  • オーダーを減らすよう、アルゴリズムから考え直す必要がある
  • (Rubyで提出できる以上可能性は薄いですが)他言語で解かないと時間的に間に合わない

いずれにしても、問題に即して考える必要があります。「for文をwhile文にしたり」といった小手先の対応で改善できる幅とはレベルが違います。

投稿2021/12/01 21:53

maisumakun

総合スコア145208

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

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

0

ベストアンサー

小手先を並べます
前提ですが、 lineで入力されるデータは matrix のサイズに過不足ない 前提で書きます。そこが危ういなら、line読んだ所で確認してください

入る前に、line はいただけません。lines にしましょう。

まず、matrix = gets.chomp.split(' ') は line と同じように map(&:to_i) しておきましょう。

tmp_h = 0 から始まる9行は line の各列の合計をh_sumにいれているのですから lineの行列を入れ替えたものを作って t_lines = line.transpose
h_sum = t_lines.map(&:sum)

2つ目の二重loopはそう単純ではないですが、いくつか
answer[cnt] と answer[(i*matrix[1].to_i)+j] が使われてますが、これ同じものですよね。同じものを違う表現するのは高速化以前に間違いの元なので。で、それ以前に、 answer ってここでしか使っていないのですね。でしたら配列にする必要はないので、answer で良いでしょう

内側のloopで String h_word を作り直してるのが気になります。これだと新しいobjectを作って古いのを捨てている。ので時間が掛かる。
内側をwhileではなく
h_word = line[i].map.with_index{|clmn,j| h_sum[j] - line[i][j] + w_sum }.join(' ')

「まず、matrix = gets.chomp.split(' ') は、、、」は不要でしたね。loopで使わなくなったから。line読み終わった所で捨てても良いもののようです。

蛇足
Arrayの要素を全部舐めるときは forやwhileでindexを変えていくのではなく each を使ったほうが「全部舐めるのね」とわかるのでプログラム追うコストが下がります。そうでないと、どこからどこまで読むのだろうか、頭と尻はどうやって決めるのだろうか など余分な妄想が片隅に浮かんで。。。
スピードが早いかどうかは分かりませんが 。

投稿2021/12/05 03:34

編集2021/12/05 03:41
winterboum

総合スコア23416

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

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

0

AtCoderのどの問題かわからないので制約がわからないのですが、
計算量はmatrix[0].to_i * matrix[1].to_i (表示されてる文字数?)程度なので、
アルゴリズムは問題ないと思います。

Rubyは入出力で時間が食われるので、
puts h_word で毎回出力するのではなく、
ループ中に配列や文字列に<<で末尾に追加し、まとめたのを最後に1回で出力してみたはいかがでしょうか

投稿2021/12/04 12:33

fast_vegetable

総合スコア4

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問