| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
-
- namespace Buhnenrennen
- {
- class Field
- {
- public Dictionary<double, List<Groyne>> Groynes { get; private set; }
- Regex groynSchema = new Regex( "(?<type>[A-Z]) (?<level>[0-9]+) (?<yCoord>[0-9\\.]+)", RegexOptions.IgnoreCase );
-
- private Field( IEnumerable<string> groynes )
- {
- Groynes = new Dictionary<double, List<Groyne>>();
- Match m;
- foreach( string groyn in groynes )
- {
- if ( ( m = groynSchema.Match( groyn ) ).Success )
- {
- char type = m.Groups[ "type" ].Value.FirstOrDefault();
- // Forcing a multiple of 70 by using '/ 70 * 70'
- int level = int.Parse( m.Groups[ "level" ].Value ) / 70 * 70;
- double yCoord = double.Parse( m.Groups[ "yCoord" ].Value );
- if ( !this.Groynes.ContainsKey( level ) ) this.Groynes.Add( level, new List<Groyne>() );
- this.Groynes[ level ].Add( new Groyne( yCoord, type ) );
- }
- }
- }
-
- /**
- * <summary>returns a field object loaded from entries out of File at {filename}</summary>
- * <param name="filename">Location of the file to read</param>
- */
- public static Field fromFile( string filename )
- {
- return new Field( File.ReadAllLines( filename ) );
- }
-
- /**
- * <summary>returns a dictionary with groynes and the fastest times the give dog is able to reach them</summary>
- * <param name="dog">dog that is running to the groynes</param>
- */
-
- 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;
- }
-
- /**
- * <summary>returns the fastest route for {hunted} where {hunted} will always be faster than {hunter}</summary>
- * <param name="hunted">The dog, which will be hunted and is not to be catched ( Minnie )</param>
- * <param name="hunter">The dog, with the desire to hunt the {hunted} dog ( Max )</param>
- */
- 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();
- }
- }
- }
|