Problem Set 11: Luhn algorithm – Validate credit card numbers

When you start a new problem set, your first instinct might be to open your computer and begin typing code right away. While this can feel productive, it often leads to frustration when things don't work as expected. Instead, take a few minutes to slow down and plan.

Here are some helpful strategies:

  1. Understand the problem clearly
    • Read the instructions carefully — twice if needed.
    • Ask yourself: What exactly is being asked?
  2. Break the problem into smaller steps
    • Think about the smallest possible actions the computer will need to perform.
    • For example: If the task is to find the first recurring letter in a word, what steps must happen first?
  3. Try solving it on paper first
    • Write out your steps in plain language (pseudocode).
    • Test your steps with a simple example before touching the keyboard.
  4. Translate your steps into code
    • Start small — write only a few lines at a time and test often.
    • Don't worry about perfection at first; get a working version, then improve it.
  5. Check your solution
    • Run it with different examples, including edge cases.
    • Ask: Does this solve the problem in all situations?

  • Read the question carefully (twice).
  • Break the task into the smallest steps.
  • Sketch or write pseudocode before coding.
  • Start small — test as you go.
  • Check your solution with different cases.

Problem Description

Payment card numbers are designed so that simple mistakes (like a mistyped digit) can be detected automatically.
The Luhn algorithm is a checksum method used to validate many card numbers (credit/debit).
Your job is to write a program that checks whether a given number passes the Luhn check.

Important: For this exercise, do not use real card numbers. Use the test numbers provided below or make up your own.

 

Learning Goals

By completing this problem, you should be able to:

  • Work with strings and digits safely (handle spaces and dashes).
  • Use loops, indexing from the right, and conditional logic.
  • Implement a checksum (sum with doubling every second digit from the right).
  • Design and run test cases to confirm correctness.

 

How the Luhn Algorithm Works

The goal: Detect common typing errors in numbers like credit cards.
Instead of storing every number in a database, the algorithm uses a mathematical checksum: a quick calculation on the digits that tells us if the number is “mathematically consistent.”


Step 1: Start with the digits

Example number:

4539 1488 0343 6467

First, remove spaces/dashes:

4539148803436467

Step 2: Work from right to left

We start at the rightmost digit (this is the “check digit”).

  • The check digit is the one we’ll use at the end to see if the number passes or fails.

So for 4539148803436467, the rightmost digit is 7.


Step 3: Double every second digit (from the right)

Starting from the second-to-last digit, double every second digit.

Example:

4 5 3 9 1 4 8 8 0 3 4 3 6 4 6 7

Double the highlighted ones:

4 (5→10) 3 (9→18) 1 (4→8) 8 (8→16) 0 (3→6) 4 (3→6) 6 (4→8) 6 (7 stays)

Step 4: Subtract 9 if the doubled number is 10 or more

Why? Because doubling a digit can only give 0–18.

  • If it’s < 10, we keep it.
  • If it’s ≥ 10, the sum of its digits is the same as subtracting 9.

Examples:

  • 10 → 1+0 = 1 (or 10–9 = 1)
  • 18 → 1+8 = 9 (or 18–9 = 9)

This keeps every result as a single digit (0–9).


Step 5: Add up all the digits

Now add all the digits (original ones + modified doubles).

If the total sum is divisible by 10, the number is valid.
If not, it’s invalid.


Step 6: Why it works

  • The algorithm is designed so that a single mistake (e.g., typing 5 instead of 6) will almost always break the checksum.
  • It also catches many digit swaps (e.g., typing 46 instead of 64).
  • It’s not encryption or security — just a smart error-detection method.

Worked Example

Number: 79927398713

Digits: 7 9 9 2 7 3 9 8 7 1 3

Double every second digit from the right:

3 (1→2) 7 (8→16→7) 9 (3→6) 7 (2→4) 9 (9→18→9) 7

Final sequence:

7, 9, 9, 4, 7, 6, 9, 7, 7, 2, 3

Sum:
7+9+9+4+7+6+9+7+7+2+3 = 60

60 is divisible by 10 → Valid.

 

In plain words:

  • Walk backward through the number.
  • Double every other digit.
  • If it’s 10 or more, subtract 9.
  • Add everything.
  • If the total ends in 0, the number is valid.

 

Tasks

Task 1: Input Cleaning

Write a small function (or code block) that:

  • Takes a string (e.g., "4539 1488 0343 6467" or "4539-1488-0343-6467"),
  • Returns only the digits (e.g., "4539148803436467"),
  • Returns an error/False if any non-digit characters remain after removing spaces/dashes.

Task 2: Implement Luhn Check (Core)

Write a function is_valid_luhn(number_str) that:

  • Assumes number_str contains digits only,
  • Applies steps 2–5 of the algorithm,
  • Returns True if valid, False if not.

Task 3: User Flow

Write a program that:

  • Asks the user to enter a card number (string),
  • Cleans it (Task 1),
  • If clean fails, print "Invalid input",
  • Otherwise, run the Luhn check and print either:
    • "Valid (passes Luhn)." or
    • "Invalid (does not pass Luhn).".

Task 4: Edge Cases

Ensure your program handles:

  • Very short inputs (e.g., length < 2 → invalid),
  • Inputs with only spaces/dashes,
  • Inputs with leading zeros,
  • Mixed separators (spaces and dashes).

Worked Example (By Hand)

Validate 79927398713:

Digits from right (mark every second to double):
7 9 9 2 7 3 9 8 7 1 3
Rightmost index starts at 1 → double indices 2, 4, 6, …

  • Original (right→left indices):
    3(1), 1(2*), 7(3), 8(4*), 9(5), 3(6*), 7(7), 2(8*), 9(9), 9(10*), 7(11)
  • Double the starred ones, subtract 9 if ≥10:
    3, 2, 7, 16→7, 9, 6, 7, 4, 9, 18→9, 7
  • Sum: 3+2+7+7+9+6+7+4+9+9+7 = 60
  • 60 mod 10 = 0 → Valid.

Test Cases

Use these (all are common test numbers for validation practice):

Valid (should be True):

  • 79927398713
  • 4539 1488 0343 6467 (Visa)
  • 4111 1111 1111 1111 (Visa test)
  • 5555 5555 5555 4444 (Mastercard test)
  • 378282246310005 (AmEx test)

Invalid (should be False):

  • 79927398710 (last digit changed)
  • 4539 1488 0343 6468 (last digit changed)
  • 1234 5678 9012 3456
  • 4111-1111-1111-1112 (last digit changed)
  • abcd-efgh (non-digits after cleaning → invalid input)

Record your program’s output for each case.

 

Extension Challenges (Optional)

  • Check digit generator: Given all but the last digit, compute the correct Luhn check digit to make the number valid.
  • Card type hint: After a valid Luhn, print a simple type guess by prefix/length (e.g., starts with 4 → “looks like Visa” if length is 13/16/19; 34/37 and length 15 → “looks like AmEx”).
  • Batch validation: Accept a comma-separated list and report validity for each.
  • Simple unit tests: Write small assertions for your test cases.

 

Success Criteria

  • You can explain why doubling every second digit and subtracting 9 works (sum of digits of 10–18).
  • Your program cleans input safely and rejects malformed input.
  • Your implementation matches the provided test cases.
  • (Extension) You can compute a check digit and/or validate batches