我將談論如何找到碰撞時的所有序列重複無限,當所有的起始時間爲0。這是很容易給這個適應有限的情況:只是檢查是否有任何你發現這種方式發生的碰撞發生得足夠早成爲一個問題。適應非0開始時間也很容易:只要將非0開始時間週期性地向後循環到0,並檢查您是否發現這種方式的任何碰撞發生的時間足以造成問題。
讓我們有一個表示通信窗口的數據結構。它將保存窗口的長度(以秒爲單位)以及該窗口正在使用的一系列時間範圍。因此:
type Block = (Int, Int)
data Window = Window
{ len :: Int
, blocks :: [Block]
}
(記號[Block]
說來存儲其元素爲Block
類型的列表,我們會解釋對Int
小號組成一個Block
爲開始時間和結束時間,併爲)。我們將保持不變,即如果w
是一個窗口並且t
是w
中的一個塊的開始或結束時間,則0 <= t < len w
。現在
,很容易使Window
時間越長,所提供的新的長度是舊的倍數:剛剛撞了len
,使現有blocks
的多個副本,由len
移,上升到新長度。因此:
unsafeExpand :: Int -> Window -> Window
unsafeExpand newLen (Window { len = oldLen, blocks = oldBlocks }) = Window
{ len = newLen
, blocks = [ (start + shift, end + shift)
| (start, end) <- oldBlocks
, shift <- [0, oldLen .. newLen-1]
]
}
(我稱這個unsafeExpand
因爲它假定newLen
是oldLen
多 - 我們將確保這下面,但unsafe
是一個提醒,有一個前提條件檢查我會用這。整個命名約定)
另一件事,很容易是要檢查特定塊是否重疊另一個特定塊:
blockCollides :: Block -> Block -> Bool
blockCollides (start, end) (start', end') = end >= start' && end' >= start
鑑於原始,很容易檢查WH以太兩個相同長度的窗口碰撞:只是檢查一個塊是否與另一個塊碰撞。實際上,因爲我們希望能夠稍後做一個有限版本的算法,所以不僅返回是否存在碰撞,而且還包括所有碰撞的列表將很方便。當然,一個空的列表表明沒有碰撞。
unsafeWindowCollisions :: Window -> Window -> [(Block, Block)]
unsafeWindowCollisions w w' =
[ (b, b')
| b <- blocks w
, b' <- blocks w'
, blockCollides b b'
]
爲確保兩個窗口具有相同的長度,我們可以將它們擴展到它們的最小公倍數。因此,我們可以把上面的不安全功能到一個安全的一個如下:
windowCollisions :: Window -> Window -> [(Block, Block)]
windowCollisions wShort wShort' = unsafeWindowCollisions wLong wLong' where
newLen = lcm (len wShort) (len wShort')
wLong = unsafeExpand newLen wShort
wLong' = unsafeExpand newLen wShort'
我們可以肯定它的好打電話unsafeExpand
因爲lcm a b
總是返回a
和b
的倍數;我們可以確定可以致電unsafeWindowCollisions
,因爲wLong
和wLong'
的長度相同(即newLen
)。
現在我們完成了:我們有一個算法來查找兩個窗口之間的碰撞。如果你有兩個以上的窗口,你可以兩兩檢查它們是否有碰撞。下面是ghci中的一些快速示例運行,以查看它的工作。以>
開頭的行表示我的輸入;其他行是解釋器的輸出。
> let testWindow1 = Window 600 [(300, 350), (400, 450)]
> let testWindow2 = Window 300 [(100, 150)]
> let testWindow3 = Window 200 [(151, 199)]
> let testWindow4 = Window 3 [(1, 1)]
> let testWindow5 = Window 4 [(2, 3)]
> windowCollisions testWindow1 testWindow2
[((400,450),(400,450))]
> windowCollisions testWindow1 testWindow3
[]
> windowCollisions testWindow4 testWindow5
[((7,7),(6,7)),((10,10),(10,11))]
如果您有固定的解決方案和相對較小的時間間隔,您可以使用數組(位域)來存儲每個插槽。 –
問題是我必須在具有非常少的空間和內存的微控制器上實現這一點。我還要管理無限次重複的最壞情況。但我會調查你的想法。 Thk –
提示:https://en.wikipedia.org/wiki/Least_common_multiple –