An array
in F# is a mutable collection of zero or more values with a fixed length. This means that once an array has been created, its size cannot change, but its values can. The values in an array must all have the same type. Arrays can be defined as follows:
let empty = [| |]
let emptyAlternative = Array.empty
let singleValue = [| 5 |]
let singleValueAlternative = Array.singleton 5
let threeValues = [| "a"; "b"; "c" |]
Elements can be assigned to an array or retrieved from it using an index. F# arrays are zero-based, meaning that the first element's index is always zero:
let numbers = [| 2; 3; 5 |]
// Update value in array
numbers[2] <- 9
// Read value from array
numbers[2]
// => 9
Arrays are either manipulated by functions and operators defined in the Array
module, or manually using pattern matching using the array pattern:
let describe array =
match array with
| [| |] -> "Empty"
| [| 1; 2; three |] -> sprintf "1, 2, %d" three
| _ -> "Other"
describe [| |] // => "Empty"
describe [| 1; 2; 4 |] // => "1, 2, 4"
describe [| 5; 7; 9 |] // => "Other"
You can also discard a value when pattern matching; when you do not care about a value in a specific case (i.e. you aren't going to use a value) you can use an underscore ('_'
) to signify this:
let describe array =
match array with
| [| |] -> "Empty array"
| [| x |] -> "Array with one item"
| [| _; y |] -> "Array with two items (first item ignored)"
| _ -> "Array with many items (all items ignored)"
describe [| |] // => "Empty array"
describe [| 1 |] // => "Array with one item"
describe [| 5; 7 |] // => "Array with two items (first item ignored)"
describe [| 5; 7; 9 |] // => "Array with many items (all items ignored)"
The single '_'
should always come last when pattern matching, every value that doesn't match any of the other cases will be handled by this case.
You're an avid bird watcher that keeps track of how many birds have visited your garden in the last seven days.
You have six tasks, all dealing with the numbers of birds that visited your garden.
For comparison purposes, you always keep a copy of last week's counts nearby, which were: 0, 2, 5, 3, 7, 8, and 4. Define the lastWeek
binding that contains last week's counts:
lastWeek
// => [| 0; 2; 5; 3; 7; 8; 4 |]
Implement the yesterday
function to return how many birds visited your garden yesterday. The bird counts are ordered by day, with the first element being the count of the oldest day, and the last element being today's count.
yesterday [| 3; 5; 0; 7; 4; 1 |]
// => 4
Implement the total
function to return the total number of birds that have visited your garden:
total [| 3; 5; 0; 7; 4; 1 |]
// => 20
Implement the dayWithoutBirds
function that returns true
if there was a day at which zero birds visited the garden; otherwise, return false
:
dayWithoutBirds [| 3; 5; 0; 7; 4; 1 |]
// => true
Implement the incrementTodaysCount
function to increment today's count and return the updated counts:
let birdCount = [| 3; 5; 0; 7; 4; 1 |]
incrementTodaysCount birdCount
// => [| 3; 5; 0; 7; 4; 2 |]
Over the last year, you've found that some weeks have the same, unusual patterns:
Implement the unusualWeek
function that returns true
if the bird count pattern of this week matches one of the unusual patterns:
unusualWeek [| 1; 0; 5; 0; 12; 0; 2 |]
// => true
unusualWeek [| 5; 0; 5; 12; 5; 3; 5|]
// => true
(Note that day-parity is 1-indexed, not 0-indexed - the first element in the array corresponds with an odd day)
Sign up to Exercism to learn and master F# with 15 concepts, 143 exercises, and real human mentoring, all for free.