How To Randomize Sentence Length From Array - javascript

There is probably a simple solution to this, but for some reason I can't seem to find it on the site, or elsewhere on the net. Just trying to produce a sentence of RANDOM LENGTH from an array. Here is an example:
var words = ["yes", "ok", "java", "pull my hair out", "sleep"];
Here is the code that I'm currently using to randomize the contents of the array, but it always produces a sentence where every string is used once. I want varying sentence lengths.
function fisherYates(words) {
var i = words.length, j, tempi, tempj;
if ( i == 0 ) return false;
while ( --i ) {
j = Math.floor( Math.random() * ( i + 1 ) );
tempi = words[i];
tempj = words[j];
words[i] = tempj;
words[j] = tempi;
}
return words;
}
Suggestions?

I would suggest you select a random number m from 1 to n inclusive (where n is the maximum length of the sentence you want). Then you randomly select m items from the array and put them into a new array:
var words = ["yes", "ok", "java", "pull my hair out", "sleep"];
alert(randomize(words, 10).join(" ") + ".");
function randomize(array, maximum) { // array, n
var length = Math.ceil(maximum * Math.random()); // m
var result = new Array(length);
var count = array.length;
var index = 0;
while (index < length) {
result[index++] = array[Math.floor(count * Math.random())];
}
return result;
}
Hope that helps.
Perhaps not.

If you don't want repeated strings, copy the array and splice random members from it to form the new collection. Just splice off a random number of strings from random positions.
function randWords(arr) {
// Copy original array
arr = arr.slice();
// Random number of words to get
var len = (Math.random() * arr.length + 1)|0;
var result = [];
// Randomly fill result from arr, don't repeat members
while (len--) {
result.push(arr.splice(Math.random()*arr.length|0, 1));
}
return result;
}
console.log( randWords(["yes", "ok", "java", "pull my hair out", "sleep"]).join(' ') );

Related

Finding a first letter most repeated in an string

Good evening, I proceed to explain my situation. I started to get interested in javascript which started to dabble
in this language, I have been doing some online courses which I have encountered the following task, basically I am trying through the condition "for" tell me what is the first repeated letter of a string also adding the funsion ".UpperCase () "which at the beginning worked best, until I entered more characters to the string in this case" x "throwing me as output result" undefined "instead of" the most repeated word is: X "reach the case that the string should Consider all the letters regardless of whether they are lowercase or capital letters, for which I ask for help to understand if ¿there is another way? for this task and thus move forward (Sorry for my bad english)
Well i making this task in JavasScript with Atom Editor
var word = "SQSQSQSSaaaassssxxxY";
var contendor = [];
var calc = [];
var mycalc = 0;
function repeat() {
for (var i = 0; i < word.length; i++) {
if (contendor.includes(word[i])) {} else {
contendor.push(word[i])
calc.push(0)
}
}
for (var p = 0; p < word.length; p++) {
for (var l = 0; l < contendor.length; l++) {
if (word[p].toUpperCase() == word[l]) {
calc[l] = calc[l] + 1
}
}
}
for (var f = 0; f < calc.length; f++) {
if (calc[f] > mycalc) {
mycalc = calc[f]
}
}
}
repeat()
console.log("The first letter repeated its: " + contendor[mycalc])
I expected the output of the String to be: "X"
but the actual output is: "Undefined"
The first error in your script is that you store the wrong value in mycalc:
mycalc = calc[f]
Since you want mycalc to be an index, the above should have been
mycalc = f
Now, you will get a result, but your code is actually going through a lot of effort to find the uppercase character that is repeated most often, not first.
Your comparison should have used toUpperCase on both sides of the comparison, otherwise lower case letters will never match.
To get the character that was repeated most often, you could use a Map (to keep track of the counts like you did in calc):
function mostRepeated(str) {
const map = new Map;
let result;
let maxCount = 0;
for (let ch of str) {
ch = ch.toUpperCase();
let count = (map.get(ch) || 0) + 1;
map.set(ch, count);
if (count > maxCount) {
maxCount = count;
result = ch;
}
}
return result;
}
var word = "MBXAYMZAXmZYxxxxxxxxxxmBxAYMZaXmZY";
console.log(mostRepeated(word));
Note that you should better use function parameters and local variables. Declaring your variables as global is not considered best practice.
You could find the letter that occurs the most number of times in a string by:
first creating a map that relates each unique letter, to the number of times it occurs in the string
converting that map to an array of "key/value" entries, and then sorting those entries by the "count value"
returning the "letter key" that has the largest count
One way to express this in JavaScript would be via the following:
function findMaxLetter(word) {
/* Create a map that relates letters to the number of times that letter occours */
const letterCounts = Array.from(word).reduce((map, letter) => {
return { ...map, [letter] : (map[letter] === undefined ? 0 : map[letter] + 1) }
}, {})
/* Sort letters by the number of times they occour, as determined in letterCounts map */
const letters = Object.entries(letterCounts).sort(([letter0, count0], [letter1, count1]) => {
return count1 - count0
})
.map(([letter]) => letter)
/* Return letter that occoured the most number of times */
return letters[0]
}
console.log("The first letter repeated its: " + findMaxLetter("MBXAYMZAXmZYxxxxxxxxxxmBxAYMZaXmZY"))
I this is solution is most detailed for you
function func( word ){
word = word.toLowerCase();
var i, charCountCache = {};
//store all char counts into an object
for( i = 0; i < word.length; i++){
if( charCountCache[ word[ i ] ] )
charCountCache[ word[ i ] ] = charCountCache[ word[ i ] ] + 1;
else
charCountCache[ word[ i ] ] = 1;
}
//find the max value of char count in cached object
var fieldNames = Object.keys( charCountCache )
, fieldValues = Object.values( charCountCache )
, mostReapeatChar = '', mostReapeatCharCount = 0;
for( i = 0; i < fieldNames.length; i++ ){
if( mostReapeatCharCount < fieldValues[i] ){
mostReapeatCharCount = fieldValues[i];
mostReapeatChar = fieldNames[i];
}
}
console.log('most repeating char: ', mostReapeatChar, ' no of times: ', mostReapeatCharCount )
}
console.log("The first letter repeated its: " + contendor[mycalc])
You tried to print the 14th index of contendor which has only 9 values, that is why your log result was undefined.
You probably wanted to print word[mycalc].
Also if you intended to count x as X, you should have added toUpperCase() to every letter you process/go-through.
This is only a note to the issues in your code, there are better/faster/cleaner solutions to reach the result which i am sure other answers will provide.
my advice would be to create a hashmap such as
letter => [indexLetter1, indexLetter2].
From that hashmap, you could easily find your first repeated letters.
For that string MBXAYMZAXmZYxxxxxxxxxxmBxAYMZaXmZY, hashmap will look like
[
M => [0,5,..],
B => [1, ..],
X => [2, ..],
...
]
now you can find every letter with multiple values in its array, then in those arrays take the one with the lowest value.
If you want to get the index of most repeated letter, you can use Array.from to convert the word into an array. Add a map function to make all letters uppercase.
Get the count of each letter by using reduce and Object.entries
Use indexOf to the get the index of the lettet in the array. Please note that indexOf count the letters from 0.
var word = "MBXAYMZAXmZYxxxxxxxxxxmBxAYMZaXmZY";
var letters = Array.from(word, o => o.toUpperCase());
var [highestLetter, highestCount]= Object.entries(letters.reduce((c, v) => (c[v] = (c[v] || 0) + 1, c), {})).reduce((c, v) => c[1] > v[1] ? c : v);
var index = letters.indexOf(highestLetter);
console.log("Most repeated letter:", highestLetter);
console.log("Count:", highestCount);
console.log("First Index:", index);

Random Selection from Array into new Array

