Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  
   3  declare(strict_types=1);
   4  
   5  namespace Phpml\Math;
   6  
   7  use ArrayIterator;
   8  use IteratorAggregate;
   9  
  10  class Set implements IteratorAggregate
  11  {
  12      /**
  13       * @var string[]|int[]|float[]|bool[]
  14       */
  15      private $elements = [];
  16  
  17      /**
  18       * @param string[]|int[]|float[]|bool[] $elements
  19       */
  20      public function __construct(array $elements = [])
  21      {
  22          $this->elements = self::sanitize($elements);
  23      }
  24  
  25      /**
  26       * Creates the union of A and B.
  27       */
  28      public static function union(self $a, self $b): self
  29      {
  30          return new self(array_merge($a->toArray(), $b->toArray()));
  31      }
  32  
  33      /**
  34       * Creates the intersection of A and B.
  35       */
  36      public static function intersection(self $a, self $b): self
  37      {
  38          return new self(array_intersect($a->toArray(), $b->toArray()));
  39      }
  40  
  41      /**
  42       * Creates the difference of A and B.
  43       */
  44      public static function difference(self $a, self $b): self
  45      {
  46          return new self(array_diff($a->toArray(), $b->toArray()));
  47      }
  48  
  49      /**
  50       * Creates the Cartesian product of A and B.
  51       *
  52       * @return Set[]
  53       */
  54      public static function cartesian(self $a, self $b): array
  55      {
  56          $cartesian = [];
  57  
  58          foreach ($a as $multiplier) {
  59              foreach ($b as $multiplicand) {
  60                  $cartesian[] = new self(array_merge([$multiplicand], [$multiplier]));
  61              }
  62          }
  63  
  64          return $cartesian;
  65      }
  66  
  67      /**
  68       * Creates the power set of A.
  69       *
  70       * @return Set[]
  71       */
  72      public static function power(self $a): array
  73      {
  74          $power = [new self()];
  75  
  76          foreach ($a as $multiplicand) {
  77              foreach ($power as $multiplier) {
  78                  $power[] = new self(array_merge([$multiplicand], $multiplier->toArray()));
  79              }
  80          }
  81  
  82          return $power;
  83      }
  84  
  85      /**
  86       * @param string|int|float|bool $element
  87       */
  88      public function add($element): self
  89      {
  90          return $this->addAll([$element]);
  91      }
  92  
  93      /**
  94       * @param string[]|int[]|float[]|bool[] $elements
  95       */
  96      public function addAll(array $elements): self
  97      {
  98          $this->elements = self::sanitize(array_merge($this->elements, $elements));
  99  
 100          return $this;
 101      }
 102  
 103      /**
 104       * @param string|int|float $element
 105       */
 106      public function remove($element): self
 107      {
 108          return $this->removeAll([$element]);
 109      }
 110  
 111      /**
 112       * @param string[]|int[]|float[] $elements
 113       */
 114      public function removeAll(array $elements): self
 115      {
 116          $this->elements = self::sanitize(array_diff($this->elements, $elements));
 117  
 118          return $this;
 119      }
 120  
 121      /**
 122       * @param string|int|float $element
 123       */
 124      public function contains($element): bool
 125      {
 126          return $this->containsAll([$element]);
 127      }
 128  
 129      /**
 130       * @param string[]|int[]|float[] $elements
 131       */
 132      public function containsAll(array $elements): bool
 133      {
 134          return count(array_diff($elements, $this->elements)) === 0;
 135      }
 136  
 137      /**
 138       * @return string[]|int[]|float[]|bool[]
 139       */
 140      public function toArray(): array
 141      {
 142          return $this->elements;
 143      }
 144  
 145      public function getIterator(): ArrayIterator
 146      {
 147          return new ArrayIterator($this->elements);
 148      }
 149  
 150      public function isEmpty(): bool
 151      {
 152          return $this->cardinality() === 0;
 153      }
 154  
 155      public function cardinality(): int
 156      {
 157          return count($this->elements);
 158      }
 159  
 160      /**
 161       * Removes duplicates and rewrites index.
 162       *
 163       * @param string[]|int[]|float[]|bool[] $elements
 164       *
 165       * @return string[]|int[]|float[]|bool[]
 166       */
 167      private static function sanitize(array $elements): array
 168      {
 169          sort($elements, SORT_ASC);
 170  
 171          return array_values(array_unique($elements, SORT_ASC));
 172      }
 173  }