Perl: финальная строка вывода в циклическом выводе дважды - PullRequest
0 голосов
/ 11 ноября 2018

Я пытаюсь написать очень простой скрипт, который берет два слова из STDIN и выводит TRUE, если они анаграммы, и FALSE, если нет. Моя главная проблема заключается в том, что если два слова не являются анаграммами (это последний оператор «else» в скрипте), результат будет выглядеть так:

Извините, это не пара анаграмм Извините, это не пара анаграмм

где я просто хочу:

Извините, это не пара анаграмм

Другие, более мелкие проблемы для особо щедрых:

  • Я знаю, что значения FALSE для Perl, но я не могу заставить скрипт напечатать FALSE, например, установив переменную в '' или 0 и т. Д. Или сказав "return" ". В идеале мне вообще не нужно было бы вставлять «print TRUE / FALSE» в скрипт.
  • Я вставил последний оператор elsif в сценарий, чтобы посмотреть, не повлияет ли это на проблему печати дважды. Это не так, и теперь мне любопытно, почему мое выражение m // не работает. Предполагается найти пары, которые идентичны, за исключением того, что у одного больше пробела, чем у другого.

Вот сценарий! Я извиняюсь, что это так долго - опять проблема в самом конце с последним утверждением "еще". Большое спасибо !!!

#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.\n\nType your first word or phrase, then hit Enter.\n\n";

$aWord = <STDIN>;
chomp $aWord;

print "\n\nThanks! Now type your second word or phrase and hit Enter.\n\n";

$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 "\n\nFALSE: Your phrases are identical!\n\n";
    }

    #"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 "\n\nTRUE: @$sortWords[0] and @$sortWords[1] are anagrams!\n\n";
    }

    #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 "\n\FALSE: @$sortWords[0] and @$sortWords[-1] are NOT anagrams. Spaces are characters, too!\n\n";
    }

    #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 pair\n";    
    }
}

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Мой окончательный ответ, большое спасибо Дэйву и @zdim! Я так счастлив, что мог умереть.

#!/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 "\n\nFALSE: 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 "\n\nTRUE: Your two terms are anagrams!";
}
else {
    say "\n\nFALSE: Your two terms are not acronyms.";
}
0 голосов
/ 11 ноября 2018

Полезно распечатать содержимое %anaHash после того, как вы закончили его строить, но перед тем, как приступить к его проверке. Используя слова "foo" и "bar", я получаю этот результат, используя Data :: Dumper .

$VAR1 = {
          'abr' => [
                     'bar'
                   ],
          'foo' => [
                     'foo'
                   ]
        };

Итак, хеш имеет два ключа. И когда вы зациклите все ключи в хэше, вы получите сообщение дважды (один раз для каждого ключа).

Я не совсем уверен, для чего здесь хеш. Я не думаю, что это необходимо. Я думаю, что вам нужно:

  1. Читать в двух словах
  2. Преобразование слов в канонический формат
  3. Проверьте, совпадают ли две строки

Упрощенно, ваш код будет выглядеть так:

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