I was assigned a project to read a large text file of different articles, and print out the top 10 most frequent words, i managed to remove all unnecessary information from the file and print it into a string, for simplicity i put a small part the list of unigrams and their frequency in a text file (text2.txt), this is essentially the format in which all the unigrams are written: "(unigram)":(it's frequency within that article),"(another unigram)":(it's frequency within that article) and so on
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void something(string input, int sizeOfDoc, string unigrams[], int freq[]){
char found;
char last_found2;
char last_found;
char next_found;
bool b = false;
int pos = 0;
string word;
unsigned int u=0;
unsigned int f=0;
for(int x = 0; x<sizeOfDoc; x++){
found = input.at(x);
if(x==sizeOfDoc){
next_found= '*';
}else{next_found = input.at(x+1);}
if(x==0){
last_found = '*';
}else{last_found = input.at(x-1);}
if(x==0 || x==1){
last_found2 = '*';
}else{last_found2 = input.at(x-2);}
if((last_found2 >= '1' && last_found2 <= '9') && last_found == ',' && found == '\"' && //
(next_found >='a' && next_found <='z' || next_found >='A' && next_found <='Z')){ //finds first letter of unigram
word = next_found; //a
}
else if((found >='a' && found <='z' || found >='A' && found <='Z') && //
(last_found >='a' && last_found <='z' || last_found >='A' && last_found <='Z')){ //finds middle of unigram
word += found; //b abc word = "abc"
}
else if((last_found2 >='a' && last_found2 <='z' || last_found2 >='A' && last_found2 <='Z') //
&& last_found =='"' && found == ':' && (next_found >= '1' && next_found <= '9')){ //finds frequency
word += last_found2; //adds last letter to word
for(int i=0; i <= u; i++){ //
if(word == unigrams[i]){ //
b = true; //
pos = i; //checks for duplicate, if found, returns position to pos
}
}
if (b==false){
unigrams[u] = word; //adds word to unigrams array
freq[f] = next_found; //adds frequency to freq array
}
else if(b == true){ //
freq[pos]=freq[f]; //increments frequency if duplicate found
}
f++;
u++;
}
}
}
int main() {
string unigrams[1279];
int freq[1279];
string s;
std::string newstring;
ifstream file; //
file.open("text2.txt"); //
while (!file.eof()) { //
getline(file, s); //
newstring += s + "\n"; //reads original text and inputs it into newstring
}file.close();
something(newstring, newstring.size(), unigrams, freq); //calls function
for (int x = 0; x <= 1278; x++) { //
cout << unigrams[x]; //prints unigrams to console
}
}
when i run the code it throws
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 1278) >= this->size() (which is 1278)
i have tried using vectors instead of arrays with emplace_back, push_back, and directly assigning, all to no avail, there's much more to work on in the project, submission is tomorrow and the more i progress the more complex it gets ):
this is the text im using:
{"others":1,"air":1,"networks,":1,"conventional":1,"Environ.":1,"AHP":1,"Osterwalder,":1,"la":8,"Non-motorized":1,"(SHE).":1,"beer":1,"[7,8]":1,"provider":1,"futurible":1,"13(4),":1,"Agency":1,"24.":1,"concern":1,"eight":1,"facilitated":1,"2009":1,"review":1,"Car,":4,"viability.":1,"cycles":1,"contribute":1,"results,":1,"design":24,"CSIROPub.9780643094529,":1,"ecodesign":2,"reserves":1,"follow:":1,"sp\u00e9cifique":2,"(2017)[20,21,22].":1,"pp.":4,"Costs":1,"diversity":1,"In-depth":1,"Both":1,"\u2013":6,"Grenoble":1,"realistic":2,"Largepurchasecost:":1,"navale":1,"Est,":1,"petits":1,"Support":1,"eliminated":1,"relationship,":1,"progressed,":1,"Imnm":1,"significantly":2,"76":1,"Technical":1,"Tertre,":1,"(Fig.":1,"Freeman,":1,"(1.28>Ib":1,"IT":2,"defined":1,"maturity":1,"experimentation.":1,"review,":2,"interests":1,"tools":1,"Firm":3,"opportunities.":1,"behaviour":1,"2014":1,"fili\u00e8res":1,"feedback":3,"interviews":1,"60":1,"187":1,"d\u00e9fi":1,"strategies":3,"did":1,"Techniques":8,"In":8,"have":5,"issues.":1,"useful":1,"se":1,"QC,":1,"vision":1,"regarding":1,"take":4,"Brezet,":1,"such":2,"circulaire":1,"software":1,"parameter":9,"appliances":3,"wedging":1,"Prod.":6,"domains\u201d.":1,"typologie,":1,"D\u00e9veloppement":3,"real":1,"desACVcomparatives":1}}
its a sample of one list of unigrams and their frequencies, the formatting is horrible as you can see i had to create a million conditions to take out the words without running into issues caused by things like words with quotation marks within them, the original file has 1500 publications and this text is just a small part of one of them, thank you for reading this at least
Your bug is here, specifically because when you call input.at() the maximum argument should be sizeOfDoc - 1.
for(int x = 0; x<sizeOfDoc; x++){
found = input.at(x);
if(x==sizeOfDoc){
next_found= '*';
}else{next_found = input.at(x+1);}
If you consider the case where x == sizeOfDoc - 1, the last line shown will result in calling at with an argument of sizeOfDoc, which is too high. To fix this, change
if(x==sizeOfDoc){
to
if(x==sizeOfDoc - 1){
Related
This question already has answers here:
Testing stream.good() or !stream.eof() reads last line twice [duplicate]
(3 answers)
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 24 days ago.
I'm currently working on the "Name That Number" USACO training problem.
It takes a number as input and outputs any matching names found in a dictionary using touch tone telephone keymapping.
The full code consistently gets a bad_alloc thrown on the USACO grader. I've been coding in a replit and it runs fine each time. I've also tried commenting out different parts of the code and running it on the USACO grader but sometimes it runs fine and sometimes it gets a bad_alloc thrown. I think it has something to do with my 2d array of vectors but I'm not sure exactly what or how to fix it.
/*
ID:*****
TASK: namenum
LANG: C++14
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
//function that takes letter and returns associated number
int convert(int letter){ //implicit conversion
if (letter < 81){
letter = letter - 65;
}
else {
letter = letter - 66;
}
int modify = letter % 3;
letter = (letter - modify) / 3 + 2;
return letter;
}
int main() {
ifstream numin ("namenum.in");
ifstream dictin ("dict.txt");
ofstream fout ("namenum.out");
//2d array storing vectors that will store matching names for that index
vector<string> names[8][8]{};
//read names in from dict and store in table
while (dictin.good())
{
string name{};
dictin >> name;
if (name[0] != 'Z' && name[1] != 'Z'){
int i = convert(name[0]) - 2;
int j = convert(name[1]) - 2;
names[i][j].push_back(name);
}
}
//read in digits from input
string digits{};
numin >> digits;
//output matches
int index1 = static_cast<int>(digits[0]) - 50;
int index2 = static_cast<int>(digits[1]) - 50;
string output{};
//check for matches
if (index1 >= 0 && index1 <= 8 && index1 >= 0 && index1 <= 8){
for (int i = 0; i < names[index1][index2].size(); i++){
string matchdigits{};
for (int j = 0; j < names[index1][index2][i].length(); j++){
matchdigits += static_cast<char>(convert(names[index1][index2][i][j]) + 48);
}
if (matchdigits == digits){
output = names[index1][index2][i] + "\n";
}
}
}
if (output == ""){
output = "NONE\n";
}
fout << output;
return 0;
}
As you can see from the title I want to change lowercase charachter in word to uppercase and vice versa.
Also I need to use struct object (in my case name).
I have a problem when I change charachter from lowercase to uppercase it only changes in the first word not in the second,third and so on. I am also reading words from file
Here is the input file
Aayak Audi
Ahmed Golf7
Samed Golf5
Here is the code
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
struct pismaStr
{
string ime;
string objekat;
};
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break;
}
}
int main()
{
ifstream pismo;
pismo.open("pismo.txt");
ofstream novoPismo;
novoPismo.open("novaSlova.txt");
pismaStr stvari[200];
int brojStvari = 0;
while(pismo >> stvari[brojStvari].ime >> stvari[brojStvari].objekat)
{
brojStvari++;
}
for (int i = 0; i < brojStvari; i++)
{
vector <pismaStr> vec = {pismaStr{stvari[i].ime}};
for (auto obj : vec)
{
malaVelikaSlova (obj.ime);
}
}
Here is the output:
aayak
ahmed
samed
It was:
Aayak
ahmed
samed
I want it to look like this
aAYAK
sAMED
aHMED
How can I fix this?
Any tips?
Tangential,
but it will be an issue, is this line
for (int i = 0; i < name.length()-1; i++)
This will loop from name[0] to name[name.length() - 2]. The std::string::length returns the number of usable characters. It does not include the null terminator, so you don't need to subtract 1. It should be
for (int i = 0; i < name.length(); i++)
Your bigger problem
is the break statement at the end of your loop (indentation added for clarity)
for (int i = 0; i < name.length()-1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
cout << name;
break; // <--- this exits the loop entirely
}
Your break; tells the program to exit the loop immediately. No further iterations of the loop are performed. Your cout statement is also within the loop. Once you do get the loop running for each iteration, you'll output each step of the transformation. To only output it once (at the end) you put it outside of the loop. If you want to loop over every character (and you do), your final code looks like
void malaVelikaSlova (string name)
{
for (int i = 0; i < name.length() - 1; i++)
{
if (name.at(i) >= 'A' && name.at(i) <= 'Z')
name.at(i) += 32;
else if (name.at(i) >= 'a' && name.at(i) <= 'z')
name.at(i) -= 32;
}
cout << name;
}
Other things you can change
You don't need to do bounds checking on your string indexes, since you're looping based on the string length, and it's not changing, so you don't need to extra overhead of std::string::at. You can just use the index operator:
// name.at(i); // <-- no need to do this anywhere
name[i] // <-- slightly faster
Since you're applying some operation to each element (character) in your container (string), this is a great candidate for std::transform, from the <algorithm> library. I'm also using a lambda expression here, which is a great too from C++ to get familiar with.
https://en.cppreference.com/w/cpp/algorithm/transform
https://en.cppreference.com/w/cpp/language/lambda
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](char c) -> char
{
if (c >= 'A' && c <= 'Z')
return c + 32;
if (c >= 'a' && c <= 'z')
return c - 32;
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
You could even take advantage of the std::isupper, std::islower, std::toupper, and std::tolower functions to make your code more explicit. Note that std::string is an alias for std::basic_string<char> (its value type is char), the upper and lower functions operate on unsigned chars, so you'll need to convert the chars to unsigned chars:
https://en.cppreference.com/w/cpp/string/basic_string
https://en.cppreference.com/w/cpp/string/byte/tolower
https://en.cppreference.com/w/cpp/string/byte/toupper
https://en.cppreference.com/w/cpp/string/byte/isupper
https://en.cppreference.com/w/cpp/string/byte/islower
void malaVelikaSlova (string name)
{
std::transform(
name.begin(),
name.end(),
[](unsigned char c) -> unsigned char // <-- must convert to unsigned to be safe with upper/lower functions
{
if std::isupper(c) return std::tolower(c);
if std::islower(c) return std::toupper(c);
return c; // <-- for all other characters
}
);
std::cout << name << "\n";
}
I am trying to create a for loop that has a conditional statement which reads until an operation is found, ex. (+,-,/,*), but every time I try I get an error:
Unhandled exception at 0x7936F2F6 (ucrtbased.dll) in CIS310 Project 44.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
while (getline(infile, hex))
{
n = hex.length();//find the length of the line
for (i = 0; hex[i] != '/'||'+'||'-'||'*'; i++,++k) //loop to split the first hexadecimal number
h1 = h1 + hex[i];
for (i++; i < n - 1; i++) //loop to get the second hexadecimal number
h2 = h2 + hex[i];
n1 = convertDecimal(h1); //convert the first hexadecimal number to decimal
n2 = convertDecimal(h2);
Your condition hex[i] != '/'||'+'||'-'||'*' is malformed. C++ requires that you specify both sides of the operator each time, so you will need something more similar to hex[i] != '/' || hex[i] != '+' || ....
You have to check after every ' | | '(OR), like:
hex[i] != '/' || hex[i] != '+' || hex[i] != '-' || hex[i] != '*'
This is a similar code to what you wrote:
while(getline(file,line))
{
string firstPart = "";
unsigned int i;
//We can use the algorithm library to search for them but its ok
for(i=0;(line[i] != '+') || (line[i] != '-') || (line[i] != '*') || (line[i] != '/') || (line[i] != '\0');i++ );
firstPart = line.substr(0,i);
}
now if you tried this, it will cause the same error (or atleast similar to it), if we even try to print every character in the loop
for(/*stuff*/)
cout << line[i];
Then notice this will become an infinite loop, the problem is that you're checking the character line[i] if it wasn't a + or - or * or / all at the same time, fix this by changing the || to &&.
I'll suppose that your file (named testfile.txt) has the content below:
0xAB+0xCD
0x11-0x03
Sample working code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream file("testfile.txt");
///Don't forget to check if file has opened
if(!file.is_open())
{
cout << "File didn\'t open :(";
return 0;
}
string line;
while(getline(file,line))
{
string firstPart = "",secondPart = "";
char operation;
unsigned int i;
//We can use the algorithm library to search for them but its ok
for(i=0;(line[i] != '+') && (line[i] != '-') && (line[i] != '*') && (line[i] != '/') && (line[i] != '\0');i++ );
firstPart = line.substr(0,i);
operation = line[i];
secondPart = line.substr(i+1,firstPart.size());
}
file.close();
return 0;
}
I have the following code. It's supposed to count the number of repetitions of the given letter in a given file. However, when i try to run this i get the Vector subscript out of range. Other people with the same error were trying to access undefined parts of it, but this doesn't seem to be an issue here i think.
struct letters
{
char letter;
int repetitions=0;
};
void howManyTimes(const string &output)
{
ifstream file(output);
vector <letters> alphabet;
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
alphabet[i].letter = 'a' + i;
}
string line;
while (file.eof() == 0)
{
getline(file, line);
for (char c : line)
{
if(c >= 'a' && c <= 'z')
alphabet[c - 'a'].repetitions++;
else if (c >= 'A' && c >= 'Z')
alphabet[c - 'A'].repetitions++;
}
}
cout << alphabet[10].repetitions;
}
vector <letters> alphabet; // (1)
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
alphabet[i].letter = 'a' + i; // (2)
}
(1) creates an empty vector.
Inside the for loop in (2) you try to access items using the index i in an empty vector, so clearly your index is out of range.
You first have to populate the vector with some data, then you can access this data.
If you want to add new items to the vector, you can use vector::push_back (which is probably what you meant in (2)).
I don't see the part of your code where alphabet is expanded to accommodate the objects you plan to store in it. std::vector only resizes itself when you use the push_back, insert, emplace or other similar methods; it doesn't do so when accessing directly using the operator[] method.
At any rate, for a task like this, I'm not sure you'd want to use a vector, when a std::map<char, int64_t> would probably be a lot cleaner, and would let you preserve the syntax you're trying to use without tons of extra maintenance.
void howManyTimes(const string &output)
{
ifstream file(output);
map<char, int64_t> alphabet;
string line;
while (getline(file, line))
{
for (char c : line)
{
if(c >= 'a' && c <= 'z')
alphabet[c - 'a']++;
else if (c >= 'A' && c >= 'Z')
alphabet[c - 'A']++;
}
}
cout << alphabet[10];
}
Other people with the same error were trying to access undefined parts of it, but this doesn't seem to be an issue here I think.
It is definitely an issue here:
vector <letters> alphabet; // Now size of the vector is 0.
for (int i = 0; i < 'z' - 'a' + 1; i++)
{
// You are trying to access elements 0, 1, 2, ..., which do not exist.
alphabet[i].letter = 'a' + i;
}
The simplest solution is to construct your vector with appropriate size:
vector <letters> alphabet('z' - 'a' + 1);
This program is really powerful for what the question is asking (makes me wonder how my students felt when I gave it as a homework assignment :) ). Do you have to use a struct? Let's assume not, and also assume we know the size of the alphabet, and that 'a' is the first letter and 'z' is the last letter:
vector<int> repetitions(26, 0);
char nextCharacter;
while( !file.eof() )
{
cin >> nextCharacter;
nextCharacter = tolower(nextCharacter);
if(nextCharacter >= 'a' && nextCharacter <= 'z')
{
repetitions[nextCharacter - 'a']++;
}
}
To check for a letter:
cin >> letterToQuery;
cout <<"The amount of occurrences of " << letterToQuery <<" is ";
cout << repetitions[tolower(letterToQuery) - 'a'] << endl;
If you don't know the size of your alphabet, the code changes to:
vector<int> repetitions('last_alphabet' - 'a' + 1, 0);
...
if(nextCharacter >= 'a' && nextCharacter <= 'last_letter')
And finally, if you DO have to use that struct, your code changes to:
struct Letter
{
char letter;
int repetitions=0;
};
vector<Letter> alphabet;
letter temp;
for(int i = 0; i < 'last_alphabet' - 'a' + 1; ++i)
{
temp.letter = 'a' + i;
alphabet.push_back(temp);
}
// then everything else is a similar structure
char nextCharacter;
while( !file.eof() )
{
cin >> nextCharacter;
nextCharacter = tolower(nextCharacter);
if(nextCharacter >= 'a' && nextCharacter <= 'last_alphabet')
{
alphabet[nextCharacter - 'a'].repetitions++;
}
}
To check for a letter:
cin >> letterToQuery;
cout <<"The amount of occurrences of " << letterToQuery <<" is ";
cout << alphabet[tolower(letterToQuery) - 'a'].repetitions << endl;
Notice, if you replace 'last_alphabet' with 'z', you get the current alphabet.
Hi I'm working a program to unscramble a set of letters and output all the words that can be made from that set of letters, for example: If i inputed the letters "vlei", the program would output "live", "evil", and "vile".
So far I have looked through the internet about this quiiiite a bit and can't find anything on my specific questions relevant to my skill level at this point (level 2 noob).
So far I have gotten as far as making all the possible combinations from the the given letters. Excluding any that are less than 7 letters, which is a problem.
This is the code I have so far:
string letter;
char newWord[7];
int main()
{
cout << "Type letters here: ";
cin >> letter;
for(int i = 0 ; i < 7 ; i++)
{
for(int j = 0 ; j < 7 ; j++)
{
for(int k = 0 ; k < 7 ; k++)
{
for(int l = 0 ; l < 7 ; l++)
{
for(int m = 0 ; m < 7 ; m++)
{
for(int n = 0 ; n < 7 ; n++)
{
for(int o = 0 ; o < 7 ; o++)
{
sprintf(newWord, "%c%c%c%c%c%c%c", letter[i], letter[j], letter[k], letter[l], letter[m], letter[n], letter[o]);
}
}
}
}
}
}
}
return 0;
}
I was wondering if anyone has any experience with anything like this, and can offer and hints or advice.
Specifically what I'm having difficulty with is how to read in a .txt file to use as a dictionary to compare words to.
Also, I was having trouble using strcmp() which is what I was planning to use to compare the scrambled words to the dictionary. So if there are any other maybe simpler ways to compare the two strings, that would be greatly appreciated.
Thanks in advance.
Hi guys, so I've just finished my program and I hope it can help someone else. Thanks a lot for all your help.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <array>
using namespace std;
//declaring variables
int i;
int scores[531811]; //array for scores of found words
string wordlist[531811]; //array for found matched words
string word[531811]; //array of strings for dictionary words about to be read it
string tester;//string for scrambled letters that will be read in
int scorefinder(string scrab) //SCORE FINDER FUNCTION
{
int score = 0;
int x = 0;
int j = 0;
while (scrab[j])
{
char ltr = toupper(scrab[j]); //converts to all caps
//assings values to each letter and adds it to itself
if(ltr == 'A' || ltr == 'E' || ltr == 'I' || ltr == 'L' || ltr == 'N' || ltr == 'O' || ltr == 'R' || ltr == 'S' || ltr == 'T' || ltr == 'U')
x += 1;
else if(ltr == 'D' || ltr == 'G')
x += 2;
else if(ltr == 'B' || ltr == 'C' || ltr == 'M' || ltr == 'P')
x += 3;
else if(ltr == 'F' || ltr == 'H' || ltr == 'V' || ltr == 'W' || ltr == 'Y')
x += 4;
else if(ltr == 'K')
x += 5;
else if(ltr == 'J' || ltr == 'X')
x += 8;
else if(ltr == 'Q' || ltr == 'Z')
x += 10;
++j;
}
score = x;
return score;
}
int main () {
//READS IN DICTIONARY
ifstream file("words.txt"); //reads in dictionary
if (!file.is_open()){ //checks if file is being NOT read correctly
cout << "BROEKN \n"; //prints error message if so
}
if(file.is_open()){ //checks if file IS being read correctly
for(int i = 0; i < 531811; i++){
file >> word[i]; //read in each word from the file and
} //assigns each to it's position in the words array
}
//END OF READ IN DICTIONARY
cout << "Enter scrambled letters: ";
cin >> tester; //reads in scrambled letters
sort(tester.begin(),tester.end()); //sorts scrambled letters for next_permutation
while (next_permutation(tester.begin(),tester.end())){ //while there are still permutations available
for(i=0;i<531811;i++){
if ( is_permutation (word[i].begin(),word[i].end(), tester.begin())){
wordlist[i] = word[i]; //assigns found word to foundword array
scores[i] = scorefinder(word[i]); //assigns found word score to foundscore array
}
}
}
//PRINTS OUT ONLY MATCHED WORDS AND SCORES
for(i=0;i<531811;i++){
if(scores[i]!=0){
cout << "Found word: " << wordlist[i] << " " << scores[i] << "\n";
}
}
}
Well, what you need is some sort of comparison. C++ doesn´t know, what a right word in english is. So you may need a wordlist. Then you can Brutforce(that´s what you´re doing at the moment) until you find a match.
For comparing your brutforced result, you may use a .txt with as many english words as you can find. Then you have to use a FileStream for iterating through every word and comparing it to your brutforce result.
After you sucessfully unscrambled a word, you should think about your solution again. As you can see, you are limited to a specific amount of chars which is not that nice.
This sounds like an interesting Task for a beginner ;)
Suppose you have found a word list in the form of plain text file on the Internet, you may load all the words into a vector for string first.
ifstream word_list_file("word_list.txt");
string buffer;
vector<string> all_words;
while (getline(word_list_file, buffer))
all_words.push_back(buffer);
Then we want to compare the input letters with the each entry of all_words. I suggest using std::is_permutation. It compares two sequence regardless the order. But it can have trouble when the two sequence has different length, so compare the length yourself first.
// Remember to #include <algorithm>
bool match(const string& letters, const string& each_word)
{
if (letters.size() != each_word.size())
return false;
return is_permutation(begin(letters), end(letters), begin(each_word));
}
Note that I have not tested my codes. But that's the idea.
An edit responsing the comment:
In short, just use std::string, not std::array. Or copy my match function directly, and invoke it. This will be easier for your case.
Details:
std::is_permutation can be used with any container and any element type. For example:
#include <string>
#include <array>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int main()
{
//Example 1
string str1 = "abcde";
string str2 = "ecdba";
is_permutation(begin(str1), end(str1), begin(str2));
//Example 2
array<double, 4> array_double_1{ 4.1, 4.2, 4.3, 4.4 };
array<double, 4> array_double_2{ 4.2, 4.1, 4.4, 4.3 };
is_permutation(begin(array_double_1), end(array_double_1), begin(array_double_2));
//Example 3
list<char> list_char = { 'x', 'y', 'z' };
string str3 = "zxy";
is_permutation(begin(list_char), end(list_char), begin(str3));
// Exampl 4
short short_integers[4] = { 1, 2, 3, 4 };
vector<int> vector_int = { 3, 4, 2, 1 };
is_permutation(begin(list_char), end(list_char), begin(str3));
return 0;
}
Example 1 uses std::string as containers of chars, which is exactly how my match function work.
Example 2 uses two arrays of double of size 4.
Example 3 even uses two different kinds of containers, with the same element types. (Have you heard of `std::list'? Never mind, just focus on our problem first.)
Example 4 is even stranger. One container is old style raw array, another is a std::vector. There are also two element types, short and int, but they are both integer. (The exact difference between short and int is not relevant here.)
Yet, all four cases can use is_permutation. Very flexiable.
The flexibility is enabled by the following facts:
is_permutation is not exactly a function. It is a function template, which is a language feature to generate new functions according to the data type you pass to it.
The containers and is_permutation algorithm do not know each other. They communicate through a middleman called "iterator". The begin and end functions together give us a pair of iterators representing the "range" of elements.
It requires more studies to understand these facts. But the general idea is not hard. Also, these facts are also true for other algorithms in the Standard Library.
Try this :
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the string. */
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "vlei";
permute(a, 0, 3);
getchar();
return 0;
}