Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)
like image 845
gmoh Avatar asked Jul 23 '09 20:07

gmoh


People also ask

How do you solve the 3x3 magic square puzzle?

Add the unused numbers to the open boxes in the magic square so that the rows, columns, and diagonals add up to 15. In the first row: 6 + 8 = 14, the missing number to total 15 is 1. In the third row: 2 + 4 = 6, the missing number to total 15 is 9. In the first column: 6+2 = 8, the missing number to total 15 is 7.

Is Square 1 hard?

One of the most frequently asked questions by beginners about this event is "Is it difficult to solve a square-1? ". In short, no! One of the prerequisites for solving a square -1 is knowing how to solve a 3x3 speedcube and to have a general understanding of notations and moves.


2 Answers

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 ;)

like image 198
Alice Purcell Avatar answered Oct 05 '22 23:10

Alice Purcell


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();
}
}
like image 32
Peter Avatar answered Oct 06 '22 01:10

Peter