C++ Matching Brackets 2 Solution not working - c++

This problem which is similar to another that I solved here is giving me a wrong answer even though the algorithm works on the sample case.I have initialized all the variables this time and it works on a modified version of my previous algorithm.
#include <iostream>
int main() {
int n;
std::cin >> n;
int arr[n];
for (int i = 0; i <n ;++i) {
std::cin >> arr[i];
}
int four_count = 0, two_count = 0, three_long=0, one_long = 0 , max1_long = 0 ,max3_long = 0,a_depth = 0,max_depth = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++four_count;
three_long += 2;
}
if (arr[i] == 1) {
if (arr[i+1] == 3) {
++a_depth;
if (a_depth > max_depth) {
max_depth = a_depth;
}
}
++two_count;
one_long += 2 ;
}
if (arr[i] == 2) {
if (arr[i+1] == 4 && i < n-1) {
--a_depth;
}
--two_count;
}
if (arr[i] == 4) {
if (arr[i+1] == 2 && i < n-1){
--a_depth;
}
--four_count;
}
if (four_count == 0 && two_count == 0) {
if (three_long >= one_long) {
if (three_long > max3_long) {
max3_long = three_long+one_long;
}
three_long = 0;
one_long = 0;
}
else {
if (one_long > max1_long) {
max1_long = one_long+three_long;
}
one_long = 0;
three_long = 0;
}
}
}
std::cout << max_depth*2 << " " << max1_long << " " << max3_long;
std::cout << "\n";
return 0;
}
Here is a link to the problem:
https://www.codechef.com/ZCOPRAC/problems/ZCO12003

In the below code:
for (int i = 0; i < n; ++i) {
if (arr[i] == 3) {
if (arr[i+1] == 1) {
when i reaches n-1, arr[i+1] becomes arr[n] resulting in an out-of-bounds memory access which will lead to undefined behaviour.

Let's say n is equal to 5. That means the array arr has the maximum index 4, because the first one is 0.
In your loop
for (int i = 0; i < n; ++i)
{ if (arr[i] == 3) {
if (arr[i+1] == 1) {
at some point i becomes n-1, so i == 4, then you try arr[i+1] meaning arr[5], which is out of bound.
Note that in the comment to P.Ws post, you tried if (arr[i+1] == 1 && i < n-1) to fix this. That won't work because there still is an arr[i+1] being executed. You could fix this by using
if(i < n-1) {
if(arr[i+1]) {
but that would mean an even deeper nesting of your ifs. You should probably rethink your approach to the given problem.
Edit: Are you sure you mean ++i and not i++?

Related

Why is this code giving me segmentation, ? when we print only count then it gives answer and when print ans[4] or any value then it gives error?

I am getting segmentation error , it gives output when only print ans[k] inside the function then it
gives corrct output but in main when I try to print ans[k] then it gives segmentation
i am new at progamming so i don't know more about it so please help me it's my assigment
question is
I have to create a array of factors of a number upto 4 * 10^6
Core Dump/Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.”
When a piece of code tries to do read and write operation in a read only location in memory or freed block of memory, it is known as core dump.
It is an error indicating memory corruption.
#include <bits/stdc++.h>
using namespace std;
#define int long long int
vector<int> arr(1000001,0);
vector<int> ans;
bool isPrime(int n)
{
if (n <= 1)
return false;
if (n <= 3)
return true;
if (n % 2 == 0 || n % 3 == 0)
return false;
for (int i = 5; i * i <= n; i = i + 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
void factorpush()
{
for (int k = 5; k <= 4000001; k += 4)
{
if (isPrime(k))
{
arr[k] = 1;
}
}
arr.clear();
ans.clear();
for (int k = 5; k <= 4000001; k += 4)
{
if (arr[k] == 1)
{
int n = (k / 4);
ans[n] = (2 * n) - 1 + k;
}
else
{
vector<int> v;
for (int i = 1; i*i < k; i++)
{
if (k % i == 0)
{
if (k / i == i && i != k)
v.push_back(i);
else
{
if (i != k)
{
v.push_back(i);
}
if (k / i != k)
{
v.push_back(k/ i);
}
}
}
}
int count = k;
int count2 = 0;
for (auto x : v)
{
if (x != 1 && x!=k)
{
int n = (k/4);
count2 += ((2*n - 1)/x);
count += ((2*n - 1)/x)*x;
}
}
int n1 = (k/4);
int val = (2*n1) - 1 - count2;
count += val;
ans[n1] = count;
//cout<<ans[n1]<<"\n";
}
}
}
int32_t main()
{
factorpush();
int n;
cin>>n;
cout<<ans[n]<<"\n";`
return 0;
}
I didn't read your code well and there may be other errors, but at least the combination of
vector<int> arr(1000001,0);
and
for (int k = 5; k <= 4000001; k += 4)
{
if (isPrime(k))
{
arr[k] = 1;
}
}
is bad because arr[k] will go further than allocated.
You have to allocate enough elements like
vector<int> arr(4000002,0);
Also accessing arr[k] and ans[n] after arr.clear(); and ans.clear(); and without adding any elements is bad because the clear() function erases all elements from the vector. Also checking for arr[k] == 1 after the erasure doesn't make sense. Not understanding your code well, it looks like
arr.clear();
ans.clear();
should be replaced with something like
ans.clear();
ans.resize(1000001);

C++ weird numbers in Output

so I tried to recreate Conways Game of Life and i got it pretty much working but i have numbers in my output and i have no idea where they are coming from.
Im fairly new to c++and programming in general i learned python and java before but i have never seen this and google didnt seem to understand my question so i hope you fellow humans do.
My output looks like this:
1664447571170186994045474010000255652800 /its about this number
0000000000
0011000000
0110000000
0001000000
0000000000
0000000000
0000000000
0000000000
0000000000
anyone has any idea where they come from cause i certainly don't.
sometimes these numbers even "collide" with the board like this:
0000-1-1-1-116644475711701869940
4547401010000000
791621423110000000
0101000000
0000000000
0000000000
0000000000
0000000000
0000000000
0020000000
My sphagetthi code:
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int main(){
int x = 10, y = 10, i, j, c, b;
int field[y][x] =
{{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,1,1,0,0,0,0},
{ 0,0,0,0,1,0,1,0,0,0},
{ 0,0,0,0,1,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0}};
int updateField[y][x];
cout << "start";
for(b = 0;b<=10; b++){
cout << "main loop: "<<b<<"\n";
for(y = 0; y < 10; y++)
{
for(x = 0; x < 10; x++)
{
c = 0;
if(y == 0 || y == 9 || x == 0 || x == 9){
}
else{
/*v v v lebende zelle v v v*/
if(field[y][x] == 1){
if(field[y-1][x-1] == 1){
c++;
}
if(field[y-1][x] == 1){
c++;
}
if(field[y-1][x+1] == 1){
c++;
}
if(field[y][x-1] == 1){
c++;
}
if(field[y+1][x-1] == 1){
c++;
}
if(field[y+1][x] == 1){
c++;
}
if(field[y+1][x+1] == 1){
c++;
}
if(field[y][x+1] == 1){
c++;
}
/*regeln v v v*/
if(c < 2 or c > 3){
updateField[y][x] = 0;
}
else
{
updateField[y][x] = 1;
}
}
/*^ ^ ^ lebende zelle ^ ^ ^*/
/*v v v tote zelle v v v*/
else if(field[y][x] == 0){
if(field[y-1][x-1] == 1){
c++;
}
if(field[y-1][x] == 1){
c++;
}
if(field[y-1][x+1] == 1){
c++;
}
if(field[y][x-1] == 1){
c++;
}
if(field[y+1][x-1] == 1){
c++;
}
if(field[y+1][x] == 1){
c++;
}
if(field[y+1][x+1] == 1){
c++;
}
if(field[y][x+1] == 1){
c++;
}
/*regeln v v v*/
if(c == 3)
{
updateField[y][x] = 1;
}
else
{
updateField[y][x] = 0;
}
}
}
}
}
cout << "\n";
for(i = 0; i < 10; i++){
for(j = 0; j < 10; j++){
field[i][j] = updateField[i][j];
}
}
for(i = 0;i < x; i++){
for(j = 0; j < y; j++ )
{
cout << field[i][j];
}
cout << "\n";
}
sleep_for(nanoseconds(500000000));
}
}
I'd appreciate any answer. thanks in advance.
The problem is that you ignore the borders when building updateField (0 or 9 in a component) but then copy updateField including those borders into field. The borders in updateField were never set, so they just contain any number which was in the memory before which is not controlled by your program.
You should either set the borders of updateField to zero or do not copy the borders into field iterating from 1 to excluding 9 instead of from 0 to 10.
While I hope that this solves your problem I would also like to share some ideas how to refactor your code. For instance you could use arrays of boolean values instead of integers as the values clearly can only be 0 or 1 according to the games logic. Scanning the neighborhood of a cell also adds a lot of redundant code which can be made shorter. Just see the following as a general idea about some improvements which can be done:
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int main(){
int x = 10, y = 10, i, j, c, b;
bool field[y][x] =
{{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,1,1,0,0,0,0},
{ 0,0,0,0,1,0,1,0,0,0},
{ 0,0,0,0,1,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0},
{ 0,0,0,0,0,0,0,0,0,0}};//too lazy to rewrite to true/false, should also work this way
bool updateField[y][x];
cout << "start";
for(b = 0;b<=10; b++){
cout << "main loop: "<<b<<"\n";
for(y = 0; y < 10; y++)
{
for(x = 0; x < 10; x++)
{
c = 0;
if(y == 0 || y == 9 || x == 0 || x == 9){
updateField[y][x] = false;
}
else{
for(i=-1;i<2;i++){
for(j=-1;j<2;j++){
if((i != 0 || j != 0) && field[y+i][x+j] == 1){// exclude i == j == 0
c++;
}
}
}
if(field[y][x]){
if(c < 2 or c > 3){
updateField[y][x] = false;
}
else
{
updateField[y][x] = true;
}
}else{
if(c == 3)
{
updateField[y][x] = true;
}
else
{
updateField[y][x] = false;
}
}
}
}
}
cout << "\n";
for(i = 0; i < 10; i++){
for(j = 0; j < 10; j++){
field[i][j] = updateField[i][j];
}
}
for(i = 0;i < x; i++){
for(j = 0; j < y; j++ )
{
cout << field[i][j];
}
cout << "\n";
}
sleep_for(nanoseconds(500000000));
}
}
If you initialize updateField as well, the weird numbers will be gone.
Because of this if statement, the edge of updatefield doesn't update:
if (y == 0 || y == 9 || x == 0 || x == 9) ;
else {
///long statements
if (c < 2 || c > 3) {
updateField[y][x] = 0;
}
else
{
updateField[y][x] = 1;
}
}
Also, you should be more consistent with your usage of variables, for example you define your map to be x*y sized, but later in the for loops you specify the maximum value of x and y to be 10.
What you're seeing is the contents of uninitialized memory. When you declare int updateField[y][x]; the compiler reserves an appropriate space of memory for you, but it doesn't initialize the memory for you, so it contains whatever random junk was already there.
To fix this, initialize updateField to be identical to field before running the loop:
for (int i = 0; i < y; ++i) {
for (int j = 0; j < x; ++j) {
updateField[i][j] = field[i][j];
}
}

My Program is throwing an error that claims the vector subscript is out of range. (C++)

I am trying to create a vector that holds a user summited value worth of my class object. Unfortunately, I am running into an error that states my vector's subscript is out of range. My main guess is there might be something wrong with the way I am analyzing each element of the vector or possibly the way I am creating the vector. Any suggestions would be gladly appreciated!
...
unsigned int population = 3;
vector<Platypus> pop;
for(unsigned int i = 0; i < population; i++) {
pop.push_back(Platypus());
}
for (unsigned int i = 0; i < length; i++) {
for (unsigned int j = 0; j < population; j++) {
if (i%(int)fabs(4 - eatAmount) == 0) {
pop.at(j).eat();
}
if(pop.at(j).getAge() >= 24 &&
pop.at(j).getGender()=='F' &&
pop.at(j).getAlive()==1 &&
pop.at(j).getMutant()!=0){
pop.push_back(pop.at(j).hatch());
}
if (i > 30) {
pop.at(j).age_me(1);
}
if (j % 3 == 0 && j!=0) {
pop.at(j).fight(pop.at(j - 1));
}
pop.at(j).print(cout);
}
}
for (int i = pop.size(); i > 0; i--) {
if (pop[i].getAlive() == 0) {
pop.erase(pop.begin()+i);
}
}
}
This is you culprit:
for (int i = pop.size(); i > 0; i--) {
if (pop[i].getAlive() == 0) { // HERE
pop.erase(pop.begin()+i);
}
}
On the first loop iteration, i is initialised to the size of the vector. To turn this into a valid index, you need to subtract 1, or otherwise you go out of bounds.

Delete enemy from vector array

This is my first question on this site. I learn programming for a year and I always found a answer for my problem in projects. I know that this is REALLY simple problem and here is a code:
#include "stdafx.h"
#include "Wave.h"
Wave::~Wave()
{
}
void Wave::setEnemyCount(int count) {
nemyCount = count;
}
bool Wave::createWave() {
for (int i = 0; i < enemyCount; i++) {
enemyArray.push_back(Enemy());
}
for (int i = 0; i < enemyArray.size(); i++) {
int randomPositionX = rand() % 150 + 10;
int randomPositionY = rand() % 50 + 10;
if (!enemyArray.at(i).init(randomPositionX, randomPositionY)) {
std::cout << "Create wave(init enemies) - failed\n";
return false;
}
}
return true;
}
void Wave::drawWave(Window* window) {
window->setCursor({ 0, 2 });
window->setColor(Window::Color::RED);
std::cout << "Enemies: " << enemyArray.size();
window->setColor(Window::Color::WHITE);
for (int i = 0; i < enemyArray.size(); i++) {
enemyArray.at(i).draw(window);
//std::cout << i;
}
}
void Wave::update(Bullet* bullet, Player* player) {
for (int i = 0; i < enemyArray.size(); i++) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(enemyArray.begin() + i);
}
}
}
}
if (enemyArray.size() <= 0) {
std::cout << "WAVE COMPLETE";
Sleep(2000);
enemyCount += 5;
createWave();
}
}
int Wave::getEnemyCount() const {
return enemyCount;
}
The collision work correct, but when bullet touch a enemy of index for example: 5, a code always remove the enemy of last index, so I can remove each enemy only shoot to one enemy with index 5 or 1 or 7.
When you do enemyArray.erase(...) you shouldn't increment i because you will skip one element.
So you should rewrite the loop like this:
for (int i = 0; i < enemyArray.size();) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= enemyArray.at(i).getPositionX() && bullet->getPositionX() <= enemyArray.at(i).getPositionX() + 5)) {
if ((bullet->getPositionY() >= enemyArray.at(i).getPositionY() && bullet->getPositionY() <= enemyArray.at(i).getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(enemyArray.begin() + i);
continue;
}
}
}
++i;
}
Or, with a more idiomatic style:
for (auto it = enemyArray.begin(), end = enemyArray.end();it!=end;) {
if (player->checkShoot()) {
if ((bullet->getPositionX() >= it->getPositionX() && bullet->getPositionX() <= it->getPositionX() + 5)) {
if ((bullet->getPositionY() >= it->.getPositionY() && bullet->getPositionY() <= it->getPositionY() + 5)) {
player->addScore(10);
enemyArray.erase(it);
continue;
}
}
}
++it;
}
Of course, if you wan a single enemy to be removed at a time, you should break instead of continue in the loop, after having erased the element.
For completeness, you can also use std::remove_if if you want to remove all enemies touched by the bullet, it's more optimal than the 2 loops above, because it does less moving of elements when multiple elements are removed.

C++ counting how many times data in array changes changed directions?

My program is suppose to count how many times the data in my array changed from increase to decrease or vice versa. For example: {1,2,3,4,3,4}
changes twice as the first four elements are increasing then decrease o 3 (causing one change) and then increase back to four causing a second change.
The idea in my code was that every time greater or decrease changed to false it would count when it happened but I cannot get it to work.
Any help is greatly appreciated as I am really struggling with this!
unsigned count = 0;
bool greater = true;
bool decrease = true;
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else
greater = false;
count++;
}
for (unsigned i = 0; i < elements; i++){
if (a[i + 1] < a[i]){
decrease = true;
}
else
decrease = false;
count++;
}
return count;
Your logic is wrong
you may do something like
enum class EDirection { none, decreasing, increasing};
std::size_t count_direction_changes(const std::vector<int>& v)
{
std::size_t res = 0;
EDirection direction = EDirection::none;
for (std::size_t i = 1; i != v.size(); ++i) {
const int diff = v[i] - v[i - 1];
switch (direction)
{
case EDirection::none: {
if (diff == 0) {
break;
}
direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing;
break;
}
case EDirection::increasing: {
if (diff < 0) {
++res;
direction = EDirection::decreasing;
}
break;
}
case EDirection::decreasing: {
if (diff > 0) {
++res;
direction = EDirection::increasing;
}
break;
}
}
}
return res;
}
Demo
You must change your loops. First of all you should stop the loop at size-1. Because you are comparing with next element and you can go out of bounds if your for is running until elements instead of elements-1.
Furthermore, you have a logic issue. If you are using a boolean variable as flag, you should check if it's true or not before increasing your counter. And in case you increments your counter you must reset that flag. Something similar to down loop should work. Maybe there is some little mistake because I don't have anythin to test it now. But it should be something similar to this.
for (unsigned i = 0; i < elements-1; i++){
if (a[i + 1] > a[i]){
greater = true;
}
else{
greater = false;
}
if(greater){
count++;
greater = false;
}
}
This is a lot like Jarod42's, but seeing as I've already coded it will throw it out there. BTW, I use the slightly awkward v[n] < v[n - 1] so it's only necessary to implement operator< to apply the algo to a user-defined type (i.e. not operator> as well).
#include <iostream>
#include <vector>
template <typename T>
size_t changes(const std::vector<T>& v)
{
if (v.size() <= 2) return 0;
size_t count = 0;
enum { Increasing, Decreasing, Flat } last;
last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat;
for (size_t i = 2; i < v.size(); ++i)
if (v[i - 1] < v[i])
{
if (last == Decreasing) ++count;
last = Increasing;
}
else if (v[i] < v[i - 1])
{
if (last == Increasing) ++count;
last = Decreasing;
}
return count;
}
int main()
{
std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n';
std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n';
}
See it run here.
Here is another approach, similar to Tony's and Jarod's:
#include <vector>
#include <cassert>
#include <iostream>
size_t countTrendChanges(const std::vector<int>& a) {
if (a.size() < 3)
return 0;
int trend = 0;
size_t count = 0;
for (size_t i = 1; i != a.size(); ++i) {
int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]);
if (new_trend == 0)
continue;
if (trend != 0 && new_trend != trend)
count++;
trend = new_trend;
}
return count;
}
int main() {
assert(countTrendChanges({}) == 0);
assert(countTrendChanges({1}) == 0);
assert(countTrendChanges({3,2,1}) == 0);
assert(countTrendChanges({1,2,3}) == 0);
assert(countTrendChanges({1,2,2,3}) == 0);
assert(countTrendChanges({3,2,1,2,3}) == 1);
assert(countTrendChanges({1,2,3,2}) == 1);
assert(countTrendChanges({2,1,1,2}) == 1);
assert(countTrendChanges({1,2,2,1}) == 1);
assert(countTrendChanges({1,2,3,4,3,4}) == 2);
}