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)









share|improve this question





















  • 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










  • 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










  • 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















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)









share|improve this question





















  • 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










  • 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










  • 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













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)









share|improve this question













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)






perl output repeating






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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 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











  • @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










  • 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











  • @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













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:



  1. Read in the two words

  2. Convert the words to a canonical format

  3. 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






share|improve this answer






















  • 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

















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.";






share|improve this answer






















  • $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 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










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















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

























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:



  1. Read in the two words

  2. Convert the words to a canonical format

  3. 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






share|improve this answer






















  • 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














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:



  1. Read in the two words

  2. Convert the words to a canonical format

  3. 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






share|improve this answer






















  • 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












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:



  1. Read in the two words

  2. Convert the words to a canonical format

  3. 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






share|improve this answer














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:



  1. Read in the two words

  2. Convert the words to a canonical format

  3. 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







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 9:18

























answered Nov 11 at 8:51









Dave Cross

45.7k33877




45.7k33877











  • 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










  • @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












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.";






share|improve this answer






















  • $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 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














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.";






share|improve this answer






















  • $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 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












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.";






share|improve this answer














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.";







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 14:59









Dave Cross

45.7k33877




45.7k33877










answered Nov 11 at 10:13









ScarletRoxanne

84




84











  • $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 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










  • 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

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














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





















































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 to read a connectionString WITH PROVIDER in .NET Core?

In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

Museum of Modern and Contemporary Art of Trento and Rovereto