I'm working on this coding challenge from freecodecamp https://www.freecodecamp.com/challenges/truncate-a-string.
To complete this my code must fulfil the following 3 conditions:
Truncate a string (first argument) if it is longer than the given maximum string length (second argument). Return the truncated string with a ... ending.
The inserted three dots at the end should also add to the string length.
However if the given maximum string length is less than or equal to 3, then the addition of the three dots does not add to the string length in determining the truncated string.
I'm able to fulfil the first 2 conditions, but for some reason my code throws up an error when I give a test case where length of the string is less than or equal to 3...
Example:
truncateString("Absolutely Longer", 2) should return "Ab..." but instead returns "Absolutely Longe..."
Please help. My code is at https://gist.github.com/adityatejas/7857c0866f67783e71a1c9d60d3beed8.
function truncateString(str, num)
{
var truncatedStr = '';
if (str.length > num)
{
truncatedStr = str.slice(0, num-3) + "...";
return truncatedStr;
}
else if (num <= 3)
{
truncatedStr = str.slice(0, num) + "...";
return truncatedStr;
}
else return str;
}
truncateString("Adi", 1);
You want to create a function that takes in two parameters, a string of your choice and a maximum length. Based on the conditions, we need three scenarios.
When the given string exceeds the maximum and the maximum is less than or equal to 3. In this case, the ellipsis is not added to the end of the string. We take a slice of the string from the first character (position zero) until three less than the max and add the ellipses.
When the given string exceeds the maximum and the maximum is greater than 3. In this case, our strings inherently get longer. We update the slice parameters to go from the first index to the length of the string and add the ellipses on top of that.
Otherwise, just return the string as it is, because it does not exceed the maximum length.
var truncatedString = document.getElementById("truncated-string");
function truncateString(myString, strLength) {
if (myString.length > strLength) {
if (strLength <= 3) {
return myString.slice(0, strLength - 3) + "...";
}
else {
return myString.slice(0, strLength) + "...";
}
}
else {
return myString;
}
}
var userInput = prompt("Please enter a string");
var lengthLimit = prompt("Enter a maximum length");
truncatedString.innerHTML = truncateString(userInput, lengthLimit);
<p id="truncated-string"></p>
You could use a conditional (ternary) operator ?: and String#slice
function truncateString(str, num) {
return str.length > num ?
str.slice(0, num > 3 ? num - 3 : num) + "..." :
str;
}
console.log(truncateString("Abcdefghijk", 5));
console.log(truncateString("A-", 1));
console.log(truncateString("Alpha", 5));
console.log(truncateString("Beta", 5));
console.log(truncateString("Epsilon", 3));
Here is a simple solution:
function truncateString(str, num) {
if (str.length > num) {
return str.slice(0, num) + "...";}
else {
return str;}}
Related
Script has to work this way:
isJumping(9) === 'JUMPING'
This is a one digit number
isJumping(79) === 'NOT JUMPING'
Neighboring digits do not differ by 1
isJumping(23454) === 'JUMPING'
Neighboring digits differ by 1
I have:
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
if (Math.abs(str[i+1]) - Math.abs(str[i]) == 1){
return 'JUMPING';
}
}
return 'NOT JUMPING';
}
console.log(isJumping(345));
Help please, where is mistake?
Loop over the characters and early return with "NOT JUMPING" if the condition is violated & if the condition is never violated return "JUMPING".
function isJumping(num) {
const strNum = String(Math.abs(num));
for (let i = 0; i < strNum.length - 1; i++) {
if (Math.abs(strNum[i] - strNum[i + 1]) > 1) {
// replace `> 1` with `!== 1`, if diff 0 is not valid!
return "NOT JUMPING";
}
}
return "JUMPING";
}
console.log(isJumping(9));
console.log(isJumping(79));
console.log(isJumping(23454));
There are a couple of issues:
You're not handling single digits.
You're returning too early. You're returning the first time you see a difference of 1 between digits, but you don't know that subsequent differences will also be 1.
You're not checking the difference between the first and second digits, and you're going past the end of the string.
You're using Math.abs as a means of converting digits to numbers.
Instead (see comments):
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
// Convert to number, do the difference, then
// use Math.abs to make -1 into 1 if necessary
if (Math.abs(+str[i] - str[i-1]) !== 1) {
// Found a difference != 1, so we're not jumping
return "NOT JUMPING";
}
}
// Never found a difference != 1, so we're jumping
return "JUMPING";
}
console.log(isJumping(345)); // JUMPING
console.log(isJumping(9)); // JUMPING
console.log(isJumping(79)); // NOT JUMPING
console.log(isJumping(23454)); // JUMPING
In that, I use +str[i] to convert str[i] to number and implicitly convert str[i-1] to number via the - operator, but there are lots of ways to convert strings to numbers (I list them here), pick the one that makes sense for your use case.
You might also need to allow for negative numbers (isJumping(-23)).
A clumsy way would be if (Math.abs(Math.abs(str[i+1]) - Math.abs(str[i])) == 1). Right now you are using Math.abs() to convert digits to numbers. Also, indexing is off, you start from 1, which is good, but then you should compare [i] and [i-1]. And the usual mismatch: you can say "JUMPING", only at the end. So you should check for !==1, and return "NOT JUMPING" inside the loop, and "JUMPING" after. That would handle the 1-digit case too.
It's a more readable practice to use parseInt() for making a number from a digit, otherwise the implementation of the comment:
function isJumping(number) {
let str = number.toString();
for (let i = 1; i < str.length; i++) {
if (Math.abs(parseInt(str[i-1]) - parseInt(str[i])) !== 1){
return 'NOT JUMPING';
}
}
return 'JUMPING';
}
console.log(isJumping(345));
console.log(isJumping(3));
console.log(isJumping(79));
You just need to check your single digit case, and then see if all the digits vary by just 1
function isJumping(number) {
let str = number.toString();
if(str.length == 1)
return 'JUMPING'
const allByOne = str.substring(1).split('').every( (x,i) => {
var prev = str[i];
return Math.abs( +x - +prev) == 1
})
return allByOne ? 'JUMPING' : 'NOT JUMPING';
}
console.log(isJumping(9));
console.log(isJumping(79));
console.log(isJumping(23454));
A vaguely functional approach... The find gets position of the first character pair where the gap is more than one. The .filter deals with negatives (and other extraneous characters) by ignoring them.
// default b to a, so that last digit case, where b===undefined, gives true
const gapIsMoreThanOne = (a,b=a) => ( Math.abs(a-b)>1);
const isDigit = n => /[0-9]/.test(n);
const isJumping = n => n.toString()
.split("")
.filter(isDigit)
.find((x,i,arr)=>gapIsMoreThanOne(x,arr[i+1]))
=== undefined
? "JUMPING" : "NOT JUMPING"
;
console.log(isJumping(1)); // JUMPING
console.log(isJumping(12)); // JUMPING
console.log(isJumping(13)); // NOT JUMPING
console.log(isJumping(21)); // JUMPING
console.log(isJumping(21234565)); // JUPING
console.log(isJumping(-21234568)); // NOT JUMPING
console.log(isJumping("313ADVD")); // NOT JUMPING
PS: To me "JUMPING" implies that there is a gap greater than one, not that there isn't: but I've gone with how it is in the question.
I am trying to solve this Kata from Codewars: https://www.codewars.com/kata/simple-fun-number-258-is-divisible-by-6/train/javascript
The idea is that a number (expressed as a string) with one digit replaced with *, such as "1047*66", will be inserted into a function. You must return an array in which the values are the original number with the * replaced with any digit that will produce a number divisive by 6. So given "1*0", the correct resulting array should be [120, 150, 180].
I have some code that is producing some correct results but erroring for others, and I can't figure out why. Here's the code:
function isDivisibleBy6(s) {
var results = [];
for(i=0;i<10;i++) {
var string = i.toString(); // Convert i to string, ready to be inserted into s
var array = Array.from(s); // Make an array from s
var index = array.indexOf("*"); // Find where * is in the array of s
array[index] = string; // Replace * with the string of i
var number = array.join(""); // Join all indexes of the s array back together. Now we should have
// a single number expressed as a string, with * replaced with i
parseInt(number, 10); // Convert the string to an integer
if((number % 6) == 0) {
results.push(number);
} // If the integer is divisible by 6, add the integer into the results array
}
return(results);
};
This code works with the above example and generally with all smaller numbers. But it is producing errors for larger numbers. For example, when s is "29070521868839*57", the output should be []. However, I am getting ['29070521868839257', '29070521868839557', '29070521868839857']. I can't figure out where this would be going wrong. Is anyone able to help?
The problem is that these numbers are larger than the Number.MAX_SAFE_INTEGER - the point when JavaScript numbers break down in terms of reliability:
var num = 29070521868839257;
console.log(num > Number.MAX_SAFE_INTEGER);
console.log(num % 6);
console.log(num)
The last log shows that the num actually has a different value than what we gave it. This is because 29070521868839257 simply cannot be represented by a JavaScript number, hence you get the closest possible value that can be represented and that's 29070521868839256.
So, after some point in numbers, all mathematical operations become unreliable as the very numbers are imprecise.
What you can do instead is ignore treating this whole as a number - treat it as a string and only apply the principles of divisibility. This makes the task vastly easier.
For a number to be divisible by 6 it has to cover two criteria:
it has to be divisible by 2.
to verify this, you can just get the very smallest digit and check if it's divisible by 2. For example in 29070521868839257 if we take 7, and check 7 % 2, we get 1 which means that it's odd. We don't need to consider the whole number.
it has to be divisible by 3.
to verify this, you can sum each of the digits and see if that sum is divisible by 3. If we sum all the digits in 29070521868839257 we get 2 + 9 + 0 + 7 + 0 + 5 + 2 + 1 + 8 + 6 + 8 + 8 + 3 + 9 + 2 + 5 + 7 = 82 which is not divisible by 3. If in doubt, we can sum the digits again, since the rule can be applied to any number with more than two digits: 8 + 2 = 10 and 1 + 0 = 1. That is still not divisible by 3.
So, if we apply these we can get something like:
function isDivisibleBy6(s) {
return isDivisibleBy2(s) && isDivisibleBy3(s);
};
function isDivisibleBy2(s) {
var lastDigit = Number(s.slice(-1));
return (lastDigit % 2) === 0;
}
function isDivisibleBy3(s) {
var digits = s.split("")
.map(Number);
var sum = digits.reduce(function(a, b) {
return a + b
});
return (sum % 3) === 0;
}
console.log(isDivisibleBy6("29070521868839257"));
console.log(isDivisibleBy6("29070521868839256"));
These can even be recursively defined true to the nature of these rules:
function isDivisibleBy6(s) {
return isDivisibleBy2(s) && isDivisibleBy3(s);
};
function isDivisibleBy2(s) {
if (s.length === 0) {
return false;
}
if (s.length > 1) {
return isDivisibleBy2(s.slice(-1));
}
var lastDigit = Number(s);
return (lastDigit % 2) === 0;
}
function isDivisibleBy3(s) {
if (s.length === 0) {
return false;
}
if (s.length > 1) {
var digits = s.split("")
.map(Number);
var sum = digits.reduce(function(a, b) {
return a + b
});
return isDivisibleBy3(String(sum));
}
var num = Number(s);
return (num % 3) === 0;
}
console.log(isDivisibleBy6("29070521868839257"));
console.log(isDivisibleBy6("29070521868839256"));
This is purely to demonstrate the rules of division and how they can be applied to strings. You have to create numbers that will be divisible by 6 and to do that, you have to replace an asterisk. The easiest way to do it is like you did - generate all possibilities (e.g., 1*0 will be 100, 110, 120, 130, 140, 150, 160, 170, 180, 190) and then filter out whatever is not divisible by 6:
function isDivisibleBy6(s) {
var allDigits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var allPossibleNumbers = allDigits.map(function(digit) {
return s.replace("*", digit);
});
var numbersDibisibleBySix = allPossibleNumbers.filter(function(s) {
return isDivisibleBy2(s) && isDivisibleBy3(s);
})
return numbersDibisibleBySix;
};
function isDivisibleBy2(s) {
var lastDigit = Number(s.slice(-1));
return (lastDigit % 2) === 0;
}
function isDivisibleBy3(s) {
var digits = s.split("")
.map(Number);
var sum = digits.reduce(function(a, b) {
return a + b
});
return (sum % 3) === 0;
}
console.log(isDivisibleBy6("29070521868839*57"));
console.log(isDivisibleBy6("29070521868839*56"));
As a last note, this can be written more concisely by removing intermediate values and using arrow functions:
function isDivisibleBy6(s) {
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
.map(digit => s.replace("*", digit))
.filter(s => isDivisibleBy2(s) && isDivisibleBy3(s));
};
const isDivisibleBy2 = s => Number(s.slice(-1)) % 2 === 0;
const isDivisibleBy3 = s => s.split("")
.map(Number)
.reduce((a, b) => a + b) % 3 === 0
console.log(isDivisibleBy6("29070521868839*57"));
console.log(isDivisibleBy6("29070521868839*56"));
Sum of all digits is divisible by three and the last digit is divisible by two.
An approach:
Get the index of the star.
Get left and right string beside of the star.
Return early if the last digit is not divisible by two.
Take the sum of all digits.
Finally create an array with missing digits:
Start loop from either zero (sum has no rest with three) or take the delta of three and the rest (because you want a number which is divisible by three).
Go while value is smaller then ten.
Increase the value either by 3 or by 6, if the index of the star is the last character.
Take left, value and right part for pushing to the result set.
Return result.
function get6(s) {
var index = s.indexOf('*'),
left = s.slice(0, index),
right = s.slice(index + 1),
result = [],
sum = 0,
i, step;
if (s[s.length - 1] % 2) return [];
for (i = 0; i < s.length; i++) if (i !== index) sum += +s[i];
i = sum % 3 && 3 - sum % 3;
step = s.length - 1 === index ? 6 : 3;
for (; i < 10; i += step) result.push(left + i + right);
return result;
}
console.log(get6("*")); // ["0", "6"]
console.log(get6("10*")); // ["102", "108"]
console.log(get6("1*0")); // ["120", "150", "180"]
console.log(get6("*1")); // []
console.log(get6("1234567890123456789012345678*0")); // ["123456789012345678901234567800","123456789012345678901234567830","123456789012345678901234567860","123456789012345678901234567890"]
.as-console-wrapper { max-height: 100% !important; top: 0; }
The problem is with:
parseInt(number, 10);
You can check and see that when number is large enough, this result converted back to string is not equal to the original value of number, due to the limit on floating point precision.
This challenge can be solved without having to convert the given string to number. Instead use a property of numbers that are multiples of 6. They are multiples of 3 and even. Multiples of 3 have the property that the sum of the digits (in decimal representation) are also multiples of 3.
So start by checking that the last digit is not 1, 3, 5, 7, or 9, because in that case there is no solution.
Otherwise, sum up the digits (ignore the asterisk). Determine which value you still need to add to that sum to get to a multiple of 3. This will be 0, 1 or 2. If the asterisk is not at the far right, produce solutions with this digit, and 3, 6, 9 added to it (until you get double digits).
If the asterisk is at the far right, you can do the same, but you must make sure that you exclude odd digits in that position.
If you are desperate, here is a solution. But I hope you can make it work yourself.
function isDivisibleBy6(s) {
// If last digit is odd, it can never be divisable by 6
if ("13579".includes(s[s.length-1])) return [];
let [left, right] = s.split("*");
// Calculate the sum of the digits (ignore the asterisk)
let sum = 0;
for (let ch of s) sum += +ch || 0;
// What value remains to be added to make the digit-sum a multiple of 3?
sum = (3 - sum%3) % 3;
// When asterisk in last position, then solution digit are 6 apart, otherwise 3
let mod = right.length ? 3 : 6;
if (mod === 6 && sum % 2) sum += 3; // Don't allow odd digit at last position
// Build the solutions, by injecting the found digit values
let result = [];
for (; sum < 10; sum += mod) result.push(left + sum + right);
return result;
}
// Demo
console.log(isDivisibleBy6("1234567890123456789012345678*0"));
BigInt
There is also another way to get around the floating point precision problem: use BigInt instead of floating point. However, BigInt is not supported on CodeWars, at least not in that specific Kata, where the available version of Node goes up to 8.1.3, while BigInt was introduced only in Node 10.
function isDivisibleBy6(s) {
let [left, right] = s.split("*");
let result = [];
for (let i = 0; i < 10; i++) {
let k = BigInt(left + i + right);
if (k % 6n === 0n) result.push(k.toString());
}
return result;
}
// Demo
console.log(isDivisibleBy6("1234567890123456789012345678*0"));
This would anyway feel like "cheating" (if it were accepted), as it's clearly not the purpose of the Kata.
As mentioned, the values you are using are above the maximum integer value and therefore unsafe, please see the docmentation about this over here Number.MAX_SAFE_INTEGER. You can use BigInt(string) to use larger values.
Thanks for all the responses. I have now created successful code!
function isDivisibleBy6(s) {
var results = [];
for(i=0;i<10;i++) {
var string = i.toString();
var array = Array.from(s);
var index = array.indexOf("*");
array[index] = string;
var div2 = 0;
var div3 = 0;
if(parseInt((array[array.length-1]),10) % 2 == 0) {
div2 = 1;
}
var numarray = array.map((x) => parseInt(x));
if(numarray.reduce(function myFunc(acc, value) {return acc+value}) % 3 == 0) {
div3 = 1;
}
if(div2 == 1 && div3 == 1) {
results.push(array.join(""));
}
}
return(results);
};
I know this could be factored down quite a bit by merging the if expressions together, but I like to see things split out so that when I look back over previous solutions my thought process is clearer.
Thanks again for all the help!
Hello I'm stuck on an edge case in a coding challenge: would be great if someone could help;
In this little assignment you are given a string of space separated numbers, and have to return the highest and lowest number.
Example:
highAndLow("1 2 3 4 5"); // return "5 1"
highAndLow("1 2 -3 4 5"); // return "5 -3"
highAndLow("1 9 3 4 -5"); // return "9 -5"
Notes:
All numbers are valid Int32, no need to validate them.
There will always be at least one number in the input string.
Output string must be two numbers separated by a single space, and highest number is first.
Here is my code in Javascript:
function highAndLow(numbers){
numbers2=numbers.split(' ');
var highest =parseInt(numbers2[0]);
var lowest =parseInt(numbers2[0]);
if (numbers2.length==1) {
return numbers;
}
else {
for (i=0;i<numbers2.length;i++) {
if (parseInt(numbers2[i])>highest) {
highest = parseInt(numbers2[i]);
}
else if (parseInt(numbers2[i])<lowest) {
lowest = parseInt(numbers2[i]);
}
}
}
return(highest + " " + lowest);
}
I can pass 17 tests but am stuck on an Expected '42 42' because I am returning '42' which is puzzling to me. Any help appreciated :]
I think you should just add <= and >= instead of > and <so the both conditions are satisfied
You can also do it by sorting the array and then choosing the first and last element from the sorted array.
function highestAndLowest(nums) {
let numbers = nums.split(' ');
let sorted = numbers.sort(function (a, b) {
return Number(a) - Number(b);
});
return sorted[0] + " " + sorted[sorted.length - 1];
}
https://jsbin.com/farapep/edit?js,console
This can be faster depending on the browsers sort implementation, the size of the array, and the initial order of the array.
I think it will work well just like this
function highAndLow(numbers){
numbers = numbers.split(" ");
return Math.max(...numbers) +" "+ Math.min(...numbers);
}
if (numbers2.length==1) {
return numbers;
}
That means if just "42" passed, you return "42". Thats not required here. Just remove that and it should work. How i would write it:
function getMaxMin(numbers){
numbers = numbers.split(" ");
return Math.max(...numbers) +" "+ Math.min(...numbers);
}
or your code a bit beautified:
function getMaxMin(numbers){
var max,min;
numbers = numbers.split(" ");
for( var num of numbers ){
if( !max || num > max ) max = num;
if( !min || num < min ) min = num;
}
return max+" "+min;
}
Kotlin
fun highAndLow(numbers: String): String {
val s = numbers.split(" ").sorted()
return "${s.last()} ${s.first()}"
}
or in one line
fun highAndLow(numbers: String): String = numbers.split(" ").sorted().run { "${first()} ${last()}" }
Let us consider the given example:
highAndLow("1 2 3 4 5"); // return "5 1"
On calling function highAndLow with arguments ("1 2 3 4 5"), output should be "5 1".
So my function takes the argument. Each number is picked upon on the basis of space between them(used split method). I have used ParseInt to specify the datatype, because var can be anything(string/integer). The algorithm used is very basic one which considers the first number as the maximum and compares its with the rest of the arguments. Value of max is updated if it finds a number greater than itself. Same algorithm is used for min value also. The return statement is designed to get the value in specific way as mentioned in the example.
function highAndLow(numbers){
num=numbers.split(' ');
var max = parseInt(num[0]);
var min = parseInt(num[0]);
for (var i = 0; i <= num.length; i++) {
if(parseInt(num[i]) > max){
max = parseInt(num[i]);
}
}
for (var i = 0; i <= num.length; i++) {
if(parseInt(num[i]) < min){
min = parseInt(num[i]);
}
}
return (max + " " + min);
}
You can also use inbuilt methods min and max. I wanted to solve this question without using them.
I'm trying to create my own decimal to binary converter with the method of decrementing the inputted variable (decimal value), by dividing it by 2 and storing the remainder (like 2nd grade math remainder), which is always either 0 or 1. Each of the remainder values i thin should be stored in an array and I think maybe put in backwards so that the most significant digit is first in the array (this is because when decrementing the remainer values are filled in left to right). Soooo yea i dont really know how to store the remainder values in an array using a function
Thanks in advance and if something is confusing then feel free to ask because im not even sure if this is the best method of doing this its just what i came up with
function decimalToBinary(num) {
var bin = 0;
while (num > 0) {
bin = num % 2 + bin;
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin);
}
Your code is almost correct. The main problem is that bin starts out as 0; when you add a digit, they are added numerically, so your code ends up just counting the binary 1s: in this manner, 10 is initial 0, and +1+0+1+0, resulting in 2. You want to handle it as a string: ""+1+0+1+0 results in 1010. So, the only needed change is:
var bin = "";
If you want to solve it using arrays, with minimal changes to your code, it would be:
function decimalToBinary(num) {
var bin = [];
while (num > 0) {
bin.unshift(num % 2);
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin.join(''));
}
Here, I use .unshift to add an element to the head of the array (and renumbering the remaining elements); .join() to collect them all into a string.
Or this:
function decimalToBinary(num) {
var bin = [];
while (num > 0) {
bin[bin.length] = num % 2;
num >>= 1; // basically /= 2 without remainder if any
}
alert("That decimal in binary is " + bin.reverse().join(''));
}
This is not as good, but illustrates some more things you can do with arrays: taking their length, setting an arbitrary element, and flipping them around.
I have written a custom Decimal to Binary method:
function toBinary (input) {
let options = [1];
let max = 0;
let i = 1;
while(i) {
max = Math.pow(2, i);
if (max > input) break;
options.push(max);
i++;
}
let j = options.length;
let result = new Array(j);
result.fill("0");
while(j >= 0) {
if (options[j] <= input) {
result[j] = "1"
input = input - options[j];
}
j--;
}
return [...result].reverse().join("");
}
//Test the toBin method with built-in toString(2)
toBinary(100) === (100).toString(2) // true
toBinary(1) === (1).toString(2) // true
toBinary(128) === (128).toString(2) // true
I have a simple javascript function that tells me how many digits are in a number.
My Problem: On the last line I get a compiler error saying "Missing last ')' parenthisis". I am altering a snippet I found through google & it uses the function Math.log10() but I am not sure a function like this exists?
Can you help me to determine the number of digits in a number (eg 1000 = 4, 10 = 2, etc.)?
function getDigitCount( number )
{
//return ((number ==0) ? 1 : (int)Math.log10(number) + 1);
if ( (number == 0) )
{
return 1;
}
else return ((int)Math.log10(number) + 1);
}
You cannot cast to an int in Javascript. Instead, use Math.floor. Also, divide by Math.log(10) (or Math.LN10) instead of using Math.log10() to find the base 10 logarithm of a number.:
else return (Math.floor(Math.log(number)/Math.log(10)) + 1);
You may try this:
Assuming that "number" is a positive integer value
function getDigitCount(number)
{
var c = "x" + number;
return c.length -1;
}