You need to find some unknown, predetermined point in three-dimensional space, in the smallest number of attempts, using only a function that can return the distance from
any point you pass to it to the desired unknown point.
To solve the problem, first implement a function f that, by taking the coordinates of any point s(x, y, z), return the distance between that point and a conditionally unknown, randomly generated point
point you arbitrarily generate r(x, y, z), where x, y, z can be integers between
0 и 100.
For example, for an arbitrarily generated point r(0, 0, 10) and a point passed to the function
s(0, 0, 0), the result of the function would be as follows:
f(s) = 10 // the distance between s(0, 0, 0) and r(0, 0, 10) is 10
Next, implement the algorithm itself for the assignment. The algorithm should find the coordinates of
of an arbitrarily generated point with the least number of calls to the function f.
I have a randomizer instead of an algorithm, that's all I got. Help.
const pointToFound = {
x: 12,
y: 9,
z: 76,
};
let attemts = 0;
let isXFound = false;
let isYFound = false;
let isZFound = false;
const pointHistory = [];
const getRandomPoint = () => {
return {
x: isXFound ? isXFound : Math.floor(Math.random() * 101),
y: isYFound ? isYFound : Math.floor(Math.random() * 101),
z: isZFound ? isZFound : Math.floor(Math.random() * 101),
};
};
const getDifference = (point, pointToCompare) => {
return {
x:
Math.max(point.x, pointToCompare.x) - Math.min(point.x, pointToCompare.x),
y:
Math.max(point.y, pointToCompare.y) - Math.min(point.y, pointToCompare.y),
z:
Math.max(point.z, pointToCompare.z) - Math.min(point.z, pointToCompare.z),
};
};
const condition = !isXFound && !isYFound && !isZFound;
while (condition) {
const point = getRandomPoint();
const difference = getDifference(point, pointToFound);
pointHistory.push(point);
attemts += 1;
if (isXFound && isYFound && isZFound) {
console.log("Total attempts: ", attemts);
console.log(point);
break;
}
if (difference.x === 0 && !isXFound) {
isXFound = point.x;
}
if (difference.y === 0 && !isYFound) {
isYFound = point.y;
}
if (difference.z === 0 && !isZFound) {
isZFound = point.z;
}
}
console.log(pointHistory);
I have a randomizer instead of an algorithm, that's all I got. Help.
This can be done with at most 3 guesses and often with 2 guesses:
Let the first guess be [0, 0, 0], and ask for the distance
Find in the 100x100x100 cube all points that have that distance to [0, 0, 0]. There might be around 100-200 points that have that distance: consider all of these candidates.
Take the first candidate as the second guess and ask for the distance
Find among the other candidates the ones that have exactly that distance to the first candidate. Often there will be only one point that satisfies this condition. In that case we can return that candidate and only 2 guesses were necessary.
Otherwise (when there is more than one candidate remaining) repeat the previous step which will now certainly lead to a single point.
Here is an implementation that provides a blackbox function which chooses the secret point in a local variable, and which returns two functions: f for the caller to submit a guess, and report for the caller to verify the result of the algorithm and report on the number of guesses. This is not part of the algorithm itself, which is provided in the findPoint function.
const rnd = () => Math.floor(Math.random() * 101);
const distance = (a, b) =>
a.reduce((acc, x, i) => acc + (x - b[i]) ** 2, 0) ** 0.5;
function findPoint(f) {
// First guess is always the zero-point
let guess = [0, 0, 0];
let dist = f(guess);
if (dist === 0) return guess; // Extremely lucky!
// Find the points in the cube that have this distance to [0,0,0]
let candidates = [];
const limit = Math.min(100, Math.round(dist));
for (let x = 0; x <= limit; x++) {
const p = [x, limit, 0];
// Follow circle in X=x plane
while (p[1] >= 0 && p[2] <= limit) {
const d = distance(p, guess);
const diff = d - dist;
if (Math.abs(diff) < 1e-7) candidates.push([...p]);
if (diff >= 0) p[1]--;
else p[2]++;
}
}
// As long there are multiple candidates, continue with a guess
while (candidates.length > 1) {
const candidates2 = [];
// These guesses are taking the first candidate as guess
guess = candidates[0];
dist = f(guess);
if (dist === 0) return guess; // lucky!
for (const p of candidates) {
let d = distance(p, guess);
let diff = d - dist;
if (Math.abs(diff) < 1e-7) candidates2.push(p);
}
candidates = candidates2;
}
return candidates[0]; // Don't call f as we are sure!
}
function blackbox() {
const secret = [rnd(), rnd(), rnd()];
console.log("Secret", JSON.stringify(secret));
let guessCount = 0;
const f = guess => {
guessCount++;
const dist = distance(secret, guess);
console.log("Submitted guess " + JSON.stringify(guess) + " is at distance " + dist);
return dist;
};
const report = (result) => {
console.log("Number of guesses: " + guessCount);
console.log("The provided result is " + (distance(secret, result) ? "not" : "") + "correct");
}
return {f, report};
}
// Example run
const {f, report} = blackbox();
const result = findPoint(f);
console.log("Algorithm says the secret point is: " + JSON.stringify(result));
report(result);
Each run will generate a new secret point. When running this thousands of times it turns out that there is 1/9 probability that the algorithm needs a third guess. In the other 8/9 cases, the algorithm needs two guesses.
One idea is as follows:
You pick an initial random point, and for each dimension, find the exact value. How? For the sake of symmetry, suppose that you desire to find x of the target point. Increase by one the x, and compute the distance of the new point from the target point. If it goes further, it means that you should move in the opposite direction. Hence, you can run a binary search and get the distance to find the exact x of the target point. Otherwise, it means that you are going in the right direction along X-axis. So, do a binary search between all points with the same y and z such that their x values can change from x+1 to 100. A more formal solution comes in the following (just a pseudo-code).
You should also ask about the complexity of this solution. As the dimension of the point is constant (3) and checking these conditions take a constant time, the complexity of number of calling getDifference function is O(log(n)). What is n here? the length of valid range for coordinates (here is 100).
1. p: (x,y,z) <- Pick a random coordinate
2. dist: (dist_x, dist_y, dist_z) <- getDifference(p, TargetPoint)
3. For each dimension, do the following (i can be 0 (x), 1 (y), 2 (3)):
4. if(dist == 0):
5. isFound[i] <- p[i]
6. continue
7. new_i <- p[i] + 1
8. new_point <- p
9. new_point[i] <- new_i
10. new_dist <- getDifference(new_point, pointToFound)
11. if(new_dist == 0):
12. isFound[i] <- new_point[i];
13. continue
14. if(new_dist[i] > dist[i]):
15. isFound[i] <- binary_search for range [0, p[i]-1] to find the exact value of the pointToFound in dimension i
15. continue
16. else:
17. isFound[i] <- binary_search for range [p[i] + 1, 100] to find the exact value of the pointToFound in dimension i
18. continue
Following method will work for coordinates with positive or negative real values as well.
Let's say you are searching for the coordinates of point P. As the first query point, use origin O. Let the distance to the origin O be |PO|. At this point, you know that P is on the surface of sphere
(P.x)^2 + (P.y)^2 + (P.z)^2 = |PO|^2 (1)
As the second query point, use Q = (|PO|, 0, 0). Not likely but if you find the distance |PQ| zero, Q is the point you are looking for. Otherwise, you get another sphere equation, and you know that P is on the surface of this sphere as well:
(P.x - |PO|)^2 + (P.y)^2 + (P.z)^2 = |PQ|^2 (2)
Now, if you subtract (1) from (2), you get
(P.x - |PO|)^2 - (P.x)^2 = |PQ|^2 - |PO|^2 (3)
Since the only unknown in this equation is P.x you can get its value:
P.x = (((-|PQ|^2 + |PO|^2) / |PO|) + |PO|)/2)
Following similar steps, you can get P.y with R = (0, |PO|, 0) and P.z with S = (0, 0, |PO|). So, by using four query points O, Q, R, and S you can get the coordinates of P.
So I have some numbers x = 320232 y = 2301 z = 12020305. I want to round these numbers off using JavaScript so that they become x = 320000 y = 2300 z = 12000000.
I tried Math.round and Math.floor but turns out that they only work with decimal values like
a = 3.1; Math.round(a); // Outputs 3 and not whole numbers.
So my question is can we round of whole numbers using JavaScript and If yes then how?
Edit: I want it to the round of to the starting 3 digit places as seen in the variables above. Like If there was another variable called c = 423841 It should round off to become c = 424000.
You could work with the logarithm of ten and adjust the digits.
const
format = n => v => {
if (!v) return 0;
const l = Math.floor(Math.log10(Math.abs(v))) - n + 1;
return Math.round(v / 10 ** l) * 10 ** l;
};
console.log([0, -9876, 320232, 2301, 12020305, 123456789].map(format(3)));
The solution is to first calculate how many numbers need to be rounded away, and then use that in a round.
Math.round(1234/100)*100 would round to 1200 so we can use this to round. We then only need to determan what to replace 100 with in this example.
That is that would be a 1 followed by LENGTH - 3 zeros. That number can be calculated as it is 10 to the power of LENGTH - 3, in JS: 10 ** (length - 3).
var x = 320232;
var y = 2301;
var z = 12020305;
function my_round(number){
var org_number = number;
// calculate integer number
var count = 0;
if (number >= 1) ++count;
while (number / 10 >= 1) {
number /= 10;
++count;
}
// length - 3
count = Math.round(count) - 3;
if (count < 0){
count = 0;
}
// 10 to the power of (length - 3)
var helper = 10 ** count;
return Math.round(org_number/helper)*helper;
}
alert(my_round(x));
alert(my_round(y));
alert(my_round(z));
It is not the prettiest code, though I tried to make it explainable code.
This should work:
function roundToNthPlace(input, n) {
let powerOfTen = 10 ** n
return Math.round(input/powerOfTen) * powerOfTen;
}
console.log([320232, 2301,12020305, 423841].map(input => roundToNthPlace(input, 3)));
Output: [320000, 2000, 12020000, 424000]
This is part of a bigger problem I try to solve in an exercise. It looks like this:
x is 10 times more likely to appear than y.
z appears 2x less often than y.
I solved this by calculating a single unit like this:
const x = 100;
const y = 10;
const z = 5;
const unit = 100 / (x + y + z);
unit equals 0.87
So when I do (0.87) + (0.87 * 10) + (0.87 * 5) I get 100%(almost)
Then I generate a random number between 0 and 1.
const randomNumber = Math.random();
function getValue() {
if (randomNumber <= 0.87) {
console.log('x');
} else if (randomNumber > 0.87 && randomNumber < 95.7) {
console.log('y');
} else console.log('z');
}
getValue();
If value<0.87 then I log out x, if value < 0.87+(0.087*10) I log y etc
Can anyone recommend a more logical and elegant way than this?
Your way looks clean for me except the fact that randomNumber > 0.87 is redundant.
if you store the value x, y and z in an array, you can probably write some cleaner code for example:
let prob = [100, 10, 5];
let sum = prob.reduce((a, b) => a + b, 0);
let normalizedProb = prob.map(p => p / sum);
let cummulativeProb = normalizedProb.map((cummulative => p => cummulative += p)(0));
for (let i = 0; i <= 50; i++) {
let r = Math.random();
console.log(cummulativeProb.filter(p => r >= p).length);
}
Also, you may want to read this post for faster implementation (in python though). However, the code will be more complicated for sure.
Since the weights are small integers, you can duplicate the x, y and z in an array, and just pick one random cell of the array:
let choices = "zyyxxxxxxxxxxxxxxxxxxxx";
console.log(choices[Math.floor(Math.random() * 23)]);
Here the magic number 23 is the number of choices, 1+2+20; and Math.floor(Math.random() * 23) is a random integer uniformly at random in range [0, 22] (both bounds included). See also:
Generating random whole numbers in JavaScript in a specific range?
I have hard time wrapping my head around how to get this to work so I came to ask the help of the brilliant minds in here.
The thing is, I want to reverse the process of the below equation so that I get X from the given Y and Z.
Z = [ ( X * 30 ) % Y ]
For the use-case, a user inputs number Y and then presses ENTER, the system get's the current server time and then multiplies that by 30. The user will then be given the remainder of the server time in format HHMMssxxx, (hmm, xxx here is the millisecond.. I don't know the format letter for millisecond.. hehe..), divided by Y - that is (X*30) % Y where X is the current server time converted to int.
How can I do this in reverse?
The catch is, X should not be greater than 2359999 -> (23:59:59.999) the maximum time value for a 24-hour clock.
Supposedly I have Z = 32, Y = 400, how can I find X?
I know that it's possible to have multiple answers. Here's what I came up so far but I think this is not very optimal in terms of performance.
function getTimeIDx(rem, codeIndexer) {
var times = [];
for(var i = 0; i < 2400000; i++) {
if((i * 30) % codeIndexer == rem) {
var str = i.toString(),
l = str.length;
if(l < 9)
str = '000000000'.substr(0, 9 - l) + str;
str = str.substr(0, 2) + ':' + str.substr(2, 2) + ':' + str.substr(4, 2) + '.' + str.substr(6);
if(/^(?:[0-1]?\d|2[0-3]):(?:[0-5]?\d):(?:[0-5]+\d)/.test(str))
times.push(str);
}
}
return times;
}
Is there some way to do this more efficiently? Is there something like a inverse modulo?
EDIT:
Updated code to check if the string is a valid time.
You cannot reverse it. Modulo is the remainder from a division operation.
Simplifying your equation. Z = Y % 2
Z is 0 for half of the values and 1 for the rest.
You can not solve for the dividend with just the remainder and the divisor.
Lets fill it into the equation:
32 = ( X * 30 ) % 400
Then this means that X * 30 is a multiple of 400 plus 32:
32
432
832
...
Now we could divide that by 30 to get x. That could be done in js like this:
function* reverse(Z, Y) {
for(let n = 0; ; n++)
yield (Z + Y * n) / 30;
}
Usable as:
for(let X of reverse(32, 400))
console.log(X);
Note that this loop will run forever as there are infinite results. Try it
How do I use JavaScript to calculate the x value in this formula?
(x * y) % z = 1
y and z are known integers.
For example, y = 7, z = 20. 3 multiplied by 7 results into 21, that divided by 20 results into remainder of 1. Solution x = 3.
(3 * 7) % 20 = 1
This is a math question, not a JavaScript question. Use the Extended Euclidean Algorithm. For example, to find the inverse of 7 modulo 20, start with these two equations:
20 = 0•7 + 1•20.
7 = 1•7 + 0•20.
Next, divide the two numbers on the left (20/7) and take the integer part (2). The subtract that times the bottom equation from the one above it:
20 = 0•7 + 1•20.
7 = 1•7 + 0•20.
6 = -2•7 + 1•20.
Repeat: The integer part of 7/6 is 1. Subtract one times the bottom equation from the one above it. The new equation is:
1 = 3•7 - 1•20.
Now you can see that 3 times 7 is 1 modulo 20. (Simultaneously, -1 times 20 is 1 modulo 7.)
Well, there's more than one number that is valid for x. x could also be 23 in this case (23 * 7 = 161, and 161 % 20 = 1). So you need to express the problem a bit differently as a starting point, such as "what is the lowest x that can solve the equation?"
If you're solving that then it is suddenly a different problem. You then only need to solve for two possibilities: (x * y) - z = 1, and (x * y) = 1. From there you can do a little algebra to solve for x.