# Infinite Loop in Code -- Logic Error

**URL:** <https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746>\
**Category:** Ruby\
**Created:** [July 17, 2010, 12:38pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746 "2010-07-17T12:38:38Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 17, 2010, 12:38pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/1 "2010-07-17T12:38:38Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 17, 2010, 3:54pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/2 "2010-07-17T15:54:54Z")

</div>

Hi –  
On Sat, 17 Jul 2010, James R. 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](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](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 18, 2010, 11:03am UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/3 "2010-07-18T11:03:04Z")

</div>

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…  
.  
.  
.

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.

Much thanks,

James R.

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 18, 2010, 12:32pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/4 "2010-07-18T12:32:07Z")

</div>

Following up my last reply: see [http://pastie.org/1049200](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](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 18, 2010, 12:44pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/5 "2010-07-18T12:44:24Z")

</div>

Just pasted a small correction to that last pastie.

AND… if you don’t care what order the people are in, you could  
actually do this:

def self.run  
spies = get\_people\_from\_file.sort\_by { rand }  
spies.each\_with\_index do |spy,i|  
puts “Person #{spy} spies on Person #{spies[i-1]}”  
end  
end

That randomizes the array up front, and then just pairs people as  
spy/spyee. Given that approach, you don’t need to test for spyability.

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](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 18, 2010, 12:31pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/6 "2010-07-18T12:31:32Z")

</div>

Hi –

On Sun, 18 Jul 2010, James R. 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.

> .  
> 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](http://www.compleatrubyist.com)

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 19, 2010, 5:11am UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/7 "2010-07-19T05:11:54Z")

</div>

On 2010/07/17, at 06:38, James R. wrote:

> 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!

This won’t help with your logic problem as it stands … but it looks  
like others have commented on that.

As another approach, Array.permutation (ruby 1.9) might be of some use  
in solving your problem. The method will give you all permutations of  
the elements of an array (which doesn’t include matching an element with  
itself) … if you’ve got an array of arrays, then all you need to do is  
reject permutations where the last-name position in both arrays contain  
the same name… same deal if it’s an array of hashes.

I started to insert some sample code here, but then realized that would  
probably defeat the purpose of your exercise. 🙂

If you’re not using 1.9, then I’m sure you can find a quick way to  
implement the equivalent.

HTH,  
Matt

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 19, 2010, 5:32am UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/8 "2010-07-19T05:32:13Z")

</div>

Hi,

Thanks everyone who’s helped out with this. I finally got my original  
code working, simply by making a rand\_array at the same time I was  
making my original array, thus duplicating the array without duplicating  
the references to the objects.

It seems fascinating to me that (I’ve looked this up on other people’s  
blogs for reference)  
[Ruby, shallow copy surprise!](http://thingsaaronmade.com/blog/ruby-shallow-copy-surprise.html) that  
duplicating an array of objects using array.dup STILL copies the  
references to the objects over. There’s no such as a “C++” shallow copy  
in Ruby, because there are no primitive datatypes, and everything is an  
object. That’s why when I changed the boolean value “found” that is a  
member variable in my persons class, that is found in my original spies  
array, it changed it in rand\_spies as well.

In short, I’m slowly learning how to use ruby to solve problems, and  
learning how to not work against it. It really has some beautiful  
features and syntax that make me smile whilst sitting at my computer.  
“wow, did I just do that in one line?” I just need to get used to the  
nature of the animal. It’s different than other languages I’ve worked in  
(Java, C++, PHP), and it’s actually, in the short time I’ve been  
learning it, made me a better programmer in these other languages,  
because I approach everything in a much more elegant, OO way.

Thanks again,

James R.

---

<div class="post-metadata">

**Author:** ![yankees26](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/eb9ed0/32.png) [@yankees26](https://www.ruby-forum.com/u/yankees26)\
**Post date:** [July 18, 2010, 3:51pm UTC](https://www.ruby-forum.com/t/infinite-loop-in-code-logic-error/191746/9 "2010-07-18T15:51:08Z")

</div>

On Sun, Jul 18, 2010 at 5:03 AM, James R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 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.

James, at this point in your journeys in Ruby, it might be well to  
understand the difference between variables and objects.

The dup method doesn’t act on variables, like all other methods in  
Ruby it acts on an object. Variables are simply references to  
objects.

[http://talklikeaduck.denhaven2.com/2006/09/13/on-variables-values-and-objects](http://talklikeaduck.denhaven2.com/2006/09/13/on-variables-values-and-objects)

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Github: [rubyredrick (Rick DeNatale) · GitHub](http://github.com/rubyredrick)  
Twitter: @RickDeNatale  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)
