Recursion: why the top of the stack is repeating twice - objective-c

I don't understand why the top of the stack is repeating two times.
Here's my code:
void count(n){
if (n>0) {
printf("Count is %i \n",n);
n=n-1;
count(n);
} else {
printf("Count is %i. Finished. \n",n);
}
printf("The count here is %i \n",n); //recursion here
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
count(5);
}
return 0;
}
The output is:
Count is 5
Count is 4
Count is 3
Count is 2
Count is 1
Count is 0. Finished.
The count here is 0
The count here is 0
The count here is 1
The count here is 2
The count here is 3
The count here is 4
Program ended with exit code: 0
So, why are there two lines of output that say "The count here is 0" ?
Isn't the first line, the 'first' time through the recursion?

Think about your code logically and I think you will see why that line is being printed twice. Consider the case when we reach this statement: n=n-1; and n is currently (before this is executed) equal to 1. Now n is 0 and you call count(n), calling your function recursively as I think you might have been saying. Now your count(0) function call will go here:
else {
printf("Count is %i. Finished. \n",n);
}
because n is not greater than 0. This is where we have your output: Count is 0. Finished.
Then, your functions next statement is: printf("The count here is %i \n",n); //recursion here
This causes the first output of: The count here is 0.
Now consider what happens. Your count(0) call is done and returns to the function it was called from. In this case, consider where you called it from. You called it from the function which was called as count(1), but now in that function, be causes of your n=n-1;, n is 0.
Following your code, after the if statement, your program will immediately proceed to: printf("The count here is %i \n",n); //recursion here
Because n is 0, it will output: The count here is 0 again.

Are you sure you want:
n=n-1;
count(n);
rather than this?
count(n-1);
The former will modify the value of n printed in your later printf, whereas the latter only modifies it in the recursive call.

Related

Conditional Running Tally / Cumulative Sum: Looking for Formula or Script

I work in a warehouse, and I'm using Google Sheets to keep track of inventory. Adding and subtracting is easy, but I've been tasked with creating a "reserve" system:
A number of pieces of stock are reserved for upcoming jobs. When that stock is ordered and received, the reserve quantity is "satisfied" and decreases by the number of pieces received. The problem with setting it up just like the ADD and SUBTRACT function is that not all stock received is "reserved", and my RESERVE totals end up being "-57", "-72", "-112", etc.
I have a large dataset of form responses logged in four columns: Timestamp, Item ID#, Action (ADD, SUBTRACT, or RESERVE), and QTY. What I'm looking for is a way to create a running tally in column E for each unique Item ID#, using the values in column D "QTY". I need for any value <0 to return "0".
Example Sheet
I've been able to create a running tally formula that satisfies my conditions for one Item ID# at a time. To avoid creating a separate column for each Item ID#, though, I need to figure out how to apply it separately to each unique Item ID#, and array it down Column E so each new form response is calculated automatically.
=if(C2="RESERVE",E1+D2,if(and(C2="ADD",(E1+D2)<0),0,E1+D2))
The closest thing to a solution I've been able to find is a script created by user79865 for this question titled: "Running Total In Google Sheets with Array". Unfortunately, trying to plug this into Google Sheets Script Editor gives me an error popup:
TypeError: Cannot read property "length" from undefined. (line 2, file "runningtotal")
I have no programming background and never dreamed I'd be looking at code just to make a running tally.
If anybody can offer any insight into this, fixing or replacing the script or offering an ARRAYFORMULA solution, I'd really appreciate it!
function runningTotal(names, dates, amounts) {
var sum, totals = [], n = names.length;
if (dates.length != n || amounts.length != n) {
return 'Error: need three columns of equal length';
}
for (var i = 0; i < n; i++) {
if (names[i][0]) {
sum = 0;
for (var j = 0; j < n; j++) {
if (names[j][0] == names[i][0] && dates[j][0] <= dates[i][0]) {
sum = sum + amounts[j][0];
}
}
}
else {
sum = '';
}
totals.push([sum]);
}
return totals;
}

Why are values over 100 become negative?

I'm working on a deserializer in C++. I get a stream of data and I am transferring this to a char array. At the moment, everything is working perfectly except when the value is over 100, the value I get returned becomes a negative value. For example 241 becomes -15 but values below what it seems to be 100 stay the same.
Here is the code I am running
char streamBuffer[1024]; //where the stream data is held
/**code in between that transfer data stream to streamBuffer[]**/
char printBuffer[10];
for(int i = 0; i < 10 ; i++){
sprintf(printBuffer, "streamData = %ld",streamBuffer[i]);
PrintData(printBuffer); //prints the value
}
For example, my stream data could look like 1,3,5,10,241,etc.
When I get to the printData function, it gives me the correct value for any value below 100 it seems.
I've used
sprintf(printBuffer, "streamData = %lld",streamBuffer[i]);
or
sprintf(printBuffer, "streamData = %d",streamBuffer[i]);
but I am still not getting the right values.
So my output will look like this.
StreamData: 1
StreamData: 3
StreamData: 5
StreamData: 10
StreamData: -15
Solution was to change char streamBuffer[1024] to unsigned char streamBuffer[1024] and change %ld to %u in the sprintf statement. Now values over 100 remain the same.

Reduce Complexity of This Formula?

I have a question about optimizing a formula I've been using in Google Sheets:
=ARRAYFORMULA(
IF(
IFERROR(
MATCH($B2 & A2, ($B$1:B1) & ($A$1:A2), 0),
0
) = 0,
1,
0))
The formula works by counting all the unique values in column A (ID) given that it appears in the date range of column B (Date), to give an output in column C (Count).
Notice how the count values are only 0 and 1, and will only show a 1 if it is the ID's first appearance in the date range.
Example data below.
ID Date Count
138 Oct-13 1
138 Oct-13 0
29 Oct-13 1
29 Nov-13 1
138 Nov-13 1
138 Nov-13 0
The issue is once I get over 10000 lines to parse, the formula grinds to a slow pace, and takes upwards of an hour to finish computing. I'm wondering if anyone has a suggestion on how to optimize this formula so I don't need to have it running for so long.
Thanks,
I've been playing around with some formulas, and I think this one works better, but is still becoming quite slow after 10000 lines.
=IF(COUNTIF((FILTER($A$1:$A2, $B$1:$B2 = $B2)),$A2) = 1, 1, 0)
Edit
Here is an additional formula posted on the Google Product Forum which only has to be put in one cell, and autofills down. This is the best answer I've found so far.
=ArrayFormula(IF(LEN(A2:A),--(MATCH(A2:A&B2:B,A2:A&B2:B,0)=ROW(A2:A)-1),))
I wasn't able to find a formula-only solution that I could say outperforms what you have. I did, however, come up with a custom function that runs in linear time, so it ought to perform well. I'd be curious to know how it compares to your final solution.
/**
* Returns 1 for rows in the given range that have not yet occurred in the range,
* or 0 otherwise.
*
* #param {A2:B8} range A range of cells
* #param {2} key_col Relative position of a column to key by, e.g. the sort
* column (optional; may improve performance)
* #return 1 if the values in the row have not yet occurred in the range;
* otherwise 0.
* #customfunction
*/
function COUNT_FIRST_OF_GROUP(range, key_col) {
if (!Array.isArray(range)) {
return 1;
}
const grouped = {};
key_col = typeof key_col === 'undefined' ? 0 : key_col - 1; // convert from 1-based to 0-based
return range.map(function(rowCells) {
const group = groupFor_(grouped, rowCells, key_col);
const rowStr = JSON.stringify(rowCells); // a bit of a hack to identify unique rows, but probably a good compromise
if (rowStr in group) {
return 0;
} else {
group[rowStr] = true;
return 1;
}
});
}
/** #private */
function groupFor_(grouped, row, key_col) {
if (key_col < 0) {
return grouped; // no key column; use one big group for all rows
}
const key = JSON.stringify(row[key_col]);
if (!(key in grouped)) {
grouped[key] = {};
}
return grouped[key];
}
To use it, in Google Sheets go to Tools > Script editor..., paste it into the editor, and click Save. Then, in your spreadsheet, use the function like so:
=COUNT_FIRST_OF_GROUP(A2:B99, 2)
It will autofill for all rows in the range. You can see it in action here.
If certain assumptions are fulfilled, Like, 1. Same ID numbers always occur together(If not, maybe you could SORT them by ID first and then date later), then,
=ARRAYFORMULA(1*(A2:A10000&B2:B10000<>A1:A9999&B1:B9999))
If dates are recognised, I think you could use + instead of & . Again, Various assumptions were made here and there.

labview while loop execution condition

Is there a way to give while loop a condition which makes it give an an output every ten times' executions, however it continues running after this output?
I hope I made myself clear...
Thanks!
Amy
Modulo is useful for this.
As an example; In swift to do modulo you use the % symbol. Essentially modulo outputs the remainder of the given terms.
So;
Value 1 MODULO Value 2 outputs Remainder.
Furthermore;
6 % 2 = 0
6 % 5 = 1
6 % 4.5 = 1.5
Essentially you want every nth element to output a value, with n being the rate. You need to track how many loops of the while you have gone through already.
The code below will run through the while 1000 times, and print out every 10 times ( for a total of 100 prints of output. )
var execution : Int = 0
while ( execution != 1000 ) {
if ( execution % 10 == 0 ) {
print("output")
}
execution = execution + 1
}
Here is the same answer as given by adam but then in Labview.

Invalid Input Exception Handling - SmallTalk

Let a smalltalk msg named "sum" return the sum of elements in an array.
Eg: #(1 2 3 4 5) sum ----> 15
When the input is #(1 2 'a' 3 5) sum. The execution terminates and shows a big exception box.
Instead of that how can we gracefully exit the execution by just showing a message. I don't want the big exception window to be shown.
sum
|sum|
sum := 0
self do: [:a | sum := sum + a]
^sum
I tried to handle the exception the below way. However, I notice that the execution doesn't terminate in case of invalid input.
sum
|sum|
sum := 0
self do: [:a |
(a isInteger) ifFalse:[
^[Error signal] on: Exception
do: [:ex | Transcript show: 'Entered values are non-numeric. Hence comparison is not possible.']
]
sum := sum + a
]
^sum
If the below code is placed in the workspace, I expected the execution to be terminated at line 2. However, line 3 is also getting executed.
|temp|
temp := #(1 2 3 'as' 4 5) sum.
temp := temp*5.
Changing the sum method to ignore the wrong types in the input Array does not make sense. Furthermore by replacing it with a UI message you completely loose control over what kind of input is acceptable. Rather deal with these exception at the place you use sum:
[ ^ self readInput sum ]
on: Error do: [ :error| Transcript show: 'Invalid input provided for sum' ].