Perl: Final Output Line in Foreach Loop Prints Twice
up vote
1
down vote
favorite
I'm trying to write a very simple script that takes two words from STDIN and outputs TRUE if they're anagrams and FALSE if not. My main issue is that if the two words aren't anagrams (this is the final "else" statement in the script), the output looks like:
Sorry, that's not an anagram pair
Sorry, that's not an anagram pair
where I just want:
Sorry, that's not an anagram pair
Other, more minor issues for the especially generous:
- I know what the FALSE values are for Perl, but I can't get the script to print FALSE by, for example, setting a variable to '' or 0, etc. or saying "return ''". Ideally, I wouldn't have to put "print TRUE/FALSE" in the script at all.
- I put in the last elsif statement in the script to see if it would affect the printing twice problem. It didn't, and now I'm curious why my m// expression doesn't work. It's supposed to find pairs that are identical except that one has more whitespace than the other.
Here's the script! I'm sorry it's so long - again, the problem is at the very end with the final "else" statement. Many thanks!!!
#To Run: Type start.pl on the command line.
#The script should prompt you to enter a word or phrase.
#Once you've done that, it'll prompt you for another one.
#Then you will be told if the two terms are anagrams or not.
#!/usr/bin/perl -w
use strict;
#I have to use this to make STDIN work. IDK why.
$|=1;
#variables
my $aWord;
my $bWord;
my $word;
my $sortWord;
my $sortWords;
my @words;
my %anaHash;
print "nReady to play the anagram game? Excellent.nnType your first word or phrase, then hit Enter.nn";
$aWord = <STDIN>;
chomp $aWord;
print "nnThanks! Now type your second word or phrase and hit Enter.nn";
$bWord = <STDIN>;
chomp $bWord;
#This foreach loop performs the following tasks:
#1. Pushes the two words from STDIN into an array (unsure if this is really necessary)
#2. lowercases everything and removes all characters except for letters & spaces
#3. splits both words into characters, sorts them alphabetically, then joins the sorted letters into a single "word"
#4.pushes the array into a hash
@words = ($bWord, $aWord);
foreach $word (@words) {
$word =~ tr/A-Z/a-z/;
$word =~ s/[^a-z ]//ig;
$sortWord = join '', sort(split(//, $word));
push @{$anaHash{$sortWord}}, $word;
}
#This foreach loop tries to determine if the word pairs are anagrams or not.
foreach $sortWords (values %anaHash) {
#"if you see the same word twice AND the input was two identical words:"
if (1 < @$sortWords &&
@$sortWords[0] eq @$sortWords[1]) {
print "nnFALSE: Your phrases are identical!nn";
}
#"if you see the same word twice AND the input was two different words (i.e. a real anagram):"
elsif (1 < @$sortWords &&
@$sortWords[0] ne @$sortWords[1]) {
print "nnTRUE: @$sortWords[0] and @$sortWords[1] are anagrams!nn";
}
#this is a failed attempt to identify pairs that are identical except one has extra spaces. Right now, this fails and falls into the "else" category below.
elsif (@$sortWords[0] =~ m/ +@$sortWords[-1]/ ||
@$sortWords[-1] =~ m/ +@$sortWords[0]/) {
print "nFALSE: @$sortWords[0] and @$sortWords[-1] are NOT anagrams. Spaces are characters, too!nn";
}
#This is supposed to identify anything that's not an acronym. But the output prints twice! It's maddening!!!!
else {
print "Sorry, that's not an anagram pairn";
}
}
perl output repeating
|
show 8 more comments
up vote
1
down vote
favorite
I'm trying to write a very simple script that takes two words from STDIN and outputs TRUE if they're anagrams and FALSE if not. My main issue is that if the two words aren't anagrams (this is the final "else" statement in the script), the output looks like:
Sorry, that's not an anagram pair
Sorry, that's not an anagram pair
where I just want:
Sorry, that's not an anagram pair
Other, more minor issues for the especially generous:
- I know what the FALSE values are for Perl, but I can't get the script to print FALSE by, for example, setting a variable to '' or 0, etc. or saying "return ''". Ideally, I wouldn't have to put "print TRUE/FALSE" in the script at all.
- I put in the last elsif statement in the script to see if it would affect the printing twice problem. It didn't, and now I'm curious why my m// expression doesn't work. It's supposed to find pairs that are identical except that one has more whitespace than the other.
Here's the script! I'm sorry it's so long - again, the problem is at the very end with the final "else" statement. Many thanks!!!
#To Run: Type start.pl on the command line.
#The script should prompt you to enter a word or phrase.
#Once you've done that, it'll prompt you for another one.
#Then you will be told if the two terms are anagrams or not.
#!/usr/bin/perl -w
use strict;
#I have to use this to make STDIN work. IDK why.
$|=1;
#variables
my $aWord;
my $bWord;
my $word;
my $sortWord;
my $sortWords;
my @words;
my %anaHash;
print "nReady to play the anagram game? Excellent.nnType your first word or phrase, then hit Enter.nn";
$aWord = <STDIN>;
chomp $aWord;
print "nnThanks! Now type your second word or phrase and hit Enter.nn";
$bWord = <STDIN>;
chomp $bWord;
#This foreach loop performs the following tasks:
#1. Pushes the two words from STDIN into an array (unsure if this is really necessary)
#2. lowercases everything and removes all characters except for letters & spaces
#3. splits both words into characters, sorts them alphabetically, then joins the sorted letters into a single "word"
#4.pushes the array into a hash
@words = ($bWord, $aWord);
foreach $word (@words) {
$word =~ tr/A-Z/a-z/;
$word =~ s/[^a-z ]//ig;
$sortWord = join '', sort(split(//, $word));
push @{$anaHash{$sortWord}}, $word;
}
#This foreach loop tries to determine if the word pairs are anagrams or not.
foreach $sortWords (values %anaHash) {
#"if you see the same word twice AND the input was two identical words:"
if (1 < @$sortWords &&
@$sortWords[0] eq @$sortWords[1]) {
print "nnFALSE: Your phrases are identical!nn";
}
#"if you see the same word twice AND the input was two different words (i.e. a real anagram):"
elsif (1 < @$sortWords &&
@$sortWords[0] ne @$sortWords[1]) {
print "nnTRUE: @$sortWords[0] and @$sortWords[1] are anagrams!nn";
}
#this is a failed attempt to identify pairs that are identical except one has extra spaces. Right now, this fails and falls into the "else" category below.
elsif (@$sortWords[0] =~ m/ +@$sortWords[-1]/ ||
@$sortWords[-1] =~ m/ +@$sortWords[0]/) {
print "nFALSE: @$sortWords[0] and @$sortWords[-1] are NOT anagrams. Spaces are characters, too!nn";
}
#This is supposed to identify anything that's not an acronym. But the output prints twice! It's maddening!!!!
else {
print "Sorry, that's not an anagram pairn";
}
}
perl output repeating
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
When you supply different words your hash will have two keys (one for each$sortWord
) and each key will have only one value in its arrayref. So bothif
and the firstelsif
are false; in the lastelsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in theelse
, for both words.
– zdim
Nov 11 at 7:58
There is no "FALSE" or such value in Perl; if you want that you print it. (There are0
and empty string''
andundef
. If you attempt to print a variable which isundef
you'll get a warning.) I don't see how a script would know what to print.
– zdim
Nov 11 at 8:05
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15
|
show 8 more comments
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I'm trying to write a very simple script that takes two words from STDIN and outputs TRUE if they're anagrams and FALSE if not. My main issue is that if the two words aren't anagrams (this is the final "else" statement in the script), the output looks like:
Sorry, that's not an anagram pair
Sorry, that's not an anagram pair
where I just want:
Sorry, that's not an anagram pair
Other, more minor issues for the especially generous:
- I know what the FALSE values are for Perl, but I can't get the script to print FALSE by, for example, setting a variable to '' or 0, etc. or saying "return ''". Ideally, I wouldn't have to put "print TRUE/FALSE" in the script at all.
- I put in the last elsif statement in the script to see if it would affect the printing twice problem. It didn't, and now I'm curious why my m// expression doesn't work. It's supposed to find pairs that are identical except that one has more whitespace than the other.
Here's the script! I'm sorry it's so long - again, the problem is at the very end with the final "else" statement. Many thanks!!!
#To Run: Type start.pl on the command line.
#The script should prompt you to enter a word or phrase.
#Once you've done that, it'll prompt you for another one.
#Then you will be told if the two terms are anagrams or not.
#!/usr/bin/perl -w
use strict;
#I have to use this to make STDIN work. IDK why.
$|=1;
#variables
my $aWord;
my $bWord;
my $word;
my $sortWord;
my $sortWords;
my @words;
my %anaHash;
print "nReady to play the anagram game? Excellent.nnType your first word or phrase, then hit Enter.nn";
$aWord = <STDIN>;
chomp $aWord;
print "nnThanks! Now type your second word or phrase and hit Enter.nn";
$bWord = <STDIN>;
chomp $bWord;
#This foreach loop performs the following tasks:
#1. Pushes the two words from STDIN into an array (unsure if this is really necessary)
#2. lowercases everything and removes all characters except for letters & spaces
#3. splits both words into characters, sorts them alphabetically, then joins the sorted letters into a single "word"
#4.pushes the array into a hash
@words = ($bWord, $aWord);
foreach $word (@words) {
$word =~ tr/A-Z/a-z/;
$word =~ s/[^a-z ]//ig;
$sortWord = join '', sort(split(//, $word));
push @{$anaHash{$sortWord}}, $word;
}
#This foreach loop tries to determine if the word pairs are anagrams or not.
foreach $sortWords (values %anaHash) {
#"if you see the same word twice AND the input was two identical words:"
if (1 < @$sortWords &&
@$sortWords[0] eq @$sortWords[1]) {
print "nnFALSE: Your phrases are identical!nn";
}
#"if you see the same word twice AND the input was two different words (i.e. a real anagram):"
elsif (1 < @$sortWords &&
@$sortWords[0] ne @$sortWords[1]) {
print "nnTRUE: @$sortWords[0] and @$sortWords[1] are anagrams!nn";
}
#this is a failed attempt to identify pairs that are identical except one has extra spaces. Right now, this fails and falls into the "else" category below.
elsif (@$sortWords[0] =~ m/ +@$sortWords[-1]/ ||
@$sortWords[-1] =~ m/ +@$sortWords[0]/) {
print "nFALSE: @$sortWords[0] and @$sortWords[-1] are NOT anagrams. Spaces are characters, too!nn";
}
#This is supposed to identify anything that's not an acronym. But the output prints twice! It's maddening!!!!
else {
print "Sorry, that's not an anagram pairn";
}
}
perl output repeating
I'm trying to write a very simple script that takes two words from STDIN and outputs TRUE if they're anagrams and FALSE if not. My main issue is that if the two words aren't anagrams (this is the final "else" statement in the script), the output looks like:
Sorry, that's not an anagram pair
Sorry, that's not an anagram pair
where I just want:
Sorry, that's not an anagram pair
Other, more minor issues for the especially generous:
- I know what the FALSE values are for Perl, but I can't get the script to print FALSE by, for example, setting a variable to '' or 0, etc. or saying "return ''". Ideally, I wouldn't have to put "print TRUE/FALSE" in the script at all.
- I put in the last elsif statement in the script to see if it would affect the printing twice problem. It didn't, and now I'm curious why my m// expression doesn't work. It's supposed to find pairs that are identical except that one has more whitespace than the other.
Here's the script! I'm sorry it's so long - again, the problem is at the very end with the final "else" statement. Many thanks!!!
#To Run: Type start.pl on the command line.
#The script should prompt you to enter a word or phrase.
#Once you've done that, it'll prompt you for another one.
#Then you will be told if the two terms are anagrams or not.
#!/usr/bin/perl -w
use strict;
#I have to use this to make STDIN work. IDK why.
$|=1;
#variables
my $aWord;
my $bWord;
my $word;
my $sortWord;
my $sortWords;
my @words;
my %anaHash;
print "nReady to play the anagram game? Excellent.nnType your first word or phrase, then hit Enter.nn";
$aWord = <STDIN>;
chomp $aWord;
print "nnThanks! Now type your second word or phrase and hit Enter.nn";
$bWord = <STDIN>;
chomp $bWord;
#This foreach loop performs the following tasks:
#1. Pushes the two words from STDIN into an array (unsure if this is really necessary)
#2. lowercases everything and removes all characters except for letters & spaces
#3. splits both words into characters, sorts them alphabetically, then joins the sorted letters into a single "word"
#4.pushes the array into a hash
@words = ($bWord, $aWord);
foreach $word (@words) {
$word =~ tr/A-Z/a-z/;
$word =~ s/[^a-z ]//ig;
$sortWord = join '', sort(split(//, $word));
push @{$anaHash{$sortWord}}, $word;
}
#This foreach loop tries to determine if the word pairs are anagrams or not.
foreach $sortWords (values %anaHash) {
#"if you see the same word twice AND the input was two identical words:"
if (1 < @$sortWords &&
@$sortWords[0] eq @$sortWords[1]) {
print "nnFALSE: Your phrases are identical!nn";
}
#"if you see the same word twice AND the input was two different words (i.e. a real anagram):"
elsif (1 < @$sortWords &&
@$sortWords[0] ne @$sortWords[1]) {
print "nnTRUE: @$sortWords[0] and @$sortWords[1] are anagrams!nn";
}
#this is a failed attempt to identify pairs that are identical except one has extra spaces. Right now, this fails and falls into the "else" category below.
elsif (@$sortWords[0] =~ m/ +@$sortWords[-1]/ ||
@$sortWords[-1] =~ m/ +@$sortWords[0]/) {
print "nFALSE: @$sortWords[0] and @$sortWords[-1] are NOT anagrams. Spaces are characters, too!nn";
}
#This is supposed to identify anything that's not an acronym. But the output prints twice! It's maddening!!!!
else {
print "Sorry, that's not an anagram pairn";
}
}
perl output repeating
perl output repeating
asked Nov 11 at 7:42
ScarletRoxanne
84
84
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
When you supply different words your hash will have two keys (one for each$sortWord
) and each key will have only one value in its arrayref. So bothif
and the firstelsif
are false; in the lastelsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in theelse
, for both words.
– zdim
Nov 11 at 7:58
There is no "FALSE" or such value in Perl; if you want that you print it. (There are0
and empty string''
andundef
. If you attempt to print a variable which isundef
you'll get a warning.) I don't see how a script would know what to print.
– zdim
Nov 11 at 8:05
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15
|
show 8 more comments
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
When you supply different words your hash will have two keys (one for each$sortWord
) and each key will have only one value in its arrayref. So bothif
and the firstelsif
are false; in the lastelsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in theelse
, for both words.
– zdim
Nov 11 at 7:58
There is no "FALSE" or such value in Perl; if you want that you print it. (There are0
and empty string''
andundef
. If you attempt to print a variable which isundef
you'll get a warning.) I don't see how a script would know what to print.
– zdim
Nov 11 at 8:05
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
When you supply different words your hash will have two keys (one for each
$sortWord
) and each key will have only one value in its arrayref. So both if
and the first elsif
are false; in the last elsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in the else
, for both words.– zdim
Nov 11 at 7:58
When you supply different words your hash will have two keys (one for each
$sortWord
) and each key will have only one value in its arrayref. So both if
and the first elsif
are false; in the last elsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in the else
, for both words.– zdim
Nov 11 at 7:58
There is no "FALSE" or such value in Perl; if you want that you print it. (There are
0
and empty string ''
and undef
. If you attempt to print a variable which is undef
you'll get a warning.) I don't see how a script would know what to print.– zdim
Nov 11 at 8:05
There is no "FALSE" or such value in Perl; if you want that you print it. (There are
0
and empty string ''
and undef
. If you attempt to print a variable which is undef
you'll get a warning.) I don't see how a script would know what to print.– zdim
Nov 11 at 8:05
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15
|
show 8 more comments
2 Answers
2
active
oldest
votes
up vote
0
down vote
accepted
It's useful to print out the contents of %anaHash
after you've finished building it, but before you start examining it. Using the words "foo" and "bar", I get this result using Data::Dumper.
$VAR1 = {
'abr' => [
'bar'
],
'foo' => [
'foo'
]
};
So the hash has two keys. And as you loop round all of the keys in the hash, you'll get the message twice (once for each key).
I'm not really sure what the hash is for here. I don't think it's necessary. I think that you need to:
- Read in the two words
- Convert the words to a canonical format
- Check if the two strings are the same
Simplified, your code would look like this:
print 'Give me a word: ';
chomp(my $word1 = <STDIN>);
print 'Give me another word: ';
chomp(my $word2 = <STDIN>);
# convert to lower case
$word1 = lc $word1;
$word2 = lc $word2;
# remove non-letters
$word1 =~ s/[^a-z]//g;
$word2 =~ s/[^a-z]//g;
# sort letters
$word1 = join '', sort split //, $word1;
$word2 = join '', sort split //, $word2;
if ($word1 eq $word2) {
# you have an anagram
} else {
# you don't
}
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
add a comment |
up vote
0
down vote
My final answer, thanks so much to Dave and @zdim! I'm so happy I could die.
#!/usr/bin/perl -w
use strict;
use feature qw(say);
#I have to use this to make STDIN work. IDK why.
$|=1;
#declare variables below
print "First word?n";
$aWord = <STDIN>;
chomp $aWord;
print "Second word?n";
$bWord = <STDIN>;
chomp $bWord;
#clean up input
$aWord =~ tr/A-Z/a-z/;
$bWord =~ tr/A-Z/a-z/;
$aWord =~ s/[^a-z ]//ig;
$bWord =~ s/[^a-z ]//ig;
#if the two inputs are identical, print FALSE and exit
if ($aWord eq $bWord) {
say "nnFALSE: Your phrases are identical!n";
exit;
}
#split each word by character, sort characters alphabetically, join characters
$aSortWord = join '', sort(split(//, $aWord));
$bSortWord = join '', sort(split(//, $bWord));
#if the sorted characters match, you have an anagram
#if not, you don't
if ($aSortWord eq $bSortWord) {
say "nnTRUE: Your two terms are anagrams!";
}
else {
say "nnFALSE: Your two terms are not acronyms.";
}
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to writelc $aWord
:-)
– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
accepted
It's useful to print out the contents of %anaHash
after you've finished building it, but before you start examining it. Using the words "foo" and "bar", I get this result using Data::Dumper.
$VAR1 = {
'abr' => [
'bar'
],
'foo' => [
'foo'
]
};
So the hash has two keys. And as you loop round all of the keys in the hash, you'll get the message twice (once for each key).
I'm not really sure what the hash is for here. I don't think it's necessary. I think that you need to:
- Read in the two words
- Convert the words to a canonical format
- Check if the two strings are the same
Simplified, your code would look like this:
print 'Give me a word: ';
chomp(my $word1 = <STDIN>);
print 'Give me another word: ';
chomp(my $word2 = <STDIN>);
# convert to lower case
$word1 = lc $word1;
$word2 = lc $word2;
# remove non-letters
$word1 =~ s/[^a-z]//g;
$word2 =~ s/[^a-z]//g;
# sort letters
$word1 = join '', sort split //, $word1;
$word2 = join '', sort split //, $word2;
if ($word1 eq $word2) {
# you have an anagram
} else {
# you don't
}
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
add a comment |
up vote
0
down vote
accepted
It's useful to print out the contents of %anaHash
after you've finished building it, but before you start examining it. Using the words "foo" and "bar", I get this result using Data::Dumper.
$VAR1 = {
'abr' => [
'bar'
],
'foo' => [
'foo'
]
};
So the hash has two keys. And as you loop round all of the keys in the hash, you'll get the message twice (once for each key).
I'm not really sure what the hash is for here. I don't think it's necessary. I think that you need to:
- Read in the two words
- Convert the words to a canonical format
- Check if the two strings are the same
Simplified, your code would look like this:
print 'Give me a word: ';
chomp(my $word1 = <STDIN>);
print 'Give me another word: ';
chomp(my $word2 = <STDIN>);
# convert to lower case
$word1 = lc $word1;
$word2 = lc $word2;
# remove non-letters
$word1 =~ s/[^a-z]//g;
$word2 =~ s/[^a-z]//g;
# sort letters
$word1 = join '', sort split //, $word1;
$word2 = join '', sort split //, $word2;
if ($word1 eq $word2) {
# you have an anagram
} else {
# you don't
}
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
add a comment |
up vote
0
down vote
accepted
up vote
0
down vote
accepted
It's useful to print out the contents of %anaHash
after you've finished building it, but before you start examining it. Using the words "foo" and "bar", I get this result using Data::Dumper.
$VAR1 = {
'abr' => [
'bar'
],
'foo' => [
'foo'
]
};
So the hash has two keys. And as you loop round all of the keys in the hash, you'll get the message twice (once for each key).
I'm not really sure what the hash is for here. I don't think it's necessary. I think that you need to:
- Read in the two words
- Convert the words to a canonical format
- Check if the two strings are the same
Simplified, your code would look like this:
print 'Give me a word: ';
chomp(my $word1 = <STDIN>);
print 'Give me another word: ';
chomp(my $word2 = <STDIN>);
# convert to lower case
$word1 = lc $word1;
$word2 = lc $word2;
# remove non-letters
$word1 =~ s/[^a-z]//g;
$word2 =~ s/[^a-z]//g;
# sort letters
$word1 = join '', sort split //, $word1;
$word2 = join '', sort split //, $word2;
if ($word1 eq $word2) {
# you have an anagram
} else {
# you don't
}
It's useful to print out the contents of %anaHash
after you've finished building it, but before you start examining it. Using the words "foo" and "bar", I get this result using Data::Dumper.
$VAR1 = {
'abr' => [
'bar'
],
'foo' => [
'foo'
]
};
So the hash has two keys. And as you loop round all of the keys in the hash, you'll get the message twice (once for each key).
I'm not really sure what the hash is for here. I don't think it's necessary. I think that you need to:
- Read in the two words
- Convert the words to a canonical format
- Check if the two strings are the same
Simplified, your code would look like this:
print 'Give me a word: ';
chomp(my $word1 = <STDIN>);
print 'Give me another word: ';
chomp(my $word2 = <STDIN>);
# convert to lower case
$word1 = lc $word1;
$word2 = lc $word2;
# remove non-letters
$word1 =~ s/[^a-z]//g;
$word2 =~ s/[^a-z]//g;
# sort letters
$word1 = join '', sort split //, $word1;
$word2 = join '', sort split //, $word2;
if ($word1 eq $word2) {
# you have an anagram
} else {
# you don't
}
edited Nov 11 at 9:18
answered Nov 11 at 8:51
Dave Cross
45.6k23877
45.6k23877
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
add a comment |
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
thank you so much; I think you're right. I do feel that "yes" and "yes" shouldn't be anagrams, but maybe I can check after the clean-up and before the split/join. I'll let you know how it went in the morning!
– ScarletRoxanne
Nov 11 at 9:24
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
@Rebecca: Good point. I suggest checking for identical strings after converting to lower case.
– Dave Cross
Nov 11 at 9:27
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Dave, also, this will make "to, by" match "Toby" which I don't think is fair, either. :) Still though, I think you're correct.
– ScarletRoxanne
Nov 11 at 9:28
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
Sorry, babbling. All I need to do is add spaces after the [a-z]'s.
– ScarletRoxanne
Nov 11 at 9:30
add a comment |
up vote
0
down vote
My final answer, thanks so much to Dave and @zdim! I'm so happy I could die.
#!/usr/bin/perl -w
use strict;
use feature qw(say);
#I have to use this to make STDIN work. IDK why.
$|=1;
#declare variables below
print "First word?n";
$aWord = <STDIN>;
chomp $aWord;
print "Second word?n";
$bWord = <STDIN>;
chomp $bWord;
#clean up input
$aWord =~ tr/A-Z/a-z/;
$bWord =~ tr/A-Z/a-z/;
$aWord =~ s/[^a-z ]//ig;
$bWord =~ s/[^a-z ]//ig;
#if the two inputs are identical, print FALSE and exit
if ($aWord eq $bWord) {
say "nnFALSE: Your phrases are identical!n";
exit;
}
#split each word by character, sort characters alphabetically, join characters
$aSortWord = join '', sort(split(//, $aWord));
$bSortWord = join '', sort(split(//, $bWord));
#if the sorted characters match, you have an anagram
#if not, you don't
if ($aSortWord eq $bSortWord) {
say "nnTRUE: Your two terms are anagrams!";
}
else {
say "nnFALSE: Your two terms are not acronyms.";
}
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to writelc $aWord
:-)
– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
add a comment |
up vote
0
down vote
My final answer, thanks so much to Dave and @zdim! I'm so happy I could die.
#!/usr/bin/perl -w
use strict;
use feature qw(say);
#I have to use this to make STDIN work. IDK why.
$|=1;
#declare variables below
print "First word?n";
$aWord = <STDIN>;
chomp $aWord;
print "Second word?n";
$bWord = <STDIN>;
chomp $bWord;
#clean up input
$aWord =~ tr/A-Z/a-z/;
$bWord =~ tr/A-Z/a-z/;
$aWord =~ s/[^a-z ]//ig;
$bWord =~ s/[^a-z ]//ig;
#if the two inputs are identical, print FALSE and exit
if ($aWord eq $bWord) {
say "nnFALSE: Your phrases are identical!n";
exit;
}
#split each word by character, sort characters alphabetically, join characters
$aSortWord = join '', sort(split(//, $aWord));
$bSortWord = join '', sort(split(//, $bWord));
#if the sorted characters match, you have an anagram
#if not, you don't
if ($aSortWord eq $bSortWord) {
say "nnTRUE: Your two terms are anagrams!";
}
else {
say "nnFALSE: Your two terms are not acronyms.";
}
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to writelc $aWord
:-)
– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
add a comment |
up vote
0
down vote
up vote
0
down vote
My final answer, thanks so much to Dave and @zdim! I'm so happy I could die.
#!/usr/bin/perl -w
use strict;
use feature qw(say);
#I have to use this to make STDIN work. IDK why.
$|=1;
#declare variables below
print "First word?n";
$aWord = <STDIN>;
chomp $aWord;
print "Second word?n";
$bWord = <STDIN>;
chomp $bWord;
#clean up input
$aWord =~ tr/A-Z/a-z/;
$bWord =~ tr/A-Z/a-z/;
$aWord =~ s/[^a-z ]//ig;
$bWord =~ s/[^a-z ]//ig;
#if the two inputs are identical, print FALSE and exit
if ($aWord eq $bWord) {
say "nnFALSE: Your phrases are identical!n";
exit;
}
#split each word by character, sort characters alphabetically, join characters
$aSortWord = join '', sort(split(//, $aWord));
$bSortWord = join '', sort(split(//, $bWord));
#if the sorted characters match, you have an anagram
#if not, you don't
if ($aSortWord eq $bSortWord) {
say "nnTRUE: Your two terms are anagrams!";
}
else {
say "nnFALSE: Your two terms are not acronyms.";
}
My final answer, thanks so much to Dave and @zdim! I'm so happy I could die.
#!/usr/bin/perl -w
use strict;
use feature qw(say);
#I have to use this to make STDIN work. IDK why.
$|=1;
#declare variables below
print "First word?n";
$aWord = <STDIN>;
chomp $aWord;
print "Second word?n";
$bWord = <STDIN>;
chomp $bWord;
#clean up input
$aWord =~ tr/A-Z/a-z/;
$bWord =~ tr/A-Z/a-z/;
$aWord =~ s/[^a-z ]//ig;
$bWord =~ s/[^a-z ]//ig;
#if the two inputs are identical, print FALSE and exit
if ($aWord eq $bWord) {
say "nnFALSE: Your phrases are identical!n";
exit;
}
#split each word by character, sort characters alphabetically, join characters
$aSortWord = join '', sort(split(//, $aWord));
$bSortWord = join '', sort(split(//, $bWord));
#if the sorted characters match, you have an anagram
#if not, you don't
if ($aSortWord eq $bSortWord) {
say "nnTRUE: Your two terms are anagrams!";
}
else {
say "nnFALSE: Your two terms are not acronyms.";
}
edited Nov 11 at 14:59
Dave Cross
45.6k23877
45.6k23877
answered Nov 11 at 10:13
ScarletRoxanne
84
84
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to writelc $aWord
:-)
– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
add a comment |
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to writelc $aWord
:-)
– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to write lc $aWord
:-)– Dave Cross
Nov 11 at 16:06
$aWord =~ tr/A-Z/a-z/
is a rather over-complicated way to write lc $aWord
:-)– Dave Cross
Nov 11 at 16:06
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I know. It's just a habit. :)
– ScarletRoxanne
Nov 12 at 16:28
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
I usually have long lists of s// and m// and I like seeing them all together. If that makes sense.
– ScarletRoxanne
Nov 12 at 16:30
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53246765%2fperl-final-output-line-in-foreach-loop-prints-twice%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
How many times does that last foreach loop run?
– Shawn
Nov 11 at 7:54
When you supply different words your hash will have two keys (one for each
$sortWord
) and each key will have only one value in its arrayref. So bothif
and the firstelsif
are false; in the lastelsif
you end up matching that one word to itself but with spaces -- it fails. So you wind up in theelse
, for both words.– zdim
Nov 11 at 7:58
There is no "FALSE" or such value in Perl; if you want that you print it. (There are
0
and empty string''
andundef
. If you attempt to print a variable which isundef
you'll get a warning.) I don't see how a script would know what to print.– zdim
Nov 11 at 8:05
@zdim, thanks so much, that's exactly what I figured was happening. Any suggestions on how to get it to NOT happen? Like saying "else { only look at one of the variables; print "blah blah"; }
– ScarletRoxanne
Nov 11 at 8:13
Oh, right: If the words are same or anagrams your hash will have one key, if they aren't it will have more than one key -- in which case you don't need this analysis. So check that first.
– zdim
Nov 11 at 8:15