Knapsacks problem 1/0 dynamic - c

I want to solve the knapsack problem with dynamic programming! The item should be in the knapsack or not, I do not want to put the same item in the knapsack more then one time!
I've looked at this code but with this one you can add the same object more then just one time
#include <stdio.h>
#define MAXWEIGHT 100
int n = 3; /* The number of objects */
int c[10] = {8, 6, 4}; /* c[i] is the *COST* of the ith object; i.e. what
YOU PAY to take the object */
int v[10] = {16, 10, 7}; /* v[i] is the *VALUE* of the ith object; i.e.
what YOU GET for taking the object */
int W = 10; /* The maximum weight you can take */
void fill_sack() {
int a[MAXWEIGHT]; /* a[i] holds the maximum value that can be obtained
using at most i weight */
int last_added[MAXWEIGHT]; /* I use this to calculate which object were
added */
int i, j;
int aux;
for (i = 0; i <= W; ++i) {
a[i] = 0;
last_added[i] = -1;
}
a[0] = 0;
for (i = 1; i <= W; ++i)
for (j = 0; j < n; ++j)
if ((c[j] <= i) && (a[i] < a[i - c[j]] + v[j])) {
a[i] = a[i - c[j]] + v[j];
last_added[i] = j;
}
for (i = 0; i <= W; ++i)
if (last_added[i] != -1)
printf("Weight %d; Benefit: %d; To reach this weight I added object %d (%d$ %dKg) to weight %d.\n",
i, a[i], last_added[i] + 1, v[last_added[i]],
c[last_added[i]], i - c[last_added[i]]);
else
printf("Weight %d; Benefit: 0; Can't reach this exact weight.\n", i);
printf("---\n");
aux = W;
while ((aux > 0) && (last_added[aux] != -1)) {
printf("Added object %d (%d$ %dKg). Space left: %d\n",
last_added[aux] + 1, v[last_added[aux]],
c[last_added[aux]], aux - c[last_added[aux]]);
aux -= c[last_added[aux]];
}
printf("Total value added: %d$\n", a[W]);
}
int main(int argc, char *argv[]) {
fill_sack();
return 0;
}
and then i tried to make a array to see if the object is in the knapsack or not, but then this program did not work as it should!
#define MAXWEIGHT 101
#define MAX_ITEMS 100000
int items = 2;
int c[10] = {1, 2};
int v[10] = {1000, 2001};
int W = 100;
int taken[MAX_ITEMS];
void takenOrNot(){
int i;
for(i = 0; i < items; i++){
taken[i] = 0;
}
}
void fill_sack() {
int a[MAXWEIGHT];
int last_added[MAXWEIGHT];
int i, j;
int aux;
for (i = 0; i <= W; ++i) {
a[i] = 0;
last_added[i] = -1;
}
a[0] = 0;
for (i = 1; i <= W; ++i)
for (j = 0; j < items; ++j)
if ((c[j] <= i) && (a[i] < a[i - c[j]] + v[j]) && taken[j] == 0) {
a[i] = a[i - c[j]] + v[j];
last_added[i] = j;
taken[j] = 1;
}
for (i = 0; i <= W; ++i)
if (last_added[i] != -1)
printf("Weight %d; Benefit: %d; To reach this weight I added object %d (%d$ %dKg) to weight %d.\n",
i, a[i], last_added[i] + 1, v[last_added[i]],
c[last_added[i]], i - c[last_added[i]]);
else
printf("Weight %d; Benefit: 0; Can't reach this exact weight.\n", i);
printf("---\n");
aux = W;
while ((aux > 0) && (last_added[aux] != -1)) {
printf("Added object %d (%d$ %dKg). Space left: %d\n",
last_added[aux] + 1, v[last_added[aux]],
c[last_added[aux]], aux - c[last_added[aux]]);
aux -= c[last_added[aux]];
}
printf("Total value added: %d$\n", a[W]);
}
int main(int argc, char *argv[]) {
takenOrNot();
fill_sack();
return 0;
}
Could you guys help me please? :)

This might help...!
public class Knapsack
{
int knapsackSize;
int[] _weights;
int[] _values;
int[,] results;
public Knapsack(int[] weights, int[] values, int size)
{
_weights = weights;
_values = values;
knapsackSize = size;
}
public int CreateSolution()
{
results = new int[_weights.Length + 1, knapsackSize + 1];
for (int i = 0; i < _weights.Length; i++) // item 1 to n
{
for (int j = 1; j <= knapsackSize; j++) //weight 1 to m
{
if (_weights[i] > j)
{
//if item weight is grater than knapsack capacity
results[i + 1, j] = results[i, j];
}
else
{
if (results[i, j] > (_values[i] + results[i, j - _weights[i]]))
{
//if previously calculated value only is grater
results[i + 1, j] = results[i, j];
}
else
{
//if including current item gives more value
results[i + 1, j] = _values[i] + results[i, j - _weights[i]];
}
}
}
}
return results[_weights.Length, knapsackSize]; // index (n, m) will be max value
}
static void Main(string[] args)
{
Knapsack demo = new Knapsack(new int[] { 23, 26, 20, 18, 32, 27, 29, 26, 30, 27 }, new int[] { 505, 352, 458, 220, 354, 414, 498, 545, 473, 543 }, 67);
Console.WriteLine("Solution is: " + demo.CreateSolution());
Console.ReadLine();
}
}

