diff --git a/bin/algs4.php b/bin/algs4.php index 69f2aa9..4b93c70 100755 --- a/bin/algs4.php +++ b/bin/algs4.php @@ -14,5 +14,6 @@ new Commands\AllowList(), new Commands\Average(), new Commands\RandomSeq(), + new Commands\Interval2D(), ]); $app->run(); \ No newline at end of file diff --git a/src/Commands/Interval2D.php b/src/Commands/Interval2D.php new file mode 100644 index 0000000..fff590a --- /dev/null +++ b/src/Commands/Interval2D.php @@ -0,0 +1,92 @@ +addArgument( + 'xmin', + InputArgument::REQUIRED, + 'the minimum x coordinate' + ); + $this->addArgument( + 'xmax', + InputArgument::REQUIRED, + 'the maximum x coordinate' + ); + $this->addArgument( + 'ymin', + InputArgument::REQUIRED, + 'the minimum y coordinate' + ); + $this->addArgument( + 'ymax', + InputArgument::REQUIRED, + 'the maximum y coordinate' + ); + $this->addArgument( + 'trials', + InputArgument::REQUIRED, + 'the number of trials' + ); + } + + #[Override] + protected function execute( + InputInterface $input, + OutputInterface $output + ): int { + $x_min = parse_float($input->getArgument('xmin')); + $x_max = parse_float($input->getArgument('xmax')); + $y_min = parse_float($input->getArgument('ymin')); + $y_max = parse_float($input->getArgument('ymax')); + $trials = parse_int($input->getArgument('trials')); + + $x_interval = Interval1D::fromMinMax($x_min, $x_max); + $y_interval = Interval1D::fromMinMax($y_min, $y_max); + $box = \Kellegous\Algs4\Interval2D::fromXY($x_interval, $y_interval); + // $box->draw(); + + $counter = new Counter('hits'); + $random = Random::withEngine(new Mt19937()); + for ($i = 0; $i < $trials; $i++) { + $x = $random->uniformFloat(); + $y = $random->uniformFloat(); + $point = new Point2D($x, $y); + if ($box->contains($point)) { + $counter->increment(); + } + // else $point->draw(); + } + + Stdio::out()->println($counter); + Stdio::out()->printf("box area = %.2f\n", $box->area()); + return Command::SUCCESS; + } +} \ No newline at end of file diff --git a/src/Interval2D.php b/src/Interval2D.php index 0554e05..f2bcd93 100644 --- a/src/Interval2D.php +++ b/src/Interval2D.php @@ -4,14 +4,43 @@ namespace Kellegous\Algs4; +/** + * The {@code Interval2D} class represents a closed two-dimensional interval, + * which represents all points (x, y) with both {@code xmin <= x <= xmax} and + * {@code ymin <= y <= ymax}. + * Two-dimensional intervals are immutable: their values cannot be changed + * after they are created. + * The class {@code Interval2D} includes methods for checking whether + * a two-dimensional interval contains a point and determining whether + * two two-dimensional intervals intersect. + *
+ * For additional documentation,
+ * see Section 1.2 of
+ * Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne.
+ *
+ * @author Robert Sedgewick
+ * @author Kevin Wayne
+ * @author Kelly Norton
+ */
final readonly class Interval2D
{
+ /**
+ * Initializes a two-dimensional interval.
+ * @param Interval1D $x
+ * @param Interval1D $y
+ */
public function __construct(
private Interval1D $x,
private Interval1D $y
) {
}
+ /**
+ * Initializes a two-dimensional interval.
+ * @param Interval1D $x
+ * @param Interval1D $y
+ * @return self
+ */
public static function fromXY(
Interval1D $x,
Interval1D $y
@@ -19,29 +48,53 @@ public static function fromXY(
return new self($x, $y);
}
+ /**
+ * Does this two-dimensional interval intersect that two-dimensional interval?
+ * @param Interval2D $that
+ * @return bool
+ */
public function intersects(self $that): bool
{
return $this->x->intersects($that->x)
&& $this->y->intersects($that->y);
}
- public function x(): Interval1D
+ /**
+ * Returns the area of this two-dimensional interval.
+ * @return float
+ */
+ public function area(): float
{
- return $this->x;
+ return $this->x->length() * $this->y->length();
}
- public function y(): Interval1D
+ /**
+ * Returns a string representation of this two-dimensional interval.
+ * @return string
+ */
+ public function __toString(): string
{
- return $this->y;
+ return sprintf('%s x %s', $this->x, $this->y);
}
- public function area(): float
+ /**
+ * Does this two-dimensional interval contain the point p?
+ * @param Point2D $point
+ * @return bool
+ */
+ public function contains(Point2D $point): bool
{
- return $this->x->length() * $this->y->length();
+ return $this->x->contains($point->x())
+ && $this->y->contains($point->y());
}
- public function __toString(): string
+ public function x(): Interval1D
{
- return sprintf('%s x %s', $this->x, $this->y);
+ return $this->x;
+ }
+
+ public function y(): Interval1D
+ {
+ return $this->y;
}
}
\ No newline at end of file
diff --git a/src/Point2D.php b/src/Point2D.php
index 0ff34b3..c6d2fad 100644
--- a/src/Point2D.php
+++ b/src/Point2D.php
@@ -4,7 +4,7 @@
final readonly class Point2D
{
- private function __construct(
+ public function __construct(
private float $x,
private float $y
) {
diff --git a/tests/Interval2DTest.php b/tests/Interval2DTest.php
index 45d0d79..053368a 100644
--- a/tests/Interval2DTest.php
+++ b/tests/Interval2DTest.php
@@ -126,6 +126,66 @@ public static function asStringTests(): iterable
];
}
+ /**
+ * @return iterable