sub note_to_sound { my ($note) = @_; return $notes{$note}; } use Test::More tests => 8; return 1 if caller(); # Done if loaded as a module my $song = make_SoM_song (join ' ', 'a' .. 'g'); my @expected = map{note_to_sound($_)} 'a' .. 'g'; Test::More::is_deeply($song, \@expected, "Notes map correctly to phrases"); my %noteCounts; my $samples = 100000; my $nominal = $samples / 7; ++$noteCounts{random_SoM_note($_)} for 1 .. $samples; Test::More::ok (abs($noteCounts{$_} - $nominal) < 200, "Random distribution of $_: $noteCounts{$_}") for map {note_to_sound($_)} 'a' .. 'g'; #### package SoundOfMusicSong; use strict; use warnings; my %SoM = ( 'c' => {phrase => 'a deer a female deer', sound => 'do'}, 'd' => {phrase => 'a drop of golden sun', sound => 're'}, 'e' => {phrase => 'a name I call myself', sound => 'me'}, 'f' => {phrase => 'a long long way to run', sound => 'fa'}, 'g' => {phrase => 'a needle pulling thread', sound => 'so'}, 'a' => {phrase => 'a note to follow so', sound => 'la'}, 'b' => {phrase => 'a drink with jam and bread', sound => 'te'}, ); my @notes = keys %SoM; sub make_SoM_song { my ($user_song) = @_; return [ map {exists $SoM{$_} ? $SoM{$_}->{sound} : 'not a note'} split /\W+/, $user_song ]; } sub getPhrase { my ($user_song) = @_; my $notes = make_SoM_song($user_song); my @new_song = map {$SoM{$_} ? "$_ $SoM{$_}" : 'not a note'} @$notes; return \@new_song; } sub random_SoM_note { return $SoM{$notes[rand @notes]}{sound}; } sub random_SoM_song { my ($number_of_notes) = @_; $number_of_notes ||= int(rand(100)) + 1; return [map {random_SoM_note()} 1 .. $number_of_notes]; } sub note_to_sound { my ($note) = @_; return $SoM{$note}{sound}; }