The three rules of Ruby Quiz: 1. Please do not post any solutions or spoiler discussion for this quiz until 48 hours have passed from the time on this message. 2. Support Ruby Quiz by submitting ideas as often as you can: http://www.rubyquiz.com/ 3. Enjoy! Suggestion: A [QUIZ] in the subject of emails about the problem helps everyone on Ruby Talk follow the discussion. Please reply to the original quiz message, if you can. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= This quiz was adapted from an ACM programming challenge at the suggestion of Gavin Kistner. Let's define two operators for a simple set of string equations. First, we will use the plus (+) operator and keep Ruby's meaning of concatenation for it. Therefore, "james" + "gray" is "jamesgray". The other operator we will support is equality (==). Two strings will be considered equal if they are anagrams (they contain the same letters in a possibly different ordering). In other words, "cinema" == "iceman". Using these two operators we can build equations: "i" + "am" + "lord" + "voldemort" == "tom" + "marvolo" + "riddle" This week's quiz is to write a program that accepts a list of words on STDIN and outputs any one string equation using those words, assuming there is one. Each word in the list may be used zero or more times, but only on one side of the equation. The program should exit(0) on success and exit(1), without printing any output, if a solution cannot be found. Let's sidestep case sensitivity issues by lower casing all incoming words. You can also remove all non-alphanumeric characters. Posting word lists and/or equations is not spoiler material.

on 2007-02-02 14:08

on 2007-02-02 17:43

cool quiz. I'm currently having trouble with this evil word list: bwu ha bwuhahahahahaha

on 2007-02-02 17:49

On Feb 2, 2007, at 10:43 AM, Daniel Lucraft wrote: > cool quiz. > > I'm currently having trouble with this evil word list: > bwu > ha > bwuhahahahahaha I like it. ;) James Edward Gray II

on 2007-02-02 18:59

James Gray > one. Each > word in the list may be used zero or more times, but only on one side of > the > equation. Shall we also add the requirement that at least one word is used at least once? :) Daniel Lucraft

on 2007-02-02 19:54

On Feb 2, 2007, at 11:59 AM, Daniel Lucraft wrote: > James Gray >> one. Each >> word in the list may be used zero or more times, but only on one >> side of >> the >> equation. > > Shall we also add the requirement that at least one word is used at > least once? :) Yes, see my post about this a little earlier. James Edward Gray II

on 2007-02-02 23:12

On 2/2/07, Daniel Lucraft <dan@fluentradical.com> wrote: > cool quiz. > > I'm currently having trouble with this evil word list: > bwu > ha > bwuhahahahahaha Here are the tests I'm using: http://pastie.caboo.se/37546 Started .... Finished in 0.735 seconds. 4 tests, 14 assertions, 0 failures, 0 errors Tests are boolean only because my solution doesn't do anything else...

on 2007-02-03 13:27

Sander Land wrote: > Here are the tests I'm using: > http://pastie.caboo.se/37546 > > Started > .... > Finished in 0.735 seconds. > 4 tests, 14 assertions, 0 failures, 0 errors > > Tests are boolean only because my solution doesn't do anything else... Thanks Sander that was useful in finding some bugs! I've added what should be the longest equation possible from your test_long word list: http://pastie.caboo.se/37659 Daniel Lucraft

on 2007-02-04 11:46

Ruby Quiz (James E. Gray): > This week's quiz is to write a program that accepts a list of words on STDIN and > outputs any one string equation using those words, assuming there is one. Each > word in the list may be used zero or more times, but only on one side of the > equation. The program should exit(0) on success and exit(1), without printing > any output, if a solution cannot be found. Shouldn't there be a requirement that an equations is invalid if there is another, shorter equation that uses the same words? Otherwise: $ ruby quiz112.rb foo oof "foo" = "oof" "foo" + "foo" = "oof" + "oof" "foo" + "foo" + "foo" = "oof" + "oof" + "oof" ... Kalman

on 2007-02-04 12:16

Kalman Noel wrote: > Shouldn't there be a requirement that an equations is invalid if there > is > another, shorter equation that uses the same words? Otherwise: > > $ ruby quiz112.rb foo oof > "foo" = "oof" > "foo" + "foo" = "oof" + "oof" > "foo" + "foo" + "foo" = "oof" + "oof" + "oof" > ... > > Kalman That sounds right. How about if you have an equation a == b, you should not be able to find equations c == d, and e == f such that c + e makes a and d + f makes b? Daniel

on 2007-02-04 15:13

On 2007/02/04, at 11:17, Daniel Lucraft wrote: > That sounds right. How about if you have an equation a == b, you > should > not be able to find equations c == d, and e == f such that c + e > makes a > and d + f makes b? Wouldn't a prolog script be better at describing all the rules than trying to figuring them out? If someone developed a prolog script that would behave as the final ruby script should, we would then have the specs without a shadow of doubt. Just don't look at me to write it =P Paulo Jorge Duarte Köchpaulo.koch@gmail.com

on 2007-02-04 16:19

here's my solution for this quiz It's quite slow, so you may want to tweak LENGTH_LIMIT constant to have the script running in a reasonable time. If you want to use this script to find equations for all the terms in wikipedia you may want to look at some other solution. It should behave as required from the original quiz. I don't think it respects all the rules added after the original quiz requirement :) With this word list bici bwu ha bwuhahahahahaha boci cibo bibo bocibici bibobici ci bo produces 166 equations Any comment is really welcome. Thanks for the fun. #!/usr/bin/env ruby require 'set' words = $stdin #a version of hash that supports + - / % class AlgHash < Hash def initialize(default = 0) super(default) end def keys super.to_set end alias len length %w(+ - % /).each do |sign| eval <<-END_EVAL def #{sign}(other) res = AlgHash.new total_keys = self.keys + other.keys total_keys.each {|k| res[k] = self[k] #{sign} other[k]} res end END_EVAL end def base?(other) other = other.signature unless other.respond_to? :keys return false unless self.keys == other.keys res = other % self if res.values.uniq == [0] if (multiplier = (other / self).values.uniq).size == 1 multiplier.first end end end end #some utility modules we want for our special version of string #and for Arrays #we want to have some methods used in Set available for arrays and string module SpecComp def multiple?(other) return false unless (self.len % other.len) == 0 if (self.signature % other.signature).values.uniq == [0] && (multiplier = (self.signature / other.signature).values.uniq).size == 1 multiplier.first else false end end def base?(other) other.multiple?(self) end def minus(other) (self.signature - other.signature).delete_if {|k, v| v == 0} end %w(subset? superset? intersection).each do |comp_method| eval <<-END_EVAL def #{comp_method}(other) return self.origin.send("#{comp_method}", other.origin) end END_EVAL end end #a rich indexed version of string #every string is lowercase and non alphanumeric chars are stripped #every string has a signature which is hash with letters as keys and number #of occurrences of the letter as values #some arithmetics is possible on the signature of the strings #the string reply to some Set class method that will be useful when we'll #compare string groups class HashedString attr_accessor :signature, :origin, :len include SpecComp def initialize(string) @signature = AlgHash.new sane_string = string.downcase.unpack('c*') sane_string.delete_if {|c| c < 49 || c > 122} sane_string.each {|c| @signature[c] = @signature[c] + 1} @len = sane_string.length @sym = sane_string.pack('c*').to_sym @origin = [@sym].to_set end def ==(other) self.signature == other.signature && self.origin != other.origin end def +(other) [self] + other end def *(integer) ret = [] integer.times {ret += self} ret end def to_s return "\"#{@sym.to_s}\"" end def to_ary [self] end def to_sym @sym end end #Array have signature too class Array include SpecComp def to_s (self.map {|w| w.to_s}).join(' + ') end def signature @signature ||= self.inject(AlgHash.new) {|sum, element| sum + element.signature} end def origin @origin ||= (self.map {|element| element.to_sym}).to_set end def len @len ||= self.inject(0) {|len, element| len + element.len} end end #the anagram finder #LENGTH_LIMIT is necessary if you don't want your PC busy for years class EquationFinder LENGTH_LIMIT = 1000 attr_reader :success def initialize(words_list) @words_list = words_list.to_a.map! {|w| HashedString.new(w)} @search_hash = Hash.new() {|h, k| h[k] = []} @words_list.each_with_index do |word, index| @search_hash[word.signature.keys.to_a.sort] << word to_add = [] @search_hash.each_value do |other_words| other_words.each do |other_word| if !word.subset?(other_word) && (other_word.origin.size < LENGTH_LIMIT) sum = word + other_word to_add << sum end end end to_add.each {|v| @search_hash[v.signature.keys.to_a.sort] << v} end end def write_equation(left_string, right_string) @success = 0 unless @success puts left_string.to_s + " == " + right_string.to_s end def find @search_hash.each_value do |homogeneus_words_list| homogeneus_words_list.size.times do word = homogeneus_words_list.pop find_equation_in_array(word, homogeneus_words_list) end end end def find_equation_in_array(word, array) array.each { |other_word| equation(word, other_word) } end def equation(left, right) if right.intersection(left).empty? if left == right write_equation(left, right) elsif multiplier = left.multiple?(right) write_equation(left, right * multiplier) elsif multiplier = left.base?(right) write_equation(left * multiplier, right) else try_other_formulas(left, right) end end end def try_other_formulas(left, right) short, long = [left, right].sort! {|a, b| a.len <=> b.len} short = [short] if short.instance_of? HashedString #begin return false if (short.collect {|o| o.len}).min > (long.len/2) #rescue # p short # p short.origin # raise #end difference = (long.minus short) short.each do |short_origin| if multiplier = (short_origin.signature.base? difference) write_equation((short + short_origin * multiplier), long) if multiplier > 0 end end end end finder = EquationFinder.new($stdin) finder.find exit(finder.success || 1)

on 2007-02-04 16:39

Here is my solution. It generates 26 equations (1 per character) in matrix form. If the nullity of this matrix is zero then the only solution is the zero solution (no words on either side), which is invalid. If it is > 0 then there are infinitely many solutions, any vector of integers in the null space corresponds to one of them. The way to generate such a solution is: (1) Find a vector in the null space using Rationals (2) Multiply it with large enough number (least common multiple of the denominators) such that all the Rationals turn into integers. (3) All the negative numbers are counts for words on the left side, positive for words on the right side. Step (1) would take more time than I have right now, so I tried searching for a library. But anything that calculates a basis for the null space has no support for Rationals and using floats makes step (2) pretty much impossible. So my code just returns if an equation exists instead of generating one. One last remark about my code: it uses Matrix#rank, which seems to be bugged. To run it you may need to patch your matrix.rb file (see http://www.ruby-forum.com/topic/96387) code: require 'matrix' class String def to_freq ('a'..'z').map{|c| Rational(count(c)) } # use Rational for stability in calculating rank end end def has_string_eqn(words) table = words.uniq.map{|w| w.downcase.gsub(/[^a-z]/,'').to_freq }.transpose nullity = words.length - Matrix[*table].rank return nullity > 0 end

on 2007-02-04 17:29

On Feb 4, 2007, at 4:45 AM, Kalman Noel wrote: > > Shouldn't there be a requirement that an equations is invalid if > there is > another, shorter equation that uses the same words? Otherwise: > > $ ruby quiz112.rb foo oof > "foo" = "oof" > "foo" + "foo" = "oof" + "oof" > "foo" + "foo" + "foo" = "oof" + "oof" + "oof" > ... If you want to make shorter equations a goal for your solution, go for it. This is not a requirement of the quiz though. James Edward Gray II

on 2007-02-04 18:12

Sander Land wrote: > Step (1) would take more time than I have right now, so I tried I guess I have too much time on my hands :) This is a solver for homogenous systems of linear equations: http://pastie.caboo.se/37827 It reduces the matrix to row echelon form, and then reads off the solutions from the non-unitary columns, multiplying them up to make them integral. It's probably not that robust in the case of degenerate or edge case matrices, but it works for solving the word equations. Obviously there are infinite solutions, so it returns the largest set of linearly independent solutions. It was fun to make, I had to dig out the linear algebra textbook I've had since my undergrad days. And this is the solution that uses it. It does exactly the same thing as Sander's in making the matrix, and then just uses the linear solver and translates the solutions into word equations. Fun quiz! Daniel # WordEquations # # $ cat test.txt # i # am # lord # voldemort # tom # marvolo # riddle # $ cat test.txt | ruby quiz112.rb # i + am + lord + voldemort == tom + marvolo + riddle # # Prints equation closest to 80 chars in length. # # Also: # $ cat test.txt | ruby quiz112.rb shortest # $ cat test.txt | ruby quiz112.rb longest # $ cat test.txt | ruby quiz112.rb all # # Generates word equations by solving the equivalent # homogenous linear equations. E.g. # # a = hohoho # b = h # c = oo # d = ho # -> # h's: 3a + b + + d = 0 # o's: 3a + 2c + d = 0 # -> # solutions: # [-2, 6, 3, 0] & [-1, 0, 0, 3] # -> # hohoho+hohoho == h+h+h+h+h+h+oo+oo+oo # hohoho == ho+ho+ho require 'homogenouslinearsolver' class WordEquations def self.word_problem(words) words = words.map {|word| word.downcase.match(/\w+/); $&}.uniq words = words.select{|w| w} rows = ('a'..'z').map do |l| words.map {|word| Rational(word.count(l), 1) } end solutions = HomogenousLinearSolver.solve(Matrix[*rows]) # if solution value is negative, add the word to the left side, # otherwise add to the right. solutions.collect do |sol| left_words = [] right_words = [] sol.each_with_index do |val, i| if val < 0 left_words += [words[i]]*(val*-1) elsif val > 0 right_words += [words[i]]*val end end left_words.join(" + ") + " == " + right_words.join(" + ") end end end if ARGV[0] == "test" require 'test/unit' class String def sorted (unpack('c*').sort).pack('c*') end end class TestWordEquations < Test::Unit::TestCase def test_hohoho words = %w{hohoho h oo} assert_equal ["hohoho + hohoho == h + h + h + h + h + h + oo + oo + oo"], WordEquations.word_problem(words) end def test_get_words_harry_potter words = %w{i am lord voldemort tom marvolo riddle} assert_equal ["i + am + lord + voldemort == tom + marvolo + riddle"], WordEquations.word_problem(words) end def test_get_words_me words = %w{daniel lucraft fluent radical} assert_equal ["daniel + lucraft == fluent + radical"], WordEquations.word_problem(words) end def test_get_words_evil! words = %w{bwu ha bwuhahahahaha} assert_equal ["bwu + ha + ha + ha + ha + ha == bwuhahahahaha"], WordEquations.word_problem(words) end def test_get_words_1 words = %w{dormitory dirty room} assert_equal ["dormitory == dirty + room"], WordEquations.word_problem(words) end def test_get_words_2 words = %w{statue of liberty built to stay free} assert_equal ["statue + of + liberty == built + to + stay + free"], WordEquations.word_problem(words) end def test_get_words_3 words = %w{hohoho h oo ho} assert_equal ["hohoho + hohoho == h + h + h + h + h + h + oo + oo + oo", "hohoho == ho + ho + ho"], WordEquations.word_problem(words) end def test_no_solutions words = %w{foo bar} assert_equal [], WordEquations.word_problem(words) end def test_long words = %w[My experience in Amsterdam is that cyclists ride where the hell they like and aim in a state of rage at all pedestrians while ringing their bell loudly, the concept of avoiding people being foreign to them. My dream holiday would be a ticket to Amsterdam, immunity from prosecution and a baseball bat- Terry Pratchett] results = WordEquations.word_problem(words).sort_by{|eq| -eq.length} result = results[0] assert_equal "my + my + my + my + my + my + my + my + my + my + my + "+ "my + my + my + my + my + my + my + my + my + my + my + my + my + "+ "my + my + my + my + my + my + my + my + my + my + in + in + in + "+ "in + in + in + in + in + is + is + is + is + is + is + is + is + "+ "is + is + is + is + is + that + that + that + that + ride + ride + "+ "ride + ride + ride + ride + ride + ride + ride + the + the + the + "+ "the + the + the + the + the + the + the + the + the + the + the + "+ "the + the + the + the + the + the + the + the + the + the + the + "+ "the + the + the + the + the + the + the + the + the + the + a + a + "+ "a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + "+ "a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + a + "+ "a + a + loudly + loudly + loudly + loudly + concept + concept + "+ "concept + concept == amsterdam + amsterdam + amsterdam + "+ "amsterdam + amsterdam + cyclists + cyclists + hell + hell + hell + "+ "they + they + they + they + they + they + they + they + they + "+ "they + they + they + they + they + they + they + they + they + "+ "they + they + they + they + they + they + they + they + they + "+ "they + they + they + they + they + they + they + they + they + "+ "and + and + and + and + and + and + and + and + aim + aim + aim + "+ "aim + aim + aim + aim + aim + aim + aim + aim + aim + aim + aim + "+ "aim + aim + aim + aim + aim + aim + aim + aim + aim + aim + "+ "prosecution + prosecution + prosecution + prosecution", result sides = result.split("==") sides.map! {|side| side.delete("+").delete(" ")} left = sides[0] right = sides[1] assert left.sorted == right.sorted end end else results = WordEquations.word_problem(STDIN.read.split).sort_by{|eq| -eq.length} if results == [] exit(1) else if ARGV[0] == "longest" puts results.first elsif ARGV[0] == "shortest" puts results.last elsif ARGV[0] == "all" results.each {|r| puts r; puts} else puts results.sort_by{|eq| (80-eq.length).abs}.first end exit(0) end end

