View Source Pythagorean Triples
Mix.install([
{:guesswork, "~> 0.5"},
{:kino, "~> 0.13"}
],
consolidate_protocols: false
)Queries that Calculate Values
import Guesswork.Ast
alias Guesswork.Ast.And
alias Guesswork.Ast.Assign
alias Guesswork.Ast.OneOf
alias Guesswork.Answer.Result
alias Guesswork.QueryQueries don't necisarily need facts to operate (in fact, Guesswork.query/2 will just
use an empty collection), they can use assigned values, and then calculate new values.
The below example is a really simple query that uses Guesswork.Ast.Assign to assign
values to a and b, and then uses is to calculated a third value based on the first two.
It should be noted that, in most cases, statements are created with functions.
But the is macro is needed to build a Guesswork.Ast.Is.
Guesswork.query(
term(And.new([Assign.new(a, 1), Assign.new(b, 2), is(d, fn a, b -> b - a end)])),
10
)Below is a more complex example, calculating pythagorean triples.
Instead of using set we use one_of to assign an enumerable to a variable, so that
the variable can be one of any of the values.
Then we use is again, but this time to test that our variables really are pythagorean
triples.
Guesswork.query(
term(
And.new([
OneOf.new(a, 1..10),
OneOf.new(b, 1..10),
OneOf.new(c, 1..10),
is(true, fn a, b -> a < b end),
is(0, fn a, b, c -> Integer.pow(c, 2) - Integer.pow(a, 2) - Integer.pow(b, 2) end)
])
),
10
)But one_of will support not just finite enumerables, but streams.
So below we calculate the first ten triples for all positive integers.
Its worth noting that here, instead of using just using the query function,
we create an unresolved query, and then run it.
This allows us to reuse the query below.
query =
Query.new(
term(
And.new([
OneOf.new(a, Stream.iterate(1, &(&1 + 1))),
OneOf.new(b, Stream.iterate(1, &(&1 + 1))),
OneOf.new(c, Stream.iterate(1, &(&1 + 1))),
is(true, fn a, b -> a < b end),
is(0, fn a, b, c -> Integer.pow(c, 2) - Integer.pow(a, 2) - Integer.pow(b, 2) end)
])
)
)
Result.run(query, 10)Now that we have the unresolved query we can calculate even more, and pull the first 100.
Note that this will take a few seconds.
The process is brute force, so as you request more results, more combinations of a,
b, and c will have to be tested.
Result.run(query, 100)