我在 IRC 上询问并收到了两个回复。我将把它们都发布出来,以便其他人受益(这样我就不会丢失它们,因为我很快就会详细介绍它们)。
示例 1 TML
<pre><?php
$cond = array(
array('a', 5, 15),
array('a', 5, 15),
array('d', 9, 50),
array('a', 45, 60),
array('a', 2, 70),
array('d', 1, 150),
);
function buildAcl($set) {
$allow = array();
foreach($set as $acl) {
$range = range($acl[1], $acl[2]);
switch($acl[0]) {
case 'a':
$allow = array_unique(array_merge(array_values($allow), $range));
break;
case 'd':
foreach($range as $entry) {
unset($allow[array_search($entry, $allow)]);
}
}
}
return $allow;
}
var_dump(buildAcl($cond));
var_dump(buildAcl(array(array('a', 5, 15), array('d', 10, 50), array('a', 45, 60))));
示例 2(matslin)
<?php
$conds = array(
array('a', 5, 15),
array('a', 5, 15),
array('d', 9, 50),
array('a', 45, 60),
array('a', 2, 70),
array('d', 1, 150),
);
$segments = array();
foreach($conds as $cond)
{
print($cond[0] . ': ' . $cond[1] . ' - ' . $cond[2] . "\n");
if ($cond[0] == 'a')
{
$new_segments = array();
$inserted = false;
$prev_segment = false;
foreach($segments as $segment)
{
if ($segment['begin'] > $cond[2])
{
$new_segments[] = array('begin' => $cond[1], 'end' => $cond[2]);
$new_segments[] = $segment;
$inserted = true;
print("begun\n");
continue;
}
if ($segment['end'] < $cond[1])
{
print("end\n");
$new_segments[] = $segment;
continue;
}
if ($cond[1] < $segment['begin'])
{
$segment['begin'] = $cond[1];
}
if ($cond[2] > $segment['end'])
{
$segment['end'] = $cond[2];
}
$inserted = true;
if (
$prev_segment &&
($prev_segment['begin'] <= $segment['begin']) &&
($prev_segment['end'] >= $segment['end'])
)
{
print("ignore identical\n");
continue;
}
print("default\n");
$prev_segment = $segment;
$new_segments[] = $segment;
}
if (!$inserted)
{
print("inserted at end\n");
$new_segments[] = array('begin' => $cond[1], 'end' => $cond[2]);
}
$segments = $new_segments;
print("---\n");
}
if ($cond[0] == 'd')
{
$new_segments = array();
foreach($segments as $segment)
{
# not contained in segment
if ($segment['begin'] > $cond[2])
{
print("delete segment is in front\n");
$new_segments[] = $segment;
continue;
}
if ($segment['end'] < $cond[1])
{
print("delete segment is behind\n");
$new_segments[] = $segment;
continue;
}
# delete whole segment
if (
($segment['begin'] >= $cond[1]) &&
($segment['end'] <= $cond[2])
)
{
print("delete whole segment\n");
continue;
}
# delete starts at boundary
if ($cond[1] <= $segment['begin'])
{
print("delete at boundary start\n");
$segment['begin'] = $cond[2];
$new_segments[] = $segment;
continue;
}
# delete ends at boundary
if ($cond[2] >= $segment['end'])
{
print("delete at boundary end\n");
$segment['end'] = $cond[1];
$new_segments[] = $segment;
continue;
}
# split into two segments
print("split into two\n");
$segment_pre = array('begin' => $segment['begin'], 'end' => $cond[1]);
$segment_post = array('begin' => $cond[2], 'end' => $segment['end']);
$new_segments[] = $segment_pre;
$new_segments[] = $segment_post;
}
print("--\n");
$segments = $new_segments;
}
print("----\n");
var_dump($segments);
print("----\n");
}
var_dump($segments);