Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked

Golf: Improve this guy's fail . . . please!

by dragonchild (Archbishop)
on Jun 30, 2009 at 21:43 UTC ( #776191=perlmeditation: print w/replies, xml ) Need Help??

This is taken from some blog. Who can beat it?
#!/usr/bin/perl -w # counts the instances of each character in the file specified. my %ascii_counts = (); my @keys = keys(%ascii_counts); my @values = values(%ascii_counts); my $total_chars; while (1) { # program's main loop &init_hash(); &fill_hash(); &clean_hash(); &print_hash(); } # Subroutines ======================================================== +== sub init_hash { # foreach ascii character add it to the hash with count = 0 foreach $i (0..255) { $ascii_counts{ord($i)} = 0; } } sub fill_hash { # get filename print "Enter 'ls' or a filename to scan: "; my $file_name = shift || ; while ($file_name =~ m/^ls/) { system("$file_name"); print "\nEnter 'ls' or a filename to scan: "; $file_name = ; } # open file open(INFILE, $file_name) or warn &fill_hash(); # iterate through lines/characters incrementing the key's value while (my $l = ) { my @line = split(//, $l); foreach $char (@line) { $ascii_counts{$char}++; } } # close file close(INFILE); } sub clean_hash { while (my ($key, $value) = each(%ascii_counts)) { # remove keys with value == 0 if ($value == 0) { delete($ascii_counts{$key}); } # remove non-alpha-numeric keys elsif ($key =~ /\W/) { delete($ascii_counts{$key}); } } # store the key/value pairs sorted for later use @keys = sort(keys(%ascii_counts)); @values = sort(values(%ascii_counts)); # determine total number of values $total_chars = 0; foreach $x (@values) { $total_chars += $x; } } sub print_hash { print "\n[key]\t[count]\t[%]\n\n"; foreach my $key (@keys) { my $value = $ascii_counts{$key}; my $percent = $value/$total_chars*100; print " $key\t$value\t$percent\n"; } print "\nTotal: $total_chars characters.\n\n"; }

My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re: Golf: Improve this guy's fail . . . please!
by moritz (Cardinal) on Jun 30, 2009 at 22:06 UTC
    This looks embarrassingly similar to my first Perl scripts, except that I never called subroutines with a leading & because I had the luck to learn Perl 5 from the start ;-).

    It's a typical case of not knowing about autovivification: instead of assigning 0 to every possible hash key, and later sort out those which remained 0, you can simply leave out both steps altogether.

    It is also typical in confusing ASCII with an 8-bit encoding.

    A non-golfed version:

    use strict; use warnings; use List::Util qw(sum); my %chars; local $/ = \1; while (<>) { $chars{$_}++ if /\w/; } my $total = sum values %chars; print "key\tcount\t%\n"; for (sort keys %chars) { printf "%s\t%d\t%.3f\n", $_, $chars{$_}, $chars{$_} / $total; }

    It doesn't prompt for a filename, instead it either expects a file name on the command line, or reads from STDIN - in good old unix tradition.

      At the opposite end of the spectrum, reading in the whole file:

      local $/; ++$chars{$_} for <> =~ /\w/g

      (Trimmed: local$/;++$c{$_}for<>=~/\w/g)

      It only accepts one file, though.

      Update: 5 shorter, accepts multiple files, and doesn't mess with $/:

      ++$chars{$_} for map /\w/g, <>

      (Trimmed: ++$c{$_}for map/\w/g,<>)

        I borrowed your idea and made something short and very ugly which does the whole job including percentages and total. I even added a count of distinct characters:
        ++$t,++$c{$_}for map/\w/g,<>; print$_,"\t",$c{$_},"\t",$c{$_}/$t*100,$/for sort keys %c; print"Distinct: ".keys(%c)."\tTotal: $t\n";

        I doubt I'd call that an "improvement", at least with a straight face. It could be cleaned up pretty easily, though.

Re: Golf: Improve this guy's fail . . . please!
by ELISHEVA (Prior) on Jul 01, 2009 at 07:22 UTC

    I realize this was posted with good intent as a learning experience/game for us here at Perl monks, but I have very mixed feelings about this post.

    On one hand, I view coding as a responsibility. The number of people who know how to use code far outnumber the number of people who know how to write even bad code. The number of people who know how to write code (bad or good) far outnumber the the number of people who know how to scan code for errors or security risks. Those of us who know how to code have a responsibility to either (a) post in a forum where we can be easily critiqued or (b) post code that has been throughly tested. From that perspective, if you post bad or careless code on an isolated blog, you deserve what you get.

    On the other hand, a rule of thumb I use when I criticize anyone in terms that are even remotely identifiable is "Can I say it to their face?". If I can't do that, I feel I don't have the right. When I saw this post, my first thought was to email the person and say here is some feedback you can learn from, but then I couldn't think of a way to say it that wouldn't run the risk of embarrassing him. So, for me, at least,it failed the 'can I say it to his face' rule. Maybe not though for others - I may just lack the creative tact needed. The only other option, keeping the author totally anonymous, would have been wrong. No matter how bad the code is, there are copyright and plagiarism issues with extensive unattributed quotes.

    I just felt I needed to share that.

    Best, beth

      I looked for a place to reply to the code's original author on his page, and found none. I found an email address and a Google Talk account name tied to it. I tried to message him via Google Talk, but although he advertises it in his contact info he requires potential "buddies" to be approved. I followed links from his Blogger account to another web site he has, but the contact form there is disabled. I'm not going to go to the trouble of opening a fourth interface to contact him, but his email address is available in his Blogger contact info if you'd rather avoid the first three I tried. At some point, it's an author's responsibility to make contacting him waste less of a commenter's time if the author really wants to be contacted.
      A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Golf: Improve this guy's fail . . . please!
