//----==== PRIVATE ====---------------------------------------------------------------------- private void AddToTopList(IMovieList sample) { if (_topLists != null) { if (!_topListFull) { _topLists.Add(sample.Clone()); _topMin = _topLists.Min(list => list.TotalEarnings); _topListFull = _topLists.Count >= _topCount; } else { // Is the sample greater than the top min? // Don't add it if it's already in the list. if (sample.TotalEarnings > _topMin && !_topLists.Any(list => list.GetHashCode() == sample.GetHashCode())) { // Remove the min and add a clone of the sample. _topLists.Remove(_topLists.First(list => list.TotalEarnings == _topMin)); _topLists.Add(sample.Clone()); _topMin = _topLists.Min(list => list.TotalEarnings); } } } }
private void AddToListAlreadyGenerated(List <IMovie> movies) { var movieList = _movieListPrototype.Clone(); movieList.Add(movies); _listGenerated.Add(movieList.GetHashCode()); }
/// <summary> /// The recursive call to find the best of the sample. /// </summary> /// <param name="best">The BEST earnings so far.</param> /// <param name="movieToAdd">The movie to be added to the list.</param> /// <param name="sample">Current movie list</param> /// <param name="movies">Sending in a smaller set each time reduces the scan on the full movie list.</param> /// <param name="remainingBudget"></param> /// <returns></returns> private IMovieList ChooseBest(IMovieList best, IMovie movieToAdd, IMovieList sample, IEnumerable <IMovie> movies, decimal remainingBudget) { if (sample == null) { sample = _movieListPrototype.Clone(); } if (sample.CanAdd(movieToAdd)) { // Add the movie to the clone that was passed in. sample.Add(movieToAdd); TotalComparisons++; var sampleHashCode = sample.GetHashCode(); var beenProcessed = _processedHashes.Contains(sampleHashCode); // DON'T PROCESS the sample: // If the sample is already full // Already been processed. if (_topLists != null && !beenProcessed) { AddToTopList(sample); } else if (best.TotalEarnings < sample.TotalEarnings) { best = sample.Clone(); } if (!sample.IsFull && !beenProcessed) { remainingBudget -= movieToAdd.Cost; var availableMovies = AvailableMovies(movies, remainingBudget).ToList(); foreach (var movie in availableMovies) { // Cloning is now cheaper than adding and removing. best = ChooseBest(best, movie, sample.Clone(), availableMovies, remainingBudget); //best = ChooseBest(best, movie, sample, availableMovies, remainingBudget); } // When finished processing this sub-list, store the list in the saved hashes. _processedHashes.Add(sampleHashCode); } //sample.Remove(movieToAdd); } return(best); }
public IMovieList ChooseBest() { IMovieList best = _movieListPrototype.Clone(); var availableMovies = AvailableMovies(_movies, TotalCost).ToList(); TotalComparisons = 0; _processedHashes.Clear(); foreach (var movie in availableMovies) { best = ChooseBest(best, movie, null, availableMovies, TotalCost); } return(best); }
public IMovieList ChooseBest2() { IMovieList best = _movieListPrototype.Clone(); var idx = 0; var maxMovies = _movies.Count; TotalComparisons = 0; foreach (var movie in _movies) { _movieArray[idx++] = movie; } // Create all 15 ^ 8 possibilities. (Kinda brute force, but it's worth a try.) // Recursive calls COULD be slow, but investigate that later. // Trying to also minimize the memory footprint. // Figure out how to use Dominance Relations to clip out some of the noise. _topCineplexes = new int[_topCount == 0 ? 1 : _topCount, ScreenCount + 1]; // Store the top cineplexes (add 1 for the total BO) _currentCineplex = new int[ScreenCount + 1]; for (int cineIdx = 0; cineIdx < _currentCineplex.Length; cineIdx++) { _currentCineplex[cineIdx] = -1; } for (int dim1 = 0; dim1 < maxMovies; dim1++) { _currentCineplex[0] = dim1; _currentCineplex[8] = (int)(_movieArray[dim1]?.Earnings ?? 0m); // Only adding one movie shouldn't break the bank, // so you shouldn't have to check to see if it is over the TotalCost for (int dim2 = 0; dim2 < maxMovies; dim2++) { var totalCost2 = _movieArray[dim1]?.Cost + _movieArray[dim2]?.Cost; _currentCineplex[1] = dim2; _currentCineplex[8] += (int)(_movieArray[dim2]?.Earnings ?? 0m); if (totalCost2 < TotalCost) { for (int dim3 = 0; dim3 < maxMovies; dim3++) { var totalCost3 = totalCost2 + _movieArray[dim3]?.Cost; if (totalCost3 < TotalCost) { // Keep adding dimensions... 8 screens if (_movieArray[dim1]?.Earnings + _movieArray[dim2]?.Earnings + _movieArray[dim3]?.Earnings > _topMin) { } } else { // Can't add any more. } } } else if (_currentCineplex[8] > _topMin) { ReplaceTopMinWithCurrent(); } TotalComparisons++; } } // Add the top cineplex to the result. for (int cineIdx = 0; cineIdx < _currentCineplex.Length - 1; cineIdx++) { var movie = _topCineplexes[0, cineIdx] >= 0 ? _movieArray[_topCineplexes[0, cineIdx]] : null; if (movie != null) { best.Add(movie); } } return(best); }