Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
While using a hash is a preferred way to remove duplicate values, I wanted to play around with perl trying to see if it could be done without using a hash. This is what I came up with.
I re-coded your idea of sorting the array and then not printing duplicates. This algorithm is going to be much slower than using a hash table, but your idea certainly works. I can tell that your brain cells were on overdrive! I hope my example will be helpful in terms of algorithmic thinking.

First a few quibbles... I changed the name of the subroutine to more accurately reflect what it does, "print the unique values". Also, in general don't push when you can print! If there is no need to save the data, then don't. Now probably this routine would have a return value in practice, but I went with what you did to illustrate this "print it!" point. I passed a reference to the @arr instead of the numbers themselves. This is just a performance tweak.

Now, to the code... Very often code isn't written in a single top down, straight line approach. I didn't do that here. First I wrote the shift statment to make clear what the interface is and to give my input param a name. Then I wrote the sort statement since I had decided to follow your approach.

Next, I decided that I was going to iterate over the @sorted array and I wrote the loop condition, the foreach(). Next I wrote the 2 statements that comprise the main part of the looop and embody the idea of "print this number unless I just printed the same number". This caused me to go up to before the loop and add the my $last_printed = undef; statement. Next, I realized that I needed to do something special right at the beginning of the array to handle the first number. That's when I wrote the "if" statement before the main bodypart of the loop. At that point, I could have made the code into an "if","else" construct, but I decided to just use "next;" in the if statement. I had already written what could have been the "else" clause.

In loops, my advice is to write the loop conditional first... what is being interated over/what stops the loop. Next write the "main line" execution path. Then decide what to do to in order to either "get the loop started" or "fix it up" after it finishes. The print "\n"; is an example of something to do in order finalize what the loop did.

Another common pattern is to do something before the loop even starts. If I were writing this in assembly, I would do it that way because it eliminates the "if" conditional within the loop. But I am not writing assembly and a simple logical test is of no consequence (btw, the sort uses comparitively massive amounts of CPU). Also note that I did not use any indicies. The "off by one" error is the most common programming mistake and my code avoids that pitfall.

One of my hobbies is chess. I am an average player. When I play a master level player, my brain is working really, really hard and burning lots of glucose. The master level player's brain is hardly working at all! His brain is accessing patterns from thousands of previous games. Those patterns were formed by working really, really hard to figure them out. Programming is similar, patterns repeat and re-occur. It takes a lot of hard work to burn these patterns into the brain.

Don't be so hard on yourself. Practice will help form those pathways to repeating patterns. The coding process will become easier and you will become more aware of the algorithms and design of the system. Concentrate on writing clear understandable code. Forgo tricky one liners - focus on the basics.

I hope this code and my explanation of how I went about writing it is helpful to you.

use warnings; use strict; my @arr = (29,24,0,24,24,12,0,0,10,10,10,19,17,15,13,1,12,12,24); sub print_uniques { my $array_ref = shift; my @sorted = sort {$a<=>$b} @$array_ref; my $last_printed = undef; foreach my $element (@sorted) { if (not defined $last_printed) # special case for 1st number { print "$element "; $last_printed = $element; next; } # do not print duplicates of the previously printed number print "$element " unless $element == $last_printed; $last_printed = $element; } print "\n"; } print_uniques(\@arr); #0 1 10 12 13 15 17 19 24 29

In reply to Re: Trudging along the learning perl path. by Marshall
in thread Trudging along the learning perl path. by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (8)
As of 2024-04-18 10:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found