# Have the function OptimalAssignments(strArr) read strArr which will represent # an NxN matrix and it will be in the following format: ["(n,n,n...)","(...)",...] # where the n's represent integers. This matrix represents a machine at row i # performing task at column j. The cost for this is matrix[i][j]. Your program # should determine what machine should perform what task so as to minimize the # whole cost and it should return the pairings of machines to tasks in the # following format: (i-j)(...)... Only one machine can perform one task. For # example: if strArr is ["(5,4,2)","(12,4,3)","(3,4,13)"] then your program # should return (1-3)(2-2)(3-1) because assigning the machines to these tasks # gives the least cost. The matrix will range from 2x2 to 6x6, there will be no # negative costs in the matrix, and there will always be a unique answer. def optimal_assignments(input) least_cost = Float::INFINITY least_keys = [] permutate(input) do |path| tasks = path.keys costs = path.values total = costs.sum if total < least_cost least_cost = total least_keys = tasks end end least_keys.map.with_index do |machine, task| [task + 1, machine + 1] end end def permutate(input, path = {}, &block) input.each do |row| row.each_with_index do |cost, task| next if path[task] if input.length == 1 yield path.merge(task => cost) else permutate( input[1..-1], path.merge(task => cost), &block ) end end break end end data = [ [ [[5,4,2],[12,4,3],[3,4,13]], [[1,3],[2,2],[3,1]] ], [ [[1,1,2],[2,1,5],[1,5,1]], [[1,1],[2,2],[3,3]] ], [ [[1,4],[5,18]], [[1,2],[2,1]] ], [ [[1,2],[1,1]], [[1,1],[2,2]] ], [ [[90,75,75,80,82],[35,85,20,50,41],[40,2,24,1,67],[4,70,2,11,23],[23,25,56,44,21]], [[1,2],[2,3],[3,4],[4,1],[5,5]] ] ] data.each do |input, expected| output = optimal_assignments(input) if output == expected puts "INPUT #{input}" puts "PASSED" else puts "INPUT: #{input}" puts "EXPECTED: #{expected}" puts "RECEIVED: #{output}" puts "FAILED" exit 1 end end