Skip to content

Instantly share code, notes, and snippets.

@monzee
Last active June 8, 2017 02:20
Show Gist options
  • Save monzee/2815ec7ba471e0b24c9f12461b1db18f to your computer and use it in GitHub Desktop.
Save monzee/2815ec7ba471e0b24c9f12461b1db18f to your computer and use it in GitHub Desktop.
somebody's homework
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.StreamSupport;
public class LongDistance {
public static void main(String[] args) throws IOException {
try (BufferedReader in = new BufferedReader(new InputStreamReader(System.in))) {
System.out.println("Total: " + in.lines()
.flatMap(line -> {
System.out.println(line);
return StreamSupport
.stream(Span.parse(line).spliterator(), false);
})
.map(record -> {
System.out.println(record);
return record.addTo(Cents.ZERO);
})
.reduce(Cents.ZERO, Cents::add));
}
}
}
class Cents {
public static final Cents ZERO = new Cents(0);
public final int amount;
Cents(int amount) {
this.amount = amount;
}
Cents add(Cents more) {
return new Cents(amount + more.amount);
}
@Override
public String toString() {
return String.format("$%.2f", amount / 100f);
}
}
enum Rate {
REGULAR(40), OFF_PEAK(25), WEEKEND(15);
private final int centsPerMinute;
Rate(int centsPerMinute) {
this.centsPerMinute = centsPerMinute;
}
Cents due(int minutes) {
return new Cents(minutes * centsPerMinute);
}
}
class Instant {
public static final Instant MONDAY = new Instant(0, 0, 0);
public static final Instant SATURDAY = new Instant(5, 0, 0);
public final int day;
public final int hour;
public final int minute;
Instant(int day, int hour, int minute) {
this.day = day;
this.hour = hour;
this.minute = minute;
}
int minutesUntil(Instant that) {
int diff = delta(that.day, that.hour, that.minute);
if (diff < 0) {
return delta(that.day + 7, that.hour, that.minute);
}
return diff;
}
private int delta(int futureDay, int futureHour, int futureMin) {
return 24*60*(futureDay - day) + 60*(futureHour - hour) + futureMin - minute;
}
}
class CallRecord {
public final Rate rate;
public final int duration;
CallRecord(Rate rate, int duration) {
this.rate = rate;
this.duration = duration;
}
Cents addTo(Cents total) {
return total.add(rate.due(duration));
}
@Override
public String toString() {
return "-> " + rate.due(duration) + " @" + rate + "(" + duration + " min)";
}
}
class Span implements Iterable<CallRecord> {
private Instant start;
private int duration;
Span(Instant start, int duration) {
this.start = start;
this.duration = duration;
}
static Span parse(String line) {
String[] parts = line.split("[ :]", 4);
Instant start = new Instant(
toDay(parts[0]),
Integer.parseInt(parts[1], 10),
Integer.parseInt(parts[2], 10));
return new Span(start, Integer.parseInt(parts[3], 10));
}
@Override
public Iterator<CallRecord> iterator() {
return new Iterator<CallRecord>() {
@Override
public boolean hasNext() {
return duration > 0;
}
@Override
public CallRecord next() {
Instant next = cutoff(start);
int elapsed = Math.min(duration, start.minutesUntil(next));
CallRecord result = new CallRecord(categorize(start), elapsed);
start = next;
duration -= elapsed;
return result;
}
};
}
private static int toDay(String dayCode) {
switch (dayCode) {
case "Mo": return 0;
case "Tu": return 1;
case "We": return 2;
case "Th": return 3;
case "Fr": return 4;
case "Sa": return 5;
case "Su": return 6;
default:
throw new IllegalArgumentException("invalid day: " + dayCode);
}
}
private static Rate categorize(Instant time) {
if (time.day > 4) {
return Rate.WEEKEND;
}
if (time.hour >= 8 && time.hour < 18) {
return Rate.REGULAR;
}
return Rate.OFF_PEAK;
}
private static Instant cutoff(Instant time) {
if (time.day > 4) {
return Instant.MONDAY;
}
if (time.day == 4 && time.hour >= 18) {
return Instant.SATURDAY;
}
if (time.hour < 8) {
return new Instant(time.day, 8, 0);
}
if (time.hour < 18) {
return new Instant(time.day, 18, 0);
}
return new Instant(time.day + 1, 8, 0);
}
}
$ java LongDistance < sample-data
Mo 13:30 16
-> $6.40 @REGULAR(16 min)
Mo 8:15 35
-> $14.00 @REGULAR(35 min)
Tu 7:50 20
-> $2.50 @OFF_PEAK(10 min)
-> $4.00 @REGULAR(10 min)
We 17:45 30
-> $6.00 @REGULAR(15 min)
-> $3.75 @OFF_PEAK(15 min)
Th 8:00 45
-> $18.00 @REGULAR(45 min)
Su 23:50 30
-> $1.50 @WEEKEND(10 min)
-> $5.00 @OFF_PEAK(20 min)
Total: $61.15
Mo 13:30 16
Mo 8:15 35
Tu 7:50 20
We 17:45 30
Th 8:00 45
Su 23:50 30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment