I have an assessment in JavaScript which is a little bit odd. Here it is:
Goal:
In Chinese culture, it is common during celebrations to give "red
envelopes" containing a little money. Most often, the adult
generations give to the younger generations. You want to build a
WeChat application to help grandparents share their donation budget
between their grandchildren.
Write a program that calculates the number of "lucky gifts" (equal to 8) according to the money budget and the number of giftees grandchildren
Functioning:
Many rules, mixing tradition and superstition, frame this gift:
Donations should not contain amount 4, as it sounds like "dead"
it is auspicious to donate an amount of 8, as it sounds like "fortune"
it would be frowned upon not to give anything to one of the
grandchildren
your algorithm must return the number of donations equal to 8 while
respecting the following rules:
Spend the entire budget (unless there is enough budget to give everyone 8)
Give no 4 (by tradition, the budget will never be 4)
Give no 0 (unless the budget is not sufficient)
Score a maximum of 8 once the above rules are respected
Implementation:
Implement the function luckyMoney(money,giftees) which :
take as inputs the integers money and giftees with:
0 <=money< 100
0 <=giftees<10
and returns the number of donations equal to 8 as an integer
Examples:
Case 1:
Inputs
12
2
Ouput
0
Case 2:
inputs
24
4
Ouput
2
Case 3
Inputs
7
2
Output
0
First of all, I don't quite understand the Case2 of the examples given above, as inputs we have money which is worth 24 and giftees which is equals to 4, after Euclidean division by 8, we get the number of gifts equals to 8 as an integer and 24 divided by 8, we get 3, but why the output is 2 instead of 3.
Did I miss something?
So I went ahead and implement the function as follows:
function luckyMoney(money,giftees){
if (money % 8 ===0){
return (money/8)
}else if(money%4===0){
return 0}
}
In fact I am going in circles and I do not know how to express the different conditions of the functioning part in my code,
Can you give me a hand please?
my attemp
function luckyMoney(money, giftees) {
if (money < 0 || money >= 100) return -1; //incorrect money input
if (giftees < 0 || giftees >= 10) return -2; //incorrect giftees input
if (money >= giftees * 8) return giftees; //spend the entire budget (unless there is enough budget to give everyone 8)
if (money < giftees) return 0; // not enough money
let b = money, g = giftees; // enough budget for giftees left after donating 8 as much as possible
while (b >= 8 + (g - 1) && g > 0) {
b -= 8;
g--;
}
if(g === 1 && b === 4) return 0;
return giftees - g;
}
console.log('inputs: 12 2, result: ', luckyMoney(12,2));
console.log('inputs: 24 4, result: ', luckyMoney(24,4));
console.log('inputs: 7 2, result: ', luckyMoney(7,2));
console.log('inputs: 64 9, result: ', luckyMoney(64,9));
console.log('inputs: 60 8, result: ', luckyMoney(60,8));
Here's a general algorithm you could follow. Hint: you can generalise the steps using a loop.
1. Try to give everyone eight. Does you have enough budget?
Yes: You have found the solution: all giftees get 8
No: Go to step 2
2. Try to give everyone except 1 person 8.
- Do we have enough in the budget? No: Invalid solution, go to step 3
Yes: How much is left over for the 1 person?
Is it 4 or 0?
No: You have found the solution: (giftees - 1)
Yes: Invalid solution, go step 3
3. Try to give everyone except 2 people 8.
- Do we have enough in the budget? No: Invalid solution, go to step 4
Yes: How much is left over for the 2 people?
Is it less than 2 (i.e. enough for 1 each)
No: You have found the solution: (giftees - 2)
Yes: Invalid solution, go to step 4
4. Try to give everyone except 3 people 8.
- Do we have enough in the budget? No: Invalid solution, go to step 5
Yes: How much is left over for the 3 people?
Is it less than 3 (i.e. enough for 1 each)
No: You have found the solution:(giftees - 3)
Yes: Invalid solution, go to step 5
... keep going until you give nobody 8
Some more test cases for you
luckyMoney(64, 8) == 8 e.g. [8,8,8,8,8,8,8,8]
luckyMoney(65, 10) == 7 e.g. [8,8,8,8,8,8,8,7,1,1]
luckyMoney(66, 10) == 8 e.g. [8,8,8,8,8,8,8,8,1,1]
luckyMoney(100, 1) == 1 e.g. [8]
This is a sample of LukyMoney function in C#:
public static int LuckyMoney(int money, int giftees)
{
decimal fortune = 8;
int dist = (int)(money / fortune);
if((giftees - dist) == 1)
return dist - 1;
if(dist > giftees)
return giftees;
return dist;
}
const luckyMoney = (money, giftees) => {
for(let i = 0; i <= giftees; i++){
const moneyleft = money - (giftees-i)*8;
if (i=== 0){
if (moneyleft >= 0){
return giftees-i
}
}
else if(i===1){
if (moneyleft>0 && moneyleft!=4){
return giftees - i
}
}
else{
if (moneyleft>=i){
return giftees -i
}
}
}
}
I think no loop is needed.
In C/ C++ :
size_t lucky_money(size_t money, size_t giftees) {
size_t max_giftees = (money / 8);
if (max_giftees < giftees) {
size_t rest_money = (money % 8);
size_t rest_giftees = (giftees - max_giftees);
// Subtract one giftee if the rest of money is not enough
return (((rest_giftees != 1) || (rest_money != 4))? (max_giftees + ((rest_money < rest_giftees)? -1: 0)): (0 /* dead */));
} else {
return giftees;
}
}
In JavaScript
function lucky_money(money, giftees) {
let max_giftees = Math.floor(money / 8);
if (max_giftees < giftees) {
let rest_money = (money % 8);
let rest_giftees = (giftees - max_giftees);
// Subtract one giftee if the rest of money is not enough
return (((rest_giftees !== 1) || (rest_money !== 4))? (max_giftees + ((rest_money < rest_giftees)? -1: 0)): (0 /* dead */));
} else {
return giftees;
}
}
console.log('inputs: 12 2, result: ', lucky_money( 12, 2)); // 8 + 4 (1 giftee) -> dead, 0
console.log('inputs: 24 4, result: ', lucky_money( 24, 4)); // 2*8 + 8 (2 giftees) -> 2
console.log('inputs: 7 2, result: ', lucky_money( 7, 2)); // 7 (money) < 8 -> 0
console.log('inputs: 64 9, result: ', lucky_money( 64, 9)); // 7*8 + 8 (2 giftees) -> 7
console.log('inputs: 60 8, result: ', lucky_money( 60, 8)); // 7*8 + 4 (1 giftee) -> dead, 0
console.log('inputs: 64 8, result: ', lucky_money( 64, 8)); // 8*8 -> 8
console.log('inputs: 65 10, result: ', lucky_money( 65, 10)); // 7*8 + 9 (3 giftees) -> 7
console.log('inputs: 66 10, result: ', lucky_money( 66, 10)); // 8*8 + 2 (2 giftees) -> 8
console.log('inputs: 100 1, result: ', lucky_money(100, 1)); // 1*8 + 92 (0 giftee) -> 1
60, 8
should be 6 and not 0!
6 * 8 = 48 and the remaining 2 giftee's will get any amount in the remaining 12(6/6)
object Solution extends App {
def f (num: Int, arr: List [Int]): List [List [Int]] =
arr.flatMap (List.fill (num) (_)).combinations (num).toList
def getDons (bd: Int, nf: Int): Int = {
var dist = (8 until budget + 1 by 8).toList
println (dist)
if (dist.length >= nbFils) return nbFils
while (dist.length > 0) {
var restBdTmp = budget - dist.last
println ("rest is : " + restBdTmp)
var restFils = nbFils - dist.length
println ("remaining childs : " + restFils)
var listP = (0 until restBdTmp + 1 by 1).toList
println("choices : " + listP)
println("combinations : "+f (restFils, listP))
var filterF = f (restFils, listP).filter (x =>
x.sum == restBdTmp && !x.contains (4) && !x
.contains (0)) // .filter(i => i.foreach{o => o!=4 && o != 0}
println (filterF)
if (filterF.length != 0) return dist.length
dist = dist.dropRight (1)
}
return 0
}
val budget = 100
val nbFils = 1
println (getDons (budget, nbFils))
}
return $money - $giftees < 7 ? 0 : (($money - $giftees) % 7 === 3 && $giftees - ((int)(($money - $giftees) / 7)) === 1 ? ((int)(($money - $giftees) / 7)) - 1 : min(((int)(($money - $giftees) / 7)), $giftees));
Related
//TASK 5 PART 1
//Request input from user
let x = Number(prompt("Enter a number:"));
// using if...else if
if (x % 7 === 0 &&
x % 11 === 0) {
console.log
(x + " is divisible by 7 and 11");
}
else if (x % 7 === 0 ||
x % 11 === 0) {
console.log
(x + " is divisible by either 7 or 11");
}
else {
console.log
(x + " is divisible by neither 7 or 11");
}
I am very new to JavaScript, and so I am here to ask for help on how to make my code more efficient, using less lines of code, perhaps a method better suited for this program, improve readability or if anybody spots any errors. I am always keen on receiving constructive criticism on where to improve.
Thank you all for your time.
(x % 7 == 0) && (x % 11 == 0) ? "both" : (x % 7 == 0) || (x % 11 == 0) ? "either" : "neither"
Here I have used the nested ternary operator, to do the solution in one line.
The syntax is:
let result = condition ? value1 : value2;
The condition is evaluated: if it’s truthy then value1 is returned, otherwise – value2.
To know more please refer to this article.
In my expierince first get comfortable with the basics first, then look to enhance your knowledge of advanced concept of Javascript.
I'd write it like this.
const x = Number(prompt('Number:'));
const d7 = !(x % 7), d11 = !(x % 11);
const result = (d7 && d11) ? 'both 7 and 11' :
(d7 || d11) ? 'either 7 or 11' :
'neither 7 nor 11';
console.log(`${x} is divisible by ${result}`);
function test3(num) {
value = value * Number(str[i]);
let value = 1;
let str = String(num);
for (let i = 0; i < str.length; i++) {
if (str.length <= 1) {
}
return test3(value);
}
return value;
}
i wanna make single Digits using recursive function.
but, the code's value can't access..
i m searching in google about recursive fuction, it's not good answer..
why cant access 'value' ?
i wanna make
234,
2* 3* 4
2* 4
8
786,
7 * 8 * 6 -> 336
3 * 3 * 6 -> 54
5 * 4 -> 20
2 * 0 -> 0
like that. i want to know why can't access 'value' in the function.
thank you.
You can't access variables form the parent function's scope. If you want to access variables, pass them in as a parameter. Regardless, this is much easier done without strings:
function productOfDigits(num) {
if (num < 10) {
return num;
}
return (num % 10) * productOfDigits(Math.floor(num / 10));
}
// use this one
function repeatedProductOfDigits(num) {
if (num < 10) {
return num;
}
// multiply all the digits then try again
return repeatedProductOfDigits(productOfDigits(num));
}
num % 10 gets the last digit, and Math.floor(num / 10) gets every digit except the last, so productOfDigits(786) == 6 * productOfDigits(78) == 6 * 8 * productOfDigits(7) == 6 * 8 * 7.
It looks like you are trying to calculate the multiplicative digital root -
const multRoot = n =>
n < 10
? n
: multRoot(product(digits(n)))
const digits = n =>
n < 10
? [ n ]
: [ ...digits(Math.floor(n / 10)), n % 10 ]
const product = ns =>
ns.reduce(mult, 1)
const mult = (m, n) =>
m * n
console.log(multRoot(234)) // 8
console.log(multRoot(786)) // 0
To see a variant of this problem, read this Q&A.
I want to check whether a number (7) is divisible by another number (5), If the number is divisible by the number then I need to return the same number. If the number is not divisible by another number I need to make it divisible and return the updated value.
var i =7;
if (i % 5 == 0) {
alert("divisible by 5");
} else {
alert("divisible not by 5");
}
Here if the condition satisfy then I need to return the same value. If the condition is not satisfied I need to add the required number and make it next divisible. (Like 7 is not divisible by 5 so I need add 3 to 7 and return the value 10 which is divisible by 5).
Are there any Math functions exists to implement the same?
What you want, it seems like, is this:
function roundTo(n, d) {
return Math.floor((n + d - 1) / d) * d;
}
For n 10 and d 5, you get 10 back. For n 7 and d 5, you also get 10. What the code does is add one less than the divisor to the input number, and then divides by the divisor. It then gets rid of any fractional part (Math.floor()) and multiplies by the divisor again.
You can do that by using a simple while loop:
function doThat(number, divider) {
while(number % divider !== 0) {
number++;
}
return number;
}
doThat(12, 5); // => returns 15
Here's a fiddle: https://jsfiddle.net/rdko8dmb/
You could use this algorithm:
i % n = r, where i = 7, n = 5, and r = 2.
Then, make i = i + (n - r). i.e. i = 7 + (5-2) → 10. Then you can use this for your division.
Try this
function divisible(dividend, divisor){
if (dividend % divisor == 0) {
return dividend;
} else {
var num = dividend + (divisor-(dividend % divisor));
return num;
}
}
var res = divisible(7, 5);
console.log(res);
Here is the fastest and cleanest way to do that:
function shift(number, divider)
{
return number + (divider - (number % divider)) % divider;
}
It takes number and moves it up by the difference from (our unit) divider to the remainder to make it divisible by the divider. The % divider makes sure that if there is no difference number doesn't get pushed up by a full unit of the divider.
I do not know if this will work for all numbers... But you might try this
7 % 5 = 2. If you subtract 2 from 5 you will get 3... This is the number you need to add to 7. 16 % 5 = 1 subtract 1 from 5 = 4 .. 4 + 16 = 20
Another example 16 % 13 = 3 ... 13-3 = 10 16+10 = 26 26/13 = 2
Here's an example of function that finds next higher natural number that is divisble by y
https://www.jschallenger.com/javascript-basics/find-next-higher-number
Option 1
while (x % y !== 0) x++;
return x;
}
Option 2
if(x % y == 0){
return x;
}
else{
for(i = x+1; i > x; i++){
if(i % y == 0){
return i;
}
}
}
I would like to dynamically generate a string of text based on a current day. So, for example, if it is day 1 then I would like my code to generate = "Its the <dynamic>1*<dynamic string>st</dynamic string>*</dynamic>".
There are 12 days in total so I have done the following:
I've set up a for loop which loops through the 12 days.
In my html I have given my element a unique id with which to target it, see below:
<h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
Then, inside my for loop I have the following code:
$("#dynamicTitle span").html(i);
var day = i;
if (day == 1) {
day = i + "st";
} else if (day == 2) {
day = i + "nd"
} else if (day == 3) {
day = i + "rd"
}
UPDATE
This is the entire for loop as requested:
$(document).ready(function () {
for (i = 1; i <= 12; i++) {
var classy = "";
if (daysTilDate(i + 19) > 0) {
classy = "future";
$("#Day" + i).addClass(classy);
$("#mainHeading").html("");
$("#title").html("");
$("#description").html("");
} else if (daysTilDate(i + 19) < 0) {
classy = "past";
$("#Day" + i).addClass(classy);
$("#title").html("");
$("#description").html("");
$("#mainHeading").html("");
$(".cta").css('display', 'none');
$("#Day" + i + " .prizeLink").attr("href", "" + i + ".html");
} else {
classy = "current";
$("#Day" + i).addClass(classy);
$("#title").html(headings[i - 1]);
$("#description").html(descriptions[i - 1]);
$(".cta").css('display', 'block');
$("#dynamicImage").attr("src", ".." + i + ".jpg");
$("#mainHeading").html("");
$(".claimPrize").attr("href", "" + i + ".html");
$("#dynamicTitle span").html(i);
var day = i;
if (day == 1) {
day = i + "st";
} else if (day == 2) {
day = i + "nd"
} else if (day == 3) {
day = i + "rd"
} else if (day) {
}
}
}
The rules are as follows:
st is used with numbers ending in 1 (e.g. 1st, pronounced first)
nd is used with numbers ending in 2 (e.g. 92nd, pronounced ninety-second)
rd is used with numbers ending in 3 (e.g. 33rd, pronounced thirty-third)
As an exception to the above rules, all the "teen" numbers ending with 11, 12 or 13 use -th (e.g. 11th, pronounced eleventh, 112th,
pronounced one hundred [and] twelfth)
th is used for all other numbers (e.g. 9th, pronounced ninth).
The following JavaScript code (rewritten in Jun '14) accomplishes this:
function ordinal_suffix_of(i) {
var j = i % 10,
k = i % 100;
if (j == 1 && k != 11) {
return i + "st";
}
if (j == 2 && k != 12) {
return i + "nd";
}
if (j == 3 && k != 13) {
return i + "rd";
}
return i + "th";
}
Sample output for numbers between 0-115:
0 0th
1 1st
2 2nd
3 3rd
4 4th
5 5th
6 6th
7 7th
8 8th
9 9th
10 10th
11 11th
12 12th
13 13th
14 14th
15 15th
16 16th
17 17th
18 18th
19 19th
20 20th
21 21st
22 22nd
23 23rd
24 24th
25 25th
26 26th
27 27th
28 28th
29 29th
30 30th
31 31st
32 32nd
33 33rd
34 34th
35 35th
36 36th
37 37th
38 38th
39 39th
40 40th
41 41st
42 42nd
43 43rd
44 44th
45 45th
46 46th
47 47th
48 48th
49 49th
50 50th
51 51st
52 52nd
53 53rd
54 54th
55 55th
56 56th
57 57th
58 58th
59 59th
60 60th
61 61st
62 62nd
63 63rd
64 64th
65 65th
66 66th
67 67th
68 68th
69 69th
70 70th
71 71st
72 72nd
73 73rd
74 74th
75 75th
76 76th
77 77th
78 78th
79 79th
80 80th
81 81st
82 82nd
83 83rd
84 84th
85 85th
86 86th
87 87th
88 88th
89 89th
90 90th
91 91st
92 92nd
93 93rd
94 94th
95 95th
96 96th
97 97th
98 98th
99 99th
100 100th
101 101st
102 102nd
103 103rd
104 104th
105 105th
106 106th
107 107th
108 108th
109 109th
110 110th
111 111th
112 112th
113 113th
114 114th
115 115th
From Shopify
function getNumberWithOrdinal(n) {
var s = ["th", "st", "nd", "rd"],
v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
}
[-4,-1,0,1,2,3,4,10,11,12,13,14,20,21,22,100,101,111].forEach(
n => console.log(n + ' -> ' + getNumberWithOrdinal(n))
);
Minimal one-line approach for ordinal suffixes
function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}
(this is for positive integers, see below for other variations)
Explanation
Start with an array with the suffixes ["st", "nd", "rd"]. We want to map integers ending in 1, 2, 3 (but not ending in 11, 12, 13) to the indexes 0, 1, 2.
Other integers (including those ending in 11, 12, 13) can be mapped to anything else—indexes not found in the array will evaluate to undefined. This is falsy in javascript and with the use of logical or (|| "th") the expression will return "th" for these integers, which is exactly what we want.
The expression ((n + 90) % 100 - 10) % 10 - 1 does the mapping. Breaking it down:
(n + 90) % 100: This expression takes the input integer − 10 mod 100, mapping 10 to 0, ... 99 to 89, 0 to 90, ..., 9 to 99. Now the integers ending in 11, 12, 13 are at the lower end (mapped to 1, 2, 3).
- 10: Now 10 is mapped to −10, 19 to −1, 99 to 79, 0 to 80, ... 9 to 89. The integers ending in 11, 12, 13 are mapped to negative integers (−9, −8, −7).
% 10: Now all integers ending in 1, 2, or 3 are mapped to 1, 2, 3. All other integers are mapped to something else (11, 12, 13 are still mapped to −9, −8, −7).
- 1: Subtracting one gives the final mapping of 1, 2, 3 to 0, 1, 2.
Verifying that it works
function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}
//test integers from 1 to 124
for(var r = [], i = 1; i < 125; i++) r.push(i + nth(i));
//output result
document.getElementById('result').innerHTML = r.join('<br>');
<div id="result"></div>
Variations
Allowing negative integers:
function nth(n){return["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"}
function nth(n){return["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"}
//test integers from 15 to -124
for(var r = [], i = 15; i > -125; i--) r.push(i + nth(i));
//output result
document.getElementById('result').innerHTML = r.join('<br>');
<div id="result"></div>
In ES6 fat arrow syntax (anonymous function):
n=>["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"
Intl.PluralRules, the standard method.
I would just like to drop the canonical way of doing this in here, as nobody seems to know it. Do not reinvent the wheel.
If you want your code to be
self-documenting
easy to localize
with the modern standard
― this is the way to go.
const english_ordinal_rules = new Intl.PluralRules("en", {type: "ordinal"});
const suffixes = {
one: "st",
two: "nd",
few: "rd",
other: "th"
};
function ordinal(number/*: number */) {
const category = english_ordinal_rules.select(number);
const suffix = suffixes[category];
return (number + suffix);
} // -> string
const test = Array(201)
.fill()
.map((_, index) => index - 100)
.map(ordinal)
.join(" ");
console.log(test);
The Intl.PluralRules constructor (Draft ECMA-402)
Unicode’s six plurality categories
Code-golf
While I do not recommend golfing with your code and killing the readability, I came up with one for those golfers (92 bytes):
n=>n+{e:"st",o:"nd",w:"rd",h:"th"}[new Intl.PluralRules("en",{type:"ordinal"}).select(n)[2]]
You can use the moment libraries local data functions.
Code:
moment.localeData().ordinal(1)
//1st
By splitting the number into an array and reversing we can easily check the last 2 digits of the number using array[0] and array[1].
If a number is in the teens array[1] = 1 it requires "th".
function getDaySuffix(num)
{
var array = ("" + num).split("").reverse(); // E.g. 123 = array("3","2","1")
if (array[1] != "1") { // Number is not in the teens
switch (array[0]) {
case "1": return "st";
case "2": return "nd";
case "3": return "rd";
}
}
return "th";
}
You've only got 12 days? I'd be tempted to make it just a simple lookup array:
var suffixes = ['','st','nd','rd','th','th','th','th','th','th','th','th','th'];
then
var i = 2;
var day = i + suffixes[i]; // result: '2nd'
or
var i = 8;
var day = i + suffixes[i]; // result: '8th'
function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}
I wrote this function to solve this problem:
// this is for adding the ordinal suffix, turning 1, 2 and 3 into 1st, 2nd and 3rd
Number.prototype.addSuffix=function(){
var n=this.toString().split('.')[0];
var lastDigits=n.substring(n.length-2);
//add exception just for 11, 12 and 13
if(lastDigits==='11' || lastDigits==='12' || lastDigits==='13'){
return this+'th';
}
switch(n.substring(n.length-1)){
case '1': return this+'st';
case '2': return this+'nd';
case '3': return this+'rd';
default : return this+'th';
}
};
With this you can just put .addSuffix() to any number and it will result in what you want. For example:
var number=1234;
console.log(number.addSuffix());
// console will show: 1234th
An alternative version of the ordinal function could be as follows:
function toCardinal(num) {
var ones = num % 10;
var tens = num % 100;
if (tens < 11 || tens > 13) {
switch (ones) {
case 1:
return num + "st";
case 2:
return num + "nd";
case 3:
return num + "rd";
}
}
return num + "th";
}
The variables are named more explicitly, uses camel case convention, and might be faster.
const getOrdinalNum = (n) => n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
I wrote this simple function the other day. Although for a date you don't need the larger numbers, this will cater for higher values too (1013th, 36021st etc...)
var fGetSuffix = function(nPos){
var sSuffix = "";
switch (nPos % 10){
case 1:
sSuffix = (nPos % 100 === 11) ? "th" : "st";
break;
case 2:
sSuffix = (nPos % 100 === 12) ? "th" : "nd";
break;
case 3:
sSuffix = (nPos % 100 === 13) ? "th" : "rd";
break;
default:
sSuffix = "th";
break;
}
return sSuffix;
};
function ordsfx(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]}
See annotated version at https://gist.github.com/furf/986113#file-annotated-js
Short, sweet, and efficient, just like utility functions should be. Works with any signed/unsigned integer/float. (Even though I can't imagine a need to ordinalize floats)
Strongly recommend the excellent date-fns library. Fast, modular, immutable, works with standard dates.
import * as DateFns from 'date-fns';
const ordinalInt = DateFns.format(someInt, 'do');
See date-fns docs: https://date-fns.org/v2.0.0-alpha.9/docs/format
Here is another option.
function getOrdinalSuffix(day) {
if(/^[2-3]?1$/.test(day)){
return 'st';
} else if(/^[2-3]?2$/.test(day)){
return 'nd';
} else if(/^[2-3]?3$/.test(day)){
return 'rd';
} else {
return 'th';
}
}
console.log(getOrdinalSuffix('1'));
console.log(getOrdinalSuffix('13'));
console.log(getOrdinalSuffix('22'));
console.log(getOrdinalSuffix('33'));
Notice the exception for the teens? Teens are so akward!
Edit: Forgot about 11th and 12th
Old one I made for my stuff...
function convertToOrdinal(number){
if (number !=1){
var numberastext = number.ToString();
var endchar = numberastext.Substring(numberastext.Length - 1);
if (number>9){
var secondfromendchar = numberastext.Substring(numberastext.Length - 1);
secondfromendchar = numberastext.Remove(numberastext.Length - 1);
}
var suffix = "th";
var digit = int.Parse(endchar);
switch (digit){
case 3:
if(secondfromendchar != "1"){
suffix = "rd";
break;
}
case 2:
if(secondfromendchar != "1"){
suffix = "nd";
break;
}
case 1:
if(secondfromendchar != "1"){
suffix = "st";
break;
}
default:
suffix = "th";
break;
}
return number+suffix+" ";
} else {
return;
}
}
I wrote this function for higher numbers and all test cases
function numberToOrdinal(num) {
if (num === 0) {
return '0'
};
let i = num.toString(), j = i.slice(i.length - 2), k = i.slice(i.length - 1);
if (j >= 10 && j <= 20) {
return (i + 'th')
} else if (j > 20 && j < 100) {
if (k == 1) {
return (i + 'st')
} else if (k == 2) {
return (i + 'nd')
} else if (k == 3) {
return (i + 'rd')
} else {
return (i + 'th')
}
} else if (j == 1) {
return (i + 'st')
} else if (j == 2) {
return (i + 'nd')
} else if (j == 3) {
return (i + 'rd')
} else {
return (i + 'th')
}
}
Here's a slightly different approach (I don't think the other answers do this). I'm not sure whether I love it or hate it, but it works!
export function addDaySuffix(day: number) {
const suffixes =
' stndrdthththththththththththththththththstndrdthththththththst';
const startIndex = day * 2;
return `${day}${suffixes.substring(startIndex, startIndex + 2)}`;
}
I would like to quote the answer available in the link
function ordinal(n) {
var s = ["th", "st", "nd", "rd"];
var v = n%100;
return n + (s[(v-20)%10] || s[v] || s[0]);
}
I wanted to provide a functional answer to this question to complement the existing answer:
const ordinalSuffix = ['st', 'nd', 'rd']
const addSuffix = n => n + (ordinalSuffix[(n - 1) % 10] || 'th')
const numberToOrdinal = n => `${n}`.match(/1\d$/) ? n + 'th' : addSuffix(n)
we've created an array of the special values, the important thing to remember is arrays have a zero based index so ordinalSuffix[0] is equal to 'st'.
Our function numberToOrdinal checks if the number ends in a teen number in which case append the number with 'th' as all then numbers ordinals are 'th'. In the event that the number is not a teen we pass the number to addSuffix which adds the number to the ordinal which is determined by if the number minus 1 (because we're using a zero based index) mod 10 has a remainder of 2 or less it's taken from the array, otherwise it's 'th'.
sample output:
numberToOrdinal(1) // 1st
numberToOrdinal(2) // 2nd
numberToOrdinal(3) // 3rd
numberToOrdinal(4) // 4th
numberToOrdinal(5) // 5th
numberToOrdinal(6) // 6th
numberToOrdinal(7) // 7th
numberToOrdinal(8) // 8th
numberToOrdinal(9) // 9th
numberToOrdinal(10) // 10th
numberToOrdinal(11) // 11th
numberToOrdinal(12) // 12th
numberToOrdinal(13) // 13th
numberToOrdinal(14) // 14th
numberToOrdinal(101) // 101st
I strongly recommend this, it is super easy and straightforward to read. I hope it help?
It avoid the use of negative integer i.e number less than 1 and return false
It return 0 if input is 0
function numberToOrdinal(n) {
let result;
if(n < 0){
return false;
}else if(n === 0){
result = "0";
}else if(n > 0){
let nToString = n.toString();
let lastStringIndex = nToString.length-1;
let lastStringElement = nToString[lastStringIndex];
if( lastStringElement == "1" && n % 100 !== 11 ){
result = nToString + "st";
}else if( lastStringElement == "2" && n % 100 !== 12 ){
result = nToString + "nd";
}else if( lastStringElement == "3" && n % 100 !== 13 ){
result = nToString + "rd";
}else{
result = nToString + "th";
}
}
return result;
}
console.log(numberToOrdinal(-111));
console.log(numberToOrdinal(0));
console.log(numberToOrdinal(11));
console.log(numberToOrdinal(15));
console.log(numberToOrdinal(21));
console.log(numberToOrdinal(32));
console.log(numberToOrdinal(43));
console.log(numberToOrdinal(70));
console.log(numberToOrdinal(111));
console.log(numberToOrdinal(300));
console.log(numberToOrdinal(101));
OUTPUT
false
0
11th
15th
21st
32nd
43rd
70th
111th
300th
101st
This is for one liners and lovers of es6
let i= new Date().getDate
// I can be any number, for future sake we'll use 9
const j = I % 10;
const k = I % 100;
i = `${i}${j === 1 && k !== 11 ? 'st' : j === 2 && k !== 12 ? 'nd' : j === 3 && k !== 13 ? 'rd' : 'th'}`}
console.log(i) //9th
Another option for +be number would be:
console.log(["st","nd","rd"][((i+90)%100-10)%10-1]||"th"]
Also to get rid of the ordinal prefix just use these:
console.log(i.parseInt("8th"))
console.log(i.parseFloat("8th"))
feel free to modify to suit you need
<p>31<sup>st</sup> March 2015</p>
You can use
1<sup>st</sup>
2<sup>nd</sup>
3<sup>rd</sup>
4<sup>th</sup>
for positioning the suffix
I am trying to implement simple validation of credit card numbers. I read about the Luhn algorithm on Wikipedia:
Counting from the check digit, which is the rightmost, and moving
left, double the value of every second digit.
Sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5)
together with the undoubled digits from the original number.
If the total modulo 10 is equal to 0 (if the total ends in zero)
then the number is valid according to the Luhn formula; else it is
not valid.
On Wikipedia, the description of the Luhn algorithm is very easily understood. However, I have also seen other implementations of the Luhn algorithm on Rosetta Code and elsewhere (archived).
Those implementations work very well, but I am confused about why they can use an array to do the work. The array they use seems to have no relation with Luhn algorithm, and I can't see how they achieve the steps described on Wikipedia.
Why are they using arrays? What is the significance of them, and how are they used to implement the algorithm as described by Wikipedia?
Unfortunately none of the codes above worked for me. But I found on GitHub a working solution
// takes the form field value and returns true on valid number
function valid_credit_card(value) {
// accept only digits, dashes or spaces
if (/[^0-9-\s]+/.test(value)) return false;
// The Luhn Algorithm. It's so pretty.
var nCheck = 0, nDigit = 0, bEven = false;
value = value.replace(/\D/g, "");
for (var n = value.length - 1; n >= 0; n--) {
var cDigit = value.charAt(n),
nDigit = parseInt(cDigit, 10);
if (bEven) {
if ((nDigit *= 2) > 9) nDigit -= 9;
}
nCheck += nDigit;
bEven = !bEven;
}
return (nCheck % 10) == 0;
}
the array [0,1,2,3,4,-4,-3,-2,-1,0] is used as a look up array for finding the difference between a number in 0-9 and the digit sum of 2 times its value. For example, for number 8, the difference between 8 and (2*8) = 16 -> 1+6 = 7 is 7-8 = -1.
Here is graphical presentation, where {n} stand for sum of digit of n
[{0*2}-0, {1*2}-1, {2*2}-2, {3*2}-3, {4*2}-4, {5*2}-5, {6*2}-6, {7*2}-7....]
| | | | | | | |
[ 0 , 1 , 2 , 3 , 4 , -4 , -3 , -2 ....]
The algorithm you listed just sum over all the digit and for each even spot digit, look up the the difference using the array, and apply it to the total sum.
Compact Luhn validator:
var luhn_validate = function(imei){
return !/^\d+$/.test(imei) || (imei.split('').reduce(function(sum, d, n){
return sum + parseInt(((n + imei.length) %2)? d: [0,2,4,6,8,1,3,5,7,9][d]);
}, 0)) % 10 == 0;
};
Works fine for both CC and IMEI numbers. Fiddle: http://jsfiddle.net/8VqpN/
Lookup tables or arrays can simplify algorithm implementations - save many lines of code - and with that increase performance... if the calculation of the lookup index is simple - or simpler - and the array's memory footprint is affordable.
On the other hand, understanding how the particular lookup array or data structure came to be can at times be quite difficult, because the related algorithm implementation may look - at first sight - quite different from the original algorithm specification or description.
Indication to use lookup tables are number oriented algorithms with simple arithmetics, simple comparisons, and equally structured repetition patterns - and of course - of quite finite value sets.
The many answers in this thread go for different lookup tables and with that for different algorithms to implement the very same Luhn algorithm. Most implementations use the lookup array to avoid the cumbersome figuring out of the value for doubled digits:
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
//
// ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
// | | | | | | | | | |
//
// - d-igit=index: 0 1 2 3 4 5 6 7 8 9
// - 1st
// calculation: 2*0 2*2 2*2 2*3 2*4 2*5 2*6 2*7 2*8 2*9
// - intermeduate
// value: = 0 = 2 = 4 = 6 = 8 =10 =12 =14 =16 =18
// - 2nd
// calculation: 1+0 1+2 1+4 1+6 1+8
//
// - final value: 0 2 4 6 8 =1 =3 =5 =7 =9
//
var luhnFinalValue = luhnArray[d]; // d is numeric value of digit to double
An equal implementation for getting the luhnFinalValue looks like this:
var luhnIntermediateValue = d * 2; // d is numeric value of digit to double
var luhnFinalValue = (luhnIntermediateValue < 10)
? luhnIntermediateValue // (d ) * 2;
: luhnIntermediateValue - 10 + 1; // (d - 5) * 2 + 1;
Which - with the comments in above true and false terms - is of course simplified:
var luhnFinalValue = (d < 5) ? d : (d - 5) * 2 + 1;
Now I'm not sure if I 'saved' anything at all... ;-) especially thanks the value-formed or short form of if-then-else. Without it, the code may look like this - with 'orderly' blocks
and embedded in the next higher context layer of the algorithm and therefore luhnValue:
var luhnValue; // card number is valid when luhn values for each digit modulo 10 is 0
if (even) { // even as n-th digit from the the end of the string of digits
luhnValue = d;
} else { // doubled digits
if (d < 5) {
luhnValue = d * 2;
} else {
lunnValue = (d - 5) * 2 + 1;
}
}
Or:
var luhnValue = (even) ? d : (d < 5) ? d * 2 : (d - 5) * 2 + 1;
Btw, with modern, optimizing interpreters and (just in time) compilers, the difference is only in the source code and matters only for readability.
Having come that far with explanation - and 'justification' - of the use of lookup tables and comparison to straight forward coding, the lookup table looks now a bit overkill to me. The algorithm without is now quite easy to finish - and it looks pretty compact too:
function luhnValid(cardNo) { // cardNo as a string w/ digits only
var sum = 0, even = false;
cardNo.split("").reverse().forEach(function(dstr){ d = parseInt(dstr);
sum += ((even = !even) ? d : (d < 5) ? d * 2 : (d - 5) * 2 + 1);
});
return (sum % 10 == 0);
}
What strikes me after going through the explanation exercise is that the initially most enticing implementation - the one using reduce() from #kalypto - just lost totally its luster for me... not only because it is faulty on several levels, but more so because it shows that bells and whistles may not always 'ring the victory bell'. But thank you, #kalypto, it made me actually use - and understand - reduce():
function luhnValid2(cardNo) { // cardNo as a string w/ digits only
var d = 0, e = false; // e = even = n-th digit counted from the end
return ( cardNo.split("").reverse().reduce(
function(s,dstr){ d = parseInt(dstr); // reduce arg-0 - callback fnc
return (s + ((e = !e) ? d : [0,2,4,6,8,1,3,5,7,9][d]));
} // /end of callback fnc
,0 // reduce arg-1 - prev value for first iteration (sum)
) % 10 == 0
);
}
To be true to this thread, some more lookup table options have to be mentioned:
how about just adjust varues for doubled digits - as posted by #yngum
how about just everything with lookup tables - as posted by #Simon_Weaver - where also the values for the non-doubled digits are taken from a look up table.
how about just everything with just ONE lookup table - as inspired by the use of an offset as done in the extensively discussed luhnValid() function.
The code for the latter - using reduce - may look like this:
function luhnValid3(cardNo) { // cardNo as a string w/ digits only
var d = 0, e = false; // e = even = n-th digit counted from the end
return ( cardNo.split("").reverse().reduce(
function(s,dstr){ d = parseInt(dstr);
return (s + [0,1,2,3,4,5,6,7,8,9,0,2,4,6,8,1,3,5,7,9][d+((e=!e)?0:10)]);
}
,0
) % 10 == 0
);
}
And for closing lunValid4() - very compact - and using just 'old fashioned' (compatible) JavaScript - with one single lookup table:
function luhnValid4(cardNo) { // cardNo as a string w/ digits only
var s = 0, e = false, p = cardNo.length; while (p > 0) { p--;
s += "01234567890246813579".charAt(cardNo.charAt(p)*1 + ((e=!e)?0:10)) * 1; }
return (s % 10 == 0);
}
Corollar: Strings can be looked at as lookup tables of characters... ;-)
A perfect example of a nice lookup table application is the counting of set bits in bits lists - bits set in a a (very) long 8-bit byte string in (an interpreted) high-level language (where any bit operations are quite expensive). The lookup table has 256 entries. Each entry contains the number of bits set in an unsigned 8-bit integer equal to the index of the entry. Iterating through the string and taking the unsigned 8-bit byte equal value to access the number of bits for that byte from the lookup table. Even for low-level language - such as assembler / machine code - the lookup table is the way to go... especially in an environment, where the microcode (instruction) can handle multiple bytes up to 256 or more in an (single CISC) instruction.
Some notes:
numberString * 1 and parseInt(numberStr) do about the same.
there are some superfluous indentations, parenthesis,etc... supporting my brain in getting the semantics quicker... but some that I wanted to leave out, are actually required... when
it comes to arithmetic operations with short-form, value-if-then-else expressions as terms.
some formatting may look new to you; for examples, I use the continuation comma with the
continuation on the same line as the continuation, and I 'close' things - half a tab - indented to the 'opening' item.
All formatting is all done for the human, not the computer... 'it' does care less.
algorithm datastructure luhn lookuptable creditcard validation bitlist
A very fast and elegant implementation of the Luhn algorithm following:
const isLuhnValid = function luhn(array) {
return function (number) {
let len = number ? number.length : 0,
bit = 1,
sum = 0;
while (len--) {
sum += !(bit ^= 1) ? parseInt(number[len], 10) : array[number[len]];
}
return sum % 10 === 0 && sum > 0;
};
}([0, 2, 4, 6, 8, 1, 3, 5, 7, 9]);
console.log(isLuhnValid("4112344112344113".split(""))); // true
console.log(isLuhnValid("4112344112344114".split(""))); // false
On my dedicated git repository you can grab it and retrieve more info (like benchmarks link and full unit tests for ~50 browsers and some node.js versions).
Or you can simply install it via bower or npm. It works both on browsers and/or node.
bower install luhn-alg
npm install luhn-alg
If you want to calculate the checksum, this code from this page is very concise and in my random tests seems to work.
NOTE: the verification algorithmns on this page do NOT all work.
// Javascript
String.prototype.luhnGet = function()
{
var luhnArr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]], sum = 0;
this.replace(/\D+/g,"").replace(/[\d]/g, function(c, p, o){
sum += luhnArr[ (o.length-p)&1 ][ parseInt(c,10) ]
});
return this + ((10 - sum%10)%10);
};
alert("54511187504546384725".luhnGet());
Here's my findings for C#
function luhnCheck(value) {
return 0 === (value.replace(/\D/g, '').split('').reverse().map(function(d, i) {
return +['0123456789','0246813579'][i % 2][+d];
}).reduce(function(p, n) {
return p + n;
}) % 10);
}
Update: Here's a smaller version w/o string constants:
function luhnCheck(value) {
return !(value.replace(/\D/g, '').split('').reverse().reduce(function(a, d, i) {
return a + d * (i % 2 ? 2.2 : 1) | 0;
}, 0) % 10);
}
note the use of 2.2 here is to make doubling d roll over with an extra 1 when doubling 5 to 9.
Code is the following:
var LuhnCheck = (function()
{
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
return function(str)
{
var counter = 0;
var incNum;
var odd = false;
var temp = String(str).replace(/[^\d]/g, "");
if ( temp.length == 0)
return false;
for (var i = temp.length-1; i >= 0; --i)
{
incNum = parseInt(temp.charAt(i), 10);
counter += (odd = !odd)? incNum : luhnArr[incNum];
}
return (counter%10 == 0);
}
})();
The variable counter is the sum of all the digit in odd positions, plus the double of the digits in even positions, when the double exceeds 10 we add the two numbers that make it (ex: 6 * 2 -> 12 -> 1 + 2 = 3)
The Array you are asking about is the result of all the possible doubles
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
0 * 2 = 0 --> 0
1 * 2 = 2 --> 2
2 * 2 = 4 --> 4
3 * 2 = 6 --> 6
4 * 2 = 8 --> 8
5 * 2 = 10 --> 1+0 --> 1
6 * 2 = 12 --> 1+2 --> 3
7 * 2 = 14 --> 1+4 --> 5
8 * 2 = 16 --> 1+6 --> 7
9 * 2 = 18 --> 1+8 --> 9
So for example
luhnArr[3] --> 6 (6 is in 3rd position of the array, and also 3 * 2 = 6)
luhnArr[7] --> 5 (5 is in 7th position of the array, and also 7 * 2 = 14 -> 5 )
Another alternative:
function luhn(digits) {
return /^\d+$/.test(digits) && !(digits.split("").reverse().map(function(checkDigit, i) {
checkDigit = parseInt(checkDigit, 10);
return i % 2 == 0
? checkDigit
: (checkDigit *= 2) > 9 ? checkDigit - 9 : checkDigit;
}).reduce(function(previousValue, currentValue) {
return previousValue + currentValue;
}) % 10);
}
Alternative ;) Simple and Best
<script>
// takes the form field value and returns true on valid number
function valid_credit_card(value) {
// accept only digits, dashes or spaces
if (/[^0-9-\s]+/.test(value)) return false;
// The Luhn Algorithm. It's so pretty.
var nCheck = 0, nDigit = 0, bEven = false;
value = value.replace(/\D/g, "");
for (var n = value.length - 1; n >= 0; n--) {
var cDigit = value.charAt(n),
nDigit = parseInt(cDigit, 10);
if (bEven) {
if ((nDigit *= 2) > 9) nDigit -= 9;
}
nCheck += nDigit;
bEven = !bEven;
}
return (nCheck % 10) == 0;
}
console.log(valid_credit_card("5610591081018250"),"valid_credit_card Validation");
</script>
Best Solution here
http://plnkr.co/edit/34aR8NUpaKRCYpgnfUbK?p=preview
with all test cases passed according to
http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
and the credit goes to
https://gist.github.com/DiegoSalazar/4075533
const LuhnCheckCard = (number) => {
if (/[^0-9-\s]+/.test(number) || number.length === 0)
return false;
return ((number.split("").map(Number).reduce((prev, digit, i) => {
(!(( i & 1 ) ^ number.length)) && (digit *= 2);
(digit > 9) && (digit -= 9);
return prev + digit;
}, 0) % 10) === 0);
}
console.log(LuhnCheckCard("4532015112830366")); // true
console.log(LuhnCheckCard("gdsgdsgdsg")); // false
I worked out the following solution after I submitted a much worse one for a test..
function valid(number){
var splitNumber = parseInt(number.toString().split(""));
var totalEvenValue = 0;
var totalOddValue = 0;
for(var i = 0; i < splitNumber.length; i++){
if(i % 2 === 0){
if(splitNumber[i] * 2 >= 10){
totalEvenValue += splitNumber[i] * 2 - 9;
} else {
totalEvenValue += splitNumber[i] * 2;
}
}else {
totalOddValue += splitNumber[i];
}
}
return ((totalEvenValue + totalOddValue) %10 === 0)
}
console.log(valid(41111111111111111));
I recently wrote a solution using Javascript, I leave the code here for anyone who can help:
// checksum with Luhn Algorithm
const luhn_checksum = function(strIn) {
const len = strIn.length;
let sum = 0
for (let i = 0; i<10; i += 1) {
let factor = (i % 2 === 1) ? 2: 1
const v = parseInt(strIn.charAt(i), 10) * factor
sum += (v>9) ? (1 + v % 10) : v
}
return (sum * 9) % 10
}
// teste exampple on wikipedia:
// https://en.wikipedia.org/wiki/Luhn_algorithm
const strIn = "7992739871"
// The checksum of "7992739871" is 3
console.log(luhn_checksum(strIn))
If you understand this code above, you will have no problem converting it to any other language.
For example in python:
def nss_checksum(nss):
suma = 0
for i in range(10):
factor = 2 if (i % 2 == 1) else 1
v = int(nss[i]) * factor
suma += (1 + v % 10) if (v >9) else v
return (suma * 9) % 10
For more info, check this:
https://en.wikipedia.org/wiki/Luhn_algorithm
My Code(En español):
https://gist.github.com/fitorec/82a3e27fae3bab709a07c19c71c3a8d4
def validate_credit_card_number(card_number):
if(len(str(card_number))==16):
group1 = []
group1_double = []
after_group_double = []
group1_sum = 0
group2_sum = 0
group2 = []
total_final_sum = 0
s = str(card_number)
list1 = [int(i) for i in list(s)]
for i in range(14, -1, -2):
group1.append(list1[i])
for x in group1:
b = 0
b = x * 2
group1_double.append(b)
for j in group1_double:
if(j > 9):
sum_of_digits = 0
alias = str(j)
temp1 = alias[0]
temp2 = alias[1]
sum_of_digits = int(temp1) + int(temp2)
after_group_double.append(sum_of_digits)
else:
after_group_double.append(j)
for i in after_group_double:
group1_sum += i
for i in range(15, -1, -2):
group2.append(list1[i])
for i in group2:
group2_sum += i
total_final_sum = group1_sum + group2_sum
if(total_final_sum%10==0):
return True
else:
return False
card_number= 1456734512345698 #4539869650133101 #1456734512345698 # #5239512608615007
result=validate_credit_card_number(card_number)
if(result):
print("credit card number is valid")
else:
print("credit card number is invalid")