You are given an n*m grid which contains lower case English letters. How many times does the phrase "saba" appear horizontally, vertically, and diagonally in the grid?
Counting horizontally, vertically and diagonally.
#include<iostream>
#include <vector>
#include <string>
using namespace std;
int TotalCount(vector<string> Str, int ItemCount)
{
string Text = "saba";
string VerticalString = "";
string DiagonalOneString = "";
string DiagonalTwoString = "";
int count = 0;
for (int i = 0; i < ItemCount; ++i)
{
string& currentRow = Str[i];
VerticalString = VerticalString.append(¤tRow.at(0));
DiagonalOneString = DiagonalOneString.append(¤tRow.at(i));
DiagonalTwoString =
DiagonalTwoString.append(¤tRow.at(currentRow.length() - 1 - i));
if ((currentRow.find(Text) != string::npos) || (VerticalString.find(Text) != string::npos) || (DiagonalOneString.find(Text) != string::npos) || (DiagonalTwoString.find(Text) != string::npos))
{
count++;
}
}
return count;
}
int main()
{
int total = 0;
int row;
cin >> row;
vector<string> rows;
// read each row and append to the "rows" vector
for (int r = 0; r < row; r++)
{
string line;
cin >> line;
rows.push_back(line);
}
cout << TotalCount(rows, row);
return 0;
}
Input format
First line: Two integer n and m, where n denotes (1 <= n,m <= 100) the number of rows and m denotes the number of columns in the grid
Next n lines: Each line must contain a string of length m which contains lower-case English letters only
Sample Input
5 5
safer
amjad
babol
aaron
songs
Expected Output
2
It seems like VerticalString copies the whole string instead of copying the character at the specified position. I am not getting the expected count. Can please someone let me know why the count is coming wrong?
When your vertical string is saba, count will increment. But count will increment again when your vertical string is sabas, for the same hit.
Also, you probably meant to search diagonals besides just the two between corners. Looking at only 2 diagonals allows for the possibility of overlooking valid hits. And reading both directions is probably required.
My recommendation would be to break down the problem into counting hits from each horizontal row, counting hits from each vertical row (could transpose the matrix and re-use the first function), counting diagonals (northeast to southwest), and finally counting diagonals (northwest to southeast). I.e., dedicate a new function for each of them, and sum the results.
Printing strings you're testing would greatly help you with debugging, too.
Related
I have a vector with a block of text read from a txt file. I need to use a window function to find the number of unique words in a sliding window of size K. I've found this count online which uses a similar technique but with an int array. However, when I try to adjust to code to fit my situation I'm getting an error:
"no match for ‘operator+’ (operand types are ‘std::vectorstd::__cxx11::basic_string<char >’ and ‘int’)gcc"
My question is, should I not be using a vector here? Should I be trying to figure out how to convert to an array? I didn't think there was too much of a difference between the two that I wouldn't be able to adapt the code, but perhaps I am wrong. I literally just started to learn C++ last night. Please help :(
// Counts distinct elements in window of size K
int countWindowDistinct(vector<string> text, int K)
{
int dist_count = 0;
// Traverse the window
for (int i = 0; i < K; i++) {
// Check if element arr[i] exists in arr[0..i-1]
int j;
for (j = 0; j < i; j++)
if (text[i] == text[j])
break;
if (j == i)
dist_count++;
}
return dist_count;
}
// Counts distinct elements in all windows of size k
void countDistinct(vector<string> text, int N, int K)
{
// Traverse through every window
for (int i = 0; i <= N - K; i++)
cout << countWindowDistinct(text + i, K) << endl;
}
int main()
{
//Declares two vectors
std::vector<std::string> book;
std::vector<std::string> unqWords;
//reads a text file and stores the contents in the vector book
book = readFile("test.txt");
//Ensures that all words in the text are lowercase
makeLower(book);
//Loops through the text (one word at a time) and removes all alphanumeric characters
for(int i = 0; i < book.size(); i++)
{
//Function used to remove alphanumeric characters from words
book[i] = removeAlpha(book[i]);
}
int K = 4;
int N = calculate_size(book);
// Function call
countDistinct(book, N, K);
}
I tried to write an algorithm to guess correctly in the game "Masterminds",
it works the average number of guesses is 6, but it takes a lot of time to calculate the best guess.
I used the idea of Knuth the algorithm works as follows:
Create the set S of 1296 possible codes (1111, 1112 ... 6665, 6666).
Start with initial guess 1122 (Knuth gives examples showing that other first guesses such as 1123, 1234 do not win in five tries on
every code).
Play the guess to get a response of colored and white pegs.
If the response is four colored pegs, the game is won, the algorithm terminates.
Otherwise, remove from S any code that would not give the same response if the current guess were the code.
In my code step 2 is to take random number.
I used vector<string> for this.
AllPoss is the vector full of strings, I guess is the last guess that was used. answer is the count of bulls and cows looks like "x,y" (where x and y are numbers)
void bullpgia::SmartGuesser::remove(string guess, string answer)
{
for (auto i= AllPoss.begin();i != AllPoss.end();i++){
string token = *i;
if (calculateBullAndPgia(token, guess) != answer)
AllPoss.erase(i--);
}
}
this is the part it take a lot of time to calculate is there any way of improvement?
to creating the list i used :
void bullpgia::SmartGuesser::All() {
/**
* creates a pool of all the possibilities strings
* we then delete the ones we dont need
* #param length is the length of the word we need to guess
*/
for(int i=0;i<pow(10,length);i++){
stringstream ss;
ss << setw(length) << setfill('0') << i;
string s = ss.str();
AllPoss.push_back(s);
}
}
the function calculateBullAndPgia(string , string) is:
string calculateBullAndPgia(const string &choice, const string &guess) {
string temp = choice;
string temp2 = guess;
unsigned int bull = 0;
unsigned int pgia = 0;
for (int i = 0; i < temp.length(); i++) {
if (temp[i] == temp2[i]) {
bull++;
temp[i] = 'a';
temp2[i] = 'z';
}
}
for (int i = 0; i < temp.length(); i++) {
for (int j = 0; j < temp2.length(); j++) {
if (i != j && temp[i] == temp2[j]) {
pgia++;
temp[i] = 'a';
temp2[j] = 'z';
}
}
}
return to_string(bull) + "," + to_string(pgia);
}
Erasing a single element in the middle of a vector is O(n). My guess is that you wind up doing it O(n) times per call to SmartGuesser::remove. Then you loop over that so you probably have a O(n^3) algorithm. You instead could use std::remove_if, which is O(n), to move all the to-be-erased elements to the end of the vector where they can be cheaply erased.:
AllPoss.erase(std::remove_if(AllPos.begin(), AllPos.end(), [&](const std::string& token, const std::string& guess) { return calculateBullAndPgia(token, guess) != answer; }), AllPos.end());
I am trying to make a Program that reads an input text from the user and then prints out each word and how many times it was repeated in a sorted order. ( the input is separated by white spaces and it can hold punctuation but no new lines)
Example of Input : I am a good programmer and I love C language.
output should be :
a : 2 times
I : 1 time
am : 1 time
good : 1 time
... and so on.
** for the input I used a vector and classes but i don't know why i can't push several items in it.
class word {public:
word();
void set_data(string data_value);
void printing_data();
void counter_addition();
int count;
string data;};
int main(){ /*creating vecotr called items of list class type*/
vector<word>items;
/*creating a variable of list class type which is used to push data into the vector*/
word *element;
/*Reading the input text seperated by white spaces*/
int size = 0;
string text;
cout << "Enter the text: " << endl;
getline(cin, text);
size = text.length();
int left_space = -1;
int right_space = 0;
string Sub_String;
/*main loop for constructing substring of words and then manipulating them*/
for (int i = 0; i<size; i++)
{
/*splitting the string into words*/
if (isspace(text[i]) || ispunct(text[i]))
{
right_space = i;
Sub_String = text.substr(left_space + 1, right_space - left_space - 1);
/*for first word just push it*/
if (left_space == -1)
{
element = new word();
element->set_data(Sub_String);
items.push_back(*element);
}
else
{
/*compare to vector's data */
for (int j = 0; j < items.size(); j++)
{
if (Sub_String == items[j].data)
{
items[j].count = items[j].count + 1;
}
else
{
element = new word();
element->set_data(Sub_String);
items.push_back(*element);
}
}
}
left_space = right_space;
}
if the words are the same the output is correct .
input : Life life life life
output: Life repeated:4
Please help me through this I am new to programming .
Store the string values and count into std::map< std::string, int > and for each word, check if it is already in the map. If it is there, increment the count. In opposite case insert it with count = 1
I have trouble to read in an input from user and convert them into matrix for calculation. For example, with the input = {1 2 3 / 4 5 6}, the program should read in the matrix in the form of
1 2 3
4 5 6
which have 3 cols and 2 rows. What i got so far which does not seem to work:
input.replace(input.begin(), input.end(), '/', ' ');
stringstream ss(input);
string token;
while (getline(ss, token, ' '))
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
int tok = atoi(token.c_str());
(*matrix).setElement(i, j, tok);
}
}
}
So what I'm trying to do is to break the input into token and store them into the matrix using the setElement function which take the number of row, column and the variable that user want to store. What wrong with this code is that the variable of tok doesnt seem to change and keep stuck in 0. Assuming that row and col are knows.
Thanks so much for any help.
Although many simple ways exist to solve the specific problem (and other answer have various good suggestions) let me try to give a more general view of the problem of "formatted input".
There are essentially three kind of problems, here:
at low level you have to do a string to number conversion
at a higher level you have to parse a composite format (understanding rows and line separation)
finally you also have to understand the size of the compound (how many rows and cols?)
this 3 things are not fully independent and the last is needed to know how to store elements (how do you size the matrix?)
Finally there is a 4th problem (that is spread all other the other 3): what to do if the input is "wrong".
These kind of problem are typically afforded in two opposite ways:
Read the data as they come, recognize if the format is matched, and dynamically grow the data structure that have to contain them or...
Read all the data as once as they are (textual form), then analyze the text to figure out how many elements it has, then isolate the "chunks" and do the conversions.
Point 2. requires good string manipulations, but also requires the ability to know how the input is long (what happens if one of the separating spaces is a new-line? the idea the everything is got with a getline fails in those cases)
Point 1 requires a Matrix class that is capable to grow as you read or a temporary dynamic structure (like and std container) in which you can place what you read before sending it into the appropriate place.
Since I don't know how your matrix works, let me keep a temporary vector and counters to store lines.
#include <vector>
#include <iostream>
#include <cassert>
class readmatrix
{
std::vector<int> data; //storage
size_t rows, cols; //the counted rows and columns
size_t col; //the counting cols in a current row
Matrix& mtx; //refer to the matrix that has to be read
public:
// just keep the reference to the destination
readmatrix(Matrix& m) :data(), rows(), cols(), cols(), mtx(m)
{}
// make this class a istream-->istream functor and let it be usable as a stream
// manipulator: input >> readmatrix(yourmatrix)
std::istream& operator()(std::istream& s)
{
if(s) //if we can read
{
char c=0:
s >> c; //trim spaces and get a char.
if(c!='{') //not an open brace
{ s.setstate(s.failbit); return s; } //report the format failure
while(s) //loop on rows (will break when the '}' will be found)
{
col=0;
while(s) //loop on cols (will break when the '/' or '}' will be found)
{
c=0; s >> c;
if(c=='/' || c=='}') //row finished?
{
if(!cols) cols=col; //got first row length
else if(cols != col) //it appears rows have different length
{ s.setstate(s.failbit); return s; } //report the format failure
if(c!='/') s.unget(); //push the char back for later
break; //row finished
}
s.unget(); //pushthe "not /" char back
int x; s >> x; //get an integer
if(!s) return s; //failed to read an integer!
++col; data.push_back(x); //save the read data
}
++rows; //got an entire row
c=0; s >> c;
if(c == '}') break; //finished the rows
else s.unget(); //push back the char: next row begin
}
}
//now, if read was successful,
// we can dispatch the data into the final destination
if(s)
{
mtx.setsize(rows,cols); // I assume you can set the matrix size this way
auto it = data.begin(); //will scan the inner vector
for(size_t r=0; r<rows; ++r) for(size_t c=0; c<cols; ++c, ++it)
mtx(r,c) = *it; //place the data
assert(it == data.end()); //this must be true if counting have gone right
}
return s;
}
};
Now you can read the matrix as
input >> readmatrix(matrix);
You will notice at this point that there are certain recurring patterns in the code: this is typical in one-pass parses, and those patterns can be grouped to form sub-parsers. If you do it generically you -in fact- will rewrite boost::spirit.
Of course some adaption can be done depending on how your matrix works (has it fixed sizes??), or what to do if rows sizes don't match (partial column filling ??)
You can even add a formatted input operator like
std::istream& operator>>(std::istream& s, Matrix& m)
{ return s >> readmatrix(m); }
so that you can just do
input >> matrix;
You are trying to operate on each cell of the matrix for each char read in the input!
You have to take one char for each cell, not multiple.
Splitting a string in tokens can be done by using the following function.
Please don't be shocked that the following code isn't runnable, this is due to the missing matrix class.
Try the following:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
using namespace std;
void split(const string& str, char delimiter, vector<string>& result) {
string::size_type i = 0;
string::size_type delimOcc = str.find(delimiter);
while (delimOcc != string::npos) {
result.push_back(str.substr(i, delimOcc-i));
i = ++delimOcc;
delimOcc = str.find(delimiter, delimOcc);
if (delimOcc == string::npos) {
result.push_back(str.substr(i, str.length()));
}
}
}
int main()
{
std::string input = "1 2 3 / 4 5 6";
vector<string> rows;
split(input, '/', rows);
for(int i = 0; i < rows.size(); i++) {
vector<string> cols;
split(rows[i], ' ', cols);
for(int j = 0; j < cols.size(); j++) {
if(cols[j][0] != '\0'){
int tok = stoi(cols[j]);
(*matrix).setElement(i, j, tok);
cout << tok << " - " << i << " - " << j << endl;
}
else {
if(j == 0) j--;
}
}
}
return 0;
}
If you know the size of the matrix on forehand you actually don't need getline, you should read int by int. (untested code)
input.replace(input.begin(), input.end(), '/', '\n');
stringstream ss(input);
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
int tok;
ss >> tok;
(*matrix).setElement(i, j, tok);
}
}
Write a program that reads the text and displays the number of one-letter, two-letter, etc. words. Words are divided by the characters: '', ',', ',' and '.'. Input: text on one line, no more than 1000 characters. Output: n rows of integers indicating the numbers of words with the corresponding lengths, n is the length of the longest word in the text.
I think I'm having a slight idea of how to count all of the words but strlen is yet unfamiliar to me and don't know how to proceed. Any help will be appreciated, thanks.
#include <iostream>
using namespace std;
int main()
{
char a[1000];
short count[1000];
int wc = 0;
int max = 0;
for (int i = 0; i < 1000; i++)
count[i] = 0;
for (int i = 0; i < 1000; i++)
{
cin >> a[i];
if ('\n')
break;
}
for (int i = 0; i < 1000; i++)
{
if (a[i] != ' ' && a[i] != ',' && a[i] != ';' && a[i] != '.')
wc++;
else
{
if (wc != 0)
{
count[wc]++;
if (wc > max)
max = wc;
}
wc = 0;
}
}
for (int i = 0; i < max; i++)
cout << count[i] << endl;
return 0;
}
Could someone fix it for me, please?
Under the circumstances, you don't really even need to read strings at all. You don't care about the content of each word, only its length. As such, you can just read and process one character at a time. When you read a non-delimiter character, increment the current word size. When you read a delimiter character, check if the current word size is non-zero. If it is, increment the count for that size of word. Also check whether the current count is larger than any count you've recorded before. If so, set the largest count to the current count.
Start with an array of 1000 shorts, all set to 0 as your counts for the different word sizes.
After processing all your input, you have a record of the longest word, so print out the counts from the array for all items from one through that maximum.