Related
I have a function that I have modified to get a string (which consists of zeros and ones only).
The string (timesheetcoldata):
100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000
The string items (the numbers one and zero) will change every time the function is run.
It will always be the same length.
I have made the string above easier to see what I am trying to achieve.
I want to return the first character and then every 24th character (as in the variable colsCount in the function).
so, in the example above, it would return something like: 111111
I then want to convert these characters to numbers (something like [1, 1, 1, 1, 1, 1]).
I then want to sum these number together (so it would return, in the example: 6).
I then want to check if the returned number matches the variable: rowsCount
or true if it does, false if it does not.
My function:
$("#J_timingSubmit").click(function(ev){
var sheetStates = sheet.getSheetStates();
var rowsCount = 6;
var colsCount = 24;
var timesheetrowsdata = "";
var timesheetcoldata = "";
for(var row= 0, rowStates=[]; row<rowsCount; ++row){
rowStates = sheetStates[row];
timesheetrowsdata += rowStates+(row==rowsCount-1?'':',');
}
timesheetcoldata = timesheetrowsdata.replace(/,/g, '');
console.log(timesheetcoldata);
});
Thank you very much to both Rajesh and MauriceNino (and all other contributers).
With their code I was able to come up with the following working function:
$("#J_timingSubmit").click(function(ev){
var sheetStates = sheet.getSheetStates();
var rowsCount = 6;
var timesheetrowsdata = "";
var timesheetcoldata = "";
for(var row= 0, rowStates=[]; row<rowsCount; ++row){
rowStates = sheetStates[row];
timesheetrowsdata += rowStates+(row==rowsCount-1?'':',');
}
timesheetcoldata = timesheetrowsdata.replace(/,/g, '');
var count = 0;
var list = [];
for(var i = 0; i< timesheetcoldata.length; i+=24) {
const num1 = Number(timesheetcoldata.charAt(i));
list.push(num1);
count += num1;
}
let isSameAsRowsCount = count == rowsCount;
console.log('Is Same? ', isSameAsRowsCount);
});
You can always rely on traditional for for such action. Using functional operations can be more readable but will be more time consuming(though not by much).
You can try this simple algo:
Create a list that will hold all numbers and a count variable to hold sum.
Loop over string. As string is fixed, you can set the increment factor to the count(24).
Convert the character at given index and save it in a variable.
Push this variable in list and also compute sum at every interval.
At the end of this loop, you have both values.
var string = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
var count = 0;
var list = [];
for(var i = 0; i< string.length; i+=24) {
const num1 = Number(string.charAt(i));
list.push(num1);
count += num1;
}
console.log(list, count)
Here is a step by step explanation, on what to do.
Use match() to get every nth char
Use map() to convert your array elements
Use reduce() to sum your array elements
Everything needed to say is included in code comments:
const testData = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
// Step 1) Create array of numbers from string
const dataArr = testData.match(/.{1,24}/g) // Split on every 24th char
.map(s => Number(s[0])) // Only take the first char as a Number
console.log(dataArr);
// Step 2) Sum array Numbers
let dataSum = dataArr.reduce((a, b) => a + b); // Add up all numbers
console.log(dataSum);
// Step 3) Compare your variables
let rowsCount = 123; // Your Test variable
let isSameAsRowsCount = dataSum == rowsCount;
console.log('Is Same? ', isSameAsRowsCount);
As #Jaromanda mentioned, you can use the following to done this.
const string = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
const value = string.split('').filter((e,i)=> !(i%24)).reduce((acc,cur)=> acc+ (+cur), 0);
console.log(value);
This question already has answers here:
Sum up a number until it becomes 1 digit JS
(16 answers)
Closed 3 years ago.
I am trying to solve a problem where a user gives a text input then I have to convert the text into given numeric values, add them together unless the answer is a single digit number.
So far, I have been able to get input, transform them into given numbers and store them in an array. But I cannot figure out what I will do next. How I will add the values together until it is left a single digit number.
var values = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26};
var someText = prompt('');
someText = someText.trim();
someText = someText.match(/\S/g);
var result = "";
for (i = 0; i < someText.length; i++) {
result += values[someText[i]];
}
alert(result);
For Example if input is "action" then numeric values will be
=>1.3.20.9.15.14.
-Add these values together.
1+3+20+9+15+14 answer will be 62.
-As the Answer is a 2 digit number, we add the numbers again
e.g 62 = 6+2= 8.
Note:
If answer is more then 1 digits: e.g 199 => 1+9+9 => 19 => 1+9 => 10 = 1+0 = 1.
Answer must always be a single digit number.
You can use reduce() to get the sum of all the digits of string. If the result is single digit then return the the number otherwise call the function recursively.
You also don't need to hard code the object with letter values. Just use reduce() and chatCodeAt to make a string of numbers.
var someText = prompt('').trim().toLowerCase().match(/\S/g)
let result = someText.reduce((ac,a) => ac + (a.charCodeAt(0) - 96),'');
function findSum(num){
if(num.length === 1) return num;
else return findSum(String(num.split('').reduce((ac,a) => ac + +a,0)))
}
console.log(findSum(result))
Here's how you can do it:
var values = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26};
var someText = prompt('');
someText = someText.trim();
someText = someText.match(/\S/g);
var result = "";
for (i = 0; i < someText.length; i++) {
result += values[someText[i]];
}
// While the result is >9, which means that there's more than 1 digit
while(result > 9) {
// Cast result as String, so we can use charAt()
var stringedResult = String(result);
// Reset our result var, because we're going to recalculate it
result = 0;
// For each int in our result, we add them up (ex. 621 = 6+2+1)
for(var i=0; i<stringedResult.length; i++) {
// Cast the stringed result back to a number, and add it to our result variable
result += Number(stringedResult.charAt(i));
}
}
alert(result);
You should use a function to sum the values and return the value when it's one digit or call itself otherwise:
var values = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26};
var someText = prompt('');
someText = someText.match(/\S/g);
var result = 0;
function getSum(string) {
for (i = 0; i < string.length; i++) {
if (isNaN(string[i])) {
result += values[string[i]];
} else {
result += parseInt(string[i]);
}
}
if (result.toString().length > 1) {
var aux = result.toString();
result = 0;
return getSum(aux);
} else {
return result;
}
}
alert(getSum(someText));
I am trying to make a webpage that makes an encrypted letter by first parsing a single character in ascii then parsing the ascii into binary then putting the binary into an array. After putting it into an array I have to loop through the array and write true for "1" or false for "0". Then I have to output to the page. an example of what the output would look like if you put in the letter "a" would be "false,true,true,false,false,false,false,true"
Update: I have added the "loop" in order to make sense of my problem
$(document).ready(function()
{
var output = document.getElementById("output");
var strQuestion = "Enter ONE character, matey!";
var strStandard = "J";
var chrCharacter = "";
var chrLength = 0;
var array = [];
var arrayLength = 0;
while (chrLength != 1)
{
chrCharacter = prompt(strQuestion, strStandard);
chrLength = chrCharacter.length;
}
intAscii = parseAscii(chrCharacter);
strBin = parseBin(intAscii);
array = strBin.split("");
for (i = 0; i < arrayLength; i++ )
{
if (array[i] = 0)
{
array[i] = false;
}
else if (array[i] = 1)
{
array[i] = true;
}
}
output.innerHTML = array;
}); //end document.ready
/*****
Purpose: Converts a character into ascii
Parameters: single character / letter
Return: integer representing an ascii value
*****/
function parseAscii(chrCharacter)
{
intAscii = chrCharacter.charCodeAt(0);
return intAscii;
}
/*****
Purpose: Takes the ascii code and turns it into binary
Parameters: single integer representing an ascii value
Return: binary, base 2 representation of the number passed to this function
*****/
function parseBin(intAscii)
{
strBin = parseInt(intAscii, 10).toString(2);
if(strBin.length < 8)
{
var intPlaceHolders = 8 - strBin.length;
for(var i = 0; i < intPlaceHolders; i++)
{
strBin = "0" + strBin;
}
}
return strBin;
}
I would convert the array with binaries to an array with boolean values wich you can joint together to a string that can be shown on the webpage.
array = [1,1,0,0,1]
// This will map over the items and perform an type conversion
var booleanArray = array.map(Boolean)
// Join all the items together as a string
Var booleanString = booleanArray.join(", ")
output.innerHTML = booleanString
`
I didn't test it, but it should work if I didn't make any typo's.
Btw, I dont think that this is what they ment with looping. But it's definitely a way to get the job done.
If I understand your question correctly, you can convert your array of ones and zeros (binary) to values of ture and false using the map function and using innerHTML to add the output to the DOM:
See example below:
// Populate myBinaryArray using your ascii method to get the follow:
let myBinaryArray = [1, 0, 0, 1, 1, 0, 1];
document.body.innerHTML += myBinaryArray.map(bit => !(!bit));
edit: without giving me too much of the answer to how i can do it in a for loop. Could you give me the logic/pseudocode on how to achieve this? the one part i am stuck at is, ok i know that i have to take the first index number and add array.length-1 zeros to it (2 zeros), but i am confused as to when it arrives at the last index, do i put in a if statement in the for loop?
In the below example 459 would be put in an array [4,5,9]
Now I want to take 4 add two zeros to the end because it has two numbers after it in the array
Then I want to take 5 and add one zero to it because there is one number after it in the array.
then 9 would have no zeros added to it because there are no numbers after it.
So final output would be 400,50,9
how can i best achieve this?
var num=459;
var nexint=num.toString().split("");
var finalint=nexint.map(Number);
var nextarr=[];
You need to use string's repeat method.
var num=459;
var a = (""+num).split('').map((c,i,a)=>c+"0".repeat(a.length-i-1))
console.log(a);
Here's another possible solution using a loop.
var num = 459;
var a = ("" + num).split('');
var ar = [];
for (var i = 0; i < a.length; i++) {
var str = a[i];
str += "0".repeat(a.length-i-1);
ar.push(str);
}
console.log(ar);
You could use Array#reduce and Array#map for the values multiplied by 10 and return a new array.
var num = 459,
result = [...num.toString()].reduce((r, a) => r.map(v => 10 * v).concat(+a), []);
console.log(result);
OP asked for a solution using loops in a comment above. Here's one approach with loops:
var num = 459
var numArray = num.toString().split('');
var position = numArray.length - 1;
var finalArray = [];
var i;
var j;
for(i = 0; i < numArray.length; i++) {
finalArray.push(numArray[i]);
for(j = 0; j < position; j++) {
finalArray.push(0);
}
position--;
}
console.log(finalArray);
The general flow
Loop over the original array, and on each pass:
Push the element to the final array
Then push X number of zeros to the final array. X is determined by
the element's position in the original array, so if the original
array has 3 elements, the first element should get 2 zeros after it.
This means X is the original array's length - 1 on the first pass.
Adjust the variable that's tracking the number of zeros to add before
making the next pass in the loop.
This is similar to #OccamsRazor's implementation, but with a slightly different API, and laid out for easier readability:
const toParts = n => String(n)
.split('')
.map((d, i, a) => d.padEnd(a.length - i, '0'))
.map(Number)
console.log(toParts(459))
What's the shortest way (within reason) to generate a random alpha-numeric (uppercase, lowercase, and numbers) string in JavaScript to use as a probably-unique identifier?
I just came across this as a really nice and elegant solution:
Math.random().toString(36).slice(2)
Notes on this implementation:
This will produce a string anywhere between zero and 12 characters long, usually 11 characters, due to the fact that floating point stringification removes trailing zeros.
It won't generate capital letters, only lower-case and numbers.
Because the randomness comes from Math.random(), the output may be predictable and therefore not necessarily unique.
Even assuming an ideal implementation, the output has at most 52 bits of entropy, which means you can expect a duplicate after around 70M strings generated.
If you only want to allow specific characters, you could also do it like this:
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
Here's a jsfiddle to demonstrate: http://jsfiddle.net/wSQBx/
Another way to do it could be to use a special string that tells the function what types of characters to use. You could do that like this:
function randomString(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('!') > -1) mask += '~`!##$%^&*()_+-={}[]:";\'<>?,./|\\';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() * mask.length)];
return result;
}
console.log(randomString(16, 'aA'));
console.log(randomString(32, '#aA'));
console.log(randomString(64, '#A!'));
Fiddle: http://jsfiddle.net/wSQBx/2/
Alternatively, to use the base36 method as described below you could do something like this:
function randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
UPDATED:
One-liner solution, for random 20 characters (alphanumeric lowercase):
Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('');
Or shorter with lodash:
_.times(20, () => _.random(35).toString(36)).join('');
Another variation of answer suggested by JAR.JAR.beans
(Math.random()*1e32).toString(36)
By changing multiplicator 1e32 you can change length of random string.
Or to build upon what Jar Jar suggested, this is what I used on a recent project (to overcome length restrictions):
var randomString = function (len, bits)
{
bits = bits || 36;
var outStr = "", newStr;
while (outStr.length < len)
{
newStr = Math.random().toString(bits).slice(2);
outStr += newStr.slice(0, Math.min(newStr.length, (len - outStr.length)));
}
return outStr.toUpperCase();
};
Use:
randomString(12, 16); // 12 hexadecimal characters
randomString(200); // 200 alphanumeric characters
This is cleaner
Math.random().toString(36).substr(2, length)
Example
Math.random().toString(36).substr(2, 5)
function randomString(len) {
var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return [...Array(len)].reduce(a=>a+p[~~(Math.random()*p.length)],'');
}
Summary:
Create an array of the size we want (because there's no range(len) equivalent in javascript.
For each element in the array: pick a random character from p and add it to a string
Return the generated string.
Some explanation:
[...Array(len)]
Array(len) or new Array(len) creates an array with undefined pointer(s). One-liners are going to be harder to pull off. The Spread syntax conveniently defines the pointers (now they point to undefined objects!).
.reduce(
Reduce the array to, in this case, a single string. The reduce functionality is common in most languages and worth learning.
a=>a+...
We're using an arrow function.
a is the accumulator. In this case it's the end-result string we're going to return when we're done (you know it's a string because the second argument to the reduce function, the initialValue is an empty string: ''). So basically: convert each element in the array with p[~~(Math.random()*p.length)], append the result to the a string and give me a when you're done.
p[...]
p is the string of characters we're selecting from. You can access chars in a string like an index (E.g., "abcdefg"[3] gives us "d")
~~(Math.random()*p.length)
Math.random() returns a floating point between [0, 1) Math.floor(Math.random()*max) is the de facto standard for getting a random integer in javascript. ~ is the bitwise NOT operator in javascript.
~~ is a shorter, arguably sometimes faster, and definitely funner way to say Math.floor( Here's some info
I think the following is the simplest solution which allows for a given length:
Array(myLength).fill(0).map(x => Math.random().toString(36).charAt(2)).join('')
It depends on the arrow function syntax.
for 32 characters:
for(var c = ''; c.length < 32;) c += Math.random().toString(36).substr(2, 1)
Random character:
String.fromCharCode(i); //where is an int
Random int:
Math.floor(Math.random()*100);
Put it all together:
function randomNum(hi){
return Math.floor(Math.random()*hi);
}
function randomChar(){
return String.fromCharCode(randomNum(100));
}
function randomString(length){
var str = "";
for(var i = 0; i < length; ++i){
str += randomChar();
}
return str;
}
var RandomString = randomString(32); //32 length string
Fiddle: http://jsfiddle.net/maniator/QZ9J2/
Using lodash:
function createRandomString(length) {
var chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUFWXYZ1234567890"
var pwd = _.sampleSize(chars, length || 12) // lodash v4: use _.sampleSize
return pwd.join("")
}
document.write(createRandomString(8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Random Key Generator
keyLength argument is the character length you want for the key
function keyGen(keyLength) {
var i, key = "", characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var charactersLength = characters.length;
for (i = 0; i < keyLength; i++) {
key += characters.substr(Math.floor((Math.random() * charactersLength) + 1), 1);
}
return key;
}
keyGen(12)
"QEt9mYBiTpYD"
var randomString = function(length) {
var str = '';
var chars ='0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(
'');
var charsLen = chars.length;
if (!length) {
length = ~~(Math.random() * charsLen);
}
for (var i = 0; i < length; i++) {
str += chars[~~(Math.random() * charsLen)];
}
return str;
};
When I saw this question I thought of when I had to generate UUIDs. I can't take credit for the code, as I am sure I found it here on stackoverflow. If you dont want the dashes in your string then take out the dashes. Here is the function:
function generateUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x7|0x8)).toString(16);
});
return uuid.toUpperCase();
}
Fiddle: http://jsfiddle.net/nlviands/fNPvf/11227/
This function should give a random string in any length.
function randString(length) {
var l = length > 25 ? 25 : length;
var str = Math.random().toString(36).substr(2, l);
if(str.length >= length){
return str;
}
return str.concat(this.randString(length - str.length));
}
I've tested it with the following test that succeeded.
function test(){
for(var x = 0; x < 300000; x++){
if(randString(x).length != x){
throw new Error('invalid result for len ' + x);
}
}
}
The reason i have chosen 25 is since that in practice the length of the string returned from Math.random().toString(36).substr(2, 25) has length 25. This number can be changed as you wish.
This function is recursive and hence calling the function with very large values can result with Maximum call stack size exceeded. From my testing i was able to get string in the length of 300,000 characters.
This function can be converted to a tail recursion by sending the string to the function as a second parameter. I'm not sure if JS uses Tail call optimization
A simple function that takes the length
getRandomToken(len: number): string {
return Math.random().toString(36).substr(2, len);
}
Ff you pass 6 it will generate 6 digit alphanumeric number
Nice and simple, and not limited to a certain number of characters:
let len = 20, str = "";
while(str.length < len) str += Math.random().toString(36).substr(2);
str = str.substr(0, len);
One could just use lodash uniqueId:
_.uniqueId([prefix=''])
Generates a unique ID. If prefix is given, the ID is appended to it.
Here's a simple code to generate random string alphabet.
Have a look how this code works.
go(lenthOfStringToPrint); - Use this function to generate the final string.
var letters = {
1: ["q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m"],
2: ["Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M"]
},i,letter,final="";
random = (max,min) => {
return Math.floor(Math.random()*(max-min+1)+min);
}
function go(length) {
final="",letter="";
for (i=1; i<=length; i++){
letter = letters[random(0,3)][random(0,25)];
final+=letter;
}
return final;
}
I used #Nimphious excellent second approach and found that occasionally the string returned was numeric - not alphanumeric.
The solution I used was to test using !isNaN and use recursion to call the function again.
Why bother? I was using this function to create object keys, if all the keys are alphanumeric everything sorts properly but if you use
numbers as keys mixed with alphanumeric (strings) looping through the object will produce a different order to original order.
function newRandomString(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('$') > -1) mask += '0123456789';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() *
mask.length)];
/*
we need a string not a number !isNaN(result)) will return true if '1234' or '3E77'
because if we're looping through object keys (created by newRandomString()) and
a number is used and all the other keys are strings then the number will
be first even if it was the 2nd or third key in object
*/
//use recursion to try again
if(!isNaN(result)){
console.log('found a number....:'+result);
return newRandomString(length, chars)
}else{
return result;
}
};
var i=0;
while (i < 1000) {
var a = newRandomString(4, '#$aA');
console.log(i+' - '+a);
//now we're using recursion this won't occur
if(!isNaN(a)){
console.log('=============='+i+' - '+a);
}
i++;
}
console.log('3E77:'+!isNaN('3E77'));//true
console.log('1234:'+!isNaN('1234'));//true
console.log('ab34:'+!isNaN('ab34'));//false
After looking at solutions in answers to this question and other sources, this is the solution that is simplest while allowing for modification of the included characters and selection in the length of the returned result.
// generate random string of n characters
function randomString(length) {
const characters = '0123456789abcdefghijklmnopqrstuvwxyz'; // characters used in string
let result = ''; // initialize the result variable passed out of the function
for (let i = length; i > 0; i--) {
result += characters[Math.floor(Math.random() * characters.length)];
}
return result;
}
console.log(randomString(6));
Use md5 library: https://github.com/blueimp/JavaScript-MD5
The shortest way:
md5(Math.random())
If you want to limit the size to 5:
md5(Math.random()).substr(0, 5)