recursion sum of subsets keeping getting error message - c

I am working on this problem on this online judge site(http://zerojudge.tw/ShowProblem?problemid=a981#). Sorry for that it's only in Mandarin :(.Basically it's a sum-of-subsets-problem.
Keep getting same error message on my submit:
RE (SIGSEGV)
Segmentation fault
My C code below:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int w[35]= {0};
bool is_included[35]= {false};
bool is_promising(int);
void sum_of_subsets(int,int,int);
int n = 0,W = 0,weight = 0,total = 0,i = 0,j = 0,k = 0,flag = 0,temp = 0;
int main(int argc,char* argv[]) {
while(scanf("%d %d",&n,&W)==2) {
memset(w,0,sizeof(w));
memset(is_included,false,sizeof(is_included));
total = 0;
i = 1;
temp = n;
while(temp--) {
scanf("%d",&w[i++]);
}
//ascending bubble sort
for(j = n; j >= 1; --j) {
flag=0;
for(k = 1; k < j; ++k) {
if(w[k]>w[k+1]) {
temp = w[k];
w[k] = w[k+1];
w[k+1] = temp;
flag=1;
}
}
if(!flag) {
break;
}
}
for(i=1; i<=n; ++i) {
total+=w[i];
}
sum_of_subsets(0,0,total);
}
return 0;
}
bool is_promising(int index) {
return (weight+total>=W)&&(weight==W||weight+w[index+1]<=W);
}
void sum_of_subsets(int index,int weight,int total) {
int j=1;
if(is_promising(index)) {
if(weight==W) {
for(j=1; j<=index; ++j) {
if(is_included[j]) {
printf("w[%d] = %d\n",j,w[j]);
}
}
} else {
//include w[index+1]
is_included[index+1]=true;
sum_of_subsets(index+1,weight+w[index+1],total-w[index+1]);
//exclude w[index+1]
is_included[index+1]=false;
sum_of_subsets(index+1,weight,total-w[index+1]);
}
}
}
Thanks for any advice.

Related

Is there a way to combine two different strings alphabetically using stack in C?

Here is the program:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *stack;
int stackindex = 0;
int push(char in){
if (stack==NULL) {
stack = (char *) malloc (sizeof(char));
}
else {
stack = (char *) realloc(stack, sizeof(char)* ++stackindex);
}
stack[stackindex] = in;
return 1;
}
char pop(){
return stack[stackindex--];
}
void show() {
for (int i=stackindex; i>=0;i--) {
printf("%c", pop());
}
}
int main(int argc, char**argv) {
for (int i = 1; i < argc; i++) {
int k = strlen(argv[i]);
int j;
for (int j = 0; j < k ; j++) {
char in = argv [i] [j];
push( in );
}
for (j = i; j < k; j++){
char temp;
if (stack[i] > stack[j]) {
temp = stack[j];
stack[j] = stack[i];
stack[i] = temp;
}
if (i, argc-1) push(' ');
}
show();
return 0;
}
}
I've been trying to make an output from the string "im loving" alphabetically in descending order (ASCII based) using command line arguments like this: vonmliig, but the output was "m i" instead.
Looks like you are trying to sort as you build the stack. I would build the stack first, then sort.
int main(int argc, char**argv)
{
if (argc >= 3) {
// Build stack
for (int i = 1; i < argc; i++) {
int k = strlen(argv[i]);
for (int j = 0; j < k ; j++) {
push(argv[i][j]);
}
}
// Sort
for (int i = 0; i < stackindex; i++) {
for (int j = i; j < stackindex; j++){
if (stack[i] > stack[j]) {
char temp = stack[j];
stack[j] = stack[i];
stack[i] = temp;
}
}
}
show();
}
return 0;
}
Also, there is an error in the handling of stackindex in push().
int push(char in)
{
char *temp = realloc(stack, stackindex + 1);
if (!temp) {
// Handle error
return -1;
}
stack = temp;
stack[stackindex++] = in;
return 1;
}
char pop()
{
if (stackindex) return stack[--stackindex];
else return 0;
}
void show()
{
do {
printf("%c", pop());
} while (stackindex);
}

Segfault in Merge - Sort in C

I am trying to sort an array of structures of size 5500 using merge sort.
However, I am getting a segmentation fault pretty quickly because I am not allowed to use VLA. so I have to create 2 extra arrays of size 5500 each time I call merge-sort recursively.
I would appreciate a fix for my problem. I will provide my code here:
void merge(Student rightArr[], Student leftArr[], Student mergedArr[], int sizeOfRight, int sizeOfLeft) {
int rightArrIndex = 0;
int leftArrIndex = 0;
int mergedArrIndex = 0;
while (leftArrIndex < sizeOfLeft && rightArrIndex < sizeOfRight) {
char *ptrLeft, *ptrRight;
long gradeLeft = strtol(leftArr[leftArrIndex].grade, &ptrLeft, BASE_COUNT);
long gradeRight = strtol(rightArr[rightArrIndex].grade, &ptrRight, BASE_COUNT);
if (gradeLeft > gradeRight) {
mergedArr[mergedArrIndex] = rightArr[rightArrIndex];
rightArrIndex++;
} else {
mergedArr[mergedArrIndex] = leftArr[leftArrIndex];
leftArrIndex++;
}
mergedArrIndex++;
}
if (leftArrIndex == sizeOfLeft) {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = rightArr[rightArrIndex];
rightArr++;
}
} else {
for (int i = mergedArrIndex; i < (sizeOfLeft + sizeOfRight); i++) {
mergedArr[i] = leftArr[leftArrIndex];
leftArr++;
}
}
}
void mergeSort(Student studentsArray[], int amountOfStudents) {
if (amountOfStudents <= 1) {
return;
}
int leftSize = (amountOfStudents / 2);
int rightSize = (amountOfStudents - leftSize);
Student leftArr[5500], rightArr[5500];
for (int i = 0; i < leftSize; i++) {
leftArr[i] = studentsArray[i];
}
for (int i = 0; i < rightSize; i++) {
rightArr[i] = studentsArray[i + leftSize];
}
mergeSort(leftArr, leftSize);
mergeSort(rightArr, rightSize);
merge(rightArr, leftArr, studentsArray, rightSize, leftSize);
}
Ok, I think this should do what you want. It assumes that Student and BASE_COUNT have been defined:
#include <stdlib.h>
#include <stdio.h>
void merge(Student studentsArr[],
int leftSize, int rightSize,
Student scratchArr[])
{
Student *leftArr = studentsArr;
Student *rightArr = studentsArr + leftSize;
int leftIx = 0, rightIx = 0, mergeIx = 0, ix;
while (leftIx < leftSize && rightIx < rightSize) {
long gradeLeft = strtol(leftArr[leftIx].grade, NULL, BASE_COUNT);
long gradeRight = strtol(rightArr[rightIx].grade, NULL, BASE_COUNT);
if (gradeLeft <= gradeRight) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
else {
scratchArr[mergeIx++] = rightArr[rightIx++];
}
}
while (leftIx < leftSize) {
scratchArr[mergeIx++] = leftArr[leftIx++];
}
// Copy the merged values from scratchArr back to studentsArr.
// The remaining values from rightArr (if any) are already in
// their proper place at the end of studentsArr, so we stop
// copying when we reach that point.
for (ix = 0; ix < mergeIx; ix++) {
studentsArr[ix] = scratchArr[ix];
}
}
void mergeSortInternal(Student studentsArray[],
int amountOfStudents,
Student scratchArr[])
{
if (amountOfStudents <= 1) {
return;
}
int leftSize = amountOfStudents / 2;
int rightSize = amountOfStudents - leftSize;
mergeSortInternal(studentsArray, leftSize, scratchArr);
mergeSortInternal(studentsArray + leftSize, rightSize, scratchArr);
merge(studentsArray, leftSize, rightSize, scratchArr);
}
#define MAX_ARR_SIZE 5500
void mergeSort(Student studentsArray[], int amountOfStudents)
{
if (amountOfStudents <= 1) {
return;
}
if (amountOfStudents > MAX_ARR_SIZE) {
fprintf(stderr, "Array too large to sort.\n");
return;
}
Student scratchArr[MAX_ARR_SIZE];
mergeSortInternal(studentsArray, amountOfStudents, scratchArr);
}
The top-level sort function is mergeSort, defined as in the original post. It declares a single scratch array of size MAX_ARR_SIZE, defined as 5500. The top-level function is not itself recursive, so this scratch array is only allocated once.

