Smallest enclosing circle problem: Difference between revisions

m
→‎{{header|Raku}}: various idiomatifications
m (→‎{{header|Raku}}: various idiomatifications)
Line 937:
=={{header|Raku}}==
{{trans|Go}}
<lang perl6>#class 20201208P Raku{ programminghas ($.x, $.y) is rw; # solutionPoint
 
class P { has ($.x, $.y) is rw; # Point
method gist { "({$.x~", "~$.y})" }
}
 
class C { has (P $.c, Numeric $.r); # Circle
 
method gist { "Center = " ~$.c.gist ~ " and Radius = $.r\n" }
 
# returnstests whether a circle contains the point 'p'
method contains(P \p --> Bool) { return distSq($.c, p) ≤ $.r² }
 
} # returnstests whether a circle contains a slice of point
method encloses(@ps --> Bool) {
method encloses(@ps --> Bool) { [and] @ps.map: { return False unless $.contains($_) } }
return True
} # returns whether a circle contains a slice of point
}
 
sub infix:<−> (P \a, P \b) { a.x - b.x, a.y - b.y } # note: Unicode 'minus'
 
# returns the square of the distance between two points
sub distSq (P \a, P \b) { return (a.x - b.x)² [+] (a.y - b.y)»² }
 
sub getCenter (\bx, \by, \cx, \cy --> P) {
my (\b,\c,\d) = bx²+by² , cx²+cy², bx*cy - by*cx;
P.new: x => (cy*b - by*c) / (2 * d), y => (bx*c - cx*b) / (2 * d)
} # returns the center of a circle defined by 3 points
 
sub circleFrom3 (P \a, P \b, P \c --> C) {
my \k = $ = getCenter |(b.x - a.x, b.y - a.y, c.x - a.x), |(c.y - a.y);
k.x, k.y Z[+=] a.x, a.y;
kC.ynew: c +=> k, r => distSq(k, a).y;sqrt
return C.new: c => k, r => distSq(k, a).sqrt
} # returns a unique circle that intersects 3 points
 
sub circleFrom2 (P \a, P \b --> C ) {
my \center = P.new: x => ((a.x + b.x) / 2), y => ((a.y + b.y) / 2) ;
return C.new: c => center, r => (distSq(a, b).sqrt / 2)
} # returns smallest circle that intersects 2 points
 
sub secTrivial( @rs --> C ) {
given +@rs {
when * == 0 { return C.new: c => 3(P.new: {x die=> "There0, shouldn'ty be=> more0), thanr 3=> points."0 }
when * == 0 { return C.new: c => (P.new: x => 0, y => 0) , r => 0 }
when * == 1 { return C.new: c => @rs[0], r => 0 }
when * == 2 { return circleFrom2 |@rs[0], @rs[1] }
when * == 3 { #`{ no-op } }
when * > 3 { die "There shouldn't be more than 3 points." }
}
for 0, 1 X 1, 2 -> ( \i, \j ) {
given circleFrom2(@rs[i], @rs[j]) { return $_ if .encloses(@rs) }given circleFrom2 |@rs[i,j]
}
return circleFrom3 |@rs[0], @rs[1], @rs[2]
} # returns smallest enclosing circle for n ≤ 3
 
sub welzlHelperWelzl-helper( @ps is copy, @rs is copy , \n --> C ) {
return secTrivial(@rs) if ( n == 0 ||or +@rs == 3 );
my \p = @ps.shift;
return $_ if .contains(p) given Welzl-helper welzlHelper(@ps, @rs, n-1) { return $_ if .contains(p) };
returnWelzl-helper welzlHelper(@ps, @rs.append(p), n-1)
} # helper function for Welzl method
 
# applies the Welzl algorithm to find the SEC
sub welzl(@ps --> C) { returnWelzl-helper welzlHelper(@ps.pick(*), [], +@ps) }
 
my @tests = (
2,392

edits