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

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

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

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

Q&A

4回答

1239閲覧

ruby とある問題での回答例。関数やクラス使えそうか?

garchomp

総合スコア128

Ruby

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

0グッド

1クリップ

投稿2017/05/27 15:45

失礼します。
とある問題を説いていたら次のようなコードになりました。(問題の内容は拡散禁止されているため個人的な回答内容から読み取ってください。)

ちなみに入力される値はこれです。

~~

n
s_1
s_2
...
s_n

例:
3
SET 1 10
SET 2 20
ADD 40

10 50
~~

ruby

1x = gets.to_i 2a=0 3b=0 4for i in 1..x do 5 rd=gets.split(" ") 6 if rd[0]=="SET" 7 if rd[1].to_i==1 8 a=rd[2].to_i 9 elsif rd[1].to_i==2 10 b=rd[2].to_i 11 end 12 elsif rd[0]=="ADD" 13 b=a+rd[1].to_i 14 elsif rd[0]=="SUB" 15 b=a-rd[1].to_i 16 end 17end 18 19puts "#{a} #{b}"

恐らく、これらはdef classなどをうまく使うこともできるのでは?とも思いましたが、あいにく使い慣れていないので頭で考えてみたら上記のような回答になりましたが、関数などを定義する場合はどのような記述になるでしょうか?

また、関数、クラスなどを使っていく際に必要な考え方、組み立て方、見通しの建て方などありましたらご指導よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

さらに、クラスをつかってかいてみました。
メソッドへの分離をした時にあった swith-case の分岐をなくすこともしてみました。

ruby

1class Mem 2 def initialize(mem = [0] * 2) 3 @mem = mem 4 @actions = { 5 SET: method(:do_set), 6 ADD: method(:do_add), 7 SUB: method(:do_sub) 8 } 9 end 10 11 def dump 12 @mem.join(' ') 13 end 14 15 def play(statements) 16 statements.each do |statement| 17 args = statement.split(' ') 18 inst = args.shift.to_sym 19 raise "bad instraction: #{inst}" unless @actions[inst] 20 @actions[inst].call(args) 21 end 22 end 23 24 private 25 26 def do_set(args) 27 @mem[args[0].to_i - 1] = args[1].to_i 28 end 29 30 def do_add(args) 31 @mem[1] = @mem[0] + args[0].to_i 32 end 33 34 def do_sub(args) 35 @mem[1] = @mem[0] - args[0].to_i 36 end 37end 38 39# lines = [] 40# x = gets.to_i 41# x.times { lines << gets } 42lines = [ 43 'SET 1 10', 44 'SET 2 20', 45 'ADD 40' 46] 47 48mem = Mem.new [0, 0] 49mem.play(lines) 50puts mem.dump 51

投稿2017/05/28 17:29

編集2017/05/28 17:34
katoy

総合スコア22324

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

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

退会済みユーザー

退会済みユーザー

2017/05/29 05:54

勉強になります。
guest

0

関数をつかって処理を分割してみました。
gets でのデータ入力を処理から分離させることもしています。
各関数が mem を入力、mem を返すようになってます。

a.rb

ruby

1def play(statements, mem) 2 statements.each do |statement| 3 tokens = statement.split(' ') 4 inst = tokens.shift 5 case inst 6 when 'SET' 7 mem = do_set(tokens, mem) 8 when 'ADD' 9 mem = do_add(tokens, mem) 10 when 'SUB' 11 mem = do_sub(tokens, mem) 12 else 13 raise "bad instraction: #{token[0]}" 14 end 15 end 16 mem 17end 18 19def do_set(tokens, mem) 20 pos = tokens[0].to_i - 1 21 val = tokens[1].to_i 22 mem[pos] = val 23 mem 24end 25 26def do_add(tokens, mem) 27 mem[1] = mem[0] + tokens[0].to_i 28 mem 29end 30 31def do_sub(tokens, mem) 32 mem[1] = mem[0] - tokens[0].to_i 33 mem 34end 35 36lines = [] 37x = gets.to_i 38x.times { lines << gets } 39 40mem = [0, 0] # [a, b] 41mem = play(lines, mem) 42puts mem.join(' ') 43

イメージ説明

Mem クラス(a と b の状態をもち、その状態を変更したり参照するメソッドを持つ) として定義すれば、各メソッドでいちいち mem を返すようなことは不要にできます。

クラスを定義すると、扱える変数を a, b だけでなくもっと多くするとか、SET, ADD, SUB 以外の操作もできるようにするといった場合に、変更とテストがしやすくなると思います。
(質問文のコード自体は短いので、そういった変更はいまのままでも簡単にできますが)

実際に、扱える変数を a..z に増やしたり、MUL, DIV, MOD といった処理をあつかえるように変更してみるとよいと思います。
(最終ゴールとしてはマシン語シュミレータをつくるとか、そのマシン語を生成するコンパイラーをつくるとか...)

投稿2017/05/28 04:04

katoy

総合スコア22324

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

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

garchomp

2017/05/28 12:34

買いおつありがとうございます! 確かにこれだとメンテナンス性も高く、拡張なども非常にしやすいですね・・・ 先のことも考えたプログラムを書けるように色々頑張ってみます! マシン語・・・難しそうですね・・・頑張ってみます(汗)
guest

0

arr = Array.new(2,0) # p a,b class Array def order(x) num = x[1].to_i case x[0] when "SET" self[num - 1] = x[2].to_i when "ADD" self[1] = self[0] + num when "SUB" self[1] = self[0] - num end end end gets.to_i.times{ arr.order(gets.split) } arr.join(" ").tap{|s| puts s }

自分がこの問題を解いた時の回答はこれですね
わざわざ新しいclassを書くよりはArrayクラスにメソッドを加えてしまった方が手取り早くコードが短くなると考えました。

投稿2017/05/30 02:36

haneru

総合スコア440

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

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

garchomp

2017/05/30 04:27

解答ありがとうございます! arrayクラスにメソッドを加える…そんなこともできるんですね… 全然考え付きませんでした^^; 勉強り成りました!
guest

0

Ruby

1a, b = 0, 0 2 3x = gets.chomp.to_i 4 5x.times do 6 e = gets.chomp.split("\s").map { |t| t.to_i.to_s == t ? t.to_i : t } 7 case e[0] 8 when 'SET' then e[1] == 1 ? a = e[2] : b = e[2] 9 when 'ADD' then b = a + e[1] 10 when 'SUB' then b = a - e[1] 11 end 12end 13 14puts "#{a} #{b}"

Ruby

1data = [] 2 3loop do 4 input = gets 5 break if input.nil? 6 data << input.chomp 7end 8 9def answer(array) 10 a, b = 0, 0 11 12 array.drop(1).each do |e| 13 e = e.split("\s").map { |t| t.to_i.to_s == t ? t.to_i : t } 14 case e[0] 15 when 'SET' then e[1] == 1 ? a = e[2] : b = e[2] 16 when 'ADD' then b = a + e[1] 17 when 'SUB' then b = a - e[1] 18 end 19 end 20 21 return "#{a} #{b}" 22end 23 24puts answer(data)

質問者様のコードを参考にしてやってみました。
メソッド初心者の私の個人的な考えですが今回の場合は
メソッドを使わないほうが簡単なのではと思います。

投稿2017/05/27 16:47

編集2017/05/27 17:02
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

garchomp

2017/05/28 00:21

回答ありがとうございます! メソッド使うかどうかは時と場合による。ですか。。。 同じ処理を複数回やる時にメソッドを考えた方が良さそうですね。 よく考えてみたら今回の場合ループで片付けられる。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問