From 16a29792862341dec8cc0268e65c19a42ea4675f Mon Sep 17 00:00:00 2001 From: "Markus \"Holli\" Holzer" Date: Sat, 30 May 2020 22:16:34 +0200 Subject: final --- challenge-062/markus-holzer/raku/ch-1.raku | 81 ++++++++++++++++++------------ 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/challenge-062/markus-holzer/raku/ch-1.raku b/challenge-062/markus-holzer/raku/ch-1.raku index 550eecea7d..a2207abf11 100644 --- a/challenge-062/markus-holzer/raku/ch-1.raku +++ b/challenge-062/markus-holzer/raku/ch-1.raku @@ -1,43 +1,58 @@ +# This should really follow the spec or use something from CPAN class Mail { - has Str $.adress; - has Str $.domain; - has Str $.mailbox; - has Str $.norm; - - submethod TWEAK( :$!adress ) - { - my $index = $!adress.index: '@'; - - $!mailbox = $!adress.substr( 0, $index ); - $!domain = $!adress.substr( $index + 1, * ).lc; - $!norm = $!mailbox ~ '@' ~ $!domain; - } + has Str $.address; + has Str $.domain; + has Str $.mailbox; + has Str $.norm; + has Bool $.valid; + + method Str { $!address } + + submethod TWEAK( :$!address ) + { + my $index = $!address.index: '@'; + return unless $index && 0 < $index < $!address.chars - 1; + + $!mailbox = $!address.substr: 0, $index; + $!domain = lc $!address.substr: $index + 1, *; + $!norm = $!mailbox ~ '@' ~ $!domain; + $!valid = True; + } +} - method gist() { - $.norm } +subset FileIsReadable where { .IO.f && .IO.e && .IO.r } +subset FilesAreReadable where { .all ~~ FileIsReadable } - method Str() { - $.adress } -} +#| read from files +multi sub MAIN( + Bool :$u, #= unique. filters duplicates + *@files where FilesAreReadable #= files containing email addresses, 1 per line +) { + output-email-addresses $u, sort-mail-addresses @files.map: *.IO.open( :r ) } -multi sub MAIN( :$u ) { - output-email-adresses $u, sort-mail-adresses $*IN } +#| read from STDIN +multi sub MAIN( Bool :$u ) { + output-email-addresses $u, sort-mail-addresses $*IN } -multi sub MAIN( :$u, *@args ) { - output-email-adresses $u, sort-mail-adresses @args.map: *.IO.open( :r ) } +# catch bad arguments +multi sub MAIN( Bool :$u?, *@bad ) is hidden-from-USAGE { + $*USAGE.say } -sub output-email-adresses( $unique, @things ) { - .Str.say for $unique ?? @things.unique( :as( *.norm ) ) !! @things } +sub output-email-addresses( $unique, @addresses ) { + .address.say for $unique + ?? @addresses.squish( as => *.norm ) + !! @addresses } -sub sort-mail-adresses( *@handles ) +multi sub sort-mail-addresses( $handles where { .cache.all ~~ IO::Handle } ) { - my &adress = -> $adress { Mail.new( :$adress ) }; - my &sort = -> $a, $b { $a.domain cmp $b.domain || $a.mailbox cmp $b.mailbox }; - - @handles - .map( *.lines ) - .flat - .map( &adress ) - .sort( &sort ) + my &address = -> $address { Mail.new( :$address ) } + my &valid = -> $mail { $mail.valid || $*ERR.say("Bad data <$mail>") && False } + my &sort = -> $a, $b { $a.domain cmp $b.domain || $a.mailbox cmp $b.mailbox } + + $handles + .map( | *.lines ) + .map( &address ) + .grep( &valid ) + .sort( &sort ) } \ No newline at end of file -- cgit