rubylog 1.0.0 → 2.0pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +3 -12
- data/Gemfile.lock +22 -48
- data/README.rdoc +38 -38
- data/README.rdoc.orig +284 -0
- data/RELEASE_NOTES.rdoc +51 -0
- data/Rakefile +14 -18
- data/TODO.txt +0 -0
- data/VERSION +1 -1
- data/examples/a_plus_b.rb +6 -0
- data/examples/checkmate.rb +88 -0
- data/examples/combination.rb +17 -0
- data/examples/dcg.rb +3 -2
- data/examples/dcg2.rb +2 -2
- data/{logic → examples}/directory_structure_logic.rb +3 -5
- data/examples/dirlist.rb +4 -0
- data/examples/divisors.rb +6 -0
- data/examples/enumerators.rb +3 -3
- data/examples/factorial.rb +2 -3
- data/examples/file_search.rb +14 -0
- data/examples/hanoi.rb +4 -5
- data/examples/hello.rb +6 -4
- data/examples/mice.rb +92 -0
- data/examples/mice2.rb +19 -0
- data/examples/n_queens.rb +32 -0
- data/examples/object_oriented.rb +14 -0
- data/examples/palindrome_detection.rb +18 -0
- data/examples/parsing.rb +6 -4
- data/examples/permutation.rb +12 -0
- data/examples/prefix.rb +13 -0
- data/examples/primality_by_division.rb +22 -0
- data/examples/primitives.rb +10 -8
- data/examples/sieve_of_eratosthenes.rb +14 -0
- data/examples/string_interpolation.rb +4 -0
- data/examples/sudoku.rb +52 -0
- data/examples/tracing.rb +19 -0
- data/lib/rspec/rubylog.rb +29 -0
- data/lib/rubylog/assertable.rb +24 -0
- data/lib/rubylog/builtins/arithmetics.rb +63 -0
- data/lib/rubylog/builtins/assumption.rb +71 -0
- data/lib/rubylog/builtins/ensure.rb +13 -0
- data/lib/rubylog/builtins/file_system.rb +30 -8
- data/lib/rubylog/builtins/logic.rb +69 -38
- data/lib/rubylog/builtins/reflection.rb +35 -50
- data/lib/rubylog/builtins/term.rb +15 -17
- data/lib/rubylog/builtins.rb +11 -0
- data/lib/rubylog/clause.rb +19 -0
- data/lib/rubylog/{interfaces/composite_term.rb → compound_term.rb} +3 -3
- data/lib/rubylog/context.rb +24 -0
- data/lib/rubylog/context_creation.rb +71 -0
- data/lib/rubylog/context_modules/checks.rb +35 -0
- data/lib/rubylog/context_modules/demonstration.rb +16 -0
- data/lib/rubylog/context_modules/predicates.rb +86 -0
- data/lib/rubylog/context_modules/primitives.rb +18 -0
- data/lib/rubylog/context_modules/thats.rb +13 -0
- data/lib/rubylog/default_context.rb +9 -0
- data/lib/rubylog/dsl/array_splat.rb +11 -3
- data/lib/rubylog/dsl/primitives.rb +24 -12
- data/lib/rubylog/dsl/thats.rb +6 -0
- data/lib/rubylog/dsl/variables.rb +56 -21
- data/lib/rubylog/errors.rb +26 -15
- data/lib/rubylog/mixins/array.rb +95 -62
- data/lib/rubylog/mixins/kernel.rb +3 -2
- data/lib/rubylog/mixins/method.rb +0 -1
- data/lib/rubylog/mixins/object.rb +2 -1
- data/lib/rubylog/mixins/proc.rb +9 -12
- data/lib/rubylog/mixins/string.rb +15 -23
- data/lib/rubylog/mixins/symbol.rb +7 -24
- data/lib/rubylog/nullary_predicates.rb +3 -0
- data/lib/rubylog/predicate.rb +53 -0
- data/lib/rubylog/primitive.rb +15 -0
- data/lib/rubylog/procedure.rb +42 -0
- data/lib/rubylog/rule.rb +24 -0
- data/lib/rubylog/structure.rb +19 -38
- data/lib/rubylog/{interfaces/term.rb → term.rb} +2 -7
- data/lib/rubylog/tracing.rb +75 -0
- data/lib/rubylog/variable.rb +31 -12
- data/lib/rubylog.rb +36 -32
- data/rubylog.gemspec +92 -84
- data/spec/inriasuite_spec.rb +906 -9
- data/spec/integration/custom_classes_spec.rb +61 -0
- data/spec/integration/dsl_spec.rb +38 -0
- data/spec/integration/recursion_spec.rb +14 -0
- data/spec/integration/theory_as_module_spec.rb +20 -0
- data/spec/integration/theory_as_module_with_include_spec.rb +14 -0
- data/spec/rspec/rubylog_spec.rb +75 -0
- data/spec/rubylog/assertable_spec.rb +111 -0
- data/spec/rubylog/builtins/arithmetics_spec.rb +94 -0
- data/spec/rubylog/builtins/assumption_spec.rb +70 -0
- data/spec/rubylog/builtins/ensure_spec.rb +8 -0
- data/spec/rubylog/builtins/file_system_spec.rb +40 -0
- data/spec/rubylog/builtins/logic_spec.rb +340 -0
- data/spec/rubylog/builtins/reflection_spec.rb +43 -0
- data/spec/rubylog/builtins/term_spec.rb +85 -0
- data/spec/rubylog/context_modules/demonstration_spec.rb +132 -0
- data/spec/rubylog/context_modules/predicates_spec.rb +57 -0
- data/spec/rubylog/context_modules/thats_spec.rb +94 -0
- data/spec/rubylog/dsl/array_splat_spec.rb +15 -0
- data/spec/rubylog/dsl/primitives_spec.rb +43 -0
- data/spec/rubylog/errors_spec.rb +18 -0
- data/spec/{unification_spec.rb → rubylog/interfaces/term_spec.rb} +8 -9
- data/spec/rubylog/mixins/array_spec.rb +80 -0
- data/spec/rubylog/mixins/composite_term_spec.rb +66 -0
- data/spec/rubylog/mixins/proc_spec.rb +59 -0
- data/spec/rubylog/mixins/string_spec.rb +48 -0
- data/spec/rubylog/mixins/symbol_spec.rb +9 -0
- data/spec/{clause_spec.rb → rubylog/structure_spec.rb} +16 -15
- data/spec/rubylog/term_spec.rb +7 -0
- data/spec/rubylog/tracing_spec.input +27 -0
- data/spec/rubylog/tracing_spec.rb +44 -0
- data/spec/rubylog/variable_spec.rb +279 -0
- data/spec/spec_helper.rb +1 -0
- data/vimrc +11 -0
- metadata +103 -123
- data/README.hu.rb +0 -58
- data/bin/rubylog +0 -18
- data/examples/theory.rb +0 -32
- data/lib/rubylog/builtins/default.rb +0 -10
- data/lib/rubylog/dsl.rb +0 -70
- data/lib/rubylog/interfaces/assertable.rb +0 -16
- data/lib/rubylog/interfaces/callable.rb +0 -18
- data/lib/rubylog/interfaces/predicate.rb +0 -8
- data/lib/rubylog/interfaces/procedure.rb +0 -60
- data/lib/rubylog/mixins/class.rb +0 -11
- data/lib/rubylog/simple_procedure.rb +0 -8
- data/lib/rubylog/theory.rb +0 -422
- data/logic/builtins/file_system_logic.rb +0 -23
- data/logic/builtins/reflection_logic.rb +0 -40
- data/logic/dereference_logic.rb +0 -23
- data/logic/dsl_logic.rb +0 -29
- data/logic/errors_logic.rb +0 -9
- data/logic/guard_logic.rb +0 -115
- data/logic/list_logic.rb +0 -55
- data/logic/map_logic.rb +0 -15
- data/logic/multitheory.rb +0 -23
- data/logic/recursion_logic.rb +0 -12
- data/logic/string_logic.rb +0 -41
- data/logic/thats_logic.rb +0 -51
- data/logic/variable_logic.rb +0 -24
- data/spec/bartak_guide_spec.rb +0 -86
- data/spec/builtins/all_spec.rb +0 -99
- data/spec/builtins/and_spec.rb +0 -22
- data/spec/builtins/array_spec.rb +0 -16
- data/spec/builtins/branch_or_spec.rb +0 -27
- data/spec/builtins/cut_spec.rb +0 -44
- data/spec/builtins/fail_spec.rb +0 -5
- data/spec/builtins/false_spec.rb +0 -5
- data/spec/builtins/in_spec.rb +0 -38
- data/spec/builtins/is_false_spec.rb +0 -12
- data/spec/builtins/is_spec.rb +0 -26
- data/spec/builtins/matches_spec.rb +0 -23
- data/spec/builtins/or_spec.rb +0 -22
- data/spec/builtins/splits_to.rb +0 -18
- data/spec/builtins/then_spec.rb +0 -27
- data/spec/builtins/true_spec.rb +0 -5
- data/spec/compilation_spec.rb +0 -61
- data/spec/custom_classes_spec.rb +0 -43
- data/spec/dereference.rb +0 -10
- data/spec/queries_spec.rb +0 -150
- data/spec/recursion_spec.rb +0 -18
- data/spec/ruby_code_spec.rb +0 -52
- data/spec/rules_spec.rb +0 -97
- data/spec/theory_spec.rb +0 -29
- data/spec/variable_spec.rb +0 -26
@@ -0,0 +1,88 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
|
3
|
+
|
4
|
+
rubylog do
|
5
|
+
predicate_for Array, ".on()"
|
6
|
+
|
7
|
+
black, white = 0, 1
|
8
|
+
pawn,rook,knight,bishop,queen,king = :pawn, :rook, :knight, :bishop, :queen, :king
|
9
|
+
|
10
|
+
mark = :mark
|
11
|
+
|
12
|
+
signs = {pawn: "p", rook:"r", knight:"n", bishop:"b", queen:"q", king:"k", mark:"x"}
|
13
|
+
|
14
|
+
[black,pawn] .on! [5,7]
|
15
|
+
[black,bishop].on! [8,1]
|
16
|
+
[black,pawn] .on! [8,5]
|
17
|
+
[black,king] .on! [8,6]
|
18
|
+
|
19
|
+
[white,pawn] .on! [1,7]
|
20
|
+
[white,king] .on! [1,8]
|
21
|
+
[white,bishop].on! [2,8]
|
22
|
+
[white,pawn] .on! [3,7]
|
23
|
+
[white,pawn] .on! [5,5]
|
24
|
+
[white,pawn] .on! [6,6]
|
25
|
+
[white,knight].on! [6,8]
|
26
|
+
[white,bishop].on! [7,2]
|
27
|
+
[white,pawn] .on! [7,7]
|
28
|
+
[white,pawn] .on! [8,4]
|
29
|
+
|
30
|
+
predicate ":show"
|
31
|
+
|
32
|
+
:show.if do
|
33
|
+
(R_.in(1..8).and(R.is{9-R_})).each do
|
34
|
+
F.in(1..8).each do
|
35
|
+
print '.' unless prove [C,P].on([F,R]).and :cut!.and { print C==white ? signs[P].upcase : signs[P]; true }
|
36
|
+
end
|
37
|
+
puts
|
38
|
+
end
|
39
|
+
puts
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
functor_for Rubylog::Structure, :attacks, :can_move_to
|
44
|
+
functor_for Integer, :rook_move, :bishop_move, :squares, :squares_forward
|
45
|
+
prefix_functor :knight_move, :pawn_attack, :pawn_move
|
46
|
+
|
47
|
+
|
48
|
+
[C,king ].on(S).can_move_to(S1).if 1. rook_move(S,S1).or 1.bishop_move(S,S1)
|
49
|
+
[C,queen ].on(S).can_move_to(S1).if ANY. rook_move(S,S1).or ANY.bishop_move(S,S1)
|
50
|
+
[C,bishop ].on(S).can_move_to(S1).if ANY.bishop_move(S,S1)
|
51
|
+
[C,knight ].on(S).can_move_to(S1).if knight_move(S,S1)
|
52
|
+
[C,rook ].on(S).can_move_to(S1).if ANY. rook_move(S,S1)
|
53
|
+
|
54
|
+
[white,pawn].on(S).can_move_to(S1).if pawn_move(S,S1)
|
55
|
+
[black,pawn].on(S).can_move_to(S1).if pawn_move(S1,S)
|
56
|
+
[white,pawn].on([F,2]).can_move_to!([F,4])
|
57
|
+
[black,pawn].on([F,7]).can_move_to!([F,5])
|
58
|
+
|
59
|
+
[white,pawn].on(S).attacks(S1).if! pawn_attack(S,S1)
|
60
|
+
[black,pawn].on(S).attacks(S1).if! pawn_attack(S1,S)
|
61
|
+
X.attacks(S1).if X.can_move_to(S1)
|
62
|
+
|
63
|
+
|
64
|
+
N.squares_forward(A[1..8],B[1..8]).if B.is(A,:+,N)
|
65
|
+
N.squares(A,B).if A.in(1..8).and B.in(1..8).and B.is(A,:+,N).or A.is(B,:+,N)
|
66
|
+
|
67
|
+
N. rook_move([F ,R1],[F ,R2]).if N.squares(R1,R2)
|
68
|
+
N. rook_move([F1,R ],[F2,R ]).if N.squares(F1,F2)
|
69
|
+
N.bishop_move([F1,R1],[F2,R2]).if N.squares(R1,R2).and N.squares(F1,F2)
|
70
|
+
|
71
|
+
knight_move([F1,R1],[F2,R2]).if((1.squares(F1,F2).and 2.squares(R1,R2))
|
72
|
+
.or(1.squares(R1,R2).and 2.squares(F1,F2)))
|
73
|
+
pawn_move( [F ,R1],[F ,R2]).if 1.squares_forward(R1,R2)
|
74
|
+
pawn_attack([F1,R1],[F2,R2]).if R2.is(R1,:+,1).and 1.squares(F1,F2)
|
75
|
+
|
76
|
+
|
77
|
+
functor_for Rubylog::Structure, :moved_to
|
78
|
+
|
79
|
+
[C,P].on(S).moved_to(S1).if [C,P].on(S).and [C,P].on(S).can_move_to(S1).and [C,P].on(S).revoked.and [C,P].on(S1).assumed
|
80
|
+
|
81
|
+
solve :show.and [C,P].on(S).moved_to(S1).and{ puts "#{C} #{P}: #{S} -> #{S1}"; true}.and :show
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for Array, ".choose(,,)"
|
5
|
+
predicate_for Integer, ".one_less_than()"
|
6
|
+
|
7
|
+
N.one_less_than(M).if M.sum_of(N,1)
|
8
|
+
|
9
|
+
L.choose!(0,[],L)
|
10
|
+
[A,*REST].choose(N[thats>0],CHOSEN,[A,*REM]).if REST.choose(N,CHOSEN,REM)
|
11
|
+
[A,*REST].choose(N[thats>0],[A,*CHOSEN],REM).if N1.one_less_than(N).and REST.choose(N1,CHOSEN,REM)
|
12
|
+
|
13
|
+
[1,2,3,4,5].choose(3,L,ANY).each do
|
14
|
+
L.choose(1,[A],REM).each do
|
15
|
+
puts "#{A}: #{REM}"
|
16
|
+
end
|
17
|
+
end
|
data/examples/dcg.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require "rubylog"
|
1
2
|
# This is a quick and dirty solution to replace Prolog's DCG syntax.
|
2
3
|
# It is slow for long inputs. See examples/dcg2.rb for a more efficient algorithm (the same as Prolog's DCG).
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
rubylog do
|
6
|
+
predicate_for Array, ".sentence", ".subject", ".object", ".nominal_phrase", ".noun", ".verb", ".article"
|
6
7
|
|
7
8
|
[*S,*V,*O].sentence.if S.subject.and V.verb.and O.object
|
8
9
|
S.subject.if S.nominal_phrase
|
data/examples/dcg2.rb
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
$:.unshift File.dirname(__FILE__)+"/../lib"
|
5
5
|
require 'rubylog'
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
rubylog do
|
8
|
+
predicate_for Array, ".sentence()", ".subject()", ".object()", ".nominal_phrase()", ".noun()", ".verb()", ".article()"
|
9
9
|
|
10
10
|
# sentence --> subject, verb, object
|
11
11
|
Se.sentence(L3).if Se.subject(L1).and L1.verb(L2).and L2.object(L3)
|
@@ -1,9 +1,7 @@
|
|
1
|
-
require "
|
1
|
+
require "rubylog"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
functor :dir, :contains
|
6
|
-
check_discontiguous false
|
3
|
+
rubylog do
|
4
|
+
predicate_for String, ".dir", ".contains()"
|
7
5
|
|
8
6
|
".git".dir!.contains! "Git repository"
|
9
7
|
"bin".dir!.contains! "executables"
|
data/examples/dirlist.rb
ADDED
data/examples/enumerators.rb
CHANGED
data/examples/factorial.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for String, "FILE.found_in(DIR)"
|
5
|
+
|
6
|
+
FILE.found_in(DIR).if FILE.file_in(DIR)
|
7
|
+
FILE.found_in(DIR).if DIR2[thats_not =~ /\/\./].dir_in(DIR).and FILE.found_in(DIR2)
|
8
|
+
|
9
|
+
"lib/#{X}.rb".found_in("lib").and "lib/#{X}"
|
10
|
+
"#{X}/spec/#{S}_spec.rb".found_in("spec").each do
|
11
|
+
puts S
|
12
|
+
end
|
13
|
+
|
14
|
+
|
data/examples/hanoi.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
2
|
require "rubylog"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
prefix_functor :write_info
|
4
|
+
rubylog do
|
5
|
+
predicate_for Integer, ".move(,,)", ".hanoi"
|
7
6
|
|
8
7
|
0.move(ANY,ANY,ANY).if :cut!
|
9
8
|
N.move(A,B,C).if (
|
@@ -15,10 +14,10 @@ theory do
|
|
15
14
|
N.hanoi.if N.move('left', 'right', 'center')
|
16
15
|
|
17
16
|
puts "\nWhat's the solution for a single disc?"
|
18
|
-
|
17
|
+
solve 1.hanoi
|
19
18
|
|
20
19
|
puts "\n\nWhat's the solution for 5 discs?"
|
21
|
-
|
20
|
+
solve 5.hanoi
|
22
21
|
|
23
22
|
|
24
23
|
end
|
data/examples/hello.rb
CHANGED
@@ -3,13 +3,15 @@ $:.unshift File.dirname(__FILE__)+"/../lib"
|
|
3
3
|
require 'rubylog'
|
4
4
|
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
rubylog do
|
7
|
+
predicate_for String, ".written :hello"
|
8
8
|
|
9
9
|
X.written.if {puts X; true}
|
10
10
|
|
11
|
-
:hello.if "Hello
|
11
|
+
:hello.if "Hello world!".written
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
rubylog do
|
15
|
+
solve :hello
|
16
|
+
end
|
15
17
|
|
data/examples/mice.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.dirname(__FILE__)+"/../lib"
|
3
|
+
# This is a solution for a math problem.
|
4
|
+
#
|
5
|
+
# Mafia the black cat plays a game. She has N cups with 0 or 1 mouse under each.
|
6
|
+
# She peeks under some cups one by one to see if there is a mouse under them.
|
7
|
+
# What she wants to find out is whether there are two cups next to each other
|
8
|
+
# which both have a mouse. She found that for some number of cups she has to
|
9
|
+
# peek under every cup to decide if there are two adjacent ones with a mouse.
|
10
|
+
# In this case she considers the task hard. For which N's does she consider it
|
11
|
+
# hard (N<=2013)?
|
12
|
+
|
13
|
+
require "rubylog"
|
14
|
+
require "rubylog/builtins/assumption"
|
15
|
+
extend Rubylog::Context
|
16
|
+
|
17
|
+
|
18
|
+
class Cup < Struct.new :i
|
19
|
+
extend Rubylog::Context
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"##{i}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# A cup can be peeked: it has mouse or not
|
26
|
+
predicate %w(.peeked .has_mouse .seen )
|
27
|
+
C.peeked.if C.has_mouse.assumed.or(:true).and C.seen.assumed
|
28
|
+
|
29
|
+
# A cup can be guessed: it has mouse or not
|
30
|
+
predicate %w(.guessed)
|
31
|
+
C.guessed.if C.has_mouse.assumed.or(:true)
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
class CupSet
|
37
|
+
extend Rubylog::Context
|
38
|
+
|
39
|
+
def initialize n
|
40
|
+
@cups = (1..n).map {|i| Cup.new i }
|
41
|
+
end
|
42
|
+
|
43
|
+
def each &block
|
44
|
+
@cups.each &block
|
45
|
+
end
|
46
|
+
|
47
|
+
def [] index
|
48
|
+
@cups[index]
|
49
|
+
end
|
50
|
+
|
51
|
+
# A set has neighbors if
|
52
|
+
predicate %w(.has_neighbors)
|
53
|
+
CS.has_neighbors.if [C,D].in{CS[0..-2].zip(CS[1..-1] || [])}.and C.has_mouse.and D.has_mouse
|
54
|
+
|
55
|
+
# A predicate definitely solves a set if there is no ambiguity
|
56
|
+
predicate_for Rubylog::Clause, %w(.definitely_solves())
|
57
|
+
T.definitely_solves(CS).if T.any(CS.has_neighbors).and(T.any(CS.has_neighbors.false)).false
|
58
|
+
|
59
|
+
# A trial consist of peeking some cups
|
60
|
+
predicate_for Rubylog::Clause, %w(.trial_for())
|
61
|
+
T.trial_for(CS).if T.is{C.in(CS).map{C.peeked.or :true}.inject(:true,&:and)}.and T
|
62
|
+
|
63
|
+
# A set is easy if can be definitely solved by a trial that has not seen all
|
64
|
+
# cups. A set is had if it cannot.
|
65
|
+
predicate %w(.easy() .hard)
|
66
|
+
CS.easy(Peeks).if any T.trial_for(CS).and(C.in(CS).all(C.seen).false).definitely_solves(CS).and(Peeks.is{D.in(CS).and(D.peeked).map{D}})
|
67
|
+
CS.hard.if CS.easy.false
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
N.in(0..4).each do
|
73
|
+
puts "#{N}:"
|
74
|
+
CS.is{CupSet.new(N)}.each do
|
75
|
+
|
76
|
+
C.in{CS}.each { p C }
|
77
|
+
T.trial_for(CS).each { p T }
|
78
|
+
|
79
|
+
easy = false
|
80
|
+
CS.easy(Peeks).each do
|
81
|
+
puts "easy: #{Peeks.inspect}"
|
82
|
+
easy = true
|
83
|
+
end
|
84
|
+
puts "hard" if not easy
|
85
|
+
end
|
86
|
+
puts
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
|
data/examples/mice2.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for Array, ".array(N) Peek.matches(Guess)"
|
5
|
+
|
6
|
+
[].peek!(0)
|
7
|
+
[K,*REST].mice(N[thats>0]).if K.in([0,1]).and N.sum_of(N1,1).and REST.mice(N1)
|
8
|
+
|
9
|
+
[].seen!([])
|
10
|
+
[0,*REST].seen([nil,*REST2]).if REST.seen(REST2)
|
11
|
+
[1,*REST].seen([A,*REST2]).if A.in([0,1]).and REST.seen(REST2)
|
12
|
+
|
13
|
+
[].guess!([])
|
14
|
+
[nil,*REST].guess([A,*REST2]).if A.in([0,1]).and REST.guess(REST2)
|
15
|
+
[0,*REST].guess([0,*REST2]).if A.in([0,1]).and REST.guess(REST2)
|
16
|
+
[1,*REST].guess([1,*REST2]).if A.in([0,1]).and REST.guess(REST2)
|
17
|
+
|
18
|
+
solve N.is(6).and any Peek.peek(N), all(Peek.seen(Seen), all(Guess.guess(Seen), Guess.has_neighbors.false).or(all(Guess.guess(Seen), Guess.has_neighbors)))
|
19
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
|
+
require "rubylog"
|
3
|
+
|
4
|
+
rubylog do
|
5
|
+
predicate_for Integer, ".on(,)", ".attacks(,)", ".placed"
|
6
|
+
predicate ":arranged"
|
7
|
+
|
8
|
+
N=7
|
9
|
+
|
10
|
+
A.attacks(R,ANY_C).if A.on(R,ANY_C)
|
11
|
+
A.attacks(ANY_R,C).if A.on(ANY_R,C)
|
12
|
+
A.attacks(R2,C2).if A.on(R1,C1).and {R1-C1==R2-C2}
|
13
|
+
A.attacks(R2,C2).if A.on(R1,C1).and {R1+C1==R2+C2}
|
14
|
+
|
15
|
+
A.placed.if \
|
16
|
+
C.in(1..N).and(B.on(ANY,ANY).none(B.attacks(A,C))).and A.on(A,C).assumed
|
17
|
+
|
18
|
+
:arranged.if every A.in(1..N), A.placed
|
19
|
+
|
20
|
+
:arranged.solve do
|
21
|
+
L.in(1..N).each do
|
22
|
+
M.in(1..N).each do
|
23
|
+
print ANY.on?(L,M) ? "X" : "."
|
24
|
+
end
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
puts
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for String, ".palindrome"
|
5
|
+
|
6
|
+
S[length: 0..1].palindrome!
|
7
|
+
S.palindrome.if S.is("#{A[length: 1]}#{B}#{A}").and B.palindrome
|
8
|
+
|
9
|
+
check "".palindrome
|
10
|
+
check "a".palindrome
|
11
|
+
check "aa".palindrome
|
12
|
+
check "aba".palindrome
|
13
|
+
check "abba".palindrome
|
14
|
+
check "ababa".palindrome
|
15
|
+
check "ab".palindrome.false
|
16
|
+
check "abb".palindrome.false
|
17
|
+
check "abbc".palindrome.false
|
18
|
+
check "ababab".palindrome.false
|
data/examples/parsing.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
|
+
require "rubylog"
|
1
3
|
require "readline"
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
+
rubylog do
|
6
|
+
predicate_for String, ".term()", ".expr()", ".atom()"
|
5
7
|
|
6
|
-
"#{A}+#{B}".expr(K).if A.
|
7
|
-
"#{A}-#{B}".expr(K).if A.
|
8
|
+
"#{A}+#{B}".expr(K).if A.expr(I).and B.term(J).and K.is{I+J}
|
9
|
+
"#{A}-#{B}".expr(K).if A.expr(I).and B.term(J).and K.is{I-J}
|
8
10
|
A.expr(K).if A.term(K)
|
9
11
|
"#{A}*#{B}".term(K).if A.atom(I).and B.term(J).and K.is{I*J}
|
10
12
|
"#{A}/#{B}".term(K).if A.atom(I).and B.term(J).and K.is{I/J}
|
data/examples/prefix.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for Integer, ".prime .odd .divides()"
|
5
|
+
|
6
|
+
A.divides(B).if { B%A == 0 }
|
7
|
+
A.odd.if 2.divides(A).false
|
8
|
+
|
9
|
+
2.prime!
|
10
|
+
N[thats>2].prime.if N.odd.and none D[thats.odd?].in{3..Math.sqrt(N)}, D.divides(N)
|
11
|
+
|
12
|
+
check 1.prime.false
|
13
|
+
check 2.prime
|
14
|
+
check 3.prime
|
15
|
+
check 4.prime.false
|
16
|
+
check 5.prime
|
17
|
+
check 6.prime.false
|
18
|
+
check 7.prime
|
19
|
+
check 8.prime.false
|
20
|
+
check 9.prime.false
|
21
|
+
check 10.prime.false
|
22
|
+
|
data/examples/primitives.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
2
|
require 'rubylog'
|
3
3
|
|
4
|
-
Rubylog.
|
5
|
-
|
4
|
+
Try = Rubylog.create_context
|
5
|
+
Try.instance_eval do
|
6
|
+
predicate ":hello_world"
|
6
7
|
|
7
8
|
def primitives.hello
|
8
9
|
puts "Hello"
|
9
10
|
yield
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
class << primitives_for(String)
|
14
|
+
def hello x
|
15
|
+
puts "Hello #{x.rubylog_deep_dereference}!"
|
16
|
+
yield
|
17
|
+
end
|
15
18
|
end
|
16
19
|
|
17
20
|
:hello_world.if "World".hello
|
@@ -19,6 +22,5 @@ Rubylog.theory "Try" do
|
|
19
22
|
end
|
20
23
|
|
21
24
|
|
22
|
-
p Try.
|
23
|
-
p Try.
|
24
|
-
p Try.prove{X.is("World").and X.hello}
|
25
|
+
p Try.true? :hello
|
26
|
+
p Try.true? :hello_world
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "rubylog"
|
2
|
+
extend Rubylog::Context
|
3
|
+
|
4
|
+
predicate_for Integer, ".sieve .prime .nonprime .multiple_of(N,Limit)"
|
5
|
+
|
6
|
+
A.multiple_of(N,Limit).if I.in{(0..Limit/N)}.and A.is{N*I}
|
7
|
+
|
8
|
+
N.sieve.if X.in{2..N}.all X.nonprime.or(
|
9
|
+
proc{X.prime!}.and M.multiple_of(X,N).all{M.nonprime!}
|
10
|
+
)
|
11
|
+
|
12
|
+
100.sieve.solve
|
13
|
+
|
14
|
+
p A.in(1..100).and(A.prime).map{A}
|
data/examples/sudoku.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
|
+
require "rubylog"
|
3
|
+
|
4
|
+
class Sudoku
|
5
|
+
def initialize
|
6
|
+
@rows = (1..9).map{(1..9).map{Rubylog::Variable.new}}
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :rows
|
10
|
+
|
11
|
+
def columns
|
12
|
+
@rows.transpose
|
13
|
+
end
|
14
|
+
|
15
|
+
def blocks
|
16
|
+
(0..2).map {|a| (0..2).map {|b| (0..2).map {|c| (0..2).map {|d|
|
17
|
+
@rows[a*3+c][b*3+d]
|
18
|
+
}}.flatten(1) }}.flatten(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
extend Rubylog::Context
|
22
|
+
|
23
|
+
predicate_for Array, ".unique"
|
24
|
+
L.unique.unless L.is [*ANY, X, *ANY, X, *ANY]
|
25
|
+
|
26
|
+
predicate ".solved .good .shown .given(s)"
|
27
|
+
S.solved.if every L.in{S.rows}.and(F.in(L)), F.in(1..9)
|
28
|
+
S.good.if all(T.in{[S.rows, S.columns, S.blocks]}.and(L.in{T}), L.unique)
|
29
|
+
|
30
|
+
S.shown.if do
|
31
|
+
L.in{S.rows}.each do
|
32
|
+
p L
|
33
|
+
end
|
34
|
+
puts
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
_=ANY
|
39
|
+
solve S.is{Sudoku.new}.and lambda{S.rows}.is([
|
40
|
+
[5,_,_,_,2,4,7,_,_],
|
41
|
+
[_,_,2,_,_,_,8,_,_],
|
42
|
+
[1,_,_,7,_,3,9,_,2],
|
43
|
+
[_,_,8,_,7,2,_,4,9],
|
44
|
+
[_,2,_,9,8,_,_,7,_],
|
45
|
+
[7,9,_,_,_,_,_,8,_],
|
46
|
+
[_,_,_,_,3,_,5,_,6],
|
47
|
+
[9,6,_,_,1,_,3,_,_],
|
48
|
+
[_,5,_,6,9,_,_,1,_]
|
49
|
+
]).and S.solved.and S.good.and S.shown rescue p $!
|
50
|
+
end
|
51
|
+
|
52
|
+
|
data/examples/tracing.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)+"/../lib"
|
2
|
+
require "rubylog"
|
3
|
+
extend Rubylog::Context
|
4
|
+
|
5
|
+
# no trace
|
6
|
+
solve S.is("Hello #{X}!").and X.is("no Trace") do puts S end
|
7
|
+
|
8
|
+
# tracing with on/off
|
9
|
+
Rubylog.trace!
|
10
|
+
solve S.is("Hello #{X}!").and X.is("Trace") do puts S end
|
11
|
+
Rubylog.trace!(false)
|
12
|
+
|
13
|
+
# no trace again
|
14
|
+
solve S.is("Hello #{X}!").and X.is("no Trace again") do puts S end
|
15
|
+
|
16
|
+
# tracing with block
|
17
|
+
Rubylog.trace do
|
18
|
+
solve S.is("Hello #{X}!").and X.is("Trace with block") do puts S end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require "rubylog"
|
3
|
+
|
4
|
+
# This module is included in RSpecExampleGroup's with rubylog:true metadata.
|
5
|
+
#
|
6
|
+
module Rubylog::RSpecExampleGroup
|
7
|
+
def self.included example_group
|
8
|
+
# Make it a context
|
9
|
+
example_group.extend Rubylog::Context
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec.configure do |c|
|
14
|
+
|
15
|
+
# enable use of Rubylog in example groups
|
16
|
+
c.include Rubylog::RSpecExampleGroup, :rubylog => true
|
17
|
+
|
18
|
+
# enable use of Rubylog in examples
|
19
|
+
c.before do
|
20
|
+
# when :rubylog=>true is given
|
21
|
+
if self.class.metadata[:rubylog]
|
22
|
+
# create the context from the example
|
23
|
+
# this initializes the context
|
24
|
+
Rubylog.create_context self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|