I have written the below code to implement the coin change problem: you are given n types of coin denominations of values v(1) < v(2) < ... < v(n) (all integers). Assume v(1) = 1, so you can always make change for any amount of money C. Give an algorithm which makes change for an amount of money C with as few coins as possible.
I modified the knapsack with repetitions allowed problem by setting all the values of each coin to -1. The program should then return the maximum value such that the weight of the required coins(denominations) add up to the size variable(required change). I cannot figure where i have went wrong. I should be getting an answer of -2 implying i need two coins but i'm getting -1 as the answer. Code:
#include <stdio.h>
#define max(a,b) (a > b ? a : b)
int matrix[100][100] = {0};
int knapsack(int index, int size, int weights[],int values[]){
int take,dontTake;
take = dontTake = 0;
if (matrix[index][size]!=0)
return matrix[index][size];
if (index==0){
if (weights[0]<=size){
matrix[index][size] = values[0];
return values[0];
}
else{
matrix[index][size] = 0;
return 0;
}
}
if (weights[index]<=size)
take = values[index] + knapsack(index, size-weights[index], weights, values); //knapsack(index) and not //knapsack(index-1)
dontTake = knapsack(index-1, size, weights, values);
matrix[index][size] = max (take, dontTake);
return matrix[index][size];
}
int main(){
int nItems = 4;
int knapsackSize = 10;
int weights[4] = {5,4,6,3};
int values[4] = {-1,-1,-1,-1};
printf("Max value = %dn",knapsack(nItems-1,knapsackSize,weights,values));
return 0;
}
Where am i going wrong and how can i fix this?
It is simple because, -1 > -2 and you are taking the maximum between the 2 choices at every level.
EDIT : I have impelmented a solution in which values are taken as positive, also i have made minor changes to the code, if there is something that you do not understand feel free to ask.
#include <stdio.h>
#define min(a,b) (a < b ? a : b)
#define INF 10000000
int matrix[100][100] = {0};
int knapsack(int index, int size, int weights[],int values[]){
int take = INF;
if (index == -1){
if(size == 0) return 0;
else return INF;
}
if (matrix[index][size]!=-1)
return matrix[index][size];
for(int itemcount = 0;(itemcount * weights[index]) <= size;itemcount++){
if ((weights[index] * itemcount) <= size)
take = min(take, (values[index] * itemcount) + knapsack(index - 1, size - (itemcount * weights[index]), weights, values)); //knapsack(index) and not //knapsack(index-1)
}
matrix[index][size] = take;
return matrix[index][size];
}
int main(){
int nItems = 4;
int knapsackSize = 10;
int weights[4] = {5,4,6,3};
int values[4] = {1,1,1,1};
for(int i = 0;i < 100;i++) for(int j = 0;j < 100;j++) matrix[i][j] = -1;
printf("Min value = %d\n",knapsack(nItems-1,knapsackSize,weights,values));
return 0;
}
Link to solution on Ideone : http://ideone.com/TNycZo
Here i have taken infinity as a large integer, to find minimum values, if the answer is infinity that means it is not possible to create such a denomination.
Related
I have looked through various questions on the site and I haven't managed to find anything which implements this by the following reasoning (so I hope this isn't a duplicate).
The problem I'm trying to solve via a C program is the following:
As the programmer of a vending machine controller your are required to compute the minimum number of coins that make up the required change to give back to customers. An efficient solution to this problem takes a dynamic programming approach, starting off computing the number of coins required for a 1 cent change, then for 2 cents, then for 3 cents, until reaching the required change and each time making use of the prior computed number of coins. Write a program containing the function ComputeChange(), that takes a list of valid coins and the required change. This program should repeatedly ask for the required change from the console and call ComputeChange() accordingly. It should also make use of “caching”, where any previously computed intermediate values are retained for subsequent look-up.
After looking around online to find how others have solved it, I found the following example applied with pennies, nickels and dimes:
Which I tried to base my code upon. But first of all, my code isn't halting, and secondly, I'm not sure if I'm incorporating the caching element mentioned in the rubric above. (I'm not really sure how I need to go about that part).
Can anyone help find the flaws in my code?
#include <stdio.h>
#include <limits.h>
int computeChange(int[],int,int);
int min(int[],int);
int main(){
int cur[]={1,2,5,10,20,50,100,200};
int n = sizeof(cur)/sizeof(int);
int v;
printf("Enter a value in euro cents: ");
scanf("%d", &v);
printf("The minimum number of euro coins required is %d", computeChange(cur, v, n));
return 0;
}
int computeChange(int cur[], int v, int n){
if(v < 0)
return -1;
else if(v == 0)
return 0;
else{
int possible_mins[n], i;
for(i = 0; i < n; i++){
possible_mins[i]=computeChange(cur, v-cur[i], n);
}
return 1+min(possible_mins, n);
};
}
int min(int a[], int n){
int min = INT_MAX, i;
for(i = 0; i < n; i++){
if((i>=0) && (a[i]< min))
min = a[i];
}
return min;
}
Any assistance will be greatly appreciated.
OP's supplied Change() algorithm incurs lots of recursion, even with the if(v < 0) return INT_MAX; correction. So much recursion that even small-ish values take millions of recursive calls.
A simple improvement is to "cache" the best solution found so far. Then when an intermediate solution is already worse than the best, no need to continue that path.
int computeChange(int cur[], int v, int n, int count_now, int *bestcount) {
if (count_now >= *bestcount) {
return INT_MAX;
}
if (v < 0) {
return INT_MAX;
}
if (v == 0) {
*bestcount = count_now;
return 0;
}
int min_count = INT_MAX;
for (int i = 0; i < n; i++) {
int count = computeChange(cur, v - cur[i], n, count_now+1, bestcount);
if (count < min_count) {
min_count = count + 1;
}
}
return min_count;
}
int bc = INT_MAX;
computeChange(cur, v, n, 0, &bc));
A secondary improvement is to attempt using large coins first
// int count = computeChange(cur, v - cur[i], n, count_now+1, bestcount);
int count = computeChange(cur, v - cur[n-i-1], n, count_now+1, bestcount);
So the below is the code snippet for your problem using memoization and dynamic programming. The complexity is O(Val*numTypesofCoins).
In the end, change[val] will give you the min number of coins for val.
int change [MAX];
int cur[]={1,2,5,10,20,50,100,200};
int n = sizeof(a)/sizeof(int);
int val= //whatever user enters to get the num of coins required.
for (i=0; i <= val; i++) {
change[i] = INT_MAX;
}
for (i=0; i < n; i++) { // change for the currency coins should be 1.
change[cur[i]] = 1;
}
for (i=1; i <= val; i++) {
int min = INT_MAX;
int coins = 0;
if (change[i] != INT_MAX) { // Already got in 2nd loop
continue;
}
for (j=0; j < n; j++) {
if (cur[j] > i) { // coin value greater than i, so break.
break;
}
coins = 1 + change[i - cur[j]];
if (coins < min) {
min = coins;
}
}
change[i] = min;
}
if you have the sum of say x and the coins of denominations say a1, a2, a3, a4..(in decreasing order)
then the answer is simply->
x/a1+(x%a2)/a3+((x%a2)%a3)/a4+...
This should hopefully give the answer
So I was trying to find the largest and 2nd largest integer in an array. So I assisnged it to be the smallest value possible and it seems like it can go below -(2^31).
I tried with value as large as -2^63 and it still work
void findMax1Max2(int m[], int size, int *max1, int *max2)
{
int i;
*max1 = -2147483648;
*max2 = -2147483648;
for (i = 0; i < size; i++)
{
if (m[i] > *max1){
*max2 = *max1;
*max1 = m[i];
}
else if (m[i] > *max2){
*max2 = m[i];
}
}
}
The right way to get the smallest integer value is
#include <limits.h>
int val = INT_MIN;
Regarding your question you should read this blog post explaining why INT_MIN is defined as -2147483647 - 1 instead of -2147483648.
It's a bit immature, but I have to ask,
The Bytelandian Gold coin problem mentioned here - http://www.codechef.com/problems/COINS/ ,
is said to be typical DP problem,even though I have read basics of DP & recursion, but I am finding hard to understand its solution,
# include <stdio.h>
# include <stdlib.h>
long unsigned int costArray[30][19];
unsigned int amount;
unsigned int currentValue(short int factor2,short int factor3)
{
int j;
unsigned int current = amount >> factor2;
for(j=0;j<factor3;j++)
current /= 3;
return current;
}
long unsigned int findOptimalAmount(short int factor2,short int factor3)
{
unsigned int n = currentValue(factor2,factor3);
if(n < 12)
{
costArray[factor2][factor3] = n;
return (long unsigned int)n;
}
else
{
if(costArray[factor2][factor3] == 0)
costArray[factor2][factor3] = (findOptimalAmount(factor2+1,factor3) + findOptimalAmount(factor2,factor3+1) + findOptimalAmount(factor2+2,factor3));
return costArray[factor2][factor3];
}
}
int main()
{
int i,j;
while(scanf("%d",&amount) != EOF)
{
for(i=0;i<30;i++)
for(j=0;j<19;j++)
costArray[i][j] = 0;
printf("%lu\n",findOptimalAmount(0,0));
}
return 0;
}
Like how does its recursion works? How is costArray size is decided to be 30x19?
Also how can I improve my thinking for such problems solving?
Thanks!
your explanation is correct. But the important point here is still unexplained. Here is what f(n) is defined to be
max{ f(n) , f(n/2) + f(n/3) + f(n/4) }
whichever is maximum is the solution for f(n). Digging little further, for all n < 12 f(n) is greater than f(n/2) + f(n/3) + f(n/4). This will become the stopping condition for the recursion. Though at first the above expression may seem a trivial recursion, Its implementation would lead to very inefficient algorithm(reason for not getting accepted on spoj).
We have to some how store the intermediate values of function f such a way that part of the recursive implementation would become lookup of the stored values.
Unfortunately straight storage of the values like memoziation of fibbonaci series would not work for this example. Because in the given program n can reach 1000000000 and we can not create an array of size 1000000000. So here is the clever trick, instead of storing the value of the subproblem directly for every n. We know that n is subdivided by 2(max 30 times) and 3(max 20 times) at every stage(division by 4 is just division by 2 twice), So we will consider a matrix of size 30x20 where an element at index i,j denote the value of n when divided with i times by 2 and j times by 3. This way the given problem f(n) transforms to F(0,0). Now we apply recursion on F and use memoization of the value of n at every stage.
#include<stdio.h>
#define max2(a, b) ((a) > (b) ? (a) : (b))
unsigned long long ff[30][20] = {0};
unsigned long long n = 0;
/* returns value of n when divided by nthDiv2 and nthDiv3 */
unsigned long long current(int nthDiv2, int nthDiv3)
{
int i = 0;
unsigned long long nAfterDiv2 = n >> nthDiv2;
unsigned long long nAfterDiv2Div3 = nAfterDiv2;
for (i = 0; i < nthDiv3; i++)
nAfterDiv2Div3 /= 3;
return nAfterDiv2Div3;
}
unsigned long long F(int nthDiv2, int nthDiv3)
{
/* if the value of n when divided by nthDiv2 and nthDiv3 is already calculated just return it from table */
if (ff[nthDiv2][nthDiv3] != 0)
return ff[nthDiv2][nthDiv3];
else {
//calculate the current value of n when divided by nthDiv2 and nthDiv3 => F(nthDiv2, nthDiv3)
unsigned long long k1 = current(nthDiv2, nthDiv3);
if (k1 < 12) /* terminating condition */
return k1;
unsigned long long t = F(nthDiv2 + 1, nthDiv3) + F(nthDiv2, nthDiv3 + 1) + F(nthDiv2 + 2, nthDiv3);
/* Maximum of F(nthDiv2, nthDiv3) and F(nthDiv2 + 1, nthDiv3) + F(nthDiv2, nthDiv3 + 1) + F(nthDiv2 + 2, nthDiv3) */
return ff[nthDiv2][nthDiv3] = max2(k1 , t);
}
}
int main()
{
int i, j;
while (scanf("%llu", &n) != EOF) {
/* Every testcase need new Memoization table */
for (i = 0; i < 30; i++)
for (j = 0; j < 20; j++)
ff[i][j] = 0;
printf("%llu\n", F(0, 0));
}
return 0;
}
Thank you all for your comment!
Answering it for my understanding,
this,
costArray[factor2][factor3] = (findOptimalAmount(factor2+1,factor3) + findOptimalAmount(factor2,factor3+1) + findOptimalAmount(factor2+2,factor3));
is just a fancy way of putting,
cost = optimalAmount(n/2) + optimalAmount(n/3) + optimalAmount(n/4);
recursively, until base condition - amount < 12 is met,
& the values are stored in an array (30x20, maximum factors that are possible for 1000000000 ~ 2^30 ~ 3^20, thanks Pavel & Picarus), & all are added to get final value.
plus num>>1 is num/2 , num>>2 is num/4 & so on, (in currentValue()).
A newbie's explanation, you are welcome to edit!
Guess I'll just have to practice more.
Here's my version for this problem using c#:
class MainBytelandian
{
//Temp Global variables
private static List<int> FinalCollectionofCoins = new List<int>();
static void Main()
{
string TempEntry = string.Empty;
int TempNumber;
Console.WriteLine("Welcome to Bytelandian gold coins program"); // Welcome message
Console.WriteLine("Please provide your Bytelandian gold coin"); // Input
int.TryParse(TempEntry = Console.ReadLine(), out TempNumber);
ExchangeGoldCoins(TempNumber);
Console.WriteLine("{0}", FinalCollectionofCoins.Sum());
Console.Read();
}//End of main()
static void ExchangeGoldCoins(int GoldCoin)
{
int SumOfExchangedCoins = (GoldCoin / 2) + (GoldCoin / 3) + (GoldCoin / 4);
if (SumOfExchangedCoins > GoldCoin)
{
ExchangeGoldCoins(GoldCoin / 2);
ExchangeGoldCoins(GoldCoin / 3);
ExchangeGoldCoins(GoldCoin / 4);
}
else //If it's not more add its value to the final collection and return empty list
{
FinalCollectionofCoins.Add(GoldCoin);
}
}
}
I have a problem, then given some input number n, we have to check whether the no is factorial of some other no or not.
INPUT 24, OUTPUT true
INPUT 25, OUTPUT false
I have written the following program for it:-
int factorial(int num1)
{
if(num1 > 1)
{
return num1* factorial(num1-1) ;
}
else
{
return 1 ;
}
}
int is_factorial(int num2)
{
int fact = 0 ;
int i = 0 ;
while(fact < num2)
{
fact = factorial(i) ;
i++ ;
}
if(fact == num2)
{
return 0 ;
}
else
{
return -1;
}
}
Both these functions, seem to work correctly.
When we supply them for large inputs repeatedly, then the is_factorial will be repeatedly calling factorial which will be really a waste of time.
I have also tried maintaining a table for factorials
So, my question, is there some more efficient way to check whether a number is factorial or not?
It is wasteful calculating factorials continuously like that since you're duplicating the work done in x! when you do (x+1)!, (x+2)! and so on.
One approach is to maintain a list of factorials within a given range (such as all 64-bit unsigned factorials) and just compare it with that. Given how fast factorials increase in value, that list won't be very big. In fact, here's a C meta-program that actually generates the function for you:
#include <stdio.h>
int main (void) {
unsigned long long last = 1ULL, current = 2ULL, mult = 2ULL;
size_t szOut;
puts ("int isFactorial (unsigned long long num) {");
puts (" static const unsigned long long arr[] = {");
szOut = printf (" %lluULL,", last);
while (current / mult == last) {
if (szOut > 50)
szOut = printf ("\n ") - 1;
szOut += printf (" %lluULL,", current);
last = current;
current *= ++mult;
}
puts ("\n };");
puts (" static const size_t len = sizeof (arr) / sizeof (*arr);");
puts (" for (size_t idx = 0; idx < len; idx++)");
puts (" if (arr[idx] == num)");
puts (" return 1;");
puts (" return 0;");
puts ("}");
return 0;
}
When you run that, you get the function:
int isFactorial (unsigned long long num) {
static const unsigned long long arr[] = {
1ULL, 2ULL, 6ULL, 24ULL, 120ULL, 720ULL, 5040ULL,
40320ULL, 362880ULL, 3628800ULL, 39916800ULL,
479001600ULL, 6227020800ULL, 87178291200ULL,
1307674368000ULL, 20922789888000ULL, 355687428096000ULL,
6402373705728000ULL, 121645100408832000ULL,
2432902008176640000ULL,
};
static const size_t len = sizeof (arr) / sizeof (*arr);
for (size_t idx = 0; idx < len; idx++)
if (arr[idx] == num)
return 1;
return 0;
}
which is quite short and efficient, even for the 64-bit factorials.
If you're after a purely programmatic method (with no lookup tables), you can use the property that a factorial number is:
1 x 2 x 3 x 4 x ... x (n-1) x n
for some value of n.
Hence you can simply start dividing your test number by 2, then 3 then 4 and so on. One of two things will happen.
First, you may get a non-integral result in which case it wasn't a factorial.
Second, you may end up with 1 from the division, in which case it was a factorial.
Assuming your divisions are integral, the following code would be a good starting point:
int isFactorial (unsigned long long num) {
unsigned long long currDiv = 2ULL;
while (num != 1ULL) {
if ((num % currDiv) != 0)
return 0;
num /= currDiv;
currDiv++;
}
return 1;
}
However, for efficiency, the best option is probably the first one. Move the cost of calculation to the build phase rather than at runtime. This is a standard trick in cases where the cost of calculation is significant compared to a table lookup.
You could even make it even mode efficient by using a binary search of the lookup table but that's possibly not necessary given there are only twenty elements in it.
If the number is a factorial, then its factors are 1..n for some n.
Assuming n is an integer variable, we can do the following :
int findFactNum(int test){
for(int i=1, int sum=1; sum <= test; i++){
sum *= i; //Increment factorial number
if(sum == test)
return i; //Factorial of i
}
return 0; // factorial not found
}
now pass the number 24 to this function block and it should work. This function returns the number whose factorial you just passed.
You can speed up at least half of the cases by making a simple check if the number is odd or even (use %2). No odd number (barring 1) can be the factorial of any other number
#include<stdio.h>
main()
{
float i,a;
scanf("%f",&a);
for(i=2;a>1;i++)
a/=i;
if(a==1)
printf("it is a factorial");
else
printf("not a factorial");
}
You can create an array which contains factorial list:
like in the code below I created an array containing factorials up to 20.
now you just have to input the number and check whether it is there in the array or not..
#include <stdio.h>
int main()
{
int b[19];
int i, j = 0;
int k, l;
/*writing factorials*/
for (i = 0; i <= 19; i++) {
k = i + 1;
b[i] = factorial(k);
}
printf("enter a number\n");
scanf("%d", &l);
for (j = 0; j <= 19; j++) {
if (l == b[j]) {
printf("given number is a factorial of %d\n", j + 1);
}
if (j == 19 && l != b[j]) {
printf("given number is not a factorial number\n");
}
}
}
int factorial(int a)
{
int i;
int facto = 1;
for (i = 1; i <= a; i++) {
facto = facto * i;
}
return facto;
}
public long generateFactorial(int num){
if(num==0 || num==1){
return 1;
} else{
return num*generateFactorial(num-1);
}
}
public int getOriginalNum(long num){
List<Integer> factors=new LinkedList<>(); //This is list of all factors of num
List<Integer> factors2=new LinkedList<>(); //List of all Factorial factors for eg: (1,2,3,4,5) for 120 (=5!)
int origin=1; //number representing the root of Factorial value ( for eg origin=5 if num=120)
for(int i=1;i<=num;i++){
if(num%i==0){
factors.add(i); //it will add all factors of num including 1 and num
}
}
/*
* amoong "factors" we need to find "Factorial factors for eg: (1,2,3,4,5) for 120"
* for that create new list factors2
* */
for (int i=1;i<factors.size();i++) {
if((factors.get(i))-(factors.get(i-1))==1){
/*
* 120 = 5! =5*4*3*2*1*1 (1!=1 and 0!=1 ..hence 2 times 1)
* 720 = 6! =6*5*4*3*2*1*1
* 5040 = 7! = 7*6*5*4*3*2*1*1
* 3628800 = 10! =10*9*8*7*6*5*4*3*2*1*1
* ... and so on
*
* in all cases any 2 succeding factors inf list having diff=1
* for eg: for 5 : (5-4=1)(4-3=1)(3-2=1)(2-1=1)(1-0=1) Hence difference=1 in each case
* */
factors2.add(i); //in such case add factors from 1st list " factors " to " factors2"
} else break;
//else if(this diff>1) it is not factorial number hence break
//Now last element in the list is largest num and ROOT of Factorial
}
for(Integer integer:factors2){
System.out.print(" "+integer);
}
System.out.println();
if(generateFactorial(factors2.get(factors2.size()-1))==num){ //last element is at "factors2.size()-1"
origin=factors2.get(factors2.size()-1);
}
return origin;
/*
* Above logic works only for 5! but not other numbers ??
* */
}
I'm trying to write the first 10 terms of the Fibonacci sequence. I feel like I'm on the right line, but I can't seem to quite grasp the actual code (in C).
float fib = 0;
const float minn = 1;
const float maxn = 20;
float n = minn;
while (n <= maxn);{
n = n + 1;
printf (" %4,2f", fib);
fib = (n - 1) + (n - 2);
}
With the fibonacci sequence the value f(n) = f(n - 1) + f(n = 2). the first three values are defined as 0, 1, 1.
The fibonacci sequence is a sequence of integer values (math integers, not necessarily C language values). consider using int or long for the fibonacci value. float is worthless, it only adds unneeded overhead.
when calculating the fibonacci sequence you must store the previous 2 values to get the next value.
you want 10 fibonacci values. you know the first three already so print those and then calculate the next seven values.
7 values implies a loop that iterates 7 times. it has no bearing on the maximum value of the fibonacci value returned, just how many values you want to print.
do something like this:
printf("0, 1, 1");
int currentValue;
int valueN1 = 1;
int valueN2 = 1;
for (int counter = 1; counter <= 7; ++counter)
{
currentValue = valueN1 + valueN2;
printf(", %d", currentValue);
valueN2 = valueN1;
valueN1 = currentValue;
}
You need run loop 10 times only,to find first 10 terms of the Fibonacci sequence.
in your code,while loop would not let you go further because of semicolon at the end of loop
//declare fib value as long int or unsigned int
// because the value of any fib term is not at all
long int fib;
int n=1;
while (n <= 10)
{
printf (" %d", fib);
fib = fib_term(n);
n = n + 1;
}
implement fib_term(int n); by seeing this snippet
First off, I would suggest changing your datatype from a float to an integer or other datatype. floats are not exact numbers and if you had used while (n = maxn) instead of while (n <= maxn) you could have ended up with an infinite loap since the two floats would never have matched.
Second, you don't seem to really understand what the fibonacci sequence is. Take a look at the wikipedie article http://en.wikipedia.org/wiki/Fibonacci_number.
The fibinocci number is NOT (n - 1) + (n - 2) like you have. It is the sum of the previous two numbers in the sequence. You need to restructure your loop to hold the last two values and calculate the next one based on these values.
There are (at least) 2 ways to implement the Fibonacci Algorithm in C:
The Iterative:
int fib(int n){
if (n == 0)
return 0;
int a = 1
int b = 1;
for (int i = 3; i <= n; i++) {
int c = a + b;
a = b;
b = c;
}
return b;
}
The Recursive:
unsigned int fibonacci_recursive(unsigned int n)
{
if (n == 0)
{
return 0;
}
if (n == 1) {
return 1;
}
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
void main(){
unsigned int i = fibonacci_recursive(10);
}
Suggestions
Consider integer types before FP types when doing integer problems.
Omit a ; in your while (n <= maxn);{
Use a . in floating point formats %4.2f instead of %4,2f.
Fibonacci is the sum of the previous 2 terms, not simply fib = (n - 1) + (n - 2).
Consider an unsigned solution:
C code:
void Fibonacci_Sequence(unsigned n) {
const unsigned minn = 1;
const unsigned maxn = 20;
unsigned F[3];
F[0] = 0;
F[1] = 1;
unsigned i = 0;
for (i = 0; i <= maxn; i++) {
if (i >= minn) printf(" %u,", F[0]);
F[2] = F[1] + F[0];
F[0] = F[1];
F[1] = F[2];
}
}
This uses n/2 iterations
#include<stdio.h>
main()
{
int i,n,a=0,b=1,odd;
scanf("%d",&n);
odd=n%2;
for(i=1;i<=n/2;i++)
{
printf("%d %d ",a,b);
a=a+b;
b=a+b;
}
if(odd)
printf("%d",a);
}