From d58f0416f3a5c6eab11a34771b67818bf8585147 Mon Sep 17 00:00:00 2001 From: hectordacb Date: Sat, 4 Jan 2025 19:12:41 -0400 Subject: [PATCH 1/3] Add solutions and tests for challenge_16 --- solutions/challenge_16/README.MD | 46 +++++++++++++++++ solutions/challenge_16/__init__.py | 0 .../challenge_16/hide_credit_card_number.py | 46 +++++++++++++++++ solutions/tests/challenge_16/__init__.py | 0 .../test_hide_credit_card_number.py | 50 +++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 solutions/challenge_16/README.MD create mode 100644 solutions/challenge_16/__init__.py create mode 100644 solutions/challenge_16/hide_credit_card_number.py create mode 100644 solutions/tests/challenge_16/__init__.py create mode 100644 solutions/tests/challenge_16/test_hide_credit_card_number.py diff --git a/solutions/challenge_16/README.MD b/solutions/challenge_16/README.MD new file mode 100644 index 000000000..7620fcd3b --- /dev/null +++ b/solutions/challenge_16/README.MD @@ -0,0 +1,46 @@ +# **Challenge: Hide a Credit Card Number** + +**Description** + +The "Hide a Credit Card Number" challenge involves writing a function to mask all but the last four digits of a credit card number. This is useful for displaying sensitive information in a secure manner. The masked digits should be replaced with the `*` character. + +Write a function that takes a credit card number as a string and returns the masked version of the number, with only the last four digits visible. + +**For example:** + +``` +Input: '1234567812345678' +Output: '************5678' +``` + +**Requirements:** + +The input will always be a valid credit card number as a string. +The function should preserve the last four digits. +It should handle inputs of varying lengths (e.g., short card numbers). + +**Example** + +``` +hide_credit_card('1234567812345678') +# Output: '************5678' + +hide_credit_card('9876543210987654') +# Output: '************7654' + +hide_credit_card('1234') +# Output: '1234' (no masking needed if the number has only 4 or fewer digits) +``` + +**Testing** + +Develop unit tests to validate the function's correctness. Include cases for: + +- Regular 16-digit credit card numbers. +- Short numbers (e.g., fewer than 8 digits). +- Edge case: Exactly 4 digits (no masking needed). + +**Helpful Links** + +- [String Slicing in Python](https://www.geeksforgeeks.org/string-slicing-in-python/) +- [GeeksforGeeks: Python String Methods](https://www.geeksforgeeks.org/python-string-methods/) diff --git a/solutions/challenge_16/__init__.py b/solutions/challenge_16/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/challenge_16/hide_credit_card_number.py b/solutions/challenge_16/hide_credit_card_number.py new file mode 100644 index 000000000..8faaddad1 --- /dev/null +++ b/solutions/challenge_16/hide_credit_card_number.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for masking sensitive credit card numbers. + +Module contents: + - hide_credit_card: masks all but the last four digits of a credit card number. + +Created on 04/01/2025 +Author: Hector Colmenares +""" + + +def hide_credit_card(card_number: str) -> str: + """Masks all but the last four digits of a credit card number. + + Parameters: + card_number: str, a valid credit card number as a string + + Returns -> str with the masked credit card number, keeping only the last four digits visible + + Raises: + ValueError: if the input is not a string + ValueError: if the input is empty or contains non-digit characters + + >>> hide_credit_card('1234567812345678') + '************5678' + + >>> hide_credit_card('9876543210987654') + '************7654' + + >>> hide_credit_card('1234') + '1234' + """ + # Ensure the input is a valid string of digits + if not isinstance(card_number, str): + raise ValueError("Input must be a string.") + if not card_number.isdigit() or len(card_number) == 0: + raise ValueError("Input must be a non-empty string of digits.") + + # If the length is less than or equal to 4, return the card number unchanged + if len(card_number) <= 4: + return card_number + + # Mask all but the last four digits + return "*" * (len(card_number) - 4) + card_number[-4:] diff --git a/solutions/tests/challenge_16/__init__.py b/solutions/tests/challenge_16/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/tests/challenge_16/test_hide_credit_card_number.py b/solutions/tests/challenge_16/test_hide_credit_card_number.py new file mode 100644 index 000000000..25df79571 --- /dev/null +++ b/solutions/tests/challenge_16/test_hide_credit_card_number.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for the hide_credit_card function. + +Class: + TestHideCreditCard: Contains tests for various cases. + +Created on 04/01/2025 +Author: Hector Colmenares +""" + +import unittest + +from solutions.challenge_16.hide_credit_card_number import hide_credit_card + + +class TestHideCreditCard(unittest.TestCase): + """Tests for the hide_credit_card function.""" + + def test_regular_number(self): + """Test with a regular 16-digit credit card number.""" + self.assertEqual(hide_credit_card("1234567812345678"), "************5678") + + def test_short_number(self): + """Test with a short credit card number.""" + self.assertEqual(hide_credit_card("12345"), "*2345") + + def test_exactly_four_digits(self): + """Test with a credit card number of exactly four digits.""" + self.assertEqual(hide_credit_card("1234"), "1234") + + def test_non_digit_characters_raises_value_error(self): + """Test with a credit card number containing non-digit characters.""" + with self.assertRaises(ValueError): + hide_credit_card("1234abcd5678") + + def test_empty_string_raises_value_error(self): + """Test with an empty string.""" + with self.assertRaises(ValueError): + hide_credit_card("") + + def test_non_string_input_raises_value_error(self): + """Test with non-string input.""" + with self.assertRaises(ValueError): + hide_credit_card(12345678) + + +if __name__ == "__main__": + unittest.main() From 7d04057f4432fa4f48f3e7820545fcad44bd05a5 Mon Sep 17 00:00:00 2001 From: hectordacb Date: Sat, 4 Jan 2025 19:12:41 -0400 Subject: [PATCH 2/3] Add solutions and tests for challenge_16 --- solutions/challenge_16/README.MD | 46 +++++++++++++++++ solutions/challenge_16/__init__.py | 0 .../challenge_16/hide_credit_card_number.py | 46 +++++++++++++++++ solutions/tests/challenge_16/__init__.py | 0 .../test_hide_credit_card_number.py | 50 +++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 solutions/challenge_16/README.MD create mode 100644 solutions/challenge_16/__init__.py create mode 100644 solutions/challenge_16/hide_credit_card_number.py create mode 100644 solutions/tests/challenge_16/__init__.py create mode 100644 solutions/tests/challenge_16/test_hide_credit_card_number.py diff --git a/solutions/challenge_16/README.MD b/solutions/challenge_16/README.MD new file mode 100644 index 000000000..7620fcd3b --- /dev/null +++ b/solutions/challenge_16/README.MD @@ -0,0 +1,46 @@ +# **Challenge: Hide a Credit Card Number** + +**Description** + +The "Hide a Credit Card Number" challenge involves writing a function to mask all but the last four digits of a credit card number. This is useful for displaying sensitive information in a secure manner. The masked digits should be replaced with the `*` character. + +Write a function that takes a credit card number as a string and returns the masked version of the number, with only the last four digits visible. + +**For example:** + +``` +Input: '1234567812345678' +Output: '************5678' +``` + +**Requirements:** + +The input will always be a valid credit card number as a string. +The function should preserve the last four digits. +It should handle inputs of varying lengths (e.g., short card numbers). + +**Example** + +``` +hide_credit_card('1234567812345678') +# Output: '************5678' + +hide_credit_card('9876543210987654') +# Output: '************7654' + +hide_credit_card('1234') +# Output: '1234' (no masking needed if the number has only 4 or fewer digits) +``` + +**Testing** + +Develop unit tests to validate the function's correctness. Include cases for: + +- Regular 16-digit credit card numbers. +- Short numbers (e.g., fewer than 8 digits). +- Edge case: Exactly 4 digits (no masking needed). + +**Helpful Links** + +- [String Slicing in Python](https://www.geeksforgeeks.org/string-slicing-in-python/) +- [GeeksforGeeks: Python String Methods](https://www.geeksforgeeks.org/python-string-methods/) diff --git a/solutions/challenge_16/__init__.py b/solutions/challenge_16/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/challenge_16/hide_credit_card_number.py b/solutions/challenge_16/hide_credit_card_number.py new file mode 100644 index 000000000..8faaddad1 --- /dev/null +++ b/solutions/challenge_16/hide_credit_card_number.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +A module for masking sensitive credit card numbers. + +Module contents: + - hide_credit_card: masks all but the last four digits of a credit card number. + +Created on 04/01/2025 +Author: Hector Colmenares +""" + + +def hide_credit_card(card_number: str) -> str: + """Masks all but the last four digits of a credit card number. + + Parameters: + card_number: str, a valid credit card number as a string + + Returns -> str with the masked credit card number, keeping only the last four digits visible + + Raises: + ValueError: if the input is not a string + ValueError: if the input is empty or contains non-digit characters + + >>> hide_credit_card('1234567812345678') + '************5678' + + >>> hide_credit_card('9876543210987654') + '************7654' + + >>> hide_credit_card('1234') + '1234' + """ + # Ensure the input is a valid string of digits + if not isinstance(card_number, str): + raise ValueError("Input must be a string.") + if not card_number.isdigit() or len(card_number) == 0: + raise ValueError("Input must be a non-empty string of digits.") + + # If the length is less than or equal to 4, return the card number unchanged + if len(card_number) <= 4: + return card_number + + # Mask all but the last four digits + return "*" * (len(card_number) - 4) + card_number[-4:] diff --git a/solutions/tests/challenge_16/__init__.py b/solutions/tests/challenge_16/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/tests/challenge_16/test_hide_credit_card_number.py b/solutions/tests/challenge_16/test_hide_credit_card_number.py new file mode 100644 index 000000000..25df79571 --- /dev/null +++ b/solutions/tests/challenge_16/test_hide_credit_card_number.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Unit tests for the hide_credit_card function. + +Class: + TestHideCreditCard: Contains tests for various cases. + +Created on 04/01/2025 +Author: Hector Colmenares +""" + +import unittest + +from solutions.challenge_16.hide_credit_card_number import hide_credit_card + + +class TestHideCreditCard(unittest.TestCase): + """Tests for the hide_credit_card function.""" + + def test_regular_number(self): + """Test with a regular 16-digit credit card number.""" + self.assertEqual(hide_credit_card("1234567812345678"), "************5678") + + def test_short_number(self): + """Test with a short credit card number.""" + self.assertEqual(hide_credit_card("12345"), "*2345") + + def test_exactly_four_digits(self): + """Test with a credit card number of exactly four digits.""" + self.assertEqual(hide_credit_card("1234"), "1234") + + def test_non_digit_characters_raises_value_error(self): + """Test with a credit card number containing non-digit characters.""" + with self.assertRaises(ValueError): + hide_credit_card("1234abcd5678") + + def test_empty_string_raises_value_error(self): + """Test with an empty string.""" + with self.assertRaises(ValueError): + hide_credit_card("") + + def test_non_string_input_raises_value_error(self): + """Test with non-string input.""" + with self.assertRaises(ValueError): + hide_credit_card(12345678) + + +if __name__ == "__main__": + unittest.main() From 3104e9188420eab9b7b2a20358c2adbfc992a684 Mon Sep 17 00:00:00 2001 From: hectordacb Date: Wed, 8 Jan 2025 17:34:05 -0400 Subject: [PATCH 3/3] Removing unnecessary code --- solutions/tests/challenge_16/test_hide_credit_card_number.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/solutions/tests/challenge_16/test_hide_credit_card_number.py b/solutions/tests/challenge_16/test_hide_credit_card_number.py index 25df79571..0aa381aba 100644 --- a/solutions/tests/challenge_16/test_hide_credit_card_number.py +++ b/solutions/tests/challenge_16/test_hide_credit_card_number.py @@ -44,7 +44,3 @@ def test_non_string_input_raises_value_error(self): """Test with non-string input.""" with self.assertRaises(ValueError): hide_credit_card(12345678) - - -if __name__ == "__main__": - unittest.main()