rubylog 1.0.0 → 2.0pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|