Here is my function for Combinatorics Combinations.
For example: combinations "ABCD", 2 = AB AC AD BC BD CD.
In future, i will do some operations with each combination(not just printf).
I wonder, is there a way to improve perfomance of this code?
#include "stdafx.h"
#include "iostream"
#include <vector>
void display(std::vector<char> v, int* indices, int r)//f() to display combinations
{
for (int i = 0; i < r; ++i)
std::cout << v[indices[i]];
std::cout << std::endl;
}
void combinations(std::vector<char> v, int n, int r, void(*f)(std::vector<char>, int*, int))
{
int* indices = new int[r];
for (int i = 0; i < r; ++i)
indices[i] = i;
int count;
bool b;
f(v, indices, r);
while (true)
{
b = true;
for (count = r - 1; count >= 0; --count)
{
if (indices[count] != count + n - r)
{
b = false;
break;
}
}
if (b)
break;
++indices[count];
for (int i = count + 1; i < r; ++i)
indices[i] = indices[i - 1] + 1;
f(v, indices, r);
}
delete[] indices;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<char> v(4);//pool
v[0] = 'A';
v[1] = 'B';
v[2] = 'C';
v[3] = 'D';
int n = 4;// pool size
int r = 2;// length of each combination
combinations(v, n, r, display);// pool, pool size, len of combination, func for each combination
return 0;
}
Maybe not performance but readability is also important.
See a solution in recursion.
http://cpp.sh/2jimb
#include <iostream>
#include <string>
typedef unsigned int uint;
typedef std::string::iterator seq_iterator;
std::string FindCombinations(seq_iterator current, seq_iterator end, uint comb_length, std::string comb)
{
if (comb_length == 0 || comb_length > std::distance(current, end))
return comb;//no more possible combinations
auto next = current + 1;
std::string with;
if (std::distance(next, end) >= comb_length - 1)
with = FindCombinations(next, end, comb_length - 1, comb + *current);//use current in combination
std::string without;
if (std::distance(next, end) >= comb_length)
without = FindCombinations(next, end, comb_length, comb);//skip current in combination
std::string result = with;
if (!result.empty() && !without.empty())
result += ' ';
return result + without;
}
int main()
{
std::string seq = "ABCDE";
std::cout << FindCombinations(seq.begin(), seq.end(), 2, "") << std::endl;
}
Related
I want to write a method in C++ which creates an array of monotonically increasing values. It has the inputs of int begin, int end, int interval.
In this example; method should return the array of [0,1,2,3,4,5,6,7,8,9,10]. When I print the results it should print out the first two indexes and get 0 and 1. However, when I print it, it gives 0 for the first one and 9829656 for the second one.
When I only print one index it is always correct, but when I print more than one index, every value except for the first printed one gives a different result. I think the other results are related to memory address since I used pointers.
#include <iostream>
using namespace std;
int* getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
int result[11] = {};
for (int i = 0; i <= len - 1; i++) {
result[i] = begin + interval * i;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
int* newResult = getIntervalArray(begin, end, interval);
cout << newResult[0] << endl;
cout << newResult[1] << endl;
return 0;
}
You are returning a pointer to a local variable. You can instead return a std::vector by value as shown below:
#include <iostream>
#include <vector>
//return a vector by value
std::vector<int> getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
std::vector<int> result(len); //create a vector of size len
for (int i = 0; i <= len - 1; i++) {
result.at(i) = begin + interval * i;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
std::vector<int> newResult = getIntervalArray(begin, end, interval);
//print out elements of returned vector
for(int i = 0; i < newResult.size(); ++i)
{
std::cout << newResult.at(i) << std::endl;
}
return 0;
}
The output of the above program can be seen here.
A possible solution dynamically allocating the local array, and returning it via a smart pointer:
#include <array>
#include <iostream>
#include <memory> // make_unique
auto getIntervalArray(int begin, int end, int interval)
{
int len = (end - begin) / interval + 1;
auto result{ std::make_unique<std::array<int, 11>>() };
for (int i = 0; i <= len - 1; i++) {
(*result)[i] = begin + interval * i;
}
return result;
}
int main()
{
int begin = 0;
int end = 10;
int interval = 1;
auto newResult{ getIntervalArray(begin, end, interval) };
std::cout << (*newResult)[0] << std::endl;
std::cout << (*newResult)[1] << std::endl;
std::cout << (*newResult)[2] << std::endl;
return 0;
}
Demo
Set the array variable in your function as static. This is because C++ does not support returning the address of a local variable.
static int result[11];
try this. also add deletion of the newResult
#include <iostream>
using namespace std;
int* getIntervalArray(int begin, int end, int interval){
int len = (end - begin) / interval + 1;
int* result = new int[len];
int lastValue = begin;
for (int i = 0; i <= len - 1; i++) {
result[i] = lastValue;
lastValue += interval;
}
return result;
}
int main(){
int begin = 0;
int end = 10;
int interval = 1;
int* newResult = getIntervalArray(begin, end, interval);
cout << newResult[0] << endl;
cout << newResult[1] << endl;
// add delete here.
return 0;
}
I have been practicing median search algorithm, and this is what I wrote-
#include <iostream>
#include <stdlib.h>
using namespace std;
int S1[10] = { 0 };
int S2[1] = { 0 };
int S3[10] = { 0 };
int mediansearch(int A[], int k, int size)
{
int ran = rand() % size;
int i = 0;
int a = 0;
int b = 0;
int c = 0;
for (i = 0; i < size; i++)
{
if (A[ran] > A[i])
{
S1[a] = A[i];
a++;
}
else if (A[ran] == A[i])
{
S2[b] = A[i];
b++;
}
else
{
S3[c] = A[i];
c++;
}
}
if (a <= k)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
}
int main()
{
int arr[] = { 6, 5, 4, 8, 99, 74, 23 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = mediansearch(arr, 5, n);
cout << "5th smallest is:" << x << endl;
}
And I have been getting output as-
Process returned -1073741676 (0xC0000094) execution time : 1.704 s
So, what am I doing wrong? Any kind of help will be appreciated.
There are a few issues with this code, the first one being the naming of variables.
I suggest you choose more significative names in the future, because good naming is fundamental when someone else has to understand your code and your ideas.
Another thing is that the arguments of are in a counterintuitive order because the pair related to the array are separated by the index you want to look for.
I'd write int mediansearch(int A[], int size, int k)
Here the comparisons are reversed, k should be less than rather than greater than equal a
if (a <= k) // (k < a)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k) // (k < a + b)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
The other thing is that you're sharing S1, S2, and S3 among all the recursive calls and that causes some error that I wasn't able to identify, maybe someone commenting will help me out.
However, I suggest you read this article that explains in detail the procedure you're trying to implement: https://rcoh.me/posts/linear-time-median-finding/
It's python, but it can be easily ported to C/C++, and in fact that's what I did.
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
using namespace std;
int medianSearch(int A[], int size, int k)
{
int *lows = (int *)calloc(size, sizeof(int));
int lowsLen = 0;
int *highs = (int *)calloc(size, sizeof(int));
int highsLen = 0;
int *pivots = (int *)calloc(size, sizeof(int));
int pivotsLen = 0;
int median;
int pivot;
int i;
if (size == 1)
return A[0];
// Other ways of randomly picking a pivot
// pivot = 0;
// pivot = size-1;
// pivot = size/2;
assert(size > 0);
pivot = rand() % size;
for (i = 0; i < size; ++i)
{
if (A[i] < A[pivot])
{
lows[lowsLen] = A[i];
lowsLen++;
}
else if (A[i] > A[pivot])
{
highs[highsLen] = A[i];
highsLen++;
}
else
{
pivots[pivotsLen] = A[i];
pivotsLen++;
}
}
if (k < lowsLen)
median = medianSearch(lows, lowsLen, k);
else if (k < lowsLen + pivotsLen)
median = A[pivot];
else
median = medianSearch(highs, highsLen, k - lowsLen - pivotsLen);
free(lows);
free(highs);
free(pivots);
return median;
}
int compare(const void *a, const void *b)
{
return ( *(int *)a - *(int *)b );
}
int medianSorted(int A[], int size, int k)
{
qsort(A, size, sizeof(int), compare);
return A[k];
}
#define N 1000
int main()
{
int arr[N];
int brr[N];
int n = sizeof(arr) / sizeof(arr[0]);
int k = 200;
int x;
int y;
for (int i = 0; i < n; ++i)
arr[i] = brr[i] = rand();
x = medianSearch(arr, n, (k-1)%n);
y = medianSorted(brr, n, (k-1)%n);
string suffix;
switch (k % 10)
{
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0: suffix = "th"; break;
}
cout << k << suffix << " smallest is: " << x << endl;
cout << k << suffix << " smallest is: " << y << endl;
}
https://onlinegdb.com/HJc2V6Lbu
I am writing a C++ program that finds the number of inversions in a vector using merge sort. An inversion happens when the i'th element is greater than the j'th element, where i < j. For example, say the vector is { 1, 3, 5, 2 }, then there are 2 inversions: {3,2} and {5,2}.
The countNsort function keeps recursing and dividing the vector until the length of the subvector is only one element. The countNsortSplit function performs merge sort to sort and count the number of inversions.
I tried:
Different ways of initializing the input vector. vector<int> a{2,1};, vector<int> a; a={2,1};, and vector<int> a(2); a={2,1};.
Different ways of splitting the input vector into subvectors. vector<int> c(a.begin()+half, a.begin()+n); and vector<int> c(a.begin()+half, a.end());, where n is the size of the vector.
Different IDEs. Atoms gives me this: bash: line 1: 13763 Segmentation fault: 11 /tmp/cpp.out [Finished in 20.57s], CodeBlocks gives me this: error: expected expression for this line: a={2,1}:.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortSplit(vector<int> left, vector<int> right, int n) {
returnVal output;
int count = 0;
vector<int> merge;
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (left[i] < right[j]) {
merge[k] = left[i];
i++;
} else {
merge[k] = right[j];
j++;
// increment count by the # of remaining elements in left
count += left.size()-i;
}
}
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a, int n) {
returnVal output;
if (n == 1) {
output.sorted_array = a;
output.count = 0;
return output;
} else {
returnVal left;
returnVal right;
returnVal split;
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
left = countNsort(b, half);
right = countNsort(c, n - half); // need n-n/2 in case of odd length
split = countNsortSplit(left.sorted_array, right.sorted_array, n);
output.sorted_array = split.sorted_array;
output.count = left.count + right.count + split.count;
return output;
}
}
int main() {
vector<int> a(2);
//a = {1,3,5,2};
//a = {1,3,5,2,4,6};
a = {2, 1};
returnVal result;
result = countNsort(a, a.size());
cout << result.count << endl;
}
There are multiple problems in you code:
You do not define the destination vector with the proper size
You do not test if i or j have reached to size of the left and right vectors respectively.
The initializer for vector a in main() has an invalid syntax.
Note that you do not need to pass the vector sizes to countNsort and countNsortSplit.
Here is a corrected version:
#include <iostream>
#include <vector>
using namespace std;
struct returnVal {
int count;
vector<int> sorted_array;
};
returnVal countNsortMerge(vector<int> left, vector<int> right) {
int leftSize = left.size();
int rightSize = right.size();
int n = leftSize + rightSize;
int count = 0;
vector<int> merge(n);
int i = 0;
int j = 0;
for (int k = 0; k < n; k++) {
if (i < leftSize && (j == rightSize || left[i] < right[j])) {
merge[k] = left[i++];
} else {
merge[k] = right[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
returnVal output;
output.sorted_array = merge;
output.count = count;
return output;
}
returnVal countNsort(vector<int> a) {
int n = a.size();
if (n <= 1) {
returnVal output;
output.sorted_array = a;
output.count = 0;
return output;
} else {
int half = n / 2;
vector<int> b(a.begin(), a.begin() + half);
vector<int> c(a.begin() + half, a.begin() + n);
returnVal left = countNsort(b);
returnVal right = countNsort(c);
returnVal result = countNsortMerge(left.sorted_array, right.sorted_array);
result.count += left.count + right.count;
return result;
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
vector<int> a(values, values + sizeof values / sizeof *values);
returnVal result = countNsort(a);
cout << result.count << endl;
return 0;
}
Note however that it would be more efficient and idiomatic to sort the vector in place and return the inversion count:
#include <iostream>
#include <vector>
size_t countNsortMerge(std::vector<int>& a, size_t start, size_t middle, size_t end) {
std::vector<int> temp(a.begin() + start, a.begin() + middle);
size_t i = 0;
size_t leftSize = middle - start;
size_t j = middle;
size_t count = 0;
for (size_t k = start; k < end; k++) {
if (i < leftSize && (j == end || temp[i] < a[j])) {
a[k] = temp[i++];
} else {
a[k] = a[j++];
// increment count by the # of remaining elements in left
count += leftSize - i;
}
}
return count;
}
size_t countNsort(std::vector<int>& a, size_t start, size_t end) {
if (end - start <= 1) {
return 0;
} else {
size_t middle = start + (end - start) / 2;
size_t leftCount = countNsort(a, start, middle);
size_t rightCount = countNsort(a, middle, end);
return leftCount + rightCount + countNsortMerge(a, start, middle, end);
}
}
int main() {
//int values[] = { 1, 3, 5, 2 };
//int values[] = { 2, 1 };
int values[] = { 1, 3, 5, 2, 4, 6 };
std::vector<int> a(values, values + sizeof values / sizeof *values);
size_t result = countNsort(a, 0, a.size());
std::cout << result << std::endl;
return 0;
}
If I want to get the Cartesian Product of these two vector<string>s:
vector<string> final{"a","b","c"};
vector<string> temp{"1","2"};
But I want to put the result in final, such that final would contain:
a1
a2
b1
b2
c1
c2
I'd like to do this without creating a temporary array. Is it possible to do this? If it matters, the order of final is not important.
You may try the following approach
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> final{ "a", "b", "c" };
std::vector<std::string> temp{ "1", "2" };
auto n = final.size();
final.resize( final.size() * temp.size() );
for ( auto i = n, j = final.size(); i != 0; --i )
{
for ( auto it = temp.rbegin(); it != temp.rend(); ++it )
{
final[--j] = final[i-1] + *it;
}
}
for ( const auto &s : final ) std::cout << s << ' ';
std::cout << std::endl;
return 0;
}
The program output is
a1 a2 b1 b2 c1 c2
Try the function cartesian:
#include <vector>
#include <string>
using namespace std;
void cartesian(vector<string>& f, vector<string> &o) {
int oldfsize = f.size();
f.resize(oldfsize * o.size());
for (int i = o.size() - 1; i>=0; i--) {
for (int j = 0; j < oldfsize; j++) {
f[i*oldfsize + j] = f[j] + o[i];
}
}
}
int main()
{
vector<string> f{"a","b","c"};
vector<string> temp{"1","2"};
cartesian(f, temp);
for (auto &s: f) {
printf("%s\n", s.c_str());
}
}
This works for me:
void testCartesianString(vector<string>& final,
vector<string>const& temp)
{
size_t size1 = final.size();
size_t size2 = temp.size();
// Step 1.
// Transform final to : {"a","a","b","b","c","c"}
final.resize(size1*size2);
for ( size_t i = size1; i > 0; --i )
{
for ( size_t j = (i-1)*size2; j < i*size2; ++j )
{
final[j] = final[i-1];
}
}
// Step 2.
// Now fix the values and
// change final to : {"a1","a2","b1","b2","c1","c2"}
for ( size_t i = 0; i < size1; ++i )
{
for ( size_t j = 0; j < size2; ++j )
{
final[i*size2+j] = final[i*size2+j] + temp[j];
cout << final[i*size2+j] << " ";
}
cout << endl;
}
}
This is just a personal preference option to Vald from Moscow's solution. I think it may be faster for dynamic arrays because there would be less branching. But I haven't gotten around to writing a timing test bench.
Given the inputs vector<string> final and vector<string> temp:
const auto size = testValues1.first.size();
testValues1.first.resize(size * testValues1.second.size());
for (int i = testValues1.first.size() - 1; i >= 0; --i){
testValues1.first[i] = testValues1.first[i % size] + testValues1.second[i / size];
}
EDIT:
Nope, this solution is slower not faster: http://ideone.com/e.js/kVIttT
And usually significantly faster, though I don't know why...
In any case, prefer Vlad from Moscow's answer
I have written an implementation of Donald Knuth's Algorithm X for solving exact cover problems and applied it to Sudoku for the purpose of solving Project Euler Problem 96. My code is a translation from Python into C++ of Ali Assaf's implementation of the same algorithm.
My version is solves most of the grids contained in this text file, but it hangs for Grid 06.
Grid 06
100920000
524010000
000000070
050008102
000000000
402700090
060000000
000030945
000071006
I have used a bunch of exploratory cout statements, but I have not been able to figure out what is causing the program to hang.
Please let me know if you need more information to be able to understand my code.
#include <algorithm>
#include <array>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution);
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r);
// square boxes only
static const int BOX_SIZE = 3; // standard sudoku grid
static const int SIZE = BOX_SIZE*BOX_SIZE;
int main() {
int top_left_sum = 0;
// initialize the sparse matrix representation of the sudoku problem
map<int, set<int>> C; // constraints/columns
for (int i = 0; i < 4*SIZE*SIZE; i++) {
C[i] = set<int>();
}
map<int, array<int, 4>> R; // subsets/rows
for (int i = 0; i < SIZE*SIZE*SIZE; i++) {
// i is the subset index and encodes location and number on grid
int index = i/SIZE;
int row = i/(SIZE*SIZE);
int column = (i/SIZE) % SIZE;
int box = BOX_SIZE*(row/BOX_SIZE) + column/BOX_SIZE;
int value = i % SIZE;
// there are 4 constaints satisfied by each number placement
array<int, 4> subset;
// insert the keys of constraints that subset satisfies
subset[0] = (index); // row-column
subset[1] = (SIZE*SIZE + SIZE*row + value); // row-number
subset[2] = (2*SIZE*SIZE + SIZE*column + value); // column-number
subset[3] = (3*SIZE*SIZE + SIZE*box + value); // box-number
R.insert(pair<int, array<int, 4>>(i, subset));
for (auto c : subset) {
C[c].insert(i);
}
}
ifstream ifs("../sudoku.txt");
string line;
while (getline(ifs, line)) {
if (line[0] == 'G') {
map<int, set<int>> X = C;
map<int, array<int, 4>> Y = R;
vector<int> solution;
for (int i = 0; i < SIZE; i++) {
getline(ifs, line);
for (int j = 0; j < SIZE; j++) {
if (line[j] != '0') {
int r = SIZE*SIZE*i + SIZE*j + line[j] - '1';
solution.push_back(r);
vector<set<int>> cs;
select_row(&X, &Y, &cs, r);
}
}
}
solve(&X, &Y, &solution);
sort(solution.begin(), solution.end());
top_left_sum += 100*(solution[0] % SIZE + 1)
+ 10*(solution[1] % SIZE + 1)
+ solution[2] % SIZE + 1;
// display solution
for (size_t i = 0; i < solution.size(); i++) {
if (i % 9 == 0) cout << endl;
cout << solution[i] % 9 + 1 << ' ';
} cout << endl << endl;
}
}
ifs.close();
cout << top_left_sum << endl;
return 0;
}
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
// for each row pointed to by c_min, call solve recursively
for (auto r : (*c_min).second) {
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}
void select_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (auto j : (*Y)[r]) {
for (auto i : (*X)[j]) {
for (auto k : (*Y)[i]) {
if (k != j) (*X)[k].erase(i);
}
}
(*cs).push_back((*X)[j]);
(*X).erase(j);
}
return;
}
void deselect_row(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<set<int>>* cs, int r) {
for (array<int, 4>::reverse_iterator j = (*Y)[r].rbegin();
j != (*Y)[r].rend(); ++j) {
(*X)[*j] = (*cs).back();
(*cs).pop_back();
for (auto i : (*X)[*j]) {
for (auto k : (*Y)[i]) {
if (k != *j) (*X)[k].insert(i);
}
}
}
return;
}
As PaulMackenzie pointed out, the problem with my code was that I was erasing objects which still had pointers to them initialized, specifically the integers inside the set (*c_min).second that I iterate over in my solve function.
I fixed this by making a copy of (*c_min).second and iterating over the copy.
The fixed version of the solve function looks like this:
bool solve(map<int, set<int>>* X, map<int, array<int, 4>>* Y,
vector<int>* solution) {
if ((*X).empty()) return true;
// find the column with the minimum number of nonzero elements
map<int, set<int>>::iterator c_min = (*X).begin();
for (map<int, set<int>>::iterator c = ++(*X).begin();
c != (*X).end(); ++c) {
if ((*c).second.size() < (*c_min).second.size()) {
c_min = c;
}
}
set<int> c = (*c_min).second; // ADDED LINE
// for each row pointed to by c_min, call solve recursively
for (auto r : c) { // CHANGED LINE
(*solution).push_back(r);
vector<set<int>> cs;
select_row(X, Y, &cs, r);
if (solve(X, Y, solution)) return true;
deselect_row(X, Y, &cs, r);
(*solution).pop_back();
}
return false;
}