Related

Find longest sub-array with no repetitions

The task is to find the longest contiguous sub-array with all elements distinct.
Example Input {4, 3, 1, 3, 2, 1, 0} Output {3, 2, 1, 0}
Algorithm
Extract first sub Array (here 431)
Extract second sub Array (here 31)
Compare number of elements and keep the array with the biggest number (keep 431)
Return to 2
Problem The output is incorrect
/* Free old array and replace it by the new array
* If we only want to free old array and replace it by a new array
* Function will free old array and replace it by a new array with size equal to maximum size it can have
* Maximum size is the size of the input array
*/
int* newArray(int* oldArray,int* newArray, int sizeArray, int sizeFArray)
{
if (newArray == NULL) {
int* temp = malloc(sizeFArray * sizeof(int));
if (temp == NULL)
exit(1);
return temp;
} else {
memcpy(oldArray, newArray, sizeArray);
return oldArray;
}
printf("Error");
exit(1);
}
//int isAvailable(int* array , int size, int number) checks if number is available in array (return 0 if true, 1 if false)
//printArray(int* array, int size) is a simple function to print an array
void subArray(int* inputArray, int sizeInputArray)
{
int* candidate = malloc(sizeInputArray * sizeof(int));
if (candidate == NULL)
exit(1);
int sizeCandidate = 0;
int* newCandidate = malloc(sizeInputArray * sizeof(int));
if (newCandidate == NULL)
exit(1);
int sizeNewCandidate = 0;
//We will first fill the candidate
while (sizeCandidate < sizeInputArray && isAvailable(candidate, sizeCandidate, *(inputArray + sizeCandidate)) != 0) {
*(candidate + sizeCandidate) = *(inputArray + sizeCandidate);
sizeCandidate++;
}
int index = 1;
//Check all potential new candidates
//If new candidate holds more elements than the current candidate
//Current candidate will be replaced by new candidate
//Else we will redo the process and check using the next candidate if availble
for (int i = 1; i < sizeInputArray; i++) {
if(isAvailable(newCandidate, sizeNewCandidate, *(inputArray + i)) == 0) {
if (sizeNewCandidate > sizeCandidate) {
candidate = newArray(candidate, newCandidate, sizeNewCandidate, sizeInputArray);
newCandidate = newArray(newCandidate, NULL, 0, 0);
sizeCandidate = sizeNewCandidate;
sizeNewCandidate = 0;
i = ++index;
} else {
newCandidate = newArray(newCandidate, NULL, 0, sizeInputArray);
sizeNewCandidate = 0;
i = ++index;
}
} else {
*(newCandidate + sizeNewCandidate) = *(inputArray + i);
sizeNewCandidate++;
}
}
printArray(candidate, sizeCandidate);
}
I hope this code looks more compact and has clear comments:
#include <stdio.h>
int a[] = { 4, 3, 1, 3, 2, 1, 0 };
int check(int a[], int i, int j)
{
for (int k = i; k < j; k++)
for (int l = k + 1; l < j; l++)
if (a[k] == a[l])
return 0;
return 1;
}
int main()
{
int s = 0; // start position of the best candidate
int m = 1; // length of the best candidate
int n = sizeof(a) / sizeof(0); // length of the array
for (int i = 0; i < n; i++) { // for every start position
for (int j = i + m + 1; j <= n; j++) { // for every lengh if it more than the best one
if (check(a, i, j)) { // check if it contains repetitions
if (j - i > m) { // if no repetions
s = i; // update the candidate
m = j - i; // and length
}
}
else
break;
}
}
printf("{%d", a[s]);
for(int i = s + 1; i < s + m; ++i)
printf(", %d", a[i]);
printf("}\n");
return 0;
}
This works and gives the correct output.
I don't understand the complexity of the code.
#include <stdio.h>
int main()
{
// int x[] = { 4, 3, 1, 3, 2, 1, 0 };
int x[] = { 4, 3, 1, 3, 2, 5, 0 };
int offset;
int cur_offset = 0;
int max = 0;
int max_offset = 0;
for (int i = 1; i < sizeof(x) / sizeof(int); i++) {
for (int j = i-1; j >= cur_offset; j--) {
if (x[i] == x[j]) {
if (max <= i - j) {
max = i - j;
max_offset = j + 1;
} else if (max_offset == cur_offset) {
max = i - max_offset;
}
cur_offset = j + 1;
break;
}
}
}
if (max < sizeof(x) / sizeof(int) - cur_offset) {
max_offset = cur_offset;
max = sizeof(x) / sizeof(int) - max_offset;
}
printf("%d", x[max_offset]);
for (int i = max_offset + 1; i < max_offset + max; i++)
printf(", %d", x[i]);
printf("\n");
}

