SCRIPTING:

Pamela Anderson
THE DNA I-CHING ALGORITHM
Three scripts with active forms to test them. Given an input vector of objects, say [ABC], these scripts would produce all the recombinations taking in each Vector entry not just once but also reproducing it.
If my fullCollection() algorithm would have generated: A B C AA AB AC BB BC CC ABC these here would generate: A B C AA AB AC BB BC CC AAB AAC AAD ABB ABC ABD ACC ACD ADD BBB BBC BBD BCC BCD BDD CCC CCD CDD DDD and upon request all the anagrams for each of them!
January 2002
{ @ }

The model above is Pamela Anderson
LOADS OF PAMELA ANDERSON ON THE NET


PURPOSES OF THE SCRIPTS
What these scripts do and the requirements of the DNA algorithm

Note: if you're here because you're interested in the DNA algorithm, you may also be interested in scripts that try emulating Hamming sequences/distances calculations: they can be found clicking here.
Featuring three scripts:
  1. abstractPartitions
    Given a ceil limit, say 4, and an input vector, say [ABC], would generate all the possible combinations without limiting itself to produce only those where each instance of the input vector would appear just once (for such a thing you may refer to my fullCollection() script) but producing even all the combinations where each given input letter would appear as many times as the limit (in our example 4 times) sets.
    It will proceed by subsets taking in one single letter, and would produce all the subsets (subsets of 2 instances, subsets of 3 instances, finally subsets of 4 instances) until the ceil limit is attained.
  2. rangeAbstractPartitions
    Given a ceil limit, say 4, and an input vector, say [ABC], would generate all the possible combinations without limiting itself to produce only those where each instance of the input vector would appear just once (for such a thing you may refer to my fullCollection() script) but producing even all the combinations where each given input letter would appear as many times as the limit (in our example 4 times) sets.
    Will produce only those subsets whose length matches the given ceil limit (therefore in our limit example of 4, only subsets whose length is 4).
  3. DNA
    This is the script which will first run the rangeAbstractPartitions script, and then for each produced entry would yield even all the anagrams.
Test them in the active forms to understand at a glimpse what they do.

For the DNA script (but not for the Partition scripts) we are taking avail of a few previously defined scripts, therefore they have to be included in your script to make the former work; for the codes along with all the explanations on their workings you can peruse the documentation in their respective files, for I won't repat here all that has been already documented there!


All this bountiful (©) stuff for free
Please keep this website commented string as my only "reward"
allAnagrams() hasher()
highestLast() & highestFirst() dealEntries()

Now your codes, and after each code the active form and a few explanations.

ABSTRACT PARTITIONS
The code and the form and the explanations for this script

function abstractPartitions(array, repeat, complexOutput){
/* If complexOutput, returns array of arrays of array (slightly faster)
* else unfolds to return array of arrays.
* Requires gen 4++ browsers, using concat()
*/
//validate:
if(!array|| !array.length|| typeof(array)!="object"){
 return new Array(0)};
//initialize:
var output=new Array(0);
var rows=new Array(0);
var columns=array.length;
 for(var i=0;i<array.length;i++){
 var L=++output.length-1
 output[L]=new Array(0)
 var LL=++output[L].length-1
 output[L][LL]=new Array(0)
 output[L][LL][++output[L][LL].length-1]=
 array[i];
 rows[++rows.length-1]=0;
 }
repeat= (repeat&&repeat>0&&!isNaN(parseInt(repeat)))?
parseInt(repeat):1;
/**********RUNTIME**********/
while(--repeat>0){
 for(var still=0, C=0; C<columns; C++){
 if(still==C){var storeStillLength=output[still].length};
 var fixedLength=output[C].length;
  for(var R=rows[C]; R<fixedLength; R++){
   var L=++output[still].length-1;
   output[still][L]=new Array(0);
   output[still][L][++output[still][L].length-1]=array[still]
   output[still][L]=output[still][L].concat(output[C][R])
  }
 rows[still]=storeStillLength;
 C=(C==columns-1)?++still-1:C;
 }
}
/**********runtime OVER**********/
//streamline:
if(complexOutput){return output}
else{
var simplerOutput=new Array(0)
for(var z=0;z<output.length;z++){
 for(var z2=0;z2<output[z].length;z2++){
 simplerOutput[++simplerOutput.length-1]=output[z][z2]
 }
}
return simplerOutput};/* keep this comment to reuse freely:
http://www.unitedscripters.com */}

TEST ABSTRACT PARTITIONS
Withespace separated Vector:
Settings:
REPEAT
Delacroix

