Related
I'm just starting out with JS and stuck on a question which is print integers 1-20 using a while loop. Print only five integers per line.
Any help would be great!
I tried a few things, here's the latest:
var x=" ";
var i=1;
while (i<=20; i++) {
x=i%5=0; "\n"
}
alert(x);
For very basic JavaScript like this, it would probably help to use a console rather than write code for a web page. Ideally, you'd write a bunch of programs using console.log(), and then you'd write a bunch of programs that manipulate and generate DOM elements, and you'll entirely skip the awkward stage of alert() and document.write(). Eloquent JavaScript is a book that I followed in precisely this way.
In any case, here are three loops that do about what you describe. The first is very similar to your attempt. The other two output lines of output at a time, but differ considerably in their looping logic.
console.log('\nloop one')
;(function() {
var x = '',
i = 1
while (i <= 20) {
x += i
x += i%5 ? ' ' : '\n'
i++
}
console.log(x)
})()
console.log('\nloop two')
;(function() {
var line = ''
for (var i = 1; i <= 20; i++) {
line += i + ' '
if (i % 5 === 0) {
console.log(line)
line = ''
}
}
})()
console.log('\nloop three')
;(function() {
for (var i = 1, line = ''; i <= 20; line = '') {
for (var j = 0; j < 5; j++)
line += i++ + ' '
console.log(line)
}
})()
node example, with the above all in a file named 'example', produces this output:
loop one
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
loop two
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
loop three
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
You need some syntax and logic changes, like below:
var i=1;
while (i<=20){
var x=i%5; // checks for 5 numbers in a line
if(x==0)
document.write(i+",<br>"); // give a break if 5 numbers on line
else
document.write(i+",");
i++;
};
Try using an array to store values of i , Array.prototype.splice()
var x = []
, i = 1
, len = 5
, max = 20;
while (i <= max) {
x.push(i++); --len;
if (len === 0 && x[x.length - 1] !== max) {
x.splice(x.length, 0, "\n");
len = 5
}
}
console.log(x);
alert(x.join(" "));
that's my version over here:
http://jsbin.com/pamaledopi/1/edit?js,console
Don't forget to turn F12 on! (Be sure you have console opened and click "Run")
_padEmpty is for formatting purposes, you can drop it and call to it too.
I am trying to write a function that returns the PrimeNumber. for testing purposes i am just doing a console.log for stages of this function, to try and understand it better.
so this line(line:18) in my total function will just return i; as opposed to do a console.log
So Basically, 30 will be passed to the function and the function will return every prime number <=30.
It is based on this from wiki:
This routine consists of dividing n by each integer m that is greater than 1
and less than or equal to the square root of n.
If the result of any of these divisions is an integer,
then n is not a prime, otherwise it is a prime.
(Question here: 25/Math.sqrt(25) = 0, therefore NotPrime
BUT 25/2=12.5, 25/3=8.3333 25/4=6.25 => IsPrime as 12.5 is not an integer Or am I mising something here???)
there is also the problem of duplication: 13 is printed twice because 13/2 and 13/3 is executed. Question here: I would like to fix this duplication also?
function isInt(n) {
return n % 1 === 0;
}
var test = 25
console.log(Math.sqrt(test));
function prime(n) {
for(var i = 1; i <= n; i++)
{ if(i%2 !==0 && i%3 !==0){ // if i/2 does not have a remainder it might be a prime so go to next line else jump
to next number and i%3 the same
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++){
console.log(i + "/" + j); //print j//it prints 9 twice and 10 twice
console.log("==" + i/j); //because the sqrt of 9 = 3 =>
for j= 2 and j=3
if(isInt(i/j)) {}
else{console.log("----" + i + "is Prime");}
}
}
}
};
prime(test);
Another example here using aslightly different method: but again I have the same problem as the above 25 and duplication
var test = 25
console.log(Math.sqrt(test));
for(var i = 1; i <= test; i++)
{ if(i%2 !==0 && i%3 !==0){ // if i/2 does not have a remainder it might be a prime so go to next line else jump to next number and i%3 the same
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++){
console.log(i + "%" + j); //print j//it prints 9 twice and 10 twice
console.log("==" + i%j); //because the sqrt of 9 = 3 => for j= 2 and j=3
if(i%j !==0) {
console.log("----" + i + "is Prime");
}
}
}
}
[EDIT]Thank you all very much for pointing out my flaws/mistakes
here is my working example. Thank you all again!!
function isInt(n) {
return n % 1 === 0;
}
var test = 100
console.log(Math.sqrt(test));
function prime(n) {
for (var i = 1; i <= n; i++) {
var a = Math.floor(Math.sqrt(i));
var bool = true;
for(j = 2; j<=a; j++) {
if(!isInt(i/j)) {
//console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");
} else {bool = false;}
}
if(bool) {console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");}
}
}
prime(test);
25/Math.sqrt(25) = 0, therefore NotPrime
BUT 25/2=12.5, 25/3=8.3333 25/4=6.25 => IsPrime
No. Only because it neither is divisible by 2, 3, and 4, it does not mean that 25 is a prime number. It must be divisible by nothing (except 1 and itself) - but 25 is divisible by 5 as you noticed. You will have to check against that as well.
13 is printed twice because 13/2 and 13/3 is executed.
Question here: I would like to fix this duplication also?
Your logic is flawed. As above, just because a number is not divisible by an other number that does not mean it was prime - but your code prints results based on that condition. Instead, is has to be not divisible by all other numbers.
You just have an extra condition that nothing that is divisible by 2 or 3 enters the loop, but everything that is divisible by 5, 7, 11 etc (and not divisible by 2 or 3) is yielded. 25 is just the first number to occur in that series, the next ones will be 35 and 49.
Actually you're already testing 2 and 3 in the loop from 2 to a already, so you should just omit that condition. You would've noticed your actual problem much faster then if you had tried:
function prime(n) {
for (var i = 1; i <= n; i++) {
var a = Math.floor(Math.sqrt(i));
for(j = 2; j<=a; j++) {
if(!isInt(i/j)) {
console.log(i+"/"+j+"=="+i/j+", therefore "+i+" is Prime");
}
}
}
}
prime(25);
The logic should be: Test all divisors from 2 to sqrt(i), and if i is divisible by any of them you know that it's not a prime. Only if it has passed the loop with none of them being a factor of i, you know in the end that it's a prime. I'll leave that as an exercise to you :-)
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")
I am slightly stuck on the javascript logic to accomplish this.
Basically
If I give a number (say 30)
I want to show 5 either side.
so
25 26 27 28 29 30 31 32 33 34 35
That part is easy.
But then I need to handle cases where the number is below 5 (say 3).
What I want to to is,
for every number not shown on the right,
add it to the left
so
1 2 3 4 5 6 7 8 9 10 11
But then I need to handle cases where the number is above a (maximum-5) (say maximum = 100, number = 98).
What I want to to is,
for every number not shown on the left,
add it to the right
so
90 91 92 93 94 95 96 97 98 99 100
But then I need to handle cases where the maximum is below 10 (say number = 3, maximum = 8
What I want to to is,
only show the applicable range
so
1 2 3 4 5 6 7 8
But I am not sure on the logic
function ranger(num) {
//Establish limits and pre/post array storage
var low = 0, high = 100, howMany = 5;
var pre = [];
var post = [];
//Increment/decrement if appropriate
for(x=1;x<=howMany;x++) {
if((num-x) > low) { pre.push(num-x); }
if((num+x) < high) { post.push(num+x); }
}
pre.reverse();
alert("Before: "+pre+'\nNumber: '+num+'\nAfter: '+post)
}
ranger(7);
ranger(2);
ranger(96);
Tested for all your cases:
range = 5;
maximum = 8;
number = 3;
left = right = number;
while(right - left < range*2 ) {
if (right + 1 <= maximum) {
right++;
}
if (left - 1 > 0 ) {
left--;
}
if (right == maximum && left == 1) {
break;
}
}
for(i=left;i<=right;i++) {
console.log(i);
}
One possible solution:
function getPages(fromPageNumber) {
var result = [];
fromPageNumber= Math.min(94, Math.max(6, fromPageNumber));
for(var i = -5; i <=5; i++)
result.push(fromPageNumber + i);
return result;
}
// Set up your limits and bounds
var radius = 5.
middleNumber = 20,
lowerBound = 1,
upperBound = 100;
// For the defined (and available range) create an array of valid numbers
var results = [];
for (int i = Math.max(middleNumber - radius, lowerBound);
i <= Math.min(middleNumber + radius, upperBound);
i++) {
results.push(i);
}
// Print out the resulting numbers with spaces in between
console.log(results.join(' '));
function getSequence(num, length)
{
var min = 0;
var max=100;
Array result;
for(int i=num-(length/2); i<num+(length/2);i++)
{
if(i>min && i< max)
result.add(i);
}
return result;
}