|
|
|
|
|
|
|
|
|
POWER BINARY SEARCH WITH PHP. COMBINATORIAL ALGORITHMS: ALL COMBINATIONS OR RANGED COMBINATIONS, MAKE ANAGRAMS LIKE ARRAY PERMUTATIONS.
|
|
PHP implementations of javascript functions already sported on this website. Many javascript functions perform tasks whose utility in Php too is obvious, so here a few of them are turned into Php codex.
Though the complete documentations are on the linked javascript documents, a brief summary is provided here too, with special care to those cases where the PHP implementation differs from its javascript version.
|
|
October 2004 |
|
{ @ }
|
|
|
|
BINARY SEARCH PHP IMPLEMENTATION
|
|
A PHP Binary Search On Steroids
|
This is a Php binary search implementation that I drafted, with minor changes, on the same (and earlier) javascript version I devised time ago.
Though you should still refer to that javascript documentation for the full details, yet I can here repeat a few basic things.
Raffaello Sanzio (Raphael) paintings
|
Firstly, this binary search does a bit more than what standard binary searches do: for instance, it can guess whether the input array, which must always have been previously sorted (or your binary search will fail), has been sorted in direct or inverse order (an obvious thing that none the less, perhaps rather surprising, most binary search codes forget to deal with).
Then, if your input array hosts strings, you can arrange so to make your search not on the whole string but only on substrings of it, from the beginning till a defined x amount of chars.
Keep in mind that though these additional features imply additional conditional checks, no performance issue can truly be feared in: a binary search is able to spot in less than 30 moves a match in a one million entries array: thus even 3 or 4 more conditional checks in an environment where the algorithm performs at most 30 rounds can not set an issue in the least if not for the sake of the bias and of the thesis.
The arguments are as follows:
- Input array.
- Element you want to find.
- sortArray parameter defaults to zero. If passed as 1, before being scanned the input array will be sorted by sort (till november 2005 it used natcasesort but that caused an overlooked problem, because natcasesort does not reindex the array, thus the entries get ordered but their keys were kept unmodified: this would make a binary search fail).
- caseInsensitive parameter, defaults to zero. If passed as 1, makes the search case insensitive (this presumes your array hosts strings: only String data types can be case sensitive!)
- getSubstring parameter, defaults to zero. If passed as 1, compares on each input array entry not on each entry as a whole but on a substring of them from the beginning till the length of the $find parameter (this presumes your array hosts strings and that your $find parameter is a string too - and not for instance a number: you can get sub-strings only of strings!)
- arrayCheckThisIndex parameter: please refer to the javascript version documentation for this advanced feature.
Upon failure the algorithm returns null.
Please note that returning zero would be a mistake: a binary search returns by default the array index of the found match, namely a number; as such, it could well be zero if the match was per chance in the very first array slot, for arrays gets indexed from number zero included onward. So zero can not be a flag for a failure, for zero could rather be a successfully returned & found entry: at index position 0.
$foo=binarySearch(range('a', 'z'), 'd');
| The Php Power Binary Search Code |
|
|
A Joan Miro painting
|
LINEARCOLLECTION IMPLEMENTATION
|
|
A more than imagined searched for algorithm
|
Though with a few variations, this ia a PHP implementation of a javascript that I called linearCollection - perhaps not a happy name but I couldn't find a better one.
My experience with search engines queries proved that this seems an algorithmic pattern that is sought for quite more often that one could suspect.
What the function does is this, and I am positive this simple example will make itself and its pattern self evident: from an input of an array like, say, ABCDEF it draws:
AB, AC, AD, AE, AF
BC, BD, BE, BF
CD, CE, CF
DE, DF
EF
In fact:
$foo=linearCollection(array('a', 'b', 'c', 'd', 'e', 'f'));
That returns:
|
A Jean-Michel Basquiat painting
|
Unlike its javascript version, its arguments are a bit different, the function does a bit more, and as a trade-off consequence returns a slightly more complicated output.
Its arguments:
- First argument is the input array.
- Second argument, optional: defaults to 1 and, if set to something higher, means that rather than a collection like, say,
AB, AC, AD etc... you want a starting set of more elements than just the leading single one (the letter A, in the example).
$foo=linearCollection(array('a', 'b', 'c', 'd', 'e', 'f'), 3);
That returns:
- Third argument, optional: defaults to 1 and, if set to something higher, means that rather than a collection like, say,
AB, AC, AD etc... you want a trailing set of more elements than just the ending single one (the letter B or C or D, in the example).
$foo=linearCollection(array('a', 'b', 'c', 'd', 'e', 'f'), 1, 3);
That returns:
As you may have noticed the returned output is a bit complex: an array. Each of its entries is an array on its own, always of two entries alone.
These latter two entries are both an array again, and always at least of one entry (default): so a reference to what gets returned and stored in $foo can look like:
$foo[ NUMBER ][ 0 or 1 ][ 0 or NUMBER ];
| The Php Linear Collection Code |
|
|
A Dante Gabriel Rossetti painting
|
THE FULL COLLECTIONS PHP IMPLEMENTATION
|
|
Grab all combinations in an array
|
This Php script cumulates in one single function both the behaviours of the fullCollection javascript code and of the fullRangeCollection javascript code, with a few variations that I am now to document.
Unlike the javascript versions that make the combinations also returning the original array entries, this PHP implementations only and exclusively returns the array numerical indexes: this because those indexes are actually enough and all you need to grab immediately the equivalent entry in the original input array - once you know the index, you know what matters.
Of course, you could argue that this is a "waste" of space for it produces two arrays: the input one and the result array, which always have to coexist in order to retrieve the actual entries of the former from the latter; yet this Php implementation is meant to stress to your eyes a fact: you should not run such somewhat a complex algorithm every time you need to make all the combinations out of an array of x length (size): you'd rather run it once and then store that result so to use it back as a map on whatever array whose length either is inferior or matches that of the array used to produce such stored result the first time. This returned result should therefore been seen by you as a very useful map that can be used and resued on many arrays once produced, and without any need to produce it again if you store it - maybe by serialize.
Whereas the previous script featured here, the so called linearCollection, made only one set of combinations (the binary ones, so to call them), this script makes all the possible combinations: not just AB, AC, AD etc but also ABC ABD ABE ACD ACE etc... - but does not the permutations: that is from an input array like ABCDEF (or 012345, for that matter) it can make:
$foo=collections( range('a','f') );
|
A Edvard Munch painting |
You have all the combinations that are possible, but within those combination you don't have the permutations of the positions too: that is in the set:
[48] => Array
(
[0] => 1
[1] => 3
[2] => 4
[3] => 5
)
you will not have also the position swaps ( permutations) like 1453 or 1534: you only have the combination namely all the possible sets where all the numbers appear at least once, but not also the different positions within that set of numbers.
You may have noticed that the function produced first the groups of the sets of two numbers, then the group of the sets of three numbers, then the group of the set of four numbers, and so on.
If you want only one specific set of those groups (say the sets within the range 4?), pass to the function a second argument, which must be a number: if lower than 2, defaults to 2; if by mistake higher than the input array length, it defaults to such length ( all combinations, that is: for the last and highest combination set available in a set is the one whose length is the length of the input array itself). Also, if this argument is passed as zero, it would still assume you meant you wanted all the combinations, for it just makes no sense running an algorithm with the intention to have nothing (zero) of its results; I hope this makes sense to you.
So, instance to set only the range of 3:
$foo=collections(array(0,1,2,3,12), 3);
| The Php Collections Code |
|
|
A James Rosenquist painting
|
ANAGRAMS IMPLEMENTATION
|
|
Make anagrams of an array by PHP
|
An algorithm implemented on the javascript version I devised.
Be very, very careful when running this algorithm: making the anagrams of more than ten letter long string may produce scores of millions of entries: 9 letters is 362,880 possible anagrams, and it grows exponentially by each newly added char! Producing millions of entries can indeed pose a performance issue, and that's not the algorithm's fault when we're at dealing with such numbers - especially considering that PHP is not a compiled language.
The script arguments are as follows:
- input: must be an Array, or if a String it gets split by default into an array, char by char.
- sorted: optional; if you pass this second argument, the output array is sorted so that it gets returned with an alphabetical order.
Since the algorithm returns an array whose each entry is again an array listing char by char a set of combinations (an anagram, that is), if you pass this argument be aware that each array appended to the backbone array will be rejoined to form a string (only way to sort the output: PHP doesn't sort arrays of arrays, unless we use some usort): thus the returned result would be a simpler array of strings.
You may want to consider passing this argument as a white space if you want to sort, which is what I suggest if you decide to pass it.
If passed, remember that the output can be then scanned only by a foreach loop, and not by a numerical ordered loop: in fact in PHP sorting an array implies that its numerical indexes remain unaffected - that is, you could find index 79 at the beginning: sorting in PHP sorts by value but leaves the indexes unaffected!
- limit: optional, a number; you can limit their max amount of anagrams produced. The limited anagrams are anyway different at each run because before applying the limit by curtailing the array when the limit is attained, the output array gets shuffled
$foo=anagrams('input', ' ', 10);
That shuffles (though perhaps a better solution was possible: a random generationn of indexes to pick - for $limit times) and so it prints, for instance, in two different calls of the same line:
| The Php Anagrams Code |
|
|
A Han-Wu Shen painting
|
|
|