protected ProblemOutput Solve2(ProblemInput input) { var dictionary = input.Photos.GroupBy(photo => photo.IsVertical).ToDictionary(photos => photos.Key); IEnumerable <Photo> vertical = dictionary.ContainsKey(true) ? dictionary[true] : (IEnumerable <Photo>)Array.Empty <Photo>(); IEnumerable <Photo> horizontal = dictionary.ContainsKey(false) ? dictionary[false] : (IEnumerable <Photo>)Array.Empty <Photo>(); var slides = horizontal.Select(photo => new Slide(new List <Photo> { photo })) .Concat(VerticalUnifier.GetUnified(vertical.ToList(), NumbersGenerator)).ToList(); Dictionary <string, List <Slide> > tagToImages = new Dictionary <string, List <Slide> >(); // HashSet<string> tags = new HashSet<string>(); foreach (var image in slides) { foreach (var tag in image.Tags) { // tags.Add(tag); if (tagToImages.ContainsKey(tag)) { tagToImages[tag].Add(image); } else { tagToImages.Add(tag, new List <Slide>() { image }); } } } ProblemOutput res = new ProblemOutput(); res.Slides = new List <Slide>(); HashSet <int> takenPhotos = new HashSet <int>(); int count = 1; int index = 1; int lastTaken = 0; var first = GetFirstSlide(takenPhotos, slides); res.Slides.Add(first); takenPhotos.Add(first.Images[0].Index); if (first.Images.Count == 2) { takenPhotos.Add(first.Images[1].Index); } while (count < input.Photos.Length && index < slides.Count) { count++; var photo = res.Slides[res.Slides.Count - 1]; Slide nextSlide = GetNextSlide(tagToImages, takenPhotos, slides, photo); if (nextSlide == null) { var randomSlide = GetFirstSlide(takenPhotos, slides); if (randomSlide == null) { break; } takenPhotos.Add(randomSlide.Images[0].Index); if (randomSlide.Images.Count == 2) { takenPhotos.Add(randomSlide.Images[1].Index); } res.Slides.Add(randomSlide); } else { takenPhotos.Add(nextSlide.Images[0].Index); if (nextSlide.Images.Count == 2) { takenPhotos.Add(nextSlide.Images[1].Index); } res.Slides.Add(nextSlide); } } return(res); }
private Slide GetNextSlide(Dictionary <string, List <Slide> > tagToImages, HashSet <int> takenPhotos, List <Slide> input, Slide firstPhoto) { int maxScore = 0; int threshold = 4; Slide nex = null; foreach (var tag in firstPhoto.Tags) { if (tagToImages[tag].Count == 1) { continue; } foreach (var optionalImage in tagToImages[tag]) { bool isTaken = false; if (optionalImage.Images.Count == 1) { isTaken = takenPhotos.Contains(optionalImage.Images[0].Index); } else { isTaken = takenPhotos.Contains(optionalImage.Images[0].Index) || takenPhotos.Contains(optionalImage.Images[1].Index); } if (!isTaken) { var score = Calcutaor.CalculatePhotosScore(firstPhoto, optionalImage); if (score >= maxScore) { maxScore = score; nex = optionalImage; if (maxScore > threshold) { return(nex); } } } } } return(nex); }
protected override ProblemOutput Solve(ProblemInput input) { var allPhotos = input.Photos.ToArray(); var totalTags = input.TagCount; var usedInASlideC = new ConcurrentDictionary <long, byte>(); var usedInASlide = new HashSet <long>(); Slide lastSlide; ////for (int i = 0; i < allPhotos.Length; i++) ////{ //// var bestScore = -1; //// for (int j = 0; j < allPhotos.Length; j++) //// { //// int currScore = -1; //// if (visited.Contains(j)) //// { //// continue; //// } //// currScore = CalclateScoreForCurrentSlide(lastSlide, allPhotos[i], allPhotos[j]); //// if (bestScore < currScore) //// { //// } //// } ////} // Build First Slide List <Slide> slides = new List <Slide>(); if (!allPhotos.First().IsVertical) { lastSlide = new Slide(new List <Photo>() { allPhotos.First() }); } else { lastSlide = new Slide(new List <Photo>() { allPhotos.First(), allPhotos.Skip(1).First(_ => _.IsVertical) }); } slides.Add(lastSlide); foreach (var photo in lastSlide.Images) { usedInASlide.Add(photo.Index); usedInASlideC.TryAdd(photo.Index, 0); } var lastSlideTagsBool = new bool[input.TagCount]; var pairTagsBool = new bool[input.TagCount]; while (usedInASlide.Count != allPhotos.Length) { Array.Clear(lastSlideTagsBool, 0, lastSlideTagsBool.Length); int lastSlideTagCount = 0; foreach (var tagIndex in lastSlide.TagsIndexes) { lastSlideTagsBool[tagIndex] = true; lastSlideTagCount++; } // build a slide long bestScore = -1; Slide slideToUse = null; Parallel.ForEach(Partitioner.Create(1, allPhotos.Length), range => { for (int i = range.Item1; i < range.Item2; i++) { if (usedInASlideC.ContainsKey(i)) { continue; } // Build a slide with this photo var potentialSlide = new Slide(new List <Photo>() { allPhotos[i] }); long ScoreIfUsed = CalculateScoreForNewSlide(allPhotos[i], lastSlideTagsBool, lastSlideTagCount); if (ParallelHelper.InterlockedExchangeIfGreaterThan(ref bestScore, ScoreIfUsed)) { // use this //bestScore = ScoreIfUsed; lock (slides) { slideToUse = potentialSlide; } } } }); //for (int i = 1; i < allPhotos.Length; i++) //{ // // Skip if already used // if (usedInASlide.Contains(i)) // { // continue; // } // // Build a slide with this photo // var potentialSlide = new Slide(new List<Photo>() { allPhotos[i] }); // long ScoreIfUsed = CalculateScoreForNewSlide(allPhotos[i], lastSlideTagsBool, lastSlideTagCount); // if (bestScore < ScoreIfUsed) // { // // use this // slideToUse = potentialSlide; // bestScore = ScoreIfUsed; // } //} // if slideToUse is lonely V, find it a pair: if (slideToUse.Images.First().IsVertical) { // Build Pair Bool Array.Clear(pairTagsBool, 0, pairTagsBool.Length); foreach (var tagindex in slideToUse.Images.First().TagIndexes) { pairTagsBool[tagindex] = true; } long bestScoreForV = -1; Photo vPair = null; object lockpair = new object(); Parallel.ForEach(Partitioner.Create(1, allPhotos.Length), range => { for (int i = range.Item1; i < range.Item2; i++) { if (usedInASlideC.ContainsKey(i) || !allPhotos[i].IsVertical || i == slideToUse.Images.First().Index) { continue; } long scoreIfUsed = CalculateScoreForVPair(lastSlideTagsBool, lastSlideTagCount, slideToUse.Images.First(), allPhotos[i], pairTagsBool); if (ParallelHelper.InterlockedExchangeIfGreaterThan(ref bestScoreForV, scoreIfUsed)) { lock (lockpair) { vPair = allPhotos[i]; } } } }); //for (int i = 0; i < allPhotos.Length; i++) //{ // if (usedInASlide.Contains(i) || !allPhotos[i].IsVertical || i == slideToUse.Images.First().Index) // { // continue; // } // ////foreach (var tagIndex in allPhotos[i].TagIndexes) // ////{ // //// pairTagsBool[tagIndex] = true; // ////} // long scoreIfUsed = CalculateScoreForVPair(lastSlideTagsBool, lastSlideTagCount, slideToUse.Images.First(), allPhotos[i]); // if (bestScoreForV < scoreIfUsed) // { // vPair = allPhotos[i]; // bestScoreForV = scoreIfUsed; // } //} if (vPair == null) { var vertsNotUsed = allPhotos.Where(p => p.IsVertical && !usedInASlide.Contains(p.Index)).ToArray(); } slideToUse.Images.Add(vPair); } slides.Add(slideToUse); foreach (var photo in slideToUse.Images) { usedInASlide.Add(photo.Index); usedInASlideC.TryAdd(photo.Index, 0); } lastSlide = slideToUse; } return(new ProblemOutput() { Slides = slides }); }