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

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

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

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

4回答

5522閲覧

シフト管理アプリのアルゴリズム

raaacho

総合スコア28

Ruby

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2017/05/09 17:54

railsでシフト管理アプリケーションを作成しています.

しかし,最も重要なシフト決定のアルゴリズムがわかりません.
どなたかアドバイスいただけないでしょうか?

シフトの条件
・シフトは1ヶ月単位
・想定は約15人
・シフトは1日につき1人. よって時間は考慮しない.
・15人全員からシフトイン可能日時を受け付け,シフトを決定する.
・できるだけ1ヶ月のシフト回数が全員が公平(全員2回ずつが理想)になるようにする.

シフト入力受け付けまでは完了しているものとします.
またその情報に紐づいてユーザーIDも取れているものとします.
またデータベースはActiveRecordによりPostgreSQLを使用するとします.

以上のようなシフトを組むアルゴリズムがわかるかた,知恵を貸していただけないでしょうか.
データベース設計はまだしていないので,皆様のアルゴリズムに都合の良い設計で考えていただいて結構です.
シフト入力の形も問いません.

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

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

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

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

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

guest

回答4

0

これは、 **『組み合わせ最適化』**という応用数学の一分野の問題かと思います。

「組み合わせ最適化」とは特定の条件を満たす解の中で最適なものを求める問題です。

一般的には最適化ソルバーというツールを使用して解を求めることになろうかと思われます。(ソルバーは無料から有料まで様々あります)

ソルバー内でどのような処理(アルゴリズム)を行われているかは、書籍や文献をあたる必用があります。

「組み合わせ最適化」に関しては、ネット上にも様々な情報がありますので、とりあえず検索をかけてみてはいかがでしょうか。

投稿2017/05/10 04:28

編集2017/05/10 05:56
magichan

総合スコア15898

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

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

0

投稿2017/05/09 22:20

Zuishin

総合スコア28656

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

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

0

アルゴリズムではないですけど「時間割編成問題」でググってみては?
似てるような気がします。

投稿2017/05/09 17:58

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

Ruby

1# encoding: utf-8 2 3data = (1..30).to_a 4name = ('A'..'O').to_a 5hash = {} 6 7# シフトのサンプルを作成 8 9siken = [] 10 11=begin 1215.times do |n| 13 t = data.sample(rand(1..30)).sort 14 hash[:"#{name[n]}"] = t 15 siken << t 16end 17=end 18 19sample = [ 20 ['A', []], 21 ['B', [1]], 22 ['C', [1, 2, 13]], 23 ['D', [3, 2, 6]], 24 ['E', [2, 14, 23, 24, 29, 5]], 25 ['F', [4, 8, 7]], 26 ['G', [23, 27]], 27 ['H', [4]], 28 ['I', [15, 12, 11]], 29 ['J', [3, 6, 9, 12, 13]], 30 ['K', [7, 8]], 31 ['L', [4, 8, 3]], 32 ['M', [12, 15, 19]], 33 ['N', [21, 22]], 34 ['O', [30]] 35] 36 37sample.each do |key, value| 38 hash[key.to_sym] = value 39 siken << value 40end 41 42# シフトのサンプルから一日ごとに一か月の間に各人が入れる日の配列作成 43list = [] 4430.times do |x| 45 tmp_list = [] 46 hash.each do |key, value| 47 if value.include?(x + 1) 48 tmp_list << key.to_s 49 end 50 end 51 list << tmp_list 52end 53 54# 各人の入れる回数を数えて入れる日が少ない順に並べる 55check_list = list.flatten 56name.map!{|e| [check_list.count(e), e]}.shuffle! # ここを変更(shuffle or sort) 57 58# シフトの情報作成 59sift = [] 60name.each do |c| 61 test = hash[c[1].to_sym] 62 tmp = [] 63 test.each do |e| 64 if data.include?(e) 65 tmp << e 66 end 67 end 68 day = tmp.sample(2) 69 sift << [c[1], day] 70 data -= day 71end 72 73# 残った日の割り当て 74sift.sort! 75name.map!{|e| e[1]}.sort! 76check = (1..30).to_a - sift.map{|e| e[1]}.flatten 77 78unless check.size.zero? 79 name_list = [] 80 check.each do |d| 81 key = list[d - 1].sample 82 next if key.nil? 83 sift[name.index(key)][1].push(d) 84 end 85end 86 87# 出力 88a = [] 89sift.each do |n, v| 90 a << v 91 puts "#{n}:#{v.sort.join(',')}" 92end 93 94# 確認用 95puts '-' * 20 96a.each_with_index do |e, i| 97 flags = false 98 e.each do |ee| 99 unless siken[i].include?(ee) 100 flags = true 101 end 102 end 103 p flags 104end 105 106a.flatten! 107p a.size 108p a.uniq.size

実行結果例

A: B:1 C:2,13 D:3,6 E:5,14,24,29 F: G:23,27 H:4 I:11,15 J:9 K:7,8 L: M:12,19 N:21,22 O:30

データベースは分かりませんが考えてみました。
入れる日が少ない人から順に2つずつ日を選べるようにしました。
1日しか入れない人は1日だけ表示されます。
#補足
私のコードだとsampleのLのようにシフトが割り当てられない場合があります。

2017/05/10追記
shuffleをつけてみました。この変更で場合によってLにもシフトが割り当てられるようになりました。

投稿2017/05/09 19:55

編集2017/05/09 22:12
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問