квадратное решение для загадки

4 ответа

Другой способ сделать это, на этот раз на 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;
    }
}
2
ответ дан 13 December 2019 в 19:32
поделиться

Я нашел способ. Теперь мне нужно немного улучшить его, особенно я должен найти более чистый способ создания "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)
1
ответ дан 13 December 2019 в 19:32
поделиться

Хотя ваш пример написан на Python, а это на Java, я думаю, вы должны уметь следовать логике:

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();
}
}
2
ответ дан 13 December 2019 в 19:32
поделиться

Вот другой подход. Он основан на определении того, что движения, которые вы совершаете, циклически меняются между: вправо, вниз, влево, вверх, вправо, .... Кроме того, количество ваших перемещений идет: 3 вправо, 3 вниз, 3 влево, 2 вверх, 2 вправо , 1 вниз, 1 слева. Итак, без лишних слов, я запрограммирую это на Python.

Во-первых, я воспользуюсь некоторыми itertools и некоторыми numpy:

from itertools import chain, cycle, imap, izip, repeat
from numpy import array

Циклы направлений: вправо, вниз, влево, вверх, вправо, ...:

directions = cycle(array(v) for v in ((0,1),(1,0),(0,-1),(-1,0)))

(Здесь я использую массивы numpy, чтобы я мог легко складывать направления. Кортежи складываются плохо.)

Далее, количество раз, когда я перемещаюсь, отсчитывается от n-1 до 1, каждое число повторяется дважды , и первое число трижды:

countdown = chain((n-1,), *imap(repeat, range(n-1,0,-1), repeat(2)))

Итак, теперь моя последовательность направлений может быть создана путем повторения каждого последующего направления по парному числу в обратном отсчете:

dirseq = chain(*imap(repeat, directions, countdown))

Чтобы получить мою последовательность индексов, Я могу просто суммировать эту последовательность, но (AFAIK) Python не предоставляет такой метод, поэтому давайте быстро объединим его:

def sumseq(seq, start=0):
  v = start
  yield v
  for s in seq:
    v += s
    yield v

Теперь, чтобы сгенерировать исходный массив, я могу сделать следующее:

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

Что для n = 4 дает:

[[ 1  2  3  4]
 [12 13 14  5]
 [11 16 15  6]
 [10  9  8  7]]

, а для n = 5:

[[ 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]]

Этот подход может быть обобщен на прямоугольные сетки; Я оставляю это в качестве упражнения для читателя;)

5
ответ дан 13 December 2019 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: