DEV Community

Nicolas DUBIEN
Nicolas DUBIEN

Posted on • Edited on

3 2

Advent of PBT 2021 - Day 4 - Solution

Our algorithm was: detectCycleInLinkedList.
Go to the subject itself for more details

CodeSandbox with a possible set of properties you may have come with: https://codesandbox.io/s/advent-of-pbt-day-4-solution-jxqle?file=/src/index.spec.ts&previewwindow=tests


Property 1: should not detect any cycle in a non-looping linked list

For this first property, we will come up with tailored inputs having some already known characteristics. Instead of taking two fully random strings, we build two strings having some links together.

for any linked list not defining any cycle
it should not detect any cycle

Written with fast-check:

it("should not detect any cycle in a non-looping linked list", () => {
  // fc.letrec allows us to generate a recursive structure
  // as our typing said a LinkedList is just a value
  // and potentially another LinkedList defined via next
  const noCycleLinkedListArbitrary = fc.letrec((tie) => ({
    node: fc.record({
      value: fc.integer(),
      next: fc.option(tie("node") as fc.Arbitrary<LinkedList>, {
        nil: undefined,
        depthFactor: 1
      })
    })
  })).node;
  fc.assert(
    fc.property(noCycleLinkedListArbitrary, (linkedList) => {
      // Arrange / Act
      const cycleDetected = detectCycleInLinkedList(linkedList);

      // Assert
      expect(cycleDetected).toBe(false);
    })
  );
});
Enter fullscreen mode Exit fullscreen mode

Property 2: should detect a cycle in a looping linked list

As we did for our example based test building a linked list with a cycle, we will create a linked list and attach the next of the last item to the first one.

for any linked list defining a cycle
it should detect any cycle

Written with fast-check:

it("should detect a cycle in a looping linked list", () => {
  fc.assert(
    fc.property(fc.array(fc.integer(), { minLength: 1 }), (nodes) => {
      // Arrange
      const lastNode: LinkedList = { value: nodes[0], next: undefined };
      const linkedList = nodes
        .slice(1)
        .reduce((acc, n) => ({ value: n, next: acc }), lastNode);
      lastNode.next = linkedList;

      // Act
      const cycleDetected = detectCycleInLinkedList(linkedList);

      // Assert
      expect(cycleDetected).toBe(true);
    })
  );
});
Enter fullscreen mode Exit fullscreen mode

Please node that the reduce trick could also have been used to build the first property without relying on fc.letrec.


Back to "Advent of PBT 2021" to see topics covered during the other days and their solutions.

More about this serie on @ndubien or with the hashtag #AdventOfPBT.

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❀ or a friendly comment on this post if you found it helpful!

Okay