Faith, yeah Everyone is so much, regular exercise oh no, pop one final friends surrogate and while no-one car Where was better, I get out of the last time Here it but you go When I'm not like a change Sometimes I can see my real farm my reflection It's such a house and somehow Yester, i'm not idealise I didn't cope if you A little birds, the future I do? If I don't wants you never leave me hills explode ray, but the kids in half Into yourself a local make love I get old Remind me crazy, maybe I want you can try the think you're in a week, get offered and there, I lost m #### Comes like a bug in a fast Germarket Just don't die the furniture I'm on antibiotics. I wish, I wish the ceiling, starting I doing that I'm gone Remind me that keep moving Be a while And the YEN We're talk slowerless Woh i can is what the really fed us on Let don't leave me In the best you? Been the lost myself. I'll always runs from here? Hey man, slow down though For a ride tonight, ever had, you'll not coming to my head of itself I'll drown Tie your eyes There's a danger Mobiles skwrking But never cheek Talking pills Just don't know what might as well comes i think now why I feel. My Belisha beacon on politics and when you wants to be crisps I'll be in a child, pearly #### #!/usr/bin/perl -w print "Content-type: text/html\r\n\r\n"; #radiohead song generator #has all the songs, but not the Demo Songs nor the covers (not sure the demo songs belong in there, and the #covers really don't seem to belong there) #includes use XML::DOM; #rough estimate of line numbers in Fake Plastic Trees #can later figure out the average on the fly, or generate a weighted random based on the real lengths. #$maxLines = 43*5;#for some reason this needs to be multiplied by vaguely the number of letters in the wordlength you choose $maxLines = 137; #setup parser, load songlist and turn into an XML document $parser = new XML::DOM::Parser; $doc = $parser->parsefile ("radiohead.xml"); ########################### #pass in album name and then get all the songs names for that album #return one long string of them ########################### sub getSongNames{ my $inputAlbumName = shift(@_); my $albumNodes = $doc->getElementsByTagName ("album"); my $n = $albumNodes->getLength; my $albumNode; my $albumName; my $songNodes; my $nn; my $x; for (my $i = 0; $i < $n; $i++) { $albumNode = $albumNodes->item ($i); if(lc($albumNode->getNodeName()) eq "album"){ $albumName = $albumNode->getAttributeNode("name"); $albumName = $albumName->getValue; #if the name matches what was passed in if(lc($albumName) eq lc($inputAlbumName)){ #we now match what was passed in - now find all the song nodes $songNodes = $albumNode->getChildNodes(); $nn = $songNodes->getLength(); for($x = 0;$x < $nn; $x++){ $songNode = $songNodes->item($x); if(lc($songNode->getNodeName()) eq 'song'){ $songNameArray[@songNameArray]=$songNode->getAttributeNode("name")->getValue(); } } } } } return join(' ', @songNameArray); } ########################### ########################### #pass in album name and then get all the songs for that album #return one long string of them ########################### sub getSongs{ my $inputAlbumName = shift(@_); my $albumNodes = $doc->getElementsByTagName ("album"); my $n = $albumNodes->getLength; my $i = 0; my $x = 0; my $albumNode; my $albumName; my $songNodes; my $nn = 0; for ($i = 0; $i < $n; $i++) { $albumNode = $albumNodes->item ($i); if(lc($albumNode->getNodeName()) eq "album"){ $albumName = $albumNode->getAttributeNode("name"); $albumName = $albumName->getValue; #if the name matches what was passed in if(lc($albumName) eq lc($inputAlbumName)){ #we now match what was passed in - now find all the song nodes $songNodes = $albumNode->getChildNodes(); $nn = $songNodes->getLength(); for($x = 0;$x < $nn; $x++){ $songNode = $songNodes->item($x); if(lc($songNode->getNodeName()) eq 'song'){ $songArray[@songArray]=$songNode->getFirstChild->getNodeValue(); } } } } } return join(' ', @songArray); } ########################### ########################### #pass in band name and then get all the albums for that band #take each album and pass it into getSongs and collect the returned strings #looks at 'words' of size 1 at a time (a single char) ########################### sub createSongHashMono{ my $inputBandName = shift(@_); my $bandNodes = $doc->getElementsByTagName ("band"); my $n = $bandNodes->getLength; my $i; my $bandName; my $albumNodes; my $nn = 0; my $x; my $albumName; for ($i = 0; $i < $n; $i++) { my $bandNode = $bandNodes->item ($i); if(lc($bandNode->getNodeName()) eq "band"){ $bandName = $bandNode->getAttributeNode("name"); $bandName = $bandName->getValue; #if the name matches what was passed in if(lc($bandName) eq lc($inputBandName)){ #we now match what was passed in - now find all the album nodes $albumNodes = $bandNode->getChildNodes(); $nn = $albumNodes->getLength(); for($x = 0;$x < $nn; $x++){ $albumNode = $albumNodes->item($x); if(lc($albumNode->getNodeName()) eq 'album'){ $albumName = $albumNode->getAttributeNode("name")->getValue(); $allLyrics .= ' '.getSongs($albumName); } } } } } #now take $allLyrics and split it into an array @allLyricsArray = split('', $allLyrics); #iterate the array and fill a hash, looking at the $_ and the one to the right for($x = 0; $x < $#allLyricsArray; $x++){ #make sure that the $pos2 isn't gonna be out of the array if($x+1 < $#allLyricsArray){ $pos1 = $allLyricsArray[$x]; $pos2 = $allLyricsArray[$x+1]; } else{ $pos1 = $allLyricsArray[$x]; $pos2 = '**NULL**';#end of array, so this one won't be charted } $mainHash{$pos1}{$pos2}++; } return %mainHash; } ########################### ########################### #pass in band name and then get all the albums for that band #take each album and pass it into getSongs and collect the returned strings #looks at 'words' of size 4 at a time ########################### sub createSongHashQuad{ my $inputBandName = shift(@_); my $bandNodes = $doc->getElementsByTagName ("band"); my $n = $bandNodes->getLength; my $i; my $bandName; my $albumNodes; my $nn; my $x; my $albumName; for ($i = 0; $i < $n; $i++) { $bandNode = $bandNodes->item ($i); if(lc($bandNode->getNodeName()) eq "band"){ my $bandName = $bandNode->getAttributeNode("name"); $bandName = $bandName->getValue; #if the name matches what was passed in if(lc($bandName) eq lc($inputBandName)){ #we now match what was passed in - now find all the album nodes $albumNodes = $bandNode->getChildNodes(); $nn = $albumNodes->getLength(); for($x = 0;$x < $nn; $x++){ $albumNode = $albumNodes->item($x); if(lc($albumNode->getNodeName()) eq 'album'){ $albumName = $albumNode->getAttributeNode("name")->getValue(); $allLyrics .= ' '.getSongs($albumName); } } } } } $allLyrics =~ tr/[]()\"//d; #now take $allLyrics and split it into an array @allLyricsArray = split('', $allLyrics); #iterate the array and fill a hash, looking at the $_ and the one to the right for($x = 0; $x < $#allLyricsArray; $x++){ #make sure that the $pos2 isn't gonna be out of the array if($x+7 <= $#allLyricsArray){ $pos1 = $allLyricsArray[$x].$allLyricsArray[$x+1].$allLyricsArray[$x+2].$allLyricsArray[$x+3]; $pos2 = $allLyricsArray[$x+4].$allLyricsArray[$x+5].$allLyricsArray[$x+6].$allLyricsArray[$x+7]; $mainHash{$pos1}{$pos2}++; } } return %mainHash; } ########################### ########################### #pass in band name and then get all the albums for that band #take each album and pass it into getSongs and collect the returned strings #looks at 'words' of size 5 at a time ########################### sub createSongHashPent{ my $inputBandName = shift(@_); my $bandNodes = $doc->getElementsByTagName ("band"); my $n = $bandNodes->getLength; my $i; my $bandNode; my $bandName; my $albumNodes; my $nn = 0; my $x = 0; my $albumName; for ($i = 0; $i < $n; $i++) { $bandNode = $bandNodes->item ($i); if(lc($bandNode->getNodeName()) eq "band"){ $bandName = $bandNode->getAttributeNode("name"); $bandName = $bandName->getValue; #if the name matches what was passed in if(lc($bandName) eq lc($inputBandName)){ #we now match what was passed in - now find all the album nodes $albumNodes = $bandNode->getChildNodes(); $nn = $albumNodes->getLength(); for($x = 0;$x < $nn; $x++){ $albumNode = $albumNodes->item($x); if(lc($albumNode->getNodeName()) eq 'album'){ $albumName = $albumNode->getAttributeNode("name")->getValue(); $allLyrics .= ' '.getSongs($albumName); } } } } } $allLyrics =~ tr/[]()\"//d; #now take $allLyrics and split it into an array @allLyricsArray = split('', $allLyrics); #iterate the array and fill a hash, looking at the $_ and the one to the right for($x = 0; $x < $#allLyricsArray; $x++){ #make sure that the $pos2 isn't gonna be out of the array if($x+9 <= $#allLyricsArray){ $pos1 = $allLyricsArray[$x].$allLyricsArray[$x+1].$allLyricsArray[$x+2].$allLyricsArray[$x+3].$allLyricsArray[$x+4]; $pos2 = $allLyricsArray[$x+5].$allLyricsArray[$x+6].$allLyricsArray[$x+7].$allLyricsArray[$x+8].$allLyricsArray[$x+9]; $mainHash{$pos1}{$pos2}++; } } return %mainHash; } ########################### ########################### #pass in band name and then get all the albums for that band #take each album and pass it into getSongs and collect the returned strings #looks at 'words' of size 3 at a time ########################### sub createSongHashTri{ my $inputBandName = shift(@_); my $bandNodes = $doc->getElementsByTagName ("band"); my $n = $bandNodes->getLength; my $i = 0; my $bandName; my $albumNodes; my $nn = 0; my $x = 0; my $albumName; for ($i = 0; $i < $n; $i++) { my $bandNode = $bandNodes->item ($i); if(lc($bandNode->getNodeName()) eq "band"){ $bandName = $bandNode->getAttributeNode("name"); $bandName = $bandName->getValue; #if the name matches what was passed in if(lc($bandName) eq lc($inputBandName)){ #we now match what was passed in - now find all the album nodes $albumNodes = $bandNode->getChildNodes(); $nn = $albumNodes->getLength(); for($x = 0;$x < $nn; $x++){ $albumNode = $albumNodes->item($x); if(lc($albumNode->getNodeName()) eq 'album'){ $albumName = $albumNode->getAttributeNode("name")->getValue(); $allLyrics .= ' '.getSongs($albumName); } } } } } $allLyrics =~ tr/[]()\"//d; #now take $allLyrics and split it into an array @allLyricsArray = split('', $allLyrics); #iterate the array and fill a hash, looking at the $_ and the one to the right for($x = 0; $x < $#allLyricsArray; $x++){ #make sure that the $pos2 isn't gonna be out of the array if($x+5 <= $#allLyricsArray){ $pos1 = $allLyricsArray[$x].$allLyricsArray[$x+1].$allLyricsArray[$x+2]; $pos2 = $allLyricsArray[$x+3].$allLyricsArray[$x+4].$allLyricsArray[$x+5]; $mainHash{$pos1}{$pos2}++; } } return %mainHash; } ########################### ########################### #pass in band name and then get all the albums for that band #take each album and pass it into getSongs and collect the returned strings #looks at 'words' of size 2 at a time ########################### sub createSongHashDuo{ my $inputBandName = shift(@_); my $bandNodes = $doc->getElementsByTagName ("band"); my $n = $bandNodes->getLength; my $i = 0; my $bandNode; my $bandName; my $albumNodes; my $nn = 0; my $x = 0; my $albumName; for ($i = 0; $i < $n; $i++) { $bandNode = $bandNodes->item ($i); if(lc($bandNode->getNodeName()) eq "band"){ $bandName = $bandNode->getAttributeNode("name"); $bandName = $bandName->getValue; #if the name matches what was passed in if(lc($bandName) eq lc($inputBandName)){ #we now match what was passed in - now find all the album nodes $albumNodes = $bandNode->getChildNodes(); $nn = $albumNodes->getLength(); for($x = 0;$x < $nn; $x++){ $albumNode = $albumNodes->item($x); if(lc($albumNode->getNodeName()) eq 'album'){ $albumName = $albumNode->getAttributeNode("name")->getValue(); $allLyrics .= ' '.getSongs($albumName); } } } } } #now take $allLyrics and split it into an array @allLyricsArray = split('', $allLyrics); #iterate the array and fill a hash, looking at the $_ and the one to the right for($x = 0; $x < $#allLyricsArray; $x++){ #make sure that the $pos2 isn't gonna be out of the array if($x+3 < $#allLyricsArray){ $pos1 = $allLyricsArray[$x].$allLyricsArray[$x+1]; $pos2 = $allLyricsArray[$x+2].$allLyricsArray[$x+3]; $mainHash{$pos1}{$pos2}++; } } return %mainHash; } ########################### ########################### #from Perl Cookbook 2.10 #take in a hash - convert the values to percentages, and then return that hash ########################### sub weight_to_dist { my %weights = @_; my %dist = (); my $total = 0; my ($key, $weight); local $_; foreach (values %weights) { $total += $_; } while ( ($key, $weight) = each %weights ) { $dist{$key} = $weight/$total; } return %dist; } ########################### ########################### #from Perl Cookbook 2.10 #take in a hash and via a weighted random, pick one of the keys based on the value and return it ########################### sub weighted_rand { my %dist = @_; my ($key, $weight); my $rand; while (1) { # to avoid floating point inaccuracies $rand = rand; while ( ($key, $weight) = each %dist ) { return $key if ($rand -= $weight) < 0; } } } ########################### ########################### #randomly pick and return a starting letter ########################### sub startLetter{ my $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; my $startLetter = substr($alphabet, int(rand(26)), 1); return $startLetter; } ########################### ########################### #randomly pick a key from the songsHash ########################### sub randomKeyFromFirstHash{ return ((keys %songsHash)[int rand keys %songsHash]); } ########################### ########################### #main ########################### print '
';


