154 lines
5.6 KiB
C#
154 lines
5.6 KiB
C#
using Parsing.Data;
|
|
|
|
namespace Parsing.Data;
|
|
|
|
public class SearchResult<TIndexType>
|
|
{
|
|
public SearchResult(IDataIndex<TIndexType> dataIndex)
|
|
{
|
|
this.DataIndex = dataIndex;
|
|
}
|
|
|
|
public IDataIndex<TIndexType>? DataIndex { get; set; }
|
|
}
|
|
|
|
public class DirectionalSearchResult<TIndexType> : SearchResult<TIndexType>
|
|
{
|
|
public DirectionalSearchResult(IDataIndex<TIndexType> dataIndex, Direction direction, int length): base(dataIndex)
|
|
{
|
|
this.Direction = direction;
|
|
this.Length = length;
|
|
}
|
|
|
|
public Direction Direction { get; set; }
|
|
public int Length { get; set; }
|
|
}
|
|
|
|
public abstract class DataSetManipulatorBase<TCollectedType, TDataType, TIndexType> where TDataType : IEquatable<TDataType>
|
|
{
|
|
protected IDataSetIndexer<TDataType, TIndexType> indexer;
|
|
|
|
protected List<TCollectedType> dataSet;
|
|
|
|
public DataSetManipulatorBase(List<TCollectedType> dataSet, IDataSetIndexer<TDataType, TIndexType> indexer)
|
|
{
|
|
this.indexer = indexer;
|
|
this.dataSet = dataSet;
|
|
}
|
|
|
|
// we do not know how to iterate a specific data set exactly, the implementation has to take care of validating directional input
|
|
protected abstract Direction ValidDirections();
|
|
|
|
protected void ValidateDirection(Direction d)
|
|
{
|
|
var allValidDirections = this.ValidDirections();
|
|
var isValid = ((d | allValidDirections) == allValidDirections) && ((d & allValidDirections) > 0);
|
|
|
|
if (!isValid)
|
|
{
|
|
throw new ArgumentException("Invalid search direction provided for given data set!");
|
|
}
|
|
}
|
|
|
|
protected List<Direction> SimplifyDirections(Direction d)
|
|
{
|
|
this.ValidateDirection(d);
|
|
var allDirections = DirectionProvider.GetAllDirections();
|
|
var singleDirections = new List<Direction>();
|
|
|
|
foreach (Direction direction in allDirections)
|
|
{
|
|
if ((direction & d) > 0)
|
|
{
|
|
singleDirections.Add(direction);
|
|
}
|
|
}
|
|
|
|
return singleDirections;
|
|
}
|
|
|
|
public List<Direction> GetValidDirectionList(Direction d)
|
|
{
|
|
return SimplifyDirections(this.ValidDirections());
|
|
}
|
|
|
|
// we do not know how to iterate a specific data set exactly, the implementation has to take care of ending traversal in any direction
|
|
public abstract bool IsValidIndex(IDataIndex<TIndexType> queryPosition);
|
|
|
|
// we do not know how to iterate a specific data set exactly, the implementation has to take care of traversing the set
|
|
public abstract IDataIndex<TIndexType> Move(IDataIndex<TIndexType> currentPosition, Direction direction);
|
|
|
|
public List<IDataIndex<TIndexType>> GetNeighborIndices(IDataIndex<TIndexType> currentPosition, Direction directions)
|
|
{
|
|
var singleDirections = this.SimplifyDirections(directions);
|
|
var neighbors = new List<IDataIndex<TIndexType>>();
|
|
|
|
foreach (var direction in singleDirections)
|
|
{
|
|
var newPosition = this.Move(currentPosition, direction);
|
|
if (this.IsValidIndex(newPosition))
|
|
{
|
|
neighbors.Add(newPosition);
|
|
}
|
|
}
|
|
|
|
return neighbors;
|
|
}
|
|
|
|
// we do not know how to iterate a specific data set exactly, but we only need to find specific items to be able to continue with any other algorithm
|
|
public abstract List<SearchResult<TIndexType>> FindInSet(TDataType data);
|
|
|
|
public List<DirectionalSearchResult<TIndexType>> FindAtPosition(IDataIndex<TIndexType> currentPosition, List<TDataType> data)
|
|
{
|
|
return this.FindAtPosition(currentPosition, data, this.ValidDirections());
|
|
}
|
|
|
|
public List<DirectionalSearchResult<TIndexType>> FindAtPosition(IDataIndex<TIndexType> currentPosition, List<TDataType> data, Direction directions)
|
|
{
|
|
var results = new List<DirectionalSearchResult<TIndexType>>();
|
|
var givenDirections = this.SimplifyDirections(directions);
|
|
if (EqualityComparer<TDataType>.Default.Equals(this.indexer.Get(this.dataSet, currentPosition), data[0]))
|
|
{
|
|
// found valid search start point, now validate each given direction
|
|
foreach (var direction in givenDirections)
|
|
{
|
|
int searchIndex = 1;
|
|
var searchPosition = this.Move(currentPosition, direction); ;
|
|
while (searchIndex < data.Count && this.IsValidIndex(searchPosition)
|
|
&& EqualityComparer<TDataType>.Default.Equals(this.indexer.Get(this.dataSet, searchPosition), data[searchIndex]))
|
|
{
|
|
searchPosition = this.Move(searchPosition, direction);
|
|
searchIndex++;
|
|
}
|
|
if (searchIndex == data.Count)
|
|
{
|
|
var result = new DirectionalSearchResult<TIndexType>(currentPosition, direction, searchIndex);
|
|
results.Add(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
public List<DirectionalSearchResult<TIndexType>> FindInSet(List<TDataType> data, Direction directions)
|
|
{
|
|
var result = new List<DirectionalSearchResult<TIndexType>>();
|
|
|
|
// find valid starting points in set and perform search from there
|
|
var startingPoints = this.FindInSet(data[0]);
|
|
foreach (var startingPoint in startingPoints)
|
|
{
|
|
foreach (var results in this.FindAtPosition(startingPoint.DataIndex, data, directions))
|
|
{
|
|
result.AddRange(results);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public List<DirectionalSearchResult<TIndexType>> FindInSet(List<TDataType> data)
|
|
{
|
|
return this.FindInSet(data, this.ValidDirections());
|
|
}
|
|
} |