rubylog 1.0.0 → 2.0pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (163) hide show
  1. data/Gemfile +3 -12
  2. data/Gemfile.lock +22 -48
  3. data/README.rdoc +38 -38
  4. data/README.rdoc.orig +284 -0
  5. data/RELEASE_NOTES.rdoc +51 -0
  6. data/Rakefile +14 -18
  7. data/TODO.txt +0 -0
  8. data/VERSION +1 -1
  9. data/examples/a_plus_b.rb +6 -0
  10. data/examples/checkmate.rb +88 -0
  11. data/examples/combination.rb +17 -0
  12. data/examples/dcg.rb +3 -2
  13. data/examples/dcg2.rb +2 -2
  14. data/{logic → examples}/directory_structure_logic.rb +3 -5
  15. data/examples/dirlist.rb +4 -0
  16. data/examples/divisors.rb +6 -0
  17. data/examples/enumerators.rb +3 -3
  18. data/examples/factorial.rb +2 -3
  19. data/examples/file_search.rb +14 -0
  20. data/examples/hanoi.rb +4 -5
  21. data/examples/hello.rb +6 -4
  22. data/examples/mice.rb +92 -0
  23. data/examples/mice2.rb +19 -0
  24. data/examples/n_queens.rb +32 -0
  25. data/examples/object_oriented.rb +14 -0
  26. data/examples/palindrome_detection.rb +18 -0
  27. data/examples/parsing.rb +6 -4
  28. data/examples/permutation.rb +12 -0
  29. data/examples/prefix.rb +13 -0
  30. data/examples/primality_by_division.rb +22 -0
  31. data/examples/primitives.rb +10 -8
  32. data/examples/sieve_of_eratosthenes.rb +14 -0
  33. data/examples/string_interpolation.rb +4 -0
  34. data/examples/sudoku.rb +52 -0
  35. data/examples/tracing.rb +19 -0
  36. data/lib/rspec/rubylog.rb +29 -0
  37. data/lib/rubylog/assertable.rb +24 -0
  38. data/lib/rubylog/builtins/arithmetics.rb +63 -0
  39. data/lib/rubylog/builtins/assumption.rb +71 -0
  40. data/lib/rubylog/builtins/ensure.rb +13 -0
  41. data/lib/rubylog/builtins/file_system.rb +30 -8
  42. data/lib/rubylog/builtins/logic.rb +69 -38
  43. data/lib/rubylog/builtins/reflection.rb +35 -50
  44. data/lib/rubylog/builtins/term.rb +15 -17
  45. data/lib/rubylog/builtins.rb +11 -0
  46. data/lib/rubylog/clause.rb +19 -0
  47. data/lib/rubylog/{interfaces/composite_term.rb → compound_term.rb} +3 -3
  48. data/lib/rubylog/context.rb +24 -0
  49. data/lib/rubylog/context_creation.rb +71 -0
  50. data/lib/rubylog/context_modules/checks.rb +35 -0
  51. data/lib/rubylog/context_modules/demonstration.rb +16 -0
  52. data/lib/rubylog/context_modules/predicates.rb +86 -0
  53. data/lib/rubylog/context_modules/primitives.rb +18 -0
  54. data/lib/rubylog/context_modules/thats.rb +13 -0
  55. data/lib/rubylog/default_context.rb +9 -0
  56. data/lib/rubylog/dsl/array_splat.rb +11 -3
  57. data/lib/rubylog/dsl/primitives.rb +24 -12
  58. data/lib/rubylog/dsl/thats.rb +6 -0
  59. data/lib/rubylog/dsl/variables.rb +56 -21
  60. data/lib/rubylog/errors.rb +26 -15
  61. data/lib/rubylog/mixins/array.rb +95 -62
  62. data/lib/rubylog/mixins/kernel.rb +3 -2
  63. data/lib/rubylog/mixins/method.rb +0 -1
  64. data/lib/rubylog/mixins/object.rb +2 -1
  65. data/lib/rubylog/mixins/proc.rb +9 -12
  66. data/lib/rubylog/mixins/string.rb +15 -23
  67. data/lib/rubylog/mixins/symbol.rb +7 -24
  68. data/lib/rubylog/nullary_predicates.rb +3 -0
  69. data/lib/rubylog/predicate.rb +53 -0
  70. data/lib/rubylog/primitive.rb +15 -0
  71. data/lib/rubylog/procedure.rb +42 -0
  72. data/lib/rubylog/rule.rb +24 -0
  73. data/lib/rubylog/structure.rb +19 -38
  74. data/lib/rubylog/{interfaces/term.rb → term.rb} +2 -7
  75. data/lib/rubylog/tracing.rb +75 -0
  76. data/lib/rubylog/variable.rb +31 -12
  77. data/lib/rubylog.rb +36 -32
  78. data/rubylog.gemspec +92 -84
  79. data/spec/inriasuite_spec.rb +906 -9
  80. data/spec/integration/custom_classes_spec.rb +61 -0
  81. data/spec/integration/dsl_spec.rb +38 -0
  82. data/spec/integration/recursion_spec.rb +14 -0
  83. data/spec/integration/theory_as_module_spec.rb +20 -0
  84. data/spec/integration/theory_as_module_with_include_spec.rb +14 -0
  85. data/spec/rspec/rubylog_spec.rb +75 -0
  86. data/spec/rubylog/assertable_spec.rb +111 -0
  87. data/spec/rubylog/builtins/arithmetics_spec.rb +94 -0
  88. data/spec/rubylog/builtins/assumption_spec.rb +70 -0
  89. data/spec/rubylog/builtins/ensure_spec.rb +8 -0
  90. data/spec/rubylog/builtins/file_system_spec.rb +40 -0
  91. data/spec/rubylog/builtins/logic_spec.rb +340 -0
  92. data/spec/rubylog/builtins/reflection_spec.rb +43 -0
  93. data/spec/rubylog/builtins/term_spec.rb +85 -0
  94. data/spec/rubylog/context_modules/demonstration_spec.rb +132 -0
  95. data/spec/rubylog/context_modules/predicates_spec.rb +57 -0
  96. data/spec/rubylog/context_modules/thats_spec.rb +94 -0
  97. data/spec/rubylog/dsl/array_splat_spec.rb +15 -0
  98. data/spec/rubylog/dsl/primitives_spec.rb +43 -0
  99. data/spec/rubylog/errors_spec.rb +18 -0
  100. data/spec/{unification_spec.rb → rubylog/interfaces/term_spec.rb} +8 -9
  101. data/spec/rubylog/mixins/array_spec.rb +80 -0
  102. data/spec/rubylog/mixins/composite_term_spec.rb +66 -0
  103. data/spec/rubylog/mixins/proc_spec.rb +59 -0
  104. data/spec/rubylog/mixins/string_spec.rb +48 -0
  105. data/spec/rubylog/mixins/symbol_spec.rb +9 -0
  106. data/spec/{clause_spec.rb → rubylog/structure_spec.rb} +16 -15
  107. data/spec/rubylog/term_spec.rb +7 -0
  108. data/spec/rubylog/tracing_spec.input +27 -0
  109. data/spec/rubylog/tracing_spec.rb +44 -0
  110. data/spec/rubylog/variable_spec.rb +279 -0
  111. data/spec/spec_helper.rb +1 -0
  112. data/vimrc +11 -0
  113. metadata +103 -123
  114. data/README.hu.rb +0 -58
  115. data/bin/rubylog +0 -18
  116. data/examples/theory.rb +0 -32
  117. data/lib/rubylog/builtins/default.rb +0 -10
  118. data/lib/rubylog/dsl.rb +0 -70
  119. data/lib/rubylog/interfaces/assertable.rb +0 -16
  120. data/lib/rubylog/interfaces/callable.rb +0 -18
  121. data/lib/rubylog/interfaces/predicate.rb +0 -8
  122. data/lib/rubylog/interfaces/procedure.rb +0 -60
  123. data/lib/rubylog/mixins/class.rb +0 -11
  124. data/lib/rubylog/simple_procedure.rb +0 -8
  125. data/lib/rubylog/theory.rb +0 -422
  126. data/logic/builtins/file_system_logic.rb +0 -23
  127. data/logic/builtins/reflection_logic.rb +0 -40
  128. data/logic/dereference_logic.rb +0 -23
  129. data/logic/dsl_logic.rb +0 -29
  130. data/logic/errors_logic.rb +0 -9
  131. data/logic/guard_logic.rb +0 -115
  132. data/logic/list_logic.rb +0 -55
  133. data/logic/map_logic.rb +0 -15
  134. data/logic/multitheory.rb +0 -23
  135. data/logic/recursion_logic.rb +0 -12
  136. data/logic/string_logic.rb +0 -41
  137. data/logic/thats_logic.rb +0 -51
  138. data/logic/variable_logic.rb +0 -24
  139. data/spec/bartak_guide_spec.rb +0 -86
  140. data/spec/builtins/all_spec.rb +0 -99
  141. data/spec/builtins/and_spec.rb +0 -22
  142. data/spec/builtins/array_spec.rb +0 -16
  143. data/spec/builtins/branch_or_spec.rb +0 -27
  144. data/spec/builtins/cut_spec.rb +0 -44
  145. data/spec/builtins/fail_spec.rb +0 -5
  146. data/spec/builtins/false_spec.rb +0 -5
  147. data/spec/builtins/in_spec.rb +0 -38
  148. data/spec/builtins/is_false_spec.rb +0 -12
  149. data/spec/builtins/is_spec.rb +0 -26
  150. data/spec/builtins/matches_spec.rb +0 -23
  151. data/spec/builtins/or_spec.rb +0 -22
  152. data/spec/builtins/splits_to.rb +0 -18
  153. data/spec/builtins/then_spec.rb +0 -27
  154. data/spec/builtins/true_spec.rb +0 -5
  155. data/spec/compilation_spec.rb +0 -61
  156. data/spec/custom_classes_spec.rb +0 -43
  157. data/spec/dereference.rb +0 -10
  158. data/spec/queries_spec.rb +0 -150
  159. data/spec/recursion_spec.rb +0 -18
  160. data/spec/ruby_code_spec.rb +0 -52
  161. data/spec/rules_spec.rb +0 -97
  162. data/spec/theory_spec.rb +0 -29
  163. 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
