Reversing positive sequences in array - c++

So, I have a cycle that goes over an array and should reverse the sequence of consecutive positive numbers, but it seems to count excess negative number as a part of a sequence, thus changing its position. I can't figure the error myself, and will be happy to hear any tips!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int Arr[100];
int Arr2[100];
int main()
{
srand(time(NULL));
int n, x;
bool seq = false;
int ib = 0;
printf("Starting array\n");
for (n = 0; n < 100; Arr[n++] = (rand() % 101) - 50);
for (n = 0; n < 100; printf("%3d ", Arr[n++]));
putchar('\n');
for (n = 0; n < 100; n++) //sorting
{
if (Arr[n] > 0) //check if the number is positive
{
if (seq == false) //if it isn't the part of a sequence
{
seq = true; ib = n; //declare it now is, and remember index of sequence's beginning
}
else
seq = true; //do nothing if it isn't first
}
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
seq = false; //declaring sequence's end
Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array
}
}
printf("Modified array\n");
for (n = 0; n < 100; printf("%3d ", Arr2[n++]));
putchar('\n');
system('pause');
return 0;
}

following what we discussed in comments, i listed couple of rules here to shape my answer around it.
Rules :
the sequence of elements can be varied. so if there are 5 positive numbers in a row within an array, we would be reversing the 5 elements. for example
array[5] = {1,2,3,4,5} would become array[5]{5,4,3,2,1}
if single positive number neighboured by negatives, no reverse can happen
array[4] = {-1,0,-2,1} would result the same array
no processing happens when a negative number is discovered.
based on these rules.
here is what I think going wrong in your code.
Problems :
1- consider thisarray = {1,2,-1}. notice that the last value is negative. because of this. the following code would run when the 3rd index of the array is processed;
` Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array`
this is a no-no. since you are already at the end of the Arr2 n+1 would indicate that there is a 4th element in the array. (in your case 101h element of the array) this would cause an undefined behaviour.
2 - consider the same array mentioned above. when that array is looped, the outcome would be array = {-1,2,1} . the -1 and 1 are swapped instead of 1 and 2.
3 - you are assigning ib = n whenever a negative number is found. because whenever a negative value is hit, seq=false is forced. But the ib, never been put into use until a next negative number is found. here is an example;
array = {...2, 6}
in such scenario, 2 and 6 would never get reversed because there is no negative value is following this positive sequence.
4 - consider this scenario arr = {-10,-1,....} this would result in arr = {0,-1,....}. This happens because of the same code causing the undefined behaviour problem mentioned above.
`Arr2[n + 1] = Arr[n + 1];`
Suggestion
Most of the problems mentioned above is happening because you are trying to figure out the sequence of the positive numbers when a negative number is found.
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
you should completely get rid of that and completely ignore the negative numbers unless you forgot to mention in your question some key details. instead just focus on the positive numbers. I'm not going to send you the entire code but here is how I approached the problem. feel free to let me know if you need help and I would be more then happy to go through in detail.
start your for loop as usual.
for (n = 0; n < 100; n++) //sorting
{
don't try to do anything when an element in an array is a negative value.
if (Arr[n] > 0) //check if the number is positive
if the number is positive. create recording the sequence indices. for one, we know the sequence will start at n once the `if (Arr[n] > 0) true. so we can do something like this;
int sequenceStart = n;
we also need to know when the positive number sequence ends.
int sequenceEnd = sequenceStart;
the reason for int sequenceEnd = sequenceStart; is because we going to start using the same n value to start with. we can now loop through the array and increment the sequenceEnd until we reach to a negative number or to the end of the array.
while (currentElement > 0)
{
n++;//increment n
if(n < arraySiz) //make sure we still in the range
{
currentElement = Arr[n]; // get the new elemnet
if (currentElement > 0)
{
sequenceEnd++;
}
}
else
break; // we hit to a negative value so stop the while loop.
}
notice the n++;//increment n this would increment the n++ until we reach to the negative number. which is great because at the end of the sequence the for loop will continue from the updated n
after the while loop, you can create an array that has the same size as the number of sequences you iterated through. you can then store the elements from starting arr[sequenceStart] and arr[sequenceEnd] this will make the reversing the sequence in the array easier.

Related

Comparing Floats in a vector

I am writing a program that creates two vectors to practice comparing elements in a vector. The first vector is a list of all numbers that are not prime numbers between 1-100 (not prime numbers), the second vector is a list of all numbers between 1-100 (vector number_bank). I am using loops to compare each element in the vectors. Lets say the number 5 comes up from the number_bank (which is a prime number), if this number does not match any number in the not_prime_numbers vector then it is pushed back into a third vector called prime numbers. If a number like 4 were to be compared to the elements of the not_prime_number list it is supposed to match with the number 4 in this list and break the loop without pushing back the number into the prime_numbers vector. What is happening is all numbers between 1-100 are being pushed back. 4 in the number_bank vector is never equal to the 4 in the not_prime_numbers vector so the cycle continues pushing back 4 into the prime numbers vector.
There is no math involved changing the elements in these vectors so there shouldn't be an incremental margin of error (epsilon) usually associated with comparing floats. Is there a better way to compare the elements in these vectors?
int main()
{
float i = 1.0;
unsigned int n = 0;
std::vector<float>not_prime_numbers;
std::vector<float>number_bank;
std::vector<float>prime_numbers;
while (i < 101.0)
{
for (float j = 1.0;j<(i);++j)
{
float p = i / j;
if (abs(floor(p)) == p&&j!=1.0)
{
not_prime_numbers.push_back(i);
break;
}
}
++i;
}
for (float k = 1.0; k < 101.0; ++k)
{
number_bank.push_back(k);
}
for (unsigned int m = 0; m < number_bank.size(); ++m)
{
while (n < not_prime_numbers.size())
{
if (not_prime_numbers[n] == number_bank[m]) // here is where i try to break the loop
{
break;
}
if (n == (not_prime_numbers.size()-1))
{ // here is where element is pushed back when compared to all loop elements
prime_numbers.push_back(number_bank[m]);
break;
}
if (not_prime_numbers[n] != number_bank[m])
{
++n;
}
}
}
std::cout << "All prime numbers between 0 and 100 are as follows:\n";
for (unsigned int j = 0; j < prime_numbers.size(); ++j)
{
std::cout << prime_numbers[j] << "\n";
}
return 0;
}
I read about .compare and tried it but it states that there needs to be a class structure to the left (perhaps a vector has no class structure?). I'm new to C++ and would greatly appreciate the help.
You never reset n, so once you get a prime number (when n == (not_prime_numbers.size()-1)) the rest of the numbers will also be added to the prime list.
Why are you checking that condition within the loop? You should set a flag variable if you find the number is not prime, then check that after your loop to possibly add it to your prime list.

Runtime of KMP algorithm and LPS table construction

I recently came across the KMP algorithm, and I have spent a lot of time trying to understand why it works. While I do understand the basic functionality now, I simply fail to understand the runtime computations.
I have taken the below code from the geeksForGeeks site: https://www.geeksforgeeks.org/kmp-algorithm-for-pattern-searching/
This site claims that if the text size is O(n) and pattern size is O(m), then KMP computes a match in max O(n) time. It also states that the LPS array can be computed in O(m) time.
// C++ program for implementation of KMP pattern searching
// algorithm
#include <bits/stdc++.h>
void computeLPSArray(char* pat, int M, int* lps);
// Prints occurrences of txt[] in pat[]
void KMPSearch(char* pat, char* txt)
{
int M = strlen(pat);
int N = strlen(txt);
// create lps[] that will hold the longest prefix suffix
// values for pattern
int lps[M];
// Preprocess the pattern (calculate lps[] array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
int j = 0; // index for pat[]
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}
if (j == M) {
printf("Found pattern at index %d ", i - j);
j = lps[j - 1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i]) {
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
}
// Fills lps[] for given patttern pat[0..M-1]
void computeLPSArray(char* pat, int M, int* lps)
{
// length of the previous longest prefix suffix
int len = 0;
lps[0] = 0; // lps[0] is always 0
// the loop calculates lps[i] for i = 1 to M-1
int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search step.
if (len != 0) {
len = lps[len - 1];
// Also, note that we do not increment
// i here
}
else // if (len == 0)
{
lps[i] = 0;
i++;
}
}
}
}
// Driver program to test above function
int main()
{
char txt[] = "ABABDABACDABABCABAB";
char pat[] = "ABABCABAB";
KMPSearch(pat, txt);
return 0;
}
I am really confused why that is the case.
For LPS computation, consider: aaaaacaaac
In this case, when we try to compute LPS for the first c, we would keep going back until we hit LPS[0], which is 0 and stop. So, essentially, we would travel back atleast the length of the pattern until that point. If this happens multiple times, how will time complexity be O(m)?
I have similar confusion on runtime of KMP to be O(n).
I have read other threads in stack overflow before posting, and also various other sites on the topic. I am still very confused. I would really appreciate if someone can help me understand the best and worse case scenarios for these algorithms and how their runtime is computed using some examples. Again, please don't suggest I google this, I have done it, spent a whole week trying to gain any insight, and failed.
One way to establish an upper bound on the runtime for construction of the LPS array is to consider a pathological case - how can we maximize the number of times we have to execute len = lps[len - 1]? Consider the following string, ignoring spaces: x1 x2 x1x3 x1x2x1x4 x1x2x1x3x1x2x1x5 ...
The second term needs to be compared to the first term as if it ended in 1 instead of 2, it would match the first term. Similarly the third term needs to be compared to the first two terms as if it ended in 1 or 2 instead of 3, it would match those partial terms. And so forth.
In the example string, it is clear that only every 1/2^n characters can match n times, so the total runtime will be m+m/2+m/4+..=2m=O(m), the length of the pattern string. I suspect it's impossible to construct a string with worse runtime than the example string and this can probably be formally proven.

Explaining Radix Sort

I'm trying to understand a radix sort. Particularly, I'm having trouble understanding the radixing function--more specifically, the j and k loops. I'm not sure what is exactly happening. From what I can see, it seems that the j loop is setting up indices for the k loop to utilize in forming the output array that is sorted. If anyone could help explain the logic behind it, that would be great!
// RADIX SORT BEGIN //
// Get the maximum value in arr[]
int getMax(int arr[], int size)
{
int max = arr[0]; // Set max to presumably the first one
int i = 1;
while (i < size)
{
if (arr[i] > max) // We have a new max ladies and gents
max = arr[i];
i++;
}
return max;
}
// Do a sort of arr[] based off the digit represented by exp
void radixing(int arr[], int size, int exponent)
{
int output[size];
int count[10] = {0};
// Tally the amount of numbers whose LSB based off current exponent
// is 0-9, represented by each
// index in the array
for (int i = 0; i < size; i++)
count[ (arr[i]/exponent) % 10 ]++;
for (int j = 1; j < 10; j++)
count[ j ] += count [j - 1];
for (int k = size - 1; k >= 0; k--)
{
output[ count[ (arr[k]/exponent) % 10 ] -1 ] = arr[k];
count[ (arr[k]/exponent) % 10 ]--;
}
// Finalize output into the original array
for (int o = 0; o < size; o++)
arr[o] = output[o];
}
// Main radix sort function
void radixsort(int arr[], int size)
{
// Find the max in the array to know the number of digits to traverse
int max = getMax(arr, size);
// Begin radixing by sorting the arr[] based off every digit until max
// Exponent is 10^i where i starts at 0, the current digit number
for (int exponent = 1; (max / exponent) > 0; exponent = exponent * 10)
radixing(arr, size, exponent);
}
// RADIX SORT END //
Rather than break down each step in the algorithm I'm going to tell you what it intends to accomplish which you can use to understand how it works. This looks like it is doing what is called an LSD radix sort.
If you've ever used a card sorter (hard to find nowadays) it does the same thing as this algorithm. The idea is to start with the least significant digit and work toward the most. The card sorter would have 10 bins -- one for each digit. A column (exponent) will be selected and the cards will fall into the proper bins depending upon what digit it had for the selected column.
What the algorithm is doing is counting the number of records with each digit in the given exponent column then outputs that many records in order. Actually, it uses the counts to compute an offset into the output array.
Now with the records in order for a given column (exponent) it moves to the next higher exponent.
Edit: embellished somewhat.
The j loop converts the counts into the ending index (1 + index to last element) for each bucket. The k loop moves the elements from last to first into the buckets based on the current digit. The process starts with the least significant digit, and ends with the most significant digit.
An alternative is to convert the counts into starting indexes, where the first index == 0, the second index == number of elements with '0' digits, ... (number of elements with '9' digits doesn't matter and isn't used). The radix part of the sort would sort elements from first to last.
In either case, the size of the buckets is variable, and the end of one bucket is the start of the next bucket. When a radix sort pass is completed, then there are no gaps between the buckets.

How to reduce complexity of this code

Please can any one provide with a better algorithm then trying all the combinations for this problem.
Given an array A of N numbers, find the number of distinct pairs (i,
j) such that j >=i and A[i] = A[j].
First line of the input contains number of test cases T. Each test
case has two lines, first line is the number N, followed by a line
consisting of N integers which are the elements of array A.
For each test case print the number of distinct pairs.
Constraints:
1 <= T <= 10
1 <= N <= 10^6
-10^6 <= A[i] <= 10^6 for 0 <= i < N
I think that first sorting the array then finding frequency of every distinct integer and then adding nC2 of all the frequencies plus adding the length of the string at last. But unfortunately it gives wrong ans for some cases which are not known help. here is the implementation.
code:
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long fun(long a) //to find the aC2 for given a
{
if (a == 1) return 0;
return (a * (a - 1)) / 2;
}
int main()
{
long t, i, j, n, tmp = 0;
long long count;
long ar[1000000];
cin >> t;
while (t--)
{
cin >> n;
for (i = 0; i < n; i++)
{
cin >> ar[i];
}
count = 0;
sort(ar, ar + n);
for (i = 0; i < n - 1; i++)
{
if (ar[i] == ar[i + 1])
{
tmp++;
}
else
{
count += fun(tmp + 1);
tmp = 0;
}
}
if (tmp != 0)
{
count += fun(tmp + 1);
}
cout << count + n << "\n";
}
return 0;
}
Keep a count of how many times each number appears in an array. Then iterate over the result array and add the triangular number for each.
For example(from the source test case):
Input:
3
1 2 1
count array = {0, 2, 1} // no zeroes, two ones, one two
pairs = triangle(0) + triangle(2) + triangle(1)
pairs = 0 + 3 + 1
pairs = 4
Triangle numbers can be computed by (n * n + n) / 2, and the whole thing is O(n).
Edit:
First, there's no need to sort if you're counting frequency. I see what you did with sorting, but if you just keep a separate array of frequencies, it's easier. It takes more space, but since the elements and array length are both restrained to < 10^6, the max you'll need is an int[10^6]. This easily fits in the 256MB space requirements given in the challenge. (whoops, since elements can go negative, you'll need an array twice that size. still well under the limit, though)
For the n choose 2 part, the part you had wrong is that it's an n+1 choose 2 problem. Since you can pair each one by itself, you have to add one to n. I know you were adding n at the end, but it's not the same. The difference between tri(n) and tri(n+1) is not one, but n.

Recursive function that takes the sum of odd integers

The program runs but it also spews out some other stuff and I am not too sure why. The very first output is correct but from there I am not sure what happens. Here is my code:
#include <iostream>
using namespace std;
const int MAX = 10;
int sum(int arrayNum[], int n)
{
int total = 0;
if (n <= 0)
return 0;
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0)
total += arrayNum[i];
}
cout << "Sum of odd integers in the array: " << total << endl;
return arrayNum[0] + sum(arrayNum+1,n-1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
sum(x,MAX);
system("pause");
return 0;
}
The term recursion means (in the simplest variation) solving a problem by reducing it to a simpler version of the same problem until becomes trivial. In your example...
To compute the num of the odd values in an array of n elements we have these cases:
the array is empty: the result is trivially 0
the first element is even: the result will be the sum of odd elements of the rest of the array
the first element is odd: the result will be this element added to the sum of odd elements of the rest of the array
In this problem the trivial case is computing the result for an empty array and the simpler version of the problem is working on a smaller array. It is important to understand that the simpler version must be "closer" to a trivial case for recursion to work.
Once the algorithm is clear translation to code is simple:
// Returns the sums of all odd numbers in
// the sequence of n elements pointed by p
int oddSum(int *p, int n) {
if (n == 0) {
// case 1
return 0;
} else if (p[0] % 2 == 0) {
// case 2
return oddSum(p + 1, n - 1);
} else {
// case 3
return p[0] + oddSum(p + 1, n - 1);
}
}
Recursion is a powerful tool to know and you should try to understand this example until it's 100% clear how it works. Try starting rewriting it from scratch (I'm not saying you should memorize it, just try rewriting it once you read and you think you understood the solution) and then try to solve small variations of this problem.
No amount of reading can compensate for writing code.
You are passing updated n to recursive function as argument but not using it inside.
change MAX to n in this statement
for(int i = 0; i < n; i ++)
so this doesnt really answer your question but it should help.
So, your code is not really recursive. If we run through your function
int total = 0; //Start a tally, good.
if (n <= 0)
return 0; //Check that we are not violating the array, good.
else
for(int i = 0; i < MAX; i ++)
{
if(arrayNum[i] % 2 != 0) //THIS PART IS WIERD
total += arrayNum[i];
}
And the reason it is wierd is because you are solving the problem right there. That for loop will run through the list and add all the odd numbers up anyway.
What you are doing by recursing could be to do this:
What is the sum of odd numbers in:
13,14,8,7,45,89,22,18,6,10
+
14,8,7,45,89,22,18,6
+
8,7,45,89,22,18
+
7,45,89,22 ... etc
And if so then you only need to change:
for(int i = 0; i < MAX; i ++)
to
for(int i = 0; i < n; i ++)
But otherwise you really need to rethink your approach to this problem.
It's not recursion if you use a loop.
It's also generally a good idea to separate computation and output.
int sum(int arrayNum[], int n)
{
if (n <= 0) // Base case: the sum of an empty array is 0.
return 0;
// Recursive case: If the first number is odd, add it to the sum of the rest of the array.
// Otherwise just return the sum of the rest of the array.
if(arrayNum[0] % 2 != 0)
return arrayNum[0] + sum(arrayNum + 1, n - 1);
else
return sum(arrayNum + 1, n - 1);
}
int main()
{
int x[MAX] = {13,14,8,7,45,89,22,18,6,10};
cout << sum(x,MAX);
}