It's much simpler, if there's an increasing run of length k, it contains k(k+1)/2 subruns. So you can just do one pass over the array, keeping track of the length of the current run.
function f(arr) {
var j=0, ret=0;
for (var i=1; i<=arr.length; i++) {
if (i==arr.length || arr[i]<=arr[i-1]) {
ret += (i-j)*(i-j+1)/2;
j = i;
}
}
return ret;
}
I don't get it. Why not just test for net sum of the directions for a finite number of iterations? If the net sum is zero, there is a loop and if not, the program halts. Am I missing something?
There is a nugget buried at the bottom of this: you will get different output for different kinds of for ... range or for i ... loops. You'd think these are equivalent:
for i = range arr {
sum += arr[i]
}
for _, c = range arr {
sum += c
}
... but the latter is 4 bytes shorter in x86. The compiler takes things literally.
OK, here's a C version. Had to add a parameter, of course:
void add1(int arr[], int length, int val, int n)
{
int direction = n >= 0;
int counter = n == 0 ? length : abs(n);
int index;
for(int i = 0; (i < length) && (counter != 0) ; i++)
{
index = direction ? i : length - i;
if(arr[index] == val)
{
arr[index]++;
counter--;
}
}
}
detectSum: aBlock
"Evaluate aBlock with each of the receiver's elements as the argument.
Return the sum of the answers."
| sum |
sum := 0.
self do: [:each |
sum := (aBlock value: each) + sum].
^ sum
Anyway, my point still stands. Better to accept a block than to use a sum method that assumes the Array consists of numbers
Here's my cheating version that uses a third-party library:
add1_cheating = (arr, val, n) ->
n = arr.length if n is 0
start = if n < 0 then arr.length else 0
end = if n < 0 then 0 else arr.length
step = n/(Math.abs n)
n = Math.abs n
count = 0
for i in _.range start, end, step
break if count > n
arr[i]++ if arr[i] is val
count++
return arr
You're welcome. In the second edition, which is what I happen to have, it's column 9 (because the old column 4 got split into two) and the code is in a pseudocode that's much more like C with the semicolons deleted than like any version of BASIC.
I wasn't quite right to say that the inner loop is very tight; rather, the code assumes a particular size of array and unrolls the loop completely. But, indeed, the size doesn't need to be a power of 2.
Here's the (pseudo)code, in case anyone cares. It's for an array of size 1000. I've changed a variable name from "l" to "m" because of the usual l1I| thing. I've removed a couple of helpful comments because anyone who cares enough to bother reading them will probably have more fun figuring everything out on their own. I've also elided some obvious repetitive code and formatted it slightly differently from Bentley. Any errors in the code were probably introduced by me.
m = -1
if (x[ 511] < t) m = 1000-512
if (x[m+256] < t) m += 256
if (x[m+128] < t) m += 128
/* ... */
if (x[m+ 2] < t) m += 2
if (x[m+ 1] < t) m += 1
p = m+1
if (p>1000 || x[p]!=t) p = -1 /* i.e., not found */
Bentley says this is "not for the faint of heart". I agree, but I do think it's lovely. Though personally I'd be inclined to use a value of m offset by 1 from what Bentley does (initialize to 0, look up m+255, m+127, etc.) and save a line of code and a couple of cycles.
sum = 0
for i in range(0, 10000000):
sum += 0.1
print(round(sum*1000, 2))
what should this code print? what does it print?
I mean, sure, this is a contrived example. But can you guarantee that your code doesn't do anything similarly bad? Maybe the chance is tiny, but still: wouldn't you like to know for sure?
You don't need functions (but that's kind of an opinion, so whatever).
More importantly, to check if a rolling sum is increasing you don't need to compute that sum. I wonder if Copilot can ever figure that out.
reply