Reduce subsequence problem complexity from exponential to polynomial? - c++

I am working on the following problem:
Given a set of non-negative distinct integers, and a value m, determine if there is a subset of the given set with sum divisible by m.
Input: The first line of input contains an integer T denoting the number of test cases. Then T test cases follow. The first line of each test case contains an integer N and M where N denotes the size of the array and M is the number for which we have to check the divisibility. The second line of each test case contains N space separated integers denoting elements of the array A[ ].
Output: If there is a subset which is divisible by M print '1' else print '0'.
I have tried a recursive solution:
#include <iostream>
#include<unordered_map>
using namespace std;
bool find_it(int a[],int &m,int n,int sum) {
if ((sum%m)==0 && sum>0)
return true;
if (n==0)
return false;
return find_it(a,m,n-1,sum) || find_it(a,m,n-1,sum-a[n-1]);
}
int main() {
int tc;
cin >> tc;
while (tc--) {
int n,m;
cin >> n >> m;
int a[n];
int sum = 0;
for (int i=0;i<n;i++) {
cin >> a[i];
sum += a[i];
}
bool answer = find_it(a,m,n,sum);
cout << answer << "\n";
}
return 0;
}
Which works fine and get accepted, but then I tried top-down approach, and am getting TLE ("Time Limit Exceeded"). What am I doing wrong in this memoization?
#include <iostream>
#include<unordered_map>
using namespace std;
bool find_it(
int a[], int &m, int n, int sum,
unordered_map<int,unordered_map<int,bool>> &value,
unordered_map<int,unordered_map<int,bool>> &visited){
if ((sum%m)==0 && sum>0)
return true;
if(n==0)
return false;
if(visited[n][sum]==true)
return value[n][sum];
bool first = false,second = false;
first = find_it(a,m,n-1,su1m,value,visited);
if(sum<a[n-1])
{
second=false;
}
else
second = find_it(a,m,n-1,sum-a[n-1],value,visited);
visited[n][sum] = true;
value[n][sum] = first || second;
return value[n][sum];
}
int main() {
int tc;
cin >> tc;
while (tc--) {
int n,m;
cin >> n >> m;
int a[n];
int sum = 0;
for (int i=0;i<n;i++) {
cin >> a[i];
sum+=a[i];
}
unordered_map<int,unordered_map<int,bool>> value;
unordered_map<int,unordered_map<int,bool>> visited;
cout << find_it(a,m,n,sum,value,visited) << "\n";
}
return 0;
}

