From cb68117d83e7754f9c6fd0909adfa12ac8d26d0f Mon Sep 17 00:00:00 2001
From: MarcUs7i <96580944+MarcUs7i@users.noreply.github.com>
Date: Thu, 5 Dec 2024 23:14:53 +0100
Subject: [PATCH] Add function doesnt work as supposed at 3+ participants
---
Marathons/Marathon.cs | 188 +++++++++++++++++++++++++++++++++++++++++-
Marathons/Node.cs | 5 +-
2 files changed, 187 insertions(+), 6 deletions(-)
diff --git a/Marathons/Marathon.cs b/Marathons/Marathon.cs
index 97f87ea..99780d9 100644
--- a/Marathons/Marathon.cs
+++ b/Marathons/Marathon.cs
@@ -2,7 +2,8 @@
public sealed class Marathon
{
- //private Node? _head;
+ private Node? _head;
+ private Node? _tail;
public readonly string City;
public readonly DateOnly Date;
public int ParticipantCount { get; private set; }
@@ -13,16 +14,61 @@ public sealed class Marathon
Date = date;
}
+ ///
+ /// Adds a participant to the list
+ ///
+ /// The participant
public void AddParticipant(Participant participant)
{
+ int insertIndex = GetIndex(participant, out bool exactPosFound);
+ if (exactPosFound)
+ {
+ return;
+ }
+ ParticipantCount++;
+ Node middleNode = new Node(participant);
+ Node? leftNode = GetNodeByIndex(insertIndex - 1);
+ Node? rightNode = GetNodeByIndex(insertIndex);
+ if (leftNode == null || rightNode == null)
+ {
+ _head = middleNode;
+ _tail = middleNode;
+ return;
+ }
+ MoveNode(leftNode, rightNode, middleNode);
}
- public bool RemoveParticipant(int index)
+ public bool RemoveParticipant(int startNo)
{
- return false;
- }
+ Node? nodeToRemove = GetNodeByStartNo(startNo);
+ if (nodeToRemove == null)
+ {
+ return false;
+ }
+ ParticipantCount--;
+ Node? leftNode = GetNodeByIndex(GetIndex(nodeToRemove.Data!, out _) - 1);
+ // some explanation here |↑ node of → |↑ index of → |↑ Participant
+ Node? rightNode = nodeToRemove.Next;
+
+ // If nodeToRemove is the first node
+ if (leftNode == null)
+ {
+ _head = rightNode;
+ return true;
+ }
+ // If nodeToRemove is the last node
+ if (rightNode == null)
+ {
+ _tail = leftNode;
+ return true;
+ }
+
+ MoveNode(leftNode, rightNode);
+ return true;
+ }
+
public string[] GetResultList()
{
return Array.Empty();
@@ -32,4 +78,138 @@ public sealed class Marathon
{
return $"{City} marathon on {Date.ToString(Const.Culture)}";
}
+
+ ///
+ /// Returns the index of the participant in the list
+ /// It's a merged method that can be used to determine the index of a participant,
+ /// or the index where the participant can be placed
+ /// Should be efficient for VERY large lists
+ ///
+ /// the participant you want to check
+ /// true: found exact location; false: no exact location/doesn't exist
+ /// The index where the participant is or might be
+ private int GetIndex(Participant participant, out bool exactPosFound)
+ {
+ //check if the list is empty
+ if (_head is null || _tail is null)
+ {
+ exactPosFound = false;
+ return 0;
+ }
+
+ //check if the participant is the first or last
+ int result = _head.Data?.CompareTo(participant) ?? 0; // why ?? are you confused? you sure its not null??
+ // haha, you sure??
+ // I'm sure, I'm sure
+ // haha, okay, I trust you
+ // ok, i should stop talking to co-pilot now
+ // If the participant is the first or can be placed before the first
+ if (result <= 0)
+ {
+ exactPosFound = result == 0;
+ return 0;
+ }
+ // If the participant is the last or can be placed after the last
+ result = _tail.Data?.CompareTo(participant) ?? 0;
+ if (result >= 0)
+ {
+ exactPosFound = result == 0;
+ return ParticipantCount;
+ }
+
+ // Half the list and check both sides
+ int left = 0;
+ int right = ParticipantCount;
+ while (left < right)
+ {
+ int middle = (left + right) / 2;
+ Node? current = _head;
+ for (int i = 0; i < middle; i++)
+ {
+ current = current?.Next;
+ }
+ result = current?.Data?.CompareTo(participant) ?? 0;
+ if (result == 0)
+ {
+ exactPosFound = true;
+ return middle;
+ }
+ if (result < 0)
+ {
+ left = middle + 1;
+ }
+ else
+ {
+ right = middle;
+ }
+ }
+
+ // If not in the list, return the index where it should be
+ exactPosFound = false;
+ return left;
+ }
+
+ ///
+ /// Makes the connection to the specified node
+ /// A -> B -> C
+ /// If no middle node specified, then it will be A -> C
+ ///
+ /// The starting Node, or A node
+ /// The targetNode, or the B node if no middle node specified, else C node
+ /// The middle node or the B node
+ private void MoveNode(Node startingNode, Node targetNode, Node? middleNode = null)
+ {
+ if(middleNode is null)
+ {
+ startingNode.Next = targetNode;
+ return;
+ }
+
+ if(startingNode == targetNode)
+ {
+ _tail = middleNode;
+ }
+ else middleNode.Next = targetNode;
+ startingNode.Next = middleNode;
+ }
+
+ Node? GetNodeByIndex(int index)
+ {
+ if(index <= 0)
+ {
+ return _head;
+ }
+ if(index >= ParticipantCount)
+ {
+ return _tail;
+ }
+
+ Node? current = _head;
+ for (int i = 0; i < index; i++)
+ {
+ current = current?.Next;
+ }
+
+ return current;
+ }
+
+ Node? GetNodeByStartNo(int startNo)
+ {
+ Node? current = _head;
+ for (int i = 0; i < ParticipantCount; i++)
+ {
+ if (current == null)
+ {
+ return null;
+ }
+
+ if (current.Data?.StartNo == startNo)
+ {
+ return current;
+ }
+ current = current.Next;
+ }
+
+ return null;
+ }
}
\ No newline at end of file
diff --git a/Marathons/Node.cs b/Marathons/Node.cs
index a10214f..a7aef11 100644
--- a/Marathons/Node.cs
+++ b/Marathons/Node.cs
@@ -1,7 +1,8 @@
namespace Marathons;
-public sealed class Node(double? value)
+public sealed class Node(Participant? value)
{
- public double? Data { get; } = value;
+ //accept anything
+ public Participant? Data { get; } = value;
public Node? Next { get; set; }
}