Nó đây rồi Đây là chương trình F # đầu tiên của tôi. Nếu tôi bỏ lỡ một tính năng của ngôn ngữ, xin vui lòng thông báo cho tôi vì tôi vẫn đang học.
Đây là đầu vào mẫu của tôi
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . B . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . A . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . C . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . G . . . . .
. . . . . . . D . . . . . . . . . . . . . . . . .
. . . . . . . . F . . . . . . . . . . . . . . . .
. . . . . . . E . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
Đây là đầu ra
. . . . . . . . . a b . . . . . . . b g . . . . .
. . . . . . . . . a b . B . . . b b b g . . . . .
. . . . . . . . . . a b . . . b c c c g . . . . .
. . . . . . . . A . . a b . b c . . c g . . . . .
. . . . . . . . . . . a b b c . . . c g . . . . .
a a a a a a a a . . . a b c . . C . c g . . . . .
d d d d d d d d a a a a b c . . . c g . . . . . .
. . . . . . . . d d d d b c . . c g . G . . . . .
. . . . . . . D d d d d d c . . c g . . . . . . .
d d d d d d d d f f f f f f c . c g . . . . . . .
e e e e e e e e e e e e e e c . c g . . . . . . .
. . . . . . . . . . . . . e c . c g . . . . . . .
. . . . . . . . . . . . . e c . c g . . . . . . .
. . . . . . . . . . . . . e c . c g . . . . . . .
Đây là mã. Thưởng thức.
// The first thing that we need is some data.
let originalData = [
"........................."
"............B............"
"........................."
"........A................"
"........................."
"................C........"
"........................."
"...................G....."
".......D................."
"........F................"
".......E................."
"........................."
"........................."
"........................."
]
Bây giờ chúng ta cần chuyển đổi dữ liệu đó thành một mảng hai chiều để chúng ta có thể truy cập nó thông qua các bộ chỉ mục.
let dataMatrix =
originalData
|> List.map (fun st -> st.ToCharArray())
|> List.toArray
// We are going to need a concept of ownership for each
// cell.
type Owned =
| Unclaimed
| Owner of char
| Claimed of char
| Boundary of char
Chúng ta hãy tạo một ma trận thể hiện quyền sở hữu của mỗi ô
let claims =
dataMatrix
|> Array.map (fun row ->
row
|> Array.map (function
| '.' -> Owned.Unclaimed
| ch -> Owned.Owner(ch))
)
Hãy để chúng tôi có một phương pháp tiện ích để xem những gì đã xảy ra.
let printIt () =
printfn ""
claims
|> Array.iter (fun row ->
row |> Array.iter (function
| Owned.Claimed(ch) -> printf " ."
| Owned.Owner(ch) -> printf " %c" ch
| Owned.Boundary(ch) -> printf " %c" ch
| _ -> printf " ." )
printfn "")
Hãy để chúng tôi tạo một bản ghi để thể hiện nơi một chữ in hoa cụ thể cư trú.
type CapitalLocation = { X:int; Y:int; Letter:char }
Bây giờ chúng tôi muốn tìm tất cả các chữ in hoa.
let capitals =
dataMatrix
|> Array.mapi (fun y row ->
row
|> Array.mapi (fun x item ->
match item with
| '.' -> None
| _ -> Some({ X=x; Y=y; Letter=item }))
|> Array.choose id
|> Array.toList
)
|> Array.fold (fun acc item -> item @ acc) List.empty<CapitalLocation>
|> List.sortBy (fun item -> item.Letter)
Khi chúng ta di chuyển, chúng ta cần một khái niệm về hướng.
type Direction =
| Left = 0
| Up = 1
| Right = 2
| Down = 3
// Function gets the coordinates of the adjacent cell.
let getCoordinates (x, y) direction =
match direction with
| Direction.Left -> x-1, y
| Direction.Up -> x, y-1
| Direction.Right -> x+1, y
| Direction.Down -> x, y+1
| _ -> (-1,-1) // TODO: Figure out how to best throw an error here.
Khi chúng ta di chuyển, chúng ta sẽ cần phải biết về kích thước. Điều này sẽ giúp chúng tôi theo dõi xem chúng tôi có di chuyển ra khỏi giới hạn hay không.
type Size = { Width:int; Height: int }
// Get the size of the matrix.
let size = {Width=originalData.Head.Length; Height=originalData.Length}
Mô hình hoạt động: khớp với tiêu chí của một ô đã cho.
let (|OutOfBounds|UnclaimedCell|Claimed|Boundary|) (x,y) =
match (x,y) with
| _,_ when x < 0 || y < 0 -> OutOfBounds
| _,_ when x >= size.Width || y >= size.Height -> OutOfBounds
| _ ->
match claims.[y].[x] with
| Owned.Unclaimed -> UnclaimedCell(x,y)
| Owned.Claimed(ch) -> Claimed(x,y,ch)
| Owned.Boundary(ch) -> Boundary(x,y,ch)
| Owned.Owner(ch) -> Claimed(x,y,ch)
Bây giờ chúng tôi đang giảm thuế đồng. Điều này tuyên bố tế bào!
let claimCell letter (x, y) =
// Side effect: Change the value of the cell
(claims.[y].[x] <- Owned.Claimed (System.Char.ToLower letter)) |> ignore
Sử dụng mẫu đang hoạt động, xác nhận ô này nếu không được yêu cầu và trả về tọa độ của các ô liền kề.
let claimAndReturnAdjacentCells (letter, coordinates, direction) =
match coordinates with
| UnclaimedCell (x,y) ->
// Claim it and return the Owned object.
claimCell letter coordinates // meaningful side effect
// use Direction as int to allow math to be performed.
let directionInt = int direction;
Some(
// [counter-clockwise; forward; clockwise]
[(directionInt+3)%4; directionInt; (directionInt+1)%4]
|> List.map enum<Direction>
|> List.map (fun newDirection ->
(
letter,
getCoordinates coordinates newDirection,
newDirection
))
)
| Claimed(cx,cy,cch) when cch <> System.Char.ToLower letter->
// If we find a "Claimed" element that is not our letter, we have
// hit a boundary. Change "Claimed" to "Boundary" and return the
// element that led us to evaluating this element. It is also a
// boundary.
(claims.[cy].[cx] <- Owned.Boundary (System.Char.ToLower cch)) |> ignore
let reverseDirection = enum<Direction>(((int direction)+2)%4)
Some[(
cch,
getCoordinates (cx, cy) reverseDirection,
reverseDirection
)]
| _ -> None
Chúng tôi đang bắt đầu tạo danh sách của túi dữ liệu này, hãy để chúng tôi tạo một loại để làm cho mọi thứ rõ ràng hơn.
type CellClaimCriteria = (char * (int * int) * Direction)
Đưa ra một danh sách các tiêu chí để yêu cầu các ô, chúng tôi sẽ lặp lại danh sách trả về các ô tiếp theo để yêu cầu và lặp lại vào danh sách đó.
let rec claimCells (items:CellClaimCriteria list) =
items
|> List.fold (fun acc item ->
let results = claimAndReturnAdjacentCells item
if Option.isSome(results)
then (acc @ Option.get results)
else acc
) List.empty<CellClaimCriteria>
|> (fun l ->
match l with
| [] -> []
| _ -> claimCells l)
Đối với mỗi thủ đô, hãy tạo một tiêu chí yêu cầu theo từng hướng và sau đó yêu cầu đệ quy các ô đó.
let claimCellsFromCapitalsOut ()=
capitals
|> List.fold (fun acc capital ->
let getCoordinates = getCoordinates (capital.X, capital.Y)
[Direction.Left; Direction.Up; Direction.Right; Direction.Down]
|> List.map (fun direction ->
(
capital.Letter,
getCoordinates direction,
direction
))
|> (fun items -> acc @ items)) List.empty<CellClaimCriteria>
|> claimCells
Mỗi chương trình cần một chính.
[<EntryPoint>]
let main args =
printIt()
claimCellsFromCapitalsOut()
printIt()
0