How to read input to a C++ program in reverse order? - c++

Suppose I give input to a C++ program as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
C++ code:
int n;
for (int i = 0; i < 15; i++)
{
std::cin >> n;
// use the value of n to make changes
}
In the above code I can read the input sequentially,
i.e. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.
Is there any way to read input directly (without using extra memory in C++ program) from the input stream in the following order:
5 4 3 2 1 10 9 8 7 6 15 14 13 12 11
First five digits in reverse order 5 4 3 2 1, next five digits in reverse order 10 9 8 7 6, ...

No.
You need to read the data as they flow into the input stream.
In your program then, you can re-order them in any way you like.

As noted in the comments, the best way to do this is to read them in the order they are given and sort them afterwards.
// vector to hold the values
std::vector<int> values;
values.reserve(15); // reserve for better performance
int n;
for (int i = 0; i < 15; i++)
{
std::cin >> n;
values.push_back(n); // add value to back of vector
}
// sort the vector
std::sort(values.begin(), values.end());
// use the values in ascending order...
for (int i = 0; i < 15; i++) {
std::cout << values[i];
}

Yes this is possible ,but it increase the running time complexity of the code .
First you can make the outer loop for how many series it insert , in the above test case its 3.
Secondly you can make a inner loop which adds the number .
I am not sure the code is running but the logic helps you .
I am implementing the psuedo code using stack !
int n=5;
for(int count = 1 ; count <= 3 ;count++)
{
for(int i=n ; i > n-5 ; i++)
{
push_on_stack(i);
}
n=n+5;
}

You need to wrap your taking input in some functionality that reorders the values for you. You might be able to do so outside the program, i.e., pipe the input stream through another program that reorders the values. Then your code might already work as you have it now.
Or you do this wrapping in your program. For example using a custom stream-like class that buffers the values in between.
There's no way to get this done without using extra memory to buffer the values you don't yet need.
Example:
#include <iostream>
#include <stack>
struct reader {
std::stack<int> data;
reader& operator>>(int & i) {
if (data.empty()) {
while (data.size() < 5) {
data.push(0);
std::cin >> data.top();
}
}
i = data.top();
data.pop();
return *this;
}
explicit operator bool() const { return bool(std::cin); }
};
int main () {
reader r;
int i;
while (r >> i) {
std::cout << i << std::endl;
}
}
Example output:
$ g++ tt.cc -std=c++11 && echo "1 2 3 4 5 6 7 8 9 10" | ./a.out
5
4
3
2
1
10
9
8
7
6
A more straight forward approach would probably be something like this:
#include <iostream>
#include <vector>
int main () {
std::vector<int> buffer;
for (int i; std::cin >> i; ) {
buffer.push_back(i);
if (buffer.size() == 5) {
// do something with buffer
//std::vector<int> reversed(buffer.rbegin(), buffer.rend());
while (!buffer.empty()) {
std::cout << buffer.back() << "\n";
buffer.pop_back();
}
}
}
}

Related

How do I save all the numbers from a string into a multi-dimensional array in c++?

I have to write a program that takes a completed sudoku board, saves only the numbers (meaning all the symbols used between the numbers to separate them such as '-', '|' etc cant be saved) into a two-dimensional array.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int input[11] = { 0 };
int sudoku[9][9] = { 0 };
for (int line = 0; line <= 10; line++)
{
cin >> input[line];
}
system("PAUSE");
return 0;
}
This is the only working code I've got so far. I've tried different kinds of for loops to get this done but I can't figure why it doesn't work.
So I wanted to ask, is it even possible save all the numbers of a string into a multi-dimensional array? And if it's not, where is my approach wrong or how could I solve this task?
One example of the input would be:
.5.1.4.|.8.6.9.|.7.2.3
.8.7.2.|.3.4.5.|.6.1.9
.9.6.3.|.2.1.7.|.5.4.8
-------|-------|-------
.6.2.8.|.1.3.4.|.9.5.7
.1.9.7.|.6.5.2.|.8.3.4
.4.3.5.|.7.9.8.|.1.6.2
-------|-------|-------
.2.4.6.|.9.7.1.|.3.8.5
.7.5.1.|.4.8.3.|.2.9.6
.3.8.9.|.5.2.6.|.4.7.1
One approach is to use regular expressions. This way the formatting of the sudoku board can change but your will still be able to parse out the numbers.
The reason I broke it into two for loops was to easily ignore the row that has no numbers in it.
#include <iostream>
#include <regex>
#include <string>
#include <vector>
int main()
{
std::string line;
// this regular expression matches a single digit
std::regex exp("(\\d)");
std::smatch res;
int sudoku[9][9] = {{0}};
int row = 0;
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
// get a line of the board
std::getline(std::cin, line);
// search for the next digit in the line
for (int k = 0; std::regex_search(line, res, exp); ++k)
{
// convert the digit into an integer and store it in the board
sudoku[row][k] = std::stoi(res[0]);
// the rest of the line after the first match becomes the new
// line so that we can search for the next digit
line = res.suffix();
}
row += 1;
}
// ignore every third row that is used to separate the board sections
std::getline(std::cin, line);
}
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 9; ++j)
{
std::cout << sudoku[i][j] << " ";
}
std::cout << std::endl;
}
return 0;
}
For your example board, it produces this output:
5 1 4 8 6 9 7 2 3
8 7 2 3 4 5 6 1 9
9 6 3 2 1 7 5 4 8
6 2 8 1 3 4 9 5 7
1 9 7 6 5 2 8 3 4
4 3 5 7 9 8 1 6 2
2 4 6 9 7 1 3 8 5
7 5 1 4 8 3 2 9 6
3 8 9 5 2 6 4 7 1

