# my @arr = ("abc", "def", "g");
# my $str = @arr.join("-");
# say $str;
# exit;
# my $counter = 0;
# repeat {
# say "Counter is $counter";
# $counter++;
# } until $counter >= 5;
# $counter = 0;
# repeat {
# say "Counter is $counter";
# $counter++;
# } while $counter < 5;
# exit;
# my $string = "This_is_a_test _string";
# if $string !~~ /<[\s\n]>+/ {
# say "String does not contain any whitespace or newlines.";
# } else {
# say "String contains whitespace or newlines.";
# }
# exit;
# my $string = "";#" \n ";
# if $string !~~ /^ <[\s\n]>+ $/ {
# say "String contains other characters.";
# } else {
# say "String is only whitespace or newline.";
# }
# exit;
# my $string = "";
# # Using inequality check
# if $string ne "" {
# say "String is not empty.";
# } else {
# say "String is empty";
# }
# exit;
# my %val;
# say %val;
# %val{'test'} = 5;
# say %val;
# # %val := {}; # Bind %val to an empty object (https://docs.raku.org/routine/:=)
# %val = ();
# say %val;
# exit;
# say split(";", "a;b;c").raku;
# say "abc.de".split(".").raku;
# my %capitals = 'Spain' => {'Madrid' => 3}, 'United States' => {'Washington DC' => 4};
# my %cts;
# if (not %capitals{'Zimbabwe'}:exists) {
# say "not exists";
# %capitals{'Zimbabwe'} = 'Harare' => 5;
# } else {
# say "exists";
# }
# if (not %capitals{'United States'}{'Sacramento'}:exists) {
# say "not exists 2";
# %capitals{'United States'}{'Sacramento'} = 8;
# } else {
# say "exists 2";
# }
# %capitals{'United States'}{'Sacramento'} += 1;
# if (not %capitals{'United States'}{'Sacramento'}:exists) {
# say "not exists 3";
# %capitals{'United States'}{'Sacramento'} = 8;
# } else {
# say "exists 3";
# %capitals{'United States'}{'Sacramento'} += 1;
# }
# if (not %capitals{'Canada'}:exists) {
# say "not exists 4";
# %capitals{'Canada'} = {'Quebec' => 15};
# } elsif (not %capitals{'Canada'}{'Quebec'}:exists) {
# say "not exists 5";
# %capitals{'Canada'}{'Quebec'} = 15;
# } else {
# say "exists 5";
# %capitals{'Canada'}{'Quebec'} += 1;
# }
# if (not %capitals{'Canada'}:exists) {
# say "not exists 4";
# %capitals{'Canada'} = {'Quebec' => 15};
# } elsif (not %capitals{'Canada'}{'Quebec'}:exists) {
# say "not exists 5";
# %capitals{'Canada'}{'Quebec'} = 15;
# } else {
# say "exists 5";
# %capitals{'Canada'}{'Quebec'} += 1;
# }
# say %capitals{'Spain'};
# say %capitals{'Spain'}{'Madrid'};
# say %capitals{'United States'};
# say %capitals{'United States'}{'Washington DC'};
# say %capitals{'United States'}{'Sacramento'};
# say %capitals{'Zimbabwe'};
# say %capitals{'Zimbabwe'}{'Harare'};
# say %capitals;
# %capitals = %capitals.sort: *.kv.reverse;
# say %capitals;
# for %capitals.sort -> (:$key, :$value) {
# say "Pair: $key:$value";
# }
# exit;
my $SEQUENCE_LENGTH = 10; # length of song title, suggested default 10
# hash of hashes for bigram counts
my %counts = ();
# hash of words already used in current sequence, reset for new sequence
my %word_history = ();
# build_bigram
# This splits the tracks into words and builds the bi-gram model
sub build_bigrams {
my @tracks = (
"foggy mountain breakdown",
"all same blood",
"when you're sick blues",
"all sick mountain",
"foggy mess",
"foggy",
"mess all same buff",
"man all same stuff",
"all good",
"all good dude",
"dude all good",
"i'm all sick",
"all bad",
"foggy mountain"
);
# foreach title in tracks array
# split title into individual words
# if there is more than one word
# while there are adjacent word pairs
# update count for word pair by 1
# end while
# end if
# end foreach
for @tracks -> $title {
say $title;
# Split title using one or more whitespaces as delimiter
my @word_array = $title.split(/\s+/);
say @word_array;
say @word_array.raku;
say @word_array.elems;
if (@word_array.elems > 1) {
say "more than 1 elems found."
} else {
say "1 or less elems found"
}
# Add each word pair to %counts hash map.
# The last word is ignored since no words follow it.
loop (my $i = 0; $i < @word_array.elems - 1; $i++) {
say $i ~ ":" ~ @word_array[$i] ~ "," ~ @word_array[$i+1];
if (not %counts{@word_array[$i]}:exists) { # Add new word pair for a new word key hash
say "key1 not exists";
%counts{@word_array[$i]} = {@word_array[$i+1] => 1};
} elsif (not %counts{@word_array[$i]}{@word_array[$i+1]}:exists) { # Add new word pair to an existing word key
say "key2 not exists" ~ ":" ~ %counts{@word_array[$i]};
%counts{@word_array[$i]}{@word_array[$i+1]} = 1;
} else { # Increment existing word pair
say "both keys exist";
%counts{@word_array[$i]}{@word_array[$i+1]} += 1;
}
say %counts;
}
say "\n";
}
say "FINAL";
say %counts;
}
##############################################################################################################################
# mcw
# This finds the most-common-word (mcw) to follow the given word
sub mcw {
# Seed word (arg) for which we find the next word
my $word = @_[0];
# Store the most common next word in this variable and return it.
my $best_word = '';
##########################
# LAB 2 TASK 2: MCW
##########################
##
## Find all available "next" words for $word
## Sort them (there is a function for that)
## so your results are deterministic and match the tests
##
## Iterate through all the available words
## that follow $word in the %counts
##
## Remember to check the %word_history
## and skip that word if used before
##
## Find the candidate word with highest count,
## update $best_word (it gets returned)
##
## In case of ties, stick with first one found
## (i.e. use strictly > in your count comparison if)
## that way you make the same choice the tests do
##
## This comment is longer than your code will be for this task.
##########################
##########################
# my %word_pair_counts = %counts{$word};
my $highest_count = 0; # track highest pair count
if (%counts{$word}:exists) {
say "\%counts{$word}.sort:\n" ~ %counts{$word}.sort;
# Check each word pair in key-sorted order
for %counts{$word}.sort -> (:$key, :$value) {
say "Pair: $key:$value";
# Update best_word if current count is greater than highest_count
# and only if current word is not already in word_history
if ($value > $highest_count && not %word_history{$key}:exists) {
$highest_count = $value;
$best_word = $key;
}
}
}
##########################
########################## End Task MCW
# if ($DEBUG) {say " <mcw for \'$word\' is \'$best_word'\>\n";}
# return the most common word to follow word
return $best_word
}
##############################################################################################################################
# sequence
# This builds a song title based on mcw
sub sequence {
# if ($DEBUG) {say "<sequence for \'@_[0]\'>\n";}
# clear word history for new sequence
%word_history = ();
##########################
# LAB 2 TASK 3: Build Song Title
##########################
## Use the seed word to build a sequence.
## For each word, look up the mcw
## Add to sequence.
## Repeat until next word is empty or newline
## Mind the max $SEQUENCE_LENGTH
## Remember to track word history using %word_history
## My solution is about 12 lines (and could have been less)
##########################
##########################
my $word = @_[0]; # Seed word (arg) for building a sequence
say "word:" ~ $word;
my $seq_length = 0; # track current sequent length
my @seq; # contains the sequence of words for output
# Push current word to sequence, add to word history, update sequence length, and fetch next word from mcw.
# Stop when next word is empty string, only whitespace/newline, or when maximum sequence length has been reached.
repeat {
@seq.push: $word;
%word_history{$word} = 1;
$seq_length++;
$word = mcw($word);
say "next word:" ~ $word;
} while ($word ne "" && $word !~~ /^ <[\s\n]>+ $/ && $seq_length < $SEQUENCE_LENGTH);
##########################
# return the sequence you created instead of this measely string
# return "ERROR: SEQUENCE 404";
say @seq;
return @seq.join(" "); # Join the sequence words together separated by a space.
########################## End Task Song Title
}
build_bigrams();
%word_history{'good'} = 1;
# %word_history{'same'} = 1;
# %word_history{'sick'} = 1;
# %word_history{'bad'} = 1;
say mcw("all");
say sequence("foggy");
say "\n";
say sequence("all")