2 Commits 97955498da ... a3a2cc7c13

Author SHA1 Message Date
  Frédéric G. MARAND a3a2cc7c13 Merge branch '11-sieve' 1 month ago
  Frédéric G. MARAND 31c1db54bd 11: Sieve. 1 month ago
7 changed files with 471 additions and 0 deletions
  1. 25 0
      sieve/.exercism/config.json
  2. 1 0
      sieve/.exercism/metadata.json
  3. 52 0
      sieve/HELP.md
  4. 72 0
      sieve/README.md
  5. 59 0
      sieve/Sieve.php
  6. 226 0
      sieve/SieveTest.php
  7. 36 0
      sieve/sieve.go

+ 25 - 0
sieve/.exercism/config.json

@@ -0,0 +1,25 @@
+{
+  "authors": [
+    "jeslopcru"
+  ],
+  "contributors": [
+    "arueckauer",
+    "kunicmarko20",
+    "kytrinyx",
+    "petemcfarlane"
+  ],
+  "files": {
+    "solution": [
+      "Sieve.php"
+    ],
+    "test": [
+      "SieveTest.php"
+    ],
+    "example": [
+      ".meta/example.php"
+    ]
+  },
+  "blurb": "Use the Sieve of Eratosthenes to find all the primes from 2 up to a given number.",
+  "source": "Sieve of Eratosthenes at Wikipedia",
+  "source_url": "https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes"
+}

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

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

+ 52 - 0
sieve/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 Sieve.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.

+ 72 - 0
sieve/README.md