How to find a sequence of size k(or more) of people that are friends with each other?

I am trying to solve a problem that was given at an exam in a university in my country. It gives me as input a file that contains on the first line 3 numbers:
The first one(n) represents the number of people
The second one(m) represents the number of friendships between people
The third one(k) is the size of the sequence(but the sequence doesn't have to be exactly as large as this number, it can be bigger)
...and on the second line the relations(m pairs of numbers with the form (a, b) meaning a is friend with b and b is friend with a).
The task is to find the sequence with the maximum length(which is at least k people) in which people are friends with each other as efficiently as possible. If there is no such sequence "NO" will be printed.
Their examples:
data.txt:
5 5 3
1 2 5 1 3 2 4 5 1 4
output:
1 4 5
data.txt:
5 5 4
1 2 5 1 3 2 4 5 1 4
output:
No
data.txt:
11 18 3
1 8 4 7 7 10 11 10 2 1 2 3 8 9 8 3 9 3 9 2 5 6 5 11 1 4 10 6 7 6 2 8 11 7 11 6
output.txt:
2 3 6 7 8 9 10 11
My approach
Friendships in this case can be represented with an undirected graph (for me at least this seems the most logical data structure to use) where vertices represent people and edges represent friendships. To be part of the sequence a vertex needs to have a degree greater than or equal to k - 1.
And that's where I stop. Currently all I can do is eliminate the nodes that don't have a degree of at least k - 1:
#include <iostream>
#include <fstream>
#include <vector>
#include <utility>
#include <algorithm>
std::ifstream f{ "data.txt" };
constexpr size_t LIMIT = 101;
// graph[i][j]: i is friend with j
// short to avoid vector<bool> specialization
std::vector<std::vector<short>> graph(LIMIT, std::vector<short>(LIMIT, 0));
std::vector<int> validNodes;
int numOfNodes, numOfRelationships, sequenceSize;
void Read()
{
f >> numOfNodes >> numOfRelationships >> sequenceSize;
int a;
int b;
for(int i = 1; i <= numOfRelationships; ++i) {
f >> a >> b;
graph[a][b] = graph[b][a] = 1;
}
}
int Degree(int node)
{
int result = 0;
for(int i = 1; i <= numOfNodes; ++i) {
if(i != node && graph[node][i] == 1) {
++result;
}
}
return result;
}
void KeepValidNodes()
{
for(int i = 1; i <= numOfNodes; ++i) {
if(Degree(i) < sequenceSize - 1) {
// Don't add the node to validNodes vector
// "Remove it from the graph" aka it's not friend with anyone
// all nodes that were friends with it now have a lower degree, remove them from the validNodes vector if that's the case
for(int j = 1; j <= numOfNodes; ++j) {
auto findPos = std::find(validNodes.begin(), validNodes.end(), j);
if(findPos != validNodes.end() && Degree(j) - 1 < sequenceSize - 1) {
*findPos = -1;
}
graph[i][j] = graph[j][i] = 0;
}
}
else {
validNodes.push_back(i);
}
}
}
void PrintSequence()
{
bool empty = true;
for(const int& node : validNodes) {
if(node != -1) {
empty = false;
std::cout << node << std::endl;
}
}
if(empty) {
std::cout << "No" << std::endl;
}
}
int main()
{
Read();
KeepValidNodes();
PrintSequence();
}
This works only for their first 2 examples. The only possible solution that I could think of is generating all possible combinations of nodes and see which one satisfies the requirements. How can I solve this problem efficiently as they say?
EDIT:
I am not necessarily looking for a fully working code but I don't even know how I could approach this problem.
Your problem is about finding a clique of size k or smaller. I don't know if there are any algorithms capable of doing that, but there are certainly algorithms able to find maximum size clique. Once you find the maximum size clique (let's call it n-clique) in your graph, finding a clique of size <= n reduces to extracting a subset of vertices from n-clique.
There is no polynomial time algorithm for the general case because this problem is NP-complete, so don't expect awesome results. This answer containts a short list of algorithms that will solve this problem quicker than brute-force algorithm. You should also take a look at Karp's paper on problem reducibility if you want to learn a little more about it (even if you don't apply this concept to that problem, it's worth reading because many solutions to NP-complete problems rely on reduction).