#create the frequency hash
#%songsHash = createSongHashMono('radiohead');#not very good
%songsHash = createSongHashQuad('radiohead');#very good
#%songsHash = createSongHashPent('radiohead');#good, but tends to reproduce exact lyrics from songs
#%songsHash = createSongHashTri('radiohead');#okay, but not so great
#%songsHash = createSongHashDuo('radiohead');#not very good

#randomly pick a spot in the hash, then check to see if the first letter is a cap letter
#if it is, then carry on, if not, pick again
$fail = 0;
while($fail < 1){
    $start = randomKeyFromFirstHash();
    #if the first position is a capital letter, then cool, 
    #try to ignore symbols, specifically '[' and ']' since I know they are in there.
    #newline is okay 
    if(ord($start) > 64 && ord($start) < 91){
        $fail = 1;    
    }
}
#take the start letter and get rolling...
print $s = $start;
$lineCount = 0;
#count the newilnes ('\n') and for each one
while($lineCount < $maxLines){
    %tempHash = weight_to_dist(%{$songsHash{$s}});
    print $s = weighted_rand(%tempHash);
    #if it contains a newline, then increment the count
    if(index($s, "\n")){
    #if($s eq '\n'){
        $lineCount++;
       # print '*';
    }
}


print '
'; ########################### # Avoid memory leaks - cleanup circular references for garbage collection $doc->dispose;