<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -5,11 +5,21 @@ require 'eliza1'
 require 'pat_read'
 require 'pat_match'
 
-Exp = Struct.new(:lhs, :op, :rhs)
-
 Pattern.match_abbrev(:&quot;?x*&quot;, %w(?* ?x))
 Pattern.match_abbrev(:&quot;?y*&quot;, %w(?* ?y))
 
+def exp_rhs(exp)
+  exp[2]
+end
+
+def exp_op(exp)
+  exp[1]
+end
+
+def exp_lhs(exp)
+  exp[0]
+end
+
 class Rule
   def self.split(obj)
     case obj
@@ -29,13 +39,13 @@ class Rule
      [&quot;if ?x* then ?y*&quot;,               &quot;?x ?y&quot;],
      [&quot;if ?x* , ?y*&quot;,                  &quot;?x ?y&quot;],
      [&quot;?x* , and ?y*&quot;,                 &quot;?x ?y&quot;],
-     [&quot;find ?x* and ?y*&quot;,             [&quot;to_find_1 == ?x&quot;, &quot;to_find_2 == ?y&quot;]],
-     [&quot;find ?x*&quot;,                      &quot;to_find == ?x&quot;],
-     [&quot;?x* equals ?y*&quot;,                &quot;?x == ?y&quot;],
-     [&quot;?x* same as ?y*&quot;,               &quot;?x == ?y&quot;],
-     [&quot;?x* = ?y*&quot;,                     &quot;?x == ?y&quot;],
-     [&quot;?x* is equal to ?y*&quot;,           &quot;?x == ?y&quot;],
-     [&quot;?x* is ?y*&quot;,                    &quot;?x == ?y&quot;],
+     [&quot;find ?x* and ?y*&quot;,             [&quot;to_find_1 = ?x&quot;, &quot;to_find_2 = ?y&quot;]],
+     [&quot;find ?x*&quot;,                      &quot;to_find = ?x&quot;],
+     [&quot;?x* equals ?y*&quot;,                &quot;?x = ?y&quot;],
+     [&quot;?x* same as ?y*&quot;,               &quot;?x = ?y&quot;],
+     [&quot;?x* = ?y*&quot;,                     &quot;?x = ?y&quot;],
+     [&quot;?x* is equal to ?y*&quot;,           &quot;?x = ?y&quot;],
+     [&quot;?x* is ?y*&quot;,                    &quot;?x = ?y&quot;],
      [&quot;?x* - ?y*&quot;,                     &quot;?x - ?y&quot;],
      [&quot;?x* minus ?y*&quot;,                 &quot;?x - ?y&quot;],
      [&quot;difference between ?x* and ?y*&quot;,&quot;?x - ?y&quot;],
@@ -53,9 +63,9 @@ class Rule
      [&quot;one half ?x*&quot;,                  &quot;?x / ?y&quot;],
      [&quot;twice ?x*&quot;,                     &quot;2 * ?x&quot;],
      [&quot;square ?x*&quot;,                    &quot;?x * ?x&quot;],
-     [&quot;?x* % less than ?y*&quot;,          [&quot;?y&quot;, &quot;*&quot;, [[&quot;100 - ?x&quot;], &quot;/&quot;, &quot;100&quot;]]],
-     [&quot;?x* % more than ?y*&quot;,          [&quot;?y&quot;, &quot;*&quot;, [[&quot;100 + ?x&quot;], &quot;/&quot;, &quot;100&quot;]]],
-     [&quot;?x* % ?y*&quot;,                    [&quot;?x / 100&quot;, &quot;*&quot;, &quot;?y&quot;]]
+     [&quot;?x* % less than ?y*&quot;,          [&quot;?y&quot;, &quot;*&quot;, [[&quot;100.0 - ?x&quot;], &quot;/&quot;, &quot;100.0&quot;]]],
+     [&quot;?x* % more than ?y*&quot;,          [&quot;?y&quot;, &quot;*&quot;, [[&quot;100.0 + ?x&quot;], &quot;/&quot;, &quot;100.0&quot;]]],
+     [&quot;?x* % ?y*&quot;,                    [&quot;?x / 100.0&quot;, &quot;*&quot;, &quot;?y&quot;]]
     ].map{ |s| [Pattern.from_string(s[0]), split(s[1])]}
 end
 
@@ -115,6 +125,129 @@ module Student
     def translate_pair(first, second)
       [first, translate_to_expression(second)]
     end
