Solving 935B - Fafa and the Gates in Codeforces - c++

I have a question about 935B - Fafa and the Gates in CodeForces. My code is working for the first test cases but it’s getting stuck on test case 20, this is the code I used, could someone please tell me what I’m doing wrong here? Thanks!
#include <iostream>
#include <string>
using namespace std;
int main(){
long long a, x = 0, y = 0, total = 0;
cin >> a;
string s;
cin >> s;
for (long long i = 0; i <= a; i++){
if (s[i] == 'U') x += 1;
if (s[i] == 'R') y += 1;
if (x == y && s[i] == s[i+1]) total += 1;
}
cout << total << endl;
}

Aside from the i<=a issue I called out in the comments above, there's another issue.
Even if you fix the for loop to be stop after i<a, then this statement:
if (x == y && s[i] == s[i+1]) total += 1;
Will still reference an invalid index at s[i+1] since i+1 is an invalid index on the last iteration of the array.
On each iteration of the loop, you need to see if he's at the gate first, then update x or y appropriately, then assess if he changed kingdoms.
If he's at a position x > y, you know he's in the lower kingdom. Likewise if y > x, you know he's in the upper kingdom on the map.
I think this is closer to what you want:
bool topKingdom = false; // initially at 0,0. Fafa is currently in the "lower kingdom" on the map
for (long long i = 0; i < a; i++){
bool atGate = (x == y);
if (s[i] == 'U') y++;
if (s[i] == 'R') x++;
// if we were previously "at a gate", assess if we are now in a new kingdom from before
if (atGate && !topKingdom && y > x) {
topKingdom = true;
total++;
}
else if (atGate && topKingdom && x > y) {
topKingdom = false;
total++;
}
}
cout << total << endl;

Related

A program that reads integers as long as they are alternately positive and negative. C++

I'm new to programming in C++. I've been trying to create a program that reads integers as long as they are alternately positive and negative. I don't know how to make it without using if in if, and because of that it can read e.g (2, -2, 2, -2, -2, -2).
int temp = 0, x = 0, y = 0;
while (temp == 0){
cin >> x;
if (x > 0) {
y = x;
cin >> x;
if (x < 0)
continue;
else if(y > 0 && x > 0)
break;
}
if(x < 0){
y = x;
cin >> x;
if (x > 0)
continue;
else if(y < 0 && x < 0)
break;
}
}
I would read the first number outside the loop, and set a variable based on whether that number is positive or negative. Then I'd have the loop read numbers, and based on the variable know whether to expect a positive or negative number. If it gets what it expects, invert the value in the variable, and repeat. In something pseudo-codeish, something on this general order:
read(number)
// if this number's negative, expect the next to be positive (and vice versa)
expect_positive = number < 0
for (;;) {
read(number)
bool positive = number >= 0
if (positive != expect_positive)
break;
expect_positive = !expect_positive;
}
Also, you could use property (a XOR b) < 0 if a and b have a different sign bit.
#include <iostream>
int main()
{
int a, b;
std::cin >> b;
do {
a = b;
std::cin >> b;
}while( (a^b) < 0);
std::cout << "Same sign" << std::endl;
}
template<typename In, typename Out, typename F>
Out copy_while_alternative(In b, In e, Out r, F f)
{
if (b == e) return r;
bool lastF = f(*b);
*r++ = *b++;
while (b != e && f(*b) != lastF) {
*r++ = *b++;
lastF = !lastF;
}
return r;
}
https://godbolt.org/z/9rq93e
One possible implementation:
#include <iostream>
int main()
{
int currentNumber, previousNumber;
std::cin >> currentNumber;
do
{
previousNumber = currentNumber;
std::cin >> currentNumber;
} while (currentNumber * previousNumber < 0);
}
Two numbers are opposite signs if their product is negative.
The other answers are already good, but I wanted to give a solution that is close to yours, to show you how you can simplify things.
For example, you have a lot of unnecassary checks. You test x < 0, set y=x and then test y < 0 again.
You were missing to consider the starting case separately. The cin >> x should not happen unconditionally every loop iteration.
Here is a simplification:
int x = 0;
int last = 0; //more meaningful name
cin >> last; //you were missing some starting point
while (true){ //you do not need temp, instead just replace it by what you want to say
cin >> x;
if (x > 0 && last < 0) {
last = x;
continue;
}
else if(x < 0 && last > 0){
last = x;
continue;
}
break;
}
Of course it is somewhat better to replace these checks by a product check to simplify things even more.
If only the oposite sign is needed then number * -1 will do fine.
#include <iostream>
#include <string>
int main(){
int input_int;
std::string input;
int last = 2;
while (1){
std::cout << "Last int -> " << last << std::endl;
std::cin >> input;
input_int = std::stoi(input);
if (last * -1 == input_int) {
last = input_int;
} else {
break;
}
}
return 0;
}
Move the first cin outside the loop
int temp = 0, x = 0, y = 0;
cin >>x;
if ( x !=0)
{
while (temp == 0){
//cin >> x;// should be above as this because it resets the +- order every 2nd time
if (x > 0) {
y = x;
cin >> x;
if (x < 0)
continue;
else if(y > 0 && x >= 0)//>= to avoid infinite loop if 0 is input
break;
}
if(x < 0){
y = x;
cin >> x;
if (x > 0)
continue;
else if(y < 0 && x <= 0)//<= to avoid infinite loop if 0 is input
break;
}
}
}

This snippet of code does not stop stoi from running when it gets bad input

I am stuck with this bit of code. I am trying to get this code snippet to restart if the user input isn't numeric. It doesn't seem to do this and I don't know why. I would appreciate it if someone could give me a hand. Sorry about the start and end line indents, it's driving me mad.
void write() {
string x, y;
int x1 = 0, y1 = 0, no = 0;
/*highNumber (x1, y1);*/
cout << endl << " x to display: ";
cin >> x;
cout << endl << " y to display: ";
cin >> y;
for (int i = 0; i < x.length(); i++) {
if (x[i] >= '0' || x[i] <= '9') {
no++;
}
}
if (no == x.length()) {
no = 0;
}
else {
write();
}
for (int i = 0; i < x.length(); i++) {
if (y[i] >= '0' || y[i] <= '9') {
no++;
}
}
if (no == x.length()) {
no = 0;
}
else {
write();
}
x1 = stoi(x);
y1 = stoi(y);
highNumber (x1, y1);
}
The mistake seems to be right here: if (x[i] >= '0' || x[i] <= '9')
This should probably be if (x[i] >= '0' && x[i] <= '9') if I understand your code correctly, even though I am having some difficulty parsing it. Either way, the code you have there before will return true for all characters. This checks that it is within the number range of ascii characters.
Also, seems like your second loop is checking x.size() instead of y.size() when working on y. This should matter if x doesn't have the same size as y.

c++ Expression: string subscript out of range error

hello i am new to programming but every time i run this code i get the error "c++ Expression: string subscript out of range" i am pretty sure that the error is in the second for loop
#include<iostream>
#include<string>
#include <algorithm>
using namespace std;
int main()
{
string x;
string n;
cin >> x;
for (int i = 0; i <= x.length(); i++){
if (x[i] == 'a' || x[i] == 'e' || x[i] == 'i' || x[i] == 'o' || x[i] == 'u' || x[i] == 'y')
{
x[i] = ' ';
}
}
x.erase(remove_if(x.begin(), x.end(), isspace), x.end());
int f = x.length() * 2;
for (int i = 0; i <f-1; i+=2){
n[i] = '.';
}
cout << n << endl;
}
for (int i = 0; i <= x.length(); i++)
should be:
for (int i = 0; i < x.length(); i++)
because index starts from 0
x[x.length()] out of range
can not use n[index] when the size of n is 0,use n.push_back()
for (int i = 0; i < x.length(); i++){ //error
if (x[i] == 'a' || x[i] == 'e' || x[i] == 'i' || x[i] == 'o' || x[i] == 'u' || x[i] == 'y')
{
x[i] = ' ';
}
}
x.erase(remove_if(x.begin(), x.end(), isspace), x.end());
int f = x.length() * 2;
for (int i = 0; i <f-1; i+=2){
n[i] = '.'; // n.push_back('.');
}
cout << n <
< endl;
If you are trying to remove all the vowels from your input string, you do not need to run two separate loops. You are already using std::remove_if, just add lambda shown in following code and you will have your desired output.
#include <iostream>
#include <algorithm>
#include <string>
#include <cctype>
using namespace std;
int main() {
std::string str = "This is test of vowels aeiou to be removed. Also the upper case AEIOU.";
std::cout << "Original String: " << str << std::endl;
str.erase(std::remove_if(str.begin(), str.end(), [](char x) {
return (x == 'a'|| x == 'e' || x == 'i' || x == 'o' || x == 'u' || x == 'y'
|| x == 'A'|| x == 'E' || x == 'I' || x == 'O' || x == 'U' || x == 'Y')
}), str.end());
std::cout << "String with vowels removed: " << str << std::endl;
// Not sure what you are trying to achieve with this code.
int f = x.length() * 2;
for (int i = 0; i <f-1; i+=2)
{
n[i] = '.';
}
return 0;
}
Here is the LiveDemo
You have 3 bits of code causing errors:
1) Your first error occurs because you should be checking that i < x.length() in the first loop condition, not that i <= x.length() . Even better, calculate the length once and then use that value in the loop condition to avoid calling x.length() repeatedly. Your first loop should look like this:
int length = x.length();
for (int i = 0; i < x.length(); ++i)
note: ++i is quicker than i++ and in this case using ++i would not make a difference to the logic.
2) Your second error is due to the line int f = x.length() * 2 because you are doubling the length of the array and then using that number to iterate through the array. For example, if your array has a length() of 5 then int f = x.length() * 2 would mean that f = 10 but if the length of the array is 5 than accessing the array with any number greater than 4 (array index starts at zero) would produce an error. In your second loop condition you do this
for (int i = 0; i < f-1; i+=2 ) {
n[i] = '.' // i could easily be more than 4 at this point
}
To fix you second problem, take out the * 2 from int f = x.length() * 2
3) Your third is because you haven't given the n string object a value yet you are accessing it using array indexing []

C++ Wrong answer in code chef

Problem: http://www.codechef.com/problems/LEBOMBS
I have tried every single test case that come to my mind. But it still gives a wrong answer. I don't know why.
Please point out if there's any error in my code. This is my code.
#include <iostream>
using namespace std;
int main() {
int t, i, total, n;
char a[1001];
cin >> t;
while (t--) {
i = 0;
cin >> n;
total = n;
cin >> a;
while (i < n) {
if (a[i] == '1') {
if (i == '0')
total -= 2;
else if (i == 1) {
if (a[i - 1] == '1')
total--;
else
total -= 3;
} else if (i > 1 && i < n - 1) {
if (a[i - 1] == '1')
total--;
else if (a[i - 2] == '1')
total -= 2;
else
total -= 3;
} else {
if (a[i - 1] == '1')
;
else if (a[i - 2] == '1')
total--;
else
total -= 2;
}
}
i++;
}
if (total < 0)
total = 0;
cout << total << "\n";
}
return 0;
}
P.S. If you see the code, there is a line that says "if(total<0)total=0;" that is for the case when the number of buildings is equal to 1 or 2, because that case gave the wrong answer for the code that I wrote, but after that it gives a wrong answer. Please help.
And is there any way about how do I think a test case that might be violating my code for future reference?
Your method is really complicated, and I'm not sure why it is that way:
bool bombs_nearby(char *bombs, int length, int index) {
if (length == 1)
return bombs[0] == '1';
if (index == 0)
return bombs[0] == '1' || bombs[1] == '1';
if (index == length - 1)
return bombs[length - 1] == '1' || bombs[length - 2] == '1';
return bombs[index - 1] == '1' || bombs[index] == '1' || bombs[index + 1] == '1';
}
int remaining_buildings(char *bombs, int length) {
int total = 0;
for (int i=0; i<length; ++i)
if (!bombs_nearby(bombs, length, i))
total++;
return total;
}
And the test case code would just be:
cin >> n >> a;
cout << remaining_buildings(a, n) << "\n";
Test Cases
Additionally, here's a test case that you fail:
1 49 0101100010101110000101111101101010011010001100111
The correct answer is 4, but you only claim 2 houses will survive.
Why does your code fail that test case?
So, I spent some time re-reading your code. And it's actually not that bad of a method. I think if there was a comment describing what you were trying to do, it would have been very clear how you were going about it.
Sadly though, all of your pain is due to a very small bug:
while (i < n) {
if (a[i] == '1') {
if (i == '0')
total -= 2;
Note that you test i == '0'. You meant to do i == 0. You should be testing that you are not at the zeroth index, not that i is the '0' character.

Counting Multi-Character Characters in String

For example, how do you count the occurrence of "TJ" in OAEKOTJEOTJ?
if (s[i] == 'TJ') and (s[i] == 'T'+'J')
x += 1;
First one gives me an error, second one doesn't count. I need a beginner solution to this, I haven't learned very much about c++ commands yet. Thanks
int x = 0
string s;
cin >> s;
for (int i = 0; i < 100; i++)
if (s[i] == T || s[i] == t) && (s[i+1] == J || s[i+1] == j)
x += 1
cout << x << endl;
That's the excerpt from my code, it doesn't count any tj, tJ, Tj or TJ
Try using:
if(s[i] == 'T' && s[i+1] == 'J') // and make sure you do not run out of bounds of string with index i.
x += 1;
EDIT:
Based on your code:
int x = 0
string s;
cin >> s;
for (int i = 0; i < 100; i++)
if (s[i] == T || s[i] == t) && (s[i+1] == J || s[i+1] == j)
x += 1
cout << x << endl;
You should do it like following:
int x = 0
string s;
cin >> s;
for (int i = 0; i < s.length()-1; i++) // use size of string s.length()-1 to iterate the string instead of 100
if (s[i] == 'T' || s[i] == 't') && (s[i+1] == 'J' || s[i+1] == 'j') // compare the ascii values of characters like - 'T' 'J' etc.
x += 1
cout << x << endl;
std::string provides a function find which searches the string for substrings, including multi-character substrings (below, I am using C++11 syntax):
#include <iostream>
#include <string>
int main()
{
using namespace std;
string text { "OAEKOTJEOTJ" };
unsigned int occ { 0 };
size_t pos { 0 };
for (;;) {
pos = text.find("TJ",pos); // Search for the substring, start at pos
if (pos == string::npos) // Quit if nothing found
break;
++pos; // Continue from next position
++occ; // Count the occurrence
}
std::cout << "Found " << occ << " occurrences." << std::endl;
}
The way it's done above we advance by one character only after each match. Depending on whether/how we want to deal with overlapping matches, we might want to advance pos by the length of the search pattern. (See chris's comment as well.)
Try this:
#include <locale> // for tolower() function
string tolower(string s) {
tolower(s[0]);
tolower(s[1]);
return s;
}
...
int main() {
string s;
cin >> s;
int n = s.size(),cont = 0;
for(int i = 0; i < n ; ++i) {
if(tolower(s.substr(i,2)) == "tj") {
++cont;
}
}
cout << cont << endl;
return 0;
}