Skip to content

Instantly share code, notes, and snippets.

@prGmtc
Created December 6, 2016 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prGmtc/b62bf2f3ac5289d2d2f643aa2c196f5c to your computer and use it in GitHub Desktop.
Save prGmtc/b62bf2f3ac5289d2d2f643aa2c196f5c to your computer and use it in GitHub Desktop.
Advent of Code 2016 - Day 6 part 2 - F#
open System
open System.Security.Cryptography
let hasher = MD5.Create()
let hash (word : string) =
let bytes = System.Text.Encoding.ASCII.GetBytes(word)
let hash = hasher.ComputeHash(bytes)
BitConverter.ToString(hash).Replace("-", "")
let indexes =
Seq.initInfinite id
let appendTo word suffix =
word + suffix
let startsWith prefix (word : string) =
word.StartsWith(prefix)
let interestingHashes doorID =
indexes
|> Seq.map (string >> appendTo doorID >> hash)
|> Seq.filter (startsWith "00000")
let nth n (word : string) =
word.[n - 1]
let parseHexStringToInt (hex : string) =
let hexBase = 16
Convert.ToInt32(hex, hexBase)
let indexAndRelevantCharacter hash =
let idx =
nth 6 hash
|> string
|> parseHexStringToInt
let theCharacter = nth 7 hash
(idx, theCharacter)
let validIndexWithUpperLimit max index =
index >= 0 && index < max
let accumulateFirstHits accumulator (index, crackedChar) =
if accumulator |> Map.containsKey index then
accumulator
else
accumulator |> Map.add index crackedChar
let crack passwordLength candidates =
candidates
|> Seq.scan accumulateFirstHits Map.empty
|> Seq.find (fun acc -> acc |> Seq.length = passwordLength)
let indexesWithCharactersToString indexesWithCharacters =
indexesWithCharacters
|> Seq.sortBy fst
|> Seq.map (snd >> string)
|> String.concat ""
let toLower (text : string) =
text.ToLower()
let findCode doorID =
let length = Seq.length doorID
doorID
|> interestingHashes
|> Seq.map indexAndRelevantCharacter
|> Seq.filter (fst >> validIndexWithUpperLimit length)
|> crack length
|> Map.toSeq
|> indexesWithCharactersToString
|> toLower
let secret = "reyedfim"
printfn "Here we go!"
let sw = System.Diagnostics.Stopwatch.StartNew()
let solution = findCode secret
printfn "It took me %A seconds to find %s" sw.Elapsed.TotalSeconds solution // 100s :(
@theburningmonk
Copy link

theburningmonk commented Dec 6, 2016

a little F# trick, when you're in a script, you can use the #time directive to turn on timing, so you don't need to use a stopwatch yourself, it also gives you info on gen0 and gen1 GCs too

@prGmtc
Copy link
Author

prGmtc commented Dec 6, 2016

Good to know, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment