Bubble Sort Ascending Comparison & Swap Count - algorithm

We are studying algorithms and we haven't yet started making any programs with it, so we have a simple exercises. For example:
I have to bubble sort:
4 2 7 16 6
Here is a proccess (we have to look from the right to left in this case):
4 2 7 16 6 (it makes 3 swaps and 4 comparisons in this)
2 4 6 7 16 (it makes 0 swaps and 3 comparison in this)
2 4 6 7 16 (the result)
This how I understand it:
4 2 7 16 6 (6 is swapped with 16)
4 2 7 6 16 (6 is swapped with 7)
4 2 6 7 16 (6 is not swapped with 2)
4 2 6 7 16 (2 is swapped with 4)
2 4 6 7 16 (result after 1st iteration)
now we have numbers which have been arranged properly, we have made 4 comparisons at the beginning and 3 swaps and we know that 2 is the smallest number so we will look at 4 6 7 16 now. However they are arranged properly but still we have to make 3 additional
comparisons.
My question is: do we have to make another 2 comparisons and then the last 1 comparison (which would result in 10 comparisons overall) to finish the bubble sort? Or it stops after 7?
I'm not sure when the Bubble-sort stops.

Related

Can you check for duplicates by taking the sum of the array and then the product of the array?

Let's say we have an array of size N with values from 1 to N inside it. We want to check if this array has any duplicates. My friend suggested two ways that I showed him were wrong:
Take the sum of the array and check it against the sum 1+2+3+...+N. I gave the example 1,1,4,4 which proves that this way is wrong since 1+1+4+4 = 1+2+3+4 despite there being duplicates in the array.
Next he suggested the same thing but with multiplication. i.e. check if the product of the elements in the array is equal to N!, but again this fails with an array like 2,2,3,2, where 2x2x3x2 = 1x2x3x4.
Finally, he suggested doing both checks, and if one of them fails, then there is a duplicate in the array. I can't help but feel that this is still incorrect, but I can't prove it to him by giving him an example of an array with duplicates that passes both checks. I understand that the burden of proof lies with him, not me, but I can't help but want to find an example where this doesn't work.
P.S. I understand there are many more efficient ways to solve such a problem, but we are trying to discuss this particular approach.
Is there a way to prove that doing both checks doesn't necessarily mean there are no duplicates?
Here's a counterexample: 1,3,3,3,4,6,7,8,10,10
Found by looking for a pair of composite numbers with factorizations that change the sum & count by the same amount.
I.e., 9 -> 3, 3 reduces the sum by 3 and increases the count by 1, and 10 -> 2, 5 does the same. So by converting 2,5 to 10 and 9 to 3,3, I leave both the sum and count unchanged. Also of course the product, since I'm replacing numbers with their factors & vice versa.
Here's a much longer one.
24 -> 2*3*4 increases the count by 2 and decreases the sum by 15
2*11 -> 22 decreases the count by 1 and increases the sum by 9
2*8 -> 16 decreases the count by 1 and increases the sum by 6.
We have a second 2 available because of the factorization of 24.
This gives us:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
Has the same sum, product, and count of elements as
1,3,3,4,4,5,6,7,9,10,12,13,14,15,16,16,17,18,19,20,21,22,22,23
In general you can find these by finding all factorizations of composite numbers, seeing how they change the sum & count (as above), and choosing changes in both directions (composite <-> factors) that cancel out.
I've just wrote a simple not very effective brute-force function. And it shows that there is for example
1 2 4 4 4 5 7 9 9
sequence that has the same sum and product as
1 2 3 4 5 6 7 8 9
For n = 10 there are more such sequences:
1 2 3 4 6 6 6 7 10 10
1 2 4 4 4 5 7 9 9 10
1 3 3 3 4 6 7 8 10 10
1 3 3 4 4 4 7 9 10 10
2 2 2 3 4 6 7 9 10 10
My write-only c++ code is here: https://ideone.com/2oRCbh

Maximize the minimum score

Given a grid of dimensions A*B with values between 1-9, find a sequence of B numbers that maximizes the minimum number of values matched when compared with A rows.
Describe the certain steps you would take to maximize the minimum score.
Example:
Grid Dimension
A = 5 , B = 10
Grid Values
9 3 9 2 9 9 4 5 7 6
6 3 4 2 8 5 7 5 9 2
4 9 5 8 3 7 3 2 7 6
7 5 8 9 9 4 7 3 3 7
2 6 8 3 2 4 5 4 2 2
Possible Answer
6 3 8 2 9 4 7 5 7 4
Score Calculation
This answer scores
5 when compared with Row 1
5 when compared with Row 2
1 when compared with Row 3
4 when compared with Row 4
2 when compared with Row 5
And thus the minimal score for this answer is 1.
I would go for a local hill-climbing approach that you can complement with a randomization to avoid local minima. Something like:
1. Generate a random starting solution S
2. Compute its score score(S, row) for each row. We'll call min_score(S) the minimum score among all rows for S.
3. Attempt to improve the solution with:
For each digit i (1..B) in S:
If i belongs to a row such that score(S, row) > (min_score(S) + 1) then:
Change i to be the digit of a row with min_score(S). If there was only one row with min_score(S), then min_score(S) has improved by 1
Update the scores of all the rows.
If min_score(S) hasn't improved for more than N iterations of 3, go back to 1 and start with a new random solution.

Combining integer vectors

I have a vector of length k where each element is a 2-by-m matrix that is a mapping between indices. All elements are integers from the set {1,2,...,mn}, there are no duplicates within a given 2-by-m matrix, and I know what m and n are. I want an efficient way of finding n-1 of these 2-by-m matrices such that combining these mappings gives me all of the elements in {1,2,...,mn}. To make things more concrete, assume that m=n=3 and my vector is
4 3 6
2 7 5
4 6 3
1 9 8
9 1 8
6 2 7
7 8 3
2 1 4
I want the algorithm to output
4 3 6
2 7 5
1 8 9
which is found by combining the first two mappings.

Build heap algorithm(s) on an array.Generate outcomes without brute-forcing

The Build-Heap algorithm given in CLRS
BUILD-MAX-HEAP(A)
1 heap-size[A] ← length[A]
2 for i ← ⌊length[A]/2⌋ downto 1
3 do MAX-HEAPIFY(A, i)
It produces only One of several possible cases.Are there other algorithms which would yield a different case than that of the above algorithm.
For input array
A={4,1,3,2,16,9,10,14,8,7}
Build-Heap produces A={16,14,10,8,7,9,3,2,4,1} which satisfies heap property.
May be this is the most efficient algorithm to build a heap out of an array but there are several other permutations of the array which also have the heap property.
When i generated all permutations of the array and performed a test for heap property.I got 3360 permutations of the array which had the heap property.
Count1 16 9 14 4 8 10 3 2 1 7
Count2 16 9 14 4 8 10 3 1 2 7
Count3 16 9 14 4 8 10 2 1 3 7
Count4 16 9 14 4 8 10 2 3 1 7
Count5 16 9 14 4 8 10 7 2 1 3
Count6 16 9 14 4 8 10 7 2 3 1
Count7 16 9 14 4 8 10 7 1 3 2
Count8 16 9 14 4 8 10 7 1 2 3
Count9 16 9 14 4 8 10 7 3 1 2
Count10 16 9 14 4 8 10 7 3 2 1
...........................................................
Count3358 16 8 14 7 4 9 10 2 1 3
Count3359 16 8 14 7 4 9 10 3 2 1
Count3360 16 8 14 7 4 9 10 3 1 2
So is there a different build-heap algorithm which would give an output which differs from that of the above algorithm or which gives some of the 3360 possible outcomes?
Once we have used the build-heap to get an array which satisfies the heap property.How can we generate maximum number of other cases using this array.We can swap the leaf nodes of the heap to generate some of the cases.Is there any other way to get more possible cases without checking all permutations for heap property test?
Given the range of values in the array and all values being distinct.Can we say anything about the total number of possible cases that will satisfy the heap property?
Any heap building algorithm will be sensitive to the order in which items are inserted. Even the Build-Heap algorithm will generate a different heap if you give it the same elements, but in a different order.
Remember that when you're building a heap, the partially-built part must maintain the heap property after each insertion. So that's going to limit the different permutations that can be generated by any particular algorithm.
Given a heap, it's fairly easy to generate at least some of the permitted permutations.
A node doesn't care about the relative size of its two child nodes. Therefore, you can swap the children of any node, then do a sift-up on the smaller of the two to ensure that the heap property is maintained for that subtree (i.e., if it's smaller than one of its sub-nodes, swap it with that sub-node, and continue doing the same down that path until it gets to a spot where it's larger than either sub-node, or it's moved close enough to the end of the array that it's a leaf node.

Solving a recreational square packing problem