How can I combine two arrays and output stored values as it`s written in description. May be there are some ways to do that?

Task description -> Whole task description is here
I have done part with sorting and got stuck.
How can I combine these arrays in one of already sorted pairs?
printf("\nHeight of boys in descending order\n");
for (i = (LENGTH1 - 1); i >= 0; i--)
{
printf("%d ", heightBoys[i]);
}
for (i = 0; i < LENGTH2; i++)
{
for (j = 0; j < (LENGTH2 - j - 1); j++)
{
if (heightGirls[j] > heightGirls[j+1])
{
temp = heightGirls[j];
heightGirls[j] = heightGirls[j+1];
heightGirls[j+1] = temp;
}
}
}
printf("\nHeight of girls in descending order\n");
for (j = (LENGTH2 - 1); j >= 0; j--)
{
printf("%d ", heightGirls[j]);
}
You have a sort [for the girls], but it is broken. Change:
for (j = 0; j < (LENGTH2 - j - 1); j++)
Into:
for (j = 0; j < (LENGTH2 - i - 1); j++)
To avoid [needless] replication of code, put the sorting code into a separate function.
Sort both arrays.
Take the minimum of the lengths of the two arrays (e.g. minlen).
I'm not sure what you mean [exactly] by "pairing", but the simplest is to print the pairing
Then, just loop on:
for (i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
If you needed something more complex, you might need an array of structs like:
struct pair {
int boyheight;
int girlheight;
};
This array would need to be at least minlen in length. You could fill it in by adapting the final print loop.
But, if you're just printing, here is some sample code:
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
printf("\n");
printf("Pairing:\n");
for (int i = 0; i < minlen; ++i)
printf("Girl:%d Boy:%d\n",heightGirls[i],heightBoys[i]);
return 0;
}
UPDATE:
Let's say that we input heights and number of them by ourselves. If we have extra heights of boys or girls, how can we output these extra heights apart from the rest?
Two additional for loops appended to the bottom should do the trick. In order for this to work, the iteration variable of the final for loop in the previous example must be defined outside the loop. In other words, notice the definition and usage of ipair below.
If you are creating an array the type of struct that I suggested, these loops can fill it in. The array size would then need to be max(LENGTH1,LENGTH2).
And, in unpaired loops (e.g. for boy 8, the girl value in the struct could be set to 0 or -1 to indicate that the boy is unpaired)
#include <stdio.h>
void
print_single(const int *height,int len,const char *sex)
{
printf("\nHeight of %s in descending order\n",sex);
for (int i = (len - 1); i >= 0; i--)
printf(" %d", height[i]);
printf("\n");
}
void
sort_height(int *height,int len)
{
for (int i = 0; i < len; i++) {
for (int j = 0; j < (len - i - 1); j++) {
if (height[j] > height[j + 1]) {
int temp = height[j];
height[j] = height[j + 1];
height[j + 1] = temp;
}
}
}
}
int
main(void)
{
int heightBoys[] = { 5, 8, 7, 9, 6 };
int heightGirls[] = { 3, 1, 2 };
int LENGTH1 = sizeof(heightBoys) / sizeof(heightBoys[0]);
int LENGTH2 = sizeof(heightGirls) / sizeof(heightGirls[0]);
sort_height(heightBoys,LENGTH1);
print_single(heightBoys,LENGTH1,"boys");
sort_height(heightGirls,LENGTH2);
print_single(heightGirls,LENGTH2,"girls");
int minlen = LENGTH1;
if (minlen > LENGTH2)
minlen = LENGTH2;
int ipair = 0;
printf("\n");
printf("Pairing:\n");
for (; ipair < minlen; ++ipair)
printf("Girl:%d Boy:%d\n",heightGirls[ipair],heightBoys[ipair]);
if (ipair < LENGTH1) {
printf("\n");
printf("Unpaired Boys:\n");
for (int i = ipair; i < LENGTH1; ++i)
printf("Boy:%d\n",heightBoys[i]);
}
if (ipair < LENGTH2) {
printf("\n");
printf("Unpaired Girls:\n");
for (int i = ipair; i < LENGTH2; ++i)
printf("Girl:%d\n",heightGirls[i]);
}
return 0;
}

Interleaving array in C

I posted earlier, but I did not properly format or add my code. Say I have an int array x = [1,2,3]. Given a value i, I want to create an array x^i, such that, if i = 3, array x^i = [1,1,1,2,2,2,3,3,3]. If i = 5, array x^i = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5]. I am dynamically allocating memory for this.
However, my code for i = 3 is creating an array = [1,2,3,1,2,3,1,2,3]. I've tried many different things, and I got something like [1,1,1,1,1,1,1,1,1] or [3,3,3,3,3,3,3,3,3] but never the correct answer.
Here is my code:
void binary_search(int size_a, int * A, int size_x, int *X, int max_i, int min_i){
int i, j, k, count = 0, max_repeat = 0;
while(min_i <= max_i){
int repeats = (max_i + min_i)/2;
int * temp = realloc(X, size_x * sizeof(int) * repeats);
X = temp;
for(k = 0; k < size_x; ++k){
int idx = size_x - k -1;
temp = &X[idx];
for(j = 0; j < repeats; ++j){
X[idx * repeats + j] = *temp;
}
}
printf("New X: ");
for(i = 0; i < size_x * repeats; i++){
printf("%d ", X[i]);
}
int count = 0;
for(i = 0; i < size_x * repeats; i++){
for(j = 0; j < size_a; j++){
if(A[j] == X[i]){
count++;
i++;
}
}
}
if (count == size_x * repeats){
printf("Low: %d Mid %d High % d Passes\n", min_i, repeats, max_i);
min_i = repeats + 1;
}
else
printf("Low: %d Mid %d High % d Fails\n", min_i, repeats, max_i);
max_i = repeats - 1;
}
}
the variable repeats represents the value i in x^i.
The output is this:
Old X: 1 2 3
New X: 1 1 1 2 2 2 3 3 3 Low: 0 Mid 3 High 6 Fails
New X: 1 1 1 Low: 0 Mid 1 High 2 Fails
New X: Low: 0 Mid 0 High 0 Fails
The first iteration is correct, however, the second iteration should not be [1,1,1], it should be [1,2,3].
Where am I going wrong?
Here you go:
int misleading_function_names_is_bad_practice(size_t xsize, int x[xsize], size_t i)
{
void * const tmp = realloc(x, xsize * sizeof(*x) * i);
if (tmp == NULL) {
return -__LINE__;
}
x = tmp;
for (size_t k = 0; k < xsize; ++k) {
// index of the last original digit counting down
const size_t idx = xsize - k - 1;
const int tmp = x[idx];
for (size_t l = 0; l < i; ++l) {
// fill from the back
x[idx * i + l] = tmp;
}
}
return 0;
}
Live example available at onlinegdb.

Knight tours algorithm C implementation performance

I was playing with Knight Tour algorithm implementation in Java. All that time I was completely sure that implementation on C must be faster. So after reading GNU C Reference the code be done and logic was implemented the same way is on Java.
Can you imagine my wonder when the C variant took more time to process a 6x6 board.
So my question is how the code below can be optimized from technical perspective (i.e. without heuristic optimizations).
Some performance notes: on my i5 laptop with Ubuntu the provided implementation took more than 4 hours to solve 6x6 board. Program on Java can solve this task in about 3 hours 18 mins with single threaded approach.
Some algorithm notes: this implementation finds all possible tours from all cells on the board, not just closed tours. As well heuristic optimization isn't used as it helps to find faster first tour not all.
EDIT: code compiled without any optimization with this command: gcc knight_tour.c -o knight-tour
#include "stdio.h"
#define BOARD_SIZE 5
#define MAX_MOVE_COUNT BOARD_SIZE*BOARD_SIZE
void printBoard(int[][BOARD_SIZE], int);
void clearBoard(int[][BOARD_SIZE], int);
int knight_move(int[][BOARD_SIZE], int, int, int);
int is_valid_position(int, int);
void calc_all_knight_jumps();
static int ALL_KNIGHT_COL_JUMPS[BOARD_SIZE][BOARD_SIZE][9];
static int ALL_KNIGHT_ROW_JUMPS[BOARD_SIZE][BOARD_SIZE][8];
int main() {
int board[BOARD_SIZE][BOARD_SIZE];
clearBoard(board, BOARD_SIZE);
calc_all_knight_jumps();
int result[BOARD_SIZE][BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
result[i][j] = knight_move(board, i, j, 1);
}
}
printBoard(result, BOARD_SIZE);
return 0;
}
int knight_move(int board[][BOARD_SIZE], int cpos, int rpos, int level) {
if (level == MAX_MOVE_COUNT)
return 1;
board[cpos][rpos] = level;
int solved_count = 0;
int jump_count = ALL_KNIGHT_COL_JUMPS[cpos][rpos][8];
for (int i = 0; i < jump_count; i++) {
int next_cpos = ALL_KNIGHT_COL_JUMPS[cpos][rpos][i];
int next_rpos = ALL_KNIGHT_ROW_JUMPS[cpos][rpos][i];
if (board[next_cpos][next_rpos] == 0) {
solved_count += knight_move(board, next_cpos, next_rpos, level + 1);
}
}
board[cpos][rpos] = 0;
return solved_count;
}
void clearBoard(int board[][BOARD_SIZE], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = 0;
}
}
}
void printBoard(int board[][BOARD_SIZE], int size) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
printf("%8d", board[i][j]);
}
printf("\n");
}
}
int is_valid_position(int cpos, int rpos) {
if (cpos < 0 || cpos >= BOARD_SIZE) return 0;
if (rpos < 0 || rpos >= BOARD_SIZE) return 0;
return 1;
}
void calc_all_knight_jumps() {
int col_jumps[] = { 1, 2, 2, 1, -1, -2, -2, -1};
int row_jumps[] = { 2, 1, -1, -2, -2, -1, 1, 2};
int next_cpos, next_rpos;
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
int jump_count = 0;
for (int k = 0; k < 8; k++) {
next_cpos = i + col_jumps[k];
next_rpos = j + row_jumps[k];
if (is_valid_position(next_cpos, next_rpos) == 1) {
ALL_KNIGHT_COL_JUMPS[i][j][jump_count] = next_cpos;
ALL_KNIGHT_ROW_JUMPS[i][j][jump_count] = next_rpos;
jump_count++;
}
}
ALL_KNIGHT_COL_JUMPS[i][j][8] = jump_count;
}
}
}
Taking into account all the comments I modified the source code a bit.
tried out -O2 and -O3 optimization options with gcc compiler;
reduced number of top level invocation on knight_move() method. so now only unique results are calculated and then reflected horizontally, vertically and diagonally;
added code to measure performance without printf() usage;
checked that both C and Java variants are identical as much as possible;
And finally there are results I expected - C code is faster (but with optimization options)
C code with the -O2 option: duration - 1348 sec (22:28)
Java code: duration - 1995 sec (33:15)
C code without optimization: duration - 3518 sec (58:38)
C code with the -O3 option: duration - 2143 sec (35:43)
Here are both implementations in case someone be interested in knight tour algorithm on C and Java:-)
GNU C
#include "stdio.h"
#include "time.h"
#define BOARD_SIZE 6
#define MAX_MOVE_COUNT BOARD_SIZE*BOARD_SIZE
int knight_move(int[][BOARD_SIZE], int, int, int);
void pre_calc_all_knight_jumps();
void print_result(int[][BOARD_SIZE]);
static int ALL_KNIGHT_COL_JUMPS[BOARD_SIZE][BOARD_SIZE][9];
static int ALL_KNIGHT_ROW_JUMPS[BOARD_SIZE][BOARD_SIZE][8];
int main() {
// init board
int board[BOARD_SIZE][BOARD_SIZE];
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
board[i][j] = 0;
}
}
pre_calc_all_knight_jumps();
int result[BOARD_SIZE][BOARD_SIZE];
struct timespec s_time, e_time;
clock_gettime(CLOCK_MONOTONIC, &s_time);
int border = BOARD_SIZE - 1;
int center = BOARD_SIZE / 2.0 + 0.5;
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knight_move(board, i, j, 1);
result[i][j] = res;
result[border - i][j] = res;
result[i][border - j] = res;
result[border - i][border - j] = res;
if (i != j) result[j][i] = res;
}
}
clock_gettime(CLOCK_MONOTONIC, &e_time);
printf("Duration in seconds: %ld\n", e_time.tv_sec - s_time.tv_sec);
print_result(result);
return 0;
}
int knight_move(int board[][BOARD_SIZE], int cpos, int rpos, int level) {
if (level == MAX_MOVE_COUNT) return 1;
board[cpos][rpos] = level;
int solved_count = 0;
int valid_move_count = ALL_KNIGHT_COL_JUMPS[cpos][rpos][8];
for (int i = 0; i < valid_move_count; i++) {
int next_cpos = ALL_KNIGHT_COL_JUMPS[cpos][rpos][i];
int next_rpos = ALL_KNIGHT_ROW_JUMPS[cpos][rpos][i];
if (board[next_cpos][next_rpos] == 0) {
solved_count += knight_move(board, next_cpos, next_rpos, level + 1);
}
}
board[cpos][rpos] = 0;
return solved_count;
}
void print_result(int board[][BOARD_SIZE]) {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
printf("%8d", board[i][j]);
}
printf("\n");
}
}
void pre_calc_all_knight_jumps() {
int col_jumps[] = { 1, 2, 2, 1, -1, -2, -2, -1};
int row_jumps[] = { 2, 1, -1, -2, -2, -1, 1, 2};
int next_cpos, next_rpos;
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
int jump_count = 0;
for (int k = 0; k < 8; k++) {
next_cpos = i + col_jumps[k];
next_rpos = j + row_jumps[k];
if (next_cpos < 0 || next_cpos >= BOARD_SIZE) continue;
if (next_rpos < 0 || next_rpos >= BOARD_SIZE) continue;
ALL_KNIGHT_COL_JUMPS[i][j][jump_count] = next_cpos;
ALL_KNIGHT_ROW_JUMPS[i][j][jump_count] = next_rpos;
jump_count++;
}
ALL_KNIGHT_COL_JUMPS[i][j][8] = jump_count;
}
}
}
Java
import java.util.Arrays;
public class KnightTour1 {
private final static int BOARD_SIZE = 6;
private final static int MAX_MOVE_COUNT = BOARD_SIZE * BOARD_SIZE;
private static final int[][][] ALL_KNIGHT_COL_MOVES;
private static final int[][][] ALL_KNIGHT_ROW_MOVES;
static {
final int[] knightColJumps = { 1, 2, 2, 1, -1, -2, -2, -1};
final int[] knightRowJumps = { 2, 1, -1, -2, -2, -1, 1, 2};
ALL_KNIGHT_COL_MOVES = new int[BOARD_SIZE][BOARD_SIZE][];
ALL_KNIGHT_ROW_MOVES = new int[BOARD_SIZE][BOARD_SIZE][];
int[] tmpColMoves = new int[8];
int[] tmpRowMoves = new int[8];
for (int c = 0; c < BOARD_SIZE; c++) {
for (int r = 0; r < BOARD_SIZE; r++) {
int jumpCount = 0;
for (int i = 0; i < 8; i++) {
int nextColPos = c + knightColJumps[i];
int nextRowPos = r + knightRowJumps[i];
if (isValidBoardPos(nextColPos, nextRowPos)) {
tmpColMoves[jumpCount] = nextColPos;
tmpRowMoves[jumpCount] = nextRowPos;
jumpCount++;
}
}
ALL_KNIGHT_COL_MOVES[c][r] = Arrays.copyOf(tmpColMoves, jumpCount);
ALL_KNIGHT_ROW_MOVES[c][r] = Arrays.copyOf(tmpRowMoves, jumpCount);
}
}
}
private static boolean isValidBoardPos(int colPos, int rowPos) {
return colPos > -1 && colPos < BOARD_SIZE && rowPos > -1 && rowPos < BOARD_SIZE;
}
public static void main(String[] args) {
long sTime = System.currentTimeMillis();
int[][] result = findNumberOfTours();
long duration = (System.currentTimeMillis() - sTime) / 1000;
System.out.println("Duration in seconds: " + duration);
printResult(result);
}
private static int knightMove(int[][] board, int colPos, int rowPos, int level) {
if (level == MAX_MOVE_COUNT) return 1;
board[colPos][rowPos] = level;
final int[] validColMoves = ALL_KNIGHT_COL_MOVES[colPos][rowPos];
final int[] validRowMoves = ALL_KNIGHT_ROW_MOVES[colPos][rowPos];
final int validMoveCount = validColMoves.length;
int solvedTourCount = 0;
for (int i = 0; i < validMoveCount; i++) {
final int nextColPos = validColMoves[i];
final int nextRowPos = validRowMoves[i];
if (board[nextColPos][nextRowPos] == 0) {
solvedTourCount += knightMove(board, nextColPos, nextRowPos, level + 1);
}
}
board[colPos][rowPos] = 0;
return solvedTourCount;
}
private static int[][] findNumberOfTours() {
final int[][] result = new int[BOARD_SIZE][BOARD_SIZE];
final int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
final int border = BOARD_SIZE - 1;
final int center = (int)(BOARD_SIZE / 2f + 0.5);
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knightMove(board, i, j, 1);
result[i][j] = res;
result[border - i][j] = res;
result[i][border - j] = res;
result[border - i][border - j] = res;
if (i != j) result[j][i] = res;
}
}
return result;
}
private static void printResult(int[][] res) {
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
System.out.print(String.format("%8d", res[i][j]));
}
System.out.println();
}
}
}
Here are some suggestions about your code as well as the updated version posted in your answer:
use <> for standard header files:
#include <stdio.h>
surround expressions with parentheses in macro definitions:
#define MAX_MOVE_COUNT (BOARD_SIZE * BOARD_SIZE)
use (void) when declaring functions without arguments:
void pre_calc_all_knight_jumps(void);
avoid mixing floating point and integer calculations with implicit conversions. Use this instead:
int center = (BOARD_SIZE + 1) / 2;
Some of the symmetries are not properly reflected in the result array. You should change the main loop to:
int border = BOARD_SIZE - 1;
int center = (BOARD_SIZE + 1) / 2;
for (int i = 0; i < center; i++) {
for (int j = i; j < center; j++) {
int res = knight_move(board, i, j, 1);
result[i][j] = res;
result[j][i] = res;
result[border - i][j] = res;
result[j][border - i] = res;
result[i][border - j] = res;
result[border - j][i] = res;
result[border - i][border - j] = res;
result[border - j][border - i] = res;
}
}
I also get some cache usage improvements by making the board 8x8 and using a additional argument for the playing area size.
A more efficient algorithm is definitely needed to solve this problem for larger sizes.

How to optimize my c code?

I tried to implement C code for Wavelet transform in FPGA (Zynq ZC 702) but the code get stuck and this is because of memory problem so I should optimize my code but I don't know how.
Can anyone please give me some ideas how to do that ?
This is the main of the code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "wavemin.h"
#include "waveaux.h"
#include "waveaux.c"
#include "wavemin.c"
int main() {
printf("Hello World1 \n\r");
wave_object obj;
wt_object wt;
float *inp, *out;
int N, i, J,k;
float temp[1280] = {};
char *name = "db4";
obj = wave_init(name);
printf("Hello World2 \n\r");
N = 1280;
inp = (float*)malloc(sizeof(float) * N);
out = (float*)malloc(sizeof(float) * N);
//wmean = mean(temp, N);
for (i = 0; i < N; ++i) {
inp[i] = temp[i];
printf("Hello World3 \n\r");
//printf("%g \n", inp[i]);
}
J = 4; //Decomposition Levels
wt = wt_init(obj, "dwt", N, J); // Initialize the wavelet transform object
printf("Hello World4 \n\r");
setDWTExtension(wt, "sym"); // Options are "per" and "sym". Symmetric is the default option
printf("Hello World5 \n\r");
setWTConv(wt, "direct");
printf("Hello World6 \n\r");
dwt(wt, inp); // Perform DWT
printf("Hello World7 \n\r");
//getDWTAppx(wt, out, wt->length[0]);
// printf("Approximation Coefficients Level 1 \n");
// for (i = 0; i < wt->length[0]; ++i) {
// printf("%g ", out[i]);
// }
// printf("\n\n");
for (k = 1; k <= J; ++k) {
getDWTDetail(wt, out, wt->length[k], k);
printf("Detail Coefficients Level %d Length %d \n",
k, wt - length[k]);
for (i = 0; i < wt->length[k]; ++i) {
printf("%g ", out[i]);
}
printf("\n\n");
}
wt_summary(wt);// Prints the full summary.
printf("Hello World8 \n\r");
wave_free(obj);
wt_free(wt);
free(inp);
free(out);
return 0;
}
The other part of the code where there is the function used in the main function:
#include "wavemin.h"
wave_object wave_init(char *wname) {
wave_object obj = NULL;
int retval;
retval = 0;
if (wname != NULL) {
retval = filtlength(wname);
}
obj = (wave_object)malloc(sizeof(struct wave_set) + sizeof(float) * 4 *
retval);
obj->filtlength = retval;
obj->lpd_len = obj->hpd_len = obj->lpr_len = obj->hpr_len = obj->filtlength;
strcpy(obj->wname, wname);
if (wname != NULL) {
filtcoef(wname, obj->params, obj->params + retval, obj->params + 2 *
retval, obj->params + 3 * retval);
}
obj->lpd = &obj->params[0];
obj->hpd = &obj->params[retval];
obj->lpr = &obj->params[2 * retval];
obj->hpr = &obj->params[3 * retval];
return obj;
}
wt_object wt_init(wave_object wave, char *method, int siglength, int J) {
int size, i, MaxIter;
wt_object obj = NULL;
size = wave->filtlength;
MaxIter = wmaxiter(siglength, size);
if (!strcmp(method, "dwt") || !strcmp(method, "DWT")) {
obj = (wt_object)malloc(sizeof(struct wt_set) + sizeof(float) *
(siglength + 2 * J * (size + 1)));
obj->outlength = siglength + 2 * J * (size + 1); // Default
strcpy(obj->ext, "sym"); // Default
}
obj->wave = wave;
obj->siglength = siglength;
obj->J = J;
obj->MaxIter = MaxIter;
strcpy(obj->method, method);
if (siglength % 2 == 0) {
obj->even = 1;
}
else {
obj->even = 0;
}
strcpy(obj->cmethod, "direct"); // Default
obj->cfftset = 0;
obj->lenlength = J + 2;
obj->output = &obj->params[0];
if (!strcmp(method, "dwt") || !strcmp(method, "DWT")) {
for (i = 0; i < siglength + 2 * J * (size + 1); ++i) {
obj->params[i] = 0.0;
}
}
//wave_summary(obj->wave);
return obj;
}
static void dwt_sym(wt_object wt, float *inp, int N, float *cA, int len_cA,
float *cD, int len_cD) {
int i, l, t, len_avg;
len_avg = wt->wave->lpd_len;
for (i = 0; i < len_cA; ++i) {
t = 2 * i + 1;
cA[i] = 0.0;
cD[i] = 0.0;
for (l = 0; l < len_avg; ++l) {
if ((t - l) >= 0 && (t - l) < N) {
cA[i] += wt->wave->lpd[l] * inp[t - l];
cD[i] += wt->wave->hpd[l] * inp[t - l];
printf("world1 \n\r");
}
else if ((t - l) < 0) {
cA[i] += wt->wave->lpd[l] * inp[-t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[-t + l - 1];
printf("world2 \n\r");
}
else if ((t - l) >= N) {
cA[i] += wt->wave->lpd[l] * inp[2 * N - t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[2 * N - t + l - 1];
printf("world3 \n\r");
}
}
}
}
void dwt(wt_object wt, float *inp) {
int i, J, temp_len, iter, N, lp;
int len_cA;
float *orig, *orig2;
temp_len = wt->siglength;
J = wt->J;
wt->length[J + 1] = temp_len;
wt->outlength = 0;
wt->zpad = 0;
orig = (float*)malloc(sizeof(float) * temp_len);
orig2 = (float*)malloc(sizeof(float) * temp_len);
for (i = 0; i < wt->siglength; ++i) {
orig[i] = inp[i];
printf("Hello1 \n\r");
}
if (wt->zpad == 1) {
orig[temp_len - 1] = orig[temp_len - 2];
printf("Hello2 \n\r");
}
N = temp_len;
lp = wt->wave->lpd_len;
if (!strcmp(wt->ext, "sym")) {
//printf("\n YES %s \n", wt->ext);
i = J;
while (i > 0) {
N = N + lp - 2;
N = (int)ceil((float)N / 2.0);
wt->length[i] = N;
wt->outlength += wt->length[i];
i--;
}
wt->length[0] = wt->length[1];
wt->outlength += wt->length[0];
N = wt->outlength;
printf("Hello3 \n\r");
for (iter = 0; iter < J; ++iter) {
len_cA = wt->length[J - iter];
N -= len_cA;
dwt_sym(wt, orig, temp_len, orig2, len_cA, wt->params + N, len_cA);
temp_len = wt->length[J - iter];
printf("Hello4 \n\r");
if (iter == J - 1) {
for (i = 0; i < len_cA; ++i) {
wt->params[i] = orig2[i];
printf("Hello5 \n\r");
}
} else {
for (i = 0; i < len_cA; ++i) {
orig[i] = orig2[i];
printf("Hello6 \n\r");
}
}
}
} else {
printf("Signal extension can be either per or sym");
exit(-1);
}
free(orig);
free(orig2);
}
void setDWTExtension(wt_object wt, char *extension) {
if (!strcmp(extension, "sym")) {
strcpy(wt->ext, "sym");
} else {
printf("Signal extension can be either per or sym");
exit(-1);
}
}
void setWTConv(wt_object wt, char *cmethod) {
if (!strcmp(cmethod, "direct")) {
strcpy(wt->cmethod, "direct");
}
}
void getDWTDetail(wt_object wt, float *detail, int N, int level) {
/*
returns Detail coefficents at the jth level where j = 1,2,.., J
and Wavelet decomposition is stored as
[A(J) D(J) D(J-1) ..... D(1)] in wt->output vector
Use getDWTAppx() to get A(J)
Level 1 : Length of D(J), ie N, is stored in wt->length[1]
Level 2 :Length of D(J-1), ie N, is stored in wt->length[2]
....
Level J : Length of D(1), ie N, is stored in wt->length[J]
*/
int i, iter, J;
J = wt->J;
if (level > J) {
printf("The decomposition only has %d levels", J);
}
iter = wt->length[0];
for (i = 1; i < level; ++i) {
iter += wt->length[i];
}
for (i = 0; i < N; ++i) {
detail[i] = wt->output[i + iter];
}
}
void getDWTAppx(wt_object wt, float *appx, int N) {
/*
Wavelet decomposition is stored as
[A(J) D(J) D(J-1) ..... D(1)] in wt->output vector
Length of A(J) , N = wt->length[0]
*/
int i;
for (i = 0; i < N; ++i) {
appx[i] = wt->output[i];
}
}
void wt_summary(wt_object wt) {
int i;
int J, t;
J = wt->J;
printf("Wavelet Coefficients are contained in vector : %s \n", "output");
printf("\n");
printf("Approximation Coefficients \n");
printf("Level %d Access : output[%d] Length : %d \n",
1, 0, wt->length[0]);
printf("\n");
printf("Detail Coefficients \n");
t = wt->length[0];
for (i = 0; i < J; ++i) {
printf("Level %d Access : output[%d] Length : %d \n",
i + 1, t, wt->length[i + 1]);
t += wt->length[i + 1];
}
printf("\n");
}
void wave_free(wave_object object) {
free(object);
}
void wt_free(wt_object object) {
free(object);
}
enter image description here
In your code
Always check if malloc has returned non NULL value
Check your stack and heap settings in the linker file as you declare massive local variables and do a lots of mallocs - I suspect the (nomen omen)stack overflow, or failed mallocs.
Is it a bare metal program or you run it under some kind of OS?
Just for a matter of style and concision, I would rewrite this:
if (siglength % 2 == 0) {
obj->even = 1;
}
else {
obj->even = 0;
}
Into the following code:
obj->even = !(siglength % 2);
Or, alternatively:
obj->even = (siglength % 2) ? 0 : 1;
Also, I think there is room for optimization in this function:
static void dwt_sym(wt_object wt, float *inp, int N, float *cA, int len_cA,
float *cD, int len_cD) {
int i, l, t, len_avg;
len_avg = wt->wave->lpd_len;
for (i = 0; i < len_cA; ++i) {
t = 2 * i + 1;
cA[i] = 0.0;
cD[i] = 0.0;
for (l = 0; l < len_avg; ++l) {
if ((t - l) >= 0 && (t - l) < N) {
cA[i] += wt->wave->lpd[l] * inp[t - l];
cD[i] += wt->wave->hpd[l] * inp[t - l];
printf("world1 \n\r");
}
else if ((t - l) < 0) {
cA[i] += wt->wave->lpd[l] * inp[-t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[-t + l - 1];
printf("world2 \n\r");
}
else if ((t - l) >= N) {
cA[i] += wt->wave->lpd[l] * inp[2 * N - t + l - 1];
cD[i] += wt->wave->hpd[l] * inp[2 * N - t + l - 1];
printf("world3 \n\r");
}
}
}
}
First, you are always referring to t - 1 and never t itself, so why not have:
t = 2 * i;
And, I can guess that a lot of computation can be placed outside of the inner loop... If you want to optimize, there are many good candidate here.
One last word about optimization!
You should first profile your software and see where you spend the most time before thinking about optimization. You cannot optimize "in the air" without knowing where your software does really struggle. Consider using gprof.
PS: You should never ever use the letter l (ell) as a variable... it is way to close from the number 1 (one). Consider changing this is also, it can improve the reading.

Resources