主頁 > 企業開發 > 從中心以螺旋形式填充矩陣

從中心以螺旋形式填充矩陣

2021-12-29 04:54:51 企業開發

我最近為我正在從事的一個專案完成了一個演算法。

簡而言之,我的專案的一部分需要填充一個矩陣,如何做到這一點的要求是:

- Fill the matrix in form of spiral, from the center.
- The size of the matrix must be dynamic, so the spiral can be large or small.
- Every two times a cell of the matrix is filled, //DO STUFF must be executed.

最后,我制作的代碼有效,這是我最大的努力,我無法對其進行更多優化,不得不使用這么多ifs讓我有點困擾,我想知道是否有人可以看看我的代碼,看看是否可以進一步優化它或一些建設性的評論(它運行良好,但如果它更快會更好,因為該演算法將在我的專案中執行多次)。也讓其他人可以使用它!

#include <stdio.h>

typedef unsigned short u16_t;
const u16_t size = 7; //<-- CHANGE HERE!!! just odd numbers and bigger than 3
const u16_t maxTimes = 2;
u16_t array_cont[size][size] = { 0 };

u16_t counter = 3, curr = 0;
u16_t endColumn = (size - 1) / 2, endRow = endColumn;
u16_t startColumn = endColumn   1, startRow = endColumn   1;
u16_t posLoop = 2, buffer = startColumn, i = 0;

void fillArray() {
    if (curr < maxTimes) {
        if (posLoop == 0) { //Top
            for (i = buffer; i <= startColumn && curr < maxTimes; i  , curr  )
                array_cont[endRow][i] = counter  ;
            if (curr == maxTimes) {
                if (i <= startColumn) {
                    buffer = i;
                } else {
                    buffer = endRow;
                    startColumn  ;
                    posLoop  ;
                }
            } else {
                buffer = endRow;
                startColumn  ;
                posLoop  ;
                fillArray();
            }
        } else if (posLoop == 1) { //Right
            for (i = buffer; i <= startRow && curr < maxTimes; i  , curr  )
                array_cont[i][startColumn] = counter  ;
            if (curr == maxTimes) {
                if (i <= startRow) {
                    buffer = i;
                } else {
                    buffer = startColumn;
                    startRow  ;
                    posLoop  ;
                }
            } else {
                buffer = startColumn;
                startRow  ;
                posLoop  ;
                fillArray();
            }
        } else if (posLoop == 2) { //Bottom
            for (i = buffer; i >= endColumn && curr < maxTimes; i--, curr  )
                array_cont[startRow][i] = counter  ;
            if (curr == maxTimes) {
                if (i >= endColumn) {
                    buffer = i;
                } else {
                    buffer = startRow;
                    endColumn--;
                    posLoop  ;
                }
            } else {
                buffer = startRow;
                endColumn--;
                posLoop  ;
                fillArray();
            }
        } else if (posLoop == 3) { //Left
            for (i = buffer; i >= endRow && curr < maxTimes; i--, curr  )
                array_cont[i][endColumn] = counter  ;
            if (curr == maxTimes) {
                if (i >= endRow) {
                    buffer = i;
                } else {
                    buffer = endColumn;
                    endRow--;
                    posLoop = 0;
                }
            } else {
                buffer = endColumn;
                endRow--;
                posLoop = 0;
                fillArray();
            }
        }
    }
}

int main(void) {
    array_cont[endColumn][endColumn] = 1;
    array_cont[endColumn][endColumn   1] = 2;
    //DO STUFF

    u16_t max = ((size * size) - 1) / maxTimes;
    for (u16_t j = 0; j < max; j  ) {
        fillArray();
        curr = 0;
        //DO STUFF
    }

    //Demostration
    for (u16_t x = 0; x < size; x  ) {
        for (u16_t y = 0; y < size; y  )
            printf("%-4d ", array_cont[x][y]);
        printf("\n");
    }

    return 0;
}

從中心以螺旋形式填充矩陣

uj5u.com熱心網友回復:

從中心以螺旋形式填充矩陣

請注意,沿對角線 (1, 9, 25, 49) 的數字是奇數的平方。這是一個重要的線索,因為它表明矩陣中心的 1 應該被視為螺旋末端

從每個螺旋的末端開始,x,y 坐標應向上和向右調整 1。然后可以通過向下、向左、向上和向右移動相同的量來構建螺旋的下一層。

例如,從1的位置開始,向上和向右移動(到9的位置),然后按照以下程序形成一個回圈:

 move down, and place the 2  
 move down, and place the 3  
 move left, and place the 4  
 move left, and place the 5  
 etc.

因此代碼看起來像這樣:

int size = 7;
int matrix[size][size];
int dy[] = { 1,  0, -1, 0 };
int dx[] = { 0, -1,  0, 1 };
int directionCount = 4;

int ringCount = (size - 1) / 2;
int y = ringCount;
int x = ringCount;
int repeatCount = 0;
int value = 1;

matrix[y][x] = value  ;
for (int ring = 0; ring < ringCount; ring  )
{
    y--;
    x  ;
    repeatCount  = 2;
    for (int direction = 0; direction < directionCount; direction  )
        for (int repeat = 0; repeat < repeatCount; repeat  )
        {
            y  = dy[direction];
            x  = dx[direction];
            matrix[y][x] = value  ;
        }
}

uj5u.com熱心網友回復:

我已經看到了很多做螺旋的方法。基本上都是按照路徑繪制它。

但是,您也可以想出一個螺旋分析計算公式。

因此,通過遵循路徑等沒有遞回或迭代解決方案。如果我們有運行數,我們可以直接計算矩陣中的索引。

我將從笛卡爾坐標系中數學正方向(逆時針)的螺旋開始。我們將專注于 X 和 Y 坐標。

我制作了一個簡短的 Excel 并從中匯出了一些公式。這是一個簡短的圖片: 從中心以螺旋形式填充矩陣

從要求我們知道矩陣將是二次的。這讓事情變得更容易。有點棘手的是,讓矩陣資料對稱。但是有了一些從影像中推匯出來的簡單公式,這并不是真正的問題。

然后我們可以用一些簡單的陳述句計算 x 和 y 坐標。請參閱以下帶有長變數名稱的示例程式,以便更好地理解。代碼是使用一些逐步的方法來說明實作的。當然,它可以更容易地變得更緊湊。反正。我們來看一下。

#include <iostream>
#include <cmath>
#include <iomanip>

int main() {
    // Show some example values
    for (long step{}; step < 81;   step) {

        // Calculate result
        const long roundedSquareRoot = std::lround(std::sqrt(step));
        const long roundedSquare = roundedSquareRoot * roundedSquareRoot;
        const long distance = std::abs(roundedSquare - step) - roundedSquareRoot;
        const long rsrIsOdd = (roundedSquareRoot % 2);

        const long x = (distance   roundedSquare - step - rsrIsOdd) / (rsrIsOdd ? -2 : 2);
        const long y = (-distance   roundedSquare - step - rsrIsOdd) / (rsrIsOdd ? -2 : 2);
        // Show ouput
        std::cout << "Step:" << std::setw(4) << step << std::setw(3) << x << ' ' << std::setw(3) << y << '\n';
    }
}

所以,你看到我們真的有一個分析解決方案。給定任何數字,我們可以使用公式計算 x 和 y 坐標。涼爽的。

在矩陣中獲取索引只是添加一些偏移量。

有了這些知識,我們現在可以輕松計算完整的矩陣。而且,由于根本不需要運行時活動,我們可以讓編譯器來完成這項作業。我們將簡單地對所有內容使用 constexpr 函式。

然后編譯器會在編譯時創建這個矩陣。在運行時,什么都不會發生。

請參閱一個非常緊湊的解決方案:

#include <iostream>
#include <iomanip>
#include <array>

constexpr size_t MatrixSize = 15u;

using MyType = long;
static_assert(MatrixSize > 0 && MatrixSize%2, "Matrix size must be odd and > 0");
constexpr MyType MatrixHalf = MatrixSize / 2;

using Matrix = std::array<std::array<MyType, MatrixSize>, MatrixSize >;

// Some constexpr simple mathematical functions ------------------------------------------------------------------------------
// No need for <cmath>
constexpr MyType myAbs(MyType v) { return v < 0 ? -v : v; }
constexpr double mySqrtRecursive(double x, double c, double p) {return c == p? c: mySqrtRecursive(x, 0.5 * (c   x / c), c); }
constexpr MyType mySqrt(MyType x) {return (MyType)(mySqrtRecursive((double)x,(double)x,0.0) 0.5); }

// Main constexpr function will fill the matrix with a spiral pattern during compile time -------------------------------------
constexpr Matrix fillMatrix() {
    Matrix matrix{};
    for (int i{}; i < (MatrixSize * MatrixSize);   i) {
        const MyType rsr{ mySqrt(i) }, rs{ rsr * rsr }, d{ myAbs(rs - i) - rsr }, o{ rsr % 2 };
        const size_t col{ (size_t)(MatrixHalf  ((d   rs - i - o) / (o ? -2 : 2)))};
        const size_t row{ (size_t)(MatrixHalf -((-d   rs - i - o) / (o ? -2 : 2)))};
        matrix[row][col] = i;
    }
    return matrix;
}
// This is a compile time constant!
constexpr Matrix matrix = fillMatrix();

// All the above has been done during compile time! -----------------------------------------


int main() {

    // Nothing to do. All has beend done at compile time already!
    // The matrix is already filled with a spiral pattern

    // Just output
    for (const auto& row : matrix) {
        for (const auto& col : row) std::cout << std::setw(5) << col << ' '; std::cout << '\n';
    }
}

可以輕松適應不同的坐標系或其他螺旋方向。

快樂編碼。

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/395974.html

標籤:C 算法 矩阵 螺旋

上一篇:該程序如何在分支總和python代碼中實際流動

下一篇:變數符號靜態分析的偽代碼演算法——檢查每個操作的符號

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more