5 people like it.
Like the snippet!
Reversi Kata solution
Reversi Kata solution from February 2013 London F# Meetup Coding Kata.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
|
open System
/// Reversi board
let board = "
....
.OX.
.XO.
...."
/// Board rows
let rows = board.Split([|'\n'|], StringSplitOptions.RemoveEmptyEntries)
/// Board cells
let cells =
rows
|> Array.map (fun row -> row.ToCharArray())
|> array2D
/// Returns true if coordinates are inside board
let inside (x,y) =
x >=0 && x < rows.[0].Length && y >= 0 && y < rows.Length
/// Gets vectors from a coordinate
let getVectors (x,y) =
[-1,-1; 0,-1; 1,-1
-1, 0; 1, 0
-1, 1; 0, 1; 1, 1]
|> List.filter (fun (dx,dy) -> inside(x+dx,y+dy))
/// Returns true if board run represents a valid move
let isValidRun (s:string) =
let color = s.[0]
let opposite =
match color with
| 'O' -> 'X'
| 'X' -> 'O'
| c -> invalidOp(sprintf "Unexpected char %c" c)
let mutable i = 1
while i < s.Length && s.[i] = opposite do i <- i + 1
i > 1 && i < s.Length && s.[i] = color
/// Gets board run as string
let getRun (x,y) (dx,dy) =
let px = ref (x+dx)
let py = ref (y+dy)
let chars =
[|while inside(!px,!py) do
yield cells.[!py,!px]
px := !px + dx
py := !py + dy|]
String(chars)
/// Prints all valid moves for a color
let validMoves (color:string) =
cells
|> Array2D.iteri (fun y x cell ->
if cell = '.' then
getVectors (x,y)
|> List.exists (fun vector ->
let s = getRun (x,y) vector
isValidRun (color+s)
)
|> function
| true -> printfn "%d %d" x y
| false -> ()
)
|
namespace System
val board : string
Full name: Script.board
Reversi board
val rows : string []
Full name: Script.rows
Board rows
String.Split([<ParamArray>] separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
type StringSplitOptions =
| None = 0
| RemoveEmptyEntries = 1
Full name: System.StringSplitOptions
field StringSplitOptions.RemoveEmptyEntries = 1
val cells : char [,]
Full name: Script.cells
Board cells
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []
Full name: Microsoft.FSharp.Collections.Array.map
val row : string
String.ToCharArray() : char []
String.ToCharArray(startIndex: int, length: int) : char []
val array2D : rows:seq<#seq<'T>> -> 'T [,]
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.array2D
val inside : x:int * y:int -> bool
Full name: Script.inside
Returns true if coordinates are inside board
val x : int
val y : int
property Array.Length: int
val getVectors : x:int * y:int -> (int * int) list
Full name: Script.getVectors
Gets vectors from a coordinate
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val filter : predicate:('T -> bool) -> list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.filter
val dx : int
val dy : int
val isValidRun : s:string -> bool
Full name: Script.isValidRun
Returns true if board run represents a valid move
val s : string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
val color : char
val opposite : char
val c : char
val invalidOp : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.invalidOp
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val mutable i : int
property String.Length: int
val getRun : x:int * y:int -> dx:int * dy:int -> String
Full name: Script.getRun
Gets board run as string
val px : int ref
Multiple items
val ref : value:'T -> 'T ref
Full name: Microsoft.FSharp.Core.Operators.ref
--------------------
type 'T ref = Ref<'T>
Full name: Microsoft.FSharp.Core.ref<_>
val py : int ref
val chars : char []
Multiple items
type String =
new : value:char -> string + 7 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 2 overloads
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
member GetHashCode : unit -> int
...
Full name: System.String
--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
val validMoves : color:string -> unit
Full name: Script.validMoves
Prints all valid moves for a color
val color : string
module Array2D
from Microsoft.FSharp.Collections
val iteri : action:(int -> int -> 'T -> unit) -> array:'T [,] -> unit
Full name: Microsoft.FSharp.Collections.Array2D.iteri
val cell : char
val exists : predicate:('T -> bool) -> list:'T list -> bool
Full name: Microsoft.FSharp.Collections.List.exists
val vector : int * int
val s : String
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
More information