1
11
12
1121
122111
112213
122211
....
I was trying to solve this problem. It goes like this.
I need to check the former line and write: the number and how many time it was repeated.
ex. 1 -> 1(number)1(time)
var antsArr = [[1]];
var n = 10;
for (var row = 1; row < n; row++) {
var lastCheckedNumber = 0;
var count = 1;
antsArr[row] = [];
for (var col = 0; col < antsArr[row-1].length; col++) {
if (lastCheckedNumber == 0) {
lastCheckedNumber = 1;
antsArr[row].push(lastCheckedNumber);
} else {
if (antsArr[row-1][col] == lastCheckedNumber) {
count++;
} else {
lastCheckedNumber = antsArr[row-1][col];
}
}
}
antsArr[row].push(count);
antsArr[row].push(lastCheckedNumber);
}
for (var i = 0; i < antsArr.length; i++) {
console.log(antsArr[i]);
}
I have been on this since 2 days ago.
It it so hard to solve by myself. I know it is really basic code to you guys.
But still if someone who has a really warm heart help me out, I will be so happy! :>
Try this:
JSFiddle Sample
function lookAndSay(seq){
var prev = seq[0];
var freq = 0;
var output = [];
seq.forEach(function(s){
if (s==prev){
freq++;
}
else{
output.push(prev);
output.push(freq);
prev = s;
freq = 1;
}
});
output.push(prev);
output.push(freq);
console.log(output);
return output;
}
// Sample: try on the first 11 sequences
var seq = [1];
for (var n=0; n<11; n++){
seq = lookAndSay(seq);
}
Quick explanation
The input sequence is a simple array containing all numbers in the sequence. The function iterates through the element in the sequence, count the frequency of the current occurring number. When it encounters a new number, it pushes the previously occurring number along with the frequency to the output.
Keep the iteration goes until it reaches the end, make sure the last occurring number and the frequency are added to the output and that's it.
I am not sure if this is right,as i didnt know about this sequence before.Please check and let me know if it works.
var hh=0;
function ls(j,j1)
{
var l1=j.length;
var fer=j.split('');
var str='';
var counter=1;
for(var t=0;t<fer.length;t++)
{
if(fer[t]==fer[t+1])
{
counter++;
}
else
{
str=str+""+""+fer[t]+counter;
counter=1;
}
}
console.log(str);
while(hh<5) //REPLACE THE NUMBER HERE TO CHANGE NUMBER OF COUNTS!
{
hh++;
//console.log(hh);
ls(str);
}
}
ls("1");
You can check out the working solution for in this fiddle here
You can solve this by splitting your logic into different modules.
So primarily you have 2 tasks -
For a give sequence of numbers(say [1,1,2]), you need to find the frequency distribution - something like - [1,2,2,1] which is the main logic.
Keep generating new distribution lists until a given number(say n).
So split them into 2 different functions and test them independently.
For task 1, code would look something like this -
/*
This takes an input [1,1,2] and return is freq - [1,2,2,1]
*/
function find_num_freq(arr){
var freq_list = [];
var val = arr[0];
var freq = 1;
for(i=1; i<arr.length; i++){
var curr_val = arr[i];
if(curr_val === val){
freq += 1;
}else{
//Add the values to the freq_list
freq_list.push([val, freq]);
val = curr_val;
freq = 1;
}
}
freq_list.push([val, freq]);
return freq_list;
}
For task 2, it keeps calling the above function for each line of results.
It's code would look something like this -
function look_n_say(n){
//Starting number
var seed = 1;
var antsArr = [[seed]];
for(var i = 0; i < n; i++){
var content = antsArr[i];
var freq_list = find_num_freq(content);
//freq_list give an array of [[ele, freq],[ele,freq]...]
//Flatten so that it's of the form - [ele,freq,ele,freq]
var freq_list_flat = flatten_list(freq_list);
antsArr.push(freq_list_flat);
}
return antsArr;
}
/**
This is used for flattening a list.
Eg - [[1],[1,1],[1,2]] => [1,1,1,1,2]
basically removes only first level nesting
**/
function flatten_list(li){
var flat_li = [];
li.forEach(
function(val){
for(ind in val){
flat_li.push(val[ind]);
}
}
);
return flat_li;
}
The output of this for the first 10 n values -
OUTPUT
n = 1:
[[1],[1,1]]
n = 2:
[[1],[1,1],[1,2]]
n = 3:
[[1],[1,1],[1,2],[1,1,2,1]]
n = 4:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1]]
n = 5:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3]]
n = 6:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1]]
n = 7:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1]]
n = 8:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1],[1,2,2,1,3,1,1,1,2,1,3,1,1,3]]
n = 9:
[[1],[1,1],[1,2],[1,1,2,1],[1,2,2,1,1,1],[1,1,2,2,1,3],[1,2,2,2,1,1,3,1],[1,1,2,3,1,2,3,1,1,1],[1,2,2,1,3,1,1,1,2,1,3,1,1,3],[1,1,2,2,1,1,3,1,1,3,2,1,1,1,3,1,1,2,3,1]]
So I need to take a date and convert it into one single number by adding up each digit, and when the sum exceeds 10, I need to add up the two digits. For the code below, I have 12/5/2000, which is 12+5+2000 = 2017. So 2+0+1+7 = 10 & 1+0 = 1. I get it down to one number and it works in Firebug (output of 1). However, it is not working in a coding test environment I am trying to use, so I suspect something is wrong. I know the code below is sloppy, so any ideas or help reformatting the code would be helpful! (Note: I am thinking it has to be a function embedded in a function, but haven't been able to get it to work yet.)
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
solution("2000, December 5");
You can just use a recursive function call
function numReduce(numArr){
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend","Reducing: "+numArr.join(","));
//Using the array's reduce method to add up each number
var total = numArr.reduce(function(a,b){return (+a)+(+b);});
//Just outputting to div for demostration
document.getElementById("log").insertAdjacentHTML("beforeend",": Total: "+total+"<br>");
if(total >= 10){
//Recursive call to numReduce if needed,
//convert the number to a string and then split so
//we will have an array of numbers
return numReduce((""+total).split(""));
}
return total;
}
function reduceDate(dateStr){
var arrayDate = new Date(dateStr);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
return numReduce([d,m+1,y]);
}
alert( reduceDate("2000, December 5") );
<div id="log"></div>
If this is your final code your function is not outputting anything. Try this:
var array = [];
var total = 0;
function solution(date) {
var arrayDate = new Date(date);
var d = arrayDate.getDate();
var m = arrayDate.getMonth();
var y = arrayDate.getFullYear();
array.push(d,m+1,y);
for(var i = array.length - 1; i >= 0; i--) {
total += array[i];
};
if(total%9 == 0) {
return 9;
} else
return total%9;
};
alert(solution("2000, December 5"));
It will alert the result in a dialog.
For a project I'm working on, I needed a Javascript function that would return a random number, in a given range, without repeating itself until the whole range is 'depleted'. As there was no such thing around, I have managed to create it myself.
The function will also require an id to be passed. This way, if you require multiple random numbers, each with their own history, the id keeps track of them all.
The function works, however I need some advice;
is this the 'proper' way to achieve what I want to achieve?
how fast will inArray() perform with very big ranges (maxNum) values? I have a feeling that large numbers will slow the function down, as it is randomizing numbers until it generates a number that is still 'valid' (i.e. not in the history array). But I can't figure out another way to do this..
The script:
var UniqueRandom = {
NumHistory: [],
generate: function (maxNum, id) {
if (!this.NumHistory[id]) this.NumHistory[id] = [];
if (maxNum >= 1) {
var current = Math.round(Math.random() * (maxNum - 1)), x = 0;
if (maxNum > 1 && this.NumHistory[id].length > 0) {
if (this.NumHistory[id].length !== maxNum) {
while ($.inArray(current, this.NumHistory[id]) !== -1) {
current = Math.round(Math.random() * (maxNum - 1));
x = x + 1;
}
this.NumHistory[id].push(current);
} else {
//reset
this.NumHistory[id] = [current];
}
} else {
//first time only
this.NumHistory[id].push(current);
}
return current;
} else {
return maxNum;
}
},
clear: function (id) {
this.NumHistory[id] = [];
}
};
usage would be: (100 being the range (0-100) and the_id being.. well, the id)
UniqueRandom.NumHistory[100, 'the_id']
I have set up a Fiddle with a demo.
It's not best practice. Imo it would be better to instantiate an object per series of numbers that needs to be generated.
I'd suggest generating an array of all possible values and shuffling it. Then you can just pop of it.
I took Jack's code and adapted it to work with the popping array method.
function fisherYates ( myArray ) {
var i = myArray.length;
if ( i == 0 ) return false;
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = myArray[i];
var tempj = myArray[j];
myArray[i] = tempj;
myArray[j] = tempi;
}
}
function RandomGenerator(maxNum) {
this.max = maxNum;
this.initRandomArray();
}
RandomGenerator.prototype.generate = function() {
// if no more numbers available generate new array
if( this.left === 0 ) this.initRandomArray();
this.last = this.arr.pop();
this.left = this.arr.length;
this.history.push( this.last );
return this.last;
}
RandomGenerator.prototype.initRandomArray = function() {
this.arr = [];
this.history = [];
this.last = null;
this.left = this.max;
for( var i = 0; i < this.max; i++ ) {
this.arr.push( i );
}
fisherYates( this.arr );
}
var mygen = new RandomGenerator(100);
console.log( mygen.generate() );
I got the fisherYates algorithm from here.
The approach of generating a new random number if it is already found in a history object will result in unnecessary looping.
Fiddle here
I tend to think that it is indeed not most efficient. I dont immediately get the //first time only.
Further, you can make code more readable by skipping the else return .. and writing the condition to be the opposite, e.g.:
if (maxNum >= 1) {
//code
} else {
return maxNum;
}
becomes
if (maxNum < 1) { // or maybe even if maxNum == 0
return maxNum;
}
//code
Also your x variable seems to be redundant.
I would probably implement it like this, using actual instances of random generators. This keeps the history of each generator separated.
function RandomGenerator(maxNum)
{
this.max = maxNum;
this.history = {};
this.histn = 0;
}
// generate random number in range [0..maxNum)
RandomGenerator.prototype.generate = function()
{
var value;
if (this.histn == this.max ) {
return false;
}
do {
value = Math.floor(Math.random() * this.max );
} while (this.history[value]);
this.history['' + value] = 1;
++this.histn;
return value;
}
var mygen = new RandomGenerator(100);
console.log(mygen.generate());
In my implementation I'm choosing a plain object for the history instead of an array; testing whether a value has been generated before is done by testing a property instead of $.inArray().
I agree with Alex that in most use cases, you'd want to generate an array of all values, shuffle them, and then pop them as you need them instead.
Here is an example:
var getShuffledUniqueRandoms = function(count, suffix) {
var values = [];
for (var i = 1; i < count+1; i++) {
values.push(i + suffix);
}
// Shuffle function originally from:
//+ Jonas Raoni Soares Silva
//# http://jsfromhell.com/array/shuffle [v1.0]
return (function(o){ //v1.0
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
})(values);
}
var values = getShuffledUniqueRandoms(10, "index");
$('button').click(function() {
if (values.length == 0) {
$('body').append('<p>Out of values.</p>');
} else {
$('body').append('<p>' + values.pop() + '</p>');
}
});
FIDDLE
With this algorithm, it has a bigger upfront cost, but at least it has a known time it'll take to complete (roughly O(n)).
With the algorithm where you are constantly checking to see if a random value is in an array, it'll get slower and slower with each new iteration.
Now if your data set is always relatively small, your algorithm could work a little better, but anything larger than 10 or so and it starts losing it's edge.
I have a problem with this script, something is going wrong.
Rnumer stays undefined.This script should return and write all uneven digits from the random number list. Can someone tell me what I do wrong. Thanks in advance
var Rnumber = new Array();
for (i = 0; i<= 100;i++)
{
Rnumber[i] = Math.ceil(Math.random()*101);
// document.write(Rnumber[i] + "<br/>");
}
function unevenAndDivisible(Rnumber)
{
var remainder = new Array();
for (i = 0; i<= 100; i++)
{
remainder = parseInt(Rnumber[i])%2;
}
return remainder;
}
document.write(unevenAndDivisible());
Changed to
var Rnumber = new Array();
for (i = 0; i<= 100;i++)
{
Rnumber[i] = Math.ceil(Math.random()*101);
// document.write(Rnumber[i] + "<br/>");
}
function unevenAndDivisible(Rnumber)
{
var remainder = new Array();
for (i = 0; i<= 100; i++)
{
remainder[i] = Rnumber[i]%2;
}
return remainder;
}
document.write(unevenAndDivisible(Rnumber));
but now i get the result :
0,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,1....
I simply want maybe I asked it wrong the first time, to write al uneven numbers from the random list of Rnumbers
Then I need to divide that through 7 and return that.
EDIT
Allmost all problems are clear , thanks everyone for that.
Their is still one question left:
In this code below it only take the first uneven value from remainder and I want that it takes all values that are uneven to the next if statement to check %7.
Maybe you see the problem better if you run it for youreself
var Rnumber = new Array();
for (i = 0; i<= 100;i++)
{
Rnumber[i] = Math.ceil(Math.random()*101);
}
function unevenAndDivisible()
{
var remainder = [];
var answer = [];
for (i = 0; i<= 100; i++)
{
if (Rnumber[i]%2 !== 0)
{
remainder.push(Rnumber[i]);
for (c = 0; c <= remainder.length;c++)
{
if (remainder[c]%7 == 0)
{
answer.push(remainder[c]);
}
}
}
}
return answer;
}
answer = unevenAndDivisible();
document.write(answer);
Problem solved , Thanks everyone
You don't need to pass Rnumber to the function, as it's already available in scope:
function unevenAndDivisible()
{
var remainder = [];
for (i = 0; i<= 100; i++)
{
if (Rnumber[i]%2 !== 0) {
remainder.push(Rnumber[i]);
}
}
return remainder;
}
remainder = unevenAndDivisible();
console.log(remainder);
JS Fiddle demo.
Edited in response to question from OP (in comments to question, above):
...can someone explain what this mean: var remainder = [];
Sure, it's array-literal notation, which is equal to: var remainder = new Array();, it's just a little more concise, and I prefer to save myself the typing. I get the impression, from JS Lint, whenever I use var x = new Array(); therein that the above version is generally preferred (since it complains otherwise), but I don't know why.
Either pass Rnumber to the function unevenAndDivisible or omit it from the argument list. Since it is an argument, it has more local scope than the initial declaration of Rnumber.
Your problem is the line
function unevenAndDivisible(Rnumber)
You are passing in Rnumber in as an argument, but when you call unevenAndDivisible()
you are not passing it it.
Consequently for the body of the function Rnumber is undefined (cause you passed nothing in)
The following snippet is equivalent to what you wrote nad might explain better
function unevenAndDivisible(xyz)
{
var remainder = new Array();
for (i = 0; i<= 100; i++)
{
remainder = parseInt(xyz[i])%2;
}
return remainder;
}
then called as
unevenAndDivisible(undefined)
to fix it remove the argument from the call definition
i.e. define it as
function unevenAndDivisible()
1 - you is not defining the Rnumber value that's function argument.
2 - in loop, you're defining remainder to divised value of ranumber and is not saving in array; try:
change:
remainder = parseInt(Rnumber[i])%2;
to
remainder[i] = parseInt(Rnumber[i])%2;
var array = [],
i = 100;
while (i--) {
var random = Math.random()*i|0;
if(random % 2)
array.unshift(random);
}
alert(array);