+
+    def list_repr(l)
+      case l
+      when Array
+        &quot;(#{l.map{ |x| list_repr(x) }.join(&quot; &quot;)})&quot;
+      else
+        l.to_s
+      end
+    end
+    
+    def print_equations(header, equations)
+      puts header
+      equations.each do |eq|
+        print &quot;  &quot;
+        eq.each do |ee|
+          print &quot; #{list_repr(ee)}&quot;
+        end
+        puts
+      end
+    end
+    
+    def solve_equations(equations)
+      print_equations(&quot;The equations to be solved are: &quot;, equations)
+      print_equations(&quot;The solution is: &quot;, solve_eq(equations, []))
+    end
+
+    def unknown?(exp)
+      (exp.is_a?(String) &amp;&amp; !(Integer(exp) rescue nil)  &amp;&amp; !(Float(exp) rescue nil))
+    end
+
+    def no_unknown(exp)
+      case 
+      when unknown?(exp)
+        nil
+      when !exp.is_a?(Array) || exp.empty?
+        true
+      when no_unknown(exp_lhs(exp))
+        no_unknown(exp_rhs(exp))
+      else
+        nil
+      end
+    end
+
+    def solve_arithmetic(eq)
+      [exp_lhs(eq), &quot;=&quot;, eval(list_repr(exp_rhs(eq)))]
+    end
+    
+    def one_unknown(exp)
+      case
+      when unknown?(exp)
+        exp
+      when !exp.is_a?(Array) || exp.empty?
+        nil
+      when no_unknown(exp_lhs(exp))
+        one_unknown(exp_rhs(exp))
+      when no_unknown(exp_rhs(exp))
+        one_unknown(exp_lhs(exp))
+      else
+        nil
+      end
+    end
+
+    def exp?(exp)
+      exp.is_a?(Array) &amp;&amp; exp.length == 3
+    end
+    
+    def in_exp(x, exp)
+      x == exp ||
+        (exp?(exp) &amp;&amp; (in_exp(x, exp_lhs(exp)) || in_exp(x, exp_rhs(exp))))
+    end
+    
+    def inverse_op(op)
+      { 
+        '+' =&gt; '-',
+        '-' =&gt; '+',
+        '*'  =&gt; '/',
+        '/'  =&gt; '*',
+        '='  =&gt; '='
+      }[op]
+    end
+    
+    def commutative?(op)
+      %w(+ * =).include?(op)
+    end
+    
+    def isolate(e, x)
+      case 
+      when exp_lhs(e) == x
+        e
+      when in_exp(x, exp_rhs(e))
+        isolate([exp_rhs(e), &quot;=&quot;, exp_lhs(e)], x)
+      when in_exp(x, exp_lhs(exp_lhs(e)))
+        isolate([exp_lhs(exp_lhs(e)), 
+                 &quot;=&quot;, 
+                 [exp_rhs(e), 
+                  inverse_op(exp_op(exp_lhs(e))), 
+                  exp_rhs(exp_lhs(e))]],x)
+      when commutative?(exp_op(exp_lhs(e)))
+        isolate([exp_rhs(exp_lhs(e)),
+                 &quot;=&quot;,
+                 [exp_rhs(e),
+                  inverse_op(exp_op(exp_lhs(e))),
+                 exp_lhs(exp_lhs(e))]],x)
+      else
+        isolate([exp_rhs(exp_lhs(e)),
+                 &quot;=&quot;,
+                [exp_lhs(exp_lhs(e)),
+                 exp_op(exp_lhs(e)),
+                 exp_rhs(e)]],x)
+      end
+    end
+
+    def solve_eq(equations, known)
+      equations.some? do |equation|
+        x = one_unknown(equation)
+        if x
+          answer = solve_arithmetic(isolate(equation,x))
+          recproc = proc{ |x| x.is_a?(Array) ? x.map(&amp;recproc) : (x==exp_lhs(answer) ? exp_rhs(answer) : x) }
+          solve_eq((equations-[equation]).map(&amp;recproc), [answer] + known)
+        end
+      end ||
+        known
+    end
   end
 end
 
@@ -122,5 +255,8 @@ end
 if __FILE__ == $0
   require 'pp'
 
+  Student.solve_equations([[[&quot;3&quot;, &quot;+&quot;, &quot;4&quot;], &quot;=&quot;, [[&quot;5&quot;, &quot;-&quot;, [&quot;2&quot;, &quot;+&quot;, &quot;x&quot;]],&quot;*&quot;,&quot;7&quot;]],
+                           [[[&quot;3&quot;, &quot;*&quot;, &quot;x&quot;], &quot;+&quot;, &quot;y&quot;], &quot;=&quot;, &quot;12&quot;]])
+  
   Student.solve(%w(If the number of customers Tom gets is twice the square of 20 % of the number of advertisements he runs , and the number of advertisements is 45 , then what is the number of customers Tom gets ?).map{ |w| w.downcase })
 end</diff>
      <filename>lib/ch07/student1.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>9e42381a153d0654dec297b1e10e87bf6dba2c09</id>
    </parent>
  </parents>
  <author>
    <name>Ola Bini</name>
    <email>ola.bini@gmail.com</email>
  </author>
  <url>http://github.com/olabini/paipr/commit/7334d50b3b62924bc7c02effd22be0201658945b</url>
  <id>7334d50b3b62924bc7c02effd22be0201658945b</id>
  <committed-date>2008-10-19T08:22:00-07:00</committed-date>
  <authored-date>2008-10-19T08:22:00-07:00</authored-date>
  <message>Rest of student program</message>
  <tree>c5d8772aeaae0c760067f24d4bd2ad83c4280e9b</tree>
  <committer>
    <name>Ola Bini</name>
    <email>ola.bini@gmail.com</email>
  </committer>
</commit>
