I have 2 strings like this
$s1="32.56.86.90.23";
$s2="11.25.32.90.10";
I need to compare $s1 and $s2 and find if there are 2 or more numbers in common.
I am using this way
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
$result=array_diff($s1_ar,$s2_ar);
$rt1=5-count($result);
if($result>=2){ echo "YES"; } else {echo "no"; }
Since I need millions values of $s1 and $s2 and the code above seems to be slow, do you know alternative way to execute the work faster ?
I tested it with the following code, one million times, less than 2 seconds on my 3 years old laptop.
Loop 1M times takes no time, most time is used for displaying.
Comment off the display, 1M loops, 0.816432 seconds
Saved the results into a file, ~13.564MB, 0.731708 seconds
ob_start();
$t1 = microtime();
for($i=1; $i<=1000000; $i++) {
$s1="32.56.86.90.23";
$s2="10.25.30.90.10";
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
$result=array_diff($s1_ar,$s2_ar);
$rt1=5-count($result);
if($result>=2){ echo $i . " YES<br>"; } else {echo $i . " no<br>"; }
}
$out = ob_get_contents();
ob_end_clean();
var_dump($out);
echo '<p>'.(microtime() - $t1).'</p>';
Try this.
$s1="32.56.86.90.23";
$s2="11.23.32.90.10";
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
//assuming $s1_ar and $s2_ar both has unique values if not please make them unique
$result_array = array();
$hasMatch = 0;
for($i = 0; $i < count($s1_ar) && $i < count($s2_ar); $i++){
if(!isset($result_array[$s1_ar[$i]])){
$result_array[$s1_ar[$i]] = 1;
}else{
$result_array[$s1_ar[$i]]++;
}
if(!isset($result_array[$s2_ar[$i]])){
$result_array[$s2_ar[$i]] = 1;
}else{
$result_array[$s2_ar[$i]]++;
}
}
foreach($result_array as $result){
if($result >=2) $hasMatch++;
}
if($hasMatch >= 2)
echo "YES";
else
echo "NO";
I think it will solve your purpose.
Looking at: php array_intersect() efficiency
There's mention that array_intersect_key may be more efficient. But really it would be nice to have data and versions to compare results.
$s1 = "2.3.5.7.9.11.13.17";
$s2 = "2.3.4.5.6";
$s1 = array_flip(explode('.', $s1));
$s2 = array_flip(explode('.', $s2));
echo count(array_intersect_key($s1, $s2))>=2 ? 'yes' : 'no';
Output:
yes
I thought of a way to solve this in a 2*n complexity:
We loop one list and create an associative array from it's elements (LIST c) then we loop the second list and look up if the list c contains such an index/key ( c[element] ).
This shall be very light weighted :
$commons = 0;
$s1_fliped = array_flip($s1_ar)
foreach($s2_ar as $s2_el){
if ( isset($s1_fliped[$s2_el]) ){
$commons ++;
}
if($commons >=2) break;
});
Related
I'm writing a code to solve a problem.one of my functions is not working properly.
function check_factor($sqr,$num)
{
for($i = $sqr ; true ; $i++)
{
$n = pow($sqr,2) - $num;
$s = sqrt($n);
if(is_int($s))
{
return $i;
}
}
}
I know that $s is a "double" , but even when I limit my loop counter to 2,I'll get an endless loop.
What am I missing here? why the function doesnt simply return null? and why I get Infinite loop even when there are 2 iterations?
true is making it an infinite loop
you will always get an infinit loop because sqrt() returns float means
$s = sqrt($n);
$s is a float now
and your test is testing if $s is an integer so it will be an infinit loop even after $i=2 the loop will always stuck and the $i=2 in every loop but
if you change the code to this
<?php
function check_factor($sqr,$num)
{
echo "<br>";
for($i = 1 ; $i < 3 ; $i++)
{
echo " in the loop $i<br>";
$n = pow($sqr,2) - $num;
echo "$n<br>";
$s = sqrt($n);
echo "$s<br>";
if(is_int($s))
{
echo "in the if <br>";
return $i;
}
}
return 0;
}
$val=0;
$val = check_factor(5,2);
echo "<br>$val<br>";
?>
the out put should be like this
in the loop 1
23
4.7958315233127
in the loop 2
23
4.7958315233127
0
and that's it. i hope i helped.
According to the manual: PHP function sqrt() always returns a float and NEVER an integer.
Check http://php.net/manual/en/function.sqrt.php
This is my first StackOverFlow post.
I have an array of numbers, which I shuffle:
$nums = array("1","1","1","1","1","2","2","2","2","3","3","3","4","4","4");
shuffle($nums);
I am trying to identify a sequence/pattern of any three 3 identical numbers in a row in the shuffled array and
output the combined total of all sets of matching numbers.
The problem that I am running into seems to stem from attempting to compare the current number in the loop with the previous number (to see if they match).
When I echo the "previous" number it always outputs as "0". Thus I am unable to compare the current number and old number, which means I am not able to sum identify and sum a pattern of identical numbers.
Here is my code:
<?php
$t3count = 0;
$oldnum = 0;
$tots = 0;
$nums = array("1","1","1","1","1","2","2","2","2","3","3","3","4","4","4");
shuffle($nums);
foreach ($nums as $num) {
echo "$num: [$oldnum] ";
if ($num = $oldnum) {
$t3count++;
if ($t3count = 3) {
$tots = $num * $num;
$t3count = 0;
$oldnum = $num;
} else {
# do nonum
}
}
else {
$oldnum = $num;
}
# echo "<li>$num</li>";
}
echo "Your total is: $tots";
unset($num);
?>
Thank you.
You need to do comparison == not assignment = here:
if ($num = $oldnum)
and here:
if ($t3count = 3)
also this is probably going to bite you if i got the logic right
$t3count++;
if ($t3count == 3) {
how do you know which one counted to 3, id build nested arrays of like values first then process that.
you missed == to compare if ($num = $oldnum) and if ($t3count = 3)
replace with
if ($num == $oldnum)
if ($t3count == 3)
I'm a beginner with PHP (and programming in general).
To test what I've learned so far I wrote this code, which prints all the possibile combinations of a set number of dice with a certain number of faces. (you'll find the code at the end).
What I want to do is dynamically change the number of nested for loops according to the $dicenumber variable. Right now it can only process 3 dice, since the code is:
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
for ($d3=1; $d3 <= $d3value ; $d3++) {
array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
}
}
}
But I want to change it so that, for example, if $dicenumber were 2, it would produce something like:
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
array_push(${sum.($d1+$d2)}, "$d1"."$d2");
}
}
I want the code to process for whatever number $dicenumber may be, without limits. Looking around, it seems like I have to add some kind of recursive code, but I don't know how to do that. Any tips? Also, any feedback on what I did wrong in general, would be extremely helpful! thanks!
<?php
//defines the number and type of dice
$dicenumber = 3;
$dtype = 6;
//defines the maximum value of every die
for ($i=1; $i <=$dicenumber ; $i++) {
${d.$i.value} = $dtype;
}
//defines and array for each possible sum resulting from the roll of the given number of dice.
for ($i=$dicenumber; $i <= ($dtype*$dicenumber) ; $i++) {
${sum.$i} = array();
}
//the troublesome piece of code I want to change
for ($d1=1; $d1 <= $d1value ; $d1++) {
for ($d2=1; $d2 <= $d2value ; $d2++) {
for ($d3=1; $d3 <= $d3value ; $d3++) {
array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
}
}
}
//prints all the possible roll combinations, each line lists combination that share the same sum
for ($i=$dicenumber; $i <= ($dtype*$dicenumber); $i++) {
print join(" ", ${sum.$i})."<br />";
}
?>
Here we have a two-function process. The first function, buildArrays, creates arrays in the proper format to feed into the second function, allCombinations. So, for this example with 3 d6's in play, buildArrays will produce an array equivalent to this:
$data = array(
array(1, 2, 3, 4, 5, 6),
array(1, 2, 3, 4, 5, 6),
array(1, 2, 3, 4, 5, 6));
I will warn you that as you increase the number of dice and the number of sides, the number of possible combinations increases exponentially! This means that you could place a very large demand on the server, and both timeout and max memory limits will quickly come into play. The arrays generated could be very, very large and quickly consume more than the max memory limit. That said, here we go:
function buildArrays($dicenumber, $dtype){
for ($i = 0; $i<$dicenumber; $i++){
$tmp = array();
for ($j = 1; $j<=$dtype; $j++){
$tmp[] = $j;
}
$data[$i] = $tmp;
}
return $data;
}
function allCombinations($data){
$result = array(array()); //this is crucial, dark magic.
foreach ($data as $key => $array) {
$new_result = array();
foreach ($result as $old_element){
foreach ($array as $element){
if ($key == 0){
$new_result[] = $element;
} else {
$new_result[] = $old_element.$element;
}
}
$result = $new_result;
}
}
return $result;
}
//set variables
$dicenumber = 3;
$dtype = 6;
//set_time_limit(0); //You may need to uncomment this for large values.
//call functions
$data = buildArrays($dicenumber, $dtype);
$results = allCombinations($data);
//print out the results
foreach ($results as $result){
echo $result."<br/>";
}
N.B. This answer is a variant of the cartesian product code
If you have learned functions, you can do a recursive call and keep track of what dicenumber you're on, then increment it each call to the function (and end the loop once you've hit your #).
understanding basic recursion
I am trying to resolve project euler problem no 12 with PHP but it is taking too much time to process. I came across with similar processing problems of PHP while solving previous problems and I had to solve them in C++ just to test whether my approach is correct or not.
I want to know whether there is something wrong with my approach or somehow I can do something to make processing fast. Here is the code of my solution which works well for the triangle having 360 divisors. The link of problem is http://projecteuler.net/problem=12 and here is my code
<?php
set_time_limit(0);
ini_set('memory_limit', '1G');
$triangles = array(0);
$count = 1;
$numOfDivisiors = 0;
$lastTriangle = 0;
while($numOfDivisiors < 500){
$triangle = (int) $lastTriangle + (int) $count;
$factors = getFactors($triangle);
//$triangles[] = array('triangle' => $triangle, 'factors' => $factors, 'factorsCount' => count($factors));
$triangles[] = array('triangle' => $triangle, 'factorsCount' => count($factors));
$lastTriangle = $triangle;
$numOfDivisiors = count($factors);
$count++;
//echo '<pre>'; print_r(array('triangle' => $triangle, 'factorsCount' => count($factors), 'count' => $count)); echo '</pre>';
}
echo $numOfDivisiors; exit;
/**
for($i = 0 ; $i < 10 ; $i++){
}
**/
//echo '<pre>'; print_r($triangles); exit;
function getFactors($number){
$factors = array();
$break = false;
$count = 1;
while($break != true){
$remainder = $number % $count;
if($remainder == 0){
$factors[] = $count;
}
//echo $count." ".$number; exit;
if($count == $number){
$break = true;
}
$count++;
}
return $factors;
}
?>
use some maths.
triangle numbers can be generated by
n(n+1) /2
and that if you can find the prime factors, Adding 1 to their powers and multiplying together gives the number of divisors.
My PHP solution takes around 4 seconds and i think i can speed that up also
There are several ways to speed up your solution. The first one I'd point you at is the following:
if a * b = c then both a and b are factors of c
One of a and b will be <= to the square root of c
this should help speed up your solution
foreach(($_POST["msg"] as $mg) AND ($_POST["control"] as $id))
{
echo $mg;
echo $id;
}
i need make something like that, any way to do? i'm trying to get 10 mysql records and edit all of them
No, that won't work. The closest thing I can see to what you're trying to do is:
for($i = 0; $i < count($_POST["msg"]); $i++) {
echo $_POST["msg"][$i];
echo $_POST["control"][$i];
}
Assuming that "msg" and "control" will always contain the same amount of items.
Assuming both $_POST['msg'] and $_POST['control'] are actually arrays, have numeric keys (thanks #iMoses), and have the same length, you could use a for loop -
for ($i = 0; $i < count($_POST["msg"]); $i++){
$mg = $_POST['msg'][$i];
$id = $_POST['control'][$i];
}