Преглед изворни кода

Merge branch '16-all-your-base'

Frédéric G. MARAND пре 5 месеци
родитељ
комит
7dcaf21707

+ 24 - 0
all-your-base/.exercism/config.json

@@ -0,0 +1,24 @@
+{
+  "authors": [
+    "camilopayan"
+  ],
+  "contributors": [
+    "arueckauer",
+    "kunicmarko20",
+    "kytrinyx",
+    "mk-mxp",
+    "neenjaw"
+  ],
+  "files": {
+    "solution": [
+      "AllYourBase.php"
+    ],
+    "test": [
+      "AllYourBaseTest.php"
+    ],
+    "example": [
+      ".meta/example.php"
+    ]
+  },
+  "blurb": "Convert a number, represented as a sequence of digits in one base, to any other base."
+}

+ 1 - 0
all-your-base/.exercism/metadata.json

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

+ 64 - 0
all-your-base/AllYourBase.php

@@ -0,0 +1,64 @@
+<?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);
+
+const ErrInBase = "input base must be >= 2";
+const ErrOutBase = "output base must be >= 2";
+const ErrDigits = "all digits must satisfy 0 <= d < input base";
+
+function rebase(int $fromBase, array $digits, int $toBase): array {
+  if ($fromBase < 2) {
+    throw new \InvalidArgumentException(ErrInBase);
+  }
+  if ($toBase < 2) {
+    throw new \InvalidArgumentException(ErrOutBase);
+  }
+  if ($fromBase === $toBase) {
+    return $digits;
+  }
+  $rev = array_reverse($digits);
+
+  $value = 0;
+  $pow = 1;
+  foreach ($rev as $digit) {
+    if ($digit < 0 || $digit >= $fromBase) {
+      throw new \InvalidArgumentException(ErrDigits);
+    }
+    $value += $digit * $pow;
+    $pow *= $fromBase;
+  }
+
+  $reversed = [];
+  $current = $value;
+  while (TRUE) {
+    $reversed[] = $current % $toBase;
+    $current = (int) ($current / $toBase);
+    if ($current === 0) {
+      break;
+    }
+  }
+  $out = array_reverse($reversed);
+  return $out;
+}

+ 226 - 0
all-your-base/AllYourBaseTest.php