- theory do
5
- functor_for Array, :sentence, :subject, :object, :nominal_phrase, :noun, :verb, :article
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
- theory do
8
- functor_for Array, :sentence, :subject, :object, :nominal_phrase, :noun, :verb, :article
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 "./lib/rubylog/builtins/file_system"
1
+ require "rubylog"
2
2
 
3
- theory do
4
- subject String
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"
@@ -0,0 +1,4 @@
1
+ require "rubylog"
2
+ extend Rubylog::Context
3
+
4
+
@@ -0,0 +1,6 @@
1
+ $:.unshift File.dirname(__FILE__)+"/../lib"
2
+ require "rubylog"
3
+
4
+ extend Rubylog::Context
5
+
6
+ p (P.is(672).and A.in{1..P}.and P.product_of(A,B).and{A<=B}).count
@@ -1,9 +1,9 @@
1
1
  $:.unshift File.dirname(__FILE__)+"/../lib"
2
2
  require 'rubylog'
3
3
 
4
- theory do
5
- subject Symbol
6
- functor :likes
4
+ rubylog do
5
+ self.default_subject = Symbol
6
+ predicate ".likes()"
7
7
 
8
8
  :john.likes! :beer
9
9
  :john.likes! :milk
@@ -1,9 +1,8 @@
1
1
  $:.unshift File.dirname(__FILE__)+"/../lib"
