Counting the sign changes in a list in C - c

I have to get the number of sign changes in a list of doubles. For example if there is a list like that: "1, -1, -1, 1" there are 2 sign changes, between the adjacent elements. I tried it like this but for some reason the program crashes if I try to compile it:
int number_of_sign_changes(DoubleList* list) {
int changes = 0;
for (DoubleNode *n = list->first; n != NULL; n = n->next) {
if ((n->value >= 0) && (n->next->value < 0)) {
changes += 1;
} else if ((n->value < 0) && (n->next->value >= 0)) {
changes += 1;
}
}
return changes;
}
The loop definitely works. I tried it in other functions but here it won't work. Does anyone have an idea? Btw you could actually put the 2 if statements into 1 and I tried that aswell but same problem.

This is in essence a fence post problem. The number of possible sign changes is one less than the number of elements in the list, so as you are checking on each item, you can tell you are doing something wrong. The problem in fact occurs when checking the last item on the list - it attempts to check for a sign change to the 'next' item, and there isn't one, as n->next is NULL.
This can be fixed by a simple change to the terminating condition in the for loop as follows:
int number_of_sign_changes(DoubleList* list) {
int changes = 0;
for (DoubleNode *n = list->first; n != NULL && n->next != NULL; n = n->next) {
if ((n->value >= 0) && (n->next->value < 0)) {
changes += 1;
} else if ((n->value < 0) && (n->next->value >= 0)) {
changes += 1;
}
}
return changes;
}

Related

How can I make this code smaller, without 3 loops? I should find 3 students with the smallest marks

I have to make my lab))
In general, I should find the index of three students with the smallest rating points.
How I can do it without three loops? Just by one.
In this function, I use structures and output arguments.
int addDelateThree(stud** pListHead, int* Imin, int* Jmin, int* Cmin) {
stud* pTemp = pListHead;
stud* SpTemp = pListHead;
stud* TpTemp = pListHead;
int check = 0;
double min1 = pTemp->madian;
double min2 = SpTemp->madian;
double min3 = pTemp->median;
int i = 0;
while (pTemp != NULL) {
if (min1 > pTemp->madian) {
min1 = pTemp->madian;
*Imin = i;
}
i++;
pTemp = pTemp->next;
}
i = 0;
while (SpTemp != NULL) {
if (min2 > SpTemp->madian && i != *Imin) {
min2 = SpTemp->madian;
*Jmin = i;
}
i++;
SpTemp = SpTemp->next;
}
i = 0;
while (TpTemp != NULL) {
if (min3 > TpTemp->madian && i != *Imin && i != *Jmin) {
min3 = TpTemp->madian;
*Cmin = i;
}
i++;
TpTemp = TpTemp->next;
}
}
Make a list of 3 stud *. Initialize all to point to a dummy record whose .madian = INFINTY;
Walk the linked list once.
Compare node's .madian to list[2]->madian. If <=, adjust list of 3 with new minimal .madian. This may involve several compares as code compares 1st the greatest min value, then next greatest min and finally the least value.
Report result.
O(n) solution.

Longest substring of correct parenthesis