Read integer data from a file

I am just getting started on C++ and am working on codeval questions, so if anyones done that, they'll recognize this problem as it's the first on the list. I need to open a file that has 3 columns of space separated integer values. Here is mine, under fizbuz.txt. I need to get the integer values from the file and store them for later use elsewhere in the program.
1 2 10
3 5 15
4 5 20
2 8 12
2 4 10
3 6 18
2 3 11
8 9 10
2 5 8
4 9 25
Now I can open the file just fine, and I've used getline() to read the files just fine using my below code. However, I don't want them in string format, I'd like them as integers. So I looked around and everyone basically says the same notation (file>>int1>>int2...). I've written some code exactly how I've seen it in a few examples, and it does not behave at all like they're telling me it should.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string filename = "fizbuz.txt";
string line;
int d1,d2,len;
int i =0;
int res1[10], res2[10], length[10];
ifstream read (filename.c_str());
if (read.is_open())
{
// while(read>>d1>>d2>>len);
// {
// res1[i] = d1;
// res2[i] = d2;
// length[i] = len;
// i++;
// }
while (!read.eof())
{
read>>d1>>d2>>len;
res1[i] = d1;
res2[i] = d2;
length[i] = len;
}
read.close();
}
else
{
cout << "unable to open file\n";
}
for (int j = 0; j < 10;j++)
{
cout<< res1[j] << " " << res2[j] << " " << length[j] << '\n';
}
}
Both of the while loops perform the same in the output function at the bottom. The last line of fizbuz.txt will be returned to the first elements of res1,res2 and length, and the remaining elements of all 3 are psuedorandom values, presumably from whatever program was using that memory block before. ex output below
4 9 25
32767 32531 32767
-1407116911 4195256 -1405052128
32531 0 32531
0 0 1
0 1 0
-1405052128 807 -1404914400
32531 1 32531
-1405054976 1 -1404915256
32531 0 32531
The first version should work except that you need to remove the ; in the while line.
while (read >> d1 >> d2 >> len);
^
Try this
while (!read.eof())
{
read>>d1>>d2>>len;
res1[i] = d1;
res2[i] = d2;
length[i] = len;
i++;
}

Reading variable size 2D-STL vector from file

2
1 3
2 4 8 13
3 5 6 13
4
4
8
3 7 9 10 13
8 10 11
8 9 11 12
9 10
10 15
3 4 8 14
13
12 16
15 17 18
16
18 16
I want to read this these values from file into two dimensional STL vector. Note that the size of inner vector is not uniform and not known in adance so I need to detect '\n'. So far I have been unnsuccessful. My code is as follows. Please help. What is wrong?
int main()
{
ifstream Lin("A.txt");
double d;
vector<vector<double> > A;
vector<double> dummy;
if (Lin.is_open()){
while (Lin >> d) {
if (Lin.peek() == '\n'){
A.push_back(dummy);
dummy.clear();
}else{
dummy.push_back(d);
}
}
Lin.close();
}
...
return 0;
}
When I iterate over the vector using the following code
, it reveals what is stored:
for(int i = 0; i< A.size(); i++){
for(int j = 0; j< A[i].size() ; j++){
cout << A[i][j] << " ";
}
cout << endl;
}
1
2 4 8
3 5 6
3 7 9 10
8 10
8 9 11
9
10
3 4 8
12
15 17
18
The intended output is same as the way it is stored in the file
Make sure that there is no empty space after the last integer in each line in the data file.
In the code currently you are not adding the last integer to the dummy vector. Modify it like this:
while (Lin >> d)
{
dummy.push_back(d); // Add the number first
if (Lin.peek() == '\n') // Then check if it is end of line
{
A.push_back(dummy);
dummy.clear();
}
}
Less is more. This replaces your entire loop. Note: You don't need to check is_open or call close for this to work safely.
for(std::string s; std::getline(Lin, s);)
{
A.emplace_back(std::istream_iterator<double>(std::istringstream(s)),
std::istream_iterator<double>());
}
Consider using getline.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main() {
std::string line;
std::vector<std::vector<double> > v;
while(std::getline(cin, line)) {
std::stringstream ss(line);
double value;
std::vector<double> numbers;
while(ss >> value) {
numbers.push_back(value);
std::cout << value << std::endl;
}
v.push_back(numbers);
}
return 0;
}
There could be other whitespace characters after the number at the end of line, other than \n. Like spaces:
1234 445 445 \n
^^^^
So your approach is not safe. Better would be to read entire line (getline) to some string, then construct istringstream on this string containing line, then just parse this istringstream to your vector for one line.
Like this:
for (string line; getline(filein, line); ) {
vector<double> dd;
istringstream is(line);
for (double d; is >> d; )
dd.push_back(d);
if (not dd.empty())
A.push_back(dd);
}

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).