C sudoku backtracking solver precheck function

This is my first post on StackOverflow, so I apologize if I'm doing something wrong. I'm relatively new to C, so I'm sure my code is fairly ugly and hacky in places, however the majority of the code does what I expect it to. I'm having trouble with a precheck method that I'm using to check a sudoku board before I begin feeding it through my solver-logic. I'm redirecting input from a text file with strings that look like
4.....8.5.34.........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......
4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.5......
4.....8.5.3..........7......2.....6.....8.4......1...x...6.3.7.5..2.....1.4......
417369825632158947958724316825437169791586432346912758289643571573291684164875293
417369825632158947958724316825437169791586432346912758289643.71573291684164875293
Each string is (ideally) 81 characters with just digits 1-9 and '.'s. I parse a string into a temp char array, and then use the method fillBoard to transfer the chars in the temp array into a 2d int array. Once this is complete, I call my precheck method. If the filled board doesn't pass the row, column, and box checks, the precheck method returns a one, indicating that the puzzle is not solvable (meaning an error message should be printed and that the program should move on to the next string). For some reason, my precheck method is returning one even for strings that should be solvable. I'm not sure why this is. Any help would be appreciated. Thanks.
#include <stdio.h>
#include <string.h>
int alphaError = 0;
struct Point findEmpty(int board[9][9]);
int usedInBox(int board[9][9], int boxStartRow, int boxStartCol, int num);
int positionSafe(int board[9][9], int row, int col, int num);
int usedInCol(int board[9][9], int col, int num);
int usedInRow(int board[9][9], int row, int num);
int solvePuzzle(int board[9][9]);
int precheck(int board[9][9]);
int main()
{
char c;
int charCount = 0;
int i = 0;
char tempStr[100000];
int board[9][9];
while((fscanf(stdin, "%c", &c)) != EOF)
{
printf("%c", c);
if(c != '\n')
{
if(isalpha(c))
{
alphaError = 1;
}
tempStr[i] = c;
i++;
charCount++;
}
else
{
if(charCount != 81 || alphaError == 1)
{
printf("Error\n\n");
i = 0;
charCount = 0;
alphaError = 0;
}
else
{
fillBoard(board, tempStr);
printBoard(board);
if(precheck(board) == 1)
{
printf("Error\n\n");
}
else
{
if(solvePuzzle(board) == 1)
{
printBoard(board);
}
else
{
printf("No solution\n\n");
}
}
i = 0;
charCount = 0;
}
}
}
return 0;
}
struct Point
{
int x;
int y;
} point;
struct Point findEmpty(int board[9][9])
{
struct Point point1;
point1.x = -1;
point1.y = -1;
int row, col;
for(row = 0; row < 9; row++)
{
for(col = 0; col < 9; col++)
{
if(board[row][col] == 0)
{
point1.x = col;
point1.y = row;
}
}
}
return point1;
}
int usedInBox(int board[9][9], int boxStartRow, int boxStartCol, int num)
{
int row, col;
for(row = 0; row < 3; row++)
{
for(col = 0; col < 3; col++)
{
if(board[row + boxStartRow][col + boxStartCol] == num)
{
return 1;
}
}
}
return 0;
}
int positionSafe(int board[9][9], int row, int col, int num)
{
if((usedInRow(board, row, num)) == 0 && (usedInCol(board, col, num)) == 0 && (usedInBox(board, (row-row%3), (col-col%3), num)) == 0)
{
return 1;
}
else
{
return 0;
}
}
int usedInCol(int board[9][9], int col, int num)
{
int row;
for(row = 0; row < 9; row++)
{
if(board[row][col] == num)
{
return 1;
}
}
return 0;
}
int usedInRow(int board[9][9], int row, int num)
{
int col;
for(col = 0; col < 9; col++)
{
if(board[row][col] == num)
{
return 1;
}
}
return 0;
}
int solvePuzzle(int board[9][9])
{
int num;
struct Point point2;
point2 = findEmpty(board);
if(point2.x == -1)
{
return 1;
}
for(num = 1; num <= 9; num++)
{
if(positionSafe(board, point2.y, point2.x, num) == 1)
{
board[point2.y][point2.x] = num;
if(solvePuzzle(board) == 1)
{
return 1;
}
board[point2.y][point2.x] = 0;
}
}
return 0;
}
void printBoard(int board[9][9])
{
int i, j;
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
printf("%d", board[i][j]);
}
}
printf("\n\n");
}
void fillBoard(int board[9][9], char tempStr[100000])
{
int i, j;
int k = 0;
for(i = 0; i < 9; i++)
{
for(j = 0; j < 9; j++)
{
if(tempStr[k] == '.')
{
board[i][j] = 0;
}
else
{
board[i][j] = (tempStr[k] - '0');
}
k++;
}
}
}
int precheck(int board[9][9])
{
int i, j, num;
for(i = 0; i < 9; i++)
{
for(j = 0; j < 9; j++)
{
if(board[i][j] != 0)
{
num = board[i][j];
if(positionSafe(board, i, j, num) == 0)
{
return 1;
}
}
}
}
return 0;
}
So you are using precheck on an already filled board? That might be the problem because usedInCol, usedInRow and usedInBlock will return 1 if the value is already present. So precheck should be used only while filling the board, not after. It will always return 1 if you check values you take from the already filled board.

