patternMinor
F# code to check whether there are three same digits within a given number
Viewed 0 times
threesamenumberaredigitswithincodecheckwhethergiven
Problem
I came across this problem by accident and gave it a go. I think my solution works as it has passed all the unit tests I wrote. Given I just started learning F# a couple of weeks I would love to have some feedback on the code regarding both its accuracy and its quality.
To be clear about the problem, given an integer number, check whether the number has at least 3 same digits in it e.g. 1222, 12222, 222, 123123123 are both counted as yes.
```
module Miscellaneous =
let (|ThreeSame|_|) = function
| (l : int list) when l.Length > 20 -> Some()
| x :: y :: z :: _ when x = y && y = z -> Some()
| _ -> None
///
/// Given any integer convert its digits into a list
///
///The integer
///
///A int list
///
let convertNumberToList (number: bigint) =
let numberString = string number
numberString.ToCharArray()
|> Array.map (string >> int) //use composition to replace (fun x -> int (string x))
|> Array.toList
type NumberCheck() =
///
/// A helper function to check whether a list of numbers contains three or more
/// same numbers
///
///The list to be checked
///The flag to indicate whether the given list is sorted or not
///
/// True if there are at least 3 same numbers; False otherwise
///
static member private TripleNumberHelper(l : int list, ?sorted) =
if l.Length true
| _ -> NumberCheck.TripleNumberHelper(l.Tail, true)
else
let sortedList = l |> List.sort
match sortedList with
| Miscellaneous.ThreeSame -> true
| _ -> NumberCheck.TripleNumberHelper(sortedList.Tail, true)
///
/// Test whether a number has 3 or more same digits in it
///
///The number to be checked
///
///Ture of False
///
static member TripleN
To be clear about the problem, given an integer number, check whether the number has at least 3 same digits in it e.g. 1222, 12222, 222, 123123123 are both counted as yes.
```
module Miscellaneous =
let (|ThreeSame|_|) = function
| (l : int list) when l.Length > 20 -> Some()
| x :: y :: z :: _ when x = y && y = z -> Some()
| _ -> None
///
/// Given any integer convert its digits into a list
///
///The integer
///
///A int list
///
let convertNumberToList (number: bigint) =
let numberString = string number
numberString.ToCharArray()
|> Array.map (string >> int) //use composition to replace (fun x -> int (string x))
|> Array.toList
type NumberCheck() =
///
/// A helper function to check whether a list of numbers contains three or more
/// same numbers
///
///The list to be checked
///The flag to indicate whether the given list is sorted or not
///
/// True if there are at least 3 same numbers; False otherwise
///
static member private TripleNumberHelper(l : int list, ?sorted) =
if l.Length true
| _ -> NumberCheck.TripleNumberHelper(l.Tail, true)
else
let sortedList = l |> List.sort
match sortedList with
| Miscellaneous.ThreeSame -> true
| _ -> NumberCheck.TripleNumberHelper(sortedList.Tail, true)
///
/// Test whether a number has 3 or more same digits in it
///
///The number to be checked
///
///Ture of False
///
static member TripleN
Solution
Followed upon @hocho's comment and agree that using
groupBy is much better as it can generalise the solution to check any number of same digit rather than limited to just 3 from my initial implementation. I have also simplified the helper method which converts a number into a collection; returning a sequence is enough as there is no need to return an array.let convertNumberToSeq (number: bigint) =
let numberString = string number
numberString.ToCharArray()
|> Seq.map (string >> int)
///
/// Check whether a given number has at least n same digits
///
///The given number
///How many same digits to be checked
///
///True if there are n same digits otherwise False
///
let SameDigitCheck (number : bigint) (n : int) =
if n Seq.exists (fun x -> Seq.length x >= n)Code Snippets
let convertNumberToSeq (number: bigint) =
let numberString = string number
numberString.ToCharArray()
|> Seq.map (string >> int)
///<summary>
/// Check whether a given number has at least n same digits
///</summary>
///<param name="number">The given number</param>
///<param name="n">How many same digits to be checked</param>
///<returns>
///True if there are n same digits otherwise False
///</returns>
let SameDigitCheck (number : bigint) (n : int) =
if n < 2 then failwith "n must be at least 2"
let digits = convertNumberToSeq number
let q = query { for digit in digits do groupBy digit into g; select g }
q |> Seq.exists (fun x -> Seq.length x >= n)Context
StackExchange Code Review Q#115739, answer score: 2
Revisions (0)
No revisions yet.