I want to create a javascript function to flip 1's to 0's in a natural number and I'm out of Ideas to achieve this,
Actually, I had a couple of URL's, and I replaced all 0's from a query parameter with 1's and now I no longer know the original parameter value, because there were few 1's in the original parameter value and now both are mixed, so basically I screwed myself,
The only solution for me is to try flipping each 1 to 0 and then 0's to 1's and test each number as the parameter.
This is the parameter value (after replacing 0's with 1's)
11422971
using above input I want to generate numbers as follows and test each of these
11422970
10422971
10422970
01422971
As you can see only 1's and 0's are changing, the change according to binary,
Each position in your string can be one of n characters:
A "0" can be either "0" or "1"
A "1" can be either "0" or "1"
Any other character c can only be c
We can store this in an array of arrays:
"11422971" -> [ ["0", "1"], ["0, "1"], ["4"], ... ]
To transform your string to this format, you can do a split and map:
const chars = "11422971"
.split("")
.map(c => c === "1" || c === "0" ? ["1", "0"] : [ c ]);
Once you got this format, the remaining logic is to create all possible combinations from this array. There are many ways to do so (search for "array combinations" or "permutations"). I've chosen to show a recursive pattern:
const chars = "11422971"
.split("")
.map(c =>
c === "1" || c === "0"
? ["1", "0"]
: [ c ]
);
const perms = ([ xs, ...others ], s = "", ps = []) =>
xs
? ps.concat(...xs.map(x => perms(others, s + x, ps)))
: ps.concat(s);
console.log(perms(chars));
you can do it with a number like a string, and after parse it, something like that
var number= "12551";
number= number.replace("1","0");
The result of number will be "02550"
after that parse number to int
This will generate all permutations.
const generatePermutations = (number) => {
let digits = number.split('');
// find out which digits can be flipped
let digitPositions = digits.reduce((acc, val, i) => {
if (val === '0' || val === '1') acc.push(i);
return acc;
}, []);
// we're going to be taking things in reverse order
digitPositions.reverse();
// how many digits can we flip
let noBits = digitPositions.length;
// number of permutations is 2^noBits i.e. 3 digits means 2^3 = 8 permutations.
let combinations = Math.pow(2, digitPositions.length);
let permutations = [];
// for each permutation
for (var p = 0; p < combinations; p++) {
// take a copy of digits for this permutation
permutations[p] = digits.slice();
// set each of the flippable bits according to the bit positions for this permutation
// i = 3 = 011 in binary
for (var i = 0; i < noBits; i++) {
permutations[p][digitPositions[i]] = '' + ((p >> i) & 1);
}
permutations[p] = permutations[p].join('');
}
return permutations;
};
console.log(generatePermutations('11422970'));
In case your looking for a recursive approach:
function recursive(acc, first, ...rest) {
if(!first) return acc;
if(first == '0' || first == '1') {
var acc0 = acc.map(x => x + '0');
var acc1 = acc.map(x => x + '1');
return recursive([].concat(acc0, acc1), ...rest);
} else {
return recursive(acc.map(x => x + first), ...rest);
}
}
recursive([''], ...'11422971')
// output ["00422970", "10422970", "01422970", "11422970", "00422971", "10422971", "01422971", "11422971"]
This just counts in binary and fills out a template for each value.
function getPossibleValues(str) {
function getResult(n) {
let nIndex = 0;
const strValue = n.toString(2).padStart(nDigits, '0');
return str.replace(rxMatch, () => strValue.charAt(nIndex++));
}
const rxMatch = /[01]/g;
const nDigits = str.length - str.replace(rxMatch, '').length;
const nMax = Math.pow(2, nDigits);
const arrResult = [];
for(let n = 0; n<nMax; n++) {
arrResult.push(getResult(n));
}
return arrResult;
}
console.log(getPossibleValues('11422970'));
Thank you all to respond, you saved my life, btw the approach I used was,
0- convert the number into a string. (so we can perform string operations like split())
1- count the number of 1's in the string (let's say the string is "11422971", so we get three 1's, I used split('1')-1 to count)
2- generate binary of three-digit length,(ie from 000 to 111). three came from step 1.
2- break down the string to single chars, (we'll get
array=['1','1','4','2','2','9','7','1'] )
3- take the first binary number (ie b=0b000)
4- replace first 1 from the character array with the first binary digit of b (ie replace 1 with 0), similarly replace second 1 with the second binary digit of b and so on.
5- we'll get the first combination (ie "00422970")
5- repeat step 3 and 4 for all binary numbers we generated in step 2.
Related
If I have a string a12c56a1b5 then out put should be a13b5c56 as character a is repeated twice so a12 becomes a13
I have tried this:
function stringCompression (str) {
var output = '';
var count = 0;
for (var i = 0; i < str.length; i++) {
count++;
if (str[i] != str[i+1]) {
output += str[i] + count;
count = 0;
}
}
console.log(output); // but it returns `a11121c15161a111b151` instead of `a13b5c56`
}
It is happening because the code is counting the occurrence of each element and appending it, even the numbers in the string.
In this code,
for (var i = 0; i < str.length; i++) {
count++;
if (str[i] != str[i+1]) {
output += str[i] + count;
count = 0;
}
}
in first iteration i = 0, str[i] = 'a' and str[i + 1] = '1' for the given string a12c56a1b5 which are not equal hence, it will generate the output as a1 for first iteration, then a111 for second iteration since str[i] = '1' and str[i + 1] = '2' now, and so on.
We can achieve this by first separating the characters from the count. Assuming, that there would be characters from a-z and A-Z only followed by the count. We can do something like this, str.match(/[a-zA-Z]+/g) to get the characters: ["a", "c", "a", "b"] and str.match(/[0-9]+/g) to get their counts: ["12", "56", "1", "5"], put them in an object one by one and add if it already exists.
Something like this:
function stringCompression(str) {
var characters = str.match(/[a-zA-Z]+/g);
var counts = str.match(/[0-9]+/g);
var countMap = {};
for (var i = 0; i < characters.length; i++) {
if (countMap[characters[i]]) {
countMap[characters[i]] += parseInt(counts[i]);
} else {
countMap[characters[i]] = parseInt(counts[i]);
}
}
var output = Object.keys(countMap)
.map(key => key + countMap[key])
.reduce((a, b) => a + b);
console.log(output);
}
stringCompression('a12c56a1b5')
Using regex to extract word characters and numbers. Keeps an object map res to track and sum up following numbers. sorts and converts back to a string.
As an example, the for-of loop iteration flow with str=a12c56a1b5:
c='a', n='12'
res['a'] = (+n = 12) + ( (res['a'] = undefined)||0 = 0)
or ie: res['a'] = 12 + 0
c='c', n='56'
res['c'] = 56 + 0
c='a', n='1'
res['a'] = 1 + (res['a'] = 12 from iteration 1.) = 13
c='b', n='5'
res['b'] = 5 + 0
thus res = { 'a': 13, 'c': 56, 'b': 5 } after the for-of loop finishes
function stringCompression (str) {
// build object map with sums of following numbers
const res = {}
for(const [,c,n] of str.matchAll(/(\w+)(\d+)/g))
res[c] = +n + (res[c]||0)
// convert object map back to string
output = Object.entries(res)
output.sort(([a],[b])=>a<b ? -1 : a>b ? 1 : 0)
output = output.map(([a,b])=>`${a}${b}`).join('')
console.log(output); // but it returns `a11121c15161a111b151` instead of `a13b5c56`
}
stringCompression('a12c56a1b5')
[,c,n] = [1,2,3] is equivalent to c=2, n=3. It is called destructuring.
matchAll matches on a regex. It's a relatively new shorthand for calling .exec repeatedly to execute a regular expression that collects all the results that the regular expression matches on.
(\w+)(\d+) is a regex for two capture groups,
\w+ is for one or more alpha characters, \d+ is for one or more digits.
for(const [,c,n] of str.matchAll...) is equivalent to:
for each M of str.matchAll...
const c = M[1], n = M[2]`
res[c]||0 is shorthand for:
"give me res[c] if it is truthy (not undefined, null or 0), otherwise give me 0"
+n uses the unary operator + to force an implicit conversion to a number. JavaScript specs for + unary makes it convert to number, since + unary only makes sense with numbers.
It is basically the same as using Number(n) to convert a string to an number.
Conversion back to a string:
Object.entries converts an object {"key":value} to an array in the form of [ [key1, value1], [key2, value2] ]. This allows manipulating the elements of an object like an array.
.sort sorts the array. I destructured the keys to sort on the keys, so "a" "b" "c" are kept in order.
.map takes an array, and "maps" it to another array. In this case I've mapped each [key,value] to a string key+value, and then taking the final mapped array of key+value strings and joined them together to get the final output.
In case it asks you to sort it alphabetically, I added #user120242's sorting code snippet to #saheb's entire answer (in between Object.keys(countMap) and .map(...). That worked for me. I tried using #user120242's whole answer, but it did not pass all the tests since it did not add the repeated letters for longer strings. But #user120242's answer did work. It just need to be sorted alphabetically and it passed all the test cases in HackerRank. I had this question for a coding assessment (called "Better Coding Compression").
P.S. I also removed checking the capital letters from #saheb's code since that wasn't required for my coding challenge.
Here's how mine looked like:
function stringCompression(str) {
var characters = str.match(/[a-zA-Z]+/g);
var counts = str.match(/[0-9]+/g);
var countMap = {};
for (var i = 0; i < characters.length; i++) {
if (countMap[characters[i]]) {
countMap[characters[i]] += parseInt(counts[i]);
} else {
countMap[characters[i]] = parseInt(counts[i]);
}
}
var output = Object.keys(countMap)
.sort(([a],[b])=>a<b ? -1 : a>b ? 1 : 0)
.map(key => key + countMap[key])
.reduce((a, b) => a + b);
console.log(output);
}
stringCompression('a12c56a1b5')
Question 2: The input consist of a string, "o" represents odd number, "e" represents even number to be printed
Example 1.
Input: 8-e
Expected Output: 2|4|6|8
Example 2.
Input: 6-o
Expected Output: 1|3|5
Example 3.
Input: 1-o
Expected Output: 1
if have tried with for loop, but I'am a beginner so I'am confused with(-e)
const evenOdd = (number) => {
let evenvalue = [];
let oddValue=[];
for(let i =0; i<=number; i++){
if(number%i==0)
evenvalue.push(i);
console.log(evenvalue);
}if(number%i!=0){
oddValue.push(i);
console.log(oddValue);
}
};
evenOdd(9);
You could take a while statement and get a start value of one plus an offset of one if the wanted type is even. Then iterate and add the value to the result set until the value is greater than the maximum value.
function fn(request) {
var [max, type] = request.split('-'),
i = 1 + (type === 'e'),
result = [];
while (i <= max) {
result.push(i);
i += 2;
}
return result;
}
console.log(...fn('8-e'));
console.log(...fn('6-o'));
console.log(...fn('1-o'));
You will need to extract the letter and the number from you string first. One easy way to do that :
const evenOdd = (s) => {
let odd = s.length-1 ==='o';
let number = Number(s.substring(0, s.length-2));
let evenvalue = [];
...
if(odd){...} else {...}
};
You could also use split() or if the pattern was more complicated, a Regex.
You can split on - and add based on type add values upto the number
Split the given input by -, first value represents max number and second represents it's type
Check the type if it is even add the even values start from 2 and upto to the max number else start from 1, and join them with | in the end
let func = (input) => {
let [num, type] = input.split('-')
let arr = []
let i = 1 + (type === 'e')
while (i <= num) {
arr.push(i)
i += 2
}
return arr.join('|')
}
console.log(func('8-e'))
console.log(func('1-o'))
console.log(func('6-o'))
Basically, don't supply a number to the function, supply a string and then parse the string. That is, don't try and give the function 9-e, give it '9-e'.
Get the parts of the input by splitting on -.
Turn the number into a number.
Give 0 for even, 1 for odd (x % 2 is 0 for even number, 1 for odd).
Build the results.
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
let result = [];
for(let i = 1; i <= number; i++)
{
if(i%2 === numberType)
{
result.push(i);
}
}
return result;
}
console.log(listNumbers('8-e'));
Or if you want make the code look clever:
function listNumbers(constraint)
{
const parts = constraint.split('-');
const number = Number(parts[0]);
const numberType = parts[1] === 'e' ? 0:1;
return Array.from(Array(number), (x,i) => i + 1 ).filter(x => x%2 == numberType);
}
console.log(listNumbers('8-e'));
I saw this line of code in a correction in a coding game
const tC = readline().split(' ').map(x => +x);
I wonder what it does because when I log this function it render the same thing that this one
const tC = readline().split(' ').map(x => x);
but the rest of the code didn't work
Context :
/** Temperatures (easy) https://www.codingame.com/training/easy/temperatures
* Solving this puzzle validates that the loop concept is understood and that
* you can compare a list of values.
* This puzzle is also a playground to experiment the concept of lambdas in
* different programming languages. It's also an opportunity to discover
* functional programming.
*
* Statement:
* Your program must analyze records of temperatures to find the closest to
* zero.
*
* Story:
* It's freezing cold out there! Will you be able to find the temperature
* closest to zero in a set of temperatures readings?
**/
const N = +readline();
const tC = readline().split(' ').map(x => +x);
let min = Infinity;
for (let i in tC) {
(Math.abs(tC[i]) < Math.abs(min) || tC[i] === -min && tC[i] > 0) && (min = tC[i]);
}
print(min || 0);
Thanks a lot
The .map(x => +x) converts all items in the array to a number. And returns a new array with those converted values.
If you change it to .map(x => x) then the values are left untouched und you just create a copy of the original array. So the strings remain strings which will break the code if numbers are expected.
I personally would avoid the +x syntax and use the more verbose Number(x), and write either .map(x => Number(x)) or .map(Number).
According to this site below are the inputs the program should receive
Line 1: N, the number of temperatures to analyze
Line 2: A string with the N temperatures expressed as integers ranging from -273 to 5526
Let me provide line by line comments with respect to the game rules
// Line 1: reads number temperature inputs. + converts to number
const N = +readline();
// Line 2: reads string of temperatures.
// tC contains an array of temperatures of length N in numbers. + converts to number
const tC = readline().split(' ').map(x => +x);
let min = Infinity;
// iterate over tC array
for (let i in tC) {
// If two numbers are equally close to zero, positive integer has to be considered closest to zero
// set min = current iterating number if it matches above condition
(Math.abs(tC[i]) < Math.abs(min) || tC[i] === -min && tC[i] > 0) && (min = tC[i]);
}
print(min || 0);
Here is the working demo in javascript
modified to make it understandable for beginners.
// Line 1: reads number temperature inputs. + converts to number
// const N = +readline(); SAMPLE ALTERNATIVE
const N = +"5";
// Line 2: reads string of temperatures.
// tC contains an array of temperatures of length N in numbers. + converts to number
// const tC = readline().split(' ').map(x => +x); SAMPLE ALTERNATIVE
const tC = "1 -2 -8 4 5".split(' ').map(x => +x);
let min = Infinity;
// iterate over tC array
for (let i in tC) {
// If two numbers are equally close to zero, positive integer has to be considered closest to zero
// set min = current iterating number if it matches above condition
(Math.abs(tC[i]) < Math.abs(min) || tC[i] === -min && tC[i] > 0) && (min = tC[i]);
}
console.log(min || 0);
function readLine(){
return "123456"
}
var result = readLine().split("").map(x => +x)
console.log(result)
readLine().split("") // splits the string into an array as follows ["1", "2", "3", "4", "5", "6"]
.map(x => +x) // map method returns a new array which will take each item and gives a new array , here number changing from string to numbers as follows [1, 2, 3, 4, 5, 6] since +x is used
// the above is written in es6, which can be re written in es5 as follows
readLine().split("").map(function(x) {
return +x
})
// Note
In es6 if we have a single thing to pass we can avoid the function(x) to x
also we can remove the {} [curly braces and return too]
{return +x} to +x
ES2015
readLine().split("").map(function(x) {
return +x
})
ES2016
readLine().split("").map(x => +x);
I was given the challenge of converting a string of digits into 'fake binary' on Codewars.com, and I am to convert each individual digit into a 0 or a 1, if the number is less than 5 it should become a 0, and if it's 5 or over it should become a 1. I know how to analyze the whole string's value like so:
function fakeBin(x){
if (x < 5)
return 0;
else return 1;
}
This however, analyzes the value of the whole string, how would I go about analyzing each individual digit within the string rather than the whole thing?
Note: I have already looked at the solutions on the website and don't understand them, I'm not cheating.
You can do it in one line with two simple global string replacement operations:
function fakeBin(x){
return ("" + x).replace(/[0-4]/g,'0').replace(/[5-9]/g,'1');
}
console.log(fakeBin(1259))
console.log(fakeBin(7815))
console.log(fakeBin("1234567890"))
The ("" + x) part is just to ensure you have a string to work with, so the function can take numbers or strings as input (as in my example calls above).
Simple javascript solution to achieve expected solution
function fakeBin(x){
x = x+'' ;
var z =[];
for(var i=0;i< x.length;i++){
if((x[i]*1)<5){
z[i] =0;
}else{
z[i]=1;
}
}
return z
}
console.log(fakeBin(357))
The snippet below will take a string and return a new string comprised of zeros and/or ones based on what you described.
We use a for ...of loop to traverse the input string and will add a 0 or 1 to our return array based on whether the parsed int if greater or less than 5.
Also note that we are checking and throwing an error if the character is not a number.
const word = "1639";
const stringToBinary = function(str) {
let ret = [];
for (const char of word) {
if (Number.isNaN(parseInt(char, 10))) {
throw new Error(`${char} is not a digit!`);
} else {
const intVal = parseInt(char, 10);
ret.push(intVal > 5 ? 1 : 0);
}
}
return ret.join('');
};
console.log(stringToBinary(word));
if you are in java you can use
charAt()
and you make a for with the word length and you can check one by one
for(int i = 0; i < text.length(); i++){
yourfunction(texto.charAt(i));
}
Split the string and apply the current function you have to each element of the string. You can accomplish this with map or with reduce:
function fakeBin(x) {
x = x.split('');
let toBin = x => {
if (x < 5)
return 0;
else return 1
}
return x.map(toBin).join('');
}
console.log(fakeBin("2351"));
refactored
function fakeBin(x) {
x = [...x];
let toBin = x => x < 5 ? 0 : 1;
return x.map(toBin).join('');
}
console.log(fakeBin("2351"));
reduce
function fakeBin(x) {
let toBin = x => x < 5 ? 0 : 1;
return [...x].reduce((acc,val) => acc + toBin(val), "");
}
console.log(fakeBin("23519"));
You can use String.prototype.replace() with RegExp /([0-4])|([5-9])/g to match 0-4, 5-9, replace with 0, 1 respectively
let str = "8539734222673566";
let res = str.replace(/([0-4])|([5-9])/g, (_, p1, p2) => p1 ? 0 : 1);
console.log(res);
I want to convert a number to its corresponding alphabet letter. For example:
1 = A
2 = B
3 = C
Can this be done in javascript without manually creating the array?
In php there is a range() function that creates the array automatically. Anything similar in javascript?
Yes, with Number#toString(36) and an adjustment.
var value = 10;
document.write((value + 9).toString(36).toUpperCase());
You can simply do this without arrays using String.fromCharCode(code) function as letters have consecutive codes. For example: String.fromCharCode(1+64) gives you 'A', String.fromCharCode(2+64) gives you 'B', and so on.
Snippet below turns the characters in the alphabet to work like numerical system
1 = A
2 = B
...
26 = Z
27 = AA
28 = AB
...
78 = BZ
79 = CA
80 = CB
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var result = ""
function printToLetter(number){
var charIndex = number % alphabet.length
var quotient = number/alphabet.length
if(charIndex-1 == -1){
charIndex = alphabet.length
quotient--;
}
result = alphabet.charAt(charIndex-1) + result;
if(quotient>=1){
printToLetter(parseInt(quotient));
}else{
console.log(result)
result = ""
}
}
I created this function to save characters when printing but had to scrap it since I don't want to handle improper words that may eventually form
Just increment letterIndex from 0 (A) to 25 (Z)
const letterIndex = 0
const letter = String.fromCharCode(letterIndex + 'A'.charCodeAt(0))
console.log(letter)
UPDATE (5/2/22): After I needed this code in a second project, I decided to enhance the below answer and turn it into a ready to use NPM library called alphanumeric-encoder. If you don't want to build your own solution to this problem, go check out the library!
I built the following solution as an enhancement to #esantos's answer.
The first function defines a valid lookup encoding dictionary. Here, I used all 26 letters of the English alphabet, but the following will work just as well: "ABCDEFG", "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "GFEDCBA". Using one of these dictionaries will result in converting your base 10 number into a base dictionary.length number with appropriately encoded digits. The only restriction is that each of the characters in the dictionary must be unique.
function getDictionary() {
return validateDictionary("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
function validateDictionary(dictionary) {
for (let i = 0; i < dictionary.length; i++) {
if(dictionary.indexOf(dictionary[i]) !== dictionary.lastIndexOf(dictionary[i])) {
console.log('Error: The dictionary in use has at least one repeating symbol:', dictionary[i])
return undefined
}
}
return dictionary
}
}
We can now use this dictionary to encode our base 10 number.
function numberToEncodedLetter(number) {
//Takes any number and converts it into a base (dictionary length) letter combo. 0 corresponds to an empty string.
//It converts any numerical entry into a positive integer.
if (isNaN(number)) {return undefined}
number = Math.abs(Math.floor(number))
const dictionary = getDictionary()
let index = number % dictionary.length
let quotient = number / dictionary.length
let result
if (number <= dictionary.length) {return numToLetter(number)} //Number is within single digit bounds of our encoding letter alphabet
if (quotient >= 1) {
//This number was bigger than our dictionary, recursively perform this function until we're done
if (index === 0) {quotient--} //Accounts for the edge case of the last letter in the dictionary string
result = numberToEncodedLetter(quotient)
}
if (index === 0) {index = dictionary.length} //Accounts for the edge case of the final letter; avoids getting an empty string
return result + numToLetter(index)
function numToLetter(number) {
//Takes a letter between 0 and max letter length and returns the corresponding letter
if (number > dictionary.length || number < 0) {return undefined}
if (number === 0) {
return ''
} else {
return dictionary.slice(number - 1, number)
}
}
}
An encoded set of letters is great, but it's kind of useless to computers if I can't convert it back to a base 10 number.
function encodedLetterToNumber(encoded) {
//Takes any number encoded with the provided encode dictionary
const dictionary = getDictionary()
let result = 0
let index = 0
for (let i = 1; i <= encoded.length; i++) {
index = dictionary.search(encoded.slice(i - 1, i)) + 1
if (index === 0) {return undefined} //Attempted to find a letter that wasn't encoded in the dictionary
result = result + index * Math.pow(dictionary.length, (encoded.length - i))
}
return result
}
Now to test it out:
console.log(numberToEncodedLetter(4)) //D
console.log(numberToEncodedLetter(52)) //AZ
console.log(encodedLetterToNumber("BZ")) //78
console.log(encodedLetterToNumber("AAC")) //705
UPDATE
You can also use this function to take that short name format you have and return it to an index-based format.
function shortNameToIndex(shortName) {
//Takes the short name (e.g. F6, AA47) and converts to base indecies ({6, 6}, {27, 47})
if (shortName.length < 2) {return undefined} //Must be at least one letter and one number
if (!isNaN(shortName.slice(0, 1))) {return undefined} //If first character isn't a letter, it's incorrectly formatted
let letterPart = ''
let numberPart= ''
let splitComplete = false
let index = 1
do {
const character = shortName.slice(index - 1, index)
if (!isNaN(character)) {splitComplete = true}
if (splitComplete && isNaN(character)) {
//More letters existed after the numbers. Invalid formatting.
return undefined
} else if (splitComplete && !isNaN(character)) {
//Number part
numberPart = numberPart.concat(character)
} else {
//Letter part
letterPart = letterPart.concat(character)
}
index++
} while (index <= shortName.length)
numberPart = parseInt(numberPart)
letterPart = encodedLetterToNumber(letterPart)
return {xIndex: numberPart, yIndex: letterPart}
}
this can help you
static readonly string[] Columns_Lettre = new[] { "A", "B", "C"};
public static string IndexToColumn(int index)
{
if (index <= 0)
throw new IndexOutOfRangeException("index must be a positive number");
if (index < 4)
return Columns_Lettre[index - 1];
else
return index.ToString();
}