1
\$\begingroup\$

I am new to this SE and so bear with me. Sorry for the long post. But this much info is needed to explain !

Background:

I am student and working in one science institute. Our university has bunch of transport services which runs on daily basis based on pre-existing timings.

For example :

On Mon to Sat: 07:00, 11:00, 16:00 ... 
On Sundays: 09:30, 12:30, 21:00 ...

There can be any number of trips per day or even each day can have different trips. So I am designing app which can give users next available transport.

Task:

monday = { "07:00", "11:00", "16:00",...}
sunday = { "09:30", "12:30", "21:00", ...}

Let's say I have above as input information. Whenever I run this program, it should give me back next trip when we have input in following form

run() #On Monday 09:00
>>Output : 11:00 
run() #On Sunday 13:30
>>Output: 21:00

Initially I thought it is very easy job. But unfortunately, my university added trips post midnight , For example

monday =  { "07:00", "11:00", "16:00",..., "01:30"}
sunday = { "09:30", "12:30", "21:00", ..., "02:00"}

Here trip mentioned in Monday list "01:30" is actually on Tuesday. This broke my existing algorithm. So currently I am using following algorithm,

Step1: Distribute each input into 3 parts : first trip, trips after that and trips after midnight e.g

monday =  { "07:00", "11:00", "16:00",..., "01:30"}
monday_first = {"07:00"}
monday_rest = {"11:00", "16:00"...}
monday_post_midnight = {"01:30"}

Step2 : Combine lists from yesterday's midnight, first trip and rest of the trips

e.g.

new_monday_trip = sunday_post_midnight + monday_first + monday_rest
new_monday_trip = {"02:00", "07:00","11:00", "16:00"...}

Step3: Check current time and get next trip from list. If it is present then show it to user or get first item from next day.

I was wondering if is there any better way.

Note: Each trip input will be always in chronological order

Example Input Set

monday to saturday =  { "07:00", "11:00", "12:30", "16:00", "21:00", "00:00", "01:30"}
sunday = { "09:30", "12:30", "21:00", "00:30","01:30", "02:00"}

Code I am currently using,

DayTrips.Java

public class DayTrips {
    private List<String> rawTrips;
    private List<String> today = new ArrayList<>();
    private List<String> tomorrow = new ArrayList<>();

    public DayTrips(List<String> rawTrips) throws ParseException {
        this.rawTrips = rawTrips;
        Date firstTrip = null;
        SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault());
        firstTrip = format.parse(rawTrips.get(0));
        today.add(rawTrips.get(0)); //Add first trip.
        //Now if date is before first date, it should be after midnight trip
        for (String trip : rawTrips) {
            if (firstTrip.before(format.parse(trip))) {
                today.add(trip);
            } else if (firstTrip.after(format.parse(trip))) {
                tomorrow.add(trip);
            }
        }
    }

    public List<String> getToday() {
        return today;
    }

    public List<String> getTomorrow() {
        return tomorrow;
    }
}

Week.Java

public class Week {

    private SparseArray<List<String>> weekMap;
    private List<String> defaultTrips = null;

    /**
     * WeekMap will contains trips for any day of week. Keys are equal to Calender.DAY_OF_WEEK
     * of respective days. Default trips should be in following priority
     * Monday > Tuesday > .... > Sunday
     */
    public Week(SparseArray<List<String>> weekMap) {
        this.weekMap = weekMap;
        //Get default trips in given priority
        for (int i = Calendar.MONDAY; i <= Calendar.SATURDAY; i++) {
            if (weekMap.get(i) != null) {
                defaultTrips = weekMap.get(i);
                break;
            }
        }
        //In Case only Sunday Trips are available
        if (defaultTrips == null) {
            defaultTrips  = weekMap.get(Calendar.SUNDAY);
        }
    }

    /**
     * This method should return next transport trip for given timing
     *
     * @param calendar : User defined time
     */
    public String[] nextTrip(Calendar calendar) throws ParseException {
        Date now = new Date(calendar.getTimeInMillis()); //Record input time
        SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault());

        //Check with trips for post midnight from yesterday
        calendar.add(Calendar.DATE, -1); //Yesterday
        List<String> beforeFirstTrip = new DayTrips(weekMap.get(calendar.get(Calendar.DAY_OF_WEEK), defaultTrips)).getTomorrow();

        for (String s : beforeFirstTrip) {
            if (format.parse(s).after(now) || format.parse(s).equals(now)) {
                return new String[]{s, "yesterday"};
            }
        }

        //Check today's trips
        calendar.add(Calendar.DATE, 1); //Today
        List<String> todaysTrip = new DayTrips(weekMap.get(calendar.get(Calendar.DAY_OF_WEEK), defaultTrips)).getToday();

        for (String s : todaysTrip) {
            if (format.parse(s).after(now) || format.parse(s).equals(now)) {
                return new String[]{s, "today"};
            }
        }

        //Check tomorrow's trips (i.e. post midnight today)
        List<String> tomorrowTrip = new DayTrips(weekMap.get(calendar.get(Calendar.DAY_OF_WEEK), defaultTrips)).getTomorrow();
        for (String s : tomorrowTrip) {
//In this case we need to check if time is between last trip of today and first trip of tomorrow
        //Hence we should use before instead after for comparing
            if (format.parse(s).before(now) || format.parse(s).equals(now)) {
                return new String[]{s, "today_after_midnight"};
            }
        }

     //Else get first trip of tomorrow
    calendar.add(Calendar.DATE, 1);
    return new String[]{weekMap.get(calendar.get(Calendar.DAY_OF_WEEK), defaultTrips)).get(0), "tomorrow"};
    }
}
\$\endgroup\$
  • \$\begingroup\$ what is the exact format of the inputs you are receiving: can you please provide example. secondly imagine if have a series of numbers in an array: [1,2,3,4,6,88,444,345345] - let's say for argument's sake i sort it in increasing order. If you should give me any number, then i should be able to tell you the closest number in the array which is greater than your number. that in effect is the problem at hand. i'd order the input into date format and simply return the next highest date? \$\endgroup\$ – BKSpurgeon Jun 17 '17 at 12:05
  • \$\begingroup\$ @BKSpurgeon Thank for looking into this. Input format is exactly how I have added in question. I will have string arrays (or lists) with each element in "HH:mm" form for few days. Like monday = { "07:00", "11:00", "12:30", "16:00", "21:00", "00:00", "01:30"}, sunday = { "09:30", "12:30", "21:00", "00:30","01:30", "02:00"}. But my problem is now they also have after midnight dates which makes problem difficult. That is why I come up with solution I gave above. At least one good thing is inside each array (or list) all elements will be in chronological order. \$\endgroup\$ – Dexter Jun 17 '17 at 12:12
  • \$\begingroup\$ personally i would convert each of their inputs to some sort of date/time format, such that Monday = {"01:30"} would be converted to a date/time equivalent of Tuesday 01:30 - then you will have a linear order of times/dates/hours which you can simply compare. IF i get the chance i'll have a go at hacking something together in c#, or perhaps i might even try refactoring your code. but i don't have the Java installed on my PC yet \$\endgroup\$ – BKSpurgeon Jun 17 '17 at 13:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.