Arranging this script has been incredibly tough: you may regard this statement unusual only as long as, borrowing the script from someone's else sweat and efforts, you never took the chance to deal with this problem by yourself: so believe me, it required two weeks to find out the right conception.
The workings of the still variable are similar to the workings of the still variable used in the linearCollection() script which can be found clicking here, so read there to understand how the still variable works in the loop.
Under each letter (column) is gradually stored a set of combinations (rows) that all have in common a derivation form the leading column letter (A or B or C...): each row therefore starts with the leading letter (still variable, so array[still]).
One big difficulty is to slice off the newly generated subset in order to prevent the next loop from starting assembling combinations engaging the already used combinations: the storeStillLength variable takes care of that: for each column it keeps track of the level from where the latest generated combinations start being disposed, and this is critical because each row has a different such level: so we have a rows array which will store all the latest generated entries starting indexes, for each column: when we loop, we loop starting from such rows numbers, see:
for(var R=rows[C]; R<fixedLength; R++){
Also fixedLength is necessary since we will update the output length in the process, and therefore we need a variable that stores the output length before we start updating it;if we would have set as a limit something like the output.length itself, the loop would have never come to a close.


RANGED ABSTRACT PARTITIONS
The code and the form and the explanations for this script

function rangeAbstractPartitions(array, range){
/*returns array of arrays
* Requires gen 4++ browsers: using concat(), slice(), push(), shift()
*/
//validate:
if(!array|| !array.length|| typeof(array)!="object"){
 return new Array(0)};
range=(range && !isNaN(parseInt(range)))?
parseInt(range):1;
//initialize:
var output=new Array(0);
var startIndex=new Array(0);
var s=++startIndex.length-1;
startIndex[s]=1;
var temp=new Array(0);
for(var i=0;i<1;i++){
 var t=++temp.length-1
 temp[t]=new Array(0)
 for(var ii=0;ii<range;ii++){
  temp[t][++temp[t].length-1]=array[0]
 }
}
/**********RUNTIME**********/
while(--range>=-1){
output=output.concat(temp);
 var previousTempLength=temp.length;
 var previousStartIndexLength=startIndex.length;
 for(var t=0;t<previousTempLength;t++){
  for(var t2=startIndex[t];t2<array.length;t2++){
   var T=++temp.length-1
   temp[T]=temp[t].slice(0);/*dodge pointer by slice()*/
   temp[T].shift()
   temp[T].push(array[t2])
   var S=++startIndex.length-1;
   startIndex[S]=t2;
  }
 }
temp=temp.slice(previousTempLength)
startIndex=startIndex.slice(previousStartIndexLength)
}
return output;/* keep this comment to reuse freely:
http://www.unitedscripters.com */}

TEST RANGE ABSTRACT PARTITIONS
Withespace separated Vector:
Settings:
REPEAT
Salvador Dali

The script above is a bit different from the abstract partitions without range: it performs all by changing gradually the input by building up a starting row such as [AAAAAA] whose length matches the given range; then it goes on shifting (removing from head) and pushing (adding to tail) and saving the generated set (in order to reintroduce it in the loop soon after, for being shifted and pushed again), until it has crossed a full range of transformations.
The startIndex array is meant to keep a symmetrical record of each newly generated entry: in fact each generated entry must be able to spot its equivalent-level entry in the startIndex array.
In fact an entry such as, say, AAC should not start pushing in with A but with C: for if it would push in A, it would generate ACA: but such a combination A+A+C, as you can see clearly (AAC --< ACA!), was already there! So the subsequent elaboration of this subset (AAC) must start with C: and generate therefore not ACA but ACC . Hence, the startIndex array takes care to store for each newly generated subset the level it must start pushing in upon engagement, when the subset's back to its turn to generate a brand new subsets of combinations.


DNA I-CHING ALGORITHM
The code and the form and the explanations for this script

function DNA(array, range, partitionTYPE, sorted, noSift, limit){
/* Requires: rangeAbstractPartitions()
* Requires: allAnagrams()
* Requires: all dependancies of allAnagrams() - see online documentation at:
* http://www.unitedscripters.com
* Requires: if partitionTYPE: abstractPartitions()
*/
//validate:
if(!array|| !array.length|| typeof(array)!="object"){
 return new Array(0)};
range=(range && !isNaN(parseInt(range)))?
parseInt(range):1;
//initialize:
var output=new Array(0);
var midway;
if(!partitionTYPE){
midway=rangeAbstractPartitions(array, range)}
else{midway=abstractPartitions(array, range)};
for(var i=0;i<midway.length;i++){
var X=allAnagrams(midway[i], sorted, noSift, limit)
output=output.concat(X)
}
return output;/* keep this comment to reuse freely:
http://www.unitedscripters.com */}

TEST DNA I-CHING ALGORITHM
Pamela Anderson
Withespace separated Vector:
I CHING STYLE? Check:
[imposes sifting on the anagrams]
Settings:
REPEAT
ANAGRAM Settings:
Each anagram limits to:
Salvador Dali

This script is a mere consequence of the other ones, and the only thing it adds to them is the anagram script I have detailed clicking here: you have to read that documentation to understand hwo anagrams work.
The only thing I feel like stressing is that if you select in within the anagram settings of the form a limit value, the outcome would:
  1. Always show those combinations which are composed of the same letters (such as BBB or CCCC): in fact such a string gets parsed and anagrammed by the DNA script, but since the anagram of an input whose elements are all identical is still an anagram identical to the input string, well therefore whenever setting a limit to the anagrams, at least one instance of those entries composed by identical chars will be present. Anagrams are not performed on the whole output, but on each single entry of the output!! Therefore at least one instance of each combinations would be present, and on each of them the anagram possible limit is applied: this means that at least one instance for each generated Partition will be in place.
  2. Since the Partitions always produce an amount, whenever you set a limit to the anagrams, this limit won't be set to the whole outcome, but to each time the allAnagrams function included in the DNA script is called in: and since this happens on each entry generated by the Abstract Partitions, for:
    for(var i=0;i<midway.length;i++){
    var X=allAnagrams(midway[i])

    well the consequence is that the limit is set on each invocation: therefore you will certainly get an output whose amount is higher than the set limit for the very simple reason the limit is not set on the whole outcome but on each single entry.
    Obviously if you'd use a function that sets a limit by selecting a random output on the whole outcome after it has been used a limit on each single entry, that would produce the kind of limit you probably think of: a precisely matching limit.
  3. Arguments: give an array as input, set a range like in the ranged Abstract Partitions, then if you pass partitionTYPE argument as zero (default) would use ranged Partitions, otherwise the progressive partitions. All the subsequent arguments are optionals for the anagram function (see its own file).