Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

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?

Comment on Golf: Improve this guy's fail . . . please!
Download Code
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 shmem (Canon) 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 :-)

    map{$s{$_}++}/./gfor<>
        Now that is evil!


        holli

        You can lead your users to water, but alas, you cannot drown them.
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.   (~_~#)

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 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.
      You don't know me very well. :)

      I have, on many occasions, told someone he was being an idiot. I'd love to tell the poster the same thing, but I'm not going to hunt him down. It's not worth my time.


      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?
        Hi, I'm the poor schmuck you've been referring to. I've been trying to teach myself Perl in between classes for a couple months now (my college only really offers Java). I know my code is inelegant, but I'm also still really new to Perl. The program being laughed at was my attempt to help a friend from another class--he needed a character counter and he needed it fast, so I tried to hack one together in Perl for him (in case anyone is going to mention cheating, he wasn't turning my code in for an assignment). I'm sorry, I honestly didn't know that my code was so bad. I agree with the above post about responsibility, though I thought I was doing right by making all of my source open and available. The hope was that someone might find a post or two useful if they were trying to learn Perl too. When I found this thread on PerlMonks I laughed a little. You see, about two days ago I noticed that my blog was actually getting traffic and that a lot of it was from PM. I joked with my wife that it was really cool that I was getting referrals from a site like PM...unless I was the "How Not to Code" showcase of the week. Anyway, I didn't realize that my blog was doing harm--I'm going to take it down after I finish this post. Maybe after I've been studying Perl for a few years I'll hazard writing some tutorials for CIS students, but I'll try to go through proper channels to do so. To the couple of you that tried to contact me, email is usually the easiest way: zhespelt at gmail dot com.
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 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!!"

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (11)
As of 2014-07-29 11:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (215 votes), past polls