Seorang teman membutuhkan sebuah algoritma yang akan membiarkannya mengulangi elemen-elemen matriks NxM (N dan M aneh). Saya datang dengan solusi, tetapi saya ingin melihat apakah rekan-rekan SO saya dapat menemukan solusi yang lebih baik.
Saya memposting solusi saya sebagai jawaban untuk pertanyaan ini.
Contoh Output:
Untuk matriks 3x3, output harus:
(0, 0) (1, 0) (1, 1) (0, 1) (-1, 1) (-1, 0) (-1, -1) (0, -1) (0, -1) (1, -1 )
Selanjutnya, algoritma harus mendukung matriks non-square, jadi misalnya untuk matriks 5x3, output harus:
(0, 0) (1, 0) (1, 1) (0, 1) (-1, 1) (-1, 0) (-1, -1) (0, -1) (0, -1) (1, -1 ) (2, -1) (2, 0) (2, 1) (-2, 1) (-2, 0) (-2, -1)
Jawaban:
Inilah solusi saya (dengan Python):
sumber
C ++ siapa saja? Terjemahan cepat dari python, diposting untuk kelengkapan
sumber
Ada banyak solusi yang diusulkan untuk masalah ini yang ditulis dalam berbagai bahasa pemrograman namun mereka semua tampaknya berasal dari pendekatan yang berbelit-belit. Saya akan mempertimbangkan masalah yang lebih umum dari komputasi spiral yang dapat diekspresikan secara ringkas menggunakan induksi.
Kasing dasar: Mulai dari (0, 0), bergerak maju 1 kotak, belok kiri, maju 1 kotak, belok kiri. Langkah induktif: Bergerak maju n + 1 kotak, belok kiri, bergerak maju n + 1 kotak, belok kiri.
Keanggunan matematis untuk mengungkapkan masalah ini sangat menyarankan harus ada algoritma sederhana untuk menghitung solusinya. Dengan mengingat abstraksi, saya memilih untuk tidak mengimplementasikan algoritma dalam bahasa pemrograman tertentu tetapi lebih sebagai pseudo-code.
Pertama saya akan mempertimbangkan algoritma untuk menghitung hanya 2 iterasi spiral menggunakan 4 pasang while loop. Struktur masing-masing pasangan serupa, namun berbeda dalam dirinya sendiri. Ini mungkin tampak gila pada awalnya (beberapa loop hanya dieksekusi sekali) tetapi langkah demi langkah saya akan melakukan transformasi sampai kita tiba di 4 pasang loop yang identik dan karenanya dapat diganti dengan satu pasang ditempatkan di dalam loop lain. Ini akan memberi kami solusi umum komputasi dan iterasi tanpa menggunakan persyaratan apa pun.
Transformasi pertama yang akan kita buat adalah pengenalan variabel baru d, untuk arah, yang memiliki nilai +1 atau -1. Arah beralih setelah setiap pasangan loop. Karena kita mengetahui nilai d pada semua titik, kita dapat mengalikan setiap sisi dari setiap ketidaksetaraan dengan itu, menyesuaikan arah ketidaksetaraan sesuai dan menyederhanakan setiap perkalian dari d dengan konstanta ke konstanta lain. Ini meninggalkan kita dengan yang berikut ini.
Sekarang kita perhatikan bahwa x * d dan RHS adalah bilangan bulat sehingga kita dapat mengurangi nilai riil antara 0 dan 1 dari RHS tanpa memengaruhi hasil ketidaksetaraan. Kami memilih untuk mengurangi 0,5 dari ketidaksetaraan setiap pasangan sementara loop untuk membangun lebih banyak pola.
Kita sekarang dapat memperkenalkan variabel lain m untuk jumlah langkah yang kita ambil pada setiap pasangan while loop.
Akhirnya, kita melihat bahwa struktur setiap pasangan while loop identik dan dapat direduksi menjadi satu loop yang ditempatkan di dalam loop lain. Juga, untuk menghindari penggunaan bilangan bernilai nyata, saya telah mengalikan nilai awal m; nilai m bertambah dengan; dan kedua sisi masing-masing ketidaksetaraan oleh 2.
Ini mengarah ke solusi yang ditunjukkan di awal jawaban ini.
sumber
Inilah solusi O (1) untuk menemukan posisi dalam spiral kuadrat: Fiddle
sumber
if (n === 0) return [0, 0, r]; --n;
Lihat Fiddle: jsfiddle.net/Wishmesh/nwd9gt1s/2Saya suka generator python.
Pengujian dengan:
Anda mendapatkan:
sumber
Upaya "spiral golf Code" Java, berdasarkan pada varian C ++.
sumber
Berikut adalah solusi C ++ yang menunjukkan bahwa Anda dapat menghitung koordinat berikutnya (x, y) secara langsung dan mudah dari yang sebelumnya - tidak perlu untuk melacak arah, jari-jari saat ini, atau yang lainnya:
Jika semua yang Anda coba lakukan adalah menghasilkan titik N pertama di spiral (tanpa kendala masalah asli untuk menutupi wilayah N x M), kode menjadi sangat sederhana:
Triknya adalah Anda dapat membandingkan x dan y untuk menentukan di sisi mana Anda berada, dan itu memberi tahu Anda arah bergerak yang mana.
sumber
TDD, di Jawa.
SpiralTest.java:
Spiral.java:
sumber
Ini solusi saya (dalam Ruby)
sumber
Haskell, pilihlah:
sumber
Ini dalam C.
Saya kebetulan memilih nama variabel yang buruk. Dalam nama T == atas, L == kiri, B == bawah, R == kanan. Jadi, tli di kiri atas saya dan brj di kanan bawah j.
sumber
Saya memiliki pustaka sumber terbuka, pixelcan , yaitu pustaka python yang menyediakan fungsi untuk memindai piksel pada kisi dalam berbagai pola spasial. Pola spasial yang dimasukkan adalah lingkaran, cincin, kisi-kisi, ular, dan jalan acak. Ada juga berbagai transformasi (misalnya, klip, tukar, putar, terjemahkan). Masalah OP asli dapat diselesaikan sebagai berikut
yang menghasilkan poin
Generator perpustakaan dan transformasi dapat dirantai untuk mengubah titik dalam berbagai urutan dan pola spasial.
sumber
Berikut adalah solusi dalam Python 3 untuk mencetak bilangan bulat berturut-turut dalam spiral searah jarum jam dan berlawanan arah jarum jam.
Penjelasan
Sebuah spiral terbuat dari kotak konsentris, misalnya persegi 5x5 dengan rotasi searah jarum jam terlihat seperti ini:
(
>>>>>
berarti "jalan 5 kali benar" atau naikkan indeks kolom 5 kali,v
berarti turun atau naikkan indeks baris, dll.)Semua kotak sama dengan ukurannya, saya memutar kotak konsentris.
Untuk setiap kotak kode memiliki empat loop (satu untuk setiap sisi), dalam setiap loop kami menambah atau mengurangi kolom atau indeks baris. Jika
i
adalah indeks baris dan indeksj
kolom maka kotak 5x5 dapat dibangun dengan: - bertambahj
dari 0 menjadi 4 (5 kali) - bertambahi
dari 1 menjadi 4 (4 kali) - penurunanj
dari 3 menjadi 0 (4 kali) - pengurangani
dari 3 hingga 1 (3 kali)Untuk kotak berikutnya (3x3 dan 1x1) kami melakukan hal yang sama tetapi menggeser indeks awal dan akhir dengan tepat. Saya menggunakan indeks
k
untuk setiap kotak konsentris, ada n // 2 + 1 kotak konsentris.Akhirnya, beberapa matematika untuk pencetakan cantik.
Untuk mencetak indeks:
sumber
Inilah c #, linq'ish.
Contoh pertama pertanyaan (3x3) adalah:
Contoh kedua pertanyaan (5x3) adalah:
sumber
Ini adalah versi yang sedikit berbeda - mencoba menggunakan
recursion
daniterators
dalam LUA. Pada setiap langkah program turun lebih jauh ke dalam matriks dan loop. Saya juga menambahkan bendera ekstra untuk spiralclockwise
atauanticlockwise
. Output dimulai dari sudut kanan bawah dan loop secara rekursif menuju pusat.sumber
// Implementasi PHP
sumber
Berikut ini adalah solusi berulang JavaScript (ES6) untuk masalah ini:
Berikut cara menggunakannya:
spiralMatrix(0, 0, 1, 100);
Ini akan membuat spiral luar, mulai dari koordinat (x = 0, y = 0) dengan langkah 1 dan jumlah total item sama dengan 100. Implementasi selalu memulai gerakan dalam urutan berikut - naik, kanan, bawah, kiri.
Harap perhatikan bahwa implementasi ini membuat matriks persegi.
sumber
Inilah jawaban dalam Julia: pendekatan saya adalah menetapkan titik-titik dalam kotak konsentris ('spiral') di sekitar titik asal
(0,0)
, di mana setiap kotak memiliki panjang sisim = 2n + 1
, untuk menghasilkan kamus berurutan dengan nomor lokasi (mulai dari 1 untuk asal) sebagai kunci dan koordinat yang sesuai sebagai nilai.Karena lokasi maksimum per spiral adalah pada
(n,-n)
, sisa poin dapat ditemukan dengan hanya bekerja mundur dari titik ini, yaitu dari sudut kanan bawah denganm-1
unit, kemudian mengulangi untuk 3 segmenm-1
unit yang tegak lurus .Proses ini ditulis dalam urutan terbalik di bawah, sesuai dengan bagaimana proses spiral daripada proses penghitungan terbalik ini, yaitu
ra
segmen [naik kanan] dikurangi dengan3(m+1)
, kemudianla
[naik kiri] oleh2(m+1)
, dan seterusnya - mudah-mudahan ini cukup jelas. .Jadi untuk contoh pertama Anda, menyambungkan
m = 3
ke persamaan untuk menemukan n memberin = (5-1)/2 = 2
, danwalk(2)
memberikan kamus lokasi untuk koordinat, yang dapat Anda ubah menjadi hanya array koordinat dengan mengakses bidang kamusvals
:Perhatikan bahwa untuk beberapa fungsi [misalnya
norm
], lebih baik membiarkan koordinat dalam array daripadaTuple{Int,Int}
, tetapi di sini saya mengubahnya menjadi tupel—(x,y)
—sebagaimana diminta, menggunakan daftar pemahaman.Konteks untuk "mendukung" matriks non-kuadrat tidak ditentukan (perhatikan bahwa solusi ini masih menghitung nilai off-grid), tetapi jika Anda ingin memfilter hanya rentang
x
dengany
(di sini untukx=5
,y=3
) setelah menghitung spiral penuh makaintersect
matriks ini terhadap nilai-nilai dariwalk
.sumber
Pertanyaan Anda terlihat seperti pertanyaan yang disebut memori spiral. Dalam masalah itu, setiap kotak pada grid dialokasikan dalam pola spiral mulai dari nomor 1 yang terletak di titik asal. Dan kemudian menghitung sambil berputar keluar. Sebagai contoh:
Solusi saya untuk menghitung koordinat setiap angka mengikuti pola spiral ini diposting di bawah ini:
sumber
Ini didasarkan pada solusi Anda sendiri, tetapi kita bisa lebih pintar menemukan sudut. Ini membuatnya lebih mudah untuk melihat bagaimana Anda bisa melewati area di luar jika M dan N sangat berbeda.
dan solusi berbasis generator yang lebih baik daripada O (maks (n, m) ^ 2), itu adalah O (nm + abs (nm) ^ 2) karena melompati seluruh strip jika mereka bukan bagian dari solusi.
sumber
sumber
Ini adalah solusi saya yang sangat buruk, dibuat dari pengetahuan minimum Jawa. Di sini saya harus menempatkan unit pada bidang dalam spiral. Unit tidak dapat ditempatkan di atas unit lain atau di gunung atau di laut.
Agar jelas. Ini bukan solusi yang baik. Ini adalah solusi yang sangat buruk ditambahkan untuk kesenangan orang lain untuk menertawakan betapa buruknya hal itu dapat dilakukan
Cudos kepada siapa saja yang benar-benar dapat membaca ini
Pertanyaan bonus: Berapa waktu berjalan dari "algoritma" ini? : P
sumber
Solusi untuk AutoIt
sumber
Saya baru-baru ini memiliki tantangan serupa di mana saya harus membuat array 2D dan menggunakan algoritma matriks spiral untuk mengurutkan dan mencetak hasilnya. Kode C # ini akan bekerja dengan array N, N 2D. Ini sangat jelas untuk kejelasan dan kemungkinan dapat diperhitungkan ulang sesuai dengan kebutuhan Anda.
sumber
Saya membuat ini dengan seorang teman yang menyesuaikan rasio aspek spiral ke kanvas pada Javascript. Solusi terbaik yang saya dapatkan untuk piksel evolusi gambar demi piksel, mengisi seluruh gambar.
Semoga ini bisa membantu seseorang.
Anda dapat melihatnya bekerja di http://jsfiddle.net/hitbyatruck/c4Kd6/ . Pastikan untuk mengubah lebar dan tinggi kanvas pada vars javascript dan atribut pada HTML.
sumber
Hanya untuk bersenang-senang di Javascript:
sumber
Versi C #, menangani ukuran non-persegi juga.
sumber
Saya membagikan kode ini yang saya rancang untuk tujuan yang berbeda; ini adalah tentang menemukan nomor Kolom "X", dan nomor baris "Y" elemen array @ indeks spiral "indeks". Fungsi ini mengambil lebar "w" dan tinggi "h" dari matriks, dan "indeks" yang diperlukan. Tentu saja, fungsi ini dapat digunakan untuk menghasilkan output yang dibutuhkan sama. Saya pikir ini adalah metode tercepat yang mungkin (karena melompati sel daripada memindai mereka).
sumber
Python looping kode spiral searah jarum jam menggunakan Can Berk Güder menjawab .
sumber
Solusi terbaik Davidont di VB.Net
sumber