F# Training
F# Training
F# Training
  • Presentation
  • Fundamentals
    • Introduction
    • Syntax
      • Bases
      • Functions
      • Rules
      • Exceptions
    • First concepts
    • 🍔Quiz
  • Functions
    • Signature
    • Concepts
    • Syntax
    • Standard functions
    • Operators
    • Addendum
    • 🍔Quiz
    • 📜Summary
  • Types
    • Overview
    • Tuples
    • Records
    • Unions
    • Enums
    • Anonymous records
    • Value types
    • 📜Recap
    • Addendum
  • Monadic types
    • Intro
    • Option type
    • Result type
    • Smart constructor
    • 🚀Computation expression (CE)
    • 🚀CE theoretical basements
    • 📜Recap
  • Pattern matching
    • Patterns
    • Match expression
    • Active patterns
    • 🚀Fold function
    • 📜Recap
    • đŸ•šī¸Exercises
  • Collections
    • Overview
    • Types
    • Common functions
    • Dedicated functions
    • 🍔Quiz
    • 📜Recap
  • Asynchronous programming
    • Asynchronous workflow
    • Interop with .NET TPL
    • 📜Recap
  • Module and Namespace
    • Overview
    • Namespace
    • Module
    • 🍔Quiz
    • 📜Recap
  • Object-oriented
    • Introduction
    • Members
    • Type extensions
    • Class, Struct
    • Interface
    • Object expression
    • Recommendations
Powered by GitBook
On this page
  • Collatz Conjecture (easy)
  • đŸŽ¯ Darts (easy)
  • 👑 Queen Attack (medium)
  • 🤖 Robot Name (medium)

Was this helpful?

Edit on GitHub
  1. Pattern matching

Exercises

PreviousRecapNextOverview

Last updated 1 month ago

Was this helpful?

The following exercises on can be solved with active patterns:

Collatz Conjecture (easy)

My solution
let private (|NegativeOrZero|One|PositiveEven|PositiveOdd|) number =
    if number <= 0 then NegativeOrZero
    elif number = 1 then One
    elif number % 2 = 0 then PositiveEven
    else PositiveOdd
let steps (number: int): int option =
    let rec loop n count =
        match n with
        | NegativeOrZero -> None
        | One            -> Some count
        | PositiveEven   -> loop (n / 2) (count + 1)
        | PositiveOdd    -> loop (3 * n + 1) (count + 1)
    loop number 0

đŸŽ¯ Darts (easy)

My solution
let private radiusOfCircle = {| Outer = 10.0 ; Middle = 5.0 ; Inner = 1.0 |}

let private distanceToOrigin point =
    point
    |> List.sumBy (fun x -> x ** 2.0)
    |> sqrt

let (|Inner|Middle|Outer|Outside|) point =
    match distanceToOrigin point with
    | x when x > radiusOfCircle.Outer  -> Outside
    | x when x > radiusOfCircle.Middle -> Outer
    | x when x > radiusOfCircle.Inner  -> Middle
    | _                                -> Inner

let score (x: double) (y: double): int =
    match [ x; y ] with
    | Outside -> 0
    | Outer   -> 1
    | Middle  -> 5
    | Inner   -> 10

👑 Queen Attack (medium)

My solution
type Position = int * int

let (|SameRow|SameColumn|SameDiagonal|Other|) (queen1: Position, queen2: Position) =
  match queen1, queen2 with
  | (x1, _), (x2, _) when x1 = x2 -> SameRow
  | (_, y1), (_, y2) when y1 = y2 -> SameColumn
  | (x1, y1), (x2, y2) when abs (y1 - y2) = abs (x1 - x2) -> SameDiagonal
  | _ -> Other

let canAttack (queen1: Position) (queen2: Position) =
  match queen1, queen2 with
  | SameRow | SameColumn | SameDiagonal -> true
  | Other -> false

🤖 Robot Name (medium)

When a robot comes off the factory floor, it has no name.

The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811.

Every once in a while we need to reset a robot to its factory settings, which means that its name gets wiped. The next time you ask, that robot will respond with a new random name.

The names must be random: they should not follow a predictable sequence. Using random names means a risk of collisions. Your solution must ensure that every existing robot has a unique name.

My solution
open System

type Robot = Robot of string

let private random = Random(Guid.NewGuid().GetHashCode());

let private letters = [| 'A'..'Z' |]

let private letter () = letters[random.Next(0, 25)]
let private digit () = random.Next(0, 9)

let private randomRobotName () =
    $"{letter()}{letter()}{digit()}{digit()}{digit()}"

let mutable private names = Set.empty

let private (|Available|Taken|) name =
    if names |> Set.contains name
    then Taken
    else Available name

let rec private uniqueRobotName () =
    match randomRobotName () with
    | Available name -> name
    | Taken -> uniqueRobotName()

let private makeRobotWith adjustNames =
    let name = uniqueRobotName()
    names <-
        names
        |> adjustNames
        |> Set.add name
    Robot name

let makeRobot () = makeRobotWith id

let reset (Robot previousName) = makeRobotWith (Set.remove previousName)

đŸ•šī¸
exercism - F# track
Instructions
Wikipedia
Instructions
Wikipedia
Instructions
Wikipedia
Instructions