5 people like it.

# 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