Matrix coil (serpentine) - logic

there!
I have a problem in java to generate a matrix like this :
When n= 4
{{1 4 5 16},
{2 3 6 15},
{9 8 7 14},
{10 11 12 13}};
Matrix shoud contain numbers from 1 to n*n.
I do not want any code, I just want to see how the matrix looks like when n=5 and n=6.
I have searched on the internet and found just about the spiral matrix, but not this one.
Thank you!

I think the production rule of this matrix is to start in the top left corner, then fill it in the smallest possible loop by starting counter-clockwise, switching between clockwise and counter-clockwise as soon as the boundary is met.
So, for n = 5 it would look like this:
{{ 1 4 5 16 17},
{ 2 3 6 15 18},
{ 9 8 7 14 19},
{10 11 12 13 20},
{25 24 23 22 21}};
And for n = 6 it would look like this:
{{ 1 4 5 16 17 36},
{ 2 3 6 15 18 35},
{ 9 8 7 14 19 34},
{10 11 12 13 20 33},
{25 24 23 22 21 32},
{26 27 28 29 30 31}};
There are some interesting invariants.
In the first row, every second entry is the square of an even, starting with 4 (2).
In the first column, every second entry is the square of an odd, starting with 1 (1).
The production of the diagonal is F(n) := n == 1 ? 1 : F(n-1) + 2(n-1)
Nice stuff, have fun programming with it.

Related

Quicksort on an set of length 2

When quicksorting a dataset the list gets split down and is recursive, in that the solution calls itself on the smaller lists.
I was practising quicksort on an algorithm but a sublist of length 2 is a stone in my shoe, I can't solve it. The original list was:
2 0 1 7 4 3 5 6
Pivot being at 2, left at 0, right at 6, I start. Left moves along to 7, 7>=2. Right moves down to 1, 1<=2. Left and right have crossed. As I understand, now right becomes the split point and two new lists are formed.
2 0 1 7 4 3 5 6
As you can see, the first list, 2 and 0, is 2 items long. So 2 is the pivot, and 0 is both left and right. Left doesn't move along, right moves along to 2, 2<=2. Left and right have crossed so p replaces R and L onwards is a new list. But this leaves 2 and 0 unsorted.
Where am I going wrong?
The problem in your case came from the fact that i don't move pivot in its sorted place. After the partitioning with pivot 2 your array should look like this:
0 1 2 7 4 3 5 6
^
Let's go through partition procedure with the input array 13 19 9 5 12 8 7 4 21 2 6 11. And let's choose 11 as a pivot.
During the procedure, you need to maintain two pointers, one for the element just before the first element bigger than the pivot ^^, and another one for the current you are looking at ||.
The code looks like this:
A is array left..right
pivot = A[right]
i = left - 1 // the one before the first bigger than the pivot
for j = left to right - 1
if A[j] <= pivot
i = i + 1
swap A[i] with A[j]
swap A[i+1] with A[right] // put pivot at its place, i + 1 - is the index to split on
And the example:
13 19 9 5 12 8 7 4 21 2 6 11
13 19 9 5 12 8 7 4 21 2 6 11 13 > 11, skip
^^ ||
13 19 9 5 12 8 7 4 21 2 6 11 19 > 11, skip
^^ ||
9 19 13 5 12 8 7 4 21 2 6 11 9 < 11, swap
^^ ||
9 5 13 19 12 8 7 4 21 2 6 11 5 < 11, swap
^^ ||
9 5 13 19 12 8 7 4 21 2 6 11 12 > 11, skip
^^ ||
9 5 8 19 12 13 7 4 21 2 6 11 8 < 11, swap
^^ ||
9 5 8 7 12 13 19 4 21 2 6 11 7 < 11, swap
^^ ||
9 5 8 7 4 13 19 12 21 2 6 11 4 < 11, swap
^^ ||
9 5 8 7 4 13 19 12 21 2 6 11 21 > 11, skip
^^ ||
can you continue yourself?
The quicksort algorithm only has base case of empty array or array of size 1. In your case of [2 0] , the algorithm chooses 2 as a pivot, partitions [2 0] into empty array and array [0] and merges it with pivot [2], giving sorted array [0 2].

Euler18 dynamic algorithm

Given the array [5, 4, 12, 3, 11, 7, 2, 8, 1, 9] that forms a triangle like so:
5
4 12
3 11 7
2 8 1 9
Result should be 5 + 12 + 7 + 9 = 31.
Write a function that will traverse the triangle and find the largest possible sum of values when you can go from one point to either directly bottom left, or bottom right.
Refering to the dynamic algorithm in that link:
http://www.mathblog.dk/project-euler-18/
Result is 36.
5
4 12
3 11 7
2 8 1 9
5
4 12
11 19 16
5
23 31
36
Where is my mistake ??
The description of Problem 18 starts with an example where the optimal path is “left-right-right”. So you get a new choice of direction after every step, which means that after taking the first step to the right, you are still free to take the second step to the left and eventually come up with 5+12+11+8=36 as the optimal solution in your example, larger than the 31 you assumed. So the computation is correct in solving the problem as described. Your assumption about choosing a direction only once and then sticking with that choice would lead to a different (and rather boring) problem.

Insertion into a binary heap

If I have an array representing a minimum binary heap that contains the values {2, 8, 3, 10, 16, 7, 18, 13, 15}, what would the array look like after inserting the value of 4? Also, how would I demonstrate this to be correct?
I deduced it would be 2,4,3,10,8,7,18,13,15,16. Is that correct?
To demonstrate that your min heap is correct, you need to prove recursively that your child nodes are larger than your root node
If your root node is n, your child nodes are 2n+1 and 2n+2, so iterate through your tree and check if child nodes are greater than parent. If this logic is not satisfied anywhere then your heap is bad.
2
8 3
10 16 7 18
13 15
push at end
2
8 3
10 **16** 7 18
13 15 4
compare and replace with parent
2
**8** 3
10 4 7 18
13 15 16
compare and replace with parent-no replacement
**2**
4 3
10 8 7 18
13 15 16

Sum Pyramid with backtracking

