I've tried searching for an answer on StackOverflow and googled multiple times. I'm not really sure what exactly is wrong with the code. When I run it on Eclipse Luna, it just says "solution.exe has stopped working". Can anyone help me find out what's wrong here? Or give me a way to find out for myself?
This is my code:
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
long mergeCountInv(long list[],long tmp[],long left,long mid,long right);
long countInv(long list[],long tmp[],long left,long right);
long mergeCountInv(long list[],long tmp[],long left,long mid,long right) {
long i = 0,j = mid + 1,k = 0;
long count = 0;
while(i < mid && j < right) {
if(list[i] <= list[j]) {
tmp[k++] = list[i++];
}
else if(list[i] > list[j]) {
tmp[k++] = list[j++];
count++;
}
}
while(i < mid) {
tmp[k++] = list[i++];
}
while(j < right) {
tmp[k++] = list[j++];
}
return count;
}
long countInv(long list[],long tmp[],long left,long right) {
long k = 0,mid;
if(right == 1) return 0;
else {
mid = (left + right)/2;
k = countInv(list,tmp,left,mid) + countInv(list,tmp,mid + 1,right) + mergeCountInv(list,tmp,left,mid,right);
}
return k;
}
int main() {
long list[100001];
long i,x=0;
///////////////FILE HANDLING////////////////////////////////
ifstream fin;
fin.open("IntegerArray.txt");
while (!fin.eof()) {
fin >> i;
list[x] = i;
x++;
}
fin.close();
////////////////////////////////////////////////////////////
long size = sizeof(list)/sizeof(long) - 1;
long *tmp = new long[size];
cout<<countInv(list,tmp,0,size);
delete []tmp;
return 0;
}
These are the contents of "IntegerArray.txt":
6
3
5
4
2
1
There are actually going to be 100000 integers in the file, but I'm trying it out with a smaller test case first.
I would appreciate your help! Thanks.
The recursion never terminates if right is greater than 1, as your base case for the recursion is right == 1 while you have one recursive call that passes right unmodified.
That is, countInv(x,y,l,r) calls countInv(x,y,amidpoint,r), which calls countInv(x,y,anothermidpoint,r), and so on, until you're stuck in countInv(x,y,r-1,r) forever.
Exactly how to fix it depends on what the code is supposed to do, but you most likely want a base case that involves left as well as right.
Related
for a while now I've been trying to get this code to work to partition (as if preparing for quicksort) the indexes of substring suffixes, and while it's close I'm not getting what I'm expecting. I was wondering if a fresh set of eyes may help.
int partition(const string &S, vector<int> &indices, int low, int high, int pivotIndex)
{
int i = low;
int j = high - 1;
swap(indices[high], indices[pivotIndex]);
while (i <= j)
{
while (i < high && !lessThan(S, S[i], S[indices[high]]))
i++;
while (j >= low && lessThan(S, S[j], S[indices[high]]))
j--;
if (i < j)
{
int temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
i++;
j--;
}
}
swap(indices[high], indices[i]);
return i;
}
Indices is simply a vector of 0, 1, 2, ..., n of same size as string S.
And here's the program I wrote for lessThan just so you know what I'm working with:
bool lessThan(const string &S, int first, int second)
{
int counter = (int)S.length() - ((first <= second) ? second : first);
for (int i = 0; i <= counter; ++i)
{
if (S[first + i] != S[second + i])
{
if (S[first + i] < S[second + i])
{
return true;
}
else
{
return false;
}
}
}
if (first < second)
{
return false;
}
else
{
return true;
}
}
lessThan seems to work just fine when I test it separately, so I don't think it's the issue, but maybe it is.
Whenever I test, with say the string "abracadabra", and setting the pivotIndex to 4, I expect to get "0 1 8 3 10 5 7 4 2 9 6" as my output but I instead get "0 1 8 3 7 5 4 10 2 9 6". Close, but not quite. Can anyone spot my mistake?
(P.S. I know I could probably use substr() or some other solution to do lessThan easier, but I'm trying to do it without allocating extra memory, my focus is on the partition function)
edit: I figured it out. Complete error on my side. Check below for answer
I was an idiot, input to lessThan was supposed to be given two ints. I instead gave it two chars from S. Also swapped which lessThan call the ! was on. I think I was just up too late programming and blame this all on sleep deprivation.
Fixed Code:
int partition(const string &S, vector<int> &indices, int low, int high, int pivotIndex)
{
int i = low;
int j = high - 1;
swap(indices[high], indices[pivotIndex]);
while (i <= j)
{ //This right here
while (i < high && lessThan(S, indices[i], indices[high]))
i++;
while (j >= low && !lessThan(S, indices[j], indices[high]))
j--;
if (i < j)
{
swap(indices[i], indices[j]);
i++;
j--;
}
}
swap(indices[high], indices[i]);
return i;
}
I'm doing question 4.11 in Bjarne Stroustrup Programming-Principles and Practice Using C++.
Create a program to find all prime numbers in the range from 1 to max using a vector of primes in order(prime[2,3,5,...]). Here is my solution:
#include <iostream>
#include <string>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
bool check_prime(vector<int> &prime, int n) {
int count = 0;
for (int i = 0; prime[i] <= n || i <= prime.size() - 1; ++i) {
if (n % prime[i] == 0) {
count++;
break;
}
}
bool result = 0;
if (count == 0)
result = 1;
else
result = 0;
return result;
}
int main() {
vector<int> prime{2};
int max;
cout << "Please enter a max value:";
cin >> max;
for (int i = 2; i <= max; ++i) {
if (check_prime(prime, i))
prime.push_back(i);
}
for (int i = 0; i <= prime.size() - 1; ++i) {
cout << prime[i];
if (i <= prime.size() - 2)
cout << ',';
}
}
My code is working for numbers smaller than 23 but fail to work for anything bigger. If I open the program in Windows 10 the largest working number increase to 47, anything bigger than that fail to work.
This condition
prime[i]<=n||i<=prime.size()-1
makes the loop continue as long as at least one of them is true, and you're accessing prime[i] without checking the value of i.
This will cause undefined behaviour as soon as i == prime.size().
This means that anything can happen, and that you're experiencing that any specific values are working is just an unfortunate coincidence.
You need to check the boundary first, and you should only continue for as long as both conditions are true:
i <= prime.size() - 1 && prime[i] <= n
which is more idiomatically written
i < prime.size() && prime[i] <= n
(It's never too soon to get comfortable with the conventional half-open intervals.)
You check prime[i]<=n before i<=prime.size()-1. Then, if it's true (even if i>prime.size()-1, which is random behaviour), you work on it, generating wrong results.
So I am a beginner in c++ programming and I was doing some problem online.
I have to calculate all the products of numbers from 999 to 100 (Eg.999*999 , 999*998 ... 800* 800 , 800 *799 ... , 100 * 100). I can easily print out these products but when I try to pass these values to a function they do not work.
Can you please look at the following code and point out anything that's wrong?
I think its got something to do with buffer but I have no idea how to fix that. Thanks.
#include <iostream>
using namespace std;
unsigned long int num,rev,temp,rem = 0,reversed = 0;
int ispalin(unsigned long int n)
{
temp=n;
while(temp!=0)
{
rem = temp%10;
reversed = reversed*10 + rem;
temp/=10;
}
if(reversed == n)
{
return 1;
}
return 0;
}
int main()
{
int maxi = 0;
for (int i =999 ; i >= 100;i--)
{
for(int j = i;j >= 100; j--)
{
rev = ispalin(i*j);
if (rev == 1)
{
if(i*j > maxi)
{
maxi = i*j;
}
}
}
}
cout<<maxi<<" This is max"<<endl;
}
reversed must be reset to zero at the beginning of every check for palindrome. The best would be to make reversed (and others) a local variable of ispalin.
I'm encountering an error I've not seen before, that states that reference to things are ambiguous.
I'm writing a small test program that calculates a running median. As the list grows, it recalculates the median. In this case, median means the middle number in the list, (or upper middle). Thus, the median of 7 is 7, the median of 7 and 9 is 9, and the median of 7 3 and 9 is 7.
I'm accomplishing this (I hope) with two dynamic arrays. Initially, the first value is set as the median, and then each number entered is compared to the current median. The median is obtained for calculating the middle element, between two arrays.
The left array is for all values less than the median, and the right array is for all greater. I use insertion sort to order the numbers in each array (it's great at almost sorted lists).
I just don't understand the errors I'm getting and or where I've gone wrong. I'm fairly new to C++, so I've opted for a more simple approach to the issue.
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> left;
vector<int> right;
int leftCount = 0;
int rightCount = 0;
void leftInsertionSort(int);
void rightInsertionSort(int);
void inputNumber(int, int);
int main(int argc, char** argv) {
int length = 0;
int value;
int median;
string input;
while (cin >> input) {
value = atoi(input.c_str());
inputNumber(value, median);
if (leftCount > rightCount) {
median = (((leftCount + rightCount) / 2) + 1);
cout << left[median];
} else {
median = (((leftCount + rightCount) / 2) + 1) - leftCount;
cout << right[median];
}
}
return 0;
}
void inputNumber(int value, int median) {
if (leftCount == 0 && rightCount == 0) {
left[0] = value;
median = value;
leftCount++;
} else
if (leftCount == 1 && rightCount == 0) {
right[0] = value;
if (left[0] > right[0]) {
right[0] = left[0];
left[0] = value;
}
median = right[0];
rightCount++;
} else
if (value < median) {
left[leftCount] = value;
} else {
right[rightCount] = value;
}
}
void leftInsertionSort(int lLength)
{
leftCount++;
int key, i;
for(int j = 1; j < lLength; j++)
{
key = left[j];
i = j - 1;
while (left[i] > key && i >= 0) {
left[i+1] = left[i];
i--;
}
left[i+1] = key;
}
}
void rightInsertionSort(int rLength)
{
rightCount++;
int key, i;
for(int j = 1; j < rLength; j++)
{
key = right[j];
i = j - 1;
while (right[i] > key && i >= 0) {
right[i+1] = right[i];
i--;
}
right[i+1] = key;
}
}
The error I seem to be getting is 'error: reference to ‘left’ is ambiguous'
Judging from the compiler error I get when trying to compile that, it seems that the namespace std defines names left and right, which you're also using as variable names. The compiler can't decide which definition to use, so you get the error. It's for reasons like these that importing everything from a namespace is frowned upon - you'd be better off either explicitly importing the names you need or using namespace qualifiers.
In any case, your algorithm seems needlessly complicated. Why not just keep a single vector, push_back into it when you get a new number, place the number at the right index using an insertion algorithm, and then just return the upper middle element of the vector?
left and right are flags in iostream.
Just rename the variables.
This is a good example of why #using namespace std is not a good idea. left and right are also defined for the std namespace and there's now a conflict. If you leave out that line and refer to vector, string, cin and cout by specifying their namespace explicitly with std:: you wouldn't have encountered this conflict.
I'm trying to solve a problem which is something like this:
I'm given n numbers (1<=n<=10^5).I have to write the sum of all numbers on its left which are smaller than the current number and repeat the process for all n numbers.Then I have to find the sum of all previously obtained sum's.(Each number N,0<=N<=10^6).
For example,
1 5 3 6 4
less1 less5 less3 less6 less4
(0) + (1) + (1)+(1+5+3)+(1+3)
0 + 1 + 1 + 9 + 4
= 15
A trivial solution for this problem will be to run two loops and for each of the given number find sum of all the numbers less than that number and finally give the sum of those sum's as output.The time complexity is O(n^2).
I think a better O(nlogn) solution for this problem using Binary Indexed Tree(Fenwick Tree).
For each number I'll add each of the number in a global array a and perform two obvious operations of BIT.I think the time complexity of this algorithm is O(nlogn) which if true is obviously better than the previous O(n^2).
I have implemented the code in C++.
#include<iostream>
#include<cstdio>
using namespace std;
#define max 1000001
long int a[max];
void add(long int v,int idx){
while(idx<max){
a[idx] += v;
idx += (idx & -idx);
}
}
long int sum(int idx){
long int s=0;
while(idx>0){
s += a[idx];
idx -= (idx & -idx);
}
return s;
}
int main()
{
int t;
scanf("%d",&t);
for(int w=0;w<t;w++){
int n;
scanf("%d",&n);
for(int i=0;i<max;i++)
a[i]=0;
int arr[n];
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
long long res=0;
for(int i=0;i<n;i++){
if(arr[i]!=0){
add(arr[i],arr[i]);
res += (sum(arr[i]-1));
}
}
printf("%lld\n",res);
}
return 0;
}
I have two questions:
First, am I doing it correct? / Is my logic correct?
Second, if I'm right about the time complexity to be O(nlogn) then why does it run slow? Can you help me with any further optimizations?
Got Accepted with 1.41 seconds.At same time I have updated my finally accepted code.Any suggestion for optimization ?
Based on the comments I tried my own function for faster I/O but still it's not going my way.This is my function for fast I/O :
inline int read(){
char c=getchar_unlocked();
int n=0;
while(!(c>='0' && c<='9'))
c=getchar_unlocked();
while(c>='0' && c<='9'){
n=n*10 + (c-'0');
c=getchar_unlocked();
}
return n;
}
This is the link to the problem :
http://www.spoj.pl/problems/DCEPC206/
If there is anyone who is abled to solve it,please let me know.
Thanks.
I think your approach is a good one. I've played around with this a wee bit and haven't come up with anything generally better than what you have.
There are a couple of bugs in your code though. There are a few places suffering from integer overflow. You should change to:
long long a[max];
and
long long sum(int idx){
long long s=0;
The more apparent bug is that you're summing numbers which are less than or equal to the current number. To fix this issue, you could add a second global array for tracking the count of each value:
int b[max];
...
...
for(int i=0;i<max;i++)
a[i]=b[i]=0;
...
...
res += (sum(idx)-(++b[idx]*val));
There may be a more efficient way to fix that bug, but overall it still seems like a fast solution.
Here is another approach: the problem is similar to counting inversions, except you have to sum the elements responsible for generating inversions. We can solve this using merge sort. Modify the merge function like this:
merge(left, middle, right, array)
temp = new array
k = 0, i = left, j = middle + 1
while i <= middle and j <= right
if array[i] < array[j]
temp[k++] = array[i]
// array[i] is also smaller than all array[j+1], ..., array[right]
globalSum += array[i] * (right - j + 1)
else
// same as the classical function
Intuitively, I would say a recursive mergesort is slower than a BIT solution, but who knows? Give it a try.
Edit: This gets AC:
#include<stdio.h>
#include <iostream>
using namespace std;
#define max 100001
int n;
long long res = 0;
int temp[max];
int arr[max];
void merge(int left, int m, int right)
{
int k = 0;
int i = left, j = m + 1;
while (i <= m && j <= right)
if (arr[i] < arr[j])
{
temp[k++] = arr[i];
res += (long long)(right - j + 1) * arr[i++];
}
else
temp[k++] = arr[j++];
while (j <= right)
temp[k++] = arr[j++];
while (i <= m)
temp[k++] = arr[i++];
for (int i = 0; i < k; ++i)
arr[left + i] = temp[i];
}
void sort(int left, int right)
{
if (left < right)
{
int m = left + (right - left) / 2;
sort(left, m);
sort(m + 1, right);
merge(left, m, right);
}
}
int main()
{
int t;
scanf("%d", &t);
for(int w=0;w<t;w++)
{
scanf("%d", &n);
for(int i=0;i<n;i++)
scanf("%d", &arr[i]);
res=0;
sort(0, n - 1);
printf("%lld\n",res);
}
return 0;
}