by perigrin (Sexton) on Jul 01, 2009 at 04:52 UTC
    Following from a brain dump I made on IRC, and since nobody here seems to have looked at perl's command line switches:
    #!/usr/bin/env perl -aF'' -nl
    $t += @F; 
    $c{$_}++ for @F; 
    END { 
        printf("%s\t%d\t%.3f\n", $_, $c{$_}, $c{$_} / $t) for keys %c; 
        print "Total: $t" 
    Of course the simplest solution from IRC was say `wc -c @ARGV`
      What about
      #!/usr/bin/env perl -n0 $t++,$c{$_}++ for /./g; printf("%s\t%d\t%.3f\n", $_, $c{$_}, $c{$_} / $t) for keys %c; print "Total: $t\n"
Re: Golf: Improve this guy's fail . . . please!
by Zen (Deacon) on Jul 17, 2009 at 20:06 UTC
    In no way does this thread indicate any well-meaning intentions besides poking fun. I don't even get the joke. Shameful, actually, and harmful to the community. My vote is reap.
      In no way does this thread indicate any well-meaning intentions besides poking fun.

      Without conceding that is the situation, that doesn't seem to be a requirement for posting.

Re: Golf: Improve this guy's fail . . . please!
by shmem (Chancellor) on Jul 01, 2009 at 00:38 UTC

    Erm... sure 'yes we can'. But more fun than golf (and more valuable to the blogger) would be: count the errors. Arbitrary section picked at a glance:

    sub fill_hash { # get filename print "Enter 'ls' or a filename to scan: "; my $file_name = shift || ; while ($file_name =~ m/^ls/) { system("$file_name"); print "\nEnter 'ls' or a filename to scan: "; $file_name = ; }

    WTF? for sure,

    syntax error at foo line xx, near "|| ;"

    Ah well... golf, then :-)

        Now that is evil!


        You can lead your users to water, but alas, you cannot drown them.
Re: Golf: Improve this guy's fail . . . please!
by jdporter (Canon) on Jul 21, 2009 at 16:30 UTC

    I think all the hoo-ha could have been avoided if the OP had simply not cited the source. Where the code came from was utterly beside the point. If necessary, he could have obscured the code somewhat (though in this case I don't think it would have been necessary).

      I think all the hoo-ha could have been avoided if the OP had simply not cited the source.
      Sorry, but I have to differ. That would have changed the nature of the hoo-ha but there would still have been something very distasteful going on. And at least this way the original author got to have his say and, it is to be hoped, got some 'completion' about the whole sorry affair.

      IMO this thread went wrong right from the start, with the thread title. And then went way more wrong with the use of the "PS" term (four times!). And both of these from names that within less than a year I have come to recognise and respect within PerlMonks.

      Moritz said at the top of the thread, "This looks embarrassingly similar to my first Perl scripts". I could certainly say the same. I cringe when I see my early stuff. I cringe when I have to maintain others' early stuff (or my own). But like when one is stuck on the road behind a learner driver doing 15mph, it is as well to remember we all had to start somewhere.

      Hey! This isn't my signature!!"
Re: Golf: Improve this guy's fail . . . please!
by graff (Chancellor) on Jul 01, 2009 at 02:56 UTC
    On the one hand the code as posted at the top of this thread is not being fair to the poor shmuck who created the mess -- OTOH, the poor shmuck has it coming to him.

    The biggest problem: at the originating blog page, Poor Shmuck didn't do enough (if anything) to escape the html-sensitive characters in his perl code (like angle brackets and ampersands). That's why the code doesn't compile as posted here (or as it appears at the originating blog page).

    I can understand not taking the trouble to invent something as clever as our beloved <code> tags, but PS didn't even use <pre>... Could he really be fishing for a bad rep? I just don't get it.

      From recent personal experience with Blogspot, I was really pining for code tag; pre could only keep the formatting. Need to alter content of pre -- so that the content appear as intended -- is just too much of a bother; had to make a side trip to perl.

      Then again Blogspot does not seem to be oriented to post code, at all. I managed to not curse the frack out of Blogspot by much restraint. Until now, that is.   (~_~#)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://776191]
Approved by grep
Front-paged by grinder
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2019-11-22 10:19 GMT
Find Nodes?
    Voting Booth?
    Strict and warnings: which comes first?

    Results (110 votes). Check out past polls.