Reputation: 107
I have an array of values that represent points on a line chart:
$temperatures = [23, 24, null, '', 25, '', '', null];
I'm using PHP4, but I think it can be answered in any language.
Array contains only numbers, nulls and empty strings.
Numbers represent temperatures, nulls mean that the instruments weren't working and empty strings represent neither (instruments are working, just not measuring anything).
Points must (in most cases) be connected, since it's a line chart.
I have a variable $gap
that corresponds to each point and tells whether this point is connected to the next point. If it is set to true
, than the points are not connected (false
otherwise). For example, $gap for temperatures[0]
must be set to false
, since the line is drawn between temperatures[0]
and temperatures[1](they are both valid temperatures). $gap for
temperatures[1]and
temperatures[2]` must be true, since there is null following. And so on.
When there is null the $gap is absolutely true
. For numbers and empty strings, it depends on: if a null follows, gap is true; if a number follows, gap is false. If empty string follows, we must check if afterwards comes null or number and apply the previous sentence accordingly. If there are just empty strings following, gap is true. Here is my code that is working too slow, but produce correct results:
$limit = count($temperatures);
for ($i = 0; $i <= limit; $i++) {
$next_is_number = false;
if (is_null($temperatures[i]) {
$gap = true;
} else {
for ($y = $i + 1; $i <= limit; $i++) {
if (is_null($temperatures[$y]) {
break;
} elsif (is_numeric($temperatures[$y]) {
$next_is_number = true;
break;
}
}
if ($next_is_number) {
$gap = false;
} else {
$gap = true;
}
}
}
How can I speed it up?
Upvotes: 0
Views: 253
Reputation: 11
Your code checks whether there is a a gap somewhere in your line chart or not.
So once a gap is found, there no reason to continue in the outer for-loop. Think of a chart of 1000 values, if there is a gap between the first two values it makes no sense to continue checking the other 998 values.
Thus, the first thing I would recommend is to set $gap = false at the beginning and to leave the loop once $gap is true. You could do that either with
1.) break (not so elegant),
2.) extract your code to a method and add a return-statement or
3.) adding a condition in the for-loop. I am not familiar with php but in most languages it is possible to do it like this:
$gap = false;
$limit = count($temperatures);
for ($i = 0; $i <= limit && !$gap; $i++) {
[...]
So once $gap is true, the outer for-loop is left.
Upvotes: 1
Reputation: 6426
Iterate through backwards, remembering the last valid value and putting that in when you see an empty string. Then it's O(n) worst case, not O(n^2).
Alternatively, you can work from $y - 1
to $x
(or vice versa) after the inner loop, setting the values of your gaps array / outputting values, then skip past all the ones you've just done ($x = $y
). This is also O(n).
Then, once you've got the algorithm as fast as you can, you can ditch PHP and write it in something like Rust or C. (I don't recall any true arrays in the language, so they're always going to be slow.)
Upvotes: 0