ok try this:
makes one pass, but backtracks to obliterate sequences. loops through and uses three variables to hold state, chooses action dependant on state
min execution, no replacements : n
max execution, one big replacement, min_sequence=array_size: 2n
avg execution : 1.5 n
so this function is O(n)
this is functionally equiv to my last, but this just looks cleaner
and i can't see a way to make it smaller, without using a different algorithm altogether;
30 lines of code without comments and spacing:
if you really just wanted it smaller i could get rid of some end brackets, but it won't make it run faster
and if you know a better way, please post it., i'd love to see how someone else tackles this
- Code: Select all
$ddd = array(2,3,a,a,a,5,78,a,a,99,0,a,a,a,a,45);
$result = obliterateDuplicates( $ddd );
echo "<pre>";
print_r($ddd);
print_r($result);
echo "</pre>";
function obliterateDuplicates( $from, $obliterate_with='', $min_sequence=3 )
{
$array_size = count($from);
if ( $array_size >= $min_sequence ) {
$current = 0;
$match_to = NULL;
$match_count = 0;
/// we need only 1 pass through the array
for ( $current = 0; $current < $array_size; $current++ ) {
/// if we are looking for the next alpha character to match
if ( $match_to === NULL ) {
/// if we we have found something to try and match
if ( preg_match("/[a-zA-Z]/",$from[$current]) ) {
/// set out program to attempt to match next items to this item
$match_to = $current;
}
/// if we are trying to match this item to a previously found one
} else {
/// if this item matches, we are in a sequence of like items
if ( $from[$current] == $from[$match_to] ) {
/// update our match count
$match_count++;
/// if the match_count is < $min_sequence do nothing, we need more matches, move on
/// if the match_count is $min_sequence
if ( $match_count == 2 ) {
/// we skipped over the first few matches, so go back and obliterate them, as well as the current one
for ( $i = $current; $i >= $match_to; $i-- ) {
$from[$i]= $obliterate_with;
}
/// if the match_count is > $min_sequence
} else if ( $match_count > $min_sequence ) {
/// obliterate this match
$from[$current]= $obliterate_with;
}
/// if this item is not in our sequence
} else {
/// reset our state variables to reflect this
$match_to = NULL;
$match_count = 0;
}
}
}
}
return $from;
}