public void processVideos() { List result = findBestSequence(storage.list(), 0, timeSeconds); if (result.isEmpty()) throw new NoVideoAvailableException(); Collections.sort(result, new Comparator() { @Override public int compare(Advertisement o1, Advertisement o2) { if (o1.getAmountPerOneDisplaying() != o2.getAmountPerOneDisplaying()) { if (o1.getAmountPerOneDisplaying() > o2.getAmountPerOneDisplaying()) return -1; return 1; } return Integer.compare(o2.getDuration(), o1.getDuration()); } }); for (Advertisement video : result) { writeMessage(video.getName() + " is displaying... " + video.getAmountPerOneDisplaying() + ", " + (video.getAmountPerOneDisplaying() * 1000 / video.getDuration())); video.revalidate(); } } ArrayList findBestSequence(List videos, int startIndex, int durationLeft) { if (durationLeft == 0 || startIndex >= videos.size()) return new ArrayList<>(); if (durationLeft < videos.get(startIndex).getDuration() || videos.get(startIndex).getHits() <= 0) return findBestSequence(videos, startIndex + 1, durationLeft); ArrayList includeCurrentVideo = findBestSequence(videos, startIndex + 1, durationLeft - videos.get(startIndex).getDuration()); includeCurrentVideo.add(videos.get(startIndex)); ArrayList doNotIncludeCurrentVideo = findBestSequence(videos, startIndex + 1, durationLeft); if (calculateVideosCost(includeCurrentVideo) > calculateVideosCost(doNotIncludeCurrentVideo)) return includeCurrentVideo; if (calculateVideosCost(includeCurrentVideo) < calculateVideosCost(doNotIncludeCurrentVideo)) return doNotIncludeCurrentVideo; if (calculateVideosDuration(includeCurrentVideo) > calculateVideosDuration(doNotIncludeCurrentVideo)) return includeCurrentVideo; if (calculateVideosDuration(includeCurrentVideo) < calculateVideosDuration(doNotIncludeCurrentVideo)) return doNotIncludeCurrentVideo; if (includeCurrentVideo.size() > doNotIncludeCurrentVideo.size()) return doNotIncludeCurrentVideo; return includeCurrentVideo; } long calculateVideosCost (List videos) { long total = 0; for (Advertisement video : videos) { total += video.getAmountPerOneDisplaying(); } return total; } int calculateVideosDuration (List videos) { int total = 0; for (Advertisement video : videos) { total += video.getDuration(); } return total; }