You can install Elixir by following the official docs or via asdf.
- Download the
fact_enginezip file and unzip it cdinto it- If you are using
asdfyou'll need to runasdf install - Run
iex -S mixto get to the interactive shell - Run
FactEngine.State.start()(this starts the process that holds the persistent state) - Run
FactEngine.run(read_file_path, write_file_path)wherewrite_file_pathis the file path to the file you want to process andwrite_file_pathis the file path to the file you want the results written to. For example:read_file_path = "/Users/jonericcook/github/fact_engine/examples/4/in.txt"andwrite_file_path = "/Users/jonericcook/github/fact_engine/examples/4/out.txt"
Check the contents of the file that's to be processed
% cat /Users/jonericcook/github/fact_engine/examples/4/in.txt
INPUT make_a_triple (3, 4, 5)
INPUT make_a_triple (5, 12, 13)
QUERY make_a_triple (X, 4, Y)
QUERY make_a_triple (X, X, Y)
Start the Elixir interactive shell and use FactEngine
% iex -S mix
iex(1)> FactEngine.State.start()
iex(2)> read_file_path = "/Users/jonericcook/github/fact_engine/examples/4/in.txt"
iex(3)> write_file_path = "/Users/jonericcook/github/fact_engine/examples/4/out.txt"
iex(4)> FactEngine.run(read_file_path, write_file_path)
iex(5)> FactEngine.State.get
%{"make_a_triple" => #MapSet<[["12", "13", "5"], ["3", "4", "5"]]>}
Check the contents of the file that contains the results
% cat /Users/jonericcook/github/fact_engine/examples/4/out.txt
---
X: 3, Y: 5
---
false
In an effort to not have duplicates in state I chose to sort the arguments. I chose this because to me it wouldn't make sense to have two entries - one for INPUT are_friends (alex, sam) and one for INPUT are_friends (sam, alex).
It was unclear how to create the constraint between the number of arguments and a statement therefore I opted to not verify the number of arguments for a given statement. For example INPUT love (cat, dog) and INPUT love (cheese) would both be accepted. As I read this I think I could handle that scenario by having a MapSet for each statement and each length of arguments provided with said statement. For example:
%{
"loves" => %{
2 => #MapSet<[["garfield", "lasagna"]]>,
3 => #MapSet<[["garfield", "lasagna", "grilled_cheese"]]>
}
}
Where the key at the second depth is the length of the lists in the MapSet.