SHARE
TWEET

Untitled

a guest Oct 18th, 2019 75 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module TenPuzzle
  2.   class Solver
  3.     ALL_NUMBER_COMBINATIONS = [*1..9].combination(4).to_a
  4.     OPERATORS = %i(+ - * /)
  5.  
  6.     def solve
  7.       count = 0
  8.       ALL_NUMBER_COMBINATIONS.each do |numbers|
  9.         nodes = numbers.map { |n| Node.new(n, n.to_s) }
  10.         formulas = two_two_pattern_formulas(nodes) + two_one_one_pattern_formulas(nodes)
  11.  
  12.         count += 1 if formulas.any?
  13.  
  14.         puts "#{numbers.join(',')} : #{formulas.any? ? 'OK' : 'NO'} : example #{formulas.sample}"
  15.       end
  16.  
  17.       puts "(10になる組み合わせの数) / (全4桁の組み合わせ数) =  #{count} / #{ALL_NUMBER_COMBINATIONS.size}"
  18.     end
  19.  
  20.     def calculate_result_nodes(node1, node2)
  21.       OPERATORS.flat_map { |operator|
  22.         if %i(- /).include?(operator)
  23.           # 順番で結果が異なる演算子の場合
  24.           [
  25.             node1.calculate(node2, operator),
  26.             node2.calculate(node1, operator)
  27.           ]
  28.         else
  29.           [node1.calculate(node2, operator)]
  30.         end
  31.       }
  32.     end
  33.  
  34.     def two_two_pattern_formulas(nodes)
  35.       formulas = []
  36.       nodes.combination(2).each do |first_pair|
  37.         nodes_for_first_pair = calculate_result_nodes(*first_pair)
  38.  
  39.         other_pair = nodes - first_pair
  40.         nodes_for_other_pair = calculate_result_nodes(*other_pair)
  41.  
  42.         nodes_for_first_pair.product(nodes_for_other_pair).each do |last_pair|
  43.           whole_nodes = calculate_result_nodes(*last_pair)
  44.           formulas += whole_nodes.select(&:ten?).map(&:formula)
  45.         end
  46.       end
  47.       formulas
  48.     end
  49.  
  50.     def two_one_one_pattern_formulas(nodes)
  51.       formulas = []
  52.       nodes.combination(2).each do |first_pair|
  53.         nodes_for_first_pair = calculate_result_nodes(*first_pair)
  54.         second_node, last_node = nodes - first_pair
  55.         formulas += formulas_merged_one_and_one_nodes(nodes_for_first_pair, second_node, last_node)
  56.         formulas += formulas_merged_one_and_one_nodes(nodes_for_first_pair, last_node, second_node)
  57.       end
  58.       formulas
  59.     end
  60.  
  61.     def formulas_merged_one_and_one_nodes(nodes_for_first_pair, second_node, last_node)
  62.       second_pair_results = nodes_for_first_pair
  63.         .flat_map { |first_pair_result| calculate_result_nodes(first_pair_result, second_node) }
  64.  
  65.       second_pair_results.flat_map do |second_pair_result|
  66.         whole_nodes = calculate_result_nodes(second_pair_result, last_node)
  67.         whole_nodes.compact.select(&:ten?).map(&:formula)
  68.       end
  69.     end
  70.   end
  71.  
  72.   class Node
  73.     attr_reader :val, :formula
  74.  
  75.     def initialize(arg_val, arg_formula)
  76.       @val = arg_val
  77.       @formula = arg_formula
  78.     end
  79.  
  80.     def ten?
  81.       @val == 10
  82.     end
  83.  
  84.     def calculate(node, operator)
  85.       case operator
  86.       when :+
  87.         sum(node)
  88.       when :-
  89.         diff(node)
  90.       when :*
  91.         product(node)
  92.       when :/
  93.         quotient(node)
  94.       end
  95.     end
  96.  
  97.     def sum(node)
  98.       new_val = @val + node.val
  99.       new_formula = "(#{@formula} + #{node.formula})"
  100.       Node.new(new_val, new_formula)
  101.     end
  102.  
  103.     def diff(node)
  104.       new_val = @val - node.val
  105.       new_formula = "(#{@formula} - #{node.formula})"
  106.       Node.new(new_val, new_formula)
  107.     end
  108.  
  109.     def product(node)
  110.       new_val = @val * node.val
  111.       new_formula = "(#{@formula} * #{node.formula})"
  112.       Node.new(new_val, new_formula)
  113.     end
  114.  
  115.     def quotient(node)
  116.       return nil if node.val.zero?
  117.       new_val = Rational(@val, node.val)
  118.       new_formula = "(#{@formula} / #{node.formula})"
  119.       Node.new(new_val, new_formula)
  120.     end
  121.   end
  122. end
  123.  
  124. TenPuzzle::Solver.new.solve
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top