プロが教えるわが家の防犯対策術!

Rubyのプログラミングに詳しい方、宜しくお願いします。
何処を修正すべきかわかりません。現段階でのプログラムと実行結果の写真を添えました。
<内容>
hw.txtファイルから複数人の名前、身長、体重を読み込み、各人のBMIを求めてBMI値の高い人から順にそれぞれの名前、身長、体重、BMIを出力するプログラムを作ろうとしています。

<hw.txtファイル>
山田 太郎 169.4 80.2
中町 太郎 169.1 60.9
武田 花子 158.5 52.1
谷口 一人 180.2 75.5
三好 三吉 170.4 55.5
三川 一二三 163.3 77.0
高橋  江氏 170.0 65.0

<理想>
三川.....
山田.....
谷口
高橋
中町
武田
三好

「Rubyのプログラミングに詳しい方、宜し」の質問画像

質問者からの補足コメント

  • このような形でなんとか表示できました!助けてくださった方々ありがとうございました。

    「Rubyのプログラミングに詳しい方、宜し」の補足画像1
      補足日時:2020/11/06 17:31

A 回答 (5件)

以下でどうでしょうか。

「Rubyのプログラミングに詳しい方、宜し」の回答画像1
    • good
    • 0
この回答へのお礼

ありがとうございます
Webのruby editorを使用していますのでそちらで試してみようと思います。細かく解説して頂きとても助かります。

お礼日時:2020/11/06 16:33

> ありがとうございます。

まだ初心者で使ったことのない機能も多々ありますので、確認しながら進めたいと思います。参考にさせていただきます。

はい。

いずれにせよ、まずポイントとしては、

1. 関連付けたデータ同士はバラバラにせず、配列/リストでまとめてしまう。

つまり、各人の名前、体重、身長なんかはファイルから読み込んだ時点で、まとめて扱うようにしてしまいましょう。特に今回みたいに「BMI値でソーティングせよ」って指定されてる場合は、その配列にBMI値もまとめてしまう。わざわざバラバラにして「新しく変数を作る」ってのは作戦的には愚の骨頂ですね。どのみち最終的にはひとまとめにして出力せなあかんので、意識的にまとまったデータとして扱うのが吉、です。
結果、今回は複数のデータがあるので、構造的にはデータのデータになる。つまり、実装的には配列の配列、としてデータを設計するのが良いでしょう。こういうテクニックは割と普遍的です。
Rubyにはこういう配列みたいな「便利な」データ型(コレクション、とか呼んだりもするけど)は、他にハッシュとか、があるんで、目を通してみて下さい。

2. Rubyのような関数型言語に影響を受けた(超)高級言語のソーティングはコレクション相手に単純なソート以上の事が出来る。

通常、ソーティングは単純な数値とか文字列相手に行います。ところが、Rubyみたいな賢い言語だと配列みたいなコレクション相手にもソーティングする事が可能で、これが今回の問題におけるキモ、となります。
カテゴリ覗いてみれば分かりますが、C/C++なんかではソート自体は「アルゴリズムの宿題」になったりするカンジなんですが、出来たモノは物凄く貧弱で、言い換えるとRubyでカンタンに出来る事がC/C++では七面倒臭い、って事です(この問題をC/C++でやるとしたらメチャクチャめんどくさいので、間違いなく死にます)。
そして、1.で「扱うデータをまとめよ」と言う方針を立てるのは、Rubyの「高機能性」に頼る戦略ですね。「頼る」とは何とも情けない表現ですが、使えるモノは使いましょう。
僕はsort_byを用いましたが(別に貴方のようにsortを使っても構わない)、いずれにせよ、データ、「配列の配列」が次のようにあったとします。

[[3, 6], [1, 8], [0, 9], [2, 7], [4, 5]]

これをソーティングする、とすると「何によって?」と言う問題が出てきますよね。関数型言語に影響を受けているRubyだと「要素番号」を指定する事によって「任意の要素に従って」ソートする事が可能なのです。

➜ ~ irb
irb(main):001:0> s = [[3, 6], [1, 8], [0, 9], [2, 7], [4, 5]]
irb(main):002:0> s
=> [[3, 6], [1, 8], [0, 9], [2, 7], [4, 5]]
irb(main):003:0> s.sort_by {|a| a[0] } # 配列 s の第一要素を利用してソート
=> [[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]
irb(main):004:0> s.sort_by {|a| a[1] } # 配列 s の第二要素を利用してソート
=> [[4, 5], [3, 6], [2, 7], [1, 8], [0, 9]]
irb(main):005:0>

と言うわけで、Rubyでは「まとまったデータ」(コレクション)相手にもビビらないでソートをかます事が可能なのです。
    • good
    • 0
この回答へのお礼

助かりました

別々にデータを分けていた初めの段階で、まとまったデータにする必要があるようには薄々感じていたのですが、具体的な方法が知識不足により見つけられなかった事も一つの要因でした。詳しい解説をして頂いた事にはとても感謝しています。rubyの特徴を少し知れた気がします。

お礼日時:2020/11/07 02:13

No2です。

名前(性+半角スペース+名)が半角で20バイトを超えると
エラーが発生します。(20バイトで左詰めにしているため)
その場合は
name += " " * (20 - name.encode("WINDOWS-31J").bytesize)

name += " " * (30 - name.encode("WINDOWS-31J").bytesize)
等にしてください。(そうすると30バイトで左詰になります)
    • good
    • 0

s = []


File.open("hw.txt") do |io|
io.each do |line|
 tmp = line.split(" ", 4)
 s << [tmp[0] + " " + tmp[1], tmp[2], tmp[3].strip, tmp[3].to_f / (tmp[2].to_f / 100) / (tmp[2].to_f / 100)]
 end
end
s = s.sort_by{|x| x[3]}.reverse
puts "氏名-------身長----体重----BMI"
s.each {|var|
 puts var.join(" ")
}
    • good
    • 0
この回答へのお礼

ありがとうございます。まだ初心者で使ったことのない機能も多々ありますので、確認しながら進めたいと思います。参考にさせていただきます。

お礼日時:2020/11/06 16:35

No1です。

文字コードはUTF-8です。
実行結果です。
「Rubyのプログラミングに詳しい方、宜し」の回答画像2
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!