Created
December 20, 2023 15:56
-
-
Save einarwh/2150e61dae276ccd86a6927aaab40a9b to your computer and use it in GitHub Desktop.
Advent of Code 2023 - Day 20: Pulse Propagation - Convert input into dot format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Advent of Code 2023. Day 20: Pulse Propagation. | |
// Convert input file into dot format for rendering with graphviz. | |
// dotnet fsi dotify.fsx <inputfile> <outputfile?> | |
open System | |
open System.IO | |
type Node = | |
| Broadcaster | |
| FlipFlop | |
| Conjunction | |
let readLines = | |
File.ReadAllLines >> Array.filter ((<>) String.Empty) | |
let parseLine (s : string) = | |
let splat = s.Split(" -> ") | |
let str = splat[0] | |
let targets = splat[1].Split(", ") |> Array.toList | |
if str = "broadcaster" then | |
(Broadcaster, str, targets) | |
else | |
let kind = if str[0] = '&' then Conjunction else FlipFlop | |
let label = str.Substring(1) | |
(kind, label, targets) | |
let toEdgeLine (_, label, targets) = | |
let ts = | |
match targets with | |
| [ t ] -> t | |
| _ -> sprintf "{ %s }" (targets |> String.concat " ") | |
sprintf " %s -> %s" label ts | |
let toConjunctionLine label = | |
sprintf " %s [ shape = box ]" label | |
let run inFile outFile = | |
let lines = readLines inFile | |
let edges = lines |> Array.map parseLine | |
let conjs = edges |> Array.choose (fun (k, src, _) -> if k = Conjunction then Some src else None) | |
let conjLines = conjs |> Array.map toConjunctionLine | |
let edgeLines = edges |> Array.map toEdgeLine | |
let before = [| | |
"digraph {" | |
" node [ shape = circle ]" | |
" button [ shape = point ]" | |
" broadcaster [ shape = diamond ]" | |
|] | |
let buttonEdge = [| | |
" button -> broadcaster" | |
|] | |
let after = [| | |
"}" | |
|] | |
let lines = [ before; conjLines; buttonEdge; edgeLines; after ] |> Array.concat | |
File.WriteAllLines(outFile, lines) | |
let args = fsi.CommandLineArgs |> Array.tail | |
let inputFileName = args |> Array.item 0 | |
let outputFileName = args |> Array.tryItem 1 |> Option.defaultValue (sprintf "%s.dot" inputFileName) | |
run inputFileName outputFileName |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment