This was part of a recursion assignment in Computer Science I
taught by Dr. Cazalas at UCF.
Assignment Specification
You are working on an engineering project with other students and are in need of 2x4s (2 by 4’s) of various lengths. Thankfully, UCF has its very own “Depot” store: KnightsDepot…so you don’t have to drive far. Unfortunately, KnightsDepot only carries 2x4s in fixed lengths. So your team will have to purchase the 2x4s and then cut them as needed. Because of your tight college student budget, you want to buy the least number of 2x4s in order to cover the lengths requested by your team.
The recursive function you are designing will return the minimum number of 2x4s you need to purchase, in order to cover the lengths requested by your team. Example:
Array of 2x4 lengths requested by your team: { 6, 4, 3, 4, 1, 3 } Fixed length of 2x4s at KnightsDepot: 6 (so each purchased 2x4 has a length of 6) A possible arrangement of of 2x4s: { 6 } { 3, 3 } { 4, 1 } { 4 } Minimum number of 2x4s needed to purchase: 4
Approach to solving
-------------------
My initial thought to solve this was to use a "greedy" algorithm which simply makes the best possible choice for the next board so that no scrap is wasted.
This method of solving is certainly faster than the final solution, but it is possible for this method not to be the most efficient use of boards.
The correct solution was to permutate the order in which you bought the boards and do a simple in-order purchase and calculate if this order performed better than the previous.
``` c KnightsDepot.c
/* precondition: fin/fout are pointers to the input/output file
postcondition: calculates the minimum amount of boards needed for project
*/
void KnightsDepot(FILE *fin, FILE *fout) {
//read in args
int size, whole;
fscanf(fin, "%d %d", &whole, &size);
if (DEBUG) printf("Read in argument size: %d, whole: %d\n", size, whole);
//need to DAM for board array
int * boards = (int *) malloc(sizeof(int)*size);
//read in boards
int i;
for (i=0; i < size; i++)
fscanf(fin, "%d", &boards[i]);
//begin solving
if (DEBUG) printf("KnightsDepot: \n");
fprintf(fout, "KnightsDepot: ");
//edgecase: if boards to be bought are zero then just print 0 and get out
if (size == 0) {
fprintf(fout, "%d\n\n", 0);
if (DEBUG) printf("\ntotal boards: %d\n\n", 0);
return;
}
//for passing by reference into DepotPermuteAndCalc
//setting value to -1 indicates no boards have been counted yet.
int runningCount = -1;
//recurse
int total = DepotPermuteAndCalc(boards, size, 0, whole, &runningCount);
fprintf(fout, "%d\n\n", total);
if (DEBUG) printf("\ntotal boards: %d\n\n", total);
//cleanup
free(boards);
return;
}
/* precondition: boards is the array of our board lengths of size size. fixed is the range we are holding
in place [0-fixed] while we permute. whole is the dimension of the boards at the store and
runningCount is a pointer which holds the value of the least amount of boards we purchased
through all the permutations.
postcondition: returns the minimum number of boards needed for the project.
*/
int DepotPermuteAndCalc(int boards[], int size, int fixed, int whole, int *runningCount) {
if (DEBUG) {
printf("PermutateAndCalc() size:%d, fixed:%d, whole:%d, runningCount:%d\n", size, fixed, whole, *runningCount);
int i;
for (i=0; i<size; i++)
printf("%d ", boards[i]);
printf("\n");
}
//basecase
if (fixed == size) {
//calculate number of boards needed for this permutation
int count = DepotCalcBoards(boards, size-1, whole);
//compare to past permuations or just set it to runningCount if this is first permutation (-1)
if (*runningCount == -1 || count < *runningCount)
*runningCount = count;
}
//permutate
int i;
for (i=fixed; i < size; i++) {
swap(boards, fixed, i);
DepotPermuteAndCalc(boards, size, fixed+1, whole, runningCount);
swap(boards, fixed, i);
}
//return our lowest count
return *runningCount;
}
/* precondition: boards is the array of our board lengths of size size. whole is the dimension of the boards
at the store.
postcondition: returns the number of boards needed doing a 'dumb' linear addition
*/
int DepotCalcBoards(int boards[], int size, int whole) {
int i;
int working = 0;
//start at the end of the array and figure out how many boards we can get
for(i=size; i >= 0; i--) {
working += boards[i];
//the boards divide evenly into the whole dimension
if (working == whole) {
//are we at the end of array?
if (i == 0) return 1;
//no so recurse
else return 1 + DepotCalcBoards(boards, i-1, whole);
}
//we have to waste the rest of the board and recurse with current i as new size
if (working > whole) return 1 + DepotCalcBoards(boards, i, whole);
}
//if we get this far then we have a stray cut that needs to be made
return 1;
}
/* precondition: a is the position that will be put into b and vice-versa
postcondition: switches the values at index a and index b in the array
*/
void swap(int array[], int a, int b) {
int temp = array[a];
array[a] = array[b];
array[b] = temp;
return;
}
```