Finding if 1 vector is included in 2nd vector - c++

I need to write a program that finds out if one of the 2 vector is included in another one.
The program works like this.
1 - Gets the m and n values from input.txt (1st row)
2 - Resizes verctorM and vectorN to m and n, then fills them with numbers from input.txt (2nd row for vectorM, 3rd row for vectorN)
3 - After filling, the program should find out wich one of the vectors has the fewest "characters" by comparing n and m
4 - The program gets the first "character" of "small" vector and start to compare it with the "characters" of "big" vector ()
5 - When the statemant vectorN[i] = vectorM[0] is correct, the program compares the next "characters" if every "character" of "small" vector is in the "big" vector, program output 1, if not continues to compare with 1st "caracter" of "smal" vector, if "small" vector is not included in "big" vector, program outputs 0
Edit - the numbers must be in same order as written in input.txt
Here is the code that I ended up with
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main() {
int m;
int n;
bool y = false;
vector<int> vectorM;
vector<int> vectorN;
ifstream file1;
file1.open("input.txt");
file1 >> m;
file1 >> n;
vectorM.resize(m);
vectorN.resize(n);
for (int i = 0; i < m; i++){
file1 >> vectorM[i];
}
for (int i = 0; i < n; i++){
file1 >> vectorN[i];
}
//this is the part that I need help with
ofstream file2;
file2.open("output.txt");
if (y == false)
file2 << 0;
else
file2 << 1;
}
What's the efficent way to compare the "characters" ??
Example, if in input.txt
4 3
1 2 3 2
1 2 3
Program outputs 1, because 1 2 3 is in 1 2 3 2, but if
2 3
1 2
2 3 1
Program outputs 0

I think you're asking if a contiguous subsequence can be found inside another range of values. The standard library std::search algorithm does just that.
#include <algorithm>
#include <iostream>
#include <vector>
bool included(const std::vector<int>& seq, const std::vector<int>& sub)
{
return std::search(seq.begin(), seq.end(), sub.begin(), sub.end()) != seq.end();
}
int main()
{
auto v1 = std::vector<int>{ 1,2,3,2 };
auto v2 = std::vector<int>{ 1,2,3 };
std::cout << std::boolalpha << included(v1, v2) << '\n';
auto v3 = std::vector<int>{ 1,2 };
auto v4 = std::vector<int>{ 2,3,1 };
std::cout << included(v3, v4) << '\n';
}
Demo on ideone.com
Note: I stole Jarod42's function name and coincoin's test data.

Related

A vector as a patchwork of two other vectors

Subset a vector
Below is the benchmark of two different solutions to subset a vector
#include <vector>
#include <iostream>
#include <iomanip>
#include <sys/time.h>
using namespace std;
int main()
{
struct timeval timeStart,
timeEnd;
// Build the vector 'whole' to subset
vector<int> whole;
for (int i = 0 ; i < 10000000 ; i++)
    {
whole.push_back(i);
}
// Solution 1 - Use a for loops
gettimeofday(&timeStart, NULL);
vector<int> subset1;
subset1.reserve(9123000 - 1200);
for (int i = 1200 ; i < 9123000 ; i++)
{
subset1.push_back(i);
}
gettimeofday(&timeEnd, NULL);
cout << "Solution 1 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl;
// Solution 2 - Use iterators and constructor
gettimeofday(&timeStart, NULL);
vector<int>::iterator first = whole.begin() + 1200;
vector<int>::iterator last = whole.begin() + 9123000;
vector<int> subset2(first, last);
gettimeofday(&timeEnd, NULL);
cout << "Solution 2 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl;
}
On my old laptop, it outputs
Solution 1 took 243564 us
Solution 2 took 164220 us
Clearly solution 2 is faster.
Make a patchwork of two vectors
I would like to create a vector as a patchwork of two different vectors of the same size. The vector starts as one and then takes the value of the other and back and forth. I guess I don't fully understand how to copy values to a vector by using iterator pointing to elements in another vector. The only implementation I can think of requires using an analogous to solution 1 above. Something like...
#include <vector>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <sys/time.h>
#include <limits.h>
using namespace std;
int main()
{
// input
vector<int> breakpoints = {2, 5, 7, INT_MAX};
vector<int> v1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<int> v2 = { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
// Create output
vector<int> ExpectedOutput;
ExpectedOutput.reserve(v1.size());
int origin = 0;
int breakpoints_index = 0;
for (int i = 0 ; i < v1.size() ; i++)
{
if (origin)
{
ExpectedOutput.push_back(v1[i]);
} else
{
ExpectedOutput.push_back(v2[i]);
}
if (breakpoints[breakpoints_index] == i)
{
origin = !origin;
breakpoints_index++;
}
}
// print output
cout << "output: ";
for (int i = 0 ; i < ExpectedOutput.size() ; i++)
{
cout << ExpectedOutput[i] << " ";
}
cout << endl;
return 0;
}
which outputs
output: 10 20 30 4 5 6 70 80 9
It feels like there must be a better solution such as something analogous to Solution 2 from above. Is there a faster solution?
Repeating push_back() means that every time around the loop, a check is being performed to ensure capacity() is large enough (if not, then more space must be reserved). When you copy a whole range, only one capacity() check needs to be done.
You can still be a bit smarter with your interleaving by copying chunks. Here's the very basic idea:
int from = 0;
for( int b : breakpoints )
{
std::swap( v1, v2 );
int to = 1 + std::min( b, static_cast<int>( v1.size() ) - 1 );
ExpectedOutput.insert( ExpectedOutput.end(), v1.begin() + from, v1.begin() + to );
from = to;
}
For the sake of brevity, this code actually swaps v1 and v2 and so always operates on v1. I did the swap before the insert, to emulate the logic in your code (which is acting on v2 first). You can do this in a non-modifying way instead if you want.
Of course, you can see a bit more is going on in this code. It would only make sense if you have considerably fewer breakpoints than values. Note that it also assumes v1 and v2 are the same length.

Cannot determine why output is wrong while rotating vector

I have written the following code -
#include <cassert>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
vector<int> v;
int main()
{
int n, d, i = 0;
cin >> n >> d;
assert(n >= 1 && n <= 100000 && d >= 1 && d <= n);
int temp = 0;
for (int i = 0; i < n; i++)
{
cin >> temp;
v.push_back(temp);
}
reverse(v.begin(), v.begin() + d - 1);
reverse(v.begin() + d, v.end());
reverse(v.begin(), v.end());
for (i = 0; i < n; i++)
cout << v[i] << " ";
return 0;
}
Now, the problem is that when I enter the following input -
5 4
1 2 3 4 5
it doesn't give me the correct output 5 1 2 3 4 but rather gives me this 5 4 1 2 3
Any idea what might be wrong?
The output of the program is correct, for that input. It is your expectations that are incorrect.
The thing to realise is that standard algorithms do not dereference specified end iterators. So reverse(v.begin(), v.begin() + 3) will reverse the first three elements of v (i.e. v[0] through to v[2]) not the first four.
So the first reverse() reverses the first three elements, producing the order 3 2 1 4 5.
To get the results you expect, it would be reversing the first four.

How can I compare line from text file to multiple lines following?

I have a text file with 1s, 2s and 3s like below:
1
1
2
3
3
3
1
2
2
2
2
1
..and I am trying to find a way to find out how many in a row for each.
For example if I was checking 1 it would output:
1 in a row: 2, 2 in a row: 1, 3 in a row: 0, 4 in a row: 0....
all the way to 20 in a row (array size), since there is 2 1s in a row once and then 2 1s by themselves (only 1 in a row)
I am trying to calculate HOW MANY TIMES the number 1 is only 1 in a row, 2 in a row, 3 in a row, etc up to 20 (if i had a longer list)
So far this is what I have, however I don't know what to do at the ??? line:
int main()
{
ifstream file("test.txt");
string linebuffer;
int sequenceCounts[20];
int onez = 0;
while (file && getline(file, linebuffer)){
if (linebuffer.length() == 0)continue;
{
if (linebuffer == "1")
{
??? while the next is 1->onez++
sequenceCounts[onez]++;
}
}
}
return 0;
}
Try something along the lines of this:
int sequenceCounts[20];
int currentOnes = 0;
while (file && getline(file, linebuffer)){
if (linebuffer.length() == 0){
if (currentOnes > 0){
sequenceCounts[currentOnes]++;
}
continue;
}
if (linebuffer == "1")
{
currentOnes++; //We found another 1,
//meaning the current group is bigger than in the last line.
} else if (currentOnes > 0){
//This line does not contain a "1", but the previous lines did
sequenceCounts[currentOnes]++;
currentOnes = 0;
}
}
Basically each time you encounter a "1" you increase a counter how long your current sequence is. When the sequence is finished (a line without a "1" but with "1"s before) you increase the counter for that particular number of "1"s and reset your counter for the current sequence.
Edit: previous failed if the file ended with a "1"
I did this using a vector and a simple map to hold the longest consecutive streak, so you'd merely have to read the lines, parse them to ints, and add them to a vector.
#include <iostream>
#include <cstdlib>
#include <vector>
#include <fstream>
#include <algorithm>
#include <map>
int mostConsec(const std::vector<int> &vec) {
std::map<int, size_t> consecMap;
size_t count = 0;
int current = vec.front();
for (auto i : vec) {
if (consecMap.count(current) == 0)
consecMap[current] = 0;
if (i == current) {
count += 1;
if (consecMap[current] <= count)
consecMap[current] = count;
}
else {
count = 1;
}
current = i;
}
auto ptr = std::max_element(
consecMap.begin(),
consecMap.end(),
[](const std::pair<int, size_t> &p1, const std::pair<int, size_t> &p2) {return p1.second < p2.second; }
);
return ptr->first;
}
int main(int argc, char **argv) {
std::vector<int> v;
std::ifstream inFile("test.txt");
int tmp;
while (inFile >> tmp)
v.push_back(tmp);
inFile.close();
int most = mostConsec(v);
std::cout << most << std::endl;
system("pause");
}

Sort vector by even and odd indices. c++

Is there a one liner (or a simple loop-free) solution to sort a vector by its even and odd indices?
Example:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample(entries, entries + sizeof(entries) / sizeof(long) );
vExample.sortEvenOdd(vExample.begin(),vExample.end()); // magic one liner I wish existed...
for (int i = 0; i < vExample.size(); i++)
{
std::cout << vExample[i] << " ";
}
Now I'd like to have the following output:
0 2 11 1 10 // corresponding to indices 0 2 4 1 3
I tried to do a real one liner:
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
And here is the full program:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> input {0,1,2,10,11};
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
for (auto v : input)
std::cout << v << " ";
}
Ok I know, it works for the sole reason that vector uses a contiguous array of items and the whole thing is dirty... But for that's a one liner as asked by the OP and it doesn't require anything extra like boost...
This is not one liner but pretty close:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample;
for( bool flag : { true, false } ) {
auto cond = [&flag]( long ) { flag = !flag; return !flag; };
std::copy_if( std::begin( entries ), std::end( entries ), std::back_inserter( vExample ), cond );
}
If you can use Boost, this is pretty concise:
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <iostream>
#include <vector>
int main() {
using namespace boost::adaptors;
std::vector<int> input {0,1,2,10,11};
std::vector<int> partitioned;
boost::push_back(partitioned, input | strided(2));
boost::push_back(partitioned, input | sliced(1, input.size()) | strided(2));
for (auto v : partitioned)
std::cout << v << " ";
}
You can of course wrap that in a function to get a one liner in the calling code. Live
I don't like the messy business of fiddling with the addresses that the accepted answer of #fjardon proposes. #Slava's suggestion is much better and combined with the OP's code gives something that works quite well:
int main() {
std::vector<int> vals {0,2,3,-3,8,-5,7,8};
bool flag = true;
std::stable_partition(begin(vals), end(vals), [&flag] (auto el) mutable
{
// toggle flag, return previous value
flag = !flag; return !flag;
});
for (auto v : vals)
std::cout << v << " ";
}
Output: 0 3 8 7 2 -3 -5 8
What you need is stable_partition. Define a predicate which checks whether the index is even using modulo 2, and you are good to go.

Reversing an input from a file (C++)

I'm creating a very basic program that reads in a list of numbers from a text file, prints them in reverse order, then states if that order is the same as the original (like a palendrome).
I have the program able to print in reverse order so far, but I'm not sure how detect if it's the same as the original file. Any help would be greatly appreciated :)
EDIT: Sorry, had to go away. Here's what I have so far. Got it to reverse, just need to check for palindrome. Will read over replies.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
const int ARRYLENGTH=20;
int contnums[ARRYLENGTH];
int contents;
ifstream myFile("problem3.txt");
if(! myFile )
{
cout << "File cannot be found";
exit(EXIT_FAILURE);
}
while(!myFile.eof())
{
myFile>>contents;
for(int i=0;i<ARRYLENGTH;i++)
{
myFile >> contnums[i];
}
}
cout<<contents<<" ";
for (int i = 1; i < ARRYLENGTH; i++)
{
bool same = false;
for (int j = 0; j < i && (same == false); j++){
if (contnums[i] == contnums[j])
same = true;
}
if (!same) {
cout<< contnums[i] << " ";
}
}
cout << "\n";
system("pause");
myFile.close();
}
I just wondered wether comparing 2 lists would work in std library. It works :-)
#include <list>
#include <fstream>
using std::list;
using std::ifstream;
bool foo(const char * fn)
{
list<int> orig;
list<int> rev;
ifstream ifs(fn,std::ifstream::in);
while( ifs.good() && !ifs.eof() )
{
int num =0;
ifs >> num;
orig.push_back(num);
rev.push_front(num);
}
bool equal = (orig == rev);
return equal;
}
static bool test1 = foo("file1.txt");
static bool test2 = foo("file2.txt");
WHERE
file1.txt contains
1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 1 8
and file2.txt contains
1 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 1
Try iterating from begin to end and comparing the values with values of an iterator from end to begin.
If you know how many items you have it could simple be done by:
for(int i = 0; i < count/2; ++i) { //count/2 becouse you only have to check half
if(array[i] != array[count-i-1]) { /*not palindrome */ }
}
//palindrome
Simplest way, but i like #Dave's from comment one better since it ueses STL and iterators in nice way. (As long as you are working on STL container).