Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

numeric comparison issue 3

Status
Not open for further replies.
May 26, 2005
4
US
I need to compare a various amounts of numeric values contained in variables too result in sets of three(3) variables each which would result in the least number as a total.
Use/Application Example.
I have a various number of reels containg various known cable lengths. I need to combine these cables in various numeric sets, For this example three(3) sets which will result in the least amount of wasted length.
(Scrap Efficiency)
Thanks
Any Help is hugely appreciated
 
Rightclickn

It sounds like you need to use the MIN function.

Example:
? MIN(5,7,2)
returns 2

(By the way - this is not the same MIN function as you get with SQL statements)

Reply back if that doesn't help.


Hope that helps,

Stewart
PS If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Naw, Actually that won't work. Not in itself anyway. Let me explain exactly what I am trying to accomplish:
I am braiding cable that require a various number of cables to be braided together depending on the product manufactured.
For this example, I have three input cables to be braided into one ouput cable with the output cable obviously containing splices. I have various known lengths on a number of reels that I want to load (Braid) in sets of three to result in the least amount of wasted input cable.
So I would start with one reel containing the greatest length and add another two reels of various length with a result of two reels being depleted and length remaing on the first reel. I need to combile the input reel lengths in the most efficient/smartest combination to result in less scrap.
ie. Cable lengths in feet of: 985,580,450,345,275,265,230,190,150
need a triple braid. Oh, the other variable is a minimum length between splices of 100 ft.
Sorry if confusing
 
One method (maybe not the best, but might work well enough): Sort the lengths descending, then add them up in sequence until you exceed the desired length, then back out the last one added, add the next one down, and repeat the back-out-add-the-next-one loop until you find the shortest length that just barely goes over the desired length.

That might not work with the 100'-between-splices rule though.

Brute force method: Add all possible combinations of lengths (N items taken 2 through N at a time) and pick the combination that exceeds the desired length by the least amount.

Example:

985+580,
985+580+450
985+580+450+345
... etc.

(deep breath)

580+450
580+450+345
580+450+345+275
...etc

(another deep breath)

450+345
450+345+275
450+345+275+265
...etc

...etc...etc... all the way. You get the idea.

This is where that statistics class you slept through in school would have helped!


Mike Krausnick
Dublin, California
 
Hmm, when you say "braiding" do you mean that the 3 cables get twisted around each other? Do you then splice sets of 3 cables into each other?

Let's see, you're braiding together three cables. So these 3 cables need to be cut to the length of the shortest of the 3 and the minimum length is 100'?

So if you only had cables of lengths 120, 150, 165, you would cut the 150' & 165' cables down to 120', resulting in scrap of 30' & 45' respectively, which would have to be chucked as they are less than 100' long.

Have I got that right?

Stewart
 
Yes Stewart - During the braid operation - if say the three(3)input reel lengths to be braided as one were 120,150,220, (30' of the 150') would be scrapped, with one(1)input reel (100' of the 220') cable remaining. Two(2) new input cable reels would be mounted, the three(3) cables spliced together & the Braid operation would continue. The actual physical cutting of the resulting braided cable is done in a separate operation(Respool). Keep in mind there can be any number of input reels with different lengths to manufacture the total braided cable required. Also, in the previous example, it is possible to cut & dismount the remaining (100' of the 220') Reel cable if it would be consumed more efficiently with a latter set of three(3) cable reels. In this example, three(3) new cable reels would be mounted and spliced into the existing braided cable.

Not sure if I am thinking too much & making this more complicated than necessary.

Any Ideas?

Any suggestions are Sincerely and GREATLY APPRECIATED!
Wayne
P.S. mkrausnick: I am definitely review and test your suggestion. THANKS
 
Wayne,

My first thoughts are for the invariant of a loop.

Let's see ... we want always to braid two reels with minimum difference with a third reel that is 100' longer than the shortest of the first two. In your example, that would be 265 and 275 (leaving scrap of 10') braided with any other reel that is greater or equal to 365' (leaving no scrap).

Now I'm thinking about the loop and perhaps more to the invariant.

However, I suspect that this is an Operations Research type of problem requiring Linear Programming.

Tony
 
Wayne,

Second thoughts lead to an enhancement of the invariant:

"We want always to braid two reels with minimum difference [red](both reels less than the maximum one)[/red] with a third reel that is 100' longer than the shortest of the first two.

Here is a rough program that utilizes that invariant and results in 4% scrap. Please ignore the fact that I don't use Hungarian notation...and I included my library routine for deleting an array element (aDelete).

Code:
local i,j,p,reel,reelLens,scrap
dimension reel(1)
reelLens = "985-1,580-2,450-3,345-4,275-5,265-6,230-7,190-8,150-9"
* NOTE: reelLens ::= length-reelNumber 
scrap = 0
clear
*----- Load reels -----------
i = 1
p = at(",",reelLens)
if p = 0 then 
   p = len(reelLens)+1
endif   
reel(i)    = substr(reelLens,1,p-1)
do while p < len(reelLens)
   reelLens = substr(reelLens,p+1)
   p = at(",",reelLens)
   if p = 0 then 
      p = len(reelLens)+1
   endif
   i = i+1
   dimension reel(i)   
   reel(i)    = substr(reelLens,1,p-1)
enddo
local totLen
totLen = 0
for i=1 to alen(reel)
   totLen = totLen+val(reel)
next i    

*----- Braid reels -----------
local mindiff,imin,jmin,smaller
do while .T.
   if alen(reel) >= 3 then
      mindiff = 99999999999
*           sort descending (largest on top)
      asort(reel,1,alen(reel),1)
*           find 2 reel with minimum difference
*           (exclude the largest)
      for i=2 to alen(reel)
         for j=i+1 to alen(reel)
            if abs(val(reel(i))-val(reel(j))) < mindiff then
               mindiff = abs(val(reel(i))-val(reel(j)))
               imin = i
               jmin = j
               smaller = min(val(reel(i)),val(reel(j)))
            endif   
         next i
      next i
      scrap = scrap+abs(val(reel(imin))-val(reel(jmin)))
      ?"scrap"+str(abs(val(reel(imin))-val(reel(jmin))));
              +"  total:"+str(scrap) 
      ? "using "+substr(reel(imin),5);
                +" "+substr(reel(jmin),5)  
      if imin > jmin then
         aDelete(@reel,imin)   
         aDelete(@reel,jmin)
      else
         aDelete(@reel,jmin)   
         aDelete(@reel,imin)
      endif      
      for i=1 to alen(reel)   && find one >= 100 + smaller      
         if not inlist(i,imin,jmin) then
            if val(reel(i)) >= smaller+100 then
               reel(i)=alltrim(str(val(reel(i))-smaller));
                      +substr(reel(i),4) && use part of it
               ?" and "+str(i)
               exit &&for
            endif
         endif
      next i
      if i > alen(reel)       && none found >= 100 + smaller
         for i=1 to alen(reel)   && find one >= smaller
            if val(reel(i)) >= smaller then
               reel(i)=alltrim(str(val(reel(i))-smaller));
                      +substr(reel(i),4) && use part of it
               ?" and "+str(i)
               scrap = scrap+val(reel(i)) && scap rest < 100'
               ?"scrap "+str(val(reel(i)));
                        +"  total:"+str(scrap) 
               aDelete(@reel,i)   
               exit &&for
            endif
         next
      endif
      if i > alen(reel)      && none found >= smaller
         for i = 1 to alen(reel)      && scrapp rest of reels
            scrap = scrap+val(reel(1))
            ?"scrap "+str(val(reel(1)));
                     +"  total:"+str(scrap) 
            aDelete(@reel,1)   
         next i   
         exit &&do
      endif
   else                        && scrap rest of reels
      for i=1 to alen(reel)
         scrap = scrap+val(reel(1))
         ?"scrap "+str(val(reel(1)))+"  total:"+str(scrap) 
         aDelete(@reel,1)   
      next i
      exit &&do
   endif      
enddo   
*------ Results-----------
?
?"Wasted "+str(scrap)+" out of a total of "+str(totLen);
                     +"  = "+str(100*scrap/totLen,1)+"%" 
*==================================
PROCEDURE aDelete
   lparameters arr,i, elem
   
   local typ,j,u2
   external array arr
   elem = arr(i)
   if pcount() = 3 then 
      elem = arr(i)
   endif   

   if i > alen(arr,1) then
      RETURN
   endif   
      
   typ = type("arr")
   =adel(arr,i)
   u2 = alen(arr,2)
   if u2 > 0 then
      if alen(arr,1) > 1 then 
         dimension arr(alen(arr,1)-1,u2)
      else
         for j=1 to u2
            do case
            case typ = "C"
               arr(1,j) = ""
            case typ = "N"   
               arr(1,j) = 0
            case typ = "D"
               arr(1,j) = {//}
            endcase
         next j
      endif
   else
      if alen(arr) > 1 then 
         dimension arr(alen(arr)-1)
      else
         do case
         case typ = "C"
            arr(1) = ""
         case typ = "N"   
            arr(1) = 0
         case typ = "D"
            arr(1) = {//}
         endcase
      endif
   endif
RETURN elem
*---------------

Tony
 
Wayne,

Sorry, two mistakes in reporting the 3rd reel.
Were it says
?" and "+str(i)
use
?" and "+substr(reel(i),5) && the reel number

Tony
 
Wayne,

I cleaned up the program and defined a class for the reels. This way you can use the program as is (if it has any value to you) and implement your own reel class in a more appropiate way.

Keep in mind, I still suspect that this is an Operations Research type of problem requiring Linear Programming.

Oh, I also fixed a glich - % scraped comes out to 11%

Tony

Code:
clear
reelLens = "985,580,450,345,275,265,230,190,150"

Reels = NEWOBJECT("Reel")
Reels.Make(reelLens)

*----- Braid reels -----------
do while .T.
   if Reels.Count() >= 3 then
*     find 2 reel with minimum difference (except largest)
      Reels.getTwo()
      ?"scrap"+str(Reels.scrap);
              +"  total:"+str(Reels.totalScrap) 
      ? "using "+Reels.reel1+" "+Reels.reel2
      Reels.getLargeThird()      && >= smaller+100
      if empty(Reels.reel3) then  && none found >= 100+smaller
         Reels.getAnyThird()      && >= smaller
         if empty(Reels.reel3) then  && none found >= smaller
            Reels.ScrapRest()
            ?"scrap total:"+str(Reels.totalScrap) 
            exit &&do
         endif
      else
         ? " and "+Reels.reel3   
      endif
   else
      Reels.ScrapRest()
      ?"scrap total:"+str(Reels.totalScrap) 
      exit &&do         
   endif      
enddo   
*------ Results-----------
?
?"Wasted "+str(Reels.totalScrap);
          +" out of a total of "+str(Reels.totLen);
          +"  = "+str(100*Reels.totalScrap/Reels.totLen,2,1)+"%" 
*==================================
*=================================
DEFINE CLASS Reel AS CUSTOM
   PROTECTED imin,jmin,smaller,reel(1)
   smaller = 0
   totLen = 0
   scrap = 0
   totalScrap = 0
   reel1 = ""
   reel2 = ""
   reel3 = "" 
   *==================== 
   Procedure Make
      parameters reelLens
      local i,p
      i = 1
      p = at(",",reelLens)
      if p = 0 then 
         p = len(reelLens)+1
      endif   
      This.reel(i) = substr(reelLens,1,p-1)+"-"+alltrim(str(i))
      do while p < len(reelLens)
         reelLens = substr(reelLens,p+1)
         p = at(",",reelLens)
         if p = 0 then 
            p = len(reelLens)+1
         endif
         i = i+1
         dimension This.reel(i)   
         This.reel(i) = substr(reelLens,1,p-1)+"-"+alltrim(str(i))
      enddo
      for i=1 to alen(This.reel)
         This.totLen = This.totLen+val(This.reel(i))
      next i    
   EndProc
   *---------------------   
   Procedure getTwo
      local i,j,mindiff
      mindiff = 99999999999
*           sort descending (largest on top)
      asort(This.reel,1,alen(This.reel),1)
*           find 2 reel with minimum difference
*           (exclude the largest)
      for i=2 to alen(This.reel)
         for j=i+1 to alen(This.reel)
            if abs(val(This.reel(i))-val(This.reel(j))) < mindiff then
               mindiff = abs(val(This.reel(i))-val(This.reel(j)))
               This.imin = i
               This.jmin = j
               This.smaller = min(val(This.reel(i)),val(This.reel(j)))
            endif   
         next i
      next i
      This.scrap = ;
      	abs(val(This.reel(This.imin))-val(This.reel(This.jmin)))
      This.totalScrap = This.totalScrap+This.scrap
      This.reel1 = substr(This.reel(This.imin),5)     
      This.reel2 = substr(This.reel(This.jmin),5)     
      if This.imin > This.jmin then
         This.aDelete(This.imin)   
         This.aDelete(This.jmin)   
      else
         This.aDelete(This.jmin)   
         This.aDelete(This.imin)
      endif      
   EndProc
   *---------------------   
   Procedure getLargeThird      && >= smaller+100
      This.reel3 = ""
      for i=1 to alen(This.reel)   && find one >= 100 + smaller      
         if not inlist(i,This.imin,This.jmin) then
            if val(This.reel(i)) >= This.smaller+100 then
               This.reel(i)=alltrim(str(val(This.reel(i))-This.smaller));
                      +substr(This.reel(i),4) && use part of it
               This.reel3 = substr(This.reel(i),5)
               exit &&for
            endif
         endif
      next i
   Endproc
   *---------------------   
   Procedure getAnyThird   && > smaller
      This.reel3 = ""
      for i=1 to alen(This.reel)   && find one >= smaller
         if val(This.reel(i)) >= This.smaller then
            This.reel(i)=alltrim(str(val(This.reel(i))-This.smaller));
                   +substr(This.reel(i),4) && use part of it
            This.real3 = substr(This.reel(i),5)
            This.scrap = val(This.reel(i)) && scap rest < 100'
            This.totalScrap = This.totalScrap+This.scrap
            This.aDelete(i)   
            exit &&for
         endif
      next
   EndProc
   *---------------------   
   Procedure ScrapRest
      for i=1 to alen(This.reel)
         This.scrap = val(This.reel(1))
         This.totalScrap = This.totalScrap+This.scrap
         This.aDelete(i)   
      next i
   EndProc
   *---------------------   
   Function count
   Return alen(This.reel)
   *---------------------
   PROTECTED procedure aDelete
      lparameters i
      
      local j,u2

      if i > alen(This.reel) then
         RETURN
      endif   
         
      adel(This.reel,i)
      if alen(This.reel) > 1 then 
         dimension This.reel(alen(This.reel)-1)
      else
         This.reel(1) = ""
      endif
   Endproc
   *---------------------   
ENDDEFINE
*=================================
 
Tony - WOW, Incredible & THANKS

That sure is a wicked solid start. Thanks a million! Please don't tell me that it took you 15 minutes to wip that one out...

Thanks again Everyone!
Wayne
p.s. How do I submit votes?
 
Wayne,

No, a little longer. I love a challenge.

You might what to improve in the two routines that get the 3rd reel, getLargeThird and getAnyThird. They should get one that is closer to the size of the smaller or a multiple of the smaller or ... anything else that you can think of.

Tony
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top