I'm trying to solve this problem and I'm new to backtracking algorithms,
The problem is about making a pyramid like this so that a number sitting on two numbers is the sum of them. Every number in the pyramid has to be different and less than 100. Like this:
88
39 49
15 24 25
4 11 13 12
1 3 8 5 7
Any pointers on how to do this using backtracking?
Not necessarily backtracking but the property you are asking for is interestingly very similar to the Pascal Triangle property.
The Pascal Triangle (http://en.wikipedia.org/wiki/Pascal's_triangle), which is used for efficient computation of binomial coefficient among other things, is a pyramid where a number is equal to the sum of the two numbers above it with the top being 1.
As you can see you are asking the opposite property where a number is the sum of the numbers below it.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
For instance in the Pascal Triangle above, if you wanted the top of your pyramid to be 56, your pyramid will be a reconstruction bottom up of the Pascal Triangle starting from 56 and that will give something like:
56
21 35
6 15 20
1 5 10 10
Again that's not a backtracking solution and this might not give you a good enough solution for every single N though I thought this was an interesting approximation that was worth noting.

What is the worst case scenario for quicksort?

When does the quicksort algorithm take O(n^2) time?
Quicksort works by taking a pivot, then putting all the elements lower than that pivot on one side and all the higher elements on the other; it then recursively sorts the two sub groups in the same way (all the way down until everything is sorted.) Now if you pick the worst pivot each time (the highest or lowest element in the list) you'll only have one group to sort, with everything in that group other than the original pivot that you picked. This in essence gives you n groups that each need to be iterated through n times, hence the O(n^2) complexity.
The most common reason for this occurring is if the pivot is chosen to be the first or last element in the list in the quicksort implementation. For unsorted lists this is just as valid as any other, however for sorted or nearly sorted lists (which occur quite commonly in practice) this is very likely to give you the worst case scenario. This is why all half-decent implementations tend to take a pivot from the centre of the list.
There are modifications to the standard quicksort algorithm to avoid this edge case - one example is the dual-pivot quicksort that was integrated into Java 7.
In short, Quicksort for sorting an array lowest element first works like this:
Choose a pivot element
Presort array, such that all elements smaller than the pivot are on the left side
Recursively do step 1. and 2. for the left side and the right side
Ideally, you would want a pivot element that partitions the sequence in two equally long subsequences but this is not so easy.
There are different schemes for choosing the pivot element. Early versions just took the leftmost element. In the worst case, the pivot element will always be the lowest element of the current range.
Leftmost element is pivot
In this case it can be easily thought out that the worst case is an monotonic increasing array:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Rightmost element is pivot
Similarly, when choosing the rightmost element the worst case will be a decreasing sequence.
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Center element is pivot
One possible remedy for the worst-case for presorted arrays, is to use the center element (or slightly left of center if the sequence is of even length). Then, the worst case would be quite more exotic. It can be constructed by modifying the Quicksort algorithm to set the array elements corresponding to the currently selected pivot element to a monotonic increasing value. I.e. we know the first pivot is the center, so the center must be the lowest value, e.g. 0. Next it gets swapped to the leftmost, i.e. the leftmost value is now in the center and would be the next pivot element, so it must be 1. Now, we can already guess that the array would look like this:
1 ? ? 0 ? ? ?
Here is the C++ code for the modified Quicksort to generate a worst sequence:
// g++ -std=c++11 worstCaseQuicksort.cpp && ./a.out
#include <algorithm> // swap
#include <iostream>
#include <vector>
#include <numeric> // iota
int main( void )
{
std::vector<int> v(20); /**< will hold the worst case later */
/* p basically saves the indices of what was the initial position of the
* elements of v. As they get swapped around by Quicksort p becomes a
* permutation */
auto p = v;
std::iota( p.begin(), p.end(), 0 );
/* in the worst case we need to work on v.size( sequences, because
* the initial sequence is always split after the first element */
for ( auto i = 0u; i < v.size(); ++i )
{
/* i can be interpreted as:
* - subsequence starting index
* - current minimum value, if we start at 0 */
/* note thate in the last step iPivot == v.size()-1 */
auto const iPivot = ( v.size()-1 + i )/2;
v[ p[ iPivot ] ] = i;
std::swap( p[ iPivot ], p[i] );
}
for ( auto x : v ) std::cout << " " << x;
}
The result:
0
0 1
1 0 2
2 0 1 3
1 3 0 2 4
4 2 0 1 3 5
1 5 3 0 2 4 6
4 2 6 0 1 3 5 7
1 5 3 7 0 2 4 6 8
8 2 6 4 0 1 3 5 7 9
1 9 3 7 5 0 2 4 6 8 10
6 2 10 4 8 0 1 3 5 7 9 11
1 7 3 11 5 9 0 2 4 6 8 10 12
10 2 8 4 12 6 0 1 3 5 7 9 11 13
1 11 3 9 5 13 7 0 2 4 6 8 10 12 14
8 2 12 4 10 6 14 0 1 3 5 7 9 11 13 15
1 9 3 13 5 11 7 15 0 2 4 6 8 10 12 14 16
16 2 10 4 14 6 12 8 0 1 3 5 7 9 11 13 15 17
1 17 3 11 5 15 7 13 9 0 2 4 6 8 10 12 14 16 18
10 2 18 4 12 6 16 8 14 0 1 3 5 7 9 11 13 15 17 19
1 11 3 19 5 13 7 17 9 15 0 2 4 6 8 10 12 14 16 18 20
16 2 12 4 20 6 14 8 18 10 0 1 3 5 7 9 11 13 15 17 19 21
1 17 3 13 5 21 7 15 9 19 11 0 2 4 6 8 10 12 14 16 18 20 22
12 2 18 4 14 6 22 8 16 10 20 0 1 3 5 7 9 11 13 15 17 19 21 23
1 13 3 19 5 15 7 23 9 17 11 21 0 2 4 6 8 10 12 14 16 18 20 22 24
There is order in this. The right side is just increments of two starting with zero. The left side also has an order. Let's format the left side for the 73 element long worst case sequence nicely using Ascii art:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
------------------------------------------------------------------------------------------------------------
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35
37 39 41 43 45 47 49 51 53
55 57 59 61 63
65 67
69
71
The header is the element index. In the first row numbers starting from 1 and increasing by 2 are given to every 2nd element. In the second row the same is done to every 4th element, in the 3rd row numbers are assigned to every 8th element and so on. In this case the first value to be written in the i-th row is at index 2^i-1, but for certain lengths this looks a tad different.
The resulting structure is reminiscent to an inverted binary tree whose nodes are labeled bottom-up starting from the leaves.
Median of leftmost, center and rightmost elements is pivot
Another way is to use the median of the leftmost, the center and the rightmost element. In this case the worst case can only be, that the w.l.o.g. left subsequence is of length 2 (not just length 1 like in the examples above). Also we assume that the rightmost value will always be the highest of the median-of-three. This also means it is the highest of all values. Making adjustments in the program above, we now have this:
auto p = v;
std::iota( p.begin(), p.end(), 0 );
auto i = 0u;
for ( ; i < v.size(); i+=2 )
{
auto const iPivot0 = i;
auto const iPivot1 = ( i + v.size()-1 )/2;
v[ p[ iPivot1 ] ] = i+1;
v[ p[ iPivot0 ] ] = i;
std::swap( p[ iPivot1 ], p[i+1] );
}
if ( v.size() > 0 && i == v.size() )
v[ v.size()-1 ] = i-1;
The generated sequences are:
0
0 1
0 1 2
0 1 2 3
0 2 1 3 4
0 2 1 3 4 5
0 4 2 1 3 5 6
0 4 2 1 3 5 6 7
0 4 2 6 1 3 5 7 8
0 4 2 6 1 3 5 7 8 9
0 8 2 6 4 1 3 5 7 9 10
0 8 2 6 4 1 3 5 7 9 10 11
0 6 2 10 4 8 1 3 5 7 9 11 12
0 6 2 10 4 8 1 3 5 7 9 11 12 13
0 10 2 8 4 12 6 1 3 5 7 9 11 13 14
0 10 2 8 4 12 6 1 3 5 7 9 11 13 14 15
0 8 2 12 4 10 6 14 1 3 5 7 9 11 13 15 16
0 8 2 12 4 10 6 14 1 3 5 7 9 11 13 15 16 17
0 16 2 10 4 14 6 12 8 1 3 5 7 9 11 13 15 17 18
0 16 2 10 4 14 6 12 8 1 3 5 7 9 11 13 15 17 18 19
0 10 2 18 4 12 6 16 8 14 1 3 5 7 9 11 13 15 17 19 20
0 10 2 18 4 12 6 16 8 14 1 3 5 7 9 11 13 15 17 19 20 21
0 16 2 12 4 20 6 14 8 18 10 1 3 5 7 9 11 13 15 17 19 21 22
0 16 2 12 4 20 6 14 8 18 10 1 3 5 7 9 11 13 15 17 19 21 22 23
0 12 2 18 4 14 6 22 8 16 10 20 1 3 5 7 9 11 13 15 17 19 21 23 24
Pseudorandom element with random seed 0 is pivot
The worst case sequences for center element and median-of-three look already pretty random, but in order to make Quicksort even more robust the pivot element can be chosen randomly. If the random sequence used is at least reproducible on every Quicksort run, then we can also construct a worst case sequence for that. We only have to adjust the iPivot = line in the first program, e.g. to:
srand(0); // you shouldn't use 0 as a seed
for ( auto i = 0u; i < v.size(); ++i )
{
auto const iPivot = i + rand() % ( v.size() - i );
[...]
The generated sequences are:
0
1 0
1 0 2
2 3 1 0
1 4 2 0 3
5 0 1 2 3 4
6 0 5 4 2 1 3
7 2 4 3 6 1 5 0
4 0 3 6 2 8 7 1 5
2 3 6 0 8 5 9 7 1 4
3 6 2 5 7 4 0 1 8 10 9
8 11 7 6 10 4 9 0 5 2 3 1
0 12 3 10 6 8 11 7 2 4 9 1 5
9 0 8 10 11 3 12 4 6 7 1 2 5 13
2 4 14 5 9 1 12 6 13 8 3 7 10 0 11
3 15 1 13 5 8 9 0 10 4 7 2 6 11 12 14
11 16 8 9 10 4 6 1 3 7 0 12 5 14 2 15 13
6 0 15 7 11 4 5 14 13 17 9 2 10 3 12 16 1 8
8 14 0 12 18 13 3 7 5 17 9 2 4 15 11 10 16 1 6
3 6 16 0 11 4 15 9 13 19 7 2 10 17 12 5 1 8 18 14
6 0 14 9 15 2 8 1 11 7 3 19 18 16 20 17 13 12 10 4 5
14 16 7 9 8 1 3 21 5 4 12 17 10 19 18 15 6 0 11 2 13 20
1 2 22 11 16 9 10 14 12 6 17 0 5 20 4 21 19 8 3 7 18 15 13
22 1 15 18 8 19 13 0 14 23 9 12 10 5 11 21 6 4 17 2 16 7 3 20
2 19 17 6 10 13 11 8 0 16 12 22 4 18 15 20 3 24 21 7 5 14 9 1 23
So how to check whether those sequences are correct?
Measure time it took for the sequences. Plot time over the sequence length N. If the curve scales with O(N^2) instead of O(N log(N)), then these are indeed worst case sequences.
Adjust a correct Quicksort to give debug output about the subsequence lengths and/or the chosen pivot elements. One of the subsequences should always be of length 1 (or 2 for median-of-three). The chosen pivot elements printed should be increasing.
Getting a pivot equal to the lowest or highest number, should also trigger the worst case scenario of O(n2).
Different implementations of quicksort have different datasets required to give it a worstcase runtime. It depends on where the algorithm selects it's pivot-element.
And also as Ghpst said, selecting the biggest or smallest number would give you a worstcase.
If I remember correctly quicksort normally uses a random element for pivot to minimize the chance of getting a worstcase.
I think if the array is in revrse order then it will be worst case for pivot the last element of that array
The factors that contribute to the worst-case scenario of quicksort are as follows:
Worst case occurs when the subarrays are completely unbalanced
The worst case occurs when there are 0 elements in one subarray and n-1 elements in the other.
In other words, the worst-case running time of quicksort occurs when Quicksort takes in a sorted array (in decreasing order), to be on the time complexity of O(n^2).

Resources