#2**Khatharr**(Topic Creator)Posted 10/23/2012 1:59:13 PM | ############################################# # FINAL FANTASY - THE 4 HEROES OF LIGHT # Ruby script to produce the best solutions to Scholar Bear's Number Puzzles # Version 1.0(final) - written by Khatharr (Aug 2012) ############################################# # No rights reserved - enjoy! #############################################
#global array with all operator set permutations $operationSets = [] operators = ['+','-','*','/'] for a in operators for b in operators for c in operators $operationSets.push([a,b,c]) end end end
#takes an input value array and spits out a 2D array with all combinations def composeCombinations(ary) a = ary[0]; b = ary[1]; c = ary[2]; d = ary[3] set = [ [a,b,c,d], [a,b,d,c], [a,c,b,d], [a,c,d,b], [a,d,b,c], [a,d,c,b], [b,a,c,d], [b,a,d,c], [b,c,a,d], [b,c,d,a], [b,d,a,c], [b,d,c,a], [c,b,a,d], [c,b,d,a], [c,a,b,d], [c,a,d,b], [c,d,b,a], [c,d,a,b], [d,b,c,a], [d,b,a,c], [d,c,b,a], [d,c,a,b], [d,a,b,c], [d,a,c,b] ] return set end
#determines the score of the operation ((A [op] B) [op] C) [op] D def scoreSequential(valAry, opAry) vals = valAry.clone ops = opAry.clone sult = vals.shift retval = 0 3.times do return 0 if (ops[0] == '/') and (sult % vals[0] != 0) eval "retval += (sult = #{sult} #{ops.shift} #{vals.shift})" end return retval if sult == 10 return 0 end
#determines the score of the operation (A [op] B) [op] (C [op] D) def scorePaired(vals, ops) sult = [] return 0 if (ops[0] == '/') and (vals[0] % vals[1] != 0) eval "sult[0] = vals[0] #{ops[0]} vals[1]" return 0 if (ops[2] == '/') and (vals[2] % vals[3] != 0) eval "sult[1] = vals[2] #{ops[2]} vals[3]" if (ops[1] == '/') return 0 if sult[1] == 0 return 0 if (sult[0] % sult[1] != 0) end eval "sult[2] = sult[0] #{ops[1]} sult[1]" return 0 if sult[2] != 10 return (sult[0] + sult[1] + sult[2]) end
# POLAR BEARS ARE GOOD AT MATHS def findBestSolution(ary) results = {} combos = composeCombinations(ary) for combo in combos for ops in $operationSets score = scoreSequential(combo, ops) results[score] = [combo.clone, ops.clone, false] score = scorePaired(combo, ops) results[score] = [combo.clone, ops.clone, true] end end results.delete(0) return results.max end |

#3**Khatharr**(Topic Creator)Posted 10/23/2012 1:59:33 PM | #returns a string explaining the winning solution def composeResultString(winner) #'winner' is in the format: [score, [[A,B,C,D], [x,y,z], paired]] #score is an Integer #A,B,C and D are Integers #x,y and z are each one of '+', '-', '*' or '/' #if the boolean value paired is true then: # (A x B) y (C z D) == score #else # ((A x B) y C) z D == score outstr = "" if winner == nil outstr << "Unsolvable set! Skip this one for some free points.\n" else score = winner[0] combo = winner[1][0] ops = winner[1][1] asPair = winner[1][2] outstr << "#{score} Point Solution:\n" if asPair valA = 0 valB = 0 opStr = "#{combo[0]} #{ops[0]} #{combo[1]}" outstr << " > #{opStr} = #{valA = eval opStr}\n" opStr = "#{combo[2]} #{ops[2]} #{combo[3]}" outstr << " > #{opStr} = #{valB = eval opStr}\n" opStr = "#{valA} #{ops[1]} #{valB}" outstr << " > #{opStr} = #{eval opStr}\n" else val = combo.shift 3.times do opStr = "#{val} #{ops.shift} #{combo.shift}" outstr << " > #{opStr} = #{val = eval opStr}\n" end end end return outstr.chomp end
#returns true for a valid input array or false otherwise def arrayIsValid?(ary) return false if ary.size != 4 return ((ary.min >= 1) and (ary.max <= 9)) end
############################################ #Beyond this point there's use of stdin and stdout. If you want to port to #something that doesn't have them then you need to replace the I/O stuff. # #Basically what needs to happen for a single pass is this: # * get 4 values from the user # * put them in an Array as Integers # * pass the array to arrayIsValid? and make sure it returns true # - if it's not then the user gave you bad values, so ask them again # * pass the array to findBestSolution which returns the best result # * pass the result to composeResultString which returns a string # * show the string to the user #The rest is just window dressing. ############################################
LINE_WIDTH = 60 HR = ("-" * LINE_WIDTH)
#print intro blurb puts HR, "Final Fantasy - The 4 Heroes of Light".center(LINE_WIDTH) puts "Scholar Bear's Math Game".center(LINE_WIDTH), HR
loop do ary = [] #get a valid input array until arrayIsValid?(ary) print "Enter comma delimited start values ['q' to quit]: " input = gets exit if input.downcase == "q\n" ary = input.split(",") #this .collect! converts the string-form numbers to integers ary.collect! {|v| v.to_i} end #get the best solution winner = findBestSolution(ary) #put it in English text = composeResultString(winner) #print it puts HR, text, HR end |