2017-07-21 23 views
2
的時間表

場景:計數可行的組合給出同時滿足類

  • 一組學生(「001」,「002」 ...)都有一組類,他們需要在學校參加。
  • 時間表是爲每個學期的每個時段發生的班級列表,分爲同時發生的班級集合
  • 任務是分析給定時間表的「好」情況,哪裏好意味着每個學生都能參加他們需要的所有類的,在許多不同的排列儘可能

問題描述:

給定一個哈希:

hash = { 
    '001' => ['MX1','EF1','HG1','PN1','SP1','AU1'], 
    '002' => ['MP1','EF1','HG2','PN4','SC1','AU3'], 
    '003' => ['MG1','EF2','HP1','PP1','SC1','AU1'] 
    } 

和二維陣列:

schedule = [ 
['MX1','EF2','XE1','SP1','AU4'], 
['MX1','EF1','HP1','PP1','AU1'], 
['MP1','MG1','SP1','HG2','PN1','AU1','MX1','EG1','HG1'], 
['MG1','EF2','PN4','SC1','AU1','SP1'], 
['PP1','PN1','PN4','EF1','EF2'], 
['SC1','PP1','HP1','AU1'] 
] 

我想在多少不同的方式從hash值的元素可以與來自schedule陣列相匹配以發現,造成的結果散列:

{ 
'001' => 1, # just using example values, this is a count 
'002' => 0, # of the combinations of the array from hash 
'003' => 2 # that can be matched to each array in schedule 
} 

     # without replacement 

「匹配」意味着,給定一個哈希值數組: ['MX1','EF1','HG1','PN1','SP1','AU1'] 每個元素都可以在與schedule不同的數組中找到。爲hash['001']

一個匹配:

{ 
'MX1' => schedule[0], # given here in hash form only 
'EF1' => schedule[1], # for illustrative purposes, 
'HG1' => schedule[2], # I don't need to represent 
'PN1' => schedule[4], # each match 
'SP1' => schedule[3], 
'AU1' => schedule[5] 
} 

如果有學生0可能的匹配,我們知道,我們必須將一些類,更多的比賽,可能每一個學生,更好的安排。

+1

歡迎使用stackoverflow。這是一個幫助用戶解決問題的網站,但他們嘗試失敗,但無法解決。看起來你沒有嘗試,或者如果你有,你沒有顯示你的嘗試。請張貼你的工作並尋求在特定領域的幫助。 – moveson

+0

根據我的理解,您希望從'schedule'數組中的'hash'(變量名)獲得最小值的計數。比方說,在'hash ['001']'中,'MX1'發生了三次,但其他值是'HG1'一次。所以鍵「001」的最終輸出將是「1」。我對嗎? –

+0

嗯,我不太確定它是否總是最小。 –

回答

1

假設一個學生必須參加以下類別:

classes = ['MX1','EF1','HG1','PN1','SP1','AU1'] 

首先,爲了提高效率,轉換schedule到的套陣列。

require 'set' 

sch_sets = schedule.map { |a| a.to_set } 
    #=> [#<Set: {"MX1", "EF2", "XE1", "SP1", "AU4"}>, 
    # #<Set: {"MX1", "EF1", "HP1", "PP1", "AU1"}>, 
    # #<Set: {"MP1", "MG1", "SP1", "HG2", "PN1", "AU1", "MX1", "EG1", "HG1"}>, 
    # #<Set: {"MG1", "EF2", "PN4", "SC1", "AU1", "SP1"}>, 
    # #<Set: {"PP1", "PN1", "PN4", "EF1", "EF2"}>, 
    # #<Set: {"SC1", "PP1", "HP1", "AU1"}>] 

然後爲每個學生重複以下步驟。

classes.permutation(classes.size). 
     count { |p| sch_sets.zip(p).all? { |s,cl| s.include?(cl) } } 
    #=> 1 

對於那些好奇,在這種情況下,工作的排列,我們只需要改變countselect(或者,因爲在這裏只有一個,find)。

classes.permutation(classes.size). 
     select { |p| sch_sets.zip(p).all? { |s,cl| s.include?(cl) } } 
    #=> [["MX1", "EF1", "HG1", "SP1", "PN1", "AU1"]] 

請參閱下列實例方法的文檔。

  • permutationsize爲類Array
  • include?爲類Set
  • countzipall?select所包含的模塊Enumerable

實例方法to_set加到Enumerable當時需要(請參閱Set文檔的第二段)。

+1

感謝您的建議,我把實施信息放在最上面,我將轉換爲您建議的清晰的類別符號,並使更改設置以及。 這太有意思了,我確信我正在嘗試做的事情可能是這樣的 - 我的嘗試跑了200行,我無法弄清楚如何在沒有替換的情況下做到這一點(一名學生與你的班級考試如果每個集合中都出現'MX1',則算作有效) 關閉以瞭解zip方法,但我會在我將這些邏輯包裹起來後再返回來進行更新,再次感謝您 – zqe