2
2
  require 'rubylog'
3
3
 
4
- FactorialTheory = theory do
5
- subject Integer
6
- functor :factorial
4
+ rubylog do
5
+ predicate_for Integer, ".factorial()"
7
6
 
8
7
  0.factorial! 1
9
8
  N[thats > 0].factorial(K).if \
@@ -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
- theory do
5
- functor_for Integer, :move, :hanoi
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
- prove 1.hanoi
17
+ solve 1.hanoi
19
18
 
20
19
  puts "\n\nWhat's the solution for 5 discs?"
21
- prove 5.hanoi
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
- HelloTheory = theory do
7
- functor_for String, :written
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, world!".written
11
+ :hello.if "Hello world!".written
12
12
  end
13
13
 
14
- HelloTheory.prove :hello
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,14 @@
1
+ $:.unshift File.dirname(__FILE__)+"/../lib"
2
+ require "rubylog"
3
+
4
+ class User
5
+ extend Rubylog::Context
6
+ predicate_for self, ".user", ".admin"
7
+
8
+ def initialize admin=false
9
+ self.user!
10
+ self.admin! if admin
11
+ end
12
+ end
13
+
14
+
@@ -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
- theory do
4
- functor_for String, :term, :expr, :atom
5
+ rubylog do
6
+ predicate_for String, ".term()", ".expr()", ".atom()"
5
7
 
6
- "#{A}+#{B}".expr(K).if A.term(I).and B.expr(J).and K.is{I+J}
7
- "#{A}-#{B}".expr(K).if A.term(I).and B.expr(J).and K.is{I-J}
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}
@@ -0,0 +1,12 @@
1
+ require "rubylog"
2
+ extend Rubylog::Context
3
+ predicate_for Array, ".permutation()"
4
+
5
+ [].permutation! []
6
+ [*FRONT, A, *BACK].permutation([A,*REST]).if [*FRONT,*BACK].permutation(REST)
7
+
8
+ [1,2,3,4].permutation(P).each do
9
+ p P
10
+ end
11
+
12
+
@@ -0,0 +1,13 @@
1
+ require "rubylog"
2
+ extend Rubylog::Context
3
+
4
+ predicate_for Kernel, ".hello()"
5
+
6
+ hello!(2)
7
+ hello(5).if { puts "Hello" }
8
+
9
+ hello?(5)
10
+
11
+ check hello(2)
12
+ check hello(4).false
13
+
@@ -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
+
@@ -1,17 +1,20 @@
1
1
  $:.unshift File.dirname(__FILE__)+"/../lib"
2
2
  require 'rubylog'
3
3
 
4
- Rubylog.theory "Try" do
5
- subject String
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
- def primitives.hello x
13
- puts "Hello #{x.rubylog_deep_dereference}!"
14
- yield
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.prove :hello
23
- p Try.prove :hello_world
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}
@@ -0,0 +1,4 @@
1
+ require "rubylog"
2
+ extend Rubylog::Context
3
+
4
+ solve S.is("Mary had a #{X} lamb.").and X.is("little").and { puts S }
@@ -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
+
@@ -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
+