🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Q&A

解決済

2回答

918閲覧

Rubyで麻雀の理牌をし昇順に左から小さい順に並べ替えたい。つまり、数字と英単語混ざったものをソートしたい。

DrqYuto

総合スコア432

Ruby

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

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

0グッド

1クリップ

投稿2019/10/02 18:15

最近麻雀を勉強し始めました。
将来は麻雀アプリを作りたいと思い。
先ずはリーパイの実装を考えました。

一種類の文字なら

puts http://gets.to_s.split("").sort.join("")

2134m
.#=>
1234m
にすることできました。
しかし、二種類の文字になるとうまくできません。

r=gets.to_s puts r.split("").sort.join("")

.#=>
2134p2134m

11223344mp

となり、期待している1234p1234mとなりませんでした。
他には、sort_byを使えばいいかと考えました。

r=gets.to_s puts r.split("").sort_by(&:to_i).join("")

.#=>
pm11223344

こっちもうまくいきませんでした。

英単語のインデックスで分ければいいかと思いましたが。

r=gets.to_s puts r.index("p")

.#=>
4
とインデックスは取ったのですが,partitionの条件文が分かりません。

  • 参考

stackoverflowのsort_byを見ましたがURL忘れちゃいました…

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

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

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

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

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

guest

回答2

0

内部的には通番になる ID を振って

  • 萬子 1~9
  • 索子 11~19
  • 筒子 21~29
  • 字牌 31~37

しまった方が楽かも知れません。

投稿2019/10/03 00:10

tacsheaven

総合スコア13703

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

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

winterboum

2019/10/03 00:39

2134p2134m の記法、質問の書き方からみて、筒子の2134 と 萬子の2134という意味だろう、と解釈したのですが、これ、見る分には良いかもですが、プログラムで扱うのは厄介、というか 扱えるのかな。。。。
tacsheaven

2019/10/03 00:49

牌一つがオブジェクトですから、管理用の ID と、表示用の表現(4m とか)をまとめて扱っちゃえばよいだけですね(極端な話、to_s() が 4m などの形式で返せばよいかと)
Mugheart

2019/10/03 02:08

静的なデータとして持たせておけばいいかもしれないですね。 個人的にはクラスを萬子、索子、筒子、字牌で分けておいて、それぞれ1からIDを振ったほうが管理が楽な気がしますし、ソートも柔軟に行えそうです。 コード的にもクラスが別れていてIDが牌の値を示している方がわかりやすそうです。
winterboum

2019/10/03 02:11

super class 骰子 を継承ですかね。
tacsheaven

2019/10/03 02:30

んー……管理用のID(これはユニーク)と、オブジェクトの属性として「種別」「値」を持たせればいいような。ID が DB でいうところの auto increment なシーケンスのような扱いですね。 ※赤牌とかあっても属性で対処できるし
winterboum

2019/10/03 02:37

modelを分けたほうがよいか属性で分けるか、は 属性で場合分けする case や if がどのくらい目障りになるか、次第かとおもいます。
Mugheart

2019/10/03 02:45 編集

というよりも将来的には役を形成することになると思うんですが、それを想定した時にどちらが楽になるかですね。僕は分けたほうが楽な気がします。毎回 種別&&値 みたいなので条件分岐するより、値だけ見て各クラスでダックタイピングして最後にドッキングして評価した方が楽そう...?
Mugheart

2019/10/03 02:48 編集

いや、ごめんなさい、そうでもないかもしれない。 その辺りはよく要件を定義してから考えた方が良さそうですね。
winterboum

2019/10/03 02:51

私だと とりあえず属性で分けて、目障りになってきたらリファクタする かなぁ。
DrqYuto

2019/10/03 05:05

ありがとうございます!
guest

0

ベストアンサー

"2134p2134m".split(/([^\d])/).map{|s| s.split("").sort}.flatten.join

投稿2019/10/02 21:20

winterboum

総合スコア23567

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

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

Mugheart

2019/10/03 00:22

どうでもいい話にはなるんですが、split('') の代わりに chars、map{...}.flatten の代わりに flat_map{...}を使うほうが高速です。 text = 'HelloWorld' Benchmark.bm do |r| r.report { 1000000.times { text.chars } } r.report { 1000000.times { text.split('') } } end user system total real 0.752061 0.000867 0.752928 ( 0.753985) 5.447087 0.006786 5.453873 ( 5.461046) sample = text.chars.zip Benchmark.bm do |r| r.report { 1000000.times { sample.flat_map(&:itself) } } r.report { 1000000.times { sample.map(&:itself).flatten } } end user system total real 0.990339 0.001310 0.991649 ( 0.993212) 2.244717 0.004964 2.249681 ( 2.256893)
winterboum

2019/10/03 00:37

ありがとうございます。 文字列をバラバラにする、ってまず使わないもので chars すっかり忘れてました。
DrqYuto

2019/10/03 05:06

ありがとうございます!
DrqYuto

2019/10/03 15:29

無事 #=>1234p1234m となり、期待した結果を得られました~
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問