I have seen this question answered here, but I have an additional question that is related.
Im trying to achieve:
the same thing, but, with the output being a selection of more than 1 number, the above works fine if you only want a single value returned.
How can I return (x) amount of outputs #7 in this case into a new var or array ...? Some guidance on best practice will also be appreciated ;)
Thanks a bunch....
Just for fun,
Objective:
Create a teeny weenie web App that returns 7 variable numbers in a range [ 1 - 49 ] into an array.
`
Think return a list of Lotto Numbers
Create new array from selection using _underscore.js [Sample function]
**** I know this is easier, but im trying to get an understanding
of using Vanilla JS to accomplish this
_.sample([1, 2, 3, 4, 5, 6], 3); => [1, 6, 2]
var getLoot = Array.from(Array(50).keys()) // Create array of 49 numbers.
console.info(getLoot);
var pick = getLoot[Math.floor(Math.random() * getLoot.length)];
pick;
// pick returns a single which is fine if you want a single but, ..
// I want something like this :
var pick = function() {
// code that will return 7 numbers from the array into a new Array
// will randomize every time pick is called...
}
If you want to return more than just 1 value you can store your results into a data structure like an array. Here is a solution to the problem
assuming you can pass in your array of 50 numbers into the pick() funciton.:
var getRandomArbitrary = function(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
var pick = function(fiftyNumberArray, numberOfValuesWanted) {
var randomNums = [];
for(var i = 0; i < numberOfValuesWanted; i++) {
randomNums.push(
fiftyNumberArray[getRandomArbitrary(0, 50)]
);
}
return randomNums;
};
var fiftyNumbers = [] // <- set your array of fifty numbers
pick(fiftyNumbers, 7);
Javascript's Math.random() will return a value in between 0 and 1 (exclusive). So to get an index scaled up to the correct value to look into your array, you would want to multiply that by the formula (max - min) + min
You can use Array.prototype.splice(), Math.floor(), Math.random(), for loop to remove elements from input array, return an array containing pseudo randomly picked index from input array without duplicate indexes being selected.
function rand(n) {
var res = []; var a = Array.from(Array(n).keys());
for (;a.length;res.push(a.splice(Math.floor(Math.random()*a.length),1)[0]));
return res
}
console.log(rand(50));
One good way of doing this job is shuffling the array and picking the first n values. Such as;
function shuffle(a){
var i = a.length,
j,
tmp;
while (i > 1) {
j = Math.floor(Math.random()*i--);
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return a;
};
var arr = Array(50).fill().map((_,i) => i+1); //[1,2,3...49,50]
randoms = shuffle(arr).slice(0,7) // to get 7 random numbers from arrary arr
console.log(randoms)
This is probably what you want.
$(function()
{
var lol = [1,4,5,6,7,8,9];
function getPart(array,number)
{
var part = [],
index;
while(true)
{
if(part.length == number)
{
break;
}
index = $.random(0,part.length);
part.push(lol.splice(index,1));
}
return part;
}
});
$.random = function(min,max,filter)
{
var i,
n = Math.floor(Math.random()*(max-min+1)+min);
if(filter != undefined && filter.constructor == Array)
{
for(i=filter.length-1;i>-1;i--)
{
if(n == filter[i])
{
n = Math.floor(Math.random()*(max-min+1)+min)
i = filter.length;
}
}
}
return n;
}

randomly splice values into array

I have an array "A" of scrambled, randomly generated ASCII characters... and a message "M". I want to insert the characters of message M into array A such that the order of M's characters are intact... but randomly distributed throughout array A.
Original array: zH$#%#$##$#^^##(%*$#^&#!$^%&
Sample output: zH$#%#^t$##$#^^h##(%*$#^&#i!$^%&s, etc...
var randomChars = [];
for(var i=33;i<127;++i) {
var letter = document.createElement('span');
letter.innerHTML = String.fromCharCode(i);
randomChars.push(letter);
}
var message = "this is a message";
var rand = 0;
for (var i = 0; i < message.split("").length; i++) {
rand = Math.floor((Math.random() * randomChars.length) + rand);
var letters = document.createElement('span');
letters.innerHTML = message.split("")[i];
letters.setAttribute("hidden","");
randomChars.splice(rand, 0, letters);
}
Fiddle: https://jsfiddle.net/0ftm2srz/1/
Use the previous random index as the minimum (non inclusive) of your next randomly generated index. Start at zero.
You could end up with some barely scrambled stuff, though. (!##!$!#$#!##this) But it's random.
EDIT A better way would be to generate a message.length amount of unique random indices, sort them in ascending, and then insert characters from message at those spots in the scrambled array.
http://jsbin.com/kuzepujabo/1/edit?js,console
var o = {
array: "zH$#%#$##$#^^##(%*$#^&#!$^%&".split(''),
msg: "this is a message",
randomMsgIndex: function () { return Math.floor(Math.random() * this.msg.length); },
randomMsgChar: function () { return this.msg[this.randomMsgIndex()]; },
//resultingArray: [],
randomArrayIndex: function () { return Math.floor(Math.random() * this.array.length); }
}
for(var i = 0; i < o.msg.length; i++) {
o.array.splice(o.randomArrayIndex(), 0, o.randomMsgChar());
}
console.log(o.array);
I have come up with this - but I assume it is still not what you want - you probably want something that keeps track of which message chars were already added - so not to add them twice - and make sure the entire message (all its characters) were added to the array.
Version 2 with the feature described above:
var o = {
array: "zH$#%#$##$#^^##(%*$#^&#!$^%&".split(''),
msg: "this is a message",
msgArray: function () { this.msg.split(''); },
randomMsgIndex: function () { return Math.floor(Math.random() * this.msg.length); },
randomMsgChar: function (i) { return this.msg[i]; },
//resultingArray: [],
randomArrayIndex: function () { return Math.floor(Math.random() * this.array.length); },
stripStr: function (indexToSkip, originalStr) {
var result = "";
for (var i = 0; i < originalStr.length; i++)
if (indexToSkip != i)
result += originalStr[i];
return result;
}
}
for(var i = 0; i < o.msg.length; i++) {
var msgRandomIndex = o.randomMsgIndex();
o.array.splice(o.randomArrayIndex(), 0, o.randomMsgChar(msgRandomIndex));
o.msg = o.stripStr(msgRandomIndex, o.msg);
}
console.log(o.array);
I think it it is still not a 100%, but moving towards the "optimized" solution :-)

Order elements from string

I've got a string!
7 serpents
4 bikes
2 mangoes
It's made up of number + [space] + thing-string. I need to be able to order the whole string with reference to the number. So it should come out:
2 mangoes
4 bikes
7 serpents
It's a simple bubble sort for the number and then cross-referencing the index to get the final order. The JavaScript code below works, but I can't help but think it could be made more efficient. Am I missing a trick here??
And remember: I'm an artist, so I code in crayon!
var eventsStr = "7 serpents\n4 bikes\n2 mangoes"
var splitArr = eventsStr.split("\n")
var numArray = new Array();
var events = new Array();
for (var i = 0; i < splitArr.length; i++)
{
var temp = splitArr[i] ;
var part1 = temp.substring(0, temp.indexOf(" "))
var part2 = temp.substring(temp.indexOf(" ")+1, temp.length)
numArray[i] = part1;
events[i] = part2;
}
var sorted = superCopy(numArray);
var sorted = sorted.sort(sortArrayNumerically);
alert(getOrder(sorted, numArray, events))
function getOrder(orderedarr, arr1, arr2)
{
var str = "";
for (var i = 0; i < arr1.length; i++)
{
for (var j = 0; j < orderedarr.length; j++)
{
if (arr1[i] == orderedarr[j])
{
// found the thing !what is the event?
str += arr1[i] + " " + arr2[i] + "\n";
}
}
}
return str
}
function sortArrayNumerically(a,b)
{
return a - b;
}
function superCopy(arr)
{
tempArr = new Array();
for (var i = 0; i < arr.length; i++)
{
tempArr[i] = arr[i]
}
return tempArr
}
You could use JavaScript's sort() function:
eventsStr.split('\n').sort().join('\n');
eventsStr.split('\n') - first split the string on the newline character to create an array
.sort() - then use the sort() function to sort the array
.join('\n') - then put the string back together, joining the array elements with a newline between them
Reference:
String.prototype.split()
Array.prototype.sort()
Array.prototype.join()
This is an alphabetic sort though, so if your string contained, say, 12 mangoes, the result would not be sorted numerically. To sort numerically, you could do something like this:
eventsStr.split('\n').sort(function(a, b) {
return parseInt(a.split(' ')[0], 10) > parseInt(b.split(' ')[0], 10);
}).join('\n');
In this situation, the sort() function is called with a callback parameter, taking 2 values: the first string to be compared and the second string to be compared. This callback function then splits the string, extracts the number and compares it with the number in the other string.
Use
splitArr.sort() // as per your code
DEMO
var eventsStr = "7 serpents\n4 bikes\n2 mangoes"
arr = eventsStr.split('\n')
# ["7 serpents", "4 bikes", "2 mangoes"]
arr
# ["7 serpents", "4 bikes", "2 mangoes"]
arr.sort()
# ["2 mangoes", "4 bikes", "7 serpents"]

insert item in javascript array and sort

Let's say I have an array
var test = new Array()
the values in test are 3,6,9,11,20
if I then have a variable
var id = 5
how can I insert 5 between 3 and 6 in the array?
or do I just insert it wherever and then sort the array?
Thanks in advance.
edit:
I have the following code:
function gup( filter )
{
filter = filter.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+filter+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
var queryString = gup("SelectedID");
var hrefs = new Array();
$('.table404').children().children().each(function(){
var link = ($(this).find('a').attr('href'));
var startIndex = link.indexOf(",'");
var endIndex = link.indexOf("');");
if ( startIndex >= 0 && endIndex >= 0 ) {
var linkID = link.substring( startIndex+2, endIndex );
hrefs.push(linkID);
hrefs.push(queryString);
hrefs.sort()
}
alert(hrefs);
});
for each item inserted into the array I get an alert with the ID but for every item I get one 1 (the current queryString value), so the last pop up looks something like
1,1,1,1,1,2,4,6,7,8
Why do I get a new pop up for every item inserted into the array? I get the querystring value once for every other item inserted into the array. What do I have to do to get one pop up with the complete array?
You can use a binary searach to find an insertion point, if you array is large enough:
Below is a quick code with tests. (Warning: not thoroughly tested). Also the array has to be a sorted array.
Once you have an insertion point, just use the Array.splice function to insert at that index.
/**
* Find insertion point for a value val, as specified by the comparator
* (a function)
* #param sortedArr The sorted array
* #param val The value for which to find an insertion point (index) in the array
* #param comparator The comparator function to compare two values
*/
function findInsertionPoint(sortedArr, val, comparator) {
var low = 0, high = sortedArr.length;
var mid = -1, c = 0;
while(low < high) {
mid = parseInt((low + high)/2);
c = comparator(sortedArr[mid], val);
if(c < 0) {
low = mid + 1;
}else if(c > 0) {
high = mid;
}else {
return mid;
}
//alert("mid=" + mid + ", c=" + c + ", low=" + low + ", high=" + high);
}
return low;
}
/**
* A simple number comparator
*/
function numComparator(val1, val2) {
// Suggested b #James
return val1 - val2;
}
// TESTS --------------------------------
var arr = [0,1,3,6,9,11,20];
var idx = findInsertionPoint(arr, 2, numComparator);
arr.splice(idx, 0, 2);
alert(arr); // will alert [0,1,2,3,6,9,11,20]
var arr2 = [0,1,3,6,9,11,20];
var idx2 = findInsertionPoint(arr2, -1, numComparator);
arr2.splice(idx2, 0, -1);
alert(arr2); // will alert [-1,0,1,3,6,9,11,20]
If you have different objects, the only thing you need to do is provide appropriate comparator function.
Or if the array is really small and if you are especially lazy today, you can just do:
test.push(2).sort();
test.push(2); test.sort();

Categories