Algorithm to print all permutations with repetition of numbers - algorithm

I have successfully designed the algorithm to print all the permutations with the repetition of numbers. But the algorithm which I have designed has a flaw. It works only if the chars of the string are unique.
Can someone help me out in extending the algorithm for the case where chars of the string may not be unique..
My code so far :
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iostream>
using namespace std;
void _perm(char *arr, char*result, int index)
{
static int count = 1;
if (index == strlen(arr))
{
cout << count++ << ". " << result << endl;
return;
}
for (int i = 0; i < strlen(arr); i++)
{
result[index] = arr[i];
_perm(arr, result, index + 1);
}
}
int compare(const void *a, const void *b)
{
return (*(char*)a - *(char*)b);
}
void perm(char *arr)
{
int n = strlen(arr);
if (n == 0)
return;
qsort(arr, n, sizeof(char), compare);
char *data = new char[n];
_perm(arr, data, 0);
free(data);
return;
}
int main()
{
char arr[] = "BACD";
perm(arr);
return 0;
}
I am printing the output strings in lexicographically sorted way.
I am referring to the example.3 from this page.
http://www.vitutor.com/statistics/combinatorics/permutations_repetition.html
Thanks.

Your code doesn't print permutations, but four draws from the string pool with repetition. It will produce 4^4 == 256 combinations, one of which is "AAAA".
The code Karnuakar linked to will give you permutations of a string, but without distinguishing between the multiple occurrences of certain letters. You need some means to prevent recursing with the same letter in each recursion step. In C++, this can be done with a set.
The example code below uses a typical C string, but uses the terminating '\0' to detect the end. The C-string functions from <cstring> are not needed. The output will not be sorted unless the original string was sorted.
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
void perm(char *str, int index = 0)
{
std::set<char> used;
char *p = str + index;
char *q = p;
if (*p == '\0') {
std::cout << str << std::endl;
return;
}
while (*q) {
if (used.find(*q) == used.end()) {
std::swap(*p, *q);
perm(str, index + 1);
std::swap(*p, *q);
used.insert(*q);
}
q++;
}
}
int main()
{
char arr[] = "AAABB";
perm(arr);
return 0;
}
This will produce 5! == 120 permutations for "ABCDE", but only 5! / (2! 3!) == 10 unique permutations for "AAABB". It will also create the 1260 permutations from the linked exercise.

Related

Why is this not counting correctly?

I am reading text from a text file and need to know the number of characters in the file in total. I thought this should work but it always seems to be overcounting. For example I typed this into my text file:
thisisatestthisisa
thisisa
And the program returned a total of 32.
#include <iostream>
#include <fstream>
#include <string>
#include <ostream>
using namespace std;
int main() {
fstream inFile;
string inputString;
inFile.open("text.txt", ios::in);
unsigned int total = 0;
if (inFile) {
while (inFile)
{
getline(inFile, inputString);
unsigned int tempStringLength = inputString.length();
total += tempStringLength;
}
cout << "total is: " << total << endl;
}
else {
cerr << "Unable to open file text.txt";
exit(1);
}
return 0;
}
You are double-counting the last line in the file.
Because you are using while(inFile) instead of while(getline(inFile, inputString)) the stream's state is not invalidated until the call to getline(...):
Walking through the loop will make this obvious:
Iteration 1:
unsigned int total = 0;
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: True, inputString: thisisatestthisisa
unsigned int tempStringLength = inputString.length(); //18
total += tempStringLength; //18
}
//...
Iteration 2:
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: True, inputString: thisisa
unsigned int tempStringLength = inputString.length(); //7
total += tempStringLength; //25
}
//...
Iteration 3:
//...
while (inFile) //True
{
getline(inFile, inputString); //inFile: EOF, inputString: thisisa (not modified)
unsigned int tempStringLength = inputString.length(); //7
total += tempStringLength; //32
}
//...
inFile now returns false because the EOF was reached and your loop terminates. Printing 32 as the length.
Long story short: Don't use the file state as a loop terminator. Use the actual read, either getline or operator>> depending on the situation.

Recursive algorithm to find all possible solutions in a nonogram row

