Преглед на файлове

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 преди 5 години
родител
ревизия
f20d35610d
променени са 10 файла, в които са добавени 275 реда и са изтрити 0 реда
  1. 5
    0
      Buhnenrennen/Buhnenrennen.csproj
  2. 30
    0
      Buhnenrennen/Dog.cs
  3. 112
    0
      Buhnenrennen/Field.cs
  4. 34
    0
      Buhnenrennen/Groyne.cs
  5. 51
    0
      Buhnenrennen/GroyneRun.cs
  6. 5
    0
      Buhnenrennen/Program.cs
  7. 32
    0
      Buhnenrennen/TimedGroyne.cs
  8. Двоични данни
      Buhnenrennen/bin/Debug/Buhnenrennen.exe
  9. 6
    0
      Buhnenrennen/bin/Debug/Buhnenrennen.exe.config
  10. Двоични данни
      Buhnenrennen/bin/Debug/Buhnenrennen.pdb

+ 5
- 0
Buhnenrennen/Buhnenrennen.csproj Целия файл

@@ -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 Целия файл

@@ -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 Целия файл

@@ -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 Целия файл

@@ -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 Целия файл

@@ -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 Целия файл

@@ -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 Целия файл

@@ -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;
}
}
}

Двоични данни
Buhnenrennen/bin/Debug/Buhnenrennen.exe Целия файл


+ 6
- 0
Buhnenrennen/bin/Debug/Buhnenrennen.exe.config Целия файл

@@ -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>

Двоични данни
Buhnenrennen/bin/Debug/Buhnenrennen.pdb Целия файл


Loading…
Отказ
Запис