여기있어. 이것이 나의 첫 F # 프로그램입니다. 언어의 기능을 놓친 경우 계속 배우면서 알려주십시오.
여기 내 샘플 입력이 있습니다
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . B . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . A . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . C . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . G . . . . .
. . . . . . . D . . . . . . . . . . . . . . . . .
. . . . . . . . F . . . . . . . . . . . . . . . .
. . . . . . . E . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . .
출력은 다음과 같습니다
. . . . . . . . . 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 . . . . . . .
코드는 다음과 같습니다. 즐겨.
// The first thing that we need is some data.
let originalData = [
"........................."
"............B............"
"........................."
"........A................"
"........................."
"................C........"
"........................."
"...................G....."
".......D................."
"........F................"
".......E................."
"........................."
"........................."
"........................."
]
이제 인덱서를 통해 데이터에 액세스 할 수 있도록 해당 데이터를 2 차원 배열로 변환해야합니다.
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
각 셀의 소유권을 나타내는 행렬을 만들어 봅시다
let claims =
dataMatrix
|> Array.map (fun row ->
row
|> Array.map (function
| '.' -> Owned.Unclaimed
| ch -> Owned.Owner(ch))
)
무슨 일이 있었는지 볼 수있는 유틸리티 방법을 보자.
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 "")
특정 대문자가있는 위치를 나타내는 레코드를 작성하겠습니다.
type CapitalLocation = { X:int; Y:int; Letter:char }
이제 대문자를 모두 찾고 싶습니다.
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)
우리가 움직일 때 방향의 개념이 필요합니다.
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.
우리가 움직일 때 크기에 대해 알아야 할 것입니다. 이것은 우리가 경계 밖으로 나가고 있는지 모니터링하는 데 도움이 될 것입니다.
type Size = { Width:int; Height: int }
// Get the size of the matrix.
let size = {Width=originalData.Head.Length; Height=originalData.Length}
활성 패턴 : 주어진 셀의 기준과 일치합니다.
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)
지금 우리는 놋쇠 세금으로 내려 가고 있습니다. 이것은 세포를 주장한다!
let claimCell letter (x, y) =
// Side effect: Change the value of the cell
(claims.[y].[x] <- Owned.Claimed (System.Char.ToLower letter)) |> ignore
활성 패턴을 사용하여,이 셀을 청구하지 않으면이 셀을 청구하고 인접한 셀의 좌표를 반환하십시오.
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
우리는이 데이터 백의 목록을 만들기 시작했습니다.보다 명확한 유형을 만들겠습니다.
type CellClaimCriteria = (char * (int * int) * Direction)
셀을 청구하기위한 기준 목록이 주어지면 다음 셀을 리턴하여 해당 목록으로 돌아가서 다시 반환하는 목록을 반복합니다.
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)
각 자본에 대해 각 방향으로 클레임 기준을 만든 다음 해당 셀을 재귀 적으로 클레임하십시오.
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
모든 프로그램에는 주 프로그램이 필요합니다.
[<EntryPoint>]
let main args =
printIt()
claimCellsFromCapitalsOut()
printIt()
0