I am trying to write a simple nonogram solver, in a kind of bruteforce way, but I am stuck on a relatively easy task. Let's say I have a row with clues [2,3] that has a length of 10
so the solutions are:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$-
$$-----$$$
-$$----$$$
--$$---$$$
---$$--$$$
----$$-$$$
-$$---$$$-
--$$-$$$--
I want to find all the possible solutions for a row
I know that I have to consider each block separately, and each block will have an availible space of n-(sum of remaining blocks length + number of remaining blocks) but I do not know how to progress from here
Well, this question already have a good answer, so think of this one more as an advertisement of python's prowess.
def place(blocks,total):
if not blocks: return ["-"*total]
if blocks[0]>total: return []
starts = total-blocks[0] #starts = 2 means possible starting indexes are [0,1,2]
if len(blocks)==1: #this is special case
return [("-"*i+"$"*blocks[0]+"-"*(starts-i)) for i in range(starts+1)]
ans = []
for i in range(total-blocks[0]): #append current solutions
for sol in place(blocks[1:],starts-i-1): #with all possible other solutiona
ans.append("-"*i+"$"*blocks[0]+"-"+sol)
return ans
To test it:
for i in place([2,3,2],12):
print(i)
Which produces output like:
$$-$$$-$$---
$$-$$$--$$--
$$-$$$---$$-
$$-$$$----$$
$$--$$$-$$--
$$--$$$--$$-
$$--$$$---$$
$$---$$$-$$-
$$---$$$--$$
$$----$$$-$$
-$$-$$$-$$--
-$$-$$$--$$-
-$$-$$$---$$
-$$--$$$-$$-
-$$--$$$--$$
-$$---$$$-$$
--$$-$$$-$$-
--$$-$$$--$$
--$$--$$$-$$
---$$-$$$-$$
This is what i got:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef std::vector<bool> tRow;
void printRow(tRow row){
for (bool i : row){
std::cout << ((i) ? '$' : '-');
}
std::cout << std::endl;
}
int requiredCells(const std::vector<int> nums){
int sum = 0;
for (int i : nums){
sum += (i + 1); // The number + the at-least-one-cell gap at is right
}
return (sum == 0) ? 0 : sum - 1; // The right-most number don't need any gap
}
bool appendRow(tRow init, const std::vector<int> pendingNums, unsigned int rowSize, std::vector<tRow> &comb){
if (pendingNums.size() <= 0){
comb.push_back(init);
return false;
}
int cellsRequired = requiredCells(pendingNums);
if (cellsRequired > rowSize){
return false; // There are no combinations
}
tRow prefix;
int gapSize = 0;
std::vector<int> pNumsAux = pendingNums;
pNumsAux.erase(pNumsAux.begin());
unsigned int space = rowSize;
while ((gapSize + cellsRequired) <= rowSize){
space = rowSize;
space -= gapSize;
prefix.clear();
prefix = init;
for (int i = 0; i < gapSize; ++i){
prefix.push_back(false);
}
for (int i = 0; i < pendingNums[0]; ++i){
prefix.push_back(true);
space--;
}
if (space > 0){
prefix.push_back(false);
space--;
}
appendRow(prefix, pNumsAux, space, comb);
++gapSize;
}
return true;
}
std::vector<tRow> getCombinations(const std::vector<int> row, unsigned int rowSize) {
std::vector<tRow> comb;
tRow init;
appendRow(init, row, rowSize, comb);
return comb;
}
int main(){
std::vector<int> row = { 2, 3 };
auto ret = getCombinations(row, 10);
for (tRow r : ret){
while (r.size() < 10)
r.push_back(false);
printRow(r);
}
return 0;
}
And my output is:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$--
$$-----$$$
-$$-$$$----
-$$--$$$--
-$$---$$$-
-$$----$$$-
--$$-$$$--
--$$--$$$-
--$$---$$$
---$$-$$$-
---$$--$$$
----$$-$$$
For sure, this must be absolutely improvable.
Note: i did't test it more than already written case
Hope it works for you

why the constraints reduce the accepted test cases

this is a code i wrote to solve a problem on HackerRank "Recursive Digit Sum"
https://www.hackerrank.com/challenges/recursive-digit-sum
,the code suppose to take two digits as inputs (n,k) to calculate the super digit p.
p is created when k is concatenated n times thats if, k=148 and n=3
p=148148148
sumdigit(P) = sumdigit(148148148)
= sumdigit(1+4+8+1+4+8+1+4+8)
= sumdigit(39)
= sumdigit(3+9)
= sumdigit(12)
= sumdigit(1+2)
= sumdigit(3)
= 3.
the Constraints
1<=n<10^(100000)
1<=k<=10^5
#include <stdio.h>
#include <math.h>
unsigned long int SumDigits(unsigned long int i) {
if (i < 10) {
return i;
}
else {
return i%10 + SumDigits(i/10);
}
}
int main() {
unsigned long int n,k,pos=0;
scanf("%ld %ld",&k,&n);
/**i would put the constraint however it reduces the accepted test cases*/
// if(k>=1&&k<pow(10,100000)&&n>=1&&n<pow(10,5)){
for(unsigned long int i=0;i<n;i++){
pos+=k;
k=k*( unsigned long int)pow(10,n);
}
while(pos>=10){
pos=SumDigits(pos);
}
printf("%ld\n",pos);
//}
return 0;
}

