/// <summary> /// Reads the input /// </summary> /// <param name="filename">The file to read from</param> private static InputStructure ReadInput(string filename) { InputStructure input = new InputStructure(); using (var reader = File.OpenText(filename)) { List <string> lines = new List <string>(); var descriptor = reader.ReadIntegers(); input.NumVideos = descriptor[0]; input.NumEndpoints = descriptor[1]; input.NumRequestDescriptions = descriptor[2]; input.NumCacheServers = descriptor[3]; input.Capacity = descriptor[4]; input.VideoSizes = reader.ReadIntegers(); input.Endpoints = Enumerable.Range(0, input.NumEndpoints) .Select(_ => { var epDescriptor = reader.ReadIntegers(); int numConnections = epDescriptor[1]; return(new Endpoint { Number = _, Latency = epDescriptor[0], Connections = Enumerable.Range(0, numConnections) .Select(c => { var connLine = reader.ReadIntegers(); return new Connection { Id = connLine[0], Latency = connLine[1] }; }).ToArray() }); }) .ToArray(); input.Descriptions = Enumerable.Range(0, input.NumRequestDescriptions) .Select(_ => { var dDescriptor = reader.ReadIntegers(); return(new Description { VideoId = dDescriptor[0], EndpointId = dDescriptor[1], NumRequests = dDescriptor[2], }); }).ToArray(); } return(input); }
public static int Score(InputStructure input, OutputStructure output) { var cacheServers = output.CacheServerDescriptions .ToDictionary( x => x.Id, x => x.VideoIds.ToArray()); long sumSaved = 0; long sumRequests = 0; input.Descriptions .AsParallel() .ForAll(req => { var Rv = req.VideoId; var Re = req.EndpointId; var L = input.Endpoints[Re]; var Ld = input.Endpoints[Re].Latency; var fastestCacheServer = L.Connections .Select(x => new { Latency = x.Latency, Cache = cacheServers[x.Id] }) .Where(x => x.Cache.Contains(Rv)) .OrderBy(x => x.Latency) .FirstOrDefault(); var cacheServerLatency = fastestCacheServer?.Latency ?? int.MaxValue; var Lmin = Math.Min(cacheServerLatency, Ld); var saved = Ld - Lmin; var savedMicro = saved; Interlocked.Add(ref sumSaved, savedMicro * req.NumRequests); Interlocked.Add(ref sumRequests, req.NumRequests); }); return((int)((sumSaved * 1000) / sumRequests)); }
public static OutputStructure Process(InputStructure input) { var capacity = input.Capacity; var cacheServers = Enumerable.Range(0, input.NumCacheServers) .Select(i => new CacheServerDescription { Id = i, Usage = 0, VideoIds = new List <int>() }).ToDictionary(x => x.Id); var descs = input.Descriptions .AsParallel() .Select(req => { var Rv = req.VideoId; var Re = req.EndpointId; var L = input.Endpoints[Re]; var Ld = input.Endpoints[Re].Latency; var videoSize = input.VideoSizes[Rv]; var fastestCacheServerLatency = L.Connections .Select(x => new { Latency = x.Latency, Cache = cacheServers[x.Id] }) .OrderBy(x => x.Latency) .Select(x => x.Latency) .FirstOrDefault(); if (fastestCacheServerLatency == 0) { fastestCacheServerLatency = Ld; } var gain = Ld - fastestCacheServerLatency; var score = gain * req.NumRequests; return(new { x = req, Metric = score }); }) .OrderByDescending(x => x.Metric) .Select(x => x.x); foreach (var req in descs) { var Rv = req.VideoId; var Re = req.EndpointId; var L = input.Endpoints[Re]; var Ld = input.Endpoints[Re].Latency; var videoSize = input.VideoSizes[Rv]; var cacheServer = L.Connections .Select(x => new { Latency = x.Latency, Cache = cacheServers[x.Id], Left = capacity - cacheServers[x.Id].Usage }) .OrderBy(x => x.Latency) .Where(x => !x.Cache.VideoIds.Contains(Rv) && x.Left >= videoSize) .FirstOrDefault(); if (cacheServer == null) { continue; } cacheServer.Cache.VideoIds.Add(Rv); cacheServer.Cache.Usage += videoSize; } ; return(new OutputStructure { CacheServerDescriptions = cacheServers.Values.ToArray() }); }
/// <summary> /// Process input into output /// </summary> /// <param name="input">The input to process</param> private static OutputStructure Process(InputStructure input) { return(Processor.Process(input)); }