What does this statement do "while(a[i]--!=0)"? - c++

Below is the code used for sorting numbers in non-decreasing order:
#include<stdio.h>
#include<stdlib.h>
# define size 1000001
static int a[size];
int main()
{
int t, k, i;
scanf("%d", &t);
for(i = 0; i < t; i++)
{
scanf("%d", &k);
a[k] += 1;
}
for(i = 0; i < 1000001; i++)
{
while(a[i]-- != 0)
printf("%d\n", i);
}
return 0;
}
It would be really of great help if someone could explain the code to me. I have gone through the code and I have no idea as to how it can sort numbers. There is no swapping done at any place but still it works in c++ editor.

This program doesn't sort numbers in a mathematical sense, but that isn't important since it gives you the illusion of doing it.
The program asks for t, which would be better named numberOfValues... the number of values you will input.
The array a[size] can be thought of as size buckets of values. In your program, these buckets are simply counters. Each bucket has a number, 0 through size. When value 5 is input, bucket a[5] has its count increased. This continues until all buckets are set.
The program then works through the buckets. Most of your buckets will be empty, but when a bucket is non-zero (while a[i] != 0 -- ignore the missing -- for now), the bucket needs to be "emptied" while at the same time, its contents need to be accounted for. The bucket a[i] holds the count of i elements, so the loop prints that a value of i is next in the sort, while also decrementing the count (a[i]--). This continues until the bucket is empty (== 0) and the program moves to the next bucket.
Eventually all of your buckets have been emptied and the sort is completed.

Decrements variable a[i] until it's 0 while printing it out every time

There is no swapping because is not needed: numbers are not stored as usual, it uses a huge array to mark which number has been entered:
If you add the number 200, it stores array[200]=1. If you add again 200, then array[200]=2.
Then, it prints the array in the following way: imagine you have [0,1,2,1,0,0...], so there is one 1, two 2, one 3...
So it just shows 1,2,2,3

The code iterates for each value in the array a. Each value a[i] in the array is iterated in the while loop. while(a[i]--!=0) checks if the value of a[i] is zero. If not, the loop body is executed. When the control enters the loop body, decrementing the a[i] value. Eg) If a[i]=6, the output will be:
5
4
3
2
1
0

Consider for i=0;
Then a[i]--!=0 will get executed till value at a[i] does not become zero.When value at a[i] becomes zero while loop will get terminated and next iteration of for loop will start.

its a nice code but its space complexity is high.
This part of the code
for(i = 0; i < t; i++)
{
scanf("%d", &k);
a[k] += 1;
}
stores frequency of number entered (its somewhat like hashing)
say if I entered 5 4 2 4 2
then
a[5] =1
a[4] =2
a[2] =2
all others will be zero
so if you want to say find frequency of "n" in the array then just print a[n]
lets come to your questions now
how this code sorts the number ?
what's use of while(a[i]--!=0)?
Answer to first question :
we go from 0 to 1000001 in oder so if 4 2 5 6 is entered
As the loop goes from 0 to 100001 first it checks a[2] !=0 then a[4] later a[5] then a[6] all non zero frequency terms are printed .
so as per checking oder first 2 4 5 6 is printed
Answer to the second question :
why isn't is while(a[i]!=0) because iam checking only if its non zero if its non zero lets print the number
but say i entered 4 3 2 4 2
then the output should print 2 2 3 4 4
so while(a[i] --!=0) is used it prints the number a[i] times say if
a[4]=2 which means 4 is present 2 times hence its should print 4 4 so while loop runs twice as a[4] =2

Related

Tell me the Input in which this code will give incorrect Output

There's a problem, which I've to solve in c++. I've written the whole code and it's working in the given test cases but when I'm submitting it, It's saying wrong answer. I can't understand that why is it showing wrong answer.
I request you to tell me an input for the given code, which will give incorrect output so I can modify my code further.
Shrink The Array
You are given an array of positive integers A[] of length L. If A[i] and A[i+1] both are equal replace them by one element with value A[i]+1. Find out the minimum possible length of the array after performing such operation any number of times.
Note:
After each such operation, the length of the array will decrease by one and elements are renumerated accordingly.
Input format:
The first line contains a single integer L, denoting the initial length of the array A.
The second line contains L space integers A[i] − elements of array A[].
Output format:
Print an integer - the minimum possible length you can get after performing the operation described above any number of times.
Example:
Input
7
3 3 4 4 4 3 3
Output
2
Sample test case explanation
3 3 4 4 4 3 3 -> 4 4 4 4 3 3 -> 4 4 4 4 4 -> 5 4 4 4 -> 5 5 4 -> 6 4.
Thus the length of the array is 2.
My code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
bool end = false;
int l;
cin >> l;
int arr[l];
for(int i = 0; i < l; i++){
cin >> arr[i];
}
int len = l, i = 0;
while(i < len - 1){
if(arr[i] == arr[i + 1]){
arr[i] = arr[i] + 1;
if((i + 1) <= (len - 1)){
for(int j = i + 1; j < len - 1; j++){
arr[j] = arr[j + 1];
}
}
len--;
i = 0;
}
else{
i++;
}
}
cout << len;
return 0;
}
THANK YOU
As noted in the comments: Just picking the first two neighbours that have the same value and combining those will lead to suboptimal results.
You will need to investigate which two neighbours you should combine somehow. When you have combined two neighbours you then need to investigate which neighbours to combine on the next level. The number of combinations may become plentiful.
One way to solve this is through recursion.
If you've followed the advice in the comments, you now have all your input data in std::vector<unsigned> A(L).
You can now do std::cout << solve(A) << '\n'; where solve has the signature size_t solve(const std::vector<unsigned>& A) and is described below:
Find the indices of all neighbour pairs in A that has the same values and put the indices in a std::vector<size_t> neighbours. Example: If A contains 2 2 2 3, put 0 and 1 in neighbours.
If no neighbours are found (neighbours.empty() == true), return A.size().
Define a minimum variable and initialize it with A.size() - 1 which is the worst result you know you can get at this point. So, size_t minimum = A.size() - 1;
Loop over all indices stored in neighbours (for(size_t idx : neighbours))
Copy A into a new std::vector<unsigned>. Let's call it cpy.
Increase cpy[idx] by one and remove cpy[idx+1].
Call size_t result = solve(cpy). This is where recursion comes in.
Is result less than minimum? If so assign result to minimum.
Return minimum.
I don't think I ruined the programming exercise by providing one algorithm for solving this. It should still have plenty of things to deal with. Recursion won't be possible with big data etc.

How to find un-ordered numbers (lineal search)

A list partially ordered of n numbers is given and I have to find those numbers that does not follow the order (just find them and count them).
There are no repeated numbers.
There are no negative numbers.
MAX = 100000 is the capacity of the list.
n, the number of elements in the list, is given by the user.
Example of two lists:
1 2 5 6 3
1 6 2 9 7 4 8 10 13
For the first list the output is 2 since 5 and 6 should be both after 3, they are unordered; for the second the output is 3 since 6, 9 and 7 are out of order.
The most important condition in this problem: do the searching in a linear way O(n) or being quadratic the worst case.
Here is part of the code I developed (however it is no valid since it is a quadratic search).
"unordered" function compares each element of the array with the one given by "minimal" function; if it finds one bigger than the minimal, that element is unordered.
int unordered (int A[MAX], int n)
int cont = 0;
for (int i = 0; i < n-1; i++){
if (A[i] > minimal(A, n, i+1)){
count++;
}
}
return count;
"minimal" function takes the minimal of all the elements in the list between the one which is being compared in "unordered" function and the last of the list. i < elements <= n . Then, it is returned to be compared.
int minimal (int A[MAX], int n, int index)
int i, minimal = 99999999;
for (i = index; i < n; i++){
if (A[i] <= minimo)
minimal = A[i];
}
return minimal;
How can I do it more efficiently?
Start on the left of the list and compare the current number you see with the next one. Whenever the next is smaller than the current remove the current number from the list and count one up. After removing a number at index 'n' set your current number to index 'n-1' and go on.
Because you remove at most 'n' numbers from the list and compare the remaining in order, this Algorithmus in O(n).
I hope this helps. I must admit though that the task of finding numbers that are out of of order isn't all that clear.
If O(n) space is no problem, you can first do a linear run (backwards) over the array and save the minimal value so far in another array. Instead of calling minimal you can then look up the minimum value in O(1) and your approach works in O(n).
Something like this:
int min[MAX]; //or: int *min = new int[n];
min[n-1] = A[n-1];
for(int i = n-2; i >= 0; --i)
min[i] = min(A[i], min[i+1]);
Can be done in O(1) space if you do the first loop backwards because then you only need to remember the current minimum.
Others have suggested some great answers, but I have an extra way you can think of this problem. Using a stack.
Here's how it helps: Push the leftmost element in the array onto the stack. Keep doing this until the element you are currently at (on the array) is less than top of the stack. While it is, pop elements and increment your counter. Stop when it is greater than top of the stack and push it in. In the end, when all array elements are processed you'll get the count of those that are out of order.
Sample run: 1 5 6 3 7 4 10
Step 1: Stack => 1
Step 2: Stack => 1 5
Step 3: Stack => 1 5 6
Step 4: Now we see 3 is in. While 3 is less than top of stack, pop and increment counter. We get: Stack=> 1 3 -- Count = 2
Step 5: Stack => 1 3 7
Step 6: We got 4 now. Repeat same logic. We get: Stack => 1 3 4 -- Count = 3
Step 7: Stack => 1 3 4 10 -- Count = 3. And we're done.
This should be O(N) for time and space. Correct me if I'm wrong.

Varying initializer in a 'for loop' in C++

int i = 0;
for(; i<size-1; i++) {
int temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
Here I started with the fist position of array. What if after the loop I need to execute the for loop again where the for loop starts with the next position of array.
Like for first for loop starts from: Array[0]
Second iteration: Array[1]
Third iteration: Array[2]
Example:
For array: 1 2 3 4 5
for i=0: 2 1 3 4 5, 2 3 1 4 5, 2 3 4 1 5, 2 3 4 5 1
for i=1: 1 3 2 4 5, 1 3 4 2 5, 1 3 4 5 2 so on.
You can nest loops inside each other, including the ability for the inner loop to access the iterator value of the outer loop. Thus:
for(int start = 0; start < size-1; start++) {
for(int i = start; i < size-1; i++) {
// Inner code on 'i'
}
}
Would repeat your loop with an increasing start value, thus repeating with a higher initial value for i until you're gone through your list.
Suppose you have a routine to generate all possible permutations of the array elements for a given length n. Suppose the routine, after processing all n! permutations, leaves the n items of the array in their initial order.
Question: how can we build a routine to make all possible permutations of an array with (n+1) elements?
Answer:
Generate all permutations of the initial n elements, each time process the whole array; this way we have processed all n! permutations with the same last item.
Now, swap the (n+1)-st item with one of those n and repeat permuting n elements – we get another n! permutations with a new last item.
The n elements are left in their previous order, so put that last item back into its initial place and choose another one to put at the end of an array. Reiterate permuting n items.
And so on.
Remember, after each call the routine leaves the n-items array in its initial order. To retain this property at n+1 we need to make sure the same element gets finally placed at the end of an array after the (n+1)-st iteration of n! permutations.
This is how you can do that:
void ProcessAllPermutations(int arr[], int arrLen, int permLen)
{
if(permLen == 1)
ProcessThePermutation(arr, arrLen); // print the permutation
else
{
int lastpos = permLen - 1; // last item position for swaps
for(int pos = lastpos; pos >= 0; pos--) // pos of item to swap with the last
{
swap(arr[pos], arr[lastpos]); // put the chosen item at the end
ProcessAllPermutations(arr, arrLen, permLen - 1);
swap(arr[pos], arr[lastpos]); // put the chosen item back at pos
}
}
}
and here is an example of the routine running: https://ideone.com/sXp35O
Note, however, that this approach is highly ineffective:
It may work in a reasonable time for very small input size only. The number of permutations is a factorial function of the array length, and it grows faster than exponentially, which makes really BIG number of tests.
The routine has no short return. Even if the first or second permutation is the correct result, the routine will perform all the rest of n! unnecessary tests, too. Of course one can add a return path to break iteration, but that would make the code somewhat ugly. And it would bring no significant gain, because the routine will have to make n!/2 test on average.
Each generated permutation appears deep in the last level of the recursion. Testing for a correct result requires making a call to ProcessThePermutation from within ProcessAllPermutations, so it is difficult to replace the callee with some other function. The caller function must be modified each time you need another method of testing / procesing / whatever. Or one would have to provide a pointer to a processing function (a 'callback') and push it down through all the recursion, down to the place where the call will happen. This might be done indirectly by a virtual function in some context object, so it would look quite nice – but the overhead of passing additional data down the recursive calls can not be avoided.
The routine has yet another interesting property: it does not rely on the data values. Elements of the array are never compared. This may sometimes be an advantage: the routine can permute any kind of objects, even if they are not comparable. On the other hand it can not detect duplicates, so in case of equal items it will make repeated results. In a degenerate case of all n equal items the result will be n! equal sequences.
So if you ask how to generate all permutations to detect a sorted one, I must answer: DON'T.
Do learn effective sorting algorithms instead.

Incorrect output using array as counter

I'm trying to teach myself programming by attempting problems from codeabbey.com.
I'm not getting the correct output on this question.
Question:
Here is an array of length M with numbers in the range 1 ... N, where N is less than or equal to 20. You are to go through it and count how many times each number is encountered.
Input data contain M and N in the first line.
The second (rather long) line will contain M numbers separated by spaces.
Answer should contain exactly N values, separated by spaces. First should give amount of 1-s, second - amount of 2-s and so on.
Data input:
10 3
1 2 3 2 3 1 1 1 1 3
Correct Output:
5 2 3
My Output:
7 3 4
You can check here
My Code:
#include <iostream>
using namespace std;
int main()
{
int arrayLength,range,a;
cin>>arrayLength>>range;
int array[20];
array[20]={0};
for(int i=0; i<arrayLength; i++)
{
cin>>a;
++array[a-1];
}
for(a=0; a<range; a++)
{
cout<<array[a]<<" ";
}
return 0;
}
There aren't any error messages or warnings. Also, if you have any suggestions for improving the code, that'd be nice.
int array[20];
array[20]={0};
is wrong, since it leave the array un-initialized and tries to initialize the 21st element (which is undefined behaviour btw, since your array has only 20 elements, remember that indexing starts from 0). Use
int array[20] = {0}; // this will initialize all elements to 0
and your code will work as expected. See here for more details regarding aggregate initialization in C++.
array[20]={0}; initializes the 21st element(non-existing) to 0.
So you have to use int array[20] = {0}; which will initialize all 20 elements to zero.
Also from your code, you are not storing the elements to an array. You are just incrementing the corresponding count when an input is read. If so, what is the need of initializing an array to max limit. Just declare the array as you need it. In your case,
int array[range] = {0};
It will initialize an array of three (range =3 here) elements.

how to find consecutive numbers in a sequence

im trying to a write a program that accepts 10 random integers and checks whether there are three consecutive numbers in the sequence or not.The consecutive numbers can be in ascending or descending order.
here are some examples to help you understand better:
order. Examples:
2 9 8 3 20 15 9 6 4 24
Yes, 2 3 and 4 are consecutive
16 21 3 8 20 6 3 9 12 19
Yes, 21 20 and 19 are consecutive
I can't figure out whats wrong with my code.
here is my code so far:
#include <iostream>
using namespace std;
int main()
{
int a[10];
int i,n;
int count=0;
cout << "Enter 10 numbers between 1 and 25" << endl;
for (i = 0; i < 10; i++)
{ cin >> a[i];
}
for (n=0; n<10; n++)
{
for (i=1; i<10; i++)
{
if (a[i]==a[n]+1)
{cout<<endl<<a[i]<<endl;
count++;}
}
}
}
Your code is currently O(N2), and to get it to work it'll be O(N3).
I'd rather use an algorithm that's O(N) instead.
Given that you only care about 25 values, you can start with a 32-bit word, and set the bit in that word corresponding to each number that was entered (e.g., word |= 1 << input_number;).
Then take a value of 7 (which is three consecutive bits set) and test it at the possible bit positions in that word to see if you have three consecutive bits set anywhere in the word. If so, the position at which they're set tells you what three consecutive numbers you've found. If not, then there weren't three consecutive numbers in the input.
for (int i=0; i<32-3; i++) {
int mask = 7 << i;
if (word & mask == mask)
// three consecutive bits set -> input contained i, i+1 and i+2
}
Your logic is wrong. What your current code does is that it checks if there are any two consecutive integers. To check for three, you should introduce another nested loop. This would make the time complexity O(n^3).
Another possible way to check this is to first sort the array, and then check for consecutive elements. This would make the running time O(nlogn). You can use the inbuilt sort function for sorting.
The algorithm needs to be reworked. As it is, what you are doing is saying:
For each array element x
See if another array element is x+1
print out the array element that is x+1
Stick in more cout lines to see what is going on, like
if (a[i]==a[n]+1)
{cout<<endl<<a[n]<<","<<a[i]<<endl;
count++;}
A possible, although slow, algorithm would be
For each array element x
See if another array element is x+1
See if another array element is x+2
print out x, x+1, and x+2