58 lines
1.7 KiB
OCaml
58 lines
1.7 KiB
OCaml
(*
|
|
|
|
--- Part Two ---
|
|
|
|
For added security, yet another system policy has been put in place. Now, a valid passphrase must contain no two words that are anagrams of each other - that is, a passphrase is invalid if any word's letters can be rearranged to form any other word in the passphrase.
|
|
|
|
For example:
|
|
|
|
abcde fghij is a valid passphrase.
|
|
abcde xyz ecdab is not valid - the letters from the third word can be rearranged to form the first word.
|
|
a ab abc abd abf abj is a valid passphrase, because all letters need to be used when forming another word.
|
|
iiii oiii ooii oooi oooo is valid.
|
|
oiii ioii iioi iiio is not valid - any of these words can be rearranged to form any other word.
|
|
|
|
Under this new system policy, how many passphrases are valid?
|
|
|
|
*)
|
|
|
|
open Batteries
|
|
|
|
|
|
let rec check_word (words : string list) (word : string) : bool =
|
|
let order_word word =
|
|
String.to_list word
|
|
|> List.sort compare
|
|
|> String.of_list
|
|
in
|
|
match words with
|
|
| [] -> true
|
|
| hd :: tl ->
|
|
if hd = word
|
|
then
|
|
check_word tl word
|
|
else
|
|
if (order_word hd) = (order_word word)
|
|
then false
|
|
else check_word tl word
|
|
|
|
let filter_anagram (words : string list) : bool =
|
|
List.for_all (check_word words) words
|
|
|
|
let filter_unique (words : string list) : bool =
|
|
(List.length words) = (words |> Set.of_list |> Set.cardinal)
|
|
|
|
let parse_input (input : string list) : int =
|
|
List.map (String.split_on_char ' ') input
|
|
|> List.filter filter_unique
|
|
|> List.filter filter_anagram
|
|
|> List.length
|
|
|
|
let () =
|
|
Sys.argv.(1)
|
|
|> File.lines_of
|
|
|> List.of_enum
|
|
|> parse_input
|
|
|> print_int
|
|
|