RE: Algorithm Request

new topic     » goto parent     » topic index » view thread      » older message » newer message

> From: C. K. Lester [mailto:cklester at yahoo.com]

> 
> Howdy, Matt,
> 
> When I said, "as close to being equal in value as possible," 
> I meant their
> sums...
> 
> > Could you define 'equal amounts?'  I assume you don't mean simply
> splitting
> > n numbers into k piles, so that each pile k has either int(n/k) or
> > int(n/k)+1 numbers.
> 
> Right. I don't mean that...
> 
> > Are you concerned with the sum of the numbers?
> 
> Yes!
> 
> So, with this set:
> 
> 1, 2, 4, 5, 8, 11
> 
> split into two groups, it would create TWO groups of 3 
> numbers each whose
> sums were the closest possible to equal...
> 
> 1, 4, 11 = 16
> 2, 5, 8 = 15

Here's what I came up with real quick.  There's probably a more elegant
solution, but this should work for any number of sets you want to make:

include get.e
include sort.e

function sums(sequence nums)
    sequence sum
    integer add
    sum = repeat(0,length(nums))
    for i = 1 to length(nums) do
        add = 0
        for j = 1 to length(nums[i]) do
            add += nums[i][j]
        end for
        sum[i] = add
    end for
    return sum
end function


procedure main()
    integer mid, ideal, sum, d, rep, max, pick_max, min, pick_min, over,
under
    sequence buckets, bucket_sums, rnd
    sum = 0
    rnd = repeat( 0, 100 )
    for i = 1 to length(rnd) do
        rnd[i] = rand(1000)
        sum += rnd[i]
    end for

    rnd = sort(rnd)
    puts(1,"Numbers:\n")
    ? rnd
    puts(1,"\n")

    for b = 2 to 5 do
        ideal = floor(sum/b)

        buckets = repeat({},b)

        max = 1
        while max <= length(rnd) do
            for i = 1 to b do
                if max > length(rnd) then exit end if
                buckets[i] &= rnd[max]
                max += 1
            end for

        end while
        bucket_sums = sums(buckets)
        
        rep = 0
        d = sum
        while d and (rep < 100) do

            max = 0
            pick_max = 0
            min = sum
            for i = 1 to b do
                if bucket_sums[i] > max then
                    max = bucket_sums[i]
                    pick_max = i
                end if
                if bucket_sums[i] < min then
                    min = bucket_sums[i]
                    pick_min = i
                end if
            end for
            -- remove one number from pick_max and give to pick_min
            over = bucket_sums[pick_max] - ideal
            under = ideal - bucket_sums[pick_min]
            
            -- choose which number to give away
            
            for i = length(buckets[pick_max]) to 1 by -1 do
                if buckets[pick_max][i] < over + under then
                    buckets[pick_min] = sort( buckets[pick_min] & 
				buckets[pick_max][i] )
                    buckets[pick_max] = buckets[pick_max][1..i-1] & 
                        buckets[pick_max][i+1..length(buckets[pick_max])]
                    exit
                end if
            end for

            bucket_sums = sums( buckets )
            d = 0
            min = 0
            for i = 1 to length(bucket_sums) do
                max = bucket_sums[i] - ideal
                if max < 0 then 
                    max = -max
                end if
                if max > min then
                    min = max
                    d = min 
                end if
            end for

            rep += 1
        end while
        printf(1,"\nbuckets: %d ideal: %d  max: %d  reps: %d\n", 
			{b,ideal,d, rep} ) 
        ? bucket_sums
        for i = 1 to b do
            ? buckets[i]
        end for
    end for
    
end procedure


main()

if wait_key() then end if

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu