I have this problem. I'd like to make random a choice from array [1,2,3,4] based on arbitrary 6 letter string in such way that this choice is always same if string is same.
So if i have string 'dogdog' function would return always '3' for example, but '4' for 'bigcat' etc.
I think the solution might be first hashing the string. How could one convert hash string into choice from array?
You can calculate a hash from a string and take the array item at [hash % array.length]. An example with the DJB hashfunc (see http://www.cse.yorku.ca/~oz/hash.html for more):
function djbHash(s) {
let hash = 5381;
for (let c of s) {
hash = hash * 33 + c.charCodeAt(0);
}
return hash;
}
function mapToValues(s, values) {
return values[djbHash(s) % values.length];
}
console.log(mapToValues('dogdog', [1, 2, 3, 4]));
console.log(mapToValues('bigcat', [1, 2, 3, 4]));
A really simple hash function:
Change each letter of your word by a number (a is 1, b is 2, etc.). Let's call w the whole word changed in a number.
Calculate i = w mod 4. i will be a number between 0 and 3. Add 1 to it.
Congrats, you can now associate any word to a "random" number between 1 and 4. You can of course replace 4 by any other number to associate each world to a random number in any range.
Related
Let's say I have these four numbers: [1, 5, 3, 8].
And I want to check which of the math operations equals to 10. Also the order of the numbers matters, meaning the first number should always be the first index in the array and so on.
For example:
(1 + 5) ÷ 3 + 8
1 x 5 - 3 + 8
How can I achieve this?
Honestly, I have no idea how I should approach this. So any help would be greatly appreciated.
We create an Expr class to represent expressions, which consist of two operands (which may be simple numbers or other expressions) and an operator. This provides convenience functions for evaluating the expression and outputting the expression as a string.
In the simple case, where there are only two expressions x and y, we return all possible combinations x+y, x-y, x*y, x÷y.
Then, when there are more expression operands, we find (all combinations of (x operator y) with ...z), and (x operator (all combinations of y with ...z))
class Op {
constructor(symbol,func) { this.symbol = symbol; this.func = func; }
invoke(x,y) { return this.func(
x instanceof Expr ? x.eval() : x,
y instanceof Expr ? y.eval() : y)
}
toString() { return this.symbol }
}
const ops = [
new Op('+', (x,y)=>x+y), new Op('-', (x,y)=>x-y),
new Op('*', (x,y)=>x*y), new Op('÷', (x,y)=>x/y),
]
class Expr {
constructor(x,op,y){ this.x=x; this.op=op; this.y=y }
eval() { return this.op.invoke(this.x, this.y) }
toString() { return `(${this.x}${this.op}${this.y})` }
}
const f = (x,y,...z) =>
!z.length ? ops.map(op=>new Expr(x,op,y)) :
[...f(x,y).flatMap(expr=>f(expr, ...z)),
...f(y,...z).flatMap(expr=>f(x, expr))]
// show all combinations
console.log(f(...[1, 5, 3, 8]).map(i=>i.toString()))
// show only combinations that evaluate to 10
console.log(f(...[1, 5, 3, 8]).filter(i=>i.eval()===10).map(i=>i.toString()))
Construct the set of possible results for each contiguous range of the input values.
If a range has a single number, then the only mathematical expression constructible is the number itself.
Otherwise, if you have a range a[i], a[i+1], ..., a[j] then for each k from i+1 to j, find the set of possible results constructible from a[i], a[i+1], ..., a[k-1], and the set of possible results constructible from a[k], a[k+1], ..., a[j], then combine them using +, -, * and / in every possible combination.
For example, for [1, 5, 3, 8] there's three ways of breaking up the sequence:
[1] [5, 3, 8]
[1, 5], [3, 8]
[1, 5, 3], [8]
Working through just the second line: [1, 5] can produce {1+5, 1-5, 1*5, 1/5} and [3, 8] can produce {3+8, 3-8, 3*8, 3/8}, so this gives {(1+5)+(3+8), (1+5)-(3+8), (1+5)*(3+8), (1+5)/(3+8), (1-5)+(3+8), (1-5)-(3+8), ..., (1/5)+(3/8), (1/5)-(3/8), (1/5)*(3/8), (1/5)/(3/8)}.
This is workable as-is if you only have 4 input numbers, but if you have more then you will find you can memoize or use dynamic programming to avoid computing the same things repeatedly. It will always be exponential time though, since the range of constructible values grows exponentially.
Given a string, I'd like to create the minimum number of sets of substrings where:
substrings have a length up to x
if two sets differ when a substring in one set can be composed of smaller substrings in the other set, the second set can be excluded
For example, the substring "abcdef" with max substring length of 3 would result in the following:
[
['abc','def'],
['ab','cde','f'],
['ab','cd','ef'],
['a','bcd','ef'],
]
['abc','de','f'] is not included because of condition (2). eg, 'def' is compsed of 'de','f'
The following recursive allSubstrings() method isn't quite right and doesn't feel like the right approach. Also has the problem of being slow with longer strings.
const allSubstrings = (input,max_len = 3) => {
if( input.length === 1) return [[input]];
let result = [];
const start = input.substring(1);
allSubstrings(start).forEach(function(subresult) {
let tmp = subresult.slice(0);
if( tmp[0].length < max_len ){
tmp[0] = input.charAt(0) + tmp[0];
result.push(tmp);
}
if( subresult.length > 1 ){
if( subresult.slice(0,2).join('').length <= max_len ){
return;
}
if( subresult.slice(subresult.length-2).join('').length <= max_len ){
return;
}
}
tmp = subresult.slice(0);
tmp.unshift(input.charAt(0));
result.push(tmp);
});
return result;
}
Here's one possible approach using recursion, not optimized for performance (e.g., there's no memoization):
function splits(s: string, maxLen: number, minInitLen: number = 1): string[][] {
const ret: string[][] = s.length ? [] : [[]];
for (let i = Math.min(maxLen, s.length); i >= minInitLen; i--) {
for (const r of splits(s.slice(i), maxLen, maxLen + 1 - i)) {
ret.push([s.slice(0, i), ...r]);
}
}
return ret;
}
The idea is that splits() takes not just the string s to split and the maximum length maxLen of substrings, but also the minimum allowable length minInitLen for the first substring. When you start splitting the string this initial length is 1, but inside the recursion it could be larger. After all, let's say that you've split "abcdef" into "a" so far. Now you need to split "bcdef", but the next substring has to have length 3 ("bcd"), since "b" would collapse into "ab" and "bc" would collapse into "abc". If you've split it into "ab" so far, then the next substring has to have length at least 2 ("cd" or "cde"), since "c" would collapse into "abc". The relevant math is that if the current substring is of length i, then the next substring must have at least length maxLen + 1 - i.
The base case for the recursion is when you are asked to split an empty string. In this case you want to return [[]]; there is exactly one way to split an empty string. If you are splitting a non-empty string then you want to iterate your first substring length i between minInitLen and maxLen (well, you can't exceed s.length either), and calculate the recursive result splits(s.slice(i), maxLen, maxLen + 1 - i), and then for each set of strings in the result, prepend the initial substring s.slice(0, i) to it.
Let's see if it works:
console.log(splits("abcdef", 3))
// [["abc", "def"], ["ab", "cde", "f"], ["ab", "cd", "ef"], ["a", "bcd", "ef"]]
console.log(splits("abcdefgh", 5))
// [["abcde", "fgh"], ["abcd", "efgh"], ["abc", "defgh"], ["ab", "cdefg", "h"],
// ["ab", "cdef", "gh"], ["a", "bcdef", "gh"]]
It looks good, at least for your example input. I'm not sure if there are edge cases, or if performance becomes a problem for large strings (it probably depends very much on what "large" means). And one could certainly refactor to use functional programming array methods instead of for loops if one wanted. But at least it works.
Playground link to code
I need a function that will take an array of numbers, and which will return an array that only retains the numbers that are unique in their digit sequence, i.e. that only occur once even if you would reverse their digits.
This is my code so far:
var a=[5,8,3,8,3,7,5,12,21];
console.log(a);
let output=[...new Set([...a])] // it removes the repeated data...
console.log(output);
This works for the numbers 3, 8 and 5, whose duplicates are removed, but the value 21 should also be removed, because there is already 12, which is 21 with the digits in reversed order.
How can I achieve that?
The expected output for the above example is:
[5,8,3,7,12]
My code returns:
[5,8,3,7,12,21]
You need (of course) to include the logic of reversing digits in a number.
I will assume that when the rightmost digit of a number is 0, that the reversal of that number is not defined. So the reversal of 19 is 91, but the reversal of 190 is not 91, but undefined (or NaN).
First define a function for that reversal of digits, and then use the idea of building a set:
function reverseDigits(num) {
// A Number should not have 0 as first digit
// unless it is 0
if (num && num % 10 == 0) return NaN;
return +[...String(num)].reverse().join("");
}
function specialUnique(a) {
const set = new Set;
for (const value of a) {
if (!set.has(value) && !set.has(reverseDigits(value))) {
set.add(value);
}
}
return [...set];
}
// Example input
const a = [5,8,3,8,3,7,5,12,21];
const output = specialUnique(a);
console.log(output);
You can use the filter.
let valueToRemove = 21;
output = output.filter((item) => item !== valueToRemove);
How can you find the last occurrence of a non-zero digit in a number/string in Javascript? With that, we will be able to split a zero-padded number into the actual number and its zero padding. Any JS/Node library can be used.
Tried using .lastIndexOf() but didn't find a way to define a non-zero digit.
Input
1.23400
1.00050
1.03456
Output
['1.234', '00']
['1.0005', '0']
['1.03456']
Use a regex :
/^([0-9]+\.?[0-9]*?)(0*)$/
/^([0-9]+\.?[0-9]*?)(0*)$/.exec('1.23400'); // return ["1.23400", "1.234", "00"]
/^([0-9]+\.?[0-9]*?)(0*)$/.exec('1.03456'); // return ["1.03456", "1.03456", ""]
You can use the parseFloat too if you juste interest by getting the significative part of the number.
parseFloat('1.23400') // return 1.234
Try this :
'1.23400'.match(/^.*?(?=0*$)|0+$/g)
// ^.*?(?=0*$) : everything before zero or more trailing zeros
// 0+$ : one or more trailing zeros
Try this:
function lastIndexOfDigit(str) {
var last_indices = [];
[1, 2, 3, 4, 5, 6, 7, 8, 9].map(function (digit) {
last_indices.push(str.lastIndexOf(digit));
});
var indices = last_indices.sort(function (a, b) {
return a - b;
});
return indices[indices.length - 1];
}
I want to verify a Singapore NRIC using javascript,
the formula is
1) Take for example I want to test the NRIC number S1234567. The first digit you multiply by 2, second multiply by 7, third by 6, fourth by 5, fifth by 4, sixth by 3, seventh by 2. Then you add the totals together. So,1×2+2×7+3×6+4×5+5×4+6×3+7×2=106.
2) If the first letter of the NRIC starts with T or G, add 4 to the total.
3) Then you divide the number by 11 and get the remainder. 106/11=9r7
4) You can get the alphabet depending on the IC type (the first letter in the IC) using the code below:
If the IC starts with S or T: 0=J, 1=Z, 2=I, 3=H, 4=G, 5=F, 6=E, 7=D, 8=C, 9=B, 10=A
If the IC starts with F or G: 0=X, 1=W, 2=U, 3=T, 4=R, 5=Q, 6=P, 7=N, 8=M, 9=L, 10=K
How can I read every single number to do the formula?
Thanks in advance!
Strings are arrays so you can assign variables to the letters assuming you know the string has a fixed length, which it appears so, and then create a function to evaluate the characters and do the correct thing:
var nric = 'S1234567'
var chars = {
letter: nric[0],
one: nric[1],
...
}
string.charAt(charpos)
Should do the trick.
Alternatively,
string.substr(charpos,1)
You could also do
string[charpos]
but the first two above are recommended. This will return undefined if the string is empty, whereas the other alternatives will all return the null string.
Another idea is
string.split("")[charpos]
Finally, there is
string.slice(charpos,1)
Since you want a single character at a time I'd recommend charAt.
Elaborating on #elclanrs answer:
var nric = 'S1234567'
var numVal = 0; for(var i = 1, bound = nric.length; i < bound; i++){
numVal += parseInt(nric[i]);
}
if(nric[0] === 'S' && numVal === 28){
alert('ok');
}else{
alert('wrong');
}
should more or less do the trick.
I trust, You can do the multiplying yourself :-)