LinkedList>>#containsCycle

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

LinkedList>>#containsCycle

Sven Van Caekenberghe-2
Hi,

There exists a very elegant algorithm to detect cycles in linked lists.

  https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare

I know that our LinkedList was written with the assumption that there are no cycles. However, it seems to me that it would be nice to have a test to check for cycles. This could be useful while printing or inspecting a LinkedList (and prevent things from blowing up when there is a cycle).

Here is the implementation:

LinkedList>>#containsCycle
  | slow fast |
  slow := fast := firstLink.
  [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
    whileTrue: [
      slow := slow nextLink.
      fast := fast nextLink nextLink.
      slow == fast
        ifTrue: [ ^ true ] ].
  ^ false

And one of the tests:

LinkedListTests>>#testCycles
  1 to: 42 do: [ :each |
    list := LinkedList withAll: (1 to: each).
    "Warning: the following statement creates a cylce,
     inspecting/viewing list will probably fail"
    list lastLink nextLink: list firstLink.
    self assert: list containsCycle ]

Opinions ?

Sven


Reply | Threaded
Open this post in threaded view
|

Re: LinkedList>>#containsCycle

Max Leske
Very nice.

In such a case I would like to know, which elements are causing the cycle or, alternatively, their positions. Maybe #cyclicElements?

Cheers,
Max

> On 24 Nov 2016, at 15:16, Sven Van Caekenberghe <[hidden email]> wrote:
>
> Hi,
>
> There exists a very elegant algorithm to detect cycles in linked lists.
>
>  https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
>
> I know that our LinkedList was written with the assumption that there are no cycles. However, it seems to me that it would be nice to have a test to check for cycles. This could be useful while printing or inspecting a LinkedList (and prevent things from blowing up when there is a cycle).
>
> Here is the implementation:
>
> LinkedList>>#containsCycle
>  | slow fast |
>  slow := fast := firstLink.
>  [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
>    whileTrue: [
>      slow := slow nextLink.
>      fast := fast nextLink nextLink.
>      slow == fast
>        ifTrue: [ ^ true ] ].
>  ^ false
>
> And one of the tests:
>
> LinkedListTests>>#testCycles
>  1 to: 42 do: [ :each |
>    list := LinkedList withAll: (1 to: each).
>    "Warning: the following statement creates a cylce,
>     inspecting/viewing list will probably fail"
>    list lastLink nextLink: list firstLink.
>    self assert: list containsCycle ]
>
> Opinions ?
>
> Sven
>
>


Reply | Threaded
Open this post in threaded view
|

Re: LinkedList>>#containsCycle

stepharo
In reply to this post by Sven Van Caekenberghe-2
Hi Sven

I'm collecting alternative Collection implementations in the project  
Container
I do not remember if I have linkedList but we can add it there.

You may wonder why I'm doing that?
        - I want to be able to have strong collections that are independent from  
the kernel
        - Ideally the kernel of Pharo should be mininmal so it means that I would  
like to
        have as few as possible as collections inside the bootstrapped kernel
        and that other collections are nicely packaged in Container.

Now I can understand that others do not like what I'm doing but I will  
just continue.
I have Grid, LinkedList, DoubleLinkedList,
I have on my disc
        two implementation of Trees
        I should harvest BTrees and SkipList.

If people want to help they are welcome, else I will just do it alone.

Stef

> Hi,
>
> There exists a very elegant algorithm to detect cycles in linked lists.
>
>   https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
>
> I know that our LinkedList was written with the assumption that there  
> are no cycles. However, it seems to me that it would be nice to have a  
> test to check for cycles. This could be useful while printing or  
> inspecting a LinkedList (and prevent things from blowing up when there  
> is a cycle).
>
> Here is the implementation:
>
> LinkedList>>#containsCycle
>   | slow fast |
>   slow := fast := firstLink.
>   [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
>     whileTrue: [
>       slow := slow nextLink.
>       fast := fast nextLink nextLink.
>       slow == fast
>         ifTrue: [ ^ true ] ].
>   ^ false
>
> And one of the tests:
>
> LinkedListTests>>#testCycles
>   1 to: 42 do: [ :each |
>     list := LinkedList withAll: (1 to: each).
>     "Warning: the following statement creates a cylce,
>      inspecting/viewing list will probably fail"
>     list lastLink nextLink: list firstLink.
>     self assert: list containsCycle ]
>
> Opinions ?
>
> Sven
>
>


--
Using Opera's mail client: http://www.opera.com/mail/

Reply | Threaded
Open this post in threaded view
|

Re: LinkedList>>#containsCycle

stepharo
In reply to this post by Sven Van Caekenberghe-2
I added to the CT package

> Hi,
>
> There exists a very elegant algorithm to detect cycles in linked lists.
>
>   https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
>
> I know that our LinkedList was written with the assumption that there  
> are no cycles. However, it seems to me that it would be nice to have a  
> test to check for cycles. This could be useful while printing or  
> inspecting a LinkedList (and prevent things from blowing up when there  
> is a cycle).
>
> Here is the implementation:
>
> LinkedList>>#containsCycle
>   | slow fast |
>   slow := fast := firstLink.
>   [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
>     whileTrue: [
>       slow := slow nextLink.
>       fast := fast nextLink nextLink.
>       slow == fast
>         ifTrue: [ ^ true ] ].
>   ^ false
>
> And one of the tests:
>
> LinkedListTests>>#testCycles
>   1 to: 42 do: [ :each |
>     list := LinkedList withAll: (1 to: each).
>     "Warning: the following statement creates a cylce,
>      inspecting/viewing list will probably fail"
>     list lastLink nextLink: list firstLink.
>     self assert: list containsCycle ]
>
> Opinions ?
>
> Sven
>
>


--
Using Opera's mail client: http://www.opera.com/mail/

Reply | Threaded
Open this post in threaded view
|

Re: LinkedList>>#containsCycle

Tudor Girba-2
In reply to this post by stepharo
Hi Stef,

Would it make sense to put the collection extensions from Moose in the Container project?

Cheers,
Doru


> On Nov 26, 2016, at 12:11 PM, stepharo <[hidden email]> wrote:
>
> Hi Sven
>
> I'm collecting alternative Collection implementations in the project Container
> I do not remember if I have linkedList but we can add it there.
>
> You may wonder why I'm doing that?
> - I want to be able to have strong collections that are independent from the kernel
> - Ideally the kernel of Pharo should be mininmal so it means that I would like to
> have as few as possible as collections inside the bootstrapped kernel
> and that other collections are nicely packaged in Container.
>
> Now I can understand that others do not like what I'm doing but I will just continue.
> I have Grid, LinkedList, DoubleLinkedList,
> I have on my disc
> two implementation of Trees
> I should harvest BTrees and SkipList.
>
> If people want to help they are welcome, else I will just do it alone.
>
> Stef
>
>> Hi,
>>
>> There exists a very elegant algorithm to detect cycles in linked lists.
>>
>>  https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
>>
>> I know that our LinkedList was written with the assumption that there are no cycles. However, it seems to me that it would be nice to have a test to check for cycles. This could be useful while printing or inspecting a LinkedList (and prevent things from blowing up when there is a cycle).
>>
>> Here is the implementation:
>>
>> LinkedList>>#containsCycle
>>  | slow fast |
>>  slow := fast := firstLink.
>>  [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
>>    whileTrue: [
>>      slow := slow nextLink.
>>      fast := fast nextLink nextLink.
>>      slow == fast
>>        ifTrue: [ ^ true ] ].
>>  ^ false
>>
>> And one of the tests:
>>
>> LinkedListTests>>#testCycles
>>  1 to: 42 do: [ :each |
>>    list := LinkedList withAll: (1 to: each).
>>    "Warning: the following statement creates a cylce,
>>     inspecting/viewing list will probably fail"
>>    list lastLink nextLink: list firstLink.
>>    self assert: list containsCycle ]
>>
>> Opinions ?
>>
>> Sven
>>
>>
>
>
> --
> Using Opera's mail client: http://www.opera.com/mail/
>

--
www.tudorgirba.com
www.feenk.com

"Not knowing how to do something is not an argument for how it cannot be done."


Reply | Threaded
Open this post in threaded view
|

Re: LinkedList>>#containsCycle

stepharo
Hi doru

> Hi Stef,
>
> Would it make sense to put the collection extensions from Moose in the  
> Container project?

If you think it make sense. Yes.

For example Ropes could be managed there.
Have a look I have tiny packages.
The idea is to make sure that
        - people can use one abstraction and not be forced to load a complete  
library
        - document them with tests and others
        - gather most of collections in one place to make sure that we do not  
lose energy reimplementing them.

I'm packaging the collection from the image that have no users in the  
image for now.
Then I will continue to package
        a Tree package (I tried to contact his author but may be he passed away)
        SkipList
        Quadtrees.

Stef

>
> Cheers,
> Doru
>
>
>> On Nov 26, 2016, at 12:11 PM, stepharo <[hidden email]> wrote:
>>
>> Hi Sven
>>
>> I'm collecting alternative Collection implementations in the project  
>> Container
>> I do not remember if I have linkedList but we can add it there.
>>
>> You may wonder why I'm doing that?
>> - I want to be able to have strong collections that are independent  
>> from the kernel
>> - Ideally the kernel of Pharo should be mininmal so it means that I  
>> would like to
>> have as few as possible as collections inside the bootstrapped kernel
>> and that other collections are nicely packaged in Container.
>>
>> Now I can understand that others do not like what I'm doing but I will  
>> just continue.
>> I have Grid, LinkedList, DoubleLinkedList,
>> I have on my disc
>> two implementation of Trees
>> I should harvest BTrees and SkipList.
>>
>> If people want to help they are welcome, else I will just do it alone.
>>
>> Stef
>>
>>> Hi,
>>>
>>> There exists a very elegant algorithm to detect cycles in linked lists.
>>>
>>>  https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare
>>>
>>> I know that our LinkedList was written with the assumption that there  
>>> are no cycles. However, it seems to me that it would be nice to have a  
>>> test to check for cycles. This could be useful while printing or  
>>> inspecting a LinkedList (and prevent things from blowing up when there  
>>> is a cycle).
>>>
>>> Here is the implementation:
>>>
>>> LinkedList>>#containsCycle
>>>  | slow fast |
>>>  slow := fast := firstLink.
>>>  [ slow notNil and: [ fast notNil and: [ fast nextLink notNil ] ] ]
>>>    whileTrue: [
>>>      slow := slow nextLink.
>>>      fast := fast nextLink nextLink.
>>>      slow == fast
>>>        ifTrue: [ ^ true ] ].
>>>  ^ false
>>>
>>> And one of the tests:
>>>
>>> LinkedListTests>>#testCycles
>>>  1 to: 42 do: [ :each |
>>>    list := LinkedList withAll: (1 to: each).
>>>    "Warning: the following statement creates a cylce,
>>>     inspecting/viewing list will probably fail"
>>>    list lastLink nextLink: list firstLink.
>>>    self assert: list containsCycle ]
>>>
>>> Opinions ?
>>>
>>> Sven
>>>
>>>
>>
>>
>> --
>> Using Opera's mail client: http://www.opera.com/mail/
>>
>
> --
> www.tudorgirba.com
> www.feenk.com
>
> "Not knowing how to do something is not an argument for how it cannot be  
> done."
>
>


--
Using Opera's mail client: http://www.opera.com/mail/