on 2007-02-04 18:23

On Feb 4, 2007, at 11:12 AM, Daniel Lucraft wrote: > Sander Land wrote: >> Step (1) would take more time than I have right now, so I tried > > I guess I have too much time on my hands :) This is a solver for > homogenous systems of linear equations: http://pastie.caboo.se/37827 Wow. That's all I can think to say. ;) James Edward Gray II

on 2007-02-04 20:06

On Mon, 5 Feb 2007 01:29:32 +0900, James Edward Gray II <james@grayproductions.net> wrote: >If you want to make shorter equations a goal for your solution, go >for it. This is not a requirement of the quiz though. If you don't have this requirement, you have either none or an infinite number of solution - if a solution a==b exists, the ist also the solution a+a==b+b (and so on). So, only the minimal equations should count. hli

on 2007-02-04 20:46

My solution to the quiz below belongs to this same family of solutions. I, like Daniel, actually solved the set of equations via matrix transformations, although my code is self-contained and quick 'n dirty, not nicely refactored like his. When multiple families of word equation solutions exist, my program chooses one of them randomly to display. Eric ---------------- Are you interested in on-site Ruby training that's been highly reviewed by former students? http://LearnRuby.com ================ require 'mathn' CompactOutput = false # calculate the least common multiple of one or more numbers def lcm(first, *rest) rest.inject(first) { |l, n| l.lcm(n) } end # Returns nil if there is no solution or an array containing two # elements, one for the left side of the equation and one for the # right side. Each of those elements is itself an array containing # pairs, where each pair is an array in which the first element is the # number of times that word appears and the second element is the # word. def solve_to_array(words) # clean up word list by eliminating non-letters, converting to lower # case, and removing duplicate words words.map! { |word| word.downcase.gsub(/[^a-z]/, '') }.uniq! # calculate the letters used in the set of words letters = Hash.new words.each do |word| word.split('').each { |letter| letters[letter] = true } end # create a matrix to represent a set of linear equations. column_count = words.size row_count = letters.size equations = [] letters.keys.each do |letter| letter_counts = [] words.each { |word| letter_counts << word.count(letter) } equations << letter_counts end # transform matrix into row echelon form equations.size.times do |row| # re-order the rows, so the row with a value in then next column # to process is above those that contain zeroes equations.sort! do |row1, row2| column = 0 column += 1 until column == column_count || row2[column].abs != row1[column].abs if column == column_count : 0 else row2[column].abs <=> row1[column].abs end end # figure out which column to work on column = (0...column_count).detect { |i| equations[row][i] != 0 } break unless column # transform rows below the current row so that there is a zero in # the column being worked on ((row + 1)...equations.size).each do |row2| factor = -equations[row2][column] / equations[row][column] (column...column_count).each do |c| equations[row2][c] += factor * equations[row][c] end end end # only one of the free variables chosen randomly will get a 1, the # rest 0 rank = equations.select { |row| row.any? { |v| v != 0 }}.size free = equations[0].size - rank free_values = Array.new(free, 0) free_values[rand(free)] = 2 * rand(2) - 1 values = Array.new(equations[0].size) # holds the word_counts # use backward elimination to find values for the variables; process # each row in reverse order equations.reverse_each do |row| # determine number of free variables for the given row free_variables = (0...column_count).inject(0) do |sum, index| row[index] != 0 && values[index].nil? ? sum + 1 : sum end # on this row, 1 free variable will be calculated, the others will # get the predetermined free values; the one being calculated is # marked with nil free_values.insert(rand(free_variables), nil) if free_variables > 0 # assign values to the variables sum = 0 calc_index = nil row.each_index do |index| if row[index] != 0 if values[index].nil? values[index] = free_values.shift # determine if this is a calculated or given free value if values[index] : sum += values[index] * row[index] else calc_index = index end else sum += values[index] * row[index] end end end # calculate the remaining value on the row values[calc_index] = -sum / row[calc_index] if calc_index end if values.all? { |v| v } && values.any? { |v| v != 0 } # in case we ended up with any non-integer values, multiply all # values by their collective least common multiple of the # denominators multiplier = lcm(*values.map { |v| v.kind_of?(Rational) ? v.denominator : 1 }) values.map! { |v| v * multiplier } # deivide the terms into each side of the equation depending on # whether the value is positive or negative left, right = [], [] values.each_index do |i| if values[i] > 0 : left << [values[i], words[i]] elsif values[i] < 0 : right << [-values[i], words[i]] end end [left, right] # return found equation else nil # return no found equation end end # Returns a string containing a solution if one exists; otherwise # returns nil. The returned string can be in either compact or # non-compact form depending on the CompactOutput boolean constant. def solve_to_string(words) result = solve_to_array(words) if result if CompactOutput result.map do |side| side.map { |term| "#{term[0]}*\"#{term[1]}\"" }.join(' + ') end.join(" == ") else result.map do |side| side.map { |term| (["\"#{term[1]}\""] * term[0]).join(' + ') }. join(' + ') end.join(" == ") end else nil end end if __FILE__ == $0 # if run from the command line... # collect words from STDIN words = [] while line = gets words << line.chomp end result = solve_to_string(words) if result : puts result else exit 1 end end

