Skip to content

Commit

Permalink
Abstract List<T> into ITableList<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
joelverhagen committed Jan 20, 2024
1 parent a830430 commit f0b9583
Show file tree
Hide file tree
Showing 51 changed files with 1,064 additions and 559 deletions.
5 changes: 5 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
<DefineConstants Condition="$(UseBitArray) == 'true'">$(DefineConstants);USE_BITARRAY</DefineConstants>
</PropertyGroup>

<PropertyGroup>
<UseArray Condition="'$(UseArray)' == ''">true</UseArray>
<DefineConstants Condition="$(UseArray) == 'true'">$(DefineConstants);USE_ARRAY</DefineConstants>
</PropertyGroup>

<PropertyGroup>
<LocationAsStruct Condition="'$(LocationAsStruct)' == ''">true</LocationAsStruct>
<DefineConstants Condition="$(LocationAsStruct) == 'true'">$(DefineConstants);LOCATION_AS_STRUCT</DefineConstants>
Expand Down
118 changes: 100 additions & 18 deletions src/FactorioTools/CollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,26 @@ public static ILocationDictionary<TValue> ToDictionary<TItem, TValue>(
return dictionary;
}

public static List<Location> Distinct(this IReadOnlyCollection<Location> locations, Context context)
public static ILocationDictionary<TValue> ToDictionary<TItem, TValue>(
this IReadOnlyTableList<TItem> items,
Context context,
Func<TItem, Location> keySelector,
Func<TItem, TValue> valueSelector)
{
var dictionary = context.GetLocationDictionary<TValue>(items.Count);
for (var i = 0; i < items.Count; i++)
{
var item = items[i];
dictionary.Add(keySelector(item), valueSelector(item));
}

return dictionary;
}

public static ITableList<Location> Distinct(this IReadOnlyCollection<Location> locations, Context context)
{
var set = context.GetLocationSet(locations.Count);
var output = new List<Location>(locations.Count);
var output = TableList.New<Location>(locations.Count);
foreach (var location in locations)
{
if (set.Add(location))
Expand All @@ -41,25 +57,74 @@ public static List<Location> Distinct(this IReadOnlyCollection<Location> locatio
return output;
}

public static ILocationSet ToSet(this IReadOnlyCollection<Location> locations, Context context)
{
return locations.ToSet(context, allowEnumerate: false);
}

public static ILocationSet ToSet(this IReadOnlyCollection<Location> locations, Context context, bool allowEnumerate)
{
return context.GetLocationSet(locations, allowEnumerate);
var set = context.GetLocationSet(allowEnumerate);
foreach (var location in locations)
{
set.Add(location);
}

return set;
}

public static ILocationSet ToReadOnlySet(this IReadOnlyCollection<Location> locations, Context context)
{
return context.GetReadOnlyLocationSet(locations);
return locations.ToReadOnlySet(context, allowEnumerate: false);
}

public static ILocationSet ToReadOnlySet(this IReadOnlyCollection<Location> locations, Context context, bool allowEnumerate)
{
return context.GetReadOnlyLocationSet(locations, allowEnumerate);
Location firstLocation = Location.Invalid;
int itemCount = 0;
ILocationSet? set = null;
foreach (var location in locations)
{
if (itemCount == 0)
{
firstLocation = location;
}
else if (itemCount == 1)
{
set = context.GetLocationSet(allowEnumerate);
set.Add(firstLocation);
set.Add(location);
}
else
{
set!.Add(location);
}

itemCount++;
}

if (set is null)
{
if (itemCount == 0)
{
set = EmptyLocationSet.Instance;
}
else if (itemCount == 1)
{
set = context.GetSingleLocationSet(firstLocation);
}
else
{
throw new NotImplementedException();
}
}
return set;
}

#if ENABLE_VISUALIZER
public static List<DelaunatorSharp.IPoint> ToDelaunatorPoints(this ILocationSet set)
public static ITableList<DelaunatorSharp.IPoint> ToDelaunatorPoints(this ILocationSet set)
{
var points = new List<DelaunatorSharp.IPoint>();
var points = TableList.New<DelaunatorSharp.IPoint>();
foreach (var item in set.EnumerateItems())
{
points.Add(new DelaunatorSharp.Point(item.X, item.Y));
Expand All @@ -68,9 +133,9 @@ public static ILocationSet ToReadOnlySet(this IReadOnlyCollection<Location> loca
return points;
}

public static List<DelaunatorSharp.IPoint> ToDelaunatorPoints<T>(this ILocationDictionary<T> dictionary)
public static ITableList<DelaunatorSharp.IPoint> ToDelaunatorPoints<T>(this ILocationDictionary<T> dictionary)
{
var points = new List<DelaunatorSharp.IPoint>();
var points = TableList.New<DelaunatorSharp.IPoint>();
foreach (var item in dictionary.Keys)
{
points.Add(new DelaunatorSharp.Point(item.X, item.Y));
Expand Down Expand Up @@ -186,9 +251,27 @@ public static ILocationSet ToReadOnlySet(this IReadOnlyCollection<Location> loca
return min;
}

public static List<TSource> ToList<TSource>(this IReadOnlyCollection<TSource> source)
public static TSource[] ToArray<TSource>(this IReadOnlyTableList<TSource> source)
{
var output = new TSource[source.Count];
for (var i = 0; i < source.Count; i++)
{
output[i] = source[i];
}

return output;
}

public static ITableList<TSource> ToTableList<TSource>(this IReadOnlyCollection<TSource> source)
{
var output = TableList.New<TSource>(source.Count);
output.AddCollection(source);
return output;
}

public static ITableList<TSource> ToTableList<TSource>(this IReadOnlyTableList<TSource> source)
{
var output = new List<TSource>(source.Count);
var output = TableList.New<TSource>(source.Count);
output.AddRange(source);
return output;
}
Expand Down Expand Up @@ -269,11 +352,10 @@ public static TSource First<TSource>(this IReadOnlyCollection<TSource> source, F
throw new FactorioToolsException("An item should have matched the predicate.");
}

public static TSource? FirstOrDefault<TSource>(this IReadOnlyList<TSource> source, Func<TSource, bool> predicate)
public static TSource? FirstOrDefault<TSource>(this IReadOnlyCollection<TSource> source, Func<TSource, bool> predicate)
{
for (int i = 0; i < source.Count; i++)
foreach (var item in source)
{
var item = source[i];
if (predicate(item))
{
return item;
Expand Down Expand Up @@ -301,7 +383,7 @@ public static double Average<TSource>(this IReadOnlyCollection<TSource> source,
return sum / count;
}

public static bool SequenceEqual<TSource>(this IReadOnlyList<TSource> first, IReadOnlyList<TSource> second)
public static bool SequenceEqual<TSource>(this IReadOnlyTableList<TSource> first, IReadOnlyTableList<TSource> second)
{
if (first.Count != second.Count)
{
Expand All @@ -321,12 +403,12 @@ public static bool SequenceEqual<TSource>(this IReadOnlyList<TSource> first, IRe
return true;
}

public static int Sum<TSource>(this IReadOnlyList<TSource> source, Func<TSource, int> selector)
public static int Sum<TSource>(this IReadOnlyCollection<TSource> source, Func<TSource, int> selector)
{
var sum = 0;
for (var i = 0; i < source.Count; i++)
foreach (var item in source)
{
sum += selector(source[i]);
sum += selector(item);
}

return sum;
Expand Down
12 changes: 10 additions & 2 deletions src/FactorioTools/OilField/Algorithms/AStar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@ namespace Knapcode.FactorioTools.OilField;
/// </summary>
public static class AStar
{
public static AStarResult GetShortestPath(Context context, SquareGrid grid, Location start, ILocationSet goals, bool preferNoTurns = true, int xWeight = 1, int yWeight = 1, List<Location>? outputList = null)
public static AStarResult GetShortestPath(
Context context,
SquareGrid grid,
Location start,
ILocationSet goals,
bool preferNoTurns = true,
int xWeight = 1,
int yWeight = 1,
ITableList<Location>? outputList = null)
{
if (goals.Contains(start))
{
Expand All @@ -20,7 +28,7 @@ public static AStarResult GetShortestPath(Context context, SquareGrid grid, Loca
}
else
{
outputList = new List<Location> { start };
outputList = TableList.New(start);
}

return new AStarResult(success: true, start, outputList);
Expand Down
6 changes: 3 additions & 3 deletions src/FactorioTools/OilField/Algorithms/AStarResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace Knapcode.FactorioTools.OilField;

public class AStarResult
{
private readonly List<Location>? _path;
private readonly ITableList<Location>? _path;

public AStarResult(bool success, Location reachedGoal, List<Location>? path)
public AStarResult(bool success, Location reachedGoal, ITableList<Location>? path)
{
Success = success;
ReachedGoal = reachedGoal;
Expand All @@ -16,7 +16,7 @@ public AStarResult(bool success, Location reachedGoal, List<Location>? path)
public bool Success { get; }
public Location ReachedGoal { get; }

public List<Location> Path
public ITableList<Location> Path
{
get
{
Expand Down
4 changes: 2 additions & 2 deletions src/FactorioTools/OilField/Algorithms/BreadthFirstFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Knapcode.FactorioTools.OilField
{
public static class BreadthFirstFinder
{
public static List<Location>? GetShortestPath(Context context, Location start, Location goal)
public static ITableList<Location>? GetShortestPath(Context context, Location start, Location goal)
{
#if !USE_SHARED_INSTANCES
var toExplore = new Queue<Location>();
Expand Down Expand Up @@ -40,7 +40,7 @@ public static class BreadthFirstFinder

if (current == goal)
{
var output = new List<Location> { current };
var output = TableList.New(current);
while (parents.TryGetValue(current, out var parent))
{
output.Add(parent);
Expand Down
4 changes: 2 additions & 2 deletions src/FactorioTools/OilField/Algorithms/BresenhamsLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ namespace Knapcode.FactorioTools.OilField;

public static class BresenhamsLine
{
public static List<Location> GetPath(Location a, Location b)
public static ITableList<Location> GetPath(Location a, Location b)
{
var line = new List<Location>();
var line = TableList.New<Location>();
var dx = Math.Abs(b.X - a.X);
var sx = a.X < b.X ? 1 : -1;
var dy = -1 * Math.Abs(b.Y - a.Y);
Expand Down
8 changes: 4 additions & 4 deletions src/FactorioTools/OilField/Algorithms/DijkstrasResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ public DijkstrasResult(ILocationDictionary<ILocationSet> locationToPrevious, ILo
public ILocationDictionary<ILocationSet> LocationToPrevious { get; }
public ILocationSet ReachedGoals { get; }

public List<List<Location>> GetStraightPaths(Location goal)
public ITableList<ITableList<Location>> GetStraightPaths(Location goal)
{
var paths = new List<List<Location>>();
var paths = TableList.New<ITableList<Location>>();

if (LocationToPrevious.TryGetValue(goal, out var previousLocations))
{
if (previousLocations.Count == 0)
{
// This is a special case when the goal matches the starting point.
paths.Add(new List<Location> { goal });
paths.Add(TableList.New(goal));
}

foreach (var beforeGoal in previousLocations.EnumerateItems())
Expand All @@ -43,7 +43,7 @@ public List<List<Location>> GetStraightPaths(Location goal)
};

var current = goal;
var path = new List<Location>();
var path = TableList.New<Location>();
while (true)
{
path.Add(current);
Expand Down
4 changes: 3 additions & 1 deletion src/FactorioTools/OilField/Algorithms/Prims.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ public static ILocationDictionary<ILocationSet> GetMinimumSpanningTree(
if (!digraph)
{
// Make the MST bidirectional (a graph, not a digraph).
foreach (var center in mst.Keys.ToList())
var keys = mst.Keys.ToTableList();
for (var i = 0; i < keys.Count; i++)
{
var center = keys[i];
foreach (var neighbor in mst[center].EnumerateItems())
{
if (!mst.TryGetValue(neighbor, out var otherNeighbors))
Expand Down
Loading

0 comments on commit f0b9583

Please sign in to comment.