I'm stacked at math question with php!
Let's say we have:
$first = "3707682248186045564102137590742467172304310498516787723642221858460240158712832";
$second = "23846232839228381";
$result = bcmod($first,$second);
echo $result;
// $result = 3433268;
How to calculate the $first variable (if we dont know it) if only we have $result and the $second value ?
Actually not exact value but should be close to it, so when doing
bcmod($first, $second);
it will give the $result value equal to 3433268
Yes,
bcmod('3433268',$second);
also gives 3433268!
I appreciate all your help, thank you guys!
Any number of numbers could have given that result. Recovering a number from its remainder when divided by something is impossible.
the problem is this: ... the mod function is not bijective ... in other words, there is no inverse function ...
let's say we calculate 10 mod 7 we get 3 ... (10 is congruent to 3 mod 7)
if we calculate 17 mod 7 we also get 3 ... (17 is also congruent to 3 mod 7)
24 mod 7 ... 3
so ... if i give you the 3 and the 7 ... and tell you the operation was "mod" ... which number do i want to hear from you? ... 10? ... 17? ... 24?
all those numbers belong the the same remainder class ... but over the body of real numbers, every remainder class has an infinite amount of members ... therefore, if you want to reverse "mod 7", there is an infinite amount of possible functions which are candidates for the inverse of the operation you want to reverse ... but you have no information which one will be the right one ...
by reducing a number to it's remainder class (the mod function does just this), information is lost ... there is no way of getting that information back ...
Related
I've come to a mathematical problem which for I can't program the logic.
Let me explain it with an example:
Let's say I have 4 holes and 3 marbles, the holes are in order and my marbles are A,B and C and also in order.
I need to get every posible ORDERED combination:
ABC4
AB3C
A2BC
1ABC
This is very simple, but what if the number of holes changes? Let's say now I have 5 holes.
ABC45
AB3C5
A2BC5
1ABC5
AB34C
A2B4C
1AB4C
A23BC
1A3BC
12ABC
Now let's say we have 5 holes and 4 marbles.
ABCD5
ABC4D
AB3CD
A2BCD
1ABCD
And this can be any number of holes and any number of marbles.
The number of combinations is given by:
$combinations = factorial($number_of_holes)/(factorial($number_of_marbles)*factorial($number_of_holes-$number_of_marbles)))
(Here it is the factorial function in case you need it)
function factorial($number) {
if ($number < 2) {
return 1;
} else {
return ($number * factorial($number-1));
}
}
What I need and can't figure out how to program, is a function or a loop or something, that returns an array with the position of the holes, given X numbers of holes and Y number of marbles.
For first example it would be: [[4],[3],[2],[1]], for second: [[4,5],[2,5],[1,5],[3,4],[2,4],[1,5],[2,3],[1,3],[1,2]], for third: [[5],[4],[3],[2],[1]].
It doesn't have to be returned in order, I just need all the elements.
As you can see, another approach is the complementary or inverse or don't know how to call it, but the solution is every combinations of X number of free holes given Y number of holes, so, If I have 10 holes, and 5 marbles, there would be 5 free holes, the array returned would be every combination of 5 that can be formed with (1,2,3,4,5,6,7,8,9,10), which are 252 combinations, and what I need is the 252 combinations.
Examples for the 2nd approach:
Given an array=[1,2,3,4], return every combination for sets of 2 and 3.
Sets of 2
[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
Sets of 3
[[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
What I need is the logic to do this, I'm trying to do it in PHP, but I just can't figure out how to do it.
The function would receive the array and the set size and would return the array of sets:
function getCombinations($array,$setize){
//magic code which I can't figure out
return array(sets);
}
I hope this is clear enough and someone can help me, I've been stuck for several days now, but it seems to be just too much for me to handle by myself.
This post, PHP algorithm to generate all combinations of a specific size from a single set, is for all possible combinations, repeating the elements and order doesn't matter, its a good lead, I did read it, but it doesn't solve my problem, it's very different. I need them without repeating the elements and ordered as explained.
Let's say if I have already a set of [3,4] in my array, I don't want [4,3] as an other set.
Here's a recursive solution in PHP:
function getCombinations($array, $setsize){
if($setsize == 0)
return [[]];
// generate combinations including the first element by generating combinations for
// the remainder of the array with one less element and prepending the first element:
$sets = getCombinations(array_slice($array, 1), $setsize - 1);
foreach ($sets as &$combo) {
array_unshift($combo, $array[0]);
}
// generate combinations not including the first element and add them to the list:
if(count($array) > $setsize)
$sets = array_merge($sets, getCombinations(array_slice($array, 1), $setsize));
return $sets;
}
// test:
print_r(getCombinations([1, 2, 3, 4], 3));
Algorithm works like this:
If setsize is 0 then you return a single, empty combination
Otherwise, generate all combinations that include the first element, by recursively generating all combinations off the array excluding the first element with setsize - 1 elements, and then prepending the first element to each of them.
Then, if the array size is greater than setsize (meaning including the first element is not compulsory), generate all the combinations for the rest of the list and add them to the ones we generated in the second step.
So basically at each step you need to consider whether an element will be included or excluded in the combination, and merge together the set of combinations representing both choices.
This code:
$g = 2e3;
echo $g;
echo <br>;
echo "var_dump g gives:<br>";
Displays:
2000
float(2000)
I don't understand why it wouldn't display "8" and "float(8)"? Isn't 2 to the 3rd power equal to 8 ??
I tried looking for this question on this website already. Any help would be greatly appreciated. I did figure out that for 2e2 it displays 200. So it sounds like it just adds that many zeros to the end of the number instead of finding the 3rd power of 2. When I search for how to write exponential in php, the answers I've found said to use 'e' or 'E', but that doesn't seem to work or I've forgotten basic math. I'm sure somebody on here has a very simple answer for me.
Ok so why does $g = 2^3; give me 1? How can I write 2 to the 3rd power in php?
It's called scientific notation (or in this case "E notation").
2e3 is the same as 2 x 10^3, which is 2000.
If you want 2^3, you can use
$g = pow(2, 3);
Or in PHP 5.6+:
$g = 2**3;
Note: You need to use pow() (or **) because in PHP, when you do $g = 2^3;, you are doing 2 XOR 3.
When you read something like xey that is called scientific notation. It represents x times 10 to the power of y, or essentilly, add y zeroes to x (for positive values of y). So in this case, it's 2 * 10^3 = 2,000
2e3 is scientific notation for 2000.0. It is the same as 2.0e03. Use the pow() function:
echo pow(2, 3); // 8
I've been searching for a while to try and arrive at some sort of solution for a problem that is currently roadblocking a task I'm trying to complete.
I've come across a few solutions in other programming languages that I really can't understand despite my attempts at doing so. I've also seen a lot of terminology surrounding this problem such as permutations, refactoring, subset sums, coins in a dollar, etc.
If I'm going about this the wrong way, please do feel free to let me know.
Here's the problem in a nutshell:
Given a set (array) of numbers,
ex: 2, 3, 7, 14,
how could I find what combinations of those numbers add up to (or equal) a specific sum, ex: 14.
An example of some of the potential combinations for the above example numbers:
3 + 3 + 3 + 3 + 2
7 + 3 + 2 + 2
7 + 7
14
Since the problem I'm trying to solve is in PHP, I'd love if there were a solution that could be offered in that language. If not, even if someone could better explain what the problem is that I'm trying to solve, and potential methods of doing so, I'd be greatly appreciative.
Or again if I might be going about this the wrong way, I'm all ears.
To generate ALL solutions you are going to need to use some kind of backtracking, "guess" if the first number is in the solution or not, and recurse for each of the possibilities (it is needed to sum the result, or it is not).
Something like the following pseudo-code:
genResults(array, sum, currentResult):
if (sum == 0): //stop clause, found a series summing to to correct number
print currentResult
else if (sum < 0): //failing stop clause, passed the required number
return
else if (array.length == 0): //failing stop clause, exhausted the array
return
else:
//find all solutions reachable while using the first number (can use it multiple times)
currentResult.addLast(array[0])
genResults(array, sum - array[0], currentResult)
//clean up
currentResult.removeLast()
//find all solutions reachable while NOT using first number
genResults(array+1, sum, currentResult)
//in the above array+1 means the subarray starting from the 2nd element
Here's what I have managed to come up with thus far, based on amit's feedback and example, and some other examples.
So far it appears to be working - but I'm not 100% certain.
$totals = array();
$x=0;
function getAllCombinations($ind, $denom, $n, $vals=array()){
global $totals, $x;
if ($n == 0){
foreach ($vals as $key => $qty){
for(; $qty>0; $qty--){
$totals[$x][] = $denom[$key];
}
}
$x++;
return;
}
if ($ind == count($denom)) return;
$currdenom = $denom[$ind];
for ($i=0;$i<=($n/$currdenom);$i++){
$vals[$ind] = $i;
getAllCombinations($ind+1,$denom,$n-($i*$currdenom),$vals);
}
}
$array = array(3, 5, 7, 14);
$sum = 30;
getAllCombinations(0, $array, $sum);
var_dump($totals);
I need to generate a random pairs of numbers (floats) , within a certain range .
Basically those are points for [Lat,Lng] pairs (Longitude - latitude coordinates)
I thought This would be very straight forward with
<?php echo (rand(0,60).'.'.rand(0,99999999999999).' || '); // yes, a string is ok...?>
but it did not give me the control over how many numbers after the float point (resolution) - which I need fixed.
So the next phase was :
<?php echo (rand(0,60*pow(10,6)))/pow(10,6).' || '; //pow(10,$f) where $ is the resolution ?>
and this works . sort of ..
sometimes it produces results like
22.212346 || 33.134 || 36.870757 || //(rare , but does happen)
but hey - coordinates are from -90 to 90 (lon) and -180 to 180 (lan) - what about the minus ?
echo (rand(0,-180*pow(10,9)))/pow(10,9).' || ';
that should do it .. and combining all together should give me somehow a random string like
23.0239423525 || -135.937419777
so after all this introduction - here is Are my question(s) .
Being the newbie that I am - am I missing something ? is there no built-in function to generate random floats with a negative to positive range in PHP ?
Why is the function above sometimes turns only resolution 3,4 or 5 if it is told to return 6 (i did not apply any ABS or ROUND) - is there an automatic rounding in php ? and if there is , how to avoid it ?
I have noticed that the "random" is not so random - the generated numbers are always more or less series between a range - close to one another . is the PHP random a simple very-very-very fast rotating counter ?
how do I EXCLUDE a range from this generated range ?? (or actually and array of ranges)
I know these are a lot of questions, but any help / thought would be great ! (and if the first one is answered positively, the rest can almost be ignored :-)
The rand() function can take a negative min so maybe you can do this:
$num = mt_rand(-180000000, 180000000)/1000000;
echo number_format($num, 6);
if you want 6 places after decimal point.
In terms of excluding a range you may have to do it in two steps. First consider the ranges that you do want. Lets say you have 3 ranges from which you want to generate the random number. range 1 = -180 to -10, range 2 = 10 - 100 and range 3 = 120 - 180. Then you can generate a random number from 1 to 3 inclusive, use that to pick one range and then generate the number in that range.
I know similar questions come up a lot and there's probably no definitive answer, but I want to generate five unique random numbers from a subset of numbers that is potentially infinite (maybe 0-20, or 0-1,000,000).
The only catch is that I don't want to have to run while loops or fill an array.
My current method is to simply generate five random numbers from a subset minus the last five numbers. If any of the numbers match each other, then they go to their respective place at the end of the subset. So if the fourth number matches any other number, it will bet set to the 4th from the last number.
Does anyone have a method that is "random enough" and doesn't involve costly loops or arrays?
Please keep in mind this a curiosity, not some mission-critical problem. I would appreciate it if everyone didn't post "why are you having this problem?" answers. I am just looking for ideas.
Thanks a lot!
One random number call is enough.
If you want to choose a subset of 5 unique numbers in range 1-n, then select a random number in 1 to (n choose r).
Keep a 1-1 mapping from 1 to (n choose r) to the set of possible 5 element subsets, and you are done. This mapping is standard and can be found on the web, for instance here: http://msdn.microsoft.com/en-us/library/aa289166%28VS.71%29.aspx
As an example:
Consider the problem of generating a subset of two numbers from five numbers:
The possible 2 element subset of {1,..., 5} are
1. {1,2}
2. {1,3}
3. {1,4}
4. {1,5}
5. {2,3}
6. {2,4}
7. {2,5}
8. {3,4}
9. {3,5}
10. {4,5}
Now 5 choose 2 is 10.
So we select a random number from 1 to 10. Say we got 8. Now we generate the 8th element in the sequence above: which gives {3,4}, so the two numbers you want are 3 and 4.
The msdn page I linked to, shows you a method to generate the set, given the number. i.e. given 8, it gives back the set {3,4}.
Your best option is a loop, as in:
$max = 20;
$numels = 5;
$vals = array();
while (count($vals) < $numels) {
$cur = rand(0, $max);
if (!in_array($cur, $vals))
$vals[] = $cur;
}
For small ranges, you can use array_rand:
$max = 20;
$numels = 5;
$range = range(0, $max);
$vals = array_rand($range, $numels);
You could also generate a number between 0 and max, another between 0 and max-1, ... between 0 and max-4. Then you would sum x to the n-th generated number where x is the number calculated in this fashion:
Take the number generated in the n-th iteration and assign it to x
if it's larger or equal to that generated in the first iteration, increment it
if this new number is larger or equal to that generated (and corrected) in the second iteration, increment it
...
if this new number is larger or equal to that generated (and corrected) in the (n-1)-th iteration increment it
The mapping is like this:
1 2 3 4 5 6 7 8 9 (take 4)
1 2 3 4 5 6 7 8 9 (gives 4)
1 2 3 4 5 6 7 8 (take 5)
1 2 3 5 6 7 8 9 (gives 6)
1 2 3 4 5 6 7 (take 6)
1 2 3 5 7 8 9 (gives 8)
1 2 3 4 5 6 (take 5)
1 2 3 5 7 9 (gives 7)
example, last extraction:
x = 5
x >= 4? x == 6
x >= 6? x == 7
x >= 8? x == 7
The general form of this question is really interesting. Should one select from a pool of elements (and remove them from the pool) or should one loop "while hitting" an already taken element?
As far as I can tell, the python library implementation for random.sample chooses at runtime between the two methods depending on the proportion of the size of the input list and the number of elements to select.
A comment from the source code:
# When the number of selections is small compared to the
# population, then tracking selections is efficient, requiring
# only a small set and an occasional reselection. For
# a larger number of selections, the pool tracking method is
# preferred since the list takes less space than the
# set and it doesn't suffer from frequent reselections.
In the specific instance that the OP mentions however (selecting 5 numbers), I think that looping "while hitting a taken number" is ok, unless the pseudo random generator is broken.
Since you are just looking for different ideas here's one:
Call out to Random.org to generate the set of random numbers you need.
If you know the size N then keep each number with probability 5/N generate a random number between 0 and 1 and if it is less than 5/N keep the item. Stop when we have 5 items.
If we don't know N use resorvoir sampling.
An implementation of Artefacto's second solution above in C#, as a helper and an extension method on ICollection:
static class Program {
public static IEnumerable<int> Subset(int max) {
Random random = new Random();
List<int> selections = new List<int>();
for (int space = max; space > 0; space--) {
int selection = random.Next(space);
int offset = selections.TakeWhile((n, i) => n <= selection + i).Count();
selections.Insert(offset, selection + offset);
yield return selection + offset;
}
}
public static IEnumerable<T> Random<T>(this ICollection<T> collection) {
return Subset(collection.Count).Select(collection.ElementAt);
}
static void Main(string[] args) {
Subset(10000).Take(10).ToList().ForEach(Console.WriteLine);
"abcdefghijklmnopqrstuvwxyz".ToArray().Random().Take(5).ToList().ForEach(Console.WriteLine);
}
}
I know we are trying to avoid loops, but just in case this helps someone, you can use a HashSet instead of a List. This is very efficient on a sparse collection where collisions are somewhat rare.
var hs = new HashSet<int>();
var rand = new Random();
for(int i=0; i<10000; i++)
{
int n;
while(true)
{
n = rand.Next(0, 10000000);
if(!hs.Contains(n)) {break;}
}
hs.Add(n);
}