i need to make numbers permutations (with some features), but
my .php and mysql is not so improved.
The numbers will be posted by a .html form, max 10 numbers.
It will permute the numbers to create unique thousand number:
if 4 different numbers is posted by the .html input (1,2,3,4):
will return: 1234,1243,1324,1342... (24 unique combinations)
if 5 different numbers is posted by the .html input (1,2,3,4,5):
will return: 1234,1235,1243,... (120 unique combinations)
The number will only repeat if it posted, as (1,1,2,4)
will return: 1124, 1142, 1214,...(12 unique combinations)
Then i need to store the combinations into a mysql row, comma separated.
I tryed this function(found here Permutations - all possible sets of numbers):
$p = permutate(array('1','2','3'));
foreach($p as $perm)
print join("",$perm)."|\n";
function permutate($elements, $perm = array(), &$permArray = array())
{
if(empty($elements))
{
array_push($permArray,$perm); return;
}
for($i=0;$i<=count($elements)-1;$i++)
{
array_push($perm,$elements[$i]);
$tmp = $elements; array_splice($tmp,$i,1);
permutate($tmp,$perm,$permArray);
array_pop($perm);
}
return $permArray;
}
The output: 123| 132| 213| 231| 312| 321|
But when is given:
$p = permutate(array('1','2','2'));
the output is: 122| 122| 212| 221| 212| 221|
When should be 122|212|221
I tried array_unique, but did´t work, probally becouse i did it wrong.
Thx
First convert each result to string and then de-dupe the array:
$p = permutate(array('1','2','3'));
$result = array();
foreach($p as $perm) {
$result[]=join("",$perm);
}
$result = array_unique($result);
print join("|", $result);
Related
First, I have looked through dozens of similar questions/answers on this site an have not found any type of solution I could use or modify to use for this problem. There are a lot of things that come into play with this. I got close but it kept running out of memory or other resource so here I am.
I need to create a function that takes a set of arrays and returns all combinations with a specific set of rules. So to start I pull the arrays. There are 9 to start of all various lengths. 4 of the arrays are duplicate set of 4 other individual arrays. Heres how I pull the arrays to start, just so you have an idea of how the data looks.
$prodA1 = Products::where('type','a')->pluck('id')->toArray();
$prodA2 = Products::where('type','a')->pluck('id')->toArray();
$prodB1 = Products::where('type','b')->pluck('id')->toArray();
$prodB2 = Products::where('type','b')->pluck('id')->toArray();
$prodC1 = Products::where('type','c')->pluck('id')->toArray();
$prodC2 = Products::where('type','c')->pluck('id')->toArray();
$prodD1 = Products::where('type','d')->pluck('id')->toArray();
$prodD2 = Products::where('type','d')->pluck('id')->toArray();
$prodE = Products::where('type','e')->pluck('id')->toArray();
I need all set of arrays to be array('prodA1','prodA2','prodB1','prodB2','prodC1','prodC2','prodD1','prodD2','prodE') with the values being IDs bot the name of the array.
Each returned array must be unique
Each individual array can have as many as 96 ids but they all vary
I found the below function which if I add a take(5) to the above so it limits the output seems to produce at least all the combinations which I can then apply other rules to but it takes forever to run. This is the closest I have gotten though, there has to be a faster solution to this. Any help would be appreciated.
public function combinations($arrays, $i = 0) {
if (!isset($arrays[$i])) {
return array();
}
if ($i == count($arrays) - 1) {
return $arrays[$i];
}
// get combinations from subsequent arrays
$tmp = $this->combinations($arrays, $i + 1);
$result = array();
// concat each array from tmp with each element from $arrays[$i]
foreach ($arrays[$i] as $v) {
foreach ($tmp as $t) {
$result[] = is_array($t) ?
array_merge(array($v), $t) :
array($v, $t);
}
}
return $result;
}
EDIT:
The input wound be a set of 9 arrays with ids in them. For instance:
$prodA1 = array(1,2,3,4,5);
$prodA2 = array(1,2,3,4,5);
$prodB1 = array(6,7,8,9);
$prodB2 = array(6,7,8,9);
$prodC1 = array(10,11,12,13);
$prodC2 = array(10,11,12,13);
$prodD1 = array(14,15,16,17);
$prodD2 = array(14,15,16,17);
$prodE = array(18,19,20,21);
returns would look something like
array(1,2,6,7,10,11,14,15,18)
array(1,4,6,8,10,12,14,16,18)
so all the results would be unique, each one would contain 9 values made up of 2 prodA,2 prodB, 2 prodC, 2 prodD and 1 prodE
Hope that clears it up a little.
I have this code:
public function get_names($number){
$names = array(
'None',
'Anton',
'bertha',
'Cesa',
'Dori',
'Egon',
'Frank',
'Gollum',
'Hans',
'Kane',
'Linus',
'Moose',
'Nandor',
'Oliver',
'Paul',
'Reese');
$bin = strrev(decbin($number));
$len = strlen($bin);
$output = array();
foreach(str_split($bin) as $key=>$char)
{
if ($key == sizeof($names)){
break;
}
if($char == 1)
{
array_push($output,$names[$key]);
}
}
return $output;
}
When I now call the function with number - let's say - 32256 I would get an array with "Kane, Linus, Moose, Nandor, Oliver, Paul".
Can anyone tell me what I would have to do when I want to give a certain names array and wanna get the number as a result where the certain bits are included? So exactly the other way around.
I found that code somewhere which works fine. But I need it vice versa.
Thanks in advance!
Andreas
EDIT: I want to know the decimal number when I e.g. have an array with "Anton, bertha,Cesa". I want to store those in a database instead of storing arrays with names each time. And when I need the names I just take the decimal number from database and use my function to get my name arrays.
If you just take the position in your $names array as being the bit position, you raise 2 to this position to give it the correct bit position and keep a running total of the items found...
$input = ["Cesa", "Gollum", "Hans"];
$output = 0;
foreach ( $input as $digit ) {
$output += pow(2,array_search($digit, $names ));
}
echo $output; // 392
with
$input = ["Kane", "Linus", "Moose", "Nandor", "Oliver", "Paul"];
gives
32256
Or as Barmar points out in his comment, you can save the lookup by inverting the names array using array_flip() which will mean that looking up each key will give the position in the array...
$output = 0;
$names = array_flip($names);
foreach ( $input as $digit ) {
$output += pow(2,$names[$digit]);
}
echo $output;
I am using a text file as little database, and each line has this format:
3692|Giovanni|giojo982|0005405
9797|Stefano|stefy734|45367
2566|Marco|markkkk998|355647689
4721|Roberto|robn88|809678741
I need to order them alphabetically maintaining their indexes, if it's possible.
At the moment, I'm using this code, but in this situation logically it doesn't work any more.
Reading this post How can I sort arrays and data in PHP? I have not found nothing similar to my scenario.
So, I'm wondering... is there a solution?
$db_friends = "db_friends.txt";
$dblines = file($db_friends);
if(isset($_GET['A-Z'])) {
asort($dblines);
}
if(isset($_GET['Z-A'])) {
arsort($dblines);
}
foreach($dblines as $key => $profile) {
list($uni_id, $name_surname, $textnum_id, $num_id) = explode("|", $profile);
echo $name_surname;
}
A-Z
Z-A
How can I solve it?
I assume by alphabetically that you're trying to sort alphabetically by the name in the second column. The problem is, asort() and arsort() perform too simple a comparison to deal with the type of data you're giving them. They're just going to see the rows as strings, and sort by the number in the first column. One way to address this is by splitting the rows before sorting.
$db_friends = "db_friends.txt";
$dblines = file($db_friends);
// split each line into an array
$dblines = array_map(function($line){
return explode('|', $line);
}, $dblines);
Then you can sort by the second column more easily. Using uasort(), you'll maintain the index association.
if (isset($_GET['A-Z'])) {
uasort($dblines, function(array $a, array $b) {
return strcmp($a[1], $b[1]);
});
}
if (isset($_GET['Z-A'])) {
uasort($dblines, function(array $a, array $b) {
return strcmp($b[1], $a[1]);
});
}
Obviously if you make that change, you'll no longer need to explode when you iterate the sorted array, as it was already done in the first step.
foreach ($dblines as $key => $profile) {
list($uni_id, $name_surname, $textnum_id, $num_id) = $profile;
echo $name_surname;
}
You can avoid the complexity of a uasort() call if you just position your columns in the order that you want to alphabetize them. This method has the added benefit of sorting all column data from left to right. This means, regardless of sorting direction (asc or desc), my method will sort $rows[0], then $row[1], then $row[2], then $row[3].
I have also logically combined your two if statements and set ASC as the default sorting direction.
Code: (Demo)
$txt=['9999|Marco|markkkk998|355647689','1|Marco|markkkk998|355647689','3692|Giovanni|giojo982|0005405','9797|Stefano|stefy734|45367','2566|Marco|markkkk998|355647689','4721|Roberto|robn88|809678741'];
foreach($txt as $row){
$values=explode('|',$row);
$rows[]=[$values[1],$values[0],$values[2],$values[3]]; // just reposition Name column to be first column
}
if(isset($_GET['Z-A'])) {
arsort($rows); // this will sort each column from Left-Right using Z-A
}else{
asort($rows); // (default) this will sort each column from Left-Right using A-Z
}
// var_export($rows);
foreach($rows as $i=>$profile) {
echo "$i {$profile[0]}\n"; // name value
}
Output:
2 Giovanni
1 Marco
4 Marco
0 Marco
5 Roberto
3 Stefano
If I understood your question, you could try this function:
function sortValuesKeepKey($lines) {
//declare arrays to be used temporarily
$idNumbers = array();
$values = array();
$return = array();
//loop through each line and seperate the number at the beginning
//of the string from the values into 2 seperate arrays
foreach($lines as $line) {
$columns = explode("|", $line);
$id = array_shift($columns);
$idNumbers[] = $id;
$values[] = implode("|", $columns);
}
//sort the values without the numbers at the beginning
asort($values);
//loop through each value and readd the number originally at the beginning
//of the string
foreach($values as $key => $value) {
//use $key here to ensure your putting the right data back together.
$return[$key] = $idNumbers[$key]."|".$values[$key];
}
//return finished product
return $return;
}
Just pass it the lines as an array and it should return it ordered properly.
If you want to sort the values by name_surname, see the below code
$db_friends = "db_friends.txt";
$dblines = file($db_friends);
// loop the lines
foreach($dblines as $key => $profile) {
// explode each line with the delimiter
list($uni_id, $name_surname, $textnum_id, $num_id) = explode("|", $profile);
// create an array with name_surname as a key and the line as value
$array[$name_surname] = $profile;
}
// bases on the GET paramater sort the array.
if(isset($_GET['A-Z'])) {
ksort($array); //sort acceding
}
if(isset($_GET['Z-A'])) {
krsort($array); // sort descending
}
// loop the sorted array
foreach($array as $key => $value) {
echo $key; // display the name_surname.
}
I have already compared the data of a matrix, I have already counted the data of an array, but I have never counted, what is the repeated sequence of keys between the arrays, I want to make comparative between all sequences, and find out the maximum size of this section Repeated .. I have many hundreds of numbers that I should compare them between them, and find out the largest duplicate stretch between them, the maximum duplicity size that exists in a sequence, and that also exist in another sequence of the large array!
Finding repeating single elements can simply be done with in_array(). Repeating keys from different arrays is similarly easy with array_keys(). Neither really helps us since we are concerned with sequences, not single values.
<?php
header('Content-Type: text/html; charset=utf-8');
echo 'test - This is just for us to figure out, what is the size of the greatest duplication of stretches between the previous sequences'.'<br>';
$previous_results_manually_inserted = array(
array('12','21','34','1','51','87','42','49','37','119','101','7','111','17','11','19','2','15','6'),
array('3','5','1','18','61','75','92','84','36','81','2','07','90','2','71','17','08','51','37'),
array('81',75','92','84','36','81','2','07','90','2','17','65','44','73','27','30','41','74','88'),
);
foreach ( $previous_results_manually_inserted as $previous ) {
$match = preg_match("/.*$test.*/", $previous );
}
echo 'The largest repeated slice between these sequences is:';
echo implode(', ', $match ), "<br>\n"
output: 75','92','84','36','81','2','07','90','2'
Note: Final objective: the highest duplicity is 9 numbers. (In this example)
Thanks all.
The task is very similar to the algorithm for finding the largest common string. Can be solved as follows:
$arrs = [
['12','21','34','1','51','87','42','49','37','119','101','7','111','17','11','19','2','15','6'],
['3','5','1','18','61','75','92','84','36','81','2','07','90','2','71','17','08','51','37'],
['81','75','92','84','36','81','2','07','90','2','17','65','44','73','27','30','41','74','88'],
];
$sequence = [];
foreach($arrs as $offset => $item){
$sarr = array_slice($arrs , $offset+1);
$count = count($item);
foreach($sarr as $arr){
$str = join(',',$arr);
for($a = 0;$a<$count;$a++){
for($b = 1;$b<$count;$b++){
$needle = join(',',array_slice($item , $a , ($a + $b > $count ? $count : $b)));
if(strpos($str,$needle) !== false){
$sequence[(substr_count($needle,','))] = $needle;
}
}
}
}
}
echo array_pop($sequence).PHP_EOL;
//out : 75,92,84,36,81,2,07,90,2
I found this here PHP take all combinations
I modified it further to include n number of sets to the given array. However i am not able to figure out how to not get any duplicate numbers in a set. for example
If the output is
1 , 1, 3, 4
then it should remove the extra '1' and give it as
1,3,4
similarly if there are 2 outputs.
1,3,4,5 and 4,5,3,1
then it should remove one of the duplicate set as well.
I tried using array_unique and thought it could solve half of the issue however it gave a memory allocation error.
<?php
function permutations($arr,$n)
{
$res = array();
foreach ($arr as $w)
{
if ($n==1) $res[] = $w;
else
{
$perms = permutations($arr,$n-1);
foreach ($perms as $p)
{
$res[] = $w." ".$p;
}
}
}
return $res;
}
// Your array
$numbers = array(1,2,3,4,5,6,7);
// Get permutation by groups of n elements
for($i=1; $i<8; $i++)
$pe = permutations($numbers,$i);
$pe = array_unique($pe);
// Print it out
print_r($pe);
?>