C Header files not working?

I can't get my runner.c to see my mergesort.h import, just the last thing I need to do before I go through and add in comments.
Not seeing what I am doing wrong here so I thought I'd get more eyes to look at it. I looked up questions on here and also pretty much copied the template my lab professor has but it still won't work.
Error
/tmp/ccf8TT1E.o: In function `main':
/home/carson/CProgs/lab5/runner.c:10: undefined reference to `mergeSort'
/home/carson/CProgs/lab5/runner.c:11: undefined reference to `print'
collect2: error: ld returned 1 exit status
runner.c
#include <stdio.h>
#include <stdlib.h>
#include "mergesort.h"
int main()
{
int length = 4;
int array[4] = {7,5,3,1};
mergeSort(array, length);
print(array,length);
}
mergesort.h
#ifndef MERGESORT_H_
#define MERGESORT_H_
void mergeSort(int* x, int length);
#endif
mergesort.c
#include <stdio.h>
#include <stdlib.h>
#include "mergesort.h"
void mergeSort(int* array, int length)
{
if(length == 2)
{
if(array[1] < array[0])
{
swap(&array[1],&array[0]);
}
return;
}
else if(length == 1)
{
return;
}
else
{
if(length%2 == 0)
{
int halfLength = length/2;
int bottomHalf[halfLength];
int topHalf[halfLength];
int i;
for(i = 0; i <= (halfLength); i++)
{
bottomHalf[i] = array[i];
topHalf[i] = array[i+(halfLength)];
}
mergeSort(bottomHalf, halfLength);
mergeSort(topHalf, halfLength);
int arrayLoc = 0;
int bottomHalfLoc = 0;
int topHalfLoc = 0;
while(bottomHalfLoc < halfLength && topHalfLoc < halfLength)
{
if(bottomHalf[bottomHalfLoc] > topHalf[topHalfLoc])
{
array[arrayLoc] = topHalf[topHalfLoc];
topHalfLoc++;
}
else
{
array[arrayLoc] = bottomHalf[bottomHalfLoc];
bottomHalfLoc++;
}
arrayLoc++;
}
if(bottomHalfLoc < arrayLoc)
{
while(bottomHalfLoc < halfLength)
{
array[arrayLoc] = bottomHalf[bottomHalfLoc];
bottomHalfLoc++;
arrayLoc++;
}
}
return;
}else
{
int halfLength = length/2;
int bottomHalf[halfLength];
int topHalf[halfLength+1];
int i;
for(i = 0; i <= (halfLength); i++)
{
bottomHalf[i] = array[i];
}
for(i = 0; i <=(halfLength+1); i++)
{
topHalf[i] = array[i+halfLength];
}
mergeSort(bottomHalf, halfLength);
mergeSort(topHalf, halfLength);
int arrayLoc = 0;
int bottomHalfLoc = 0;
int topHalfLoc = 0;
while(bottomHalfLoc < halfLength && topHalfLoc < halfLength)
{
if(bottomHalf[bottomHalfLoc] > topHalf[topHalfLoc])
{
array[arrayLoc] = topHalf[topHalfLoc];
topHalfLoc++;
}
else
{
array[arrayLoc] = bottomHalf[bottomHalfLoc];
bottomHalfLoc++;
}
arrayLoc++;
}
if(bottomHalfLoc < arrayLoc)
{
while(bottomHalfLoc < halfLength)
{
array[arrayLoc] = bottomHalf[bottomHalfLoc];
bottomHalfLoc++;
arrayLoc++;
}
}
return;
}
}
}
void swap(int *smallerValue, int *largerValue)
{
int temp = *smallerValue;
*smallerValue = *largerValue;
*largerValue = temp;
}
void print(int array[], int length)
{
printf("%d",array[0]);
int i;
for(i = 1; i < length; i++)
{
printf(",%d",array[i]);
}
printf("\n");
}
use gcc *.c -o runner.out and one more thing i dont see print function in mergesort.h file but u r calling it in the main function. include it or use extern print(array,length);

Calculating characters apperances in a row

Program i've wrote is calculating how many times each letter appears in a string. I want to change it that it will find the character that appears the great amount of times in a row i.e. for the string "aabbbcccca" i want to printf "c" (as there are four c in a row and only two a and three b).
How to change my program that it will do the things i want? I am looking for the solution that will be as simple as possible and I want to use the existing code as much as possible.
#include "stdafx.h"
#include "string.h"
#include "ctype.h"
int count_nonspace(const char* str)
{
int count = 0;
while (*str)
{
if (!isspace(*str++))
count++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[127];
int i = 0, j = 0, count[127] = { 0 };
char string[100] = "Hello world";
for (i = 0; i < strlen(string); i++)
{
for (j = 33; j<127; j++)
{
if (string[i] == (j))
{
count[j]++;
}
}
}
for (j = 0; j< 127; j++)
{
if (count[j] > 0)
if (j < ' ' + 1)
printf("\n%d -> %d", count[j], j);
else
printf("\n%d -> %c", count[j], char(j));
}
}
My idea for changing the code is the following (posted only the changed part):
but still results are not as anticipated, why is that?
for (i = 0; i < strlen(string); i++)
{
for (j = 33; j<127; j++)
{
if (string[i] == (j))
{
count[j]++;
if (string[i] == string[i + 1])
count[j]++;
else
best[j] = count[j];
}
}
}
#include "stdafx.h"
#include "string.h"
#include "ctype.h"
int count_nonspace(const char* str)
{
int count = 0;
while (*str)
{
if (!isspace(*str++))
count++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[127];
int i = 0, j = 0, count[127] = { 0 };
int cur_count = 1; /* Gets compared with value in count[] */
char cur_char = '\0';
char string[100] = "Hello world";
for (i = 0; i < strlen(string); i++)
{
if(cur_char == string[i])
{
cur_count++;
}
else
{
if(32 < cur_char && cur_char < 127)
{
if(cur_count > count[cur_char])
{
count[cur_char] = cur_count;
}
}
cur_char = string[i];
cur_count = 1;
if(32 < cur_char && cur_char < 127)
{
if(!(count[cur_char]))
{
count[cur_char] = cur_count;
}
}
}
}
/* Find the most consecutive char and print it. */
char max_char = '\0';
int max_count = 0;
for(j = 0; j < 127; j++)
{
if(max_count < count[j])
{
max_count = count[j];
max_char = j;
}
}
printf("%c\n", max_char);
}

Resources