aboutsummaryrefslogtreecommitdiff
path: root/challenge-093/athanasius/perl/Line.pm
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2021-01-03 20:34:06 +0000
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2021-01-03 20:34:06 +0000
commit8c41c85f7529767d2e163c1249b64982680480e9 (patch)
tree31814575c6866c0b10c83ef7201bb4ca89502ab0 /challenge-093/athanasius/perl/Line.pm
parent7b3ee11d1db49649ef7c156290859747792ed7c5 (diff)
downloadperlweeklychallenge-club-8c41c85f7529767d2e163c1249b64982680480e9.tar.gz
perlweeklychallenge-club-8c41c85f7529767d2e163c1249b64982680480e9.tar.bz2
perlweeklychallenge-club-8c41c85f7529767d2e163c1249b64982680480e9.zip
- Added solutions by Athanasius.
Diffstat (limited to 'challenge-093/athanasius/perl/Line.pm')
-rw-r--r--challenge-093/athanasius/perl/Line.pm148
1 files changed, 148 insertions, 0 deletions
diff --git a/challenge-093/athanasius/perl/Line.pm b/challenge-093/athanasius/perl/Line.pm
new file mode 100644
index 0000000000..e6901b6015
--- /dev/null
+++ b/challenge-093/athanasius/perl/Line.pm
@@ -0,0 +1,148 @@
+#!perl
+
+###############################################################################
+##
+## Perl Weekly Challenge 093, Task #1: Max Points
+##
+###############################################################################
+
+package Line;
+
+use strict;
+use warnings;
+
+use constant EPSILON => 1.11e-16; # ~ 2^(-53) for 64-bit double precision
+
+##=============================================================================
+## Interface
+##=============================================================================
+
+#------------------------------------------------------------------------------
+sub new
+#------------------------------------------------------------------------------
+{
+ my ($class, $x1, $y1, $x2, $y2) = @_;
+ my $delta_x = $x2 - $x1;
+ my $delta_y = $y2 - $y1;
+ my $is_horizontal = 0;
+ my $is_vertical = 0;
+ my $gradient;
+ my $x_intercept;
+ my $y_intercept;
+
+ if (equals( $delta_x, 0 ) &&
+ equals( $delta_y, 0 ))
+ {
+ die sprintf "ERROR: Identical points (%d, %d), (%d, %d) do not " .
+ "define a line\n", $x1, $y1, $x2, $y2;
+ }
+ elsif (equals( $delta_x, 0 ))
+ {
+ $is_vertical = 1;
+ $x_intercept = $x1;
+ }
+ elsif (equals( $delta_y, 0 ))
+ {
+ $is_horizontal = 1;
+ $gradient = 0;
+ $y_intercept = $y1;
+ }
+ else
+ {
+ $gradient = $delta_y / $delta_x;
+ $x_intercept = $x1 - ($y1 / $gradient);
+ $y_intercept = $y1 - ($x1 * $gradient);
+ }
+
+ my %self = (is_horizontal => $is_horizontal,
+ is_vertical => $is_vertical,
+ gradient => $gradient,
+ x_intercept => $x_intercept,
+ y_intercept => $y_intercept,
+ points => [ [$x1, $y1], [$x2, $y2] ]);
+
+ return bless \%self, $class;
+}
+
+#------------------------------------------------------------------------------
+sub collinear
+#------------------------------------------------------------------------------
+{
+ my ($self, $rhs) = @_;
+ my $collinear;
+
+ if ($self->{is_horizontal})
+ {
+ $collinear = $rhs->{is_horizontal} &&
+ equals( $self->{y_intercept}, $rhs->{y_intercept} );
+ }
+ elsif ($self->{is_vertical})
+ {
+ $collinear = $rhs->{is_vertical} &&
+ equals( $self->{x_intercept}, $rhs->{x_intercept} );
+ }
+ else
+ {
+ $collinear = !$rhs->{is_horizontal} && !$rhs->{is_vertical} &&
+ equals( $self->{gradient}, $rhs->{gradient} ) &&
+ equals( $self->{x_intercept}, $rhs->{x_intercept} );
+ }
+
+ return $collinear;
+}
+
+#------------------------------------------------------------------------------
+sub add_point
+#------------------------------------------------------------------------------
+{
+ my ($self, $new_point) = @_;
+ my $found = 0;
+
+ for my $existing_point (@{ $self->{points} })
+ {
+ if (equals( $existing_point->[0], $new_point->[0] ) &&
+ equals( $existing_point->[1], $new_point->[1] ))
+ {
+ $found = 1;
+ last;
+ }
+ }
+
+ push @{ $self->{points} }, $new_point unless $found;
+}
+
+#------------------------------------------------------------------------------
+sub count_points
+#------------------------------------------------------------------------------
+{
+ my ($self) = @_;
+
+ return scalar @{ $self->{points} };
+}
+
+#------------------------------------------------------------------------------
+sub show_points # For verbose output
+#------------------------------------------------------------------------------
+{
+ my ($self) = @_;
+
+ return join ', ',
+ map { '(' . $_->[0] . ',' . $_->[1] . ')' } @{ $self->{points} };
+}
+
+##=============================================================================
+## Implementation
+##=============================================================================
+
+#------------------------------------------------------------------------------
+sub equals
+#------------------------------------------------------------------------------
+{
+ my ($lhs, $rhs) = @_;
+
+ return abs($lhs - $rhs) < EPSILON;
+}
+
+###############################################################################
+1;
+###############################################################################