I want to set a matrix with random numbers.
I used a function to create a 0 matrix first, then loop through every cell and assign a random number to it.
function getRandomArbitrary(min, max) {
let value = Math.random() * (max - min) + min;
if (value === 0)
return getRandomArbitrary(min, max);
return value;
}
function matrix(m, n, d) {
return Array.apply(null, new Array(m)).map(
Array.prototype.valueOf,
Array.apply(null, new Array(n)).map(
function() {
return d;
}
)
);
}
let weight_1 = matrix(4, 3, 0);
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
weight_1[i][j] = getRandomArbitrary(-1, 1);
}
}
console.table(weight_1)
When I run the code, I get the following output.
As can be seen in the picture, the random value changes only when i changes. Is this related to JS being asynchronous or because random numbers generated by Math.random has a relation to timestamp?
Array.prototype.valueOf is Object.prototype.valueOf, and simply returns the receiver value (this argument). It does not create a copy of the array - so you are mapping to an outer array that contains the same inner array at every index. Instead, use
function matrix(m, n, d) {
return Array.apply(null, new Array(m)).map(
function() {
return Array.apply(null, new Array(n)).map(
function() {
return d;
}
);
}
);
}
or the simpler and more conventionally formatted
function matrix(m, n, d) {
return Array.from({length: m}, () =>
Array.from({length: n}, () =>
d
)
);
}
Also you might want to make d a callback function and call it, so that you create your matrix directly by matrix(4, 3, () => getRandomArbitrary(-1, 1)) instead of initialising it with 0 and then looping it to change the values.
Related
I have an exercise about JavaScript. This exercise requires me to use higher-order functions. I have managed to specify some of the functions so far, but when I try to execute the code, the result does not seem to work properly. I have some images to give you an idea, hopefully, you can help me correct this.
The thread is: Write the function loop(loops, number, func), which runs the given function the given number of times. Also write the simple functions halve() and square().
This is my code:
function loop(loops, number, func) {
var loops = function(n) {
for (var i = 0; i < n; i++) {
if (i < 0) {
console.log('Programme ended')
}
if (i > 0) {
return n;
}
}
}
}
var halve = function(n) {
return n / 2
}
var square = function(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Your current loop function declares an inner function and then exits. Ie, nothing actually happens -
function loop(loops,number,func){
// declare loops function
var loops= function(n){
// ...
}
// exit `loop` function
}
One such fix might be to run the supplied func a number of times in a for loop, like #code_monk suggest. Another option would be to use recursion -
function loop (count, input, func) {
if (count <= 0)
return input
else
return loop(count - 1, func(input), func)
}
function times10 (num) {
return num * 10
}
console.log(loop(3, 5, times10))
// 5000
so first things first: Higher-Order functions are functions that work on other functions.
The reason why you get undefined is because you are calling a function which doesn't return anything.
function x(parameter){
result = parameter + 1;
}
// -> returns undefined every time
console.log(x(5));
// -> undefined
function y(parameter){
return parameter+1;
}
// -> returns a value that can be used later, for example in console.log
console.log(y(5));
// -> 6
Second, you are using n for your for loop when you should probably use loops so it does the intended code as many times as "loops" indicates instead of the number you insert (i.e. 200, 5, 99).
By having the "console.log" inside a loop you may get a lot of undesired "programme ended" in your output so in my version I kept it out of the loop.
The other two answers given are pretty complete I believe but if you want to keep the for loop here goes:
function loop(loops, number, func){
if(loops>0){
for(let i = 0; i< loops; i++){ // let and const are the new ES6 bindings (instead of var)
number = func(number)
}
return number
}
else{
return "Programme ended"
}
}
function halve(n) { // maybe it's just me but using function declarations feels cleaner
return n / 2;
}
function square(n) {
return n ** 2;
}
console.log(halve(50));
console.log(loop(5, 200, halve));
console.log(loop(3, 5, square));
console.log(loop(-1, 99, halve));
Here's one way
const loop = (loops, n, fn) => {
for (let i=0; i<loops; i++) {
console.log( fn(n) );
}
};
const halve = (n) => {
return n / 2;
};
const square = (n) => {
return n ** 2;
};
loop(2,3,halve);
loop(4,5,square);
I'm trying to get whatever number is the most frequently occuring number in an array, so for an array containing 1,2,10,5,1 the result should be 1. The code I wrote returns me the frequency for each number, so 1 occurs twice, 2 occurs once, 10 occurs once etc. Any suggestions how I can fix my result?
function mode(arr) {
var uniqNum = {};
var numCounter = function(num, counter) {
if(!uniqNum.hasOwnProperty(num)) {
uniqNum[num] = 1;
} else {
uniqNum[num] ++;
}
};
arr.forEach(numCounter);
return uniqNum;
}
I've kept your code unchanged and added some extra statements. Here is the demo: http://codepen.io/PiotrBerebecki/pen/rrdxRo
function mode(arr) {
var uniqNum = {};
var numCounter = function(num, counter) {
if(!uniqNum.hasOwnProperty(num)) {
uniqNum[num] = 1;
} else {
uniqNum[num] ++;
}
};
arr.forEach(numCounter);
return Object.keys(uniqNum)
.sort((a,b) => uniqNum[b] - uniqNum[a]) // sort by frequency
.filter((val,ind,array) => uniqNum[array[0]] == uniqNum[val]) // leave only most frequent
.map(val => Number(val)); // convert text to number
}
console.log( JSON.stringify(mode([3,3,2,4,4])) ) // [3,4]
console.log( JSON.stringify(mode([2,4,3,3])) ) // [3]
I think it could be done only with a little modification to your forEach loop and the assistance of another auxiliary data structure:
function mode(arr) {
var freq = [], uniqNum = {}, i;
arr.forEach(function (num) {
uniqNum[num] = i = (uniqNum[num] || 0) + 1;
freq[i] = (freq[i] || []).concat(num);
});
return freq[freq.length - 1];
}
console.log(mode([1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 6, 7, 1, 6]));
With only one iteration over all the elements of the array we can gather enough information to print out the result:
uniqNum is the set you created to gather info about the element's frequency.
freq will be an array which last element will contain an array with the elements of higher frequency.
Fiddle. Hope it helps.
First we want to make an array where we count the number of occurrences of a certain value up to that point.
Then we use the reduce function to return an array of values read from the original array for the indexes whose values have the current max appearances. We redefine max and empty the final output array of modes (if new max is established) as we go along. We want this to be a collection in case there is a tie for maximum appearances.
Additional advantage of the below is that it doesn't require sort which is more expensive o(nlog n) and keeps the time complexity down to just linear. I also wanted to keep the functions used down to only two (map and reduce) as it is all that is need in this case.
edit: fixed a major bug uniqNum[e] += 1 instead of uniqNum[e] + 1 which went unnoticed as my initial case array was still returning expected result. Also made the syntax more concise in favor of more comments.
var arr = [1,2,10,5,1,5,2,2,5,3,3];
//global max to keep track of which value has most appearances.
var max = -1;
var uniqNum = {};
var modeArray = arr.map(function(e) {
//create array that counts appearances of the value up to that point starting from beginning of the input arr array.
if(!uniqNum.hasOwnProperty(e)) {
uniqNum[e] = 1;
return 1;
} else {
return uniqNum[e] += 1;
}
//reduce the above appearance count array into an array that only contains values of the modes
}).reduce(function (modes, e1, i) {
//if max gets beaten then redefine the mode array to only include the new max appearance value.
if(e1 > max){
//redefining max
max = e1;
//returning only the new max element
return [arr[i]];
//if its a tie we still want to include the current value but we don't want to empty the array.
}else if(e1 == max){
//append onto the modes array the co-max value
return[...modes, arr[i]];
}
return modes;
},[]);
alert(modeArray);
Here is a test you can run of my solution against #acontell. In my browser (Chrome with V8) my solution was around three-four times faster for arrays with large number of repeating values and even bigger advantage with distributions with lower number of repeating values. #acontell 's is a cleaner looking solution for sure, but definitely not faster in execution.
var arr = [];
for(var i=0; i < 100000; i++){
arr.push(Math.floor(Math.random() * (100 - 1)) + 1);
}
console.time("test");
test();
function test(){
var max = -1;
var uniqNum = {};
var modeArray = arr.map(function(e) {
//create array that counts appearances of the value up to that point starting from beginning of the input arr array.
if(!uniqNum.hasOwnProperty(e)) {
uniqNum[e] = 1;
return 1;
} else {
return uniqNum[e] += 1;
}
//reduce the above appearance count array into an array that only contains values of the modes
}).reduce(function (modes, e1, i) {
//if max gets beaten then redefine the mode array to only include the new max appearance value.
if(e1 > max){
//redefining max
max = e1;
//returning only the new max element
return [arr[i]];
//if its a tie we still want to include the current value but we don't want to empty the array.
}else if(e1 == max){
//append onto the modes array the co-max value
modes.push(arr[i])
return modes;
}
return modes;
},[]);
}
console.timeEnd("test");
console.time("test1");
test1();
function test1 () {
var freq = [],
uniqNum = {},
i;
arr.forEach(function(num) {
uniqNum[num] = i = (uniqNum[num] || 0) + 1;
freq[i] = (freq[i] || []).concat(num);
});
return freq[freq.length - 1];
}
console.timeEnd("test1");
I've tried as an exercise to solve this with native js functions.
var arr = [1,2,10,5,1];
// groupBy number
var x = arr.reduce(
function(ac, cur){
ac[cur]?(ac[cur] = ac[cur] + 1):ac[cur] = 1;
return ac;
}, {}
);
// sort in order of frequencies
var res = Object.keys(x).sort(
function(a,b){ return x[a] < x[b]}
);
res[0] has the most frequent element
I have written a function for partitioning a number:
var combinations = function (i) {
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
return inner(i, [], 1);
}
In second step I would like to add a memoization to this algorithm, but can't think of implementing it the right way, beause there is no return statement until the very end (when return is specified e.g. in faactorial or fibbinacci I can add the memoization).
Can anybody drive me to the right direction?
[edit]
I need this algorithm to be as fast as possible. This is a competition for a kata at codewars: link
There is a requirement it must be executed under 6000ms for input up to 330.
That's the best algorithm I can think of, except how to store the partial results.
Here's a much simpler code that works:
function nr_partitions(n) { return p(n, n); }
function p(sum,largest) {
if (largest == 0) { return 0; }
if (sum == 0) { return 1; }
if (sum < 0) { return 0; }
return p(sum, largest-1) + p(sum-largest, largest);
}
It uses a well-known recurrence, p(n,k) = p(n,k-1) + p(n-k, k), where p(n.k) denotes the number of partitions of n where the largest part is at most k (e.g. p(3, 2)=2 because we only count 1+1+1,1+2, but not 3). For k=n we get the number of all partitions of n.
Adding memozation involves storing dictionary mapping pairs (sum, largest) to p(sum, largest).
I would go along the lines of:
var cache = {};
var combinations = function (i) {
if ( cache[i] ){
return cache[i];
};
var mem = [];
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
cache[i] = inner(i, [], 1);
return cache[i];
}
But you'll have to modify your algorithm to make use of that cache (compute the biggest terms first ?)
Depending on your other requirements, you might want to consider using underscore.js which has its own _.memoize function.
The secret of memoization is that it exploits how closures work. When you define a function inside another scope, it has access to everything in that scope. When you return that function to somewhere outside the scope, it carries references to everything it can see inside the scope.
So to implement memorization, you need to make a function that returns another function, one that does the memorization check before calling the inner one.
Your code will look something like this:
/**
* Because we'll be returning "a function that returns a function" below,
* this needs to be executed immediately so combinations() is just
* a standalone function.
*/
var combinations = (function(i) {
/**
* mem needs to stay outside the scope of your inner function.
* If it's in a closure like this, JavaScript will keep its value
* around as long as combinations still exists.
*/
var mem = [];
/**
* A memoization wrapper should return a memoized function
*/
return function(i) {
/**
* Check if mem[i] is set and return it if it has been
*/
if(mem[i] !== undefined) {
console.log('returning memoized value');
return mem[i];
}
function inner(n, r, m) {
for (var k = m; k <= n; k++) {
if (k == n) {
r.push(k);
mem[r] = 1;
return mem;
}
else {
var copy = r.slice(0);
copy.push(k);
inner(n - k, copy, k);
}
}
}
/**
* If the value needs to be computed, we can set it at the same time
* as we return it instead of putting it in a temporary variable.
*/
console.log('computed');
return mem[i] = inner(i, [], 1);
}
}()); /** <--- That's the rest of the automatic execution */
console.log(combinations(5));
console.log(combinations(5));
I'm trying to create a function that will multiply all parameters passed into it. The amount of parameters that can be passed to the function can vary. So far I have this
var multiply = function () {
var i, sum = 0;
for (i = 0; i < arguments.length; i++) {
sum *= arguments[i];
}
return sum;
};
When I call it like this - multiply(10, 5, 5) - It returns 0 when the answer should be 250 (10 x 5 x 5). What am I doing wrong here?
Multiplying any number with 0 is 0.
So set var sum = 1;
You could do it also by using Array.prototype.reduce() :
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
It does not really have a benefit over the for loop except that you make clear that you want to accumulate the value by using a function that is intended for this.
var multiply = function () {
return Array.prototype.reduce.call(arguments, function(a, b) {
return a * b;
});
};
You need to use the Array.prototype.reduce.call construct because arguments is only an array like object it most environments.
Since ES6 the answer would be =>
const multiply = (..args) => args.reduce((accum, val) => accum * val, 1);
I want to pick random number of inputs randomly in an array of input elements..
If i use the below method i Can get one random item
jQuery.jQueryRandom = 0;
jQuery.extend(jQuery.expr[":"],
{
random: function(a, i, m, r) {
if (i == 0) {
jQuery.jQueryRandom = Math.floor(Math.random() * r.length);
};
return i == jQuery.jQueryRandom;
}
});
$("input:random").prop('id')
But I want random number i=of items to be picked randomly in an array.
You can use jQuery's .filter() method with a function:
$('div').filter(function(){
return (Math.round(Math.random()) == 1);
}).css({background: 'red'});
jsFiddle example
You currently are checking if the index is equal to the random number. Maybe it´s better to generate a random number for each input and check if its bigger then 1 or smaller. So randomize a number between 0 and 2. something like:
jQuery.extend(jQuery.expr[":"],
{
random: function(a, i, m, r) {
return Math.random() > 0.5;
}
});
alert( $("input:random").length );
Also if you get a prop from an element, it will only get it from the first one.
I'm proposing a non-jQuery answer to you question on how to get count elements randomly from an array arr
var pickRandom = function (arr, count) {
var out = [], i, pick, clone = arr.slice(0, arr.length);
for (i = 0; i < count; i ++) {
pick = Math.floor(Math.random() * clone.length);
if (clone[pick] !== undefined) {
out.push(clone[pick]);
clone.splice(pick, 1);
}
}
return out;
};
This function makes sure that the original array is preserved and handles undefined values correctly