2013-08-15 3 views
2

У меня есть следующие структуры в моем коде:периодические интервалы

class Interval { 
    public $start, $end; 
} 

class Period { 
    public $interval, $period; 
} 

Они представляют собой простой и повторяющийся интервал, соответственно. Например:

**** // This is a simple interval [0, 4]. 
****__****__**** // This is "repeating interval" with period = 2 (each underline means pause between intervals) 

Таким образом, период представляет собой бесконечный набор интервалов. «Расстояние» (или пауза) между каждым из них является постоянным.

Мне нужна функция, которая принимает произвольный интервал и период и говорит, является ли этот интервал внутри периода или нет. «Внутри» означает, что данный интервал находится внутри любого из интервалов в периоде.

function interval_inside_period(Interval $interval, Period $period) { 
    return is_inside ? true : false; 
} 

$period = new Period(new Interval(0, 4), 10); 
// The first 3 intervals in this Period are [0, 4], [14, 18] and [28, 32] 
// Like: ****__________****__________**** 
interval_inside_period(new Interval(15, 16), $period); // === true, is inside [14, 18] 
interval_inside_period(new Interval(29, 32), $period); // === true, is inside [28, 32] 
interval_inside_period(new Interval(3, 5), $period); // === false, overlaps but is not inside 
interval_inside_period(new Interval(17, 29), $period); // === false, overlaps but is not inside 
interval_inside_period(new Interval(11, 12), $period); // === false 
interval_inside_period(new Interval(20, 27), $period); // === false 

Проблема в том, что из-за отсутствия математического опыта я понятия не имею, как реализовать такую ​​функцию. Я думал о волновых функциях, особенно о rectangular periodic function, но я понятия не имею, как описать Period с такой функцией.

Простой Период с одинаковой длины и периодичности может быть описана Square wave function:

$square_period = new Period(new Interval(0, 2), 2); 
// __**__**__**__** 
// This function describes such Period. 
function is_square_period($n) { 
    return ($n >= 0 && ($n/2) % 2) == 0 ? 1 : 0; 
} 

Такой подход дает возможность найти, если любое целое число $ п лежит внутри периода или нет. Но я не знаю, может ли это быть использовано для решения проблемы.

Любые идеи? Заранее спасибо.

ответ

1

Давайте посмотрим ... Смещение между двумя последовательными интервалами - $start + $end + $period. Таким образом, начало интервала k составляет k * ($start + $end + $period) + $start. Разделив x из заданного интервала (new Interval(x, y)) по $start + $end + $period мы можем рассчитать наши k:

// this is should be integer division... 
$k = ($interval->start - $period->interval->start) 
    /($period->interval->start + $period->interval->end + $period->period); 

Теперь мы можем вычислить границы интервала k и проверить, если данный интервал внутри него.

$kStart = $k * (
     $period->interval->start + $period->interval->end + $period->period 
    ) + $period->interval->start; 
$kEnd = $kStart + ($period->interval->end - $period->interval->start); 

return $kStart <= $interval->start && interval->end <= $kEnd; 

Это дает следующий с периодом и первым интервалом от вашего вопроса:

$k = (15 - 0)/(0 + 4 + 10) = 15/14 = 1 
$kStart = 1 * (0 + 4 + 10) + 0 = 1 * 14 + 0 = 14 
$kEnd = 14 + (4 - 0) = 18 

return (14 <= 15 && 16 <= 18) // true 

Значения для остальных интервалов являются:

iStart | iEnd | k | kStart | kEnd | result 
-------+------+---+--------+------+------- 
    29 | 32 | 2 |  28 | 32 | true 
    3 | 5 | 0 |  0 | 4 | false 
    17 | 29 | 1 |  14 | 18 | false 
    11 | 12 | 0 |  0 | 4 | false 
    20 | 27 | 1 |  14 | 18 | false