One-dimensional Japanese puzzle Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Reverse a word using string manipulationFind the Biggest TravelerSPOJ “SBANK - Sorting Bank Accounts” TLEDailyProgrammer 284: Wandering FingersMinimal length of substring that forms cyclic stringSort Characters By FrequencyLeetcode 49: Group Anagrams - Hash function design talkParsing Z80 assembler in C++Calculating effective shop inventories from CSV filesFunctions to count vowels and consonants in strings
Single word antonym of "flightless"
Why are there no cargo aircraft with "flying wing" design?
What does this icon in iOS Stardew Valley mean?
Withdrew £2800, but only £2000 shows as withdrawn on online banking; what are my obligations?
How do I stop a creek from eroding my steep embankment?
Why light coming from distant stars is not discreet?
List of Python versions
How widely used is the term Treppenwitz? Is it something that most Germans know?
Why is "Consequences inflicted." not a sentence?
Why did the IBM 650 use bi-quinary?
Why did the Falcon Heavy center core fall off the ASDS OCISLY barge?
Why are Kinder Surprise Eggs illegal in the USA?
Extract all GPU name, model and GPU ram
What to do with chalk when deepwater soloing?
Why didn't this character "real die" when they blew their stack out in Altered Carbon?
String `!23` is replaced with `docker` in command line
How does debian/ubuntu knows a package has a updated version
Identify plant with long narrow paired leaves and reddish stems
How to react to hostile behavior from a senior developer?
Can a non-EU citizen traveling with me come with me through the EU passport line?
How to tell that you are a giant?
How to bypass password on Windows XP account?
Why do we bend a book to keep it straight?
How to answer "Have you ever been terminated?"
One-dimensional Japanese puzzle
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Reverse a word using string manipulationFind the Biggest TravelerSPOJ “SBANK - Sorting Bank Accounts” TLEDailyProgrammer 284: Wandering FingersMinimal length of substring that forms cyclic stringSort Characters By FrequencyLeetcode 49: Group Anagrams - Hash function design talkParsing Z80 assembler in C++Calculating effective shop inventories from CSV filesFunctions to count vowels and consonants in strings
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I have been practicing competitive coding for a while now and am using codeforces.com. I recently encountered a problem called "One Dimensional Japanese Crossword" on that site.
The problem is as follows:
The judge provides an integer (up to 100) and then a string with that many characters being either 'B' or 'W'. We need to output how many groups of 'B' there are and how many 'B's there are in each group. For example:
Input:
6
BBWBWB
Output:
3
2 1 1
After lots of tries and lots of fails, I was finally able to get the code accepted by the judge. However, for some reason I feel that my code is really inefficient and there might be an easier and better way to solve this problem.
#include<iostream>
#include<vector>
using namespace std;
int main()
int n;
cin >> n;
string s;
cin >> s;
int bGroups = 0;
int wGroups = 0;
char initChar = s[0];
for (int i = 1; i < s.length(); i++)
if (initChar == 'B')
if (s[i] != initChar)
bGroups++;
initChar = 'W';
else if (initChar == 'W')
if (s[i] != initChar)
wGroups++;
initChar = 'B';
if (s[n - 1] == 'B')
bGroups++;
else if (s[n - 1] == 'W')
wGroups++;
char init = s[0];
vector<int>grpSize(bGroups);
int counter = 0;
int i = 0;
while (counter < bGroups)
if (init == 'B')
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
while (init == 'W')
i++;
init = s[i];
else
while (init == 'W')
i++;
init = s[i];
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
cout << bGroups << endl;
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
So basically, in the first pass over the string, I count how many groups of 'B' and 'W' there are. Then I create an int vector to store the size of each 'B' group. Then on the second pass I fill in the values into the vector and then output the results.
c++ programming-challenge
New contributor
$endgroup$
add a comment |
$begingroup$
I have been practicing competitive coding for a while now and am using codeforces.com. I recently encountered a problem called "One Dimensional Japanese Crossword" on that site.
The problem is as follows:
The judge provides an integer (up to 100) and then a string with that many characters being either 'B' or 'W'. We need to output how many groups of 'B' there are and how many 'B's there are in each group. For example:
Input:
6
BBWBWB
Output:
3
2 1 1
After lots of tries and lots of fails, I was finally able to get the code accepted by the judge. However, for some reason I feel that my code is really inefficient and there might be an easier and better way to solve this problem.
#include<iostream>
#include<vector>
using namespace std;
int main()
int n;
cin >> n;
string s;
cin >> s;
int bGroups = 0;
int wGroups = 0;
char initChar = s[0];
for (int i = 1; i < s.length(); i++)
if (initChar == 'B')
if (s[i] != initChar)
bGroups++;
initChar = 'W';
else if (initChar == 'W')
if (s[i] != initChar)
wGroups++;
initChar = 'B';
if (s[n - 1] == 'B')
bGroups++;
else if (s[n - 1] == 'W')
wGroups++;
char init = s[0];
vector<int>grpSize(bGroups);
int counter = 0;
int i = 0;
while (counter < bGroups)
if (init == 'B')
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
while (init == 'W')
i++;
init = s[i];
else
while (init == 'W')
i++;
init = s[i];
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
cout << bGroups << endl;
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
So basically, in the first pass over the string, I count how many groups of 'B' and 'W' there are. Then I create an int vector to store the size of each 'B' group. Then on the second pass I fill in the values into the vector and then output the results.
c++ programming-challenge
New contributor
$endgroup$
add a comment |
$begingroup$
I have been practicing competitive coding for a while now and am using codeforces.com. I recently encountered a problem called "One Dimensional Japanese Crossword" on that site.
The problem is as follows:
The judge provides an integer (up to 100) and then a string with that many characters being either 'B' or 'W'. We need to output how many groups of 'B' there are and how many 'B's there are in each group. For example:
Input:
6
BBWBWB
Output:
3
2 1 1
After lots of tries and lots of fails, I was finally able to get the code accepted by the judge. However, for some reason I feel that my code is really inefficient and there might be an easier and better way to solve this problem.
#include<iostream>
#include<vector>
using namespace std;
int main()
int n;
cin >> n;
string s;
cin >> s;
int bGroups = 0;
int wGroups = 0;
char initChar = s[0];
for (int i = 1; i < s.length(); i++)
if (initChar == 'B')
if (s[i] != initChar)
bGroups++;
initChar = 'W';
else if (initChar == 'W')
if (s[i] != initChar)
wGroups++;
initChar = 'B';
if (s[n - 1] == 'B')
bGroups++;
else if (s[n - 1] == 'W')
wGroups++;
char init = s[0];
vector<int>grpSize(bGroups);
int counter = 0;
int i = 0;
while (counter < bGroups)
if (init == 'B')
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
while (init == 'W')
i++;
init = s[i];
else
while (init == 'W')
i++;
init = s[i];
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
cout << bGroups << endl;
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
So basically, in the first pass over the string, I count how many groups of 'B' and 'W' there are. Then I create an int vector to store the size of each 'B' group. Then on the second pass I fill in the values into the vector and then output the results.
c++ programming-challenge
New contributor
$endgroup$
I have been practicing competitive coding for a while now and am using codeforces.com. I recently encountered a problem called "One Dimensional Japanese Crossword" on that site.
The problem is as follows:
The judge provides an integer (up to 100) and then a string with that many characters being either 'B' or 'W'. We need to output how many groups of 'B' there are and how many 'B's there are in each group. For example:
Input:
6
BBWBWB
Output:
3
2 1 1
After lots of tries and lots of fails, I was finally able to get the code accepted by the judge. However, for some reason I feel that my code is really inefficient and there might be an easier and better way to solve this problem.
#include<iostream>
#include<vector>
using namespace std;
int main()
int n;
cin >> n;
string s;
cin >> s;
int bGroups = 0;
int wGroups = 0;
char initChar = s[0];
for (int i = 1; i < s.length(); i++)
if (initChar == 'B')
if (s[i] != initChar)
bGroups++;
initChar = 'W';
else if (initChar == 'W')
if (s[i] != initChar)
wGroups++;
initChar = 'B';
if (s[n - 1] == 'B')
bGroups++;
else if (s[n - 1] == 'W')
wGroups++;
char init = s[0];
vector<int>grpSize(bGroups);
int counter = 0;
int i = 0;
while (counter < bGroups)
if (init == 'B')
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
while (init == 'W')
i++;
init = s[i];
else
while (init == 'W')
i++;
init = s[i];
while (init == 'B')
grpSize[counter]++;
i++;
init = s[i];
counter++;
cout << bGroups << endl;
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
So basically, in the first pass over the string, I count how many groups of 'B' and 'W' there are. Then I create an int vector to store the size of each 'B' group. Then on the second pass I fill in the values into the vector and then output the results.
c++ programming-challenge
c++ programming-challenge
New contributor
New contributor
edited Apr 12 at 18:12
200_success
131k17157422
131k17157422
New contributor
asked Apr 12 at 11:47
dhruvkapur_17dhruvkapur_17
364
364
New contributor
New contributor
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
$begingroup$
Code with iterators and standard algorithms, and you'll see your coding style improve dramatically:
finding the beginning of a group of Bs can be done with
std::find
:auto b = std::find(first, last, 'B');
finding the end of a group of Bs can also be done with
std::find
:auto e = std::find(b, last, 'W');
computing the distance between the two is the job of
std::distance
:auto nb_bs = std::distance(b, e)
.
So combining all that we get:
#include <vector>
#include <algorithm>
template <typename Iterator>
auto groups_of_bs(Iterator first, Iterator last)
std::vector<int> result;
while (true)
first = std::find(first, last, 'B');
if (first == last) break;
auto w = std::find(std::next(first), last, 'W');
result.push_back(std::distance(first, w));
if (w == last) break;
first = std::next(w);
return result;
Now the only thing left is to display the size of the vector, and then its elements:
#include <string>
#include <iostream>
int main()
std::string test"BBWBWB";
auto res = groups_of_bs(test.begin(), test.end());
std::cout << res.size() << 'n';
for (auto i : res) std::cout << i << ' ';
$endgroup$
add a comment |
$begingroup$
Here are a number of things that may help you improve your program.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid. Know when to use it and when not to (as when writing include headers). In this particular case, it's not too terrible because it's a single short program and not a header. Some people seem to think it should never be used under any circumstance, but my view is that it can be used as long as it is done responsibly and with full knowledge of the consequences.
Make sure you have all required #include
s
The code uses std::string
but doesn't #include <string>
. It's important to make sure you have all required includes to assure that the code compiles and runs portably.
Simplify your algorithm
The puzzle can be solved with a single pass through the data. Here's how this might be done:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
std::vector<unsigned> count(const std::string &s, size_t n)
std::vector<unsigned> groups;
bool withinBsfalse;
if (s.size() >= n)
for (size_t i0; i < n; ++i)
switch(s[i])
case 'B':
if (withinBs)
++groups.back();
else
groups.push_back(1);
withinBs = true;
break;
default:
withinBs = false;
return groups;
int main()
int n;
std::cin >> n;
std::string s;
std::cin >> s;
auto groupscount(s, n);
std::cout << groups.size() << 'n';
std::copy(groups.begin(), groups.end(), std::ostream_iterator<int>(std::cout, " "));
$endgroup$
add a comment |
$begingroup$
I will try to tell you what is wrong with your algorithm and why.
You do loop twice over the input string which is most certainly wrong
Your first loop does provide bGroups
and wGroups
as a result. We immediatly notice, that wGroups
is not used at all and can be removed completely. bGroups
is used only as limit in the second loop where you loop over all characters again and have to find all groups anyway. So why bother with finding them firsthand? If the second loop iterates over all characters (like the first one does) it can do the group search on its own and we can delete the first loop completely.
However your second loop contains nested while loops that do not stop at the last character. It needs to know the number of groups in advance. But it does not respect the length of the string anyway as it accesses s[s.size()]
if the last character is a 'B'
. This is guaranteed to be ''
in C++14 (and thus different than 'B'
) but may work on older compilers just by accident. The bottom line is that your algorithm would be broken for a different container or of you were searching ''
characters.
As a learning you should avoid parsing where states are represented by a position in a sequential code. Hold state in variables and have a single flat loop that can safely break.
You also can see your nested loop counting is wrong as there is code duplication. There is an if
statement to have the very same code in a different order depending on the start character.
Try to format your code pretty
#include<iostream>
should read #include <iostream>
Use std::string.size()
This is the standard how to determine the length of a container and iterate over it. It is a pretty bad idea to hold the length in a seperate variable that must match the actual length. Instead of
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
The traditional container loop looks like
for (int i = 0; i < grpSize.size(); i++)
cout << grpSize[i] << " ";
The modern range based loop - stick to that - looks like
for (const auto & n : grpSize)
cout << n << " ";
Do not construct a vector like an array
Instead of doing so and filling with the operator[]()
you should use std::vector.push_back()
to grow in size when you need.
Separate I/O from algorithm
Make a testable function without I/O that you call from main. The code should be structured somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// ...
return grpSize;
std::string input()
// ...
return s;
void output(std::vector<int> v)
// ...
int main()
std::string s(input());
output(puzzle(s));
using namespace std;
This line is found in many tutorials and even in IDE templates. You should use this very carefully in a limited scope only. Never use this in header files or before include lines as it may introduce name conflicts. When you fully understand this you may decide to use it in *.cpp files e. g. in an output function.
finally your algorithm should look somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// as we are interested in 'B' groups only
// we start in state 'W' to catch the first 'B'
char state'W';
for (const auto & c : s)
if (c == 'B')
if (state != 'B')
grpSize.push_back(0);
++grpSize.back();
state = c;
return grpSize;
$endgroup$
$begingroup$
Good review! One thing aboutstd::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.
$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
dhruvkapur_17 is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217318%2fone-dimensional-japanese-puzzle%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Code with iterators and standard algorithms, and you'll see your coding style improve dramatically:
finding the beginning of a group of Bs can be done with
std::find
:auto b = std::find(first, last, 'B');
finding the end of a group of Bs can also be done with
std::find
:auto e = std::find(b, last, 'W');
computing the distance between the two is the job of
std::distance
:auto nb_bs = std::distance(b, e)
.
So combining all that we get:
#include <vector>
#include <algorithm>
template <typename Iterator>
auto groups_of_bs(Iterator first, Iterator last)
std::vector<int> result;
while (true)
first = std::find(first, last, 'B');
if (first == last) break;
auto w = std::find(std::next(first), last, 'W');
result.push_back(std::distance(first, w));
if (w == last) break;
first = std::next(w);
return result;
Now the only thing left is to display the size of the vector, and then its elements:
#include <string>
#include <iostream>
int main()
std::string test"BBWBWB";
auto res = groups_of_bs(test.begin(), test.end());
std::cout << res.size() << 'n';
for (auto i : res) std::cout << i << ' ';
$endgroup$
add a comment |
$begingroup$
Code with iterators and standard algorithms, and you'll see your coding style improve dramatically:
finding the beginning of a group of Bs can be done with
std::find
:auto b = std::find(first, last, 'B');
finding the end of a group of Bs can also be done with
std::find
:auto e = std::find(b, last, 'W');
computing the distance between the two is the job of
std::distance
:auto nb_bs = std::distance(b, e)
.
So combining all that we get:
#include <vector>
#include <algorithm>
template <typename Iterator>
auto groups_of_bs(Iterator first, Iterator last)
std::vector<int> result;
while (true)
first = std::find(first, last, 'B');
if (first == last) break;
auto w = std::find(std::next(first), last, 'W');
result.push_back(std::distance(first, w));
if (w == last) break;
first = std::next(w);
return result;
Now the only thing left is to display the size of the vector, and then its elements:
#include <string>
#include <iostream>
int main()
std::string test"BBWBWB";
auto res = groups_of_bs(test.begin(), test.end());
std::cout << res.size() << 'n';
for (auto i : res) std::cout << i << ' ';
$endgroup$
add a comment |
$begingroup$
Code with iterators and standard algorithms, and you'll see your coding style improve dramatically:
finding the beginning of a group of Bs can be done with
std::find
:auto b = std::find(first, last, 'B');
finding the end of a group of Bs can also be done with
std::find
:auto e = std::find(b, last, 'W');
computing the distance between the two is the job of
std::distance
:auto nb_bs = std::distance(b, e)
.
So combining all that we get:
#include <vector>
#include <algorithm>
template <typename Iterator>
auto groups_of_bs(Iterator first, Iterator last)
std::vector<int> result;
while (true)
first = std::find(first, last, 'B');
if (first == last) break;
auto w = std::find(std::next(first), last, 'W');
result.push_back(std::distance(first, w));
if (w == last) break;
first = std::next(w);
return result;
Now the only thing left is to display the size of the vector, and then its elements:
#include <string>
#include <iostream>
int main()
std::string test"BBWBWB";
auto res = groups_of_bs(test.begin(), test.end());
std::cout << res.size() << 'n';
for (auto i : res) std::cout << i << ' ';
$endgroup$
Code with iterators and standard algorithms, and you'll see your coding style improve dramatically:
finding the beginning of a group of Bs can be done with
std::find
:auto b = std::find(first, last, 'B');
finding the end of a group of Bs can also be done with
std::find
:auto e = std::find(b, last, 'W');
computing the distance between the two is the job of
std::distance
:auto nb_bs = std::distance(b, e)
.
So combining all that we get:
#include <vector>
#include <algorithm>
template <typename Iterator>
auto groups_of_bs(Iterator first, Iterator last)
std::vector<int> result;
while (true)
first = std::find(first, last, 'B');
if (first == last) break;
auto w = std::find(std::next(first), last, 'W');
result.push_back(std::distance(first, w));
if (w == last) break;
first = std::next(w);
return result;
Now the only thing left is to display the size of the vector, and then its elements:
#include <string>
#include <iostream>
int main()
std::string test"BBWBWB";
auto res = groups_of_bs(test.begin(), test.end());
std::cout << res.size() << 'n';
for (auto i : res) std::cout << i << ' ';
answered Apr 12 at 12:59
papagagapapagaga
4,977522
4,977522
add a comment |
add a comment |
$begingroup$
Here are a number of things that may help you improve your program.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid. Know when to use it and when not to (as when writing include headers). In this particular case, it's not too terrible because it's a single short program and not a header. Some people seem to think it should never be used under any circumstance, but my view is that it can be used as long as it is done responsibly and with full knowledge of the consequences.
Make sure you have all required #include
s
The code uses std::string
but doesn't #include <string>
. It's important to make sure you have all required includes to assure that the code compiles and runs portably.
Simplify your algorithm
The puzzle can be solved with a single pass through the data. Here's how this might be done:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
std::vector<unsigned> count(const std::string &s, size_t n)
std::vector<unsigned> groups;
bool withinBsfalse;
if (s.size() >= n)
for (size_t i0; i < n; ++i)
switch(s[i])
case 'B':
if (withinBs)
++groups.back();
else
groups.push_back(1);
withinBs = true;
break;
default:
withinBs = false;
return groups;
int main()
int n;
std::cin >> n;
std::string s;
std::cin >> s;
auto groupscount(s, n);
std::cout << groups.size() << 'n';
std::copy(groups.begin(), groups.end(), std::ostream_iterator<int>(std::cout, " "));
$endgroup$
add a comment |
$begingroup$
Here are a number of things that may help you improve your program.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid. Know when to use it and when not to (as when writing include headers). In this particular case, it's not too terrible because it's a single short program and not a header. Some people seem to think it should never be used under any circumstance, but my view is that it can be used as long as it is done responsibly and with full knowledge of the consequences.
Make sure you have all required #include
s
The code uses std::string
but doesn't #include <string>
. It's important to make sure you have all required includes to assure that the code compiles and runs portably.
Simplify your algorithm
The puzzle can be solved with a single pass through the data. Here's how this might be done:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
std::vector<unsigned> count(const std::string &s, size_t n)
std::vector<unsigned> groups;
bool withinBsfalse;
if (s.size() >= n)
for (size_t i0; i < n; ++i)
switch(s[i])
case 'B':
if (withinBs)
++groups.back();
else
groups.push_back(1);
withinBs = true;
break;
default:
withinBs = false;
return groups;
int main()
int n;
std::cin >> n;
std::string s;
std::cin >> s;
auto groupscount(s, n);
std::cout << groups.size() << 'n';
std::copy(groups.begin(), groups.end(), std::ostream_iterator<int>(std::cout, " "));
$endgroup$
add a comment |
$begingroup$
Here are a number of things that may help you improve your program.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid. Know when to use it and when not to (as when writing include headers). In this particular case, it's not too terrible because it's a single short program and not a header. Some people seem to think it should never be used under any circumstance, but my view is that it can be used as long as it is done responsibly and with full knowledge of the consequences.
Make sure you have all required #include
s
The code uses std::string
but doesn't #include <string>
. It's important to make sure you have all required includes to assure that the code compiles and runs portably.
Simplify your algorithm
The puzzle can be solved with a single pass through the data. Here's how this might be done:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
std::vector<unsigned> count(const std::string &s, size_t n)
std::vector<unsigned> groups;
bool withinBsfalse;
if (s.size() >= n)
for (size_t i0; i < n; ++i)
switch(s[i])
case 'B':
if (withinBs)
++groups.back();
else
groups.push_back(1);
withinBs = true;
break;
default:
withinBs = false;
return groups;
int main()
int n;
std::cin >> n;
std::string s;
std::cin >> s;
auto groupscount(s, n);
std::cout << groups.size() << 'n';
std::copy(groups.begin(), groups.end(), std::ostream_iterator<int>(std::cout, " "));
$endgroup$
Here are a number of things that may help you improve your program.
Don't abuse using namespace std
Putting using namespace std
at the top of every program is a bad habit that you'd do well to avoid. Know when to use it and when not to (as when writing include headers). In this particular case, it's not too terrible because it's a single short program and not a header. Some people seem to think it should never be used under any circumstance, but my view is that it can be used as long as it is done responsibly and with full knowledge of the consequences.
Make sure you have all required #include
s
The code uses std::string
but doesn't #include <string>
. It's important to make sure you have all required includes to assure that the code compiles and runs portably.
Simplify your algorithm
The puzzle can be solved with a single pass through the data. Here's how this might be done:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <string>
std::vector<unsigned> count(const std::string &s, size_t n)
std::vector<unsigned> groups;
bool withinBsfalse;
if (s.size() >= n)
for (size_t i0; i < n; ++i)
switch(s[i])
case 'B':
if (withinBs)
++groups.back();
else
groups.push_back(1);
withinBs = true;
break;
default:
withinBs = false;
return groups;
int main()
int n;
std::cin >> n;
std::string s;
std::cin >> s;
auto groupscount(s, n);
std::cout << groups.size() << 'n';
std::copy(groups.begin(), groups.end(), std::ostream_iterator<int>(std::cout, " "));
edited Apr 12 at 13:25
answered Apr 12 at 13:06
EdwardEdward
47.9k380213
47.9k380213
add a comment |
add a comment |
$begingroup$
I will try to tell you what is wrong with your algorithm and why.
You do loop twice over the input string which is most certainly wrong
Your first loop does provide bGroups
and wGroups
as a result. We immediatly notice, that wGroups
is not used at all and can be removed completely. bGroups
is used only as limit in the second loop where you loop over all characters again and have to find all groups anyway. So why bother with finding them firsthand? If the second loop iterates over all characters (like the first one does) it can do the group search on its own and we can delete the first loop completely.
However your second loop contains nested while loops that do not stop at the last character. It needs to know the number of groups in advance. But it does not respect the length of the string anyway as it accesses s[s.size()]
if the last character is a 'B'
. This is guaranteed to be ''
in C++14 (and thus different than 'B'
) but may work on older compilers just by accident. The bottom line is that your algorithm would be broken for a different container or of you were searching ''
characters.
As a learning you should avoid parsing where states are represented by a position in a sequential code. Hold state in variables and have a single flat loop that can safely break.
You also can see your nested loop counting is wrong as there is code duplication. There is an if
statement to have the very same code in a different order depending on the start character.
Try to format your code pretty
#include<iostream>
should read #include <iostream>
Use std::string.size()
This is the standard how to determine the length of a container and iterate over it. It is a pretty bad idea to hold the length in a seperate variable that must match the actual length. Instead of
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
The traditional container loop looks like
for (int i = 0; i < grpSize.size(); i++)
cout << grpSize[i] << " ";
The modern range based loop - stick to that - looks like
for (const auto & n : grpSize)
cout << n << " ";
Do not construct a vector like an array
Instead of doing so and filling with the operator[]()
you should use std::vector.push_back()
to grow in size when you need.
Separate I/O from algorithm
Make a testable function without I/O that you call from main. The code should be structured somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// ...
return grpSize;
std::string input()
// ...
return s;
void output(std::vector<int> v)
// ...
int main()
std::string s(input());
output(puzzle(s));
using namespace std;
This line is found in many tutorials and even in IDE templates. You should use this very carefully in a limited scope only. Never use this in header files or before include lines as it may introduce name conflicts. When you fully understand this you may decide to use it in *.cpp files e. g. in an output function.
finally your algorithm should look somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// as we are interested in 'B' groups only
// we start in state 'W' to catch the first 'B'
char state'W';
for (const auto & c : s)
if (c == 'B')
if (state != 'B')
grpSize.push_back(0);
++grpSize.back();
state = c;
return grpSize;
$endgroup$
$begingroup$
Good review! One thing aboutstd::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.
$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
add a comment |
$begingroup$
I will try to tell you what is wrong with your algorithm and why.
You do loop twice over the input string which is most certainly wrong
Your first loop does provide bGroups
and wGroups
as a result. We immediatly notice, that wGroups
is not used at all and can be removed completely. bGroups
is used only as limit in the second loop where you loop over all characters again and have to find all groups anyway. So why bother with finding them firsthand? If the second loop iterates over all characters (like the first one does) it can do the group search on its own and we can delete the first loop completely.
However your second loop contains nested while loops that do not stop at the last character. It needs to know the number of groups in advance. But it does not respect the length of the string anyway as it accesses s[s.size()]
if the last character is a 'B'
. This is guaranteed to be ''
in C++14 (and thus different than 'B'
) but may work on older compilers just by accident. The bottom line is that your algorithm would be broken for a different container or of you were searching ''
characters.
As a learning you should avoid parsing where states are represented by a position in a sequential code. Hold state in variables and have a single flat loop that can safely break.
You also can see your nested loop counting is wrong as there is code duplication. There is an if
statement to have the very same code in a different order depending on the start character.
Try to format your code pretty
#include<iostream>
should read #include <iostream>
Use std::string.size()
This is the standard how to determine the length of a container and iterate over it. It is a pretty bad idea to hold the length in a seperate variable that must match the actual length. Instead of
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
The traditional container loop looks like
for (int i = 0; i < grpSize.size(); i++)
cout << grpSize[i] << " ";
The modern range based loop - stick to that - looks like
for (const auto & n : grpSize)
cout << n << " ";
Do not construct a vector like an array
Instead of doing so and filling with the operator[]()
you should use std::vector.push_back()
to grow in size when you need.
Separate I/O from algorithm
Make a testable function without I/O that you call from main. The code should be structured somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// ...
return grpSize;
std::string input()
// ...
return s;
void output(std::vector<int> v)
// ...
int main()
std::string s(input());
output(puzzle(s));
using namespace std;
This line is found in many tutorials and even in IDE templates. You should use this very carefully in a limited scope only. Never use this in header files or before include lines as it may introduce name conflicts. When you fully understand this you may decide to use it in *.cpp files e. g. in an output function.
finally your algorithm should look somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// as we are interested in 'B' groups only
// we start in state 'W' to catch the first 'B'
char state'W';
for (const auto & c : s)
if (c == 'B')
if (state != 'B')
grpSize.push_back(0);
++grpSize.back();
state = c;
return grpSize;
$endgroup$
$begingroup$
Good review! One thing aboutstd::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.
$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
add a comment |
$begingroup$
I will try to tell you what is wrong with your algorithm and why.
You do loop twice over the input string which is most certainly wrong
Your first loop does provide bGroups
and wGroups
as a result. We immediatly notice, that wGroups
is not used at all and can be removed completely. bGroups
is used only as limit in the second loop where you loop over all characters again and have to find all groups anyway. So why bother with finding them firsthand? If the second loop iterates over all characters (like the first one does) it can do the group search on its own and we can delete the first loop completely.
However your second loop contains nested while loops that do not stop at the last character. It needs to know the number of groups in advance. But it does not respect the length of the string anyway as it accesses s[s.size()]
if the last character is a 'B'
. This is guaranteed to be ''
in C++14 (and thus different than 'B'
) but may work on older compilers just by accident. The bottom line is that your algorithm would be broken for a different container or of you were searching ''
characters.
As a learning you should avoid parsing where states are represented by a position in a sequential code. Hold state in variables and have a single flat loop that can safely break.
You also can see your nested loop counting is wrong as there is code duplication. There is an if
statement to have the very same code in a different order depending on the start character.
Try to format your code pretty
#include<iostream>
should read #include <iostream>
Use std::string.size()
This is the standard how to determine the length of a container and iterate over it. It is a pretty bad idea to hold the length in a seperate variable that must match the actual length. Instead of
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
The traditional container loop looks like
for (int i = 0; i < grpSize.size(); i++)
cout << grpSize[i] << " ";
The modern range based loop - stick to that - looks like
for (const auto & n : grpSize)
cout << n << " ";
Do not construct a vector like an array
Instead of doing so and filling with the operator[]()
you should use std::vector.push_back()
to grow in size when you need.
Separate I/O from algorithm
Make a testable function without I/O that you call from main. The code should be structured somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// ...
return grpSize;
std::string input()
// ...
return s;
void output(std::vector<int> v)
// ...
int main()
std::string s(input());
output(puzzle(s));
using namespace std;
This line is found in many tutorials and even in IDE templates. You should use this very carefully in a limited scope only. Never use this in header files or before include lines as it may introduce name conflicts. When you fully understand this you may decide to use it in *.cpp files e. g. in an output function.
finally your algorithm should look somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// as we are interested in 'B' groups only
// we start in state 'W' to catch the first 'B'
char state'W';
for (const auto & c : s)
if (c == 'B')
if (state != 'B')
grpSize.push_back(0);
++grpSize.back();
state = c;
return grpSize;
$endgroup$
I will try to tell you what is wrong with your algorithm and why.
You do loop twice over the input string which is most certainly wrong
Your first loop does provide bGroups
and wGroups
as a result. We immediatly notice, that wGroups
is not used at all and can be removed completely. bGroups
is used only as limit in the second loop where you loop over all characters again and have to find all groups anyway. So why bother with finding them firsthand? If the second loop iterates over all characters (like the first one does) it can do the group search on its own and we can delete the first loop completely.
However your second loop contains nested while loops that do not stop at the last character. It needs to know the number of groups in advance. But it does not respect the length of the string anyway as it accesses s[s.size()]
if the last character is a 'B'
. This is guaranteed to be ''
in C++14 (and thus different than 'B'
) but may work on older compilers just by accident. The bottom line is that your algorithm would be broken for a different container or of you were searching ''
characters.
As a learning you should avoid parsing where states are represented by a position in a sequential code. Hold state in variables and have a single flat loop that can safely break.
You also can see your nested loop counting is wrong as there is code duplication. There is an if
statement to have the very same code in a different order depending on the start character.
Try to format your code pretty
#include<iostream>
should read #include <iostream>
Use std::string.size()
This is the standard how to determine the length of a container and iterate over it. It is a pretty bad idea to hold the length in a seperate variable that must match the actual length. Instead of
for (int i = 0; i < bGroups; i++)
cout << grpSize[i] << " ";
The traditional container loop looks like
for (int i = 0; i < grpSize.size(); i++)
cout << grpSize[i] << " ";
The modern range based loop - stick to that - looks like
for (const auto & n : grpSize)
cout << n << " ";
Do not construct a vector like an array
Instead of doing so and filling with the operator[]()
you should use std::vector.push_back()
to grow in size when you need.
Separate I/O from algorithm
Make a testable function without I/O that you call from main. The code should be structured somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// ...
return grpSize;
std::string input()
// ...
return s;
void output(std::vector<int> v)
// ...
int main()
std::string s(input());
output(puzzle(s));
using namespace std;
This line is found in many tutorials and even in IDE templates. You should use this very carefully in a limited scope only. Never use this in header files or before include lines as it may introduce name conflicts. When you fully understand this you may decide to use it in *.cpp files e. g. in an output function.
finally your algorithm should look somewhat like
std::vector<int> puzzle(std::string s)
std::vector<int> grpSize;
// as we are interested in 'B' groups only
// we start in state 'W' to catch the first 'B'
char state'W';
for (const auto & c : s)
if (c == 'B')
if (state != 'B')
grpSize.push_back(0);
++grpSize.back();
state = c;
return grpSize;
edited Apr 12 at 22:54
answered Apr 12 at 21:04
stefanstefan
1,605211
1,605211
$begingroup$
Good review! One thing aboutstd::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.
$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
add a comment |
$begingroup$
Good review! One thing aboutstd::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.
$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
$begingroup$
Good review! One thing about
std::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
Good review! One thing about
std::string.size()
is that while what you wrote is definitely generally good advice, the peculiar way this problem is set up is to have a number followed by a string of that length. There is no guidance as to what to do if they fail to match -- my version of the code just silently drops any excess characters and returns no matches if the string is too short.$endgroup$
– Edward
Apr 12 at 21:17
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@Edward: I had the wrong example on size(), fixed that, thanks. About the coding challenges - the input is used for many programming languages, some may need a size before read. So I do not give too much attention on aasserting input consistency.
$endgroup$
– stefan
Apr 12 at 22:58
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
$begingroup$
@stephan: Thanks a lot for your input. I won't lie. I am new to coding and though I understood some of what you said, quite a bit of it went over my head. But I am working on improving my knowledge of C++ and I will keep learning and reading this till I understand it completely. But quite a bit of it made perfect sense. Thanks again!
$endgroup$
– dhruvkapur_17
Apr 13 at 6:16
add a comment |
dhruvkapur_17 is a new contributor. Be nice, and check out our Code of Conduct.
dhruvkapur_17 is a new contributor. Be nice, and check out our Code of Conduct.
dhruvkapur_17 is a new contributor. Be nice, and check out our Code of Conduct.
dhruvkapur_17 is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217318%2fone-dimensional-japanese-puzzle%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown