巧解表達(dá)式展開問題

這是一個業(yè)務(wù)上遇到的真實場景。
我們定義了一個配置文件格式,給機器資源分類。
寫出來大概是這個樣子

GroupA: MachineA, MachineB, MachineC
GroupB: MachineD, MachineE
GroupC: MachineA, MachineC
GroupD: GroupB & GroupC
......

總結(jié)一下, 有如下幾個規(guī)則:

  • Group的名字和Machine的名字都由用戶自己指定
  • Group的描述可以是一組機器(見上圖GroupA, GroupB, GroupC), 也可以是其它Group的運算表達(dá)式(見上圖GroupD)
  • 表達(dá)式支持'&', '|', '-' 三種運算符, 分別代表集合運算中的交集,并集,差集
  • 表達(dá)式不能包含括號, 計算的時候按照從左到右的順序

問題來了, 當(dāng)我們拿到這么一份配置文件的時候,需要知道每個Group包含多少機器,請問如何編碼實現(xiàn)?

這個問題乍一看很簡單,如果Group的描述本身已經(jīng)是機器組,直接計算Machine的數(shù)量即可。 如果Group的描述是表達(dá)式, 則把表達(dá)式中出現(xiàn)的Group用機器組替換一下,再求數(shù)量也行啊。 難點在哪呢?
關(guān)鍵就在替換這里, 我們看下面一個場景

GroupA: GroupB & GroupC
GroupB: GroupD | GroupE
GroupC: MachineA, MachineB
GroupD: GroupA & GroupE
GroupE: MachineC, MachineD

讀者朋友可以自己試一試用代換法求解GroupA, 然后很快就會發(fā)現(xiàn)"臣妾做不到啊",原來, A引用了B,B引用了D, D又引用了A, 形成了死循環(huán)。 也就是說這個配置文件本身就是錯誤的, 但是如果我們的代碼不能檢測到這種錯誤,就會導(dǎo)致因為用戶的錯誤配置造成系統(tǒng)死循環(huán), 多么可怕啊。
怎么檢測死循環(huán)呢, 其實也不難, 仔細(xì)想一想,這其實就是一個有向圖環(huán)檢測問題(如果不理解,可以參考筆者的另一篇文章--業(yè)務(wù)模型抽象成有向圖環(huán)檢測算法,模型和這個很像)。
這樣做是解決問題了,但是算法寫起來好復(fù)雜,有沒有簡單點的方法呢?

其實筆者當(dāng)初實現(xiàn)的時候也是按照上述的方法解決的,但有一天整理這段代碼時發(fā)現(xiàn)了,根本不用這么復(fù)雜好嘛!轉(zhuǎn)換一下思路, 調(diào)整一下展開表達(dá)式的順序就解決了, 解法如下:

  1. 遍歷所有的Group, 把所有只需要一層展開的表達(dá)式 轉(zhuǎn)化成 Machine List(一層展開指的是表達(dá)式中引用的Group均為確定的Machine List)
  2. 重復(fù)步驟1,如果在整個遍歷過程中,沒有新的表達(dá)式被展開, 說明遇到了死循環(huán),流程終止。 如果所有的表達(dá)式都被展開, 說明問題解決。

是不是變簡單了,這種做法連死循環(huán)都不需要檢測了。其實,事后想一想,這算法并沒有什么難度(甚至小學(xué)生都會,因為這就是數(shù)學(xué)中的多元一次方程啊),只是在一種思維遇到困難的時候,我們往往可以跳出思維定式,找到簡潔之道。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容