HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

F# code to check whether there are three same digits within a given number

Submitted by: @import:stackexchange-codereview··
0
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

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.