Well, at first, you can reduce the problem to a modulo m problem, as properties of integers don't change when switching to modulo m field. It's easy to demonstrate that being divisible by m is the same as being identical to 0 mod m.
I would first convert all those numbers to their counterparts modulo m and eliminate repetitions by considering a_i, 2*a_i, 3*a_i,... until rep_a_i * a_i, all of them mod m. Finally you get a reduced set that has at most m elements. Then eliminate all the zeros there, as they don't contribute to the sum. This is important for two reasons:
It converts your problem from a Knapsack problem (NP-complete) on which complexity is O(a^n) into a O(K) problem, as its complexity doesn't depend on the number of elements of the set, but the number m.
You can still have a large set of numbers to compute. You can consider the reduced set a Knapsack problem and try to check (and further reduce it) for an easy-knapsack problem (the one in which the different values a_i follow a geometric sequence with K > 2)
The rest of the problem is a Knapsack problem (which is NP-complete) or one of it's P variants.
In case you don't get so far (cannot reduce it to an easy-knapsack problem) then you have to reduce the number of a_i's so the exponential time gets a minimum exponent :)
edit
(#mss asks for elaboration in a comment) Assume you have m = 8 and the list is 1 2 4 6 12 14 22. After reduction mod m the list remains as: 1 2 4 6 4 6 6 in which 6 is repeated three times. we must consider the three possible repetitions of 6, as they can contribute to get a sum, but not more (for the moment), let's consider 6*1 = 6, 6*2 = 12 and 6*3 = 18, the first is the original 6, the second makes a third repetition of 4 (so we'll need to consider 3 4s in the list), and the third converts into a 2. So now, we have 1 2 4 6 4 4 2 in the list. We make the same for the 4 repetitions (two 4 run into 8 which is 0mod m and don't contribute to sums, but we have to keep one such 0 because this means you got by repeated numbers the target m) getting into 1 2 4 6 0 4 2 => 1 2 4 6 0 0 2 =(reorder)=> 0 1 2 2 4 6 => 0 1 2 4 6. This should be the final list to consider. As it has a 0, you know a priori that there's one such sum (in this case you got is as including the two 4, for the original list's 4 and 12 numbers.

There is no need for value. Once you find a valid combination, i.e. if find_it ever returns true, you can just immediately return true in all recursive calls.
Some additional remarks:
You should use consistent indentation.
Variable sized arrays as in int a[n] are not standard C++ and will not work on all compilers.
There is no reason to pass m as int& instead of int.
A map taking boolean values is the same as a set where the element is assumed to map to true if it is in the set and false if it is not. Consider using unordered_set instead of unordered_map.
Composing two unordered_maps like this is expensive. You can just as easily put both keys into a std::pair and use that as key. This would avoid the overhead of maintaining the map.
bits/stdc++.h is also non-standard and you should specify the correct header files instead, e.g. #include <unordered_map> and #include <iostream>.
You should put spaces between the variable type and its name, even if the > from the template parameter allows it to parse correctly without. It makes code hard to read.

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.

Recurrence relation for a variant of knapsack problem?

I am finding it difficult to understand two specific implementations which solve this problem on codeforces link.
I understand this is similar to the knapsack problem. However when i solved it myself, i was not aware of the algorithm. I solved it from my own understanding of dynamic programming. My idea is to regard the remaining length of the ribbon as the next state. Here's my code
#include<iostream>
using namespace std;
int main(){
int n,res1=0,res2,x=0;
int a,b,c;
cin >> n >> a >> b >> c;
for(int i=0;i <= n/a; i++){
res2 = -20000;
for(int j=0; j <= (n-(a*i))/b; j++){
x = (n - (a*i) - (b*j));
res2=max(res2,(j + ((x % c) ? -10000 : x/c)));
}
res1=max(res1,i+res2);
}
cout << res1 << endl;
return 0;
Implementation 1:
1 #include <bits/stdc++.h>
2 using namespace std;
3 int main()
4 {
5 int f[4005],n,a,i,j;
6 fill(f+1,f+4005,-1e9);
7 cin>>n;
8 for(;cin>>a;)
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
11 cout<<f[n];
12 }
Implementation 2:
1 #include <bits/stdc++.h>
2 int n, a, b, c, ost;
3 std::bitset<4007> mog;
4 main()
5 {
6 std::cin>>n>>a>>b>>c;
7 mog[0]=1;
8 for (int i=1; i<=n; i++)
9 if ((mog=((mog<<a)|(mog<<b)|(mog<<c)))[n])
10 ost=i;
11 std::cout << ost;
12 }
Though i understand the general idea of solving the knapsack problem. I do not have a clear understanding of how lines 8,9,10 in Implementation 1 achieve this. Specifically irrespective of the input values of a,b,c the inner for loop is a single pass over the array for the corresponding value a received.
Similarly, I can see that lines 8,9,10 in implementation 2 does the same thing. But i have no clue at all how this piece of code works.
Please help me understand this. I feel there is some hidden structure to these two solutions which i am not seeing. Thanks in advance.
Implementation 1
This is quite straightforward implementation of dynamic programming.
Outer loop just goes through three values: a, b, and c
8 for(;cin>>a;)
Inner loop visits every element of an array and updates current best known number of cuts for given ribbon length.
9 for(i=a;i<=n;i++)
10 f[i]=max(f[i],f[i-a]+1);
Implementation 2
I don't think that it can be called dynamic programming, but the trick is quite neat.
It allocates array of bits with length equal to max n. Then sets one bit on the left. It means, that ribbon with length of 0 is a valid solution.
On each iteration algorithm shifts given array to the left by a, b, and c. Result of each such shift can be viewed as the new valid sizes of ribbon. By oring result of all 3 shifts, we get all valid sizes after i'th cut. If n'th bit set we know ribbon of size n can be cut i times without remainder.
n = 10
a = 2
b = 3
c = 5
i=1:
0|0000000001 // mog
0|0000000100 // mog<<a
0|0000001000 // mog<<b
0|0000100000 // mog<<c
0|0000101100 // mog=(mog<<a)|(mog<<b)|(mog<<c)
^ here is a bit checked in 'if' statement '(mog=(...))[n]'
i=2:
0|0000101100 // mog
0|0010110000 // mog<<a
0|0101100000 // mog<<b
1|0110000000 // mog<<c // here we have solution with two pieces of size 5
1|0111110000 // (mog<<a)|(mog<<b)|(mog<<c)
^ now bit set, so we have a solution
We know that there is exactly i cuts at that point, so we set ost=i. But we found the worst solution, we have to keep going until we are sure that there is no more solutions.
Eventually we will reach this state:
i=5:
1|1100000000 // mog
1|0000000000 // mog<<a // 5 pieces of size 2
0|0000000000 // mog<<b
0|0000000000 // mog<<c
1|0000000000 // (mog<<a)|(mog<<b)|(mog<<c)
Here it is the last time when bit at position n will be set. So we will set ost=5 and will do some more iterations.
Algorithm uses n as upper bound of possible cuts, but it's obvious that this bound can be improved. For example n / min({a,b,c}) should be sufficient.

Codechef beginner permut2: getting error -it gives wrong answer on codechef but gives correct for sample input

Question:
A permutation of the integers 1 to n is an ordering of these integers. So the natural way to represent a permutation is to list the integers in this order. With n = 5, a permutation might look like 2, 3, 4, 5, 1.
However, there is another possibility of representing a permutation: You create a list of numbers where the i-th number is the position of the integer i in the permutation. Let us call this second possibility an inverse permutation. The inverse permutation for the sequence above is 5, 1, 2, 3, 4.
An ambiguous permutation is a permutation which cannot be distinguished from its inverse permutation. The permutation 1, 4, 3, 2 for example is ambiguous, because its inverse permutation is the same. To get rid of such annoying sample test cases, you have to write a program which detects if a given permutation is ambiguous or not.
Input Specification
The input contains several test cases.
The first line of each test case contains an integer n (1 ≤ n ≤ 100000). Then a permutation of the integers 1 to n follows in the next line. There is exactly one space character between consecutive integers. You can assume that every integer between 1 and n appears exactly once in the permutation.
The last test case is followed by a zero.
Output Specification
For each test case output whether the permutation is ambiguous or not. Adhere to the format shown in the sample output.
Sample Input
4
1 4 3 2
5
2 3 4 5 1
1
1
0
Answer:
#include<iostream>
#include<math.h>
using namespace std;
int main(){
int t;
while(true){
scanf("%d",&t); // no of digits/numbers
if(t ==0) //if its 0 then break
break;
int a[t+2],i=1;
while(t--){
scanf("%d",&a[i++]); // take t numbers
}
int f=0;
for(int j=1;j<i;j++){
int p=a[j]; //for every position take array value at that position
f=0;
if(a[p]!= j){ //for array value at that position check if its equal to index according to sample input or output
f=1; // if fails for any digit then break loop and not ambiguous
break;
}
}
if(f==1)
printf("not ambiguous\n"); //inverse ambiguous
else
printf("ambiguous\n"); //not ambiguous
}
return 0;
}
The problem is that you couldn't create such a large (100000 elements) arrays inside function. You should create one global array:
using namespace std;
const int MaxN = 100000;
int a[MaxN+2];
int main(){
...
}

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

Group the numbers C++

Here's the problem:
You have N (N represents the number of numbers that you have) numbers. Divide them in 2 groups in such way that the difference between sums of the numbers in the groups is minimal.
Examples:
5 // N
1, 9, 5, 3, 8 // The numbers
The difference is 0 if we put 1, 9 and 3 in Group A and 5 and 8 in Group B.
I think first I should calculate the sum of all numbers and divide it by 2. Then to check ever possible combination of numbers, whose sum is not higher than half of the sum of all numbers. After I do this I will choose the biggest number and print out the groups.
I have problem with going through all combinations, especialy when N is big numbers. How can I run through all combinations?
Also i think a little bit differently, I will group the numbers in descending order and i'll put the biggest number in Group A and lowest in Group B. Then I do the other way around. This works with some of the numbers, but sometimes it doesn't show the optimal grouping. For example:
If I use the previous example. Arrange the number in descending order.
9, 8, 5, 3, 1.
Put the biggest in Group A and lowest in Group B.
Group A: 9
Group B: 1
Other way around.
Group A: 9, 3
Group B: 1, 8
And so on. If in the end i have only one number I'll put it in the group with lower sum.
So I finally will get:
Group A: 9, 3
Group B: 1, 8, 5
This isn't the optimal grouping because the difference is 2, but with grouping in different way the difference can be 0, as I showed.
How can I get optimal grouping?
CODE:
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int convertToBinary(int number) {
int remainder;
int binNumber = 0;
int i = 1;
while(number!=0)
{
remainder=number%2;
binNumber=binNumber + (i*remainder);
number=number/2;
i=i*10;
}
return binNumber;
}
int main()
{
int number, combinations, sum = 0;
double average;
cin >> number;
int numbers[number];
for(int i = 0; i<number; i++)
{
cin >> numbers[i];
sum += numbers[i];
}
if(sum%2 == 0)
{
average = sum/2;
}
else
{
average = sum/2 + 0.5;
}
combinations = pow(2,number-1);
double closest = average;
for(int i = 0; i<=combinations;i++)
{
int rem;
int temp_sum = 0;
int state = convertToBinary(i);
for(int j = 0; state!=0; j++)
{
int rem =state%10;
state = state/10;
if(rem == 1)
{
temp_sum = temp_sum + numbers[j];
}
}
if(abs(average-temp_sum)<closest)
{
closest = abs(average-temp_sum);
if(closest == 0)
{
break;
}
}
}
cout << closest*2;
return 0;
}
Although this, as others have commented, is an NP-Complete problem, you have provided two fairly helpful bounds: you only want to split the group of numbers into two groups and you want to get the sums of the two groups as close as possible.
Your suggestion of working out the total sum of the numbers and dividing it by two is the right starting point - this means you know what the ideal sum of each group is. I also suspect that your best bet is to start by putting the largest number into, say, group A. (it has to go into one group, and it's the worst one to place later, so why not put it in there?)
This is when we get into heuristics which you cycle through until the groups are done:
N: Size of list of numbers.
t: sum of numbers divided by two (t is for target)
1. Is there a non-placed number which gets either group to within 0.5 of t? If so, put it in that group, put the remaining numbers in the other group and you're done.
2. If not, place the biggest remaining number in the group with the current lowest sum
3. go back to 1.
There will doubtless be cases that fail, but as a rough approach this should get close fairly often. To actually code the above, you will want to put the numbers in an ordered list so it is easy to work through them from largest to smallest. (Step 1 can then also be streamlined by checking (against both "groups so far") from largest remaining down until the "group so far" added to the number being checked are more then 1.0 below t - after that the condition cannot be met.)
Do let me know if this works!
Using the constraint of only two groups zour problem is already solved if you can find one grouping of numbers whichs sum is exactlz half of the total. thus I suggest you try to find this group and put the remainder into the other group obviously.
The assumption to put the biggest number in the first group is simple. Now the rest is more tricky.
This is simple in the binary system: Consider that for each number you have a bit. The bit beeing 1 signals that the number is in group A, otherwise it is in group B. The entire distribution can be described by a concatination of these bits. This can be considered a number. SO to check all combinations you have to go through all the numbers and calculate the combination.
code:
#include <iostream>
#include <memory>
using namespace std;
int partition(const std::unique_ptr<int[]>& numbers, int elements) {
int sum = 0;
for(int i=0; i<elements; ++i) {
sum += numbers[i];
}
double average = sum/2.0;
double closest = average+.5;
int beststate = 0;
for(int state=1; state< 1<<(elements-1);++state) {
int tempsum = 0;
for(int i=0; i<elements; ++i) {
if( state&(1<<i) ) {
tempsum += numbers[i];
}
}
double delta=abs(tempsum-average);
if(delta < 1) { //if delta is .5 it won't get better i.e. (3,5) (9) => average =8.5
cout << state;
return state;
}
if(delta<closest) {
closest = delta;
beststate = state;
}
}
return beststate;
}
void printPartition(int state, const std::unique_ptr<int[]>& numbers, int elements) {
cout << "(";
for(int i=0; i<elements; ++i) {
if(state&(1<<i)) {
cout << numbers[i]<< ",";
}
}
cout << ")" << endl;
}
int main()
{
int elements;
cout << "number of elements:";
cin >> elements;
std::unique_ptr<int[]> numbers(new int[elements]);
for(int i = 0; i<elements; i++)
{
cin >> numbers[i];
}
int groupA = partition(numbers, elements);
cout << "\n\nSolution:\n";
printPartition(groupA, numbers, elements);
printPartition(~groupA,numbers, elements);
return 0;
}
edit: For further (and better) solutions to generating all possibilities check this awnser. Here is a link to knuths book which I found here
edit2: To explain the concept of enumeration as requested:
suppose we have three elements, 1,23,5. all possible combinations disregarding permutations can be generated by filling out a table:
1 | 23 | 5 Concatination Decimal interpretation
-----------
0 | 0 | 0 000 0
0 | 0 | 1 001 1
0 | 1 | 0 010 2
0 | 1 | 1 011 3
1 | 0 | 0 100 4
1 | 0 | 1 101 5
1 | 1 | 0 110 6
1 | 1 | 1 111 7
If we now take for instant the number 4 this maps to 100 which says that the first number is in group A and the second and third number are not (which implies they are in group B). Thus A is 1 while B is 23,5.
Now to explain the trick why I only need to look at half: if we look at the decimal interpretation 3 (011 binary) we get for Group A 23,5 and for Group B 1. If we compare this to the example for 4 we notice that we have the same numbers grouped, just in the exactly opposite group names. Since this makes no difference for your problem we don't have to look at this.
edit3:
I added real code to try out, in the pseudocode i made the wrong assumption that i would always include the first element in the sum, which was wrong. As for your code that I started out on: you can't allocate arrays like that. Another solution instead of an Array would be a vector<int> which avoids the problems of having to pass the arraysize to the functions. Using this would be a great improvement. Furthermore this code is far from good. You will run into issues with int size (usually this should work for up to 32 elements). You can work arround this though (try this maybe How to handle arbitrarily large integers). Or you actually read up on knuth (see above) I am sure you will find some recursive approach.
THis code is also slow, since it always rebuilds the whole sum. One optimization would be to look into gray codes (I think Knuth describes them aswell). That way you only have to add/substract one number per permutation you test. That would be a performance boost in the order of n, since you replace n-1 additions with 1 addition/substraction.
If the average value of the individual group is same as the average of the complete set, then obviously the difference between the two group will be less. By using this we can bring up a algorithm for this problem.
Get the average of the complete set.
Take the largest value in the set and put it in one of the group.
Get the difference of the average of the individual group and the average of the entire set.
Place the next largest number in the group which is having the maximum difference.
Repeat the steps 3 and 4 until all the numbers are placed.
This will be the efficient approach to get the near optimal solution.
How about this:
Sort the list of numbers.
Put the largest number in group A. Remove that number from the list.
If the sum of all numbers in group A is less than the sum of all numbers in group B, goto 2.
Put the largest number in group B. Remove that number from the list.
If the sum of all numbers in group B is less than the sum of all numbers in group A, goto 4.
If more than zero numbers remain in the list, goto 2.