From: James Rasmussen on 17 Jul 2010 06:38 Hi all, I've just started my journey as a ruby developer, and I'm going through a couple of exercises that one of my professors sent me, to allow me figure out the syntax. It's not for an assignment, merely for practice (I need it). My code looks like Java, it's not elegant, it's slow, but little by little, right? I'm having a problem with my code. It's attached, and if someone could look at it, that would be great. I can't figure out what I'm doing wrong. I think it's something wrong with my for loop. Basically, the code is supposed to find "spies" for all the entries, but someone cannot "spy" on a person with their same last name, or themselves. The goal is to print the list of spies all out. Thank you in advance! Attachments: http://www.ruby-forum.com/attachment/4862/exercise.rar -- Posted via http://www.ruby-forum.com/.
From: David A. Black on 17 Jul 2010 09:54 Hi -- On Sat, 17 Jul 2010, James Rasmussen wrote: > Hi all, > > I've just started my journey as a ruby developer, and I'm going through > a couple of exercises that one of my professors sent me, to allow me > figure out the syntax. It's not for an assignment, merely for practice > (I need it). My code looks like Java, it's not elegant, it's slow, but > little by little, right? Yes, but a little can go a long way :-) You definitely need to let Ruby do much more of the work. > I'm having a problem with my code. It's attached, and if someone could > look at it, that would be great. I can't figure out what I'm doing > wrong. I think it's something wrong with my for loop. Basically, the > code is supposed to find "spies" for all the entries, but someone cannot > "spy" on a person with their same last name, or themselves. The goal is > to print the list of spies all out. Thank you in advance! I had trouble with your input file (see my separate post to this list). I've changed it so that it uses spaces instead of non-printing characters. I have then created the following implementation: http://pastie.org/1048517 Not fully tested, but I wanted to insinuate at least a partial test suite in there :-) You can run the tests by giving the command-line argument "test". Otherwise it will print out the results of the spy checking. A couple of key points: Very rarely do you have to maintain explicit counters in Ruby. The language full of facilities for traversing collections. If you can get objects into collections, you can then use things like "each" and "find" instead of maintaining counters. I use find to get the first person, if there is one, from the rand_spies array on whom the current person is allowed to spy. (I think your original infinite loop problem was because the counter was misplaced in relation to the do/end nesting. Less nesting makes those things less likely and easier to fix.) I've put much more of the business logic of the Person class (which I singularized) into the class. For example, Person objects can now tell you whether or not they're allowed to spy on someone else. I may or may not have the logic exactly right, but the point is to put the knowledge of Person business into the Person objects, rather than inlining it in the code outside. Another win is the to_s method, which lets me interpolate a person object into a string without having to do the formatting explicitly. Of course, I can always use a different/explicit format if I need to, but to_s can at least cover the most common case. Finally: there are different ways to do just about everything I've done here, including the algorithms as well as the language-specific techniques. So keep tinkering :-) David -- David A. Black, Senior Developer, Cyrus Innovation Inc. The Ruby training with Black/Brown/McAnally Compleat Philadelphia, PA, October 1-2, 2010 Rubyist http://www.compleatrubyist.com
From: James Rasmussen on 18 Jul 2010 05:03 David, Thank you so much for the help, that makes a lot of sense. Your code was much more elegant than mine. It was one of those mind-broadening moments, haha. Concerning my own implementation, I think I figured out the problem as to why it wasn't working. My code was ugly, but the logic (I thought) was sound. I was doing some more debugging, trying to figure out why it would only get to six strings of output, then fail. I found it out. Here, I make my duplicate for my array: rand_spies = spies.dup rand_spies.sort_by{ rand } #perform spying operations...
From: David A. Black on 18 Jul 2010 06:18 Hi -- On Sun, 18 Jul 2010, James Rasmussen wrote: > David, > > Thank you so much for the help, that makes a lot of sense. Your code was > much more elegant than mine. It was one of those mind-broadening > moments, haha. Good -- I'm pleased. > Concerning my own implementation, I think I figured out the problem as > to why it wasn't working. My code was ugly, but the logic (I thought) > was sound. I was doing some more debugging, trying to figure out why it > would only get to six strings of output, then fail. I found it out. > Here, I make my duplicate for my array: > > rand_spies = spies.dup > rand_spies.sort_by{ rand } > #perform spying operations... > . > . > . > > However, dup copies instance variables over, and it IS a shallow copy, > but if you change an instance variable, based on my debugging, it > changes the original as well. I found this out when (using netbeans) I > put a watch on these variables: > > spies[k].found > rand_spies[l].found > spies[k+1].found > rand_spies[l+1].found > > I found that, even though my rand_spies array was randomized and shallow > copied, it was still making changes to the original array. I found this > when I saw that the rand_spies[l+1].found was being changed when I found > a match in the spies[l].found > > So my question is this: Is there any way to make a shallow copy of an > array of objects, where it passes all the values over, without passing > the reference over? I'm thinking a pass-by-value C++ copy sort of deal. > That's what I need. When you dup an array, you get a new array, but the same objects inside it. So it's not quite right to say that changes to the new array make changes to the original. The two arrays are completely different objects: >> array1 = [1,2,3,4,5] => [1, 2, 3, 4, 5] >> array2 = array1.dup => [1, 2, 3, 4, 5] >> array2.pop => 5 >> array2 => [1, 2, 3, 4] >> array1 => [1, 2, 3, 4, 5] The objects *in* the array, however, are indeed the same. The question you're asking -- a shallow copy where the values are reconstituted, instead of references being passed -- is a contradiction in terms. What makes it "shallow" is the fact that only the array (the container object) is dup'd, while the objects aren't. If you want two arrays of people objects, I would just create two arrays to start with. However, it sounds kind of odd to me, in terms of what you want your program to do (which I might well be misunderstanding). It would mean that even if, say, Clark is "found", the other Clark object would still be able to spy. I'm thinking it might make more sense to reengineer the "found" logic, and the tests for whether or not someone can spy, but keep the basic data structure in place. David -- David A. Black, Senior Developer, Cyrus Innovation Inc. The Ruby training with Black/Brown/McAnally Compleat Philadelphia, PA, October 1-2, 2010 Rubyist http://www.compleatrubyist.com
From: David A. Black on 18 Jul 2010 06:30 Following up my last reply: see http://pastie.org/1049200 for a version where you get all twelve. See the new tests at the bottom, and the tweaked found logic in the application code. David -- David A. Black, Senior Developer, Cyrus Innovation Inc. The Ruby training with Black/Brown/McAnally Compleat Philadelphia, PA, October 1-2, 2010 Rubyist http://www.compleatrubyist.com
|
Next
|
Last
Pages: 1 2 Prev: how to test a ruby script from another ruby script? Next: Driving irb from IO.popen |