Wzór na prawoskrętne stawianie kropki

0

Witam

Jak można zaprogramować wzór który będzie stawiał kropke na każdym polu na planszy po kolei, ale tak żeby te kropki układały się w kształt prawoskrętnej spirali zaczynając od pola 00 i docierając na końcu do najbardziej środkowego pola?

board = []

for x in range(11):
    for y in range(10):
        board.append(str(x)+", "+str(y))

itd.jpg

0

Panie umiesz pan kwadrat narysować w prawą stronę?
Potem min x, max x i min y, max y zmniejszony o 1, i znów kwadrat.
Na końcu dla nieparzystych zostaje 9 na końcu, czyli jeden klocek, a dla parzystych kwadrat.

0
#Wyświetl czy działa jak powinno
def podejrzyj(tab):
    for i in range(len(tab)):
        print(tab[i])
    print ("-----")

#Generujemy tablice dwuwymiarową
max_x = 9; max_y = 10
board = [[ "I" for i in range(max_x)] for i in range(max_y)]
x = 0; y = 0;
while max_x>x or max_y>y:
#Wypełniamy górny wiersz
    for i in range(x, max_x):
        board[y][i] = "W"
    podejrzyj(board)
#Wypełniamy prawą kolumnę
    for i in range(y, max_y):
        board[i][max_x-1] = "W"
    podejrzyj(board)
#Wypełniamy dolny wiersz
    for i in range(max_x-1, x-1, -1):
        board[max_y-1][i] = "W"
    podejrzyj(board)
#Wypełniamy lewą kolumnę
    for i in range(max_y-1, y-1, -1):
        board[i][x] = "W"
    podejrzyj(board)
#"Przesuwamy" zmienne aby wypełnić kolejny, wewnętrzny obrys.
    y += 1; x += 1; max_x -= 1; max_y -= 1;

podejrzyj(board)
#Możesz jeszcze pokombinować w ten sposób zamiast pętli for:
#board[y][x:max_x:1] = [1] * (max_y-y)

To bardzo prosty sposób, jednak wadą jest brak optymalności. Pobaw się z optymalizacją, osobiście polecam indeksowanie i pracę na wycinkach list.

0

@Guaz a dałoby tak się zrobić żeby po każdym powtórzeniu stawiana była tylko 1 kropka a nie cały ich rząd?

0

Tutaj jest stawiana pojedyńczo, wystarczy że sobie podejrzysz po każdej zamianie a nie po zmianie całego rzędu.
Nie byłoby pojedyńczo gdybyś wykorzystał sposób z indeksowaniem i pracę na wycinkach listy.

0

takie coś (swoją drogą fajna zagadka, sam z chęcią ją rozgryzłem):

def emit_point():
    print "x", x, "y", y

while width > 0 and height > 0:
    direction = 1
    while direction >= -1:
        for i in range(width - 1): 
            emit_point()
            x += direction
        for i in range(height - 1):
            emit_point()
            y += direction
        direction -= 2
    x += 1
    y += 1
    width -= 2
    height -= 2

dla kwadratu 4x4
najpierw (w pierwszym for in) są rysowane kropki o numerach 1, 2, 3 (mam na myśli obrazek poniżej),
screenshot-20170517001553.png
potem w drugim for in są rysowane kropki o numerach 4, 5, 6,
potem następuje zmiana direction (z 1 na -1)
więc jest wrócenie, najpierw w lewo (w pierwszym for in), potem w górę(w drugim for in) aż do punktu 12
po iteracji "kursor" wraca do punktu początkowego (punkt na rysunku 1, czyli współrzędne x,y: 0,0 ), więc jest korygowana pozycja x i y:

x += 1
y += 1

oraz zmniejszana szerokość i wysokość o 2 za każdym razem

0

@LukeJL:
Jedyne co program ma do zarzucenia, że kropka jest stawiana na polu 7, 1, 15 i 13 dwukrotnie. (Mojemu w sumie też można to zarzucić :D. Nie podmieniłem max_x - 1 na max_x -2 itd. przy drugiej parze pętli.)
Zlicz sobie ile kropek stawia program, a ile powinno być na danej siatce :).
Bardzo trywialna oczywiście kalkulacja i załatwia to:

  • zmniejszenie height i width pod koniec pętli while tak jak zmienia się direction
  • modyfikacja x oraz y o direction (-1)pod koniec pętli żeby przeskoczyć do następnego klocka a nie pozostawać w tym samym miejscu. Wtedy kalkulacja nam się nie zgodzi po drugim zatoczeniu pętli, więc poza pętlą x+=1; y+=1 muszą pozostać :).

Smaczki optymalizacyjne (tak w ramach mojego treningu, może coś nowego pokażę albo ktoś mi wskaże gdzieś głupotę gdybym taką palnął.)

  • Pętla while direction >= 1 wykona się i tak zawsze dwukrotnie, więc zamiast sprawdzać warunek większe lub równe (dwa sprawdzenia, a to drugie szczególnie wolniejsze) oraz odejmować direction optymalniejsze będzie "for direction in range(-1, 2, 2)". Ewentualnie zastąpienie tego wyrażeniem 'while direction > -2'. Jeśli to tylko możliwe, polecam zastępować >= oraz <= wartością porównawczą o 1 większą/mniejszą i porównanie większe/mniejsze.
  • Pierwszy while dobrze ujęty, and zamiast or załatwia sprawę o wiele szybciej, na przykład przy specyficznych prostokątach, a jak podkreślił to pytający w programie, kwadrat może nie być :).
0

@Guaz:

Jedyne co program ma do zarzucenia, że kropka jest stawiana na polu 7, 1, 15 i 13 dwukrotnie. (Mojemu w sumie też można to zarzucić :D

nie wiem o czym mówisz, mój stawia dokładnie 16 kropek dla 4x4 i każdą kropkę po raz (i ogólnie tyle ile trzeba przy tych wartościach width i height, które sprawdzałem - sprawdzałem kilka - co oczywiście nie jest gwarancją poprawności algorytmu, tym niemniej na tych kilku co sprawdzałem działało ok). Odpal program, to zobaczysz :)
właśnie, początek zjadłem, tam powinno być jeszcze na początku inicjalizacja zmiennych:

width = 4
height = 4

x = 0
y = 0

def emit_point():
    global x, y 
    print "x", x, "y", y

1 użytkowników online, w tym zalogowanych: 0, gości: 1