I'm working on a solution to a variant of the subset sum problem, using the below code. The problem entails generating subsets of 11 ints from a larger set (superset) and check if it matches a specific value (endsum).
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int endsum = 0, supersetsize = 0, done = 0;
int superset[] = {1,30,10,7,11,27,3,5,6,50,45,32,25,67,13,37,19,52,18,9};
int combo = 0;
int searchForPlayerInArray(int arr[], int player) {
for (int i=0; i<11; i++) {
if (arr[i] == player) {
return 1;
}
}
return 0;
}
int sumOfArray(int arr[]) {
int res = 0;
for (int i=0; i<11; i++) {
res+=arr[i];
}
return res;
}
void printArray(int arr[], int arrSize) {
for (int j=0; j<arrSize; j++) {
printf("%2d ",arr[j]);
}
printf("= %d\n",endsum);
}
void permute(int subset[], int pos, int sspos) {
if (done) { //when a correct solution has been found, stop recursion
return;
}
if (sspos == supersetsize) { // out of possible additions
return;
}
if (pos == 11) { //is the current subset 11 ints long?
int res = sumOfArray(subset);
combo++;
if (res == endsum) { //if the sum of the array matches the wanted sum, print
printArray(subset,11);
done = 1;
}
return;
}
for (int i=sspos; i<supersetsize; i++) {
//assert(pos < 11);
//assert(i+1 <= supersetsize);
subset[pos] = superset[i];
permute(subset,pos+1,i+1);
}
}
int main(void) {
endsum = 110;
supersetsize = 20;
int *arr;
arr = malloc(supersetsize*sizeof(int));
int i;
for (i=0; i<supersetsize; i++) {
arr[i] = 0;
}
permute(arr,0,0);
printf("Combinations: %d",combo);
return 0;
}
Although this solution works for small supersets (<15) it is slow and inefficient because it generates every possible permutation instead of just the unique ones. How can I optimize it to generate only unique subsets?
Edit: Complete source code added by popular demand.
One way to only generate unique subsets is to add the elements from the superset in order, and use an additional argument to permute (eg. supersetPos) to indicate where you are in the superset. This generates sorted permutations which will be unique.
EDIT: Code that AFAIK runs correctly on your sample:
#include <stdio.h>
int superset[] = {
1, 30, 10, 7, 11,
27, 3, 5, 6, 50,
45, 32, 25, 67, 13,
37, 19, 52, 18, 9
};
int supersetsize = 20;
int endsum = 110;
int done = 0;
int sumOfArray(int array[]) {
int sum = 0;
for(int i = 0; i < 11; i++)
sum += array[i];
return sum;
}
void permute(int subset[], int pos, int sspos) {
if (pos == 11) { //is the current subset 11 ints long?
if (sumOfArray(subset) == endsum) { //if the sum of the array matches the wanted sum, print
for (int j=0; j<11; j++) {
printf("%d ",subset[j]);
}
printf("\n");
done = 1;
}
return;
}
for (int i=sspos; i<supersetsize; i++) {
subset[pos] = superset[i];
permute(subset,pos+1,i+1);
if (done) { //when a correct solution has been found, stop recursion
return;
}
}
}
int main() {
int subset[11] = {0};
permute(subset, 0, 0);
}
I don't think there is a way to generate the unique subsets in better than exponential time.
To solve subset-sum efficiently you want to use dynamic programming. There are some pseudo-polynomial time algorithms for subset-sum that work this way. This Wikipedia article might help.
you can try my code ( I tried to only give a psudo code and not to solve your homework completely):
// array is all the numbers you are looking from them
// length is the number of arrays
// pos is the position of the slot you are going to fill
// max is nomber of slots you have to fill (in your case since you are going for the 11 sets you have to set this value as 11
// sum is the sum of all the values selected until now
// searchbegin is the first element you can pick from your array (I'm using this variable to only generate subarrays of the superset (array))
// target is the targetvalue you are looking for.
void generate_all(int []array, int length, int pos,int max, int sum,int searchbegin,int target)
{
if max = pos
if sum = target
printselectedresults();
for i:searchbegin->length-max+pos
if (sum + array[i] < target)
{
addtoresults(i);
generate_all(array,length,pos+1,max,sum+array[i],i+1,target);
removefromresults(i);
}
}
with all this information I think you can easily Implement this code your target language and use it.
in my function all the permutations generated are subarrays of superset so no permutation can be generated twice, and also every one is generated at least one time.
Related
Im trying set an array to have always same value in first position, but idk how to do that. for example array[10] always array[0] = 100, then continue add ohters number like: array[100,1,2,3.....], loop array[100,1,2,3.....] etc.
int main() {
int arrayNumber[10];
while (true)
{
for (int i = 0; i < 10; i++)
{
arrayNumber[0] = 100;
printf("%d\n", arrayNumber[i]);
Sleep(100);
}
}
}
Set the first value outside the loop and start the loop at 1.
arrayNumber[0] = 100;
for (int i = 1; i < arraysize; i++)
{
arrayNumber[i] = i;
}
int main() {
int arrayNumber[10] = {100};
for (int i = 1; i < 10; i++) {
arrayNumber[i] = i;
}
}
The first operator above declares the array and initializes the first it's element with the value 100, then the loop fills other elements with 1, 2, 3, ..., 9.
Since your asked about C++ let introduce C++-like solution below.
#include <numeric>
int main() {
int arrayNumber[10] = {100};
std::iota(arrayNumber + 1, arrayNumber + 10, 1);
}
Here the function iota fills the passed range in the array with sequentially increasing values, starting with 1.
I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other
bool pair(const int array[])
{
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
}
Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?
edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.
I was not trying to compile the code, for the record.
It will do neither:
i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.
If you really cant sort the array (which would be so easy with std::sort) then you can do this:
const int NumCards = 9; // If this is a constant, this definition should occur somewhere.
bool hasPair(const int array[], const int arraySize) {
int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set
// the array elements to 0.
// Iterate over all of the cards in your hand.
for (int i = 0; i < arraySize; i++) {
int myCurrentCard = array[i]; // Get the current card number.
// Increment it in the array.
possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1;
// Or the equivalent to the above in a single line.
possibleCards[array[i]]++; // Increment the card so that you
// count how many of each card is in your hand.
}
for (int i = 0; i < NumCards; ++i) {
// If you want to check for a pair or above.
if (possibleCards[i] >= 2) { return true; }
// If you want to check for exactly a pair.
if (possibleCards[i] == 2) { return true; }
}
return false;
}
This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.
do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array
#include <iostream>
using namespace std;
int* CheckForPairs(int[], int, int&);
int main()
{
int array[ ]= {2, 5, 5, 7, 7};
int nPairsFound = 0;
int* ptrPairs = CheckForPairs(array, 5, nPairsFound);
for(int i(0); i < nPairsFound; i++)
{
cout << ptrPairs[i] << endl;
}
if(ptrPairs)
{
delete[] ptrPairs;
ptrPairs = NULL;
}
return 0;
}
int* CheckForPairs(int array[] , int size, int& nPairsFound)
{
int *temp = NULL;
nPairsFound = 0;
int j = 0;
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
nPairsFound++;
}
temp = new int[nPairsFound];
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
{
temp[j] = i;
j++;
}
}
return temp;
}
You could use a std::unordered_set for a O(n) solution:
#include <unordered_set>
using namespace std;
bool hasMatchingElements(const int array[], int arraySize) {
unordered_set<int> seen;
for (int i = 0; i < arraySize; i++) {
int t = array[i];
if (seen.count(t)) {
return true;
} else {
seen.insert(t);
}
}
return false;
}
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.
You need a nested for loop:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int unsortedArray[] = {2,3,2,4,5};
int size = 5;
for(int i=0;i<size-1;i++)
{ for(int j=i+1;j<size;j++)
{ if(unsortedArray[i]==unsortedArray[j])
{ printf("matching cards found\n");
return 0;
}
}
}
printf("matching cards not found\n");
return 0;
}
----EDIT------
Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:
#include <iostream>
#include <stdio.h>
#include <stdbool.h>
#defin NUM_CARDS 52;
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int N,i,j;
cin>>N;
int unsortedArray[N];
for(int i=0;i<N;i++)
cin>>unsortedArray[i];
int count[NUM_CARDS]={0};
int cnt = 0;
for( i=0;i<N-1;i++)
{
for( j=i+1;j<N;j++)
{ if(unsortedArray[i]==-1)
break;
if(unsortedArray[i]==unsortedArray[j])
{
unsortedArray[j]=-1;
cnt++;
}
}
if(unsortedArray[i]!=-1)
{
count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
// determine the poker hand.
if(cnt==1)
cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else if(cnt>=2)
cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else
cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;
cnt = 0;
}
}
I am trying to write some c++ code that is a demo for a formula but using Recursion.
Here is my program and the error it throws.
Environment - Visual Studio 2012
Compilation - Successful
Runtime Exception -
Run-Time Check Failure #2 - Stack around the variable 'inputNumbers' was corrupted.
Code -
#include <stdlib.h>
#include <iostream>
using namespace std;
int FindNumber(int Numbers[],int index,int sum, int count)
{
if(count == 0)
return sum;
else if (count == 1)
{
sum -= Numbers[index-1];
index = index -1;
count = count-1;
return sum = FindNumber(Numbers,index,sum,count);
}
else
{
sum += Numbers[index-1];
index = index -1;
count = count-1;
return sum = FindNumber(Numbers,index,sum,count);
}
}
void main()
{
int inputNumbers[50]; //declare the series of numbers
int cnt = 0; //define and initailize an index counter for inserting the values in number series.
int position = 7; //defines the position of the number in the series whose value we want to find.
// insert the number series values in the int array.
for (int i = 1; i < 51; i++)
{
inputNumbers[cnt] = i;
cnt++;
inputNumbers[cnt] = i;
cnt++;
}
cnt=0;
for (int i = 1; i < 51; i++)
{
cout<<inputNumbers[cnt]<<endl;
cnt++;
cout<<inputNumbers[cnt]<<endl;
cnt++;
}
// set another counter variable to 3 since formula suggests that we need to substrat 3 times from the nth position
// Formula : nth = (n-1)th + (n-2)th - (n-3)th
cnt = 3;
int FoundNumber = 0;
//Check if position to be found is greater than 3.
if(position>3)
{
FoundNumber = FindNumber(inputNumbers,position,FoundNumber,cnt);
cout<< "The number found is : " << FoundNumber<< endl;
}
else
{
cout<<"This program is only applicable for finding numbers of a position value greater than 3..."<<endl;
}
}
The entire program is working perfect as per the logic I expect and gives proper output when i debug it but throw exception while exiting the main() after execution is complete.
I see i am doing a really silly but an intricate memory management mistake[and cannot find it].
Any help is appreciated.
Aren't you filling twice the size of the array here?
for (int i = 1; i < 51; i++)
{
inputNumbers[cnt] = i;
cnt++;
inputNumbers[cnt] = i;
cnt++;
}
For an array of length 50 you cannot access beyond element 49; so code should be like:
int inputNumbers[50]; //declare the series of numbers
int cnt = 0; //define and initailize an index counter for inserting the values in number series.
// insert the number series values in the int array.
for (int i = 0; i < 50; i++)
{
inputNumbers[cnt] = i;
cnt++;
}
And indeed as in the previous answer you probably want to increment cnt only once.
#include <cstdio>
#include <ctime>
int populate_primes(int array[])
{
const int max = 1000000;
char numbers[max+1];
int count=1;
array[0]=2;
for(int i=max;i>0;i-=2)numbers[i]=0;
for(int i=max-1;i>0;i-=2)numbers[i]=1;
int i;
for(i=3;i*i<=max;i+=2){
if(numbers[i]){
for(int j=i*i;j<max+1;j+=i)numbers[j]=0; array[count++]=i;
}
}
int limit = max/2;
for(;i<limit;i++) if(numbers[i])array[count++]=i;
return count;
}
int factorize(int number,int array[])
{
int i=0,factor=1;
while(number>0){
if(number%array[i]==0){
factor++;
while(number%array[i]==0)number/=array[i];
}
i++;
}
printf("%d\n",factor);
return factor;
}
int main()
{
int primes[42000];
const int max = 1000000;
int factors[max+1];
clock_t start = clock();
int size = populate_primes(primes);
factorize(1000,primes);
printf("Execution time:\t%lf\n",(double)(clock()-start)/CLOCKS_PER_SEC);
return 0;
}
I am trying to find the no. of factors using simple algo. The populate primes part is running okay , but the factorize part does not execute and gives the floating point exception error.
Please see the code and tell my mistake.
In your factorize method you access array[0], because the initial value of i is 0.
This array is the primes array which is populated by populate_primes. But populates prime doesn't write to primes[0], since the initial value of count is 1.
Thus the first element is not initialized and you probably get a div by 0 error.
You need to pass the size which you got from populate to factorize.
factorize(int number, int array[], int size);
problem is your array[] is not fully loaded, it is loaded only till size variable. So you may want to check for that.
Also the logic inside factorize is wrong. You need to check (number > 1) rather than (number >0).
Try with the function below to see some problems:
#define MAX_PRIMES 42000
int factorize(int number,int array[])
{
int i=0,factor=1;
for (i=0; number>0 && i< MAX_PRIMES; i++){
if (array[i] == 0 || array[i] == 1) {
printf("Error: array[%d] = %d\n", i, array[i]);
} else {
if(number%array[i]==0){
factor++;
while(number%array[i]==0 && number>0) {
printf("%d %d\n", number, array[i]);
number/=array[i];
}
}
}
}
printf("%d\n",factor);
return factor;
}
A book I have says this:
a) Place each value of the one-dimensional array into a row of the bucket array based on the value's ones digit. For example, 97 is placed in row 7, 3 is placed in row 3, and 100 is placed in row 0. This is called a "distribution pass."
b) Loop through the bucket array row by row, and copy the values back to the original array. This is called a "gathering pass." The new order of the preceding values in the one-dimensional array is 100, 3, and 97.
c) Repeat this process for each subsequent digit position.
I am having a lot of trouble trying to understand and implement this. So far I have:
void b_sort(int sarray[], int array_size) {
const int max = array_size;
for(int i = 0; i < max; ++i)
int array[i] = sarray[i];
int bucket[10][max - 1];
}
I'm thinking that in order to sort them by ones, tens, hundreds, etc, I can use this:
for(int i = 0; i < max; ++i)
insert = (array[i] / x) % 10;
bucket[insert];
where x = 1, 10, 100, 1000, etc. I am totally lost on how to write this now.
Here's a bucket sort based on the info in the OP question.
void b_sort(int sarray[], int array_size) {
const int max = array_size;
// use bucket[x][max] to hold the current count
int bucket[10][max+1];
// init bucket counters
for(var x=0;x<10;x++) bucket[x][max] = 0;
// main loop for each digit position
for(int digit = 1; digit <= 1000000000; digit *= 10) {
// array to bucket
for(int i = 0; i < max; i++) {
// get the digit 0-9
int dig = (sarray[i] / digit) % 10;
// add to bucket and increment count
bucket[dig][bucket[dig][max]++] = sarray[i];
}
// bucket to array
int idx = 0;
for(var x = 0; x < 10; x++) {
for(var y = 0; y < bucket[x][max]; y++) {
sarray[idx++] = bucket[x][y];
}
// reset the internal bucket counters
bucket[x][max] = 0;
}
}
}
Notes Using a 2d array for the bucket wastes a lot of space... an array of queues/lists usually makes more sense.
I don't normally program in C++ and the above code was written inside the web browser, so syntax errors may exist.
The following code uses hex digits for a bucket sort (for BITS_PER_BUCKET=4). Ofcourse it is meant to be instructive, not productive.
#include <assert.h>
#include <stdio.h>
#define TEST_COUNT 100
#define BITS_PER_BUCKET 4
#define BUCKET_COUNT (1 << BITS_PER_BUCKET)
#define BUCKET_MASK (BUCKET_COUNT-1)
#define PASS_COUNT (8*sizeof(int)/BITS_PER_BUCKET)
int main(int argc, char** argv) {
printf("Starting up ...");
assert((PASS_COUNT*BITS_PER_BUCKET) == (8*sizeof(int)));
printf("... OK\n");
printf("Creating repeatable very-pseudo random test data ...");
int data[TEST_COUNT];
int x=13;
int i;
for (i=0;i<TEST_COUNT;i++) {
x=(x*x+i*i) % (2*x+i);
data[i]=x;
}
printf("... OK\nData is ");
for (i=0;i<TEST_COUNT;i++) printf("%02x, ",data[i]);
printf("\n");
printf("Creating bucket arrays ...");
int buckets[BUCKET_COUNT][TEST_COUNT];
int bucketlevel[BUCKET_COUNT];
for (i=0;i<BUCKET_COUNT;i++) bucketlevel[i]=0;
printf("... OK\n");
for (i=0;i<PASS_COUNT;i++) {
int j,k,l;
printf("Running distribution pass #%d/%d ...",i,PASS_COUNT);
l=0;
for (j=0;j<TEST_COUNT;j++) {
k=(data[j]>>(BITS_PER_BUCKET*i)) & BUCKET_MASK;
buckets[k][bucketlevel[k]++]=data[j];
l|=k;
}
printf("... OK\n");
if (!l) {
printf("Only zero digits found, sort completed early\n");
break;
}
printf("Running gathering pass #%d/%d ...",i,PASS_COUNT);
l=0;
for (j=0;j<BUCKET_COUNT;j++) {
for (k=0;k<bucketlevel[j];k++) {
data[l++]=buckets[j][k];
}
bucketlevel[j]=0;
}
printf("... OK\nData is ");
for (l=0;l<TEST_COUNT;l++) printf("%02x, ",data[l]);
printf("\n");
}
}
a rewrite of Louis's code in C++11 with STL queues.
void bucket_sort(vector<int>& arr){
queue<int> buckets[10];
for(int digit = 1; digit <= 1e9; digit *= 10){
for(int elem : arr){
buckets[(elem/digit)%10].push(elem);
}
int idx = 0;
for(queue<int>& bucket : buckets){
while(!bucket.empty()){
arr[idx++] = bucket.front();
bucket.pop();
}
}
}
}