I was asked to find a 11x11-grid containing the digits such that one can read the squares of 1,...,100. Here read means that you fix the starting position and direction (8 possibilities) and if you can find for example the digits 1,0,0,0,0,4 consecutively, you have found the squares of 1, 2, 10, 100 and 20. I made a program (the algorithm is not my own. I modified slightly a program which uses best-first search to find a solution but it is too slow. Does anyone know a better algorithm to solve the problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
int val[21][21];//number which is present on position
int vnum[21][21];//number of times the position is used - useful if you want to backtrack
//5 unit borders
int mx[4]={-1,0,1,0};//movement arrays
int my[4]={0,-1,0,1};
int check(int x,int y,int v,int m)//check if you can place number - if you can, return number of overlaps
{
int c=1;
while(v)//extract digits one by one
{
if(vnum[x][y] && (v%10)!=val[x][y])
return 0;
if(vnum[x][y])
c++;
v/=10;
x+=mx[m];
y+=my[m];
}
return c;
}
void apply(int x,int y,int v,int m)//place number - no sanity checks
{
while(v)//extract digits one by one
{
val[x][y]=v%10;
vnum[x][y]++;
v/=10;
x+=mx[m];
y+=my[m];
}
}
void deapply(int x,int y,int v,int m)//remove number - no sanity checks
{
while(v)
{
vnum[x][y]--;
v/=10;
x+=mx[m];
y+=my[m];
}
}
int best=100;
void recur(int num)//go down a semi-random path
{
if(num<best)
{
best=num;
if(best)
printf("FAILED AT %d\n",best);
else
printf("SUCCESS\n");
for(int x=5;x<16;x++) // 16 and 16
{
for(int y=5;y<16;y++)
{
if(vnum[x][y]==0)
putchar('.');
else
putchar(val[x][y]+'0');
}
putchar('\n');
}
fflush(stdout);
}
if(num==0)
return;
int s=num*num,t;
vector<int> poss;
for(int x=5;x<16;x++)
for(int y=5;y<16;y++)
for(int m=0;m<4;m++)
if(t=check(x,y,s,m))
poss.push_back((x)|(y<<8)|(m<<16)|(t<<24));//compress four numbers into an int
if(poss.size()==0)
return;
sort(poss.begin(),poss.end());//essentially sorting by t
t=poss.size()-1;
while(t>=0 && (poss[t]>>24)==(poss.back()>>24))
t--;
t++;
//t is now equal to the smallest index which has the maximal overlap
t=poss[rand()%(poss.size()-t)+t];//select random index>=t
apply(t%256,(t>>8)%256,s,(t>>16)%256);//extract random number
recur(num-1);//continue down path
}
int main()
{
srand((unsigned)time(0));//seed
while(true)
{
for(int i=0;i<21;i++)//reset board
{
memset(val[i],-1,21*sizeof(int));
memset(vnum[i],-1,21*sizeof(int));
}
for(int i=5;i<16;i++)
{
memset(val[i]+5,0,11*sizeof(int));
memset(vnum[i]+5,0,11*sizeof(int));
}
recur(100);
}
}
Using a random search so far I only got to 92 squares with one unused spot (8 missing numbers: 5041 9025 289 10000 4356 8464 3364 3249)
1 5 2 1 2 9 7 5 6 9 5
6 1 0 8 9 3 8 4 4 1 2
9 7 2 2 5 0 0 4 8 8 2
1 6 5 9 6 0 4 4 7 7 4
4 4 2 7 6 1 2 9 0 2 2
2 9 6 1 7 8 4 4 0 9 3
6 5 5 3 2 6 0 1 4 0 6
4 7 6 1 8 1 1 8 2 8 1
8 0 1 3 4 8 1 5 3 2 9
0 5 9 6 9 8 8 6 7 4 5
6 6 2 9 1 7 3 9 6 9
The algorithm basically uses as solution encoding a permutation on the input (search space is 100!) and then places each number in the "topmost" legal position. The solution value is measured as the sum of the squares of the lengths of the numbers placed (to give more importance to long numbers) and the number of "holes" remaining (IMO increasing the number of holes should raise the likehood that another number will fit in).
The code has not been optimized at all and is only able to decode a few hundred solutions per second. Current solution has been found after 196k attempts.
UPDATE
Current best solution with this approach is 93 without free holes (7 missing numbers: 676 7225 3481 10000 3364 7744 5776):
9 6 0 4 8 1 0 0 9 3 6
6 4 0 0 2 2 5 6 8 8 9
1 7 2 9 4 1 5 4 7 6 3
5 8 2 3 8 6 4 9 6 5 7
2 4 4 4 1 8 2 8 2 7 2
1 0 8 9 9 1 3 4 4 9 1
2 1 2 9 6 1 0 6 2 4 1
2 3 5 5 3 9 9 4 0 9 6
5 0 0 6 1 0 3 5 2 0 3
2 7 0 4 2 2 5 2 8 0 9
9 8 2 2 6 5 3 4 7 6 1
This is a solution (all 100 numbers placed) however using a 12x12 grid (MUCH easier)
9 4 6 8 7 7 4 4 5 5 1 7
8 3 0 5 5 9 2 9 6 7 6 4
4 4 8 3 6 2 6 0 1 7 8 4
4 8 4 2 9 1 4 0 5 6 1 4
9 1 6 9 4 8 1 5 4 2 0 1
9 4 4 7 2 2 5 2 2 5 0 0
4 6 2 2 5 8 4 2 7 4 0 2
0 3 3 3 6 4 0 0 6 3 0 9
9 8 0 1 2 1 7 9 5 5 9 1
6 8 4 2 3 5 2 6 3 2 0 6
9 9 8 2 5 2 9 9 4 2 2 7
1 1 5 6 6 1 9 3 6 1 5 4
It has been found using a truly "brute force" approach, starting from a random matrix and keeping randomly changing digits when that improved the coverage.
This solution has been found by an highly unrolled C++ program automatically generated by a Python script.
Update 2
Using an incremental approach (i.e. keeping a more complex data structure so that when changing a matrix element the number of targets covered can be updated instead than recomputed) I got a much faster search (about 15k matrices/second investigated with a Python implementation running with PyPy).
In a few minutes this version was able to find a 99 quasi-solution (a number is still missing):
7 0 5 6 5 1 1 5 7 1 6
4 6 3 3 9 8 8 6 7 6 1
3 9 0 8 2 6 1 1 4 7 8
1 1 0 8 9 9 0 0 4 4 6
3 4 9 0 4 9 0 4 6 7 1
6 4 4 6 8 6 3 2 5 2 9
9 7 8 4 1 1 4 0 5 4 2
6 2 4 1 5 2 2 1 2 9 7
9 8 2 5 2 2 7 3 6 5 0
3 1 2 5 0 0 6 3 0 5 4
7 5 6 9 2 1 6 5 3 4 6
UPDATE 3
Ok. After a some time (no idea how much) the same Python program actually found a complete solution (several ones indeed)... here is one
6 4 6 9 4 1 2 9 7 3 6
9 2 7 7 4 4 8 1 2 1 7
1 0 6 2 7 0 4 4 8 3 4
2 1 2 2 5 5 9 2 9 6 5
9 2 5 5 2 0 2 6 3 9 1
1 6 3 6 0 0 9 3 7 0 6
6 0 0 4 9 0 1 6 0 0 4
9 8 4 4 8 0 1 4 5 2 3
2 4 8 2 8 1 6 8 6 7 5
1 7 6 9 2 4 5 4 2 7 6
6 6 3 8 8 5 6 1 5 2 1
The searching program can be found here...
You've got 100 numbers and 121 cells to work with, so you'll need to be very efficient. We should try to build up the grid, so that each time we fill a cell, we attain a new number in our list.
For now, let's only worry about 68 4-digit numbers. I think a good chunk of the shorter numbers will be in our grid without any effort.
Start with a 3x3 or 4x4 set of numbers in the top-left of your grid. It can be arbitrary, or fine-tune for slightly better results. Now let's fill in the rest of the grid one square at a time.
Repeat these steps:
Fill an empty cell with a digit
Check which numbers that knocked off the list
If it didn't knock off any 4-digit numbers, try a different digit or cell
Eventually you may need to fill 2 cells or even 3 cells to achieve a new 4-digit number, but this should be uncommon, except at the end (at which point, hopefully there's a lot of empty space). Continue the process for the (few?) remaining 3-digit numbers.
There's a lot room for optimizations and tweaks, but I think this technique is fast and promising and a good starting point. If you get an answer, share it with us! :)
Update
I tried my approach and only got 87 out of the 100:
10894688943
60213136008
56252211674
61444925224
59409675697
02180334817
73260193640
.5476685202
0052034645.
...4.948156
......4671.
My guess is that both algorithms are too slow. Some optimization algorithm might work like best-first search or simulated annealing but my I don't have much experience on programming those.
Have you tried any primary research on Two-Dimensional Bin Packing (2DBP) algorithms? Google Scholars is a good start. I did this a while ago when building an application to generate mosaics.
All rectangular bin packing algorithms can be divided into 4 groups based on their support for the following constraints:
Must the resulting bin be guillotine cuttable? I.e. do you have to later slice the bin(s) in half until all the pieces are unpacked?
Can the pieces be rotated to fit into the bin? Not an issue with square pieces, so this makes more algorithms available to you.
Out of all the algorithms I looked into, the most efficient solution is an Alternate Directions (AD) algorithm with a Tabu Search optimization layer. There are dissertations which prove this. I may be able to dig-up some links if this helps.
Some ideas off the top of my head, without investing much time into thinking about details.
I would start by counting the number of occurrences of each digit in all squares 1..100. The total number of digits will be obviously larger than 121, but by analyzing individual frequencies you can deduce which digits must be grouped on a single line to form as many different squares as possible. For example, if 0 has the highest frequency, you have to try to put as many squares containing a 0 on the same line.
You could maintain a count of digits for each line, and each time you place a digit, you update the count. This lets you easily compute which square numbers have been covered by that particular line.
So, the program will still be brute-force, but it will exploit the problem structure much better.
PS: Counting digit frequencies is the easiest way to decide whether a certain permutation of digits constitutes a square.

Resources