on 2007-02-04 20:55

I'll feed the datapoint pool as well using my solution. Here is the output of multiple runs using the Terry Pratchett quote that appeared earlier in the thread. To make it slightly easier to interpret, I'm using a more compact form (that deviates slightly from the quiz requirements) to output the word equations. 1*"my" + 2*"the" == 1*"they" + 1*"them" 2*"my" + 1*"amsterdam" + 3*"ride" + 2*"where" + 1*"the" + 1*"hell" + 2*"and" + 2*"aim" == 2*"in" + 1*"is" + 2*"they" + 2*"while" + 6*"dream" 2*"amsterdam" + 1*"is" + 3*"hell" + 5*"they" + 1*"aim" + 6*"bat" == 5*"my" + 3*"that" + 2*"ride" + 5*"the" + 2*"at" + 3*"baseball" 2*"my" + 7*"amsterdam" + 5*"is" + 27*"the" + 1*"hell" + 4*"and" + 8*"aim" + 4*"pratchett" == 8*"that" + 2*"cyclists" + 7*"ride" + 18*"a" + 4*"pedestrians" + 24*"them" 5*"cyclists" + 16*"the" + 3*"like" + 7*"and" + 6*"aim" + 7*"to" + 7*"pratchett" == 3*"amsterdam" + 7*"is" + 14*"that" + 4*"ride" + 4*"hell" + 5*"they" + 7*"concept" + 3*"ticket" 6*"in" + 11*"amsterdam" + 13*"is" + 18*"they" + 2*"and" + 6*"while" + 8*"pratchett" == 14*"my" + 16*"that" + 4*"cyclists" + 5*"ride" + 6*"where" + 9*"the" + 1*"hell" + 8*"aim" + 8*"pedestrians" Eric

on 2007-02-04 21:03

On Feb 4, 2007, at 1:05 PM, Hendrik Lipka wrote: >>> "foo" + "foo" + "foo" = "oof" + "oof" + "oof" >>> ... >> >> If you want to make shorter equations a goal for your solution, go >> for it. This is not a requirement of the quiz though. > > If you don't have this requirement, you have either none or an > infinite > number of solution - if a solution a==b exists, the ist also the > solution > a+a==b+b (and so on). That's why the quiz asks for any of the possible solutions. > So, only the minimal equations should count. An right answer is fine, so feel free to use minimal equations. James Edward Gray II

on 2007-02-05 12:06

```
James Edward Gray II:
> That's why the quiz asks for any of the possible solutions.
Ah, this is where I didn't read properly. Also this may be the reason
why I
didn't actually try and start coding.
Kalman
```