Why does my heap sort not work when I use the array of more than 10? c# - heapsort

Code:
class Program
{
static void HeapSort(int[] array, int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
Heapify(array, n, i);
for (int i = n - 1; i >= 0; i--)
{
int temp = array[0];
array[0] = array[i];
array[i] = temp;
Heapify(array, i, 0);
}
}
static void Heapify(int[] array, int n, int i)
{
int largest = i; // largest = 4
int left = 2 * i + 1; // left = 9
int right = 2 * i + 2; // right = 10
if (left < n && array[left] > array[largest]) //ar left < 10 ir ar ar9 > ar4
largest = left; //left tampa
if (right < n && array[right] > array[largest])
largest = right;
if (largest != i)
{
int swap = array[i];
array[i] = array[largest];
array[largest] = swap;
Heapify(array, n, largest);
}
}
public static void Main()
{
int[] arr = { 55, 25, 89, 34, 12, 19, 78, 95, 1, 100, 99, 98};
int n = 12, i;
Console.WriteLine("Heap Sort");
Console.Write("Initial array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
HeapSort(arr, 10);
Console.Write("\nSorted Array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
Console.ReadLine();
}
}
Works fine when I use the array of 10, but if I add elements, they are just put at the end of the array. Example:
int[] arr = { 55, 25, 89, 34, 12, 19, 78, 95, 1, 100};
int n = 10, i;
Output:
Heap Sort
Initial array is: 55 25 89 34 12 19 78 95 1 100
Sorted Array is: 1 12 19 25 34 55 78 89 95 100
now, if I add a couple more:
int[] arr = { 55, 25, 89, 34, 12, 19, 78, 95, 1, 100, 99, 98, 120, 44};
int n = 14, i;
Output:
Heap Sort
Initial array is: 55 25 89 34 12 19 78 95 1 100 99 98 120 44
Sorted Array is: 1 12 19 25 34 55 78 89 95 100 99 98 120 44
Why doesnt it sort the rest?

I found the error. I forgot to change the 10 in the first HeapSort call in Main function, leaving 10 there instead of n. Changing it to n fixed the problem.

Related

Max path with 2D array in java , arbitrary cell to start

I wanted to print the maximum value you can accumulate while moving on the 2D array until you go off the 2D edges.
Note the user either move to the right or to the button on the 2D array.
For example
so I write the code like the following
public static int find(int[][] A) {
int[][] solution = new int[A.length][A.length];
solution[0][0] = A[0][0];
// fill the first row
for (int i = 1; i < A.length; i++) {
solution[0][i] = A[0][i] + solution[0][i - 1];
}
// fill the first column
for (int i = 1; i < A.length; i++) {
solution[i][0] = A[i][0] + solution[i - 1][0];
}
// path will be either from top or left, choose which ever is maximum
int temp=0;
for (int i = 1; i < A.length; i++) {
for (int j = 1; j < A.length; j++) {
// if ((A[i][j]+ Math.max(solution[i - 1][j], solution[i][j - 1])) >A[i][j] )
solution[i][j] = A[i][j]
+ Math.max(solution[i - 1][j], solution[i][j - 1]);
// else solution[i][j] = A[i][j];
}
}
int temp1 = 0;
int temp2 =0;
for(int i=0; i< A.length; i++){
// System.out.println(" temp1= "+temp1);
if(solution[i][A.length-1] > temp1) temp1= solution[i][A.length-1];
//System.out.println(" temp1= "+temp1);
if(solution[A.length-1][i] > temp2) temp2= solution[A.length-1][i];
// System.out.println(" temp2= "+temp2);
}
for(int i=0; i< A.length; i++){
for (int j=0; j< A.length;j++){
System.out.print(solution[i][j]+"\t");
}
System.out.println(" ");
}
return Math.max(temp1,temp2);
}
but it gives me 592 as an output and didn't know where is the problem in my code.
The problem says that maximum value you can accumulate while moving on the 2D array, so the path of maximum sum can start from anywhere and end anywhere.
You should keep maximizing the result at each location (i,j). The maximum at each location can be one of the three below:
The value at the location itself : A[i][j]
The value + the maximum so far when you come from top : d[i-1][j] + A[i][j]
The value + the maximum so far when you come from left : d[i][j-1] + A[i][j]
You have to take the maximum of those three.
Code:
public static int find(int[][] A) {
int R = A.length;
int C = A[0].length;
int[][] d = new int[R+1][C+1];
int res = Integer.MIN_VALUE;
for ( int i = 1; i <= R; i++ ) {
for ( int j = 1; j <= C; j++ ) {
d[i][j] = Math.max( A[i-1][j-1], Math.max(d[i][j-1] + A[i-1][j-1], d[i-1][j] + A[i-1][j-1]));
res = Math.max( res, d[i][j]);
}
}
return res;
}
Output : 603
You can play with this code here
Edit:
Seems like my code is just like yours...
Anyways, I got 547.
The max will be solution[A.length-1][A.length-1].
Original Answer:
Here's what I got, using javascript (547) - I'm sure you can "translate" it to the language of your choice:
var inputArray=[
[-45, 87, -43, -12, 3, -39, -61, -19],
[ 97, -64, 79, -75, 19, 97, 80, 12],
[-24, -62, 46, 97, -75, -45, 92, 69],
[ 87, -31, 74, 33, -49, 1, 27, 95],
[ 13, -82, -19, 14, -76, 95, 64, -33],
[-25, 45, -61, 90, -90, 43, 32, 96],
[-27, 38, 77, -42, 36, 71, 32, 30],
[ 27, -52, -66, -78, -42, 66, 69, -11]
];
console.log(JSON.stringify(inputArray));
var maxArray=[];
for(var i=0; i<inputArray.length; i++) {
maxArray[i]=[];
for(var j=0; j<inputArray.length; j++) {
maxArray[i][j]=0;
}
}
console.log(JSON.stringify(maxArray));
maxArray[0][0]=inputArray[0][0];
for(var i=1; i<inputArray.length; i++) {
maxArray[0][i]=maxArray[0][i-1]+inputArray[0][i];
maxArray[i][0]=maxArray[i-1][0]+inputArray[i][0];
}
console.log(JSON.stringify(maxArray));
for(var i=1; i<inputArray.length; i++) {
for(var j=1; j<inputArray.length; j++) {
maxArray[i][j]=Math.max(maxArray[i-1][j], maxArray[i][j-1]) + inputArray[i][j];
}
}
console.log(JSON.stringify(maxArray));
var max=maxArray[inputArray.length-1][inputArray.length-1];
console.log("Max="+max);
I've used console.table instead of console.log(JSON.stringify, but snippet doesn't support it.
I've logged the results of each step.
First, I created an array of same dimension filled with zeros.
Then, I've copied first column/row's value.
Then, I've populated the rest of the first row and first column by adding inputArray and left/up values.
Then, I've populated the rest of the matrix by adding inputArray and max of left/up.
Last column holds max values should you go off to the right, and last row - off the bottom.
Furthest corner will be the absolute max - and I've logged it.

Collect global top-k from each node's list in MPI

I am running MPI instances in parallel. At some point, every instance has a list of 100 ranked values. I now want to collect the top-100 values from all the instances.
How can this be done in MPI? Is there a specialized function?
Thanks!
if you want to collect the top value of each instance, then MPI_Gather() is the right choice.
if you want to collect the 100 top values of all instances (e.g. the 100 top values amont n*100 values), then i do not think there is a "native" way to achieve that.
/* when you write list, i hope you really meant array */
that being said, you can use MPI_Op_create() in order to create an operator that works on two arrays, and then invoke MPI_Reduce() with the previously defined operator.
Gilles's suggestion is a very elegant one so I thought I'd write a simple example code as this would make an excellent exercise in user-defined operations for those learning MPI.
Note that I have abused the meaning of the "len" argument to the user-defined operation. This is meant to be the number of reductions to be performed and not the size of each reduction. In other words, len=5 should mean that you want to sort 5 independent lists on each process, and not that each process has a single list of length 5. To fix this would require defining a new MPI datatype appropriate for a complete list (e.g. MPI_Type_contiguous) but I can't get that working right now.
However, even this technically incorrect code illustrates the basic approach.
The sample output for lists of length 5 on 3 processes is:
rank 0, mysortedlist[0] = 12
rank 0, mysortedlist[1] = 9
rank 0, mysortedlist[2] = 6
rank 0, mysortedlist[3] = 3
rank 0, mysortedlist[4] = 0
rank 2, mysortedlist[0] = 14
rank 2, mysortedlist[1] = 11
rank 2, mysortedlist[2] = 8
rank 2, mysortedlist[3] = 5
rank 2, mysortedlist[4] = 2
rank 1, mysortedlist[0] = 13
rank 1, mysortedlist[1] = 10
rank 1, mysortedlist[2] = 7
rank 1, mysortedlist[3] = 4
rank 1, mysortedlist[4] = 1
rank 0, sortedlist[0] = 14
rank 0, sortedlist[1] = 13
rank 0, sortedlist[2] = 12
rank 0, sortedlist[3] = 11
rank 0, sortedlist[4] = 10
Here's the code.
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define N 5
void mergesortint(void *vinvec, void *vinoutvec, int *n, MPI_Datatype *type);
void mergelist(int *merge, int *a, int *b, int n);
int main(void)
{
int i;
// local sorted list
int mysortedlist[N];
// global sorted list
int sortedlist[N];
MPI_Comm comm;
MPI_Op MPI_MERGESORT;
// int rank, size;
int size, rank;
comm = MPI_COMM_WORLD;
MPI_Init(NULL, NULL);
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
// Register new reduction operation
MPI_Op_create(mergesortint, 1, &MPI_MERGESORT);
// Generate sorted lists on each rank
for (i=0; i < N; i++)
{
mysortedlist[i] = rank+size*(N-i-1);
sortedlist[i] = -1;
}
for (i=0; i < N; i++)
{
printf("rank %d, mysortedlist[%d] = %d\n", rank, i, mysortedlist[i]);
}
printf("\n");
// Perform reduction to rank 0
MPI_Reduce(mysortedlist, sortedlist, N, MPI_INT, MPI_MERGESORT, 0, comm);
if (rank == 0)
{
for (i=0; i < N; i++)
{
printf("rank %d, sortedlist[%d] = %d\n", rank, i, sortedlist[i]);
}
printf("\n");
}
MPI_Finalize();
return 0;
}
void mergesortint(void *vinvec, void *vinoutvec, int *n, MPI_Datatype *type)
{
int i;
int nvec = *n;
int *invec = (int *) vinvec;
int *inoutvec = (int *) vinoutvec;
int *mergevec = (int *) malloc(nvec*sizeof(int));
mergelist(mergevec, invec, inoutvec, nvec);
for (i=0; i < nvec; i++)
{
inoutvec[i] = mergevec[i];
}
free(mergevec);
}
void mergelist(int *merge, int *a, int *b, int n)
{
int i, ia, ib;
ia = 0;
ib = 0;
for (i=0; i < n; i++)
{
if (a[ia] > b[ib])
{
merge[i] = a[ia];
ia++;
}
else
{
merge[i] = b[ib];
ib++;
}
}
}
Here's the full code that works for multiple lists, i.e. the "count" argument to MPI_Reduce() is correctly interpreted as the number of individual lists and not the length of each list. Although the list length N is a constant in main, the reduction operation is more general and computes the length from the list type extent.
Here's the output for 3 lists of length 5 on 4 processes:
dsh#laptop> mpirun -n 4 ./mergesortlist
rank 1, mysortedlist[0] = 17 117 217
rank 1, mysortedlist[1] = 13 113 213
rank 1, mysortedlist[2] = 9 109 209
rank 1, mysortedlist[3] = 5 105 205
rank 1, mysortedlist[4] = 1 101 201
rank 2, mysortedlist[0] = 18 118 218
rank 2, mysortedlist[1] = 14 114 214
rank 2, mysortedlist[2] = 10 110 210
rank 2, mysortedlist[3] = 6 106 206
rank 2, mysortedlist[4] = 2 102 202
rank 3, mysortedlist[0] = 19 119 219
rank 3, mysortedlist[1] = 15 115 215
rank 3, mysortedlist[2] = 11 111 211
rank 3, mysortedlist[3] = 7 107 207
rank 3, mysortedlist[4] = 3 103 203
rank 0, mysortedlist[0] = 16 116 216
rank 0, mysortedlist[1] = 12 112 212
rank 0, mysortedlist[2] = 8 108 208
rank 0, mysortedlist[3] = 4 104 204
rank 0, mysortedlist[4] = 0 100 200
rank 0, sortedlist[0] = 19 119 219
rank 0, sortedlist[1] = 18 118 218
rank 0, sortedlist[2] = 17 117 217
rank 0, sortedlist[3] = 16 116 216
rank 0, sortedlist[4] = 15 115 215
and here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#define NUMLIST 3 // Number of distinct lists (of integers)
#define N 5 // Length of each list
void mergesortlist(void *vinvec, void *vinoutvec, int *n, MPI_Datatype *type);
void mergelist(int *merge, int *a, int *b, int n);
int main(void)
{
int i, ilist;
// local sorted list
int mysortedlist[NUMLIST][N];
// global sorted list
int sortedlist[NUMLIST][N];
MPI_Comm comm;
MPI_Datatype MPI_LIST;
MPI_Op MPI_MERGELIST;
int size, rank;
comm = MPI_COMM_WORLD;
MPI_Init(NULL, NULL);
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
// Define datatype appropriate for a single array of N integers
MPI_Type_contiguous(N, MPI_INT, &MPI_LIST);
MPI_Type_commit(&MPI_LIST);
// Register new reduction operation to merge two sorted lists
MPI_Op_create(mergesortlist, 1, &MPI_MERGELIST);
// Generate sorted lists on each rank
for (i=0; i < N; i++)
{
for (ilist=0; ilist < NUMLIST; ilist++)
{
mysortedlist[ilist][i] = rank+size*(N-i-1) + 100*ilist;
sortedlist[ilist][i] = -1;
}
}
for (i=0; i < N; i++)
{
printf("rank %d, mysortedlist[%d] =", rank, i);
for (ilist=0; ilist < NUMLIST; ilist++)
{
printf(" %3d", mysortedlist[ilist][i]);
}
printf("\n");
}
printf("\n");
// Perform reduction to rank 0
MPI_Reduce(mysortedlist, sortedlist, NUMLIST, MPI_LIST, MPI_MERGELIST,
0, comm);
if (rank == 0)
{
for (i=0; i < N; i++)
{
printf("rank %d, sortedlist[%d] =", rank, i);
for (ilist=0; ilist < NUMLIST; ilist++)
{
printf(" %3d", sortedlist[ilist][i]);
}
printf("\n");
}
printf("\n");
}
MPI_Finalize();
return 0;
}
void mergesortlist(void *vinvec, void *vinoutvec, int *n, MPI_Datatype *type)
{
MPI_Aint lb, listextent, intextent;
int i, ilist;
int nvec, nlist;
int *invec = (int *) vinvec;
int *inoutvec = (int *) vinoutvec;
// the count is the number of individual lists
nlist = *n;
// Infer length of each list from the extents
// Should really check "type" is valid, i.e. a contiguous block of ints
MPI_Type_get_extent(MPI_INT, &lb, &intextent);
MPI_Type_get_extent(*type, &lb, &listextent);
nvec = listextent/intextent;
// Need a temporary as "mergelist" does not work in-place
int *mergevec = (int *) malloc(nvec*sizeof(int));
// Merge each of the "nlist" lists in turn
for (ilist=0; ilist < nlist; ilist++)
{
mergelist(mergevec, &invec[ilist*nvec], &inoutvec[ilist*nvec], nvec);
for (i=0; i < nvec; i++)
{
inoutvec[ilist*nvec+i] = mergevec[i];
}
}
free(mergevec);
}
void mergelist(int *merge, int *a, int *b, int n)
{
int i, ia, ib;
ia = 0;
ib = 0;
for (i=0; i < n; i++)
{
if (a[ia] > b[ib])
{
merge[i] = a[ia];
ia++;
}
else
{
merge[i] = b[ib];
ib++;
}
}
}

Algorithm puzzle: minimum cost for allow all persons standing on a line to communicate with each other

I have a algorithm design puzzle that I could not solve.
The puzzle is formulated like this: There are N persons standing on a number line, each of them maybe standing on any integer number on that line. Multiple persons may stand on the same number. For any two persons to be able to communicate with each other, the distance between them should be less than K. The goal is to move them so that each pair of two persons can communicate each other (possibly via other people). In other words, we need to move them so that the distance between any neighboring two persons is smaller than K.
Question: What is the minimum number of total moves? It feels like this falls into greedy algorithm family or dynamic programming. Any hints are appreciated!
We can do the following in O(n):
Calculate the cost of moving all people to the right of person i towards person i at an acceptable distance:
costRight(A[i]) = costRight(A[i+1]) + (A[i+1] - A[i] - k + 1) * count of people to the right
K = 3; A = { 0, 3, 11, 17, 21}
costRight = {32, 28, 10, 2, 0}
Calculate the cost of moving all people to the left of person i towards person i at an acceptable distance:
costLeft(A[i]) = costLeft(A[i-1]) + (A[i] - A[i-1] - k + 1) * count of people to the left
K = 3; A = { 0, 3, 11, 17, 21}
costLeft = { 0, 1, 13, 25, 33}
costRight = {32, 28, 10, 2, 0}
Now that we have cost from both directions we can do this in O(n):
minCost = min(costRight + costLeft) for all A[i]
minCost = min(32 + 0, 28 + 1, 13 + 10, 25 + 2, 33 + 0) = 23
But sometimes that's no enough:
K = 3; A = { 0, 0, 1, 8, 8}
carry: -2 -4 3
costLeft = { 0, 0, 0, 11, 11}
carry: -3 5 -2
costRight = { 8, 8, 8, 0, 0}
The optimum is neither 11 nor 8. Test the current best by moving towards the greatest saving:
move 1 to 2, cost = 1
K = 3; A = { 0, 0, 2, 8, 8}
carry: -2 -2 -10
costLeft = { 0, 0, 0, 10, 10}
carry: -2 -2
costRight = { 6, 6, 6, 0, 0}
minCost = 1 + min(0 + 6, 0 + 6, 0 + 6, 10 + 0, 10 + 0) = 1 + 6 = 7
Not quite sure how to formularize this efficiently.
Here is a greedy algorithm written in Java, but I don't know if it gives the optimal solution in every case. Also it is more a proof of concept, there is some room for optimizations.
It is based on the fact that two neighbouring persons must not be more than K apart, the next neighbour must not be more than 2K away and so on. In each step we move the person that "violates these constraints most". The details of this calculation are in method calcForce.
package so;
import java.util.Arrays;
public class Main {
public static void main(String args[]) {
int[] position = new int[] {0, 0, 5, 11, 17, 23};
int k = 5;
solve(position, k);
}
private static void solve(int[] position, int k) {
if (!sorted(position)) {
throw new IllegalArgumentException("positions must be sorted");
}
int[] force = new int[position.length];
int steps = 0;
while (calcForce(position, k, force)) {
int mp = -1;
int mv = -1;
for (int i = 0; i < force.length; i++) {
if (mv < Math.abs(force[i])) {
mv = Math.abs(force[i]);
mp = i;
}
}
System.out.printf("move %d to the %s%n", mp, force[mp] > 0 ? "right" : "left");
if (force[mp] > 0) {
position[mp]++;
} else {
position[mp]--;
}
steps++;
}
System.out.printf("total: %d steps%n", steps);
}
private static boolean calcForce(int[] position, int k, int[] force) {
boolean commProblem = false;
Arrays.fill(force, 0);
for (int i = 0; i < position.length - 1; i++) {
for (int j = i + 1; j < position.length; j++) {
int f = position[j] - position[i] - (j - i) * k;
if (f > 0) {
force[i] += f;
force[j] -= f;
commProblem = true;
}
}
}
return commProblem;
}
private static boolean sorted(int[] position) {
for (int i = 0; i < position.length - 1; i++) {
if (position[i] > position[i+1]) {
return false;
}
}
return true;
}
}

Adressing for-loops in big O notation

I have the Following Loops:
n = 2^M
for(int i = n; i > 0; i--){
for(int j = 1; j < n ; j*=2){
for(int k = 0 ; k < j ; k++){
}
}
}
Im trying to understnad how to approach this, i have tried to break it down to single steps but with no luck. if someone can explane me how to look at this and what to look for in this type of question.
why don't you just instrument it, to see what happens?
for example
public static void main(String[] args) {
int[] bb = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //try other values here like 1,10,100
for (int b : bb) {
int n = (int) Math.pow(2, b);
int l1 = 0;
int l2 = 0;
int l3 = 0;
for (int i = n; i > 0; i--) {
l1++;
for (int j = 1; j < n; j *= 2) {
l2++;
for (int k = 0; k < j; k++) {
l3++;
}
}
}
System.out.println(b+" "+l1+" "+l2+" "+l3);
}
}
you'd have something like
1 2 2 2
2 4 8 12
3 8 24 56
4 16 64 240
5 32 160 992
6 64 384 4032
7 128 896 16256
8 256 2048 65280
9 512 4608 261632
10 1024 10240 1047552
what does it seem?

square puzzle solution

Question: given an integer number n, print the numbers from 1 up to n2 like this:
n = 4
result is:
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
How do you solve it (apart from the solution provided in the link below)?
http://www.programmersheaven.com/mb/CandCPP/81986/81986/problem-in-making-ap-c++-program/?S=B20000
I'm looking in another direction. So far, I'm trying to figure out if I could obtain the ordered list of positions I have to fill in.
Here's what Im looking into: is there a way to obtain the "fdisp" so as to solve the problem that way, instead of "walk" in the matrix?
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
n = len(matrix)
# final disposition wrote by hand: how to get it for arbitrary n?
fdisp = [(0,0), (0,1), (0,2), (0,3), (1,3), (2,3), (3,3), (3,2),
(3,1), (3,0), (2,0), (1,0), (1,1), (1,2), (2,2), (2,1)]
for val,i in enumerate(fdisp):
matrix[i[0]][i[1]] = val + 1
def show_matrix(matrix, n):
for i,l in enumerate(matrix):
for j in range(n):
print "%d\t" % matrix[i][j],
print
show_matrix(matrix, n)
Here's a different approach. It relies on spotting that the movements you make cycle between: right, down, left, up, right, .... Further, the number of times you move goes: 3 right, 3 down, 3 left, 2 up, 2 right, 1 down, 1 left. So without further ado, I will code this up in Python.
First, I will use some itertools and some numpy:
from itertools import chain, cycle, imap, izip, repeat
from numpy import array
The directions cycle between: right, down, left, up, right, ...:
directions = cycle(array(v) for v in ((0,1),(1,0),(0,-1),(-1,0)))
(I'm using numpy's arrays here so I can easily add directions together. Tuples don't add nicely.)
Next, the number of times I move counts down from n-1 to 1, repeating each number twice, and the first number three times:
countdown = chain((n-1,), *imap(repeat, range(n-1,0,-1), repeat(2)))
So now my sequence of directions can be created by repeating each successive direction by the paired number in countdown:
dirseq = chain(*imap(repeat, directions, countdown))
To get my sequence of indices, I can just sum this sequence, but (AFAIK) Python does not provide such a method, so let's quickly throw one together:
def sumseq(seq, start=0):
v = start
yield v
for s in seq:
v += s
yield v
Now to generate the original array, I can do the following:
a = array(((0,)*n,)*n) # n-by-n array of zeroes
for i, v in enumerate(sumseq(dirseq, array((0,0)))):
a[v[0], v[1]] = i+1
print a
Which, for n = 4, gives:
[[ 1 2 3 4]
[12 13 14 5]
[11 16 15 6]
[10 9 8 7]]
and, for n = 5, gives:
[[ 1 2 3 4 5]
[16 17 18 19 6]
[15 24 25 20 7]
[14 23 22 21 8]
[13 12 11 10 9]]
This approach can be generalised to rectangular grids; I leave this as an exercise for the reader ;)
Though your example is in python and this is in Java, I think you should be able to follow the logic:
public class SquareTest {
public static void main(String[] args) {
SquareTest squareTest = new SquareTest(4);
System.out.println(squareTest);
}
private int squareSize;
private int[][] numberSquare;
private int currentX;
private int currentY;
private Direction currentDirection;
private enum Direction {
LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP;
};
public SquareTest(int squareSize) {
this.squareSize = squareSize;
numberSquare = new int[squareSize][squareSize];
currentY = 0;
currentX = 0;
currentDirection = Direction.LEFT_TO_RIGHT;
constructSquare();
}
private void constructSquare() {
for (int i = 0; i < squareSize * squareSize; i = i + 1) {
numberSquare[currentY][currentX] = i + 1;
if (Direction.LEFT_TO_RIGHT.equals(currentDirection)) {
travelLeftToRight();
} else if (Direction.RIGHT_TO_LEFT.equals(currentDirection)) {
travelRightToLeft();
} else if (Direction.TOP_TO_BOTTOM.equals(currentDirection)) {
travelTopToBottom();
} else {
travelBottomToTop();
}
}
}
private void travelLeftToRight() {
if (currentX + 1 == squareSize || numberSquare[currentY][currentX + 1] != 0) {
currentY = currentY + 1;
currentDirection = Direction.TOP_TO_BOTTOM;
} else {
currentX = currentX + 1;
}
}
private void travelRightToLeft() {
if (currentX - 1 < 0 || numberSquare[currentY][currentX - 1] != 0) {
currentY = currentY - 1;
currentDirection = Direction.BOTTOM_TO_TOP;
} else {
currentX = currentX - 1;
}
}
private void travelTopToBottom() {
if (currentY + 1 == squareSize || numberSquare[currentY + 1][currentX] != 0) {
currentX = currentX - 1;
currentDirection = Direction.RIGHT_TO_LEFT;
} else {
currentY = currentY + 1;
}
}
private void travelBottomToTop() {
if (currentY - 1 < 0 || numberSquare[currentY - 1][currentX] != 0) {
currentX = currentX + 1;
currentDirection = Direction.LEFT_TO_RIGHT;
} else {
currentY = currentY - 1;
}
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < squareSize; i = i + 1) {
for (int j = 0; j < squareSize; j = j + 1) {
builder.append(numberSquare[i][j]);
builder.append(" ");
}
builder.append("\n");
}
return builder.toString();
}
}
Another way to do it, this time in C#:
int number = 9;
var position = new { x = -1, y = 0 };
var directions = new [] {
new { x = 1, y = 0 },
new { x = 0, y = 1 },
new { x = -1, y = 0 },
new { x = 0, y = -1 }
};
var sequence = (
from n in Enumerable.Range(1, number)
from o in Enumerable.Repeat(n, n != number ? 2 : 1)
select o
).Reverse().ToList();
var result = new int[number,number];
for (int i = 0, current = 1; i < sequence.Count; i++)
{
var direction = directions[i % directions.Length];
for (int j = 0; j < sequence[i]; j++, current++)
{
position = new {
x = position.x + direction.x,
y = position.y + direction.y
};
result[position.y, position.x] = current;
}
}
I found a way. Now I've to improve it a bit, especially I've to find a cleaner way to build "fdisp".
n = 5
dim = n
pos = (0, -1)
fdisp = []
squares = n % 2 == 0 and n / 2 or n / 2 + 1
for _ in range(squares):
pos = (pos[0], pos[1] + 1)
fdisp.append(pos)
fdisp += [(pos[0],pos[1]+i) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0]+i,pos[1]) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0],pos[1]-i) for i in range(1, dim)]
pos = fdisp[-1]
fdisp += [(pos[0]-i,pos[1]) for i in range(1, dim - 1)]
pos = fdisp[-1]
dim = dim - 2
matrix = [[0] * n for i in range(n)]
for val,i in enumerate(fdisp):
matrix[i[0]][i[1]] = val + 1
def show_matrix(matrix, n):
for i,l in enumerate(matrix):
for j in range(n):
print "%d\t" % matrix[i][j],
print
show_matrix(matrix, n)
I have solved your problem using C++. I don't know if it will be helpful for you. But posting it. If it works for you it will be a pleasure.
Here is the Code:
#include<iostream>
#include<string.h>
using namespace std;
bool valid(int n,int r,int c)
{
if(r>=1 && r<=n && c>=1 && c<=n)
return true;
return false;
}
int main()
{
pair<int,int>d1,d2,d3,d4,temp;
d1 = make_pair(0,1);
d2 = make_pair(1,0);
d3 = make_pair(0,-1);
d4 = make_pair(-1,0);
/**********************direction******************************/
int n, i, j, counter=1, newR = 1, newC = 0, direction = 4;
bool changeDir=true;
/**************************variables*************************/
cin>>n;
int arr[n+1][n+1];
int visited[n+1][n+1];
/*************************arrays********************************/
memset(visited,0,sizeof(visited));
memset(arr,0,sizeof(arr));
/***************initializing the array**************************/
while(counter<=n*n)
{
if(direction==1 && changeDir)
{
temp = make_pair(d2.first,d2.second);
direction=2;
changeDir=false;
}
else if(direction==2&& changeDir)
{
temp = make_pair(d3.first,d3.second);
direction=3;
changeDir=false;
}
else if(direction==3&& changeDir)
{
temp = make_pair(d4.first,d4.second);
direction=4;
changeDir=false;
}
else if(direction==4&& changeDir)
{
temp = make_pair(d1.first,d1.second);
direction=1;
changeDir=false;
}
while(counter<=(n*n) && !changeDir)
{
newR =newR+temp.first;
newC=newC+temp.second;
if(valid(n,newR,newC) && !visited[newR][newC])
{
arr[newR][newC]=counter;
visited[newR][newC]=1;
counter++;
}
else
{
newR-=temp.first;
newC-=temp.second;
changeDir=true;
break;
}
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(arr[i][j]<10)
cout<<0;
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
Here is the output where N=5:
01 02 03 04 05
16 17 18 19 06
15 24 25 20 07
14 23 22 21 08
13 12 11 10 09
Thank you.

Resources