Last active
May 7, 2016 22:14
-
-
Save MadcapJake/c29b76d7eccf5af86e973c5da7c7f7a3 to your computer and use it in GitHub Desktop.
Shakespeare Counter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my $text = open 'test.txt'; | |
constant CHUNK_SIZE = 5; | |
constant Vowels = <a e i o u A E I O U>.Set; | |
constant Consonants = <B C D F G H J K L M N P Q R S T V W X Y Z b c d f g h j k l m n p q r s t v w x y z>.Set; | |
sub channeled { | |
my ($read, $parsed) = Channel.new xx 2; | |
reader($text, $read); | |
counter($read, $parsed); | |
my @all-counts = await combiner($parsed); | |
@all-counts».say; | |
} | |
sub reader($text, Channel $dest) { | |
start { | |
CATCH { $dest.fail($_) } | |
my @chunk; | |
for $text.lines { | |
if @chunk.elems < CHUNK_SIZE { @chunk.push($_) } | |
else { $dest.send(@chunk.join("\n")); @chunk = Empty } | |
} | |
$dest.close | |
} | |
} | |
sub counter(Channel $source, Channel $dest) { | |
await gather for $source.list -> $chunk { | |
$chunk.say; | |
take start { | |
CATCH { $dest.fail($_) } | |
my int @ic = (0, 0, 0); | |
for $chunk.comb -> $_ { | |
when $_ ∈ Vowels { @ic[0]++ } | |
when $_ ∈ Consonants { @ic[1]++ } | |
default { @ic[2]++ } | |
} | |
$dest.send(@ic) | |
} | |
} | |
$dest.close | |
} | |
sub combiner(Channel $source) { | |
my Promise $promise .= new; | |
my $vow = $promise.vow; | |
start { | |
CATCH { $vow.break($_) } | |
my int @result = (0, 0, 0); | |
@result «+=» $_ for $source.list; | |
$vow.keep(@result) | |
} | |
$promise | |
} | |
channeled() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my $text = open 'shakespeare.txt'; | |
class Counter { | |
has $.name; | |
has int $!count = 0; | |
method tick { $!count++ } | |
method gist { "Counter.new(name => $!name, count => $!count)" } | |
} | |
sub naive { | |
my ($vowel, $consonant, $other) = do Counter.new(:name($_)) for <vowel consonant other>; | |
my \vowels = <a e i o u A E I O U>.Set; | |
while ($_ = $text.getc) { | |
when $_ ∈ vowels { $vowel.tick } | |
when /<:Letter>/ { $consonant.tick } | |
default { $other.tick } | |
} | |
($vowel, $consonant, $other)».say | |
} | |
naive(); #={214.14user 0.04system 3:34.14elapsed 100%CPU} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
constant CORES = 6; | |
constant Vowels = <a e i o u A E I O U>.Set; | |
constant Consonants = <B C D F G H J K L M N P Q R S T V W X Y Z b c d f g h j k l m n p q r s t v w x y z>.Set; | |
my $text = open 'test.txt', :r; | |
class Worker { | |
has Channel $.chunks .= new; | |
has Channel $!collector; | |
has Bool $.done = False; | |
method new ($collector) { self.bless(:$collector) } | |
submethod BUILD(:$!collector) { | |
start { | |
CATCH { $!chunks.fail($_) } | |
loop { | |
if $!chunks.poll -> $chunk { | |
'WORKER: poll'.say; | |
my int @a = 0, 0, 0; | |
for $chunk.comb -> $_ { | |
when $_ (elem) Vowels { @a[0]++ } | |
when $_ (elem) Consonants { @a[1]++ } | |
default { @a[2]++ } | |
} | |
$!collector.send(@a); | |
} elsif $!chunks.closed { $!done = True; last } | |
} | |
} | |
} | |
} | |
sub employer { | |
my ($provider, $collector) = Channel.new xx 2; | |
my Worker @workers = Worker.new($collector) xx CORES; | |
my int @collected = 0, 0, 0; | |
start { # Give chunks to provider for divying up | |
CATCH { $provider.fail($_) } | |
$provider.send($_) for $text.lines; #.rotor(20)».join("\n"); | |
$provider.close | |
} | |
start { # provide chunks to each worker | |
my $cursor = 0; | |
loop { | |
if $provider.poll -> $chunk { | |
'PROVIDE: poll'.say; | |
@workers[$cursor].chunks.send($chunk); | |
$cursor = 0 if ++$cursor == CORES | |
} elsif $provider.closed { last } | |
} | |
@workers».chunks».close; | |
loop { if all @workers».done { $collector.close; last } } | |
} | |
return await start { # apply the worker's ticks to @collected | |
CATCH { $collector.fail($_) } | |
loop { | |
if $collector.poll -> @ticks { | |
"COLLECT: @ticks[] into @collected[]".say; | |
@collected «+=» @ticks | |
} | |
elsif $collector.closed { last } | |
} | |
@collected | |
} | |
} | |
employer(); |
timo
commented
May 7, 2016
•
my $text = open 't8.shakespeare.txt', :r;
class Counter {
has $.name;
has int $!count = 0;
method tick { $!count++ }
method gist { "Counter.new(name => $!name, count => $!count)" }
}
sub naive {
my ($vowel, $consonant, $other) = do Counter.new(:name($_)) for <vowel consonant other>;
my \vowels = <a e i o u A E I O U>.Set;
my \consonants = <B C D F G H J K L M N P Q R S T V W X Y Z b c d f g h j k l m n p q r s t v w x y z>.Set;
while ($_ = $text.getc) {
if $_ (elem) vowels { $vowel.tick }
elsif $_ (elem) consonants { $consonant.tick }
else { $other.tick }
}
($vowel, $consonant, $other)».say
}
naive();
this version is significantly faster than the one in your gist.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment