Pārlūkot izejas kodu

Added Dog class for holding dog-specific data and readonly static properties with the actual data of our two dogs

Added Field for holding data of all groynes and calculating routes with it
added Groyne for holding data of a single groyne (just Y-Coordinate and the type, not X-Coordinate)
Added GroyneRun for actually running the algorithm
Added TimedGroyn for holding data of the required time between two groynes and the groynes itself (contains recursively the full route back to the root groyne)
master
benjamin.m pirms 5 gadiem
vecāks
revīzija
f20d35610d

+ 5
- 0
Buhnenrennen/Buhnenrennen.csproj Parādīt failu

@@ -43,8 +43,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Dog.cs" />
<Compile Include="Field.cs" />
<Compile Include="Groyne.cs" />
<Compile Include="GroyneRun.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TimedGroyne.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />

+ 30
- 0
Buhnenrennen/Dog.cs Parādīt failu

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Buhnenrennen
{
class Dog
{
public static readonly Dog MINNIE = new Dog( 'M', new char[] { 'm', 'x', 'M' }, 20 );
public static readonly Dog MAX = new Dog( 'X', new char[] { 'x', 'X' }, 30 );

private char[] fitsThrough;
public char[] FitsThrough => this.fitsThrough;
private double meterPerSecond;
public double MeterPerSecond => this.meterPerSecond;
private char start;
public char Start => this.start;

private Dog( char start, char[] fitsThrough, double kmh )
{
this.start = start;
this.fitsThrough = fitsThrough;
// km/h : 3,6 = m/s ( Formula found through google )
this.meterPerSecond = kmh / 3.6;
}
}
}

+ 112
- 0
Buhnenrennen/Field.cs Parādīt failu

@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Buhnenrennen
{
class Field
{
private Dictionary<double, List<Groyne>> groynes;
public Dictionary<double, List<Groyne>> Groynes => this.groynes;

public Field( Groyne[] level0, Groyne[] level1, Groyne[] level2, Groyne[] level3 )
{
groynes = new Dictionary<double, List<Groyne>>();
groynes.Add( 0, level0.ToList() );
groynes.Add( 70, level1.ToList() );
groynes.Add( 140, level2.ToList() );
groynes.Add( 210, level3.ToList() );
}

public Groyne[] findShortestPath( Dog dog )
{
List<Groyne> poles = new List<Groyne>();
Groyne start = groynes[ 0 ].Find( groyne => groyne.Type == dog.Start );
if ( start == null ) throw new Exception( "No start position found" );
poles.Add( start );

Groyne previous = start;
for( int level = 70; level <= groynes.Keys.Max(); level += 70 )
{
List<Groyne> candidates = groynes[ level ].Where( groyne => groyne.canPass( dog ) ).ToList();
var distances = candidates.Select( groyne => groyne.distanceTo( previous ) ).ToList();
var minDistance = distances.Min();
previous = candidates[ distances.IndexOf( minDistance ) ];
poles.Add( previous );
}

return poles.ToArray();
}

public TimedGroyne findFastestPath( Dog dog )
{
Groyne start = groynes[ 0 ].Find( groyne => groyne.Type == dog.Start );
if ( start == null ) throw new Exception( "No start position found" );

Groyne lastLevel = start;
Dictionary<int, List<TimedGroyne>> times = new Dictionary<int, List<TimedGroyne>>();
times.Add( 0, new TimedGroyne[] { new TimedGroyne( null, start, 0 ) }.ToList() );
for ( int level = 70; level <= groynes.Keys.Max(); level += 70 )
{
List<TimedGroyne> subTimes = new List<TimedGroyne>();
List<TimedGroyne> passables = times[ level - 70 ].Where( time => time.Groyne.canPass( dog ) ).ToList();
foreach ( Groyne groyne in groynes[ level ] )
{
List<TimedGroyne> possibleTimes = passables.Select( passable => new TimedGroyne( passable, groyne, passable.TotalTime + groyne.requiredTimeTo( passable.Groyne, dog ) ) ).ToList();
subTimes.Add( possibleTimes.OrderBy( time => time.TotalTime ).First() );
}
times.Add( level, subTimes );
}
return times[ 3 ].OrderBy( time => time.TotalTime ).First();
}

public Dictionary<double, List<TimedGroyne>> listFastestTimes( Dog dog )
{
Groyne start = groynes[ 0 ].Find( groyne => groyne.Type == dog.Start );
if ( start == null ) throw new Exception( "No start position found" );

Groyne lastLevel = start;
Dictionary<double, List<TimedGroyne>> times = new Dictionary<double, List<TimedGroyne>>();
times.Add( 0, new TimedGroyne[] { new TimedGroyne( null, start, 0 ) }.ToList() );
for ( int level = 70; level <= groynes.Keys.Max(); level += 70 )
{
List<TimedGroyne> subTimes = new List<TimedGroyne>();
List<TimedGroyne> passables = times[ level - 70 ].Where( time => time.Groyne.canPass( dog ) ).ToList();
foreach ( Groyne groyne in groynes[ level ] )
{
List<TimedGroyne> possibleTimes = passables.Select( passable => new TimedGroyne( passable, groyne, passable.TotalTime + groyne.requiredTimeTo( passable.Groyne, dog ) ) ).ToList();
subTimes.Add( possibleTimes.OrderBy( time => time.TotalTime ).FirstOrDefault() );
}
times.Add( level, subTimes );
}
return times;
}

public TimedGroyne getFastestSafeRoute( Dog hunter, Dog hunted )
{
var hunterMap = listFastestTimes( hunter );
var huntedMap = listFastestTimes( hunted );

List<Groyne> safeGroynes = new List<Groyne>();
safeGroynes.Add( groynes[ 0 ].Find( groyne => groyne.Type == hunted.Start ) );

for ( int level = 70; level <= groynes.Keys.Max(); level += 70 )
{
var huntedTimes = huntedMap[ level ];
var hunterTimes = hunterMap[ level ];

foreach( TimedGroyne time in huntedTimes )
{
if ( !safeGroynes.Contains( time.ParentGroyne.Groyne ) ) continue;
TimedGroyne hunterTime = hunterTimes.Find( _hunterTime => _hunterTime.Groyne == time.Groyne );
if ( hunterTime.TotalTime > time.TotalTime ) safeGroynes.Add( time.Groyne );
}
}

return huntedMap[ groynes.Keys.Max() ].Where( huntedRoute => safeGroynes.Contains( huntedRoute.Groyne ) ).OrderBy( huntedRoute => huntedRoute.TotalTime ).FirstOrDefault();
}
}
}

+ 34
- 0
Buhnenrennen/Groyne.cs Parādīt failu

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Buhnenrennen
{
class Groyne
{
private double yCoord;
public double YCoord => this.yCoord;
private char type;
public char Type => this.type;

public Groyne( double yCoord, char type )
{
this.yCoord = yCoord;
this.type = type;
}

public bool canPass( Dog dog ) => dog.FitsThrough.Contains( Type );

public double distanceTo( Groyne groyne ) =>
// distance: distance² = A² + B²
// A: 70
// B: difference of Y-Coordinates
Math.Sqrt( Math.Pow( 70, 2 ) + Math.Pow( YCoord - groyne.YCoord, 2 ) );

public double requiredTimeTo( Groyne groyne, Dog dog ) => distanceTo( groyne ) / dog.MeterPerSecond;

public override string ToString() => Type + "( " + YCoord + " )";
}
}

+ 51
- 0
Buhnenrennen/GroyneRun.cs Parādīt failu

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Buhnenrennen
{
class GroyneRun
{
public void Start()
{
Field field = new Field(
new Groyne[] {
new Groyne( 42.95, 'M' ),
new Groyne( 168.6, 'X' )
},
new Groyne[] {
new Groyne( 76.4, 'm' ),
new Groyne( 45.9, 'x' ),
new Groyne( 117.4, 'm' )
},
new Groyne[] {
new Groyne( 42.2, 'm' ),
new Groyne( 109.35, 'm' ),
new Groyne( 158.7, 'x' )
},
new Groyne[] {
new Groyne( 49.4, 'm' ),
new Groyne( 83.1, 'm' ),
new Groyne( 148.7, 'x' ),
new Groyne( 103.5 , 'x' )
}
);

TimedGroyne safePath = field.getFastestSafeRoute( Dog.MAX, Dog.MINNIE );

if ( safePath == null )
{
Console.WriteLine( "Es gibt leider keine sichere Route..." );
}
else
{
Console.WriteLine( "Die sichere Route für Minnie ist: " + string.Join( " -> ", safePath.FullRoute.Select( routePart => routePart.Groyne.ToString() ) ) );
Console.WriteLine( "Minnie braucht für sie ~" + Math.Round( safePath.TotalTime ) + " Sekunde(n) ( ~" + Math.Round( safePath.TotalTime / 60 ) + " Minute(n) )" );
}

Console.ReadKey();
}
}
}

+ 5
- 0
Buhnenrennen/Program.cs Parādīt failu

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;

@@ -8,8 +9,12 @@ namespace Buhnenrennen
{
class Program
{
// Buhne (de) = Groyne (en)

static void Main( string[] args )
{
GroyneRun run = new GroyneRun();
run.Start();
}
}
}

+ 32
- 0
Buhnenrennen/TimedGroyne.cs Parādīt failu

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Buhnenrennen
{
class TimedGroyne
{
public TimedGroyne ParentGroyne { get; set; }
public Groyne Groyne { get; set; }
public double TotalTime { get; set; }

public List<TimedGroyne> FullRoute {
get {
List<TimedGroyne> fullRoute;
if ( ParentGroyne != null ) fullRoute = ParentGroyne.FullRoute;
else fullRoute = new List<TimedGroyne>();
fullRoute.Add( this );
return fullRoute;
}
}

public TimedGroyne( TimedGroyne parentGroyne, Groyne groyne, double time )
{
ParentGroyne = parentGroyne;
Groyne = groyne;
TotalTime = time;
}
}
}

Binārs
Buhnenrennen/bin/Debug/Buhnenrennen.exe Parādīt failu


+ 6
- 0
Buhnenrennen/bin/Debug/Buhnenrennen.exe.config Parādīt failu

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>

Binārs
Buhnenrennen/bin/Debug/Buhnenrennen.pdb Parādīt failu


Notiek ielāde…
Atcelt
Saglabāt