Re: Murphy still winning

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

Can you make this so that the number of groups is variable? For instance,
sometimes I need to put those values across 3 or 4 or more buckets... :)

----- Original Message -----
From: <rforno at tutopia.com>
To: "EUforum" <EUforum at topica.com>
Subject: Murphy still winning


>
> The "omega" version:
>
> --Group numbers into two groups such that their sums are as close as
> possible
> --R. M. Forno 2003/04/17
> include sort.e
> include get.e
> include misc.e
> include machine.e
>
> integer Last, Lendata, Bestlast
> atom Lowgoal, Highgoal, Val, Bestval, Totval, Limit, Bound
> sequence Data, Index, Accum, Bestind
>
> set_rand(1)
>
> function Mcd2(integer d, integer r)
>     integer x
>     while r do
>     x = remainder(d, r)
>     d = r
>     r = x
>     end while
>     return d
> end function
>
> function Mcd(sequence s)
>     integer len, r
>     len = length(s)
>     r = s[len]
>     for i = len - 1 to 1 by -1 do
>     if r = 1 then
>         return r
>     end if
>     r = Mcd2(r, s[i])
>     end for
>     return r
> end function
>
> function readseq()
> --Read a sequence of integers from the keyboard or from a redirected file
>     sequence s, r
>     s = {}
>     while 1 do
>     r = get(0)
>     if r[1] != GET_SUCCESS or not integer(r[2]) then
>         exit
>     end if
>     s &= r[2]
>     end while
>     return s
> end function
>
> procedure outputresult()
> --Output resulting partitions
>     sequence aux
>     aux = repeat(0, Lendata)
>     for i = 1 to Lendata do
>     aux[i] = i
>     end for
>     for i = 1 to Bestlast do
>     aux[Bestind[i]] = 0
>     end for
>     printf(1, "Best solution values: %d %d\n", {Bestval, Totval -
Bestval})
>     puts(1, "Partition 1:\n")
>     for i = 1 to Bestlast do
>     printf(1, "%d ", Data[Bestind[i]])
>     end for
>     puts(1, '\n')
>     puts(1, "Partition 2:\n")
>     for i = 1 to Lendata do
>     if aux[i] then
>         printf(1, "%d ", Data[aux[i]])
>     end if
>     end for
>     puts(1, '\n')
> end procedure
>
> function recurse()
>     integer ind, r, dat, i1
>     if Val > Highgoal then --Impossible to get better values
>     return 0
>     elsif Val < Lowgoal then --Try to go ahead
>     if Val >= Bound then
>         if Val > Bestval then --Test for better value
>         Bestval = Val --Update best value and corresponding indexes
>         Bestlast = Last
>         Bestind = Index
>         end if
>     end if
>     if Val > Limit then --Impossible to get better values
>         return 0
>     end if
>     ind = Index[Last] --Go to next data item
>     while 1 do
>         i1 = ind --Previous
>         ind += 1
>         if ind > Lendata then --End of data vector
>         return 0
>         end if
>         if Val + Accum[ind] <= Bestval then --Impossible to get better
value
>         return 0
>         end if
>         dat = Data[ind]
>         if dat != Data[i1] or Index[Last] = i1 then --Skip repetition
>         Last += 1 --Try next index
>         Index[Last] = ind
>         Val += dat
>         r = recurse()
>         if r then --Best possible value found
>             return 1
>         end if
>         Val -= dat --Restore previous value
>         Last -= 1
>         end if
>     end while
>     else
>     Bestval = Val --Either Val = Lowgoal or Val = Highgoal
>     Bestlast = Last
>     Bestind = Index
>     return 1 --Indicate best possible value found
>     end if
> end function
>
> procedure optim()
>     integer r
>     Bestval = 0
>     Last = 1
>     Bestlast = 1
>     Index[1] = 1
>     Val = Data[1]
>     Limit = Highgoal - Data[Lendata]
>     Bound = Lowgoal - Data[1]
>     Bestind = Index
>     r = recurse()
>     if Bestval = 0 then
>     Bestval = Data[1]
>     end if
> end procedure
>
> function genrand(integer n, integer m)
>     sequence s
>     s = 14 * rand(repeat(n, m))
>     s[1] += 1
>     s[length(s)] += 1
>     return s
> end function
>
> procedure main()
>     atom t
>     integer a, b, mcd, r
>     a = 10000
>     b = 28
> --  Data = readseq()
>     Data = genrand(a, b)
> --  Data = {111, 9, 9, 9, 9, 9, 5, 1, 1, 1}
>     t = time()
>     Lendata = length(Data)
>     Index = repeat(0, Lendata)
>     if Lendata = 0 then
>     Bestlast = 0
>     Totval = 0
>     Bestval = 0
>     elsif Lendata = 1 then
>     Bestlast = 1
>     Bestind = {1}
>     Totval = Data[1]
>     Bestval = Totval
>     else
>     Data = reverse(sort(Data))
>     Accum = Data
>     for i = Lendata to 2 by -1 do
>         Accum[i - 1] += Accum[i]
>     end for
>     Totval = Accum[1]
>     Lowgoal = floor(Totval * 0.5)
>     Highgoal = - floor(- Totval * 0.5)
>     mcd = Mcd(Data)
>     Lowgoal -= remainder(Lowgoal, mcd)
>     r = remainder(Highgoal, mcd)
>     if r then
>         Highgoal += mcd - r
>     end if
>     if Totval - Highgoal < Lowgoal then
>         Lowgoal = Totval - Highgoal
>     end if
>     if Totval - Lowgoal > Highgoal then
>         Highgoal = Totval - Lowgoal
>     end if
>     printf(2, "Lowgoal = %d, Highgoal = %d\n", {Lowgoal, Highgoal})
>     optim()
>     end if
>     printf(2, "n = %d m = %d Sum1 = %d Sum2 = %d Time: %f\n",
>         {a, b, Bestval, Totval - Bestval, time() - t})
>     outputresult()
> end procedure
>
> main()
>
>
>
> TOPICA - Start your own email discussion group. FREE!
>
<snip>

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

Search



Quick Links

User menu

Not signed in.

Misc Menu