Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
out
*.iml
.idea
46 changes: 29 additions & 17 deletions Java/TollCalculator.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalField;
import java.util.*;
import java.util.concurrent.*;

Expand All @@ -12,25 +17,29 @@ public class TollCalculator {
* @return - the total toll fee for that day
*/
public int getTollFee(Vehicle vehicle, Date... dates) {
Date intervalStart = dates[0];
int totalFee = 0;
// I believe in this method the times 08:40 and 09:20 should consider as times of 2 different hours (i.e. hour of 8 and hour of 9.
// In the previous logic if the 08:40 was the first of the array then 09:20 was considered as same hour because it has considered the time gap
// Also the previous implementation was not updating the intervalStart correctly.

int[] feeOfTheHour = new int[24];
Arrays.fill(feeOfTheHour, 0);

// calculate max fee for each hour
for (Date date : dates) {
int nextFee = getTollFee(date, vehicle);
int tempFee = getTollFee(intervalStart, vehicle);

TimeUnit timeUnit = TimeUnit.MINUTES;
long diffInMillies = date.getTime() - intervalStart.getTime();
long minutes = timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS);

if (minutes <= 60) {
if (totalFee > 0) totalFee -= tempFee;
if (nextFee >= tempFee) tempFee = nextFee;
totalFee += tempFee;
} else {
totalFee += nextFee;
int fee = getTollFee(date, vehicle);
int hour = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).getHour();

if(feeOfTheHour[hour] < fee){
feeOfTheHour[hour] = fee;
}
}

// get the sum of hourly fee
int totalFee = Arrays.stream(feeOfTheHour).sum();

// cap the value
if (totalFee > 60) totalFee = 60;

return totalFee;
}

Expand All @@ -56,9 +65,11 @@ public int getTollFee(final Date date, Vehicle vehicle) {
else if (hour == 6 && minute >= 30 && minute <= 59) return 13;
else if (hour == 7 && minute >= 0 && minute <= 59) return 18;
else if (hour == 8 && minute >= 0 && minute <= 29) return 13;
else if (hour >= 8 && hour <= 14 && minute >= 30 && minute <= 59) return 8;
else if (hour == 8 && minute >= 30 && minute <= 59) return 8;
else if (hour >= 9 && hour <= 14 && minute >= 0 && minute <= 59) return 8;
else if (hour == 15 && minute >= 0 && minute <= 29) return 13;
else if (hour == 15 && minute >= 0 || hour == 16 && minute <= 59) return 18;
else if (hour == 15 && minute >= 30 && minute <= 59) return 18;
else if (hour == 16 && minute >= 0 && minute <= 59) return 18;
else if (hour == 17 && minute >= 0 && minute <= 59) return 13;
else if (hour == 18 && minute >= 0 && minute <= 29) return 8;
else return 0;
Expand All @@ -74,6 +85,7 @@ private Boolean isTollFreeDate(Date date) {
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) return true;

//TODO - consider every year differently or remove the year validation
if (year == 2013) {
if (month == Calendar.JANUARY && day == 1 ||
month == Calendar.MARCH && (day == 28 || day == 29) ||
Expand Down
68 changes: 68 additions & 0 deletions Java/ToolCalculatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.util.Date;

public class ToolCalculatorTest {
public static void main(String[] args) {
TollCalculator tollCalculator = new TollCalculator();
Date[] dateTimeArrayWeekDayLarge = new Date[]{
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 7, 30).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 7, 52).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 17).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 39).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 11, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 13, 45).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 16, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 16, 40).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 17, 40).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 17, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 12).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 27).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 43).atZone(ZoneId.systemDefault()).toInstant())
};

Date[] dateTimeArrayWeekDaySmall = new Date[]{
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 17).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 39).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 8, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 11, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 17, 40).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 17, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 12).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 27).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 14, 18, 43).atZone(ZoneId.systemDefault()).toInstant())
};

Date[] dateTimeArrayWeekEnd = new Date[]{
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 8, 17).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 8, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 8, 39).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 8, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 11, 25).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 17, 40).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 17, 48).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 18, 12).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 18, 27).atZone(ZoneId.systemDefault()).toInstant()),
Date.from(LocalDateTime.of(2022, Month.MARCH, 12, 18, 43).atZone(ZoneId.systemDefault()).toInstant())
};

test(tollCalculator, new Car(), dateTimeArrayWeekDayLarge, 60, "Weekday Fees on Car with Cap");
test(tollCalculator, new Car(), dateTimeArrayWeekDaySmall, 42, "Weekday Fees on Car without Cap");
test(tollCalculator, new Car(), dateTimeArrayWeekEnd, 0, "Weekend Fees on Car");
test(tollCalculator, new Motorbike(), dateTimeArrayWeekEnd, 0, "Weekend Fees on Motorbike");
test(tollCalculator, new Motorbike(), dateTimeArrayWeekDaySmall, 0, "Weekday Fees on Motorbike");
}

private static void test(TollCalculator tollCalculator, Vehicle vehicle, Date[] datesArray, int expectedFee, String testScenario){
int tollFee = tollCalculator.getTollFee(vehicle, datesArray);
if(tollFee == expectedFee){
System.out.printf("Test '%s' executed successfully.%n", testScenario);
} else {
System.out.printf("Test '%s' failed. Expected fee is %d SEK and actual fee returned is %d SEK.%n", testScenario, expectedFee, tollFee);
}
}
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ A calculator for vehicle toll fees.
* Make sure you read these instructions carefully
* The current code base is in Java and C#, but please make sure that you do an implementation in a language **you feel comfortable** in like Javascript, Python, Assembler or [ModiScript](https://en.wikipedia.org/wiki/ModiScript) (please don't choose ModiScript).
* No requirement but bonus points if you know what movie is in the gif
* This is taken from the Hackers movie directed by Iain Softly

## Background
Our city has decided to implement toll fees in order to reduce traffic congestion during rush hours.
Expand Down