Skip to content

Instantly share code, notes, and snippets.

@ChristianWilkie
Created November 10, 2014 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChristianWilkie/48cda58d2ed08d69d451 to your computer and use it in GitHub Desktop.
Save ChristianWilkie/48cda58d2ed08d69d451 to your computer and use it in GitHub Desktop.
[11/05/2014] Challenge #187 [Intermediate] Finding Time to Reddit
package com.christianwilkie;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* Created by chris on 11/9/2014.
*/
public class PostItNote implements Comparable<PostItNote>{
private static final DateTimeFormatter printedDateFormatter = DateTimeFormatter.ofPattern("MM-dd-yyyy");
private static final DateTimeFormatter printedTimeFormatter = DateTimeFormatter.ofPattern("hh:mm a");
private LocalDateTime startTime;
private LocalDateTime endTime;
private String data;
public PostItNote(LocalDateTime startTime, LocalDateTime endTime, String data) {
this.startTime = startTime;
this.endTime = endTime;
this.data = data;
}
@Override
public int compareTo(PostItNote o) {
return this.startTime.compareTo(o.startTime);
}
@Override
public String toString() {
return printedTimeFormatter.format(startTime.toLocalTime()) + " to " + printedTimeFormatter.format(endTime.toLocalTime()) +
" -- " + data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PostItNote that = (PostItNote) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
if (endTime != null ? !endTime.equals(that.endTime) : that.endTime != null) return false;
if (startTime != null ? !startTime.equals(that.startTime) : that.startTime != null) return false;
return true;
}
@Override
public int hashCode() {
int result = startTime != null ? startTime.hashCode() : 0;
result = 31 * result + (endTime != null ? endTime.hashCode() : 0);
result = 31 * result + (data != null ? data.hashCode() : 0);
return result;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
package com.christianwilkie;
import com.google.common.collect.Iterators;
import com.google.common.collect.PeekingIterator;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Created by chris on 11/9/2014.
*/
public class PostItNoteParser {
private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("M[M]-d[d]-yyyy");
private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mma");
//inner map: <start time, note>
private static TreeMap<LocalDate, TreeMap<LocalTime,PostItNote>> noteMap = new TreeMap<>();
private static TreeMap<String,Duration> timeSpentMap = new TreeMap<>();
private static Duration totalTimeSpentOnTasks = Duration.ZERO;
public PostItNoteParser() {
}
public static PostItNote parseLine(String line) {
String[] splitLine = line.split(" ");//split on the spaces
//super hacky and dangerous line parsing ahoy
//get rid of the ':' by splitting it out, then parse the result
//e.g. "11-6-2014:" -> "11-6-2014"
int preDataLength = 0;
LocalDate date = parseDate(splitLine[0].split(":")[0]);
//05:18, AM
LocalTime startTime = parseTime(splitLine[1]+splitLine[2]);
//skip the to, (3)
//06:00, AM
LocalTime endTime = parseTime(splitLine[4]+splitLine[5]);
//skip 6,
//the rest is data
for(int i = 0; i < 7; i++) {
//skip over all this pre-data stuff
preDataLength += splitLine[i].length()+1;
}
//now get the data substring
String data = line.substring(preDataLength);
return new PostItNote(LocalDateTime.of(date, startTime),LocalDateTime.of(date, endTime),data);
}
private static LocalDate parseDate(String date) {
//input: MM-DD-YYYY string
return LocalDate.parse(date,dateFormatter);
}
private static LocalTime parseTime(String time) {
return LocalTime.parse(time,timeFormatter);
}
private static PostItNote findBestRedditSlot(TreeMap<LocalTime,PostItNote> innerNoteMap) {
final String data = "reddit";
Set<Map.Entry<LocalTime,PostItNote>> entrySet = innerNoteMap.entrySet();
PeekingIterator<Map.Entry<LocalTime,PostItNote>> iterator = Iterators.peekingIterator(entrySet.iterator());
Duration longestDurationForBrowsingReddit = Duration.ZERO; //keep track of longest possible duration
LocalDateTime startTimeForBrowsingReddit = null;
LocalDateTime endTimeForBrowsingReddit = null;
while(iterator.hasNext()) {
PostItNote firstItem = iterator.next().getValue();
//if we aren't at the end of the day
if(iterator.hasNext()) {
PostItNote secondItem = iterator.peek().getValue();
Duration timeBetweenTasks = Duration.between(firstItem.getEndTime(), secondItem.getStartTime());
//if the duration between these 2 tasks is greater than any previously found duration between 2 tasks
if(timeBetweenTasks.compareTo(longestDurationForBrowsingReddit) > 0) {
longestDurationForBrowsingReddit = timeBetweenTasks;
startTimeForBrowsingReddit = firstItem.getEndTime();
endTimeForBrowsingReddit = secondItem.getStartTime();
}
}
}
return new PostItNote(startTimeForBrowsingReddit,endTimeForBrowsingReddit,data);
}
public static void main(String[] args) {
try(BufferedReader br = new BufferedReader(new FileReader("src/main/resources/challenge_input.txt"))) {
while(br.ready()) {
PostItNote note = parseLine(br.readLine());
TreeMap<LocalTime,PostItNote> innerNoteMap = noteMap.get(note.getStartTime().toLocalDate());
Duration taskDuration = Duration.between(note.getStartTime(),note.getEndTime());
Duration previousTimeSpentInBucket;
if (innerNoteMap == null) {
//we need to make the inner maps first
innerNoteMap = new TreeMap<>();
//make the inner note map
noteMap.put(note.getStartTime().toLocalDate(),innerNoteMap);
}
//insert the note
innerNoteMap.put(note.getStartTime().toLocalTime(), note);
//check the task duration map
previousTimeSpentInBucket = timeSpentMap.get(note.getData());
if (previousTimeSpentInBucket == null) {
//if we haven't yet added this task to the time spent map, then treat the previous duration as 0
previousTimeSpentInBucket = Duration.ZERO;
}
//insert the additional time spent
Duration summedDuration = taskDuration.plus(previousTimeSpentInBucket);
timeSpentMap.put(note.getData(), summedDuration);
//keep track of the total time spent on tasks
totalTimeSpentOnTasks = totalTimeSpentOnTasks.plus(taskDuration);
}
} catch (IOException e) {
e.printStackTrace();
}
//now we have the data sorted and separated into date buckets
//we need to find the best times for browsing reddit
noteMap.entrySet().forEach((noteMapEntry)-> {
TreeMap<LocalTime,PostItNote> innerMap = noteMapEntry.getValue();
PostItNote redditNote = findBestRedditSlot(innerMap);
//insert this note
innerMap.put(redditNote.getStartTime().toLocalTime(),redditNote);
//add to our statistic map
Duration previousTimeSpentOnReddit = timeSpentMap.get(redditNote.getData());
if(previousTimeSpentOnReddit == null) {
previousTimeSpentOnReddit = Duration.ZERO;
}
Duration redditNoteDuration = Duration.between(redditNote.getStartTime().toLocalTime(), redditNote.getEndTime().toLocalTime());
timeSpentMap.put(redditNote.getData(),previousTimeSpentOnReddit.plus(redditNoteDuration));
//add the time spent to our running total
totalTimeSpentOnTasks = totalTimeSpentOnTasks.plus(redditNoteDuration);
});
//now we found and inserted the best times for browsing reddit
//print out the notes
final DateTimeFormatter scheduleHeadingFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd yyyy");
noteMap.entrySet().forEach((noteMapEntry)-> {
System.out.println("Schedule for " + noteMapEntry.getKey().format(scheduleHeadingFormatter));
TreeMap<LocalTime,PostItNote> innerMap = noteMapEntry.getValue();
innerMap.entrySet().forEach((innerEntry) -> System.out.println(innerEntry.getValue()));
System.out.println();
});
//print out the statistics
NumberFormat percentageFormat = NumberFormat.getPercentInstance();
percentageFormat.setMaximumFractionDigits(1);
System.out.println("Time spent on tasks:");
timeSpentMap.entrySet().forEach((timeSpentMapEntry) -> {
Duration totalTaskDuration = timeSpentMapEntry.getValue();
System.out.println(timeSpentMapEntry.getKey() + ": " + totalTaskDuration.toMinutes() + " minutes (" +
percentageFormat.format((double)totalTaskDuration.toNanos() / totalTimeSpentOnTasks.toNanos()) + " of total time).");
});
System.out.println();
System.out.println("Total time spent on all tasks: " + totalTimeSpentOnTasks.toMinutes() + " minutes.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment