Weird results with swap and substr functions - c++

I was trying to solve solve questions at TopCoder. I was getting weird results on test sections of TopCoder; however, when I submit my code I got AC(stands for accepted). The case was the same on TCHS SRM 47 Level one - 250 pt - Cards Shuffle. I used swap function, my code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int f, l, t;
string c;
cin>>c;
scanf("%d%d%d", &f, &l, &t);
//while(t--) c=c.substr(f-1, l-f+1)+c.substr(0, f-1)+c.substr(l);
while(t--) for(int i=0, j=f-1; j<=l-1; i++, j++) swap(c[i], c[j]);
cout<<c;
return 0;
}
returns WA(stands for wrong answer) on test section of TC(stands for TopCoder), and AC when submitted on TC. Then I checked the code on ideone, with both substr and swap functions respectively. On first try substr function gave expected result, while swap function unexpected result. However, on second try it was vice versa. I dont know what is going on, whether my code has a bug, or ideone, or TopCoder testing system.

Your Algorithm
Your algorithm using swap is faulty. Let's walk through the steps for one iteration of the while loop. You have:
for ( int i = 0; j = f-1; j <= l-1; ++i, ++i )
swap(c[i], c[j]);
I don't know why you are using f, l, and t. It will be so much easier to read if you use first, last, and times.
for ( int i = 0; j = first-1; j <= last-1; ++i, ++i )
swap(c[i], c[j]);
Let's use the following input:
ABCDEFGHIJ
5 6 1
In the first iteration of the for loop,
i = 0;
j = 4;
after the swap, the new value of c is
EBCDAFGHIJ (A and E are swapped)
In the second iteration of the for loop,
i = 1;
j = 5;
after the swap, the new value of c is
EFCDABGHIJ (B and F are swapped)
The iteration stops here since the value of j becomes 6.
What you needed to end up with is:
EFABCDGHIJ
A Different Algorithm
If you want to minimize the number of strings created, you can use the following strategy.
For the given inputs, create the sub-string "EF" and store it. Then move "ABCDE" to the right by two. Then move "EF" to the start of the string. The following function does that. It changes c in place.
void fun(string& c, int first, int last)
{
// Convert first to a 0-based index for easier manipulation.
--first;
int delta = last-first;
string c1 = c.substr(first, delta);
for ( int i = first-1; i >= 0; --i )
{
c[i+delta] = c[i];
}
for ( int i = 0; i < delta; ++i )
{
c[i] = c1[i];
}
}

Related

Find a combination of elements from different arrays

