permuting a string (was Re: Speed)

Geoff Canyon gcanyon at gmail.com
Mon Sep 1 20:47:58 EDT 2014


On Mon, Sep 1, 2014 at 10:32 AM, Beat Cornaz <B.Cornaz at gmx.net> wrote:

> This is my fastest script so far :
>

I think this is faster for many arguments. It might be slower for others. I
removed the dependency on an external routine for removing duplicates. It
also removes duplicates only when needed, and event then not always (it's
expensive, so it's better to let some duplicate permutations sneak in and
then remove them all together).

I also made the (unsafe) assumption that the arguments would come already
ordered from most common to least.

I also think the original routine wouldn't work with non-duplicate values.
Try permuting "123" to see. This routine handles those correctly as far as
I've tested.

Sorry for the limited comments on the optimizations. Also, I haven't tested
each individual optimization for whether it actually speeds things up.


function beatPermut ToPermutateOrdered
   -- assumes the paramter is in decreasing order of frequency
   -- "11122334" is fine
   -- "11222" might work
   -- "12213" will probably fail

   put char 1 of ToPermutateOrdered into lastChar

   -- start with the longest string of duplicates possible
   repeat with i = 1 to length(ToPermutateOrdered)
      if char i of ToPermutateOrdered <> lastChar then exit repeat
      put char i of ToPermutateOrdered after TempPerms2
   end repeat
   put length(TempPerms2) into numChars
   put char numChars + 1 to -1 of  ToPermutateOrdered into tInput3
   put true into wasNewElement

   repeat for each char rNewElement in tInput3
      put rNewElement <> lastChar into isNewElement
      -- remove duplicates for each new value after a duplicate
      if isNewElement and not wasNewElement then
         split TempPerms2 using cr as set
         put the keys of TempPerms2 into TempPerms1
      else
         put TempPerms2 into TempPerms1
      end if
      put rNewElement into lastChar
      put empty into TempPerms2

      if isNewElement then
         -- for the first of a duplicate
         -- or for a unique
         -- just distribute it
         repeat for each line rLine in TempPerms1
            put rNewElement & rLine & cr after TempPerms2
            repeat with x = 1 to NumChars - 1
               put (char 1 to x of rLine) & rNewElement & (char x+1 to -1
of rLine) & cr after TempPerms2
            end repeat
            put rLine & rNewElement & cr after TempPerms2
         end repeat
      else
         -- for duplicates after the first
         -- never place before the first
         -- never insert except at the end of a string
         repeat for each line rLine in TempPerms1
            repeat with x = offset(rNewElement,rLine) + 1 to NumChars
               if char x of rLine <> rNewElement then put (char 1 to x-1 of
rLine) & rNewElement & (char x to NumChars of rLine) & cr after TempPerms2
            end repeat
            put rLine & rNewElement & cr after TempPerms2
         end repeat
      end if
      add 1 to NumChars
   end repeat

   -- Final deletion of duplicates, if the last element was a duplicate
   if isNewElement then return TempPerms2
   split TempPerms2 using cr as set
   return the keys of TempPerms2
end beatPermut



More information about the use-livecode mailing list