いつもお世話になっています。
現在rubyで、2つの名前を入力すると、相性を10段階(10、20、・・・、100)で表示するプログラムを作成したいと考えています。
例えば)
・入力値
あなたの名前を入力してください
K
相手の名前を入力してください
M
・出力
相性は60%です
そして、診断結果自体はランダムで生成されるとイメージしていて、それでいて、全く同じ組み合わせを入力すると同じ相性になるということです。
<コード>
puts "あなたの名前を入力してください"
name1 = gets.chomp
puts "相手の名前を入力してください"
name2 = gets.chomp
print "二人の相性は"
p "#{rand(10)}" + "%"#ここの数字はそれほど問題ではありません。
これが現在のコードですが、診断結果はランダムなので、再度同じ名前を入力しても、診断結果は同じになりません。
ご存知の方がいれば、教えていただけると嬉しいです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答7件
0
その用途でよく用いられるのはハッシュです。
任意の文字列をハッシュに変換かける事を「ハッシュ化」と呼びます。
ハッシュには様々な用途があり、それに伴い様々な規約が存在します。
今回の質問には要件として「同じ名前を入力すると同じ結果になって欲しい」があります。
これがハッシュの仕様とピタリ一致するのです。
今回紹介するのは、ハッシュの規約の一つであるMD5です。
有名なのでRubyにもライブラリが用意されているようですね。(標準で使えるかな?)
https://docs.ruby-lang.org/ja/latest/class/Digest=3a=3aBase.html
以下はMD5の仕様です
- 16進数で表現されている
- 常に32文字に変換される
- 同じ文字列を変換すると、同じ文字列が登場する
- 暗号化の仕組みとしては弱いが、仕組みが単純な分速度が出る
例えばabc
をMD5に変換すると、必ず'900150983cd24fb0d6963f7d28e17f72'
という文字列になります。
Ruby
1require 'digest/md5' 2 3p Digest::MD5.hexdigest('abc') #=> '900150983cd24fb0d6963f7d28e17f72' 4p Digest::MD5.file('ruby-1.8.5.tar.gz').to_s #=> '3fbb02294a8ca33d4684055adba5ed6f'
MD5にハッシュ化された文字列は「16進数」です。
Rubyでは16進数の文字列をhexメソッドを使って簡単に数値に変換できます。
10通りの結果が欲しいのですよね?
結果の数値を% 10
で余りを求めれば10パターンの結果になります!
【おまけ】
Twitterでよくある診断は結果が日替わりですよね。
中身を見たわけではないですが、十中八九このテクニックの応用です。
abc
という文字列の上に日付データを足してハッシュ値として取り出しているのです。
2018/03/12 - abc
みたいな文字列作ってMD5形式に変換…という手法にすれば簡単に日替わりの結果が作れますね。
【追記】コードにしてみた
ちょっとしたコードを書いてみました。
JavaScript
1require 'digest/md5' 2 3a = Digest::MD5.hexdigest('太郎').slice(0, 3).hex 4b = Digest::MD5.hexdigest('花子').slice(0, 3).hex 5result = (a + b) % 11
0%〜100%が出てほしいなら11パターンじゃないですかね?
というわけで% 10
ではなく、% 11
にしました。
MD5で16進数の文字列にして、一部の文字列だけをsclieで切り出し、hexで数値に変換。
相性診断なので一度足してから% 10
で10の余りを求めています。
つまりresult
には0 〜 9
の数値が格納されています。
投稿2018/02/19 10:06
編集2018/02/19 10:42総合スコア21158
0
ruby
1names = %w[あなた 相手].map{|s| 2 puts "#{s}の名前を入力してください" 3 name = gets.chomp 4} 5# あなた + 相手 と 相手 + あなた が同一の結果の場合 6namehash = names.sort.join(',').hash 7# あなた + 相手 と 相手 + あなた が同一の結果とは限らない場合 8# namehash = names.join(',').hash 9 10print '二人の相性は' 11# p 1 + (namehash.to_s.chars.map(&:to_i).sum % 10) 12puts "#{1 + (namehash.to_s.chars.map(&:to_i).reduce(0,:+) % 10)}0%"
投稿2018/02/19 09:50
編集2018/02/19 10:15総合スコア15147
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/19 10:12
2018/02/19 10:15 編集
2018/02/19 10:25
2018/02/19 10:32
2018/02/19 10:35
0
次のようになるプログラムを書いてみました。
名前の入力を逆にしても同じ相性値になる事、
名前1 と 名前2 の結合結果が同じことでも、異なる名前の組み合わせなら異なる愛称値になる事、
特定の名前の組み合わせの相性値を 100 にすること (ここでは "太朗", "花子" の相性値を 100 にするようにした)
ruby
1equire 'digest/md5' 2 3BASE_TABLE = (0..100).to_a 4 5def my_table 6 table = BASE_TABLE 7 # "太朗", "花子" の相性は 51 だが、それを 100 に調整する 8 table[51] = 100 9 table[100] = 51 10 table 11end 12 13def val(name) 14 Digest::MD5.hexdigest(name).hex % 101 15end 16 17def match(one, two) 18 my_table[(val(one) + val(two)) % 101] 19end 20 21 22while true 23 puts "あなたの名前を入力してください (空入力すると終了します)" 24 name1 = gets.chomp 25 break if name1 == '' 26 puts "相手の名前を入力してください" 27 name2 = gets.chomp 28 puts "二人の相性は#{match(name1, name2)}\n" 29end
投稿2018/02/19 14:53
編集2018/02/20 11:56総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
rand
はRubyでランダムな数値を得る方法を参考にしました。
文字を整数に変換するために、hash
だと実行のたびに変わってしまったので、
ord
で変換してみました。
puts "あなたの名前を入力してください" name1 = gets.chomp puts "相手の名前を入力してください" name2 = gets.chomp seed = (name1 + name2).chars.map(&:ord).inject(:+) random_int = Random.new(seed).rand(1..10) puts "二人の相性は#{random_int * 10}%です"
投稿2018/02/19 10:29
編集2018/02/19 10:57総合スコア322
0
(私の読解力が足りないのか)ちょっとよくわからないです。
特に
そして、診断結果自体はランダムで生成されるとイメージしていて、それでいて、全く同じ組み合わせを入力すると同じ相性になるということです。
の部分。
数字はでたらめだけど
(K,M) なら毎回 60% って出るように仕向けること?
場合によってものすごく変わります。
もし、ある条件式があり、それで割り出す...っていうことをしないためにランダムって言っているのか、
完全にランダムでいいのか...
条件式に頼らないっていう意味なら
方法1: 配列( リストでもいいが。 )を用意し、それに適当に決め打ちして定義。 それを使う。
例えば Rubyはわからないのであくまで大雑把ですが、
{ 30, 10, 40, 100, 90 } の要素数5の配列を用意。
で、乱数発行して 乱数 r の位置のデータを表示する。
例えば r = 4 なら 4番目のデータ ( 4 - 1 = 要素数3 ) の 40 を出力する。
っていう風に。
方法2: テキストファイルを定義ファイルとみなして、それに記述されているデータを使う
例えば、
// definition.txt 内として 30 20 10 100 50
とあったら、
乱数 r が 3のとき、3行目の10 を出力...
これは方法1 の定義場所をテキストファイルにしただけ。
毎回同じ条件なら同じ値にする ( 例: (K,M)なら常に100% とする ) なら計算方法を考えたほうがいいかも。
例えば、男側の名前の長さ + 女側の名前の長さ / 2 で割り出すとか。
投稿2018/02/19 10:02
総合スコア4958
0
コードは以上ですか?
理由は単純に組み合わせデータを保存していないからです。
現在の処理ですと、Aさん(name1)Bさん(name2)の名前を入力して、その結果をランダムで出力するだけです。
コードを全て読んでいないので、どこからどこまでやっているのかわからないので、判断しかねますが、Aさん、Bさん、結果を保存する配列を作成し、そこにデータを格納します。
そして、再度入力したとき、入力された値が配列通りのものであれば、既に保存してあるデータを出力するようにする形になるかと思います。
コードを記述するにしてもいろいろと対応しなければならないものが多すぎるので、僕には無理です。配列とIF文を組み合わせればできるようになりますので、そちらを調べてみるとよいかもしれません。
投稿2018/02/19 10:01
総合スコア57
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
もっと仕様をしっかりしないと回答が難しい気がしますが。。。
均一な分布でなくてよいのであれば、足した文字列を数値化し、10 で割り、余りで分類するのが単純かと。
投稿2018/02/19 09:55
編集2018/02/19 09:55退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/19 10:09
2018/02/19 10:35
2018/02/19 10:40
退会済みユーザー
2018/02/19 15:13
2018/02/19 23:47 編集
退会済みユーザー
2018/02/20 00:13
2018/02/20 00:57
退会済みユーザー
2018/02/20 01:03