Browse Source

Merge branch '12-luhn'

Frédéric G. MARAND 7 months ago
parent
commit
f8e05736c1
6 changed files with 321 additions and 0 deletions
  1. 26 0
      luhn/.exercism/config.json
  2. 1 0
      luhn/.exercism/metadata.json
  3. 52 0
      luhn/HELP.md
  4. 51 0
      luhn/Luhn.php
  5. 103 0
      luhn/LuhnTest.php
  6. 88 0
      luhn/README.md

+ 26 - 0
luhn/.exercism/config.json

@@ -0,0 +1,26 @@
+{
+  "authors": [
+    "Pierre-Vdsp"
+  ],
+  "contributors": [
+    "arueckauer",
+    "dstockto",
+    "kunicmarko20",
+    "kytrinyx",
+    "yisraeldov"
+  ],
+  "files": {
+    "solution": [
+      "Luhn.php"
+    ],
+    "test": [
+      "LuhnTest.php"
+    ],
+    "example": [
+      ".meta/example.php"
+    ]
+  },
+  "blurb": "Given a number determine whether or not it is valid per the Luhn formula.",
+  "source": "The Luhn Algorithm on Wikipedia",
+  "source_url": "https://en.wikipedia.org/wiki/Luhn_algorithm"
+}

+ 1 - 0
luhn/.exercism/metadata.json

@@ -0,0 +1 @@
+{"track":"php","exercise":"luhn","id":"14fd5f6185a14e838fbe61294039b73f","url":"https://exercism.org/tracks/php/exercises/luhn","handle":"Fairgame","is_requester":true,"auto_approve":false}

+ 52 - 0
luhn/HELP.md

@@ -0,0 +1,52 @@
+# Help
+
+## Running the tests
+
+## Running the tests
+
+1. Go to the root of your PHP exercise directory, which is `<EXERCISM_WORKSPACE>/php`.
+   To find the Exercism workspace run
+
+       ➜ exercism debug | grep Workspace
+
+1. Get [PHPUnit] if you don't have it already.
+
+       ➜ wget -O phpunit https://phar.phpunit.de/phpunit-9.phar
+       ➜ chmod +x phpunit
+       ➜ ./phpunit --version
+
+2. Execute the tests:
+
+       ➜ ./phpunit file_to_test.php
+
+   For example, to run the tests for the Hello World exercise, you would run:
+
+       ➜ ./phpunit HelloWorldTest.php
+
+[PHPUnit]: https://phpunit.de
+
+## Submitting your solution
+
+You can submit your solution using the `exercism submit Luhn.php` command.
+This command will upload your solution to the Exercism website and print the solution page's URL.
+
+It's possible to submit an incomplete solution which allows you to:
+
+- See how others have completed the exercise
+- Request help from a mentor
+
+## Need to get help?
+
+If you'd like help solving the exercise, check the following pages:
+
+- The [PHP track's documentation](https://exercism.org/docs/tracks/php)
+- The [PHP track's programming category on the forum](https://forum.exercism.org/c/programming/php)
+- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
+- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
+
+Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
+
+To get help if you're having trouble, you can use one of the following resources:
+
+ - [/r/php](https://www.reddit.com/r/php) is the PHP subreddit.
+ - [StackOverflow](https://stackoverflow.com/questions/tagged/php) can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.

+ 51 - 0
luhn/Luhn.php

@@ -0,0 +1,51 @@
+<?php
+
+/*
+ * By adding type hints and enabling strict type checking, code can become
+ * easier to read, self-documenting and reduce the number of potential bugs.
+ * By default, type declarations are non-strict, which means they will attempt
+ * to change the original type to match the type specified by the
+ * type-declaration.
+ *
+ * In other words, if you pass a string to a function requiring a float,
+ * it will attempt to convert the string value to a float.
+ *
+ * To enable strict mode, a single declare directive must be placed at the top
+ * of the file.
+ * This means that the strictness of typing is configured on a per-file basis.
+ * This directive not only affects the type declarations of parameters, but also
+ * a function's return type.
+ *
+ * For more info review the Concept on strict type checking in the PHP track
+ * <link>.
+ *
+ * To disable strict typing, comment out the directive below.
+ */
+
+declare(strict_types=1);
+
+function isValid(string $number): bool {
+  $number = str_replace(' ', '', $number);
+  if (mb_strlen($number) < 2) {
+    return FALSE;
+  }
+  if (preg_match("/\D/", $number)) {
+    return FALSE;
+  }
+  // At this point, we know the string only contains digits, so ASCII.
+  $digits = str_split($number);
+  $sum = 0;
+  $len = count($digits);
+  for ($i = $len - 1; $i >= 0; $i--) {
+    $digit = $digits[$i];
+    if (($len - $i) % 2 == 0) {
+      $digit *= 2;
+      if ($digit > 9) {
+        $digit -= 9;
+      }
+    }
+    $sum += $digit;
+    $sum %= 10;
+  }
+  return ($sum % 10) === 0;
+}

+ 103 - 0
luhn/LuhnTest.php

@@ -0,0 +1,103 @@
+<?php
+
+/*
+ * By adding type hints and enabling strict type checking, code can become
+ * easier to read, self-documenting and reduce the number of potential bugs.
+ * By default, type declarations are non-strict, which means they will attempt
+ * to change the original type to match the type specified by the
+ * type-declaration.
+ *
+ * In other words, if you pass a string to a function requiring a float,
+ * it will attempt to convert the string value to a float.
+ *
+ * To enable strict mode, a single declare directive must be placed at the top
+ * of the file.
+ * This means that the strictness of typing is configured on a per-file basis.
+ * This directive not only affects the type declarations of parameters, but also
+ * a function's return type.
+ *
+ * For more info review the Concept on strict type checking in the PHP track
+ * <link>.
+ *
+ * To disable strict typing, comment out the directive below.
+ */
+
+declare(strict_types=1);
+
+class LuhnTest extends PHPUnit\Framework\TestCase
+{
+    public static function setUpBeforeClass(): void
+    {
+        require_once 'Luhn.php';
+    }
+
+    public function testSingleDigitInvalid(): void
+    {
+        $this->assertFalse(isValid("1"));
+    }
+
+    public function testSingleZeroInvalid(): void
+    {
+        $this->assertFalse(isValid("0"));
+    }
+
+    public function testSimpleValidNumber(): void
+    {
+        $this->assertTrue(isValid("59"));
+    }
+
+    public function testSpaceHandling(): void
+    {
+        $this->assertTrue(isValid(" 5 9 "));
+    }
+
+    public function testValidCanadianSocialInsuranceNumber(): void
+    {
+        $this->assertTrue(isValid("046 454 286"));
+    }
+
+    public function testInvalidCanadianSocialInsuranceNumber(): void
+    {
+        $this->assertFalse(isValid("046 454 287"));
+    }
+
+    public function testInvalidCreditCard(): void
+    {
+        $this->assertFalse(isValid("8273 1232 7352 0569"));
+    }
+
+    public function testNonDigitCharacterInValidStringInvalidatesTheString(): void
+    {
+        $this->assertFalse(isValid("046a 454 286"));
+    }
+
+    public function testThatStringContainingSymbolsIsInvalid(): void
+    {
+        $this->assertFalse(isValid("055£ 444$ 285"));
+    }
+
+    public function testThatStringContainingPunctuationIsInvalid(): void
+    {
+        $this->assertFalse(isValid("055-444-285"));
+    }
+
+    public function testSpaceAndSingleZeroIsInvalid(): void
+    {
+        $this->assertFalse(isValid(" 0"));
+    }
+
+    public function testMultipleZerosIsValid(): void
+    {
+        $this->assertTrue(isValid(" 00000"));
+    }
+
+    public function testThatDoublingNineIsHandledCorrectly(): void
+    {
+        $this->assertTrue(isValid("091"));
+    }
+
+    public function testThatStringContainingSymbolsWhichCouldBeZeroIsInvalid(): void
+    {
+        $this->assertFalse(isValid(" ABCDEF"));
+    }
+}

+ 88 - 0
luhn/README.md

@@ -0,0 +1,88 @@
+# Luhn
+
+Welcome to Luhn on Exercism's PHP Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Instructions
+
+Given a number determine whether or not it is valid per the Luhn formula.
+
+The [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm) is
+a simple checksum formula used to validate a variety of identification
+numbers, such as credit card numbers and Canadian Social Insurance
+Numbers.
+
+The task is to check if a given string is valid.
+
+Validating a Number
+------
+
+Strings of length 1 or less are not valid. Spaces are allowed in the input,
+but they should be stripped before checking. All other non-digit characters
+are disallowed.
+
+## Example 1: valid credit card number
+
+```text
+4539 3195 0343 6467
+```
+
+The first step of the Luhn algorithm is to double every second digit,
+starting from the right. We will be doubling
+
+```text
+4_3_ 3_9_ 0_4_ 6_6_
+```
+
+If doubling the number results in a number greater than 9 then subtract 9
+from the product. The results of our doubling:
+
+```text
+8569 6195 0383 3437
+```
+
+Then sum all of the digits:
+
+```text
+8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80
+```
+
+If the sum is evenly divisible by 10, then the number is valid. This number is valid!
+
+## Example 2: invalid credit card number
+
+```text
+8273 1232 7352 0569
+```
+
+Double the second digits, starting from the right
+
+```text
+7253 2262 5312 0539
+```
+
+Sum the digits
+
+```text
+7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
+```
+
+57 is not evenly divisible by 10, so this number is not valid.
+
+## Source
+
+### Created by
+
+- @Pierre-Vdsp
+
+### Contributed to by
+
+- @arueckauer
+- @dstockto
+- @kunicmarko20
+- @kytrinyx
+- @yisraeldov
+
+### Based on
+
+The Luhn Algorithm on Wikipedia - https://en.wikipedia.org/wiki/Luhn_algorithm