vector accessing non zero elements but output as zero

I' did this program what suppose save pairs of string ,int on one vector and print the strings of the maximum number on vector
but when i try to find this strings don't appears nothing so I try print all values of int's on vector and although was finding the maximum of 10 all values in the vector was printing as 0. Someone can explain was it occurred and how I can access the values , please.
#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef vector<pair<string,int>> vsi;
bool paircmp(const pair<string,int>& firste,const pair<string,int>& seconde );
int main(int argc, char const *argv[]) {
vsi v(10);
string s;
int n,t;
cin>>t;
for (size_t i = 0;i < t;i++) {
for (size_t j = 0; j < 10; j++) {
cin>>s>>n;
v.push_back(make_pair(s,n));
}
sort(v.begin(),v.end(),paircmp);
int ma=v[v.size()-1].second;
cout<<ma<<endl;
for (size_t j = 0; j < 10; j++) {
cout << v.at(j).second <<endl;
if(v[j].second == ma)
cout<<v[j].first<<endl;
}
}
return 0;
}
bool paircmp(const pair<string,int>& firste,const pair<string,int>& seconde ){
return firste.second < seconde.second;
}
This line
vsi v(10);
creates you a std::vector filled with 10 default-constructed std::pair<std::string, int>s. That is, an empty string and zero.
You then push_back other values to your vector but they happen to be sorted after those ten initial elements, probably because they all have positive ints in them.
Therefore, printing the first member of the first ten elements prints ten empty strings.
This is all I can guess from what you have provided. I don't know what you are trying to accomplish with this code.
Try something like
for (const auto& item : v)
{
std::cout << "{ first: '" << item.first << "', "
<< "second: " << item.second << " }\n";
}
to print all elements of the vector v.

All of the option to replace an unknown number of characters

I am trying to find an algorithm that for an unknown number of characters in a string, produces all of the options for replacing some characters with stars.
For example, for the string "abc", the output should be:
*bc
a*c
ab*
**c
*b*
a**
***
It is simple enough with a known number of stars, just run through all of the options with for loops, but I'm having difficulties with an all of the options.
Every star combination corresponds to binary number, so you can use simple cycle
for i = 1 to 2^n-1
where n is string length
and set stars to the positions of 1-bits of binary representations of i
for example: i=5=101b => * b *
This is basically a binary increment problem.
You can create a vector of integer variables to represent a binary array isStar and for each iteration you "add one" to the vector.
bool AddOne (int* isStar, int size) {
isStar[size - 1] += 1
for (i = size - 1; i >= 0; i++) {
if (isStar[i] > 1) {
if (i = 0) { return true; }
isStar[i] = 0;
isStar[i - 1] += 1;
}
}
return false;
}
That way you still have the original string while replacing the characters
This is a simple binary counting problem, where * corresponds to a 1 and the original letter to a 0. So you could do it with a counter, applying a bit mask to the string, but it's just as easy to do the "counting" in place.
Here's a simple implementation in C++:
(Edit: The original question seems to imply that at least one character must be replaced with a star, so the count should start at 1 instead of 0. Or, in the following, the post-test do should be replaced with a pre-test for.)
#include <iostream>
#include <string>
// A cleverer implementation would implement C++'s iterator protocol.
// But that would cloud the simple logic of the algorithm.
class StarReplacer {
public:
StarReplacer(const std::string& s): original_(s), current_(s) {}
const std::string& current() const { return current_; }
// returns true unless we're at the last possibility (all stars),
// in which case it returns false but still resets current to the
// original configuration.
bool advance() {
for (int i = current_.size()-1; i >= 0; --i) {
if (current_[i] == '*') current_[i] = original_[i];
else {
current_[i] = '*';
return true;
}
}
return false;
}
private:
std::string original_;
std::string current_;
};
int main(int argc, const char** argv) {
for (int a = 1; a < argc; ++a) {
StarReplacer r(argv[a]);
do {
std::cout << r.current() << std::endl;
} while (r.advance());
std::cout << std::endl;
}
return 0;
}

Resources