I was getting into regular expressions a bit and discovered that Perl has some esoteric qualities that could lend itself to be a powerful tool in the fight against evil. As monks, it is our duty to use Perl as a force for good. Here is a quick and dirty script, with not much flexibility for now to allow automation, but it calculates an interesting number. :) Radagast
#!/usr/bin/perl # Have a little fun. Type a name, let the program extract the Roman # numerals in them, and add them up. The letter V was used instead of # U so that conversion will be done here. # # To verify this works, type CUTE PURPLE DINOSAUR to test it and the n +umber # output will be 666. $name = ""; $strLen = 0; $sum = 0; print "Enter name: "; while (<STDIN>) { chomp; $strLen = length $_; tr/a-z/A-Z/; tr/U/V/; @arr = split //; for ($i = 0; $i < $strLen; $i++) { if ($arr[$i] =~ /I|V|X|L|C|D|M/) { $sum += RtoD($arr[$i]); } } if ($sum == 666) { markOfTheBeast(); last; } else { print "The number is $sum...blessed be!\n"; } $sum = 0; print "Enter name: "; } sub RtoD { $X = shift; if ($X =~ /i|I/) { return 1; } elsif ($X =~ /v|V/) { return 5; } elsif ($X =~ /l|L/) { return 50; } elsif ($X =~ /c|C/) { return 100; } elsif ($X =~ /d|D/) { return 500; } elsif ($X =~ /m|M/) { return 1000; } else { return 0; } } sub markOfTheBeast { system "clear"; print <<END_OF_DAYS ********************************************************************* *YOU HAVE EXPOSED THE SIGN OF THE BEAST. PLEASE REDEEM YOUR GET OUT* * OF HELL FREE CARD AT THE NEAREST STARBUCKS OR PORTAL TO HELL TO * * AVOID THE ONCOMING APOCALYPSE. * ********************************************************************* END_OF_DAYS }
UPDATE: Sorry about the unwieldiness of the code. For example, I'd love to have combined the searches

Replies are listed 'Best First'.
Re: Perl as a Holy Weapon?
by Kanji (Parson) on Dec 02, 2000 at 20:51 UTC

    ++ for spreading the truth about Barney! ;)

    ... but why do you search for both upper and lowers in RtoD() when you're already made everything uppers with tr/a-z/A-Z/?

    As for the unweildiness and uncombined searches, you could simplify the script a lot by using a hash instead of a regexp:-

    #!/usr/bin/perl -w use strict; my %numeral = ( 'I' => 1, 'V' => 5, 'X' => 10, 'L' => 50, 'C' => 100, 'D' => 500, 'M' => 1000, ); print "Enter name: "; while ( chomp( my $phrase = <STDIN> ) ) { my $sum = 0; $phrase = uc($phrase); $phrase =~ tr(U)(V); for my $letter ( split // => $phrase ) { $sum += $numeral{$letter} || 0; } markOfTheBeast(), last if $sum == 666; print "The number is $sum ... blessed be!\n", "Enter name: "; } sub markOfTheBeast { print <<END_OF_DAYS; ********************************************************************* *YOU HAVE EXPOSED THE SIGN OF THE BEAST. PLEASE REDEEM YOUR GET OUT* * OF HELL FREE CARD AT THE NEAREST STARBUCKS OR PORTAL TO HELL TO * * AVOID THE ONCOMING APOCALYPSE. * ********************************************************************* END_OF_DAYS }

    However, if you did want to do that with regexps, you could combine them by keeping the hash and doing something like ...

    sub RtoD { # ... or uc(shift) to be paranoid. :-) my $n = shift || return 0; if ( $n =~ /([IVXCLMD])/ ) { return $numeral{$1} } else { return 0 } }

        --k.

      You could further simpify (and speed up) the code:
      for my $letter ( split // => $phrase ) { $sum += $numeral{$letter} || 0; }
      to just
      use List::Util qw(sum); # in the CPAN $sum = sum map $numeral{$_}, $phrase =~ /([IVXCLMD])/g;
      Remember list context m//g. Once you get your head around it, you can do many things for which split seemed awkward.

      -- Randal L. Schwartz, Perl hacker

Re: Perl as a Holy Weapon?
by belg4mit (Prior) on Dec 07, 2000 at 03:43 UTC
    And if you prefer not to use the hash, etc... at least using character classes instead of binary OR's
    print "Enter name: "; while (<STDIN>) { chomp; tr/a-zuU/A-ZVV/; for ( split// ) { #Get more function calls, #but the function handles invalid date fine. # if ( /[IVXLCDM]/) # { $sum += RtoD($_); # } } if ($sum == 666) { markOfTheBeast(); last; } else { print "The number is $sum...blessed be!\n"; } $sum = 0; print "Enter name: "; } sub RtoD { $X = shift; return 1 if $X eq 'I'; return 5 if $X eq 'V'; return 10 if $X eq 'X'; return 50 if $X eq 'L'; return 100 if $X eq 'C'; return 500 if $X eq 'D'; return 1000 if $X eq 'M'; return 0; }
      Or even (sorry, missed that someone else mentioned character classes)

      NOTE:, the romans didn't have the letter 'J'. (Watch your Indiana Jones, man!)
      while( 1 ){ my $sum; print "Enter name: "; chomp($_ = <>); tr/cdlmvxjJuU/CDLMVXIIVV/; map { $sum += RtoD($_) } split//; if($sum == 666) { markOfTheBeast(); last; } else { print "The number is $sum...blessed be!\n"; } } sub RtoD { $X = shift; return 1 if $X eq 'I'; return 5 if $X eq 'V'; return 10 if $X eq 'X'; return 50 if $X eq 'L'; return 100 if $X eq 'C'; return 500 if $X eq 'D'; return 1000 if $X eq 'M'; return 0; }