I'm running into a bit of a problem. I have to compute the longest substring of correctly closed parenthesis and so far I've managed to do this:
while (work_stack.size != 0){
//I have a working stack in which I have stored the elements
//which in my case are brackets and while I have elements
//i pop the first element and see if it's a left or right
a1 = pop(&work_stack.data);
work_stack.size--;
if ('{' == ((Pair*)a1->info)->type ||
'(' == ((Pair*)a1->info)->type ||
'[' == ((Pair*)a1->info)->type) {
//if it's a left bracket, then I add it to the left stack
//which i'm going to use to compare with the right sided
//brackets i will encounter.
stanga++; //i'm incrementing the no of left brackets
if(ok == 0) //if there wasn't a match, then length is set to 0
length = 0;
if (ok == 1 && stanga > 1)
//if there was a match but then two brackets of left side
//are encountered, then length = 0
/*
Now I figured that here I am wrong. Given the input:
[][()()])())[][)]
The right value should be 8, but my code encounters
two left values and sets the length to 0. I need to
find a way to determine if the substring is worth keeping
*/
length = 0;
push(&left.data, a1);
left.size++;
}
if ('}' == ((Pair*)a1->info)->type ||
')' == ((Pair*)a1->info)->type ||
']' == ((Pair*)a1->info)->type){
//if it's a right bracket and there are elements in the left
//then i pop the first element fro the left stack and compare
//it to my current bracket
if(left.size != 0){
stanga = 0;
a2 = pop(&left.data);
left.size--;
//opposing is a function that returns 1 if
//i encounter something like ( ) or [ ] or { }
//if the brackets are opposed, i increment the length
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 1){
length += 2;
ok = 1;
}
//otherwise, it seems that I have run into a stopping
//point, so I'm emptying the left stack because those
//paranthesis are not of use anymore and I'm saving
//the maximum length acquired by now
if (oposing(((Pair*)a2->info)->type, ((Pair*)a1->info)->type) == 0){
ok = 0;
while(left.size > 0){
a2 = pop(&left.data);
left.size--;
}
if(length > max){
max = length;
length = 0;
}
}
//if i haven't encountered a stopping point, i just
//compare the length to my max and save it if it's bigger
if (length > max)
max = length;
}
//this line says that if the size of the left stack is 0 and
//i have encountered a right bracket, then I can't form a
//correct substring, so the length is 0
else length = 0;
}
}
To note that: ((Pair*)a1->info)->type is my character.
Thank you!
Later Edit:
- I'm adding the structures for stack and Pair
typedef struct{
int id;
char type;
}Pair;
typedef struct cel{
void *info;
struct cel *urm;
}Celula, *TLista, **ALista;
typedef struct{
TLista data;
int size;
}stack;
My stack has the data type as a linked list but that shouldn't matter that much as the operations are correct (push and pop).
Edit: Added some new improvements to the code, as well as a new expalanation in comments as to what I'm doing. I identified the bug but I'm failing to find a solution for it.
This problem can be solved using stack. Here is my C++ implementation, hope you will feel no difficulty to understand the syntax and translate it into C.
int longestValidParentheses(string s) {
stack <int> Stack;
int maxLen = 0;
int lastPos = -1;
for(int i = 0; i < s.length(); ++i) {
if(s[i] == '(') {
Stack.push(i);
}
else {
if(Stack.empty()) {
lastPos = i;
}
else {
Stack.pop();
if(Stack.empty()) {
maxLen = max(maxLen, i - lastPos);
} else {
maxLen = max(maxLen, i - Stack.top());
}
}
}
}
return maxLen;
}
Sorry for the code rather than explanation as I am outside right now. I will put clarification if you need explanation on any part. For now, you can check with some input and pen-and-paper.

why don't my pointers work?

