-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday04_part02.fs
53 lines (40 loc) · 1.77 KB
/
day04_part02.fs
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
module day04_part02
open System.IO
let filepath = __SOURCE_DIRECTORY__ + @"../../day04_input.txt"
let input = File.ReadAllText(filepath).Split('-') |> Array.map int
let isSixDigitNumber(pass: int) : bool =
pass.ToString().Length = 6
let isInRange(range:int array, pass: int) : bool =
pass >= range.[0] && pass <= range.[1]
// Criteria Part 1
let hasDuplicatedAdjacentDigit(pass: int) : bool =
pass.ToString().ToCharArray() |> Array.map (fun _c -> int(System.Char.GetNumericValue(_c)))
|> Array.toSeq |> Seq.pairwise |> Seq.exists (fun (a, b) -> a = b)
// Criteria Part 2
let splitAt f list =
let rec splitAtAux acc list =
match list with
| x::y::ys when f x y -> List.rev (x::acc), y::ys
| x::xs -> splitAtAux (x::acc) xs
| [] -> (List.rev acc), []
splitAtAux [] list
let foldUntilEmpty f list =
let rec foldUntilEmptyAux acc list =
match f list with
| l, [] -> l::acc |> List.rev
| l, rest -> foldUntilEmptyAux (l::acc) rest
foldUntilEmptyAux [] list
let splitAtEvery f list = foldUntilEmpty (splitAt f) list
let hasMax2DuplicatedAdjacentDigit(pass: int) : bool =
pass.ToString().ToCharArray() |> Array.map (fun _c -> int(System.Char.GetNumericValue(_c)))
|> Array.toList |> splitAtEvery (<>) |> List.exists (fun _l -> _l.Length = 2)
let neverDecrease(pass: int) : bool =
pass.ToString().ToCharArray() |> Array.map (fun _c -> int(System.Char.GetNumericValue(_c)))
|> Array.toSeq |> Seq.pairwise |> Seq.forall (fun (a, b) -> a <= b)
let isValidPassword(pass: int) : bool =
isSixDigitNumber pass && isInRange(input, pass) && hasMax2DuplicatedAdjacentDigit pass && neverDecrease pass
let validPasswords =
[input.[0]..input.[1]]
|> List.filter (fun pass -> isValidPassword pass)
let execute =
validPasswords.Length