@@ -0,0 +1,72 @@
+# Sieve
+
+Welcome to Sieve on Exercism's PHP Track.
+If you need help running the tests or submitting your code, check out `HELP.md`.
+
+## Introduction
+
+You bought a big box of random computer parts at a garage sale.
+You've started putting the parts together to build custom computers.
+
+You want to test the performance of different combinations of parts, and decide to create your own benchmarking program to see how your computers compare.
+You choose the famous "Sieve of Eratosthenes" algorithm, an ancient algorithm, but one that should push your computers to the limits.
+
+## Instructions
+
+Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find all prime numbers less than or equal to a given number.
+
+A prime number is a number larger than 1 that is only divisible by 1 and itself.
+For example, 2, 3, 5, 7, 11, and 13 are prime numbers.
+By contrast, 6 is _not_ a prime number as it not only divisible by 1 and itself, but also by 2 and 3.
+
+To use the Sieve of Eratosthenes, you first create a list of all the numbers between 2 and your given number.
+Then you repeat the following steps:
+
+1. Find the next unmarked number in your list (skipping over marked numbers).
+   This is a prime number.
+2. Mark all the multiples of that prime number as **not** prime.
+
+You keep repeating these steps until you've gone through every number in your list.
+At the end, all the unmarked numbers are prime.
+
+~~~~exercism/note
+The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes.
+To check you are implementing the Sieve correctly, a good first test is to check that you do not use division or remainder operations.
+~~~~
+
+## Example
+
+Let's say you're finding the primes less than or equal to 10.
+
+- List out 2, 3, 4, 5, 6, 7, 8, 9, 10, leaving them all unmarked.
+- 2 is unmarked and is therefore a prime.
+  Mark 4, 6, 8 and 10 as "not prime".
+- 3 is unmarked and is therefore a prime.
+  Mark 6 and 9 as not prime _(marking 6 is optional - as it's already been marked)_.
+- 4 is marked as "not prime", so we skip over it.
+- 5 is unmarked and is therefore a prime.
+  Mark 10 as not prime _(optional - as it's already been marked)_.
+- 6 is marked as "not prime", so we skip over it.
+- 7 is unmarked and is therefore a prime.
+- 8 is marked as "not prime", so we skip over it.
+- 9 is marked as "not prime", so we skip over it.
+- 10 is marked as "not prime", so we stop as there are no more numbers to check.
+
+You've examined all numbers and found 2, 3, 5, and 7 are still unmarked, which means they're the primes less than or equal to 10.
+
+## Source
+
+### Created by
+
+- @jeslopcru
+
+### Contributed to by
+
+- @arueckauer
+- @kunicmarko20
+- @kytrinyx
+- @petemcfarlane
+
+### Based on
+
+Sieve of Eratosthenes at Wikipedia - https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

+ 59 - 0
sieve/Sieve.php

@@ -0,0 +1,59 @@
+<?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);
+
+enum State {
+
+  case Maybe;
+  case Prime;
+  case NotPrime;
+
+}
+
+function sieve(int $limit): array {
+  $all = [];
+  $all[0] = State::NotPrime;
+  $all[1] = State::NotPrime;
+  for ($i = 2; $i <= $limit; $i++) {
+    $all[$i] = State::Maybe;
+  }
+
+  for ($i = 2; $i <= $limit; $i++) {
+    if ($all[$i] == State::NotPrime) {
+      continue;
+    }
+    $all[$i] = State::Prime;
+    for ($j = 2; $j <= $limit / $i; $j++) {
+      $all[$i * $j] = State::NotPrime;
+    }
+  }
+  $res = [];
+  foreach ($all as $i => $v) {
+    if ($v === State::Prime) {
+      $res[] = $i;
+    }
+  }
+  return $res;
+}

+ 226 - 0
sieve/SieveTest.php

@@ -0,0 +1,226 @@
+<?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 SieveTest extends PHPUnit\Framework\TestCase
+{
+    public static function setUpBeforeClass(): void
+    {
+        require_once 'Sieve.php';
+    }
+
+    public function testNoPrimesUnderTwo(): void
+    {
+        $this->assertEquals([], sieve(1));
+    }
+    public function testFindFirstPrime(): void
+    {
+        $this->assertEquals([2], sieve(2));
+    }
+    public function testFindPrimesUpTo10(): void
+    {
+        $this->assertEquals([2, 3, 5, 7], sieve(10));
+    }
+    public function testLimitIsPrime(): void
+    {
+        $this->assertEquals([2, 3, 5, 7, 11, 13], sieve(13));
+    }
+    public function testFindPrimesUpTo1000(): void
+    {
+        $this->assertEquals(
+            [
+                2,
+                3,
+                5,
+                7,
+                11,
+                13,
+                17,
+                19,
+                23,
+                29,
+                31,
+                37,
+                41,
+                43,
+                47,
+                53,
+                59,
+                61,
+                67,
+                71,
+                73,
+                79,
+                83,
+                89,
+                97,
+                101,
+                103,
+                107,
+                109,
+                113,
+                127,
+                131,
+                137,
+                139,
+                149,
+                151,
+                157,
+                163,
+                167,
+                173,
+                179,
+                181,
+                191,
+                193,
+                197,
+                199,
+                211,
+                223,
+                227,
+                229,
+                233,
+                239,
+                241,
+                251,
+                257,
+                263,
+                269,
+                271,
+                277,
+                281,
+                283,
+                293,
+                307,
+                311,
+                313,
+                317,
+                331,
+                337,
+                347,
+                349,
+                353,
+                359,
+                367,
+                373,
+                379,
+                383,
+                389,
+                397,
+                401,
+                409,
+                419,
+                421,
+                431,
+                433,
+                439,
+                443,
+                449,
+                457,
+                461,
+                463,
+                467,
+                479,
+                487,
+                491,
+                499,
+                503,
+                509,
+                521,
+                523,
+                541,
+                547,
+                557,
+                563,
+                569,
+                571,
+                577,
+                587,
+                593,
+                599,
+                601,
+                607,
+                613,
+                617,
+                619,
+                631,
+                641,
+                643,
+                647,
+                653,
+                659,
+                661,
+                673,
+                677,
+                683,
+                691,
+                701,
+                709,
+                719,
+                727,
+                733,
+                739,
+                743,
+                751,
+                757,
+                761,
+                769,
+                773,
+                787,
+                797,
+                809,
+                811,
+                821,
+                823,
+                827,
+                829,
+                839,
+                853,
+                857,
+                859,
+                863,
+                877,
+                881,
+                883,
+                887,
+                907,
+                911,
+                919,
+                929,
+                937,
+                941,
+                947,
+                953,
+                967,
+                971,
+                977,
+                983,
+                991,
+                997,
+            ],
+            sieve(1000)
+        );
+    }
+}

+ 36 - 0
sieve/sieve.go

@@ -0,0 +1,36 @@
+package sieve
+
+import "log"
+
+const (
+	Maybe = iota
+	Prime
+	NotPrime
+)
+
+func Sieve(limit int) []int {
+	all := make([]int, limit+1)
+	all[0] = NotPrime
+	all[1] = NotPrime
+	for i := 2; i <= limit; i++ {
+		all[i] = Maybe
+	}
+
+	for i := 2; i <= limit; i++ {
+		if all[i] == NotPrime {
+			continue
+		}
+		all[i] = Prime
+		for j := 2; j <= limit/i; j++ {
+			all[i*j] = NotPrime
+		}
+		log.Printf("After %3d: %v\n", i, all)
+	}
+	res := make([]int, 0, len(all))
+	for i, v := range all {
+		if v == Prime {
+			res = append(res, i)
+		}
+	}
+	return res
+}