I am trying to write the old painter game, where you paint around squares and when the perimeter is done the square changes colour, using ncurses. I have written a simple level editor that lets me draw the squares using an asterisk. I have a block structure and an array of them and can create the blocks by brute-force scanning the screen for asterisks and setting blocks to those locations. So I realised that each block is joined to 2 - 4 other blocks, so I could just have pointers to next up/dn/lt/rt blocks and follow the pointers. This would save time because I wouldn't have to check for boundary conditions or that the player stayed on the line, i could simply check if the ptr was null and if so not let the player move in that direction. So I can save the block array and load it into the painter game and it displays it all correctly. I have a ptr to the current block cur_blk which I have set to point to array element 5, and this works. If I gdb, I can print out the value of *cur_blk and it shows everthing is right, but the pointers don't work. I think the problem is in the level editor, but I am stuck.
Here is some code. This is the block struct:
struct block{
int id;
int row, col;
int alive;
struct block *next_up, *next_dn, *next_lt, *next_rt;
struct square *my_squares;
};
Here is the block array setup:
struct block *bp;
int cnt = 0;
for(bp = &the_blocks[0]; bp < &the_blocks[1024]; bp++){
bp->id = cnt;
bp->row = 0;
bp->col = 0;
bp->alive = FALSE;
bp->next_up = NULL;
bp->next_dn = NULL;
bp->next_lt = NULL;
bp->next_rt = NULL;
bp->my_squares = (struct square *)malloc(sizeof(struct square)*4);
cnt++;
}
here is the code to give the blocks the correct co-ords, and link them together - the linky code is in the for(d=0;d<blk_cnt;d++) loop. It rescans the array comparing co-ords, such that if the row is one less and the col is the same then that is set to the_blocks[c].next_up. I am pretty sure this is where the error is but I don't know what it is.
char cc, dn_ch, rt_ch; // cur/next chars
int row, col;
//create blocks
for(row=0;row<24;row++){
for(col=0;col<61;col++){
cc = mvinch(row,col);
if(cc == '*'){
the_blocks[blk_cnt].row = row;
the_blocks[blk_cnt].col = col;
the_blocks[blk_cnt].alive = TRUE;
blk_cnt++;
}
if(row<24) ;
dn_ch = mvinch(row+1, col);
if(col<60) ;
rt_ch = mvinch(row,col+1);
if(cc == '*' && dn_ch == '*' && rt_ch == '*')
make_square(row,col);
}
}
//make into squares and link blocks
int c,d,e, scnt;
for(c=0;c<blk_cnt;c++){
int row = the_blocks[c].row;
int col = the_blocks[c].col;
for(e=0;e<sq_cnt;e++){
// for each square, check top/base then left side and rigth side.
// use tlx, tly etc
scnt = 0;
int tlx = the_squares[e].tlx;
int tly = the_squares[e].tly;
int blx = the_squares[e].blx;
int bly = the_squares[e].bly;
int trx = the_squares[e].trx;
int try = the_squares[e].try;
int brx = the_squares[e].brx;
int bry = the_squares[e].bry;
if(row == tly && col >=tlx && col <= trx){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(row == bly && col >=blx && col <= brx){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(col == tlx && row >=tly && row <= bly){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
if(col == trx && row >=try && row <= bry){
the_blocks[c].my_squares[scnt] = the_squares[e];
scnt++;
}
}
for(d=0;d<blk_cnt;d++){
if((the_blocks[d].row == row-1) && (the_blocks[d].col == col)){
//the_blocks[c].next_up = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_up = &the_blocks[d];
}
if((the_blocks[d].row == row+1) && (the_blocks[d].col == col)){
//the_blocks[c].next_dn = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_dn = &the_blocks[d];
}
if(( the_blocks[d].col == col-1) && (the_blocks[d].row == row)){
//the_blocks[c].next_lt = (struct block )malloc(sizeof(struct block));
the_blocks[c].next_lt = &the_blocks[d];
}
if((the_blocks[d].col == col+1) && (the_blocks[d].row == row)){
//the_blocks[c].next_rt = (struct block *)malloc(sizeof(struct block));
the_blocks[c].next_rt = &the_blocks[d];
}
}
}
Here is the code from the painter game that sets the cur_blk pointer
cur_blk = &the_blocks[5];
move(cur_blk->row, cur_blk->col);
addch('#');
refresh();
and this is the move code, where I thought I could just follow the pointers:
switch(dir){
case UP : if(cur_blk->next_up != NULL){
cur_blk = cur_blk->next_up;
moved = TRUE;
break;
}
case DOWN : if(cur_blk->next_dn != NULL){
cur_blk = cur_blk->next_dn;
moved = TRUE;
break;
}
case LEFT : if(cur_blk->next_lt != NULL){
cur_blk = cur_blk->next_lt;
moved = TRUE;
break;
}
case RIGHT : if(cur_blk->next_rt != NULL){
cur_blk = cur_blk->next_rt;
moved = TRUE;
break;
}
}
I am so stuck it is unreal. Thanks in advance for any help. I can post more code if needed. The level editor works apart from the linky bit!

How to efficiently add 2 linked lists of different sizes

I am having a problem with my function for adding two linked lists of different sizes together. They are already reversed. Everything this else seems to work, but i know the problem is in the while loop
while(num1 != NULL && num2 != NULL)
when i use the && operator it only stops up to the end of the first finished list (I understand that). However when i try to use the or (||) operator my entire program just crashes.
Can someone help me figure out what's wrong please.
this is the function. and my main.
//adds the two linked lists for their sum
node *addLargeNumber(node *num1, node *num2) {
node *result = NULL;
node *prev = NULL;
node *temp;
int sum, carry = 0;
while(num1 != NULL || num2 != NULL) { //while both lists exists or either is not empty
/*calculate values for the result. the next digit with be the sum of the carry
from previous number(if any) digit from 1st list and digit from second list*/
sum = carry + (num1->data) + (num2->data);
if (sum > 9) carry = 1;
else carry = 0;
sum = sum % 10; //just want ones column from sum to put in result
temp = createNode(sum);
if(result == NULL)
result = temp; //if it is first node, make it the head
else
prev->next = temp; //if not first node, connect it to rest
prev = temp; //reset prev or next insertion
// move to next nodes in both lists
if(num1 != NULL) num1 = num1->next;
if(num2 != NULL) num2 = num2->next;
}
if(carry > 0) temp->next = createNode(carry);
return result;
}
main function
int main(void) {
node *storeNumber();
void reverseList();
void printList();
node *addLargeNumber();
node *add();
char number1[numsize], number2[numsize], bigSum[numsize];
node *top;
char command;
int number;
FILE *in = fopen("input.txt", "r");
FILE *out = fopen("output.txt", "w");
while(fscanf(in, "%c", &command) != EOF) { //while there are no more commands to be read
top = NULL;
//adding two large numbers with linked list
if(command == 'A') {
fscanf(in, "%s", &number1);
fscanf(in, "%s", &number2);
node *top1 = storeNumber(number1);
node *top2 = storeNumber(number2);
node *sum = addLargeNumber(top1, top2);
printList(top1);
printf(" + ");
printList(top2);
printf(" = ");
printList(sum);
printf("\n\n");
fscanf(in, "%c", &command);
}
}
system("Pause");
return 0;
}
if you use || "or" operator, one of num may be null, and the program crashes as you try to access num1->data or num2->data
Try something like :
sum = carry;
if(num1 != NULL) sum += num1->data;
if(num2 != NULL) sum += num2->data;
and
if(num1!= NULL) num1 = num1->next;
if(num2!= NULL) num2 = num2->next;
There is no problem with the program. Ensure that "there may be infinite nodes" so that it may not reach end. If all are correct, there may be some problem due to short-circuit property of operators. There may be some problem with increment of nodes also, check that too. In that case, try NESTED WHILE statement.
while(num1!=NULL)
{
while(num2!=NULL)
{
/* ...............
..................
...............*/
}
}
EDIT:
after trying to better understand what you are trying to do, I think you need to add a carry > 0 with an OR clause in your while loop. I also think that you need to add each data element completely separately into the digit's sum checking for null prior to adding. by doing these two things, you should continue adding nodes past your initial data if indeed the carry needs to be pushed past (or to the left) of your sum.
I think the below should work and you can take out the last two lines of your routine checking for the carry after the loop. As an answer to WHY it was failing, it is the NON-CHECKING for NULL when performing your addition. If you have one number longer than another, you aren't performing NULL checking prior to your addition, and this is causing the crash.
// while both lists exists or either is not empty
while(num1 != NULL || num2 != NULL || carry > 0){
/*calculate values for the result. the next digit with be the sum of the carry
from previous number(if any) digit from 1st list and digit from second list*/
// Add in each element separately do detect for NULL on the fly
sum = carry;
if(num1->data != NULL) sum += num1-data;
if(num2->data != NULL) sum += num2-data;
// Test to see if we should carry
if (sum > 9) carry = 1;
else carry = 0;
// Lets keep the remainder as the value for this particular digit of the sum
sum = sum % 10; //just want ones column from sum to put in result
temp = createNode(sum);
if(result == NULL)
result = temp; //if it is first node, make it the head
else
prev->next = temp; //if not first node, connect it to rest
prev = temp; //reset prev or next insertion
// move to next nodes in both lists
if(num1 != NULL) num1 = num1->next;
if(num2 != NULL) num2 = num2->next;
}
Try this:
// Changed this from || to && so that either of them will force a
// stop in the looping
while(num1 != NULL && num2 != NULL) {
......
// move to next nodes in both lists - Changed these two lines to force the null
// to pop out within the while loop checking
num1 = num1->next;
num2 = num2->next;
}
You need to change the || or to an and && because the while loop is going to continue while EITHER of them are null. Further though you need to force their movement to the next value without checking for NULL at the end. Without MOVING into the null, the while loop will never get to a null point, and thus you are creating an endless loop.
It should also be noted that you don't need the if statements protecting the bottom two most lines within your main adder loop because this coverage is taken care of by your loop checking if done right.

Simplify/Neatify this two-way loop?

I've got my wires crossed somewhere (or I had not enough sleep). I need a two-way loop, and my current code is just plain ugly.
Problem: I am running along a linear datastructre using an index. I have an starting index, lets say 120. I want to run alternating into both directions.
Example:
120,121,119,122,118,123,117,...
I have a stopping criterion which needs to be met for each direction separately. If it is met for one direction, I only want to run into the other direction, if both are met I need to exit the loop. In addition I need to stop if the next index is invalid (end of data structure, say smaller than 0 or bigger than 200).
Example: Stopping execution at 116 backwards and 130 forward:
120,121,119,122,118,123,117,124,116,(break),125,126,127,128,129,130.
Running into one direction first, then the other one is unfortunately not an option.
My current code is plain ugly. It is a lot of lines without containing any "productive" code. Only iteration logic:
int start_idx = 120;
int forward_idx = start_idx;
int backward_idx = start_idx;
bool next_step_forward = true; //should next step be forward or backward?
int cur_idx;
while(backward_idx >= 0 || forward_idx >= 0)
{
if(next_step_forward //if we should step forward
&& forward_idx >= 0) //and we still can step forward
{
cur_idx = ++forward_idx;
if(forward_idx >= 200) //200 is fictive "max index"
{
next_step_forward = false;
forward_idx = -1; //end of data reached, no more stepping forward
continue;
}
if(backward_idx >= 0)
{
next_step_forward = false;
}
}
else if(!next_step_forward
&& backward_idx >= 0)
{
cur_idx = --backward_idx;
if(backward_idx < 0) //beginning of data reached, no more stepping backward
{
next_step_forward = true;
continue;
}
if(forward_idx >= 0)
{
next_step_forward = true;
}
}
else
{
next_step_forward = !next_step_forward; //ever hit?, just security case
continue;
}
//loop body
//do something with cur_idx here
if(stoppingCriterionMet())
{
if(cur_idx > start_idx)
{ //this was a forward step, stop forward stepping
forward_idx = -1;
}
else
{ //this was backward step, stop backward stepping
backward_idx = -1;
}
}
}
Am I missing anything? Any hints appreciated. Thanks.
Edit 1: There are lots of very nice answers, which put "do something with cur_idx" into a separate function. While this is a perfect idea for the way my question was asked, I prefer putting the iterating code somewhere else and leave the productive code there. I have a long algorithm and want to split it up after it is finished to minimize rearangement work.
How about this?
void do_loop(SomeType *arr, int start, int low, int high, int arr_max)
{
int downwardIndex, upwardIndex;
downwardIndex = upwardIndex = start;
while (downwardIndex > 0 && upwardIndex < arr_max) {
if (downwardIndex < low && upwardIndex > high) {
break;
}
if (downwardIndex > low) {
processElement(arr[downwardIndex]);
downwardIndex--;
}
if (upwardIndex < high) {
processElement(arr[upwardIndex]);
upwardIndex++;
}
}
}
It so happened that I coded almost this problem today. And I used a C# iterator function to do it. But I think you want a more generic solution.
If you use a language where you can build your own iterators (C++,Java,C#), it's easy. You just make a custom iterator that initially spits out numbers starting from the center. Then you give the iterator an extra function to tell it to stop running in the current direction.
If you're doing something like this in C (it looks C to me), you can mimic this with a struct containing the iterator state, and functions that you call to step it forward or stop it.
First pass at hacking this (assuming C - adaptations needed for other languages, but the concepts are basically language neutral):
void pass1(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
while (lo_x >= lo_limit)
{
Process(lo_x);
if (StopCriterion(lo_x))
lo_x = lo_limit - 1;
else
lo_x--;
}
while (hi_x <= hi_limit)
{
Process(hi_x);
if (StopCriterion(hi_x))
hi_x = hi_limit + 1;
else
hi_x++;
}
}
It is not clear what should happen if the starting position matches the stop criterion. Should the search stop altogether, or should it continue upwards, or downwards, or both ways. I chose 'stop altogether', but a case could be made for any of the options listed. In the case of 'both', you would not even bother to run the stop criterion check.
I also chose to do the lower before the upper direction; it is clearly trivially reversed. The order of the final two loops doesn't matter because if both directions terminate in the same iteration, neither trailing loop is executed; if only one direction is terminated, the corresponding loop won't execute at all - only the other will.
Since there is still repeated code in there:
void pass2(int start_x, int lo_limit, int hi_limit)
{
assert(start_x >= lo_limit && start_x <= hi_limit);
int lo_x = start_x - 1;
int hi_x = start_x + 1;
Process(start_x);
if (StopCriterion(start_x))
return; // Is that correct?
while (lo_x >= lo_limit && hi_x <= hi_limit)
{
Process_lo(&lo_x, lo_limit);
Process_hi(&hi_x, hi_limit);
}
while (lo_x >= lo_limit)
Process_lo(&lo_x, lo_limit);
while (hi_x <= hi_limit)
Process_hi(&hi_x, hi_limit);
}
void Process_lo(int *lo_x, int lo_limit)
{
Process(*lo_x);
if (StopCriterion(*lo_x))
*lo_x = lo_limit - 1;
else
*lo_x--;
}
void Process_hi(int *hi_x, int hi_limit)
{
Process(*hi_x);
if (StopCriterion(*hi_x))
*hi_x = hi_limit + 1;
else
*hi_x++;
}
Visibility controls (static functions) etc left out as details of the implementation language.
This is how I'd approach it in C#:
const int UPPER_BOUND = 200;
const int LOWER_BOUND = 0;
const int START = 120;
bool foundlower = false, foundupper = false;
int upper, lower;
upper = lower = START;
while (!foundlower || !foundupper) {
if (!foundlower) {
if (--lower <= LOWER_BOUND) foundlower = true;
if (stoppingCriterionMet(lower)) foundlower = true;
}
if (!foundupper) {
if (++upper >= UPPER_BOUND) foundupper = true;
if (stoppingCriterionMet(upper)) foundupper = true;
}
}

Resources