I recently started learning C++ and ran into problems with this task:
I am given 4 arrays of different lengths with different values.
vector<int> A = {1,2,3,4};
vector<int> B = {1,3,44};
vector<int> C = {1,23};
vector<int> D = {0,2,5,4};
I need to implement a function that goes through all possible variations of the elements of these vectors and checks if there are such values a from array A, b from array B, c from array C and d from array D that their sum would be 0(a+b+c+d=0)
I wrote such a program, but it outputs 1, although the desired combination does not exist.
using namespace std;
vector<int> test;
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <= A.size(); ai++){
test[0] = A[ai];
for ( int bi = 0; bi <= B.size(); bi++){
test[1] = B[bi];
for ( int ci = 0; ci <= C.size(); ci++){
test[2] = C[ci];
for ( int di = 0; di <= D.size(); di++){
test[3] = D[di];
if (sum (test) == 0){
return true;
}
}
}
}
}
}
I would be happy if you could explain what the problem is
Vectors don't increase their size by themself. You either need to construct with right size, resize it, or push_back elements (you can also insert, but vectors arent very efficient at that). In your code you never add any element to test and accessing any element, eg test[0] = A[ai]; causes undefined behavior.
Further, valid indices are [0, size()) (ie size() excluded, it is not a valid index). Hence your loops are accessing the input vectors out-of-bounds, causing undefined behavior again. The loops conditions should be for ( int ai = 0; ai < A.size(); ai++){.
Not returning something from a non-void function is again undefined behavior. When your abcd0 does not find a combination that adds up to 0 it does not return anything.
After fixing those issues your code does produce the expected output: https://godbolt.org/z/KvW1nePMh.
However, I suggest you to...
not use global variables. It makes the code difficult to reason about. For example we need to see all your code to know if you actually do resize test. If test was local to abcd0 we would only need to consider that function to know what happens to test.
read about Why is “using namespace std;” considered bad practice?
not pass parameters by value when you can pass them by const reference to avoid unnecessary copies.
using range based for loops helps to avoid making mistakes with the bounds.
Trying to change not more than necessary, your code could look like this:
#include <vector>
#include <iostream>
int sum (const std::vector<int>& v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(const std::vector<int>& A,
const std::vector<int>& B,
const std::vector<int>& C,
const std::vector<int>& D){
for (const auto& a : A){
for (const auto& b : B){
for (const auto& c : C){
for (const auto& d : D){
if (sum ({a,b,c,d}) == 0){
return true;
}
}
}
}
}
return false;
}
int main() {
std::vector<int> A = {1,2,3,4};
std::vector<int> B = {1,3,44};
std::vector<int> C = {1,23};
std::vector<int> D = {0,2,5,4};
std::cout << abcd0(A,B,C,D);
}
Note that I removed the vector test completely. You don't need to construct it explicitly, but you can pass a temporary to sum. sum could use std::accumulate, or you could simply add the four numbers directly in abcd0. I suppose this is for exercise, so let's leave it at that.
Edit : The answer written by #463035818_is_not_a_number is the answer you should refer to.
As mentioned in the comments by #Alan Birtles, there's nothing in that code that adds elements to test. Also, as mentioned in comments by #PaulMcKenzie, the condition in loops should be modified. Currently, it is looping all the way up to the size of the vector which is invalid(since the index runs from 0 to the size of vector-1). For implementing the algorithm that you've in mind (as I inferred from your code), you can declare and initialise the vector all the way down in the 4th loop.
Here's the modified code,
int sum (vector<int> v){
int sum_of_elements = 0;
for (int i = 0; i < v.size(); i++){
sum_of_elements += v[i];
}
return sum_of_elements;
}
bool abcd0(vector<int> A,vector<int> B,vector<int> C,vector<int> D){
for ( int ai = 0; ai <A.size(); ai++){
for ( int bi = 0; bi <B.size(); bi++){
for ( int ci = 0; ci <C.size(); ci++){
for ( int di = 0; di <D.size(); di++){
vector<int> test = {A[ai], B[bi], C[ci], D[di]};
if (sum (test) == 0){
return true;
}
}
}
}
}
return false;
}
The algorithm is inefficient though. You can try sorting the vectors first. Loop through the first two of them while using the 2 pointer technique to check if desired sum is available from the remaining two vectors
It looks to me, like you're calling the function every time you want to check an array. Within the function you're initiating int sum_of_elements = 0;.
So at the first run, you're starting with int sum_of_elements = 0;.
It finds the element and increases sum_of_elements up to 1.
Second run you're calling the function and it initiates again with int sum_of_elements = 0;.
This is repeated every time you're checking the next array for the element.
Let me know if I understood that correctly (didn't run it, just skimmed a bit).

How does C++ while code including two integers operate step by step?

I am quite new to C++ programming, I have reviewed while loops in python before however the two integers confuse me here. I would be very happy if you can explain to me how this while loop operates step by step.
#include<iostream>
using namespace std;
int main() {
int i;
int j;
while(i<10 || j < 5) { // i kucuk ondan kucuk oldu surece {} icerisindeki islemler surekli olarak while() loopu ile tekrarlancak
cout<<"i: "<<i<<" "<<"j: "<<j<<endl;
i = i + 1; // eger bu kod olmaz ise, sonsuza dek i degerine basacak
j = j + 1;
}
return 0;
}
#include<iostream>
using namespace std;
int main() {
/* You should first give a starting value
to the I and j, otherwise they
will get a random number and your while won't work*/
int i=0;
int j=0;
/* so as the word says "while" - while (something here is true)do the
following code between the starting
brackets and the finishing brackets. When it's not True skip the loop and go to the next line, in this example we will go to return 0 */
/*The value of i is 0 and the value of j is 0, and we first check if 0(i)<10 that's true next we check the other one
if 0(j) < 5 yes do the following block*/
/* the || mean "or' if either one of them
is true do the following block of code between the brackets*/
while(i<10 || j < 5) {
//we print
cout<<"i: "<<i<<" "<<"j: "<<j<<endl;
//we are incrementing the values of i and j for 1;
i = i + 1;
j = j + 1;
/*so what happens now it jumps again to the while
and checks if the statement is true, now i = 1 and j = 1;
and this runs until i is 10 because only then the i won't be lesser then
10 and j won't be lesser then 5 it will be false*/
*/
}
//close the program
return 0;
}
Hope I was clear!
You don't declare variables in Python. A "variable" is created when you first assign a value to a name. So you can't have uninitialized variables in Python.
That is not the case in C and C++. This code is declaring the i and j variables, but not assigning any values to them before trying to use them in the while loop. So your code has undefined behavior, as the variables contain whatever random values happened to already be present in memory where they get allocated.
You need to initialize the variables before your loop tries to evaluate them:
int i = 0;
int j = 0;

Doing away with Runtime Error(SIGSEGV)

I don't think in my code I tried accessing null pointers, or initialising large arrays, someone help please, I dunno where the Runtime Error(SIGSEGV) is coming from. Question to problem can be found at https://www.codechef.com
/MARCH18B/problems/MINEAT
edit:
I think i found out, NathanOliver was right, v1, because of my code, happens to be sometimes empty. Some answers were actually found out of my loop (above n). Thanks alot. I fixed that and I finally got AC, but just 30 points, my code took an additional 0.01 seconds to run. Can anyone help me optimize it, based on Problem statement, Please.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; cin>>t; while(t--)
{
int n = 0, h = 0; cin>>n>>h;
vector<int> v; vector<int> v1;
for(int i = 0; i != n; i++){int a; cin>>a; v.push_back(a);}
for(int j = 1; j <= h; j++)
{
int hold = 0;
for(auto k : v)
{
if (j >= k){hold +=1;}
else if (j < k){if(k % j == 0){hold += (k/j);} else{hold += ((k/j)+1);}}
}
if (hold <= h){v1.push_back(j);}
}
cout<<*min_element(v1.begin(),v1.end())<<endl;
}
}
Did you check the min_element function's return value? According to the user input, min_element function returns an iterator to 'last element' which is basically a nullptr. Since you're dereferencing it directly, you get the error.

why am I getting seg fault in this?

Problem Statement
Mark is an undergraduate student and he is interested in rotation. A conveyor belt competition is going on in the town which Mark wants to win. In the competition, there's A conveyor belt which can be represented as a strip of 1xN blocks. Each block has a number written on it. The belt keeps rotating in such a way that after each rotation, each block is shifted to left of it and the first block goes to last position.
There is a switch near the conveyer belt which can stop the belt. Each participant would be given a single chance to stop the belt and his PMEAN would be calculated.
PMEAN is calculated using the sequence which is there on the belt when it stops. The participant having highest PMEAN is the winner. There can be multiple winners.
Mark wants to be among the winners. What PMEAN he should try to get which guarantees him to be the winner.
Definitions
PMEAN = (Summation over i = 1 to n) (i * i th number in the list)
where i is the index of a block at the conveyor belt when it is stopped. Indexing starts from 1.
Input Format
First line contains N denoting the number of elements on the belt.
Second line contains N space separated integers.
Output Format
Output the required PMEAN
Constraints
1 ≤ N ≤ 10^6
-10^9 ≤ each number ≤ 10^9
Code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main (void)
{
int n;
cin>>n;
vector <int> foo;
int i = 0,j = 0,k,temp,fal,garb=0;
while (i < n)
{
cin>>fal;
foo.push_back(fal);
i++;
}
vector<int> arr;
//arr.reserve(10000);
for ( i = 0; i < n; i++ )
{
garb = i+1;
arr.push_back(garb);
}
long long product = 0;
long long bar = 0;
while (j < n)
{
i = 0;
temp = foo[0];
while ( i < n-1 )
{
foo[i] = foo[i+1];
i++;
}
foo[i] = temp;
for ( k = 0; k < n; k++ )
bar = bar + arr[k]*foo[k];
if ( bar > product )
product = bar;
j++;
}
return 0;
}
My Question:
What I am doing is basically trying out different combinations of the original array and then multiplying it with the array containing the values 1 2 3 ...... and then returning the maximum value. However, I am getting a segmentation fault in this.
Why is that happening?
Here's some of your code:
vector <int> foo;
int i = 0;
while (i < n)
{
cin >> fal;
foo[i] = fal;
i++;
}
When you do foo[0] = fal, you cause undefined behavior. There's no room in foo for [0] yet. You probably want to use std::vector::push_back() instead.
This same issue also occurs when you work on vector<int> arr;
And just as an aside, people will normally write that loop using a for-loop:
for (int i=0; i<n; i++) {
int fal;
cin >> fal;
foo.push_back(fal);
}
With regards to the updated code:
You never increment i in the first loop.
garb is never initialized.

Can someone explain this source code for balanced partitioning?

Can someone please explain this code in detail? I've tried debugging it but i can't figure out how it produces the result. I've been searching for a solution for the problem and this is the code that I stumbled upon, it produces accurate solutions and I would like to know how it works. Many thanks.
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;
int BalancedPartition ( int a[] , int n ){
int sum = 0;
for( int i = 0 ; i < n ; i++)
sum += a[i];
int *s = new int[sum+1];
s[0] = 1;
for(int i = 1 ; i < sum+1 ; i++) s[i] = 0;
int diff = INT_MAX , ans;
for(int i = 0 ; i < n ; i++)
{
for(int j = sum ; j >= a[i] ; j--)
{
s[j] = s[j] | s[j-a[i]];
if( s[j] == 1 )
{
if( diff > abs( sum/2 - j) )
{
diff = abs( sum/2 - j );
ans = j;
}
}
}
}
return sum-ans-ans;
}
int main()
{
int n,result, arr[300];
cin >>n;
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
result = BalancedPartition(arr,n);
cout <<abs(result); // The difference between the sums of the two subsets
return 0;
}
The function BalancedPartition first computes the summation of the elements of the array a and stores it in sum. It then allocates an array s that is indexed by possible subset summation values. It serves as a bookkeeping structure that tracks the progress of the inner for loop. If s[j] is 1, it means the value j has been processed, where the value j represents the summation of some subset of elements in the array a. Initially, only s[0] is set to 1, which corresponds to the sum of no elements (the empty subset). diff is used to compute the subset with the summation closest to one half the value of sum, and this subset summation value is stored in ans. Once ans is correctly computed, the value returned is the difference between the summation of the elements not used in ans and ans itself, that is, (sum - ans) - ans. So, what's left is the double for loop, to see how it correctly arrives at diff and ans.
The outer for loop iterates i through all the indexes of the array a. The inner loop iterates j through all possible subset summation values, starting with sum. However, it only recognizes a subset summation value if the value is derivable from a previously recognized subset sum. That is, for any given iteration of j, s[j] becomes 1 only if s[j - a[i]] is 1. Since initially only the empty subset is recognized, the first iteration only recognizes s[a[0]]. The second iteration recognizes s[a[1]] and s[a[0]+a[1]]. The third iteration recognizes s[a[2]], s[a[0]+a[2]], s[a[1]+a[2]] and s[a[0]+a[1]+a[2]]. If you recognize the pattern, you can formulate an inductive argument for the correctness of the algorithm.