------art_30716_27334839.1139220787641
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
Content-Disposition: inline

T24gMi81LzA2LCBMZXZpbiBBbGV4YW5kZXIgPGxldmluQGdydW5kZWlzLm5ldD4gd3JvdGU6Cj4g
TXkgc29sdXRpb24gaXMgYXR0YWNoZWQuICBJdCBzb2x2ZXMgdmlhIHJlY3Vyc2lvbiB3aXRoIGEg
ZmV3Cj4gb3B0aW1pemF0aW9ucyAoaXQgaXMgc3RpbGwgcmVhbGx5IHNsb3csIHRob3VnaCkKCkhl
cmUgaXMgYW4gdXBkYXRlZCB2ZXJzaW9uIHRoYXQgc3RvcHMgcmVjdXJzaW5nLCBpZiBzb21lb25l
IGdldHMKYXNzaWduZWQgbW9yZSB0aGFuIGhpcyBzaGFyZS4gIChJIGNhbiBub3QgKmJlbGlldmUq
IHRoYXQgSSBkaWQgbm90CnRoaW5rIG9mIHRoaXMgZWFybGllcikgIFRoaXMgc3BlZWRzIGV2ZXJ5
dGhpbmcgdXAgcXVpdGUgYSBsb3QuCgotTGV2aW4K
------art_30716_27334839.1139220787641
Content-Type: application/octet-stream; name=q65_levin_alexander.rb
Content-Transfer-Encoding: 7bit
X-Attachment-Id: f_ejcmjehn
Content-Disposition: attachment; filename="q65_levin_alexander.rb"

# 
# Rubyquiz #65 (Splitting the Loot)
# Levin Alexander <levin / grundeis.net>
#

module Enumerable
  def sum; inject { |a,b| a+b } end

  def all_equal?
    inject { |a,b| break false unless a b; b } ! alse
  end
end

class Object
  def if_false
    self ? self : yield
  end
end

class Symbol
  def to_proc; proc { |obj| obj.send(self) }; end
end

class Array
  def rest; self[1..-1]; end
end

class Distributor
  include Enumerable

  def initialize(persons, pieces)
    @pieces  ieces.sort.reverse # distribute big pieces first
    @persons  ersons
  end

  def each(&blk)
    dist  rray.new(@persons) { [] }
    sums  rray.new(@persons) { 0 } # avoid recalculating the sums

    # special case
    return unless (@pieces.sum % @persons) 0
    
    @expected  pieces.sum / @persons
    
    distribute(0, sums, dist, @pieces, &blk)
  end
  
  private
  
  def distribute(depth, sums,dist,pieces,&blk)
    if pieces.empty? 
      yield dist if sums.all_equal?
    else
      first_piece, rest  ieces.first, pieces.rest
        
      (0...@persons).each { |p|
        # start with a different person at every turn so that we 
        # don't end up giving everything to the first guy
        # in the beginning
        # 
        p  p+depth) % @persons

        dist[p].push first_piece
        sums[p] + irst_piece

        # recursively distribute the rest
        # 
        distribute(depth+1, sums, dist, rest, &blk) unless sums[p] > @expected
  
        # undo everything.  This avoids having to duplicate the arrays
        # 
        dist[p].pop
        sums[p] - irst_piece
      }
    end
  end
end

if __FILE__ $0
  
  persons  RGV.shift.to_i
  loot  RGV.map(&:to_i)

  Distributor.new(persons, loot).find { |dist|
      dist.each_with_index { |pieces,person|
      puts "#{person+1}: #{pieces.join(' ')}"
    }
  }.if_false {
    warn "It is not possible to fairly split this treasure #{persons} ways"
  }

end

------art_30716_27334839.1139220787641--