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

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

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

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

Q&A

4回答

446閲覧

rubyでじゃんけん列車のコードを作るときに、どのような考え方をしますか?

off

総合スコア6

Ruby

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

1グッド

0クリップ

投稿2024/03/05 08:03

実現したいこと

大学の課題で出たのですが、途中でつまずいてしまいました

ルール
5人で三回試行する
人間は1,2,3,4,5で表す
じゃんけんで負けたプレイヤーは勝ったプレイヤーの後ろにつく
3回終了時点で一番長い列を作った先頭のプレイヤーが優勝

インプットは「数字+半角空白+数字」で与えられ、先頭の数字が勝ったプレイヤーで、2番目の数字が負けたプレイヤー(じゃんけん列車といいつつジャンケンはしない

(ex 1)
インプットが
2 4

プレイヤー2の勝ち。プレイヤー4の負け。プレイヤー2の後ろにプレイヤー4がつく。

(ex 2)
インプットが
2 4
3 1
2 3
の場合、
1回目の試行で、1,[2,4], 3, 5
2回目の試行で、[2, 4], [3, 1], 5
3回目の試行で、[2, 4, 3, 1], 5
終了。アウトプットは2

発生している問題・分からないこと

私は5個の配列(a,b,c,d,e)を作ってそれぞれ1,2,3,4,5を格納
1回目の試行が仮に「2 4」の場合、appendメソッドを使って、b[] = [2, 4]
と言うふうに作ろうかと考えたのですが、問題が2個あります。

問題①
上の(ex 2)でいうと1回目の試行が「2 4」だとb[0]とd[0]の配列が関係してくるのですが、1個1個if文を作って、a[0]は2でも4でもないから違う。b[0]は2だから関係ある!、、、みたいな作り方は賢くない。

問題②
そもそも別のやり方があるのではないか?

と考えています。
アドバイスをいただけませんか
よろしくお願いいたします。

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

グーグル検索してもそれらしきコードは見当たらないので質問させてください。

補足

特になし

melian👍を押しています

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

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

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

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

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

tatsu99

2024/03/05 08:49

不明点1 必ず3回試行しますか。 1 2 で終わることはないですか。 不明点2 1 2 3 4 5 4 の場合、優勝者は1,3,5の誰ですか。
off

2024/03/05 11:07

説明不足で申し訳ありませんでした。 不明点1 今回は必ず3回です。(ex 1)の試行が一回しか載せていなかったのは見やすさを重視した為です。私のミスです。 不明点2 優勝者は誰でもありません。 これも説明不足で申し訳ありません。じゃんけん列車のルールは先頭にいる人のみじゃんけんをする権利があります。 そのため試行2回目の後ろの数字が「4」となっていますが、プレイヤー4はプレイヤー3に負けている為、プレイヤー4の後ろに並ぶことになります。 ですので、、試行3回目にじゃんけんする権利を持っているプレイヤーは1or3or5のみです。それ以外はエラーになります。 今回はエラーが起きるような前提でインプットはしない場合で考えています。
Mugheart

2024/03/10 09:38

5名で3回ジャンケンが行われる場合、必ず3回目のじゃんけんの勝者が出力されるので、 今回の問題ではロジックフル無視で3回目のじゃんけんの勝者を出力すると正解になりそうな気がします。 そういう話ではなく、人数が増えた場合、じゃんけんの試行回数が増えた場合でも応用可能な回答としてはotnさんの回答に +1 です。
Mugheart

2024/03/10 10:35

> 5名で3回ジャンケンが行われる場合、必ず3回目のじゃんけんの勝者が出力される すみません、こちら誤りでしたので取り消します。
guest

回答4

0

上の(ex 2)でいうと1回目の試行が「2 4」だとb[0]とd[0]の配列が関係してくるのですが、1個1個if文を作って、a[0]は2でも4でもないから違う。b[0]は2だから関係ある!、、、みたいな作り方は賢くない。

お気づきの通りです。気づかずそのまま書いてしまう人が多いですね。「プレーヤーごとに1つ変数を作ろう」と思ってしまうのは、ArrayやHashを学習してないことは無いと思うので、理解不足(それぞれどういう場面で使うか理解できてない)でしょう。

abといった単独の変数にするのではなく、ArrayもしくはHashを使います。
プレイヤー名は数字ですが、数値としての意味は無さそうなので、文字列にしてありますので、
データだけ変えれば「一郎」「二郎」・・・などに出来ます。

Ruby

1data = DATA.readlines 2 3players = ("1".."5").map{|player| [player]} 4# [["1"], ["2"], ["3"], ["4"], ["5"]] 5 6data.each do |line| 7 winner, loser = line.chomp.split 8 winner_idx = players.index{|row| row[0]==winner} 9 loser_idx = players.index{|row| row[0]==loser} 10 fail "Invalid Player Name" unless winner_idx and loser_idx 11 players[winner_idx].concat(players[loser_idx]) 12 players.delete_at(loser_idx) 13end 14 15max = players.max_by{|row| row.length} 16puts "Winner is player\##{max[0]}" 17 18 19players = ("1".."5").map{|player| [player,[player]]}.to_h 20# {"1"=>["1"], "2"=>["2"], "3"=>["3"], "4"=>["4"], "5"=>["5"]} 21 22data.each do |line| 23 winner, loser = line.chomp.split 24 fail "Invalid Player Name" unless players[winner] and players[loser] 25 players[winner].concat(players[loser]) 26 players.delete(loser) 27end 28 29max = players.max_by{|head,row| row.length} 30puts "Winner is player\##{max[0]}" 31 32__END__ 332 4 343 1 352 3

Arrayの方もデータのチェックをしないで良ければ(からなず該当データがあると仮定)、もうすこし短く書けそうです。

投稿2024/03/05 11:14

otn

総合スコア84566

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

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

otn

2024/03/05 11:26

5名で3回なので、同率一位は無い前提ですが、あり得る場合は、 求まった勝者の列の長さを取得して、 列の長さがそれと等しい要素を全部抽出します。 また、簡明のために「勝負をデータに反映する」「最後のデータを見て最終勝者を決める」を分けて書いてますが、勝負の都度、最長列かどうか判断して最終勝者を保存しておく方法もあり、人数が膨大な場合は効率的です。 応用として、やってみましょう。
guest

0

最初にリストから敗者を削除して、勝者の次の位置に敗者を挿入するという方法が考えられます。

ruby

1players = [1, 2, 3, 4, 5] 2 3ARGF.each do |line| 4 winner, loser = line.split.map(&:to_i) 5 players.delete(loser) 6 players.insert(players.index(winner)+1, loser) 7end 8 9print(players)

投稿2024/03/05 08:56

編集2024/03/05 09:34
melian

総合スコア19818

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

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

0

この課題は 「対戦の組み合わせを作り出してじゃんけんさせる」のではなく、「対戦の組み合わせとその結果」を外から与えられますし、勝者のみを出力すればよいので、プレイヤーを初めに設定する必要は無いです。

players = Hash.new{|h,k| h[k] = [k]} 3.times do winner, loser = gets.chomp.split players[winner] << loser end puts "勝者は #{players.sort_by{|player, list| list.size}.last.first}"

$ ruby gomi.rb
一太郎 花子
松 竹
一太郎 松
=> 勝者は 一太郎

5人と言いながら5人目の 梅 が出てきませんが、じゃんけん結果に出てこない==じゃんけんしていない ということは後ろに誰も居ないので、勝者では有りえませんから気にしないで良いです。

投稿2024/03/05 13:46

編集2024/03/05 13:48
winterboum

総合スコア23349

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

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

0

やり方はいろいろあると思いますが、自分であれば、プレイヤの後ろにいるプレイヤ一覧を管理するためのHashを導入して処理すると思います。

Ruby

1# next_player[プレイヤ] = [後ろにいるプレイヤの一覧] 2# 例) プレイヤ2の後ろに3,4,5がいる場合 … next_player[2] = [3, 4, 5] 3# 例) プレイヤ1の後ろに誰もいない場合 … next_player[1] = [] 4next_player = {} 5(1..5).each{|player| next_player[player] = []} 6 7# 入力を一行づつ処理する 8$stdin.each do |line| 9 winner, loser = line.chomp.split.map(&:to_i) 10 11 # 負けたプレイヤと、負けたプレイヤの後ろにいたプレイヤが 12 # 勝ったプレイヤの後ろにつく 13 next_player[winner] << loser 14 next_player[winner].concat(next_player[loser]) 15 16 # 負けたプレイヤの後ろにはだれもいなくなる 17 next_player[loser].clear 18end 19 20# 後ろにいるプレイヤの数が多いプレイヤを出力する 21puts (1..5).max_by{|player| next_player[player].size}

投稿2024/03/05 09:40

neko_the_shadow

総合スコア2230

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問