【題目】用自然數以螺旋的方式填充乙個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...