@@ -0,0 +1,226 @@
+<?php
+
+declare(strict_types=1);
+
+class AllYourBaseTest extends PHPUnit\Framework\TestCase
+{
+    public static function setUpBeforeClass(): void
+    {
+        require_once 'AllYourBase.php';
+    }
+
+    /**
+     * uuid 5ce422f9-7a4b-4f44-ad29-49c67cb32d2c
+     * @testdox Single bit one to decimal
+     */
+    public function testSingleBitOneToDecimal(): void
+    {
+        $this->assertEquals([1], rebase(2, [1], 10));
+    }
+
+    /**
+     * uuid 0cc3fea8-bb79-46ac-a2ab-5a2c93051033
+     * @testdox Binary to single decimal
+     */
+    public function testBinaryToSingleDecimal(): void
+    {
+        $this->assertEquals([5], rebase(2, [1, 0, 1], 10));
+    }
+
+    /**
+     * uuid f12db0f9-0d3d-42c2-b3ba-e38cb375a2b8
+     * @testdox Single decimal to binary
+     */
+    public function testSingleDecimalToBinary(): void
+    {
+        $this->assertEquals([1, 0, 1], rebase(10, [5], 2));
+    }
+
+    /**
+     * uuid 2c45cf54-6da3-4748-9733-5a3c765d925b
+     * @testdox Binary to multiple decimal
+     */
+    public function testBinaryToMultipleDecimal(): void
+    {
+        $this->assertEquals([4, 2], rebase(2, [1, 0, 1, 0, 1, 0], 10));
+    }
+
+    /**
+     * uuid 65ddb8b4-8899-4fcc-8618-181b2cf0002d
+     * @testdox Decimal to binary
+     */
+    public function testDecimalToBinary(): void
+    {
+        $this->assertEquals([1, 0, 1, 0, 1, 0], rebase(10, [4, 2], 2));
+    }
+
+    /**
+     * uuid 8d418419-02a7-4824-8b7a-352d33c6987e
+     * @testdox Trinary to hexadecimal
+     */
+    public function testTrinaryToHexadecimal(): void
+    {
+        $this->assertEquals([2, 10], rebase(3, [1, 1, 2, 0], 16));
+    }
+
+    /**
+     * uuid d3901c80-8190-41b9-bd86-38d988efa956
+     * @testdox Hexadecimal to trinary
+     */
+    public function testHexadecimalToTrinary(): void
+    {
+        $this->assertEquals([1, 1, 2, 0], rebase(16, [2, 10], 3));
+    }
+
+    /**
+     * uuid 5d42f85e-21ad-41bd-b9be-a3e8e4258bbf
+     * @testdox 15-bit integer
+     */
+    public function test15BitIntegers(): void
+    {
+        $this->assertEquals([6, 10, 45], rebase(97, [3, 46, 60], 73));
+    }
+
+    /**
+     * uuid d68788f7-66dd-43f8-a543-f15b6d233f83
+     * @testdox Empty list
+     */
+    public function testEmptyList(): void
+    {
+        $this->assertEquals([0], rebase(2, [], 10));
+    }
+
+    /**
+     * uuid 5e27e8da-5862-4c5f-b2a9-26c0382b6be7
+     * @testdox Single zero
+     */
+    public function testSingleZero(): void
+    {
+        $this->assertEquals([0], rebase(10, [0], 2));
+    }
+
+    /**
+     * uuid 2e1c2573-77e4-4b9c-8517-6c56c5bcfdf2
+     * @testdox Multiple zeros
+     */
+    public function testMultipleZeros(): void
+    {
+        $this->assertEquals([0], rebase(10, [0, 0, 0], 2));
+    }
+
+    /**
+     * uuid 3530cd9f-8d6d-43f5-bc6e-b30b1db9629b
+     * @testdox Leading zeros
+     */
+    public function testLeadingZeros(): void
+    {
+        $this->assertEquals([4, 2], rebase(7, [0, 6, 0], 10));
+    }
+
+    /**
+     * uuid a6b476a1-1901-4f2a-92c4-4d91917ae023
+     * @testdox Input base is one
+     */
+    public function testFirstBaseIsOne(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('input base must be >= 2');
+
+        rebase(1, [0], 10);
+    }
+
+    /**
+     * uuid e21a693a-7a69-450b-b393-27415c26a016
+     * @testdox Input base is zero
+     */
+    public function testFirstBaseIsZero(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('input base must be >= 2');
+
+        rebase(0, [], 10);
+    }
+
+    /**
+     * uuid 54a23be5-d99e-41cc-88e0-a650ffe5fcc2
+     * @testdox Input base is negative
+     */
+    public function testFirstBaseIsNegative(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('input base must be >= 2');
+
+        rebase(-2, [1], 10);
+    }
+
+    /**
+     * uuid 9eccf60c-dcc9-407b-95d8-c37b8be56bb6
+     * @testdox Negative digit
+     */
+    public function testNegativeDigit(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('all digits must satisfy 0 <= d < input base');
+
+        rebase(2, [1, -1, 1, 0, 1, 0], 10);
+    }
+
+    /**
+     * uuid 232fa4a5-e761-4939-ba0c-ed046cd0676a
+     * @testdox Invalid positive digit
+     */
+    public function testInvalidPositiveDigit(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('all digits must satisfy 0 <= d < input base');
+
+        rebase(2, [1, 2, 1, 0, 1, 0], 10);
+    }
+
+    /**
+     * uuid 14238f95-45da-41dc-95ce-18f860b30ad3
+     * @testdox Output base is one
+     */
+    public function testSecondBaseIsOne(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('output base must be >= 2');
+
+        rebase(2, [1, 0, 1, 0, 1, 0], 1);
+    }
+
+    /**
+     * uuid 73dac367-da5c-4a37-95fe-c87fad0a4047
+     * @testdox Output base is zero
+     */
+    public function testSecondBaseIsZero(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('output base must be >= 2');
+
+        rebase(10, [7], 0);
+    }
+
+    /**
+     * uuid 13f81f42-ff53-4e24-89d9-37603a48ebd9
+     * @testdox Output base is negative
+     */
+    public function testSecondBaseIsNegative(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+        $this->expectExceptionMessage('output base must be >= 2');
+
+        rebase(2, [1], -7);
+    }
+
+    /**
+     * uuid 0e6c895d-8a5d-4868-a345-309d094cfe8d
+     * @testdox Both bases are negative
+     */
+    public function testBothBasesIsNegative(): void
+    {
+        $this->expectException(InvalidArgumentException::class);
+
+        rebase(-2, [1], -7);
+    }
+}

+ 52 - 0
all-your-base/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
+
+2. Get [PHPUnit] if you don't have it already.
+
+       wget -O phpunit https://phar.phpunit.de/phpunit-10.phar
+       chmod +x phpunit
+       ./phpunit --version
+
+3. Execute the tests:
+
+       ./phpunit test_file.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 AllYourBase.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.

+ 56 - 0
all-your-base/README.md

@@ -0,0 +1,56 @@
+# All Your Base
+
+Welcome to All Your Base on Exercism's PHP Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Introduction
+
+You've just been hired as professor of mathematics.
+Your first week went well, but something is off in your second week.
+The problem is that every answer given by your students is wrong!
+Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)!
+Amazingly, it turns out that each week, the students use a different base.
+To help you quickly verify the student answers, you'll be building a tool to translate between bases.
+
+## Instructions
+
+Convert a sequence of digits in one base, representing a number, into a sequence of digits in another base, representing the same number.
+
+~~~~exercism/note
+Try to implement the conversion yourself.
+Do not use something else to perform the conversion for you.
+~~~~
+
+## About [Positional Notation][positional-notation]
+
+In positional notation, a number in base **b** can be understood as a linear combination of powers of **b**.
+
+The number 42, _in base 10_, means:
+
+`(4 × 10¹) + (2 × 10⁰)`
+
+The number 101010, _in base 2_, means:
+
+`(1 × 2⁵) + (0 × 2⁴) + (1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰)`
+
+The number 1120, _in base 3_, means:
+
+`(1 × 3³) + (1 × 3²) + (2 × 3¹) + (0 × 3⁰)`
+
+_Yes. Those three numbers above are exactly the same. Congratulations!_
+
+[positional-notation]: https://en.wikipedia.org/wiki/Positional_notation
+
+## Source
+
+### Created by
+
+- @camilopayan
+
+### Contributed to by
+
+- @arueckauer
+- @kunicmarko20
+- @kytrinyx
+- @mk-mxp
+- @neenjaw