haskell 基礎題解(15)

2021-09-25 19:31:26 字數 2557 閱讀 9173

【題目】用自然數以螺旋的方式填充乙個nxn的方陣。當n=5時,形如:

這個問題對函式式語言是有點小難度。

如果是命令式的,可以建乙個陣列,不斷地賦值,改變陣列的狀態,最後把陣列裝滿了就ok。但函式式風格沒有狀態,沒有賦值,只有定義而已。。。。

如果仍堅持仿照命令式風格,也可以做。用乙個函式,接受舊陣列,要填入的數和位置,返回乙個新陣列就可以了(顯然比直接命令式麻煩些)。

實際上,我們沒必要拘泥於矩陣的外觀。乙個矩陣未必要是乙個二維陣列,只要邏輯上含有它所要表達的資訊就可了。我們在這裡打算用 map (int,int) int 這樣的結構。

乙個裝著 (位置->數字)對映的map

比如填入了前三個數字後,它應該如:

這個map 記錄了: 在哪個位置已經放入了哪個數。

怎樣表示放數時要「行走」的方向呢?

所謂方向就是在行方向的變化量,以及在列方向的變化量。用乙個tuple就可以了 (dx,dy)

怎樣表示從前 乙個方向轉為下乙個方向呢?

tuple 序列,來個無限的,haskell的強項:

[(0,1),(1,0),(0,-1),(-1,0),(0,1),(1,0)…]

還是上**吧:

import data.map (map, notmember, empty, keys, insert,

(!))

import data.list (groupby)--

-用自然數螺旋填充乙個 n x n 的方陣

ju :

:int

-> [[int]]

ju n = get_ju_zhen $ f (1,

0) dir 1 empty where

----上次的位置---

--填充方向---

-要填的數---

----已經填好的---

----

---填完之後的---

-

f ::(

int,

int)

-> [(

int,

int)] -

>

int-

> map (

int,

int)

int-

> map (

int,

int)

int f _ _ cur acc | cur > n*n = acc -

-所有數字都填完了

f (x,y) dd@(

(dx,dy)

:ds) cur acc

| x'>=1&

& x'<=n &

& y'>=1&

& y'<=n &

&(x',y') `notmember` acc -

-沒越界的空位

= f (x',y') dd (cur+

1) $ insert (x',y') cur acc

| otherwise = f (x,y) ds cur acc

where x' = x + dx

y' = y + dy

dir = cycle [(0,

1),(

1,0)

,(0,

-1),

(-1,

0)]get_ju_zhen ma =

let t = groupby (\(x1,_)

(x2,_)

-> x1=

=x2) $ keys ma

in map (map (ma !)) t--

-把不足 show(n*n) 長度的串前邊補足夠的空格

bu :

:int

->

string

->

string

bu n s =

let x =

length

(show (n*n)

) y =

length s

in replicate (x-y) ' ' +

+ s-

--要顯示的東西被處理成整齊的串表

ok :

:int

-> [string]

ok n = map (unwords . map (bu n . show)

)(ju n)

main = putstrln $ unlines (ok 5

)

演算法的核心是 f 函式。

它從矩陣外的位置開始,沿水平方向向右走,邊走邊填數。如果再走就出界了,或者就踩到其它已填數字了,則轉入下乙個方向去試探。

get_ju_zhen 只是把用map表達的資訊轉化為用矩陣的表達形式。

map 中取出的所有鍵是已經排序的。正好是我們希望的先行後列。

只要再把它分成多組就可以了。行號相同的為一組。groupby 正是幹這個活的。

「遇到障礙請右轉90度」 這個描述如果更通用一點處理,可以利用數學知識,想想複數的乘法的幾何意義就知道怎麼辦了吧。

haskell 基礎題解(06)

題目 如果乙個數的所有真因子 不包含它自身的因子 之和恰等於其自身,則該數為完全數,也稱為完美數 perfect number 完全數有許多奇妙的性質。但它們很稀少,你來求前幾個吧。最小的乙個是 6,因為 6 1 2 3 這個完全數的定義已經很清楚了,如果沒有什麼妙法,就地毯式搜尋也可以。下法就是 ...

haskell 基礎題解(07)

題目 11 1 1 2 1 1 3 3 1 1 4 6 4 1 這個陣勢叫楊輝三角,國外叫帕斯卡三角。前一行的數字中,每兩個相鄰的數字相加就得到下一行的數字。左右兩邊的數永遠是 1 寫個程式,輸出前幾行的楊輝三角。import data.list intersperse yang hui int y...

haskell基礎題解(14)

題目 用自然數蛇形填充乙個 n 階的方陣。當n 5時,形如 這個問題用 haskell 解決時與 題目13 差別甚微。實際上,從函式式的思考習慣看,只要讓有些行作成後反轉一下就可以了。上 ju n f x x 0.n 1 where f row even row take n row n 1.odd...