private static List<Schedule> generateSchedules(
     List<ArrayList<CourseSelection>> selections, int count) {
   List<Schedule> schedules = new ArrayList<Schedule>();
   if (count == 0) {
     for (CourseSelection cs : selections.get(count)) {
       // This is one course's course selections.
       schedules.add(new Schedule(cs));
     }
   } else {
     schedules = generateSchedules(selections, count - 1);
     List<Schedule> nextSchedules = new ArrayList<Schedule>();
     for (Schedule s : schedules) {
       for (CourseSelection cs : selections.get(count)) {
         if (!s.collidesWith(cs)) {
           List<CourseSelection> temp = s.getCourseSelections();
           Schedule result = new Schedule(cs);
           for (int i = 0; i < temp.size(); i++) {
             result.addCourseSelection(temp.get(i));
           }
           nextSchedules.add(result);
         }
       }
     }
     return nextSchedules;
   }
   return schedules;
 }
  public static List<Schedule> generateSchedules(
      List<Course> selectedCourses, List<Course> optionalCourses, int requiredOptional) {
    // Welcome to the worst sub of your life.

    // Original schedules: generate your mandatory course schedules. Easy.
    List<Schedule> originalSchedules = new ArrayList<Schedule>();
    if (selectedCourses.size() > 0) {
      originalSchedules = generateSchedules(selectedCourses);
    }

    // A string list to hold gray code.
    List<String[]> nChooseK = new ArrayList<String[]>();

    // Creates the digits that will be used, depending on how many optional courses there are.
    String[] inputs = new String[optionalCourses.size()];
    for (int j = 0; j < optionalCourses.size(); j++) {
      inputs[j] = Integer.toString(j);
    }

    // Run the gray code nChooseK sub.
    nChooseK = nChooseK(inputs, requiredOptional, 0, new String[requiredOptional], nChooseK);

    // Final schedules will be returned to the user.
    List<Schedule> finalSchedules = new ArrayList<Schedule>();

    // For each string array in nChooseK, meaning for each possible gray code...
    for (String[] sArray : nChooseK) {
      // A temporary schedule holder.
      List<Schedule> tempSchedules;

      // A temporary selections holder
      List<ArrayList<CourseSelection>> selections = new ArrayList<ArrayList<CourseSelection>>();

      // Of the nChooseK string, we add k courses to selections.
      for (String s : sArray) {
        selections.add(
            (ArrayList<CourseSelection>)
                optionalCourses.get(Integer.parseInt(s)).getCourseSelections());
      }
      tempSchedules = generateSchedules(selections, requiredOptional - 1);
      // Now we must merge tempSchedules with original schedules into final schedules.
      if (originalSchedules.size() == 0) {
        for (Schedule s : tempSchedules) {
          finalSchedules.add(s);
        }
      } else {
        for (Schedule s1 : originalSchedules) { // For every schedule generated previously,
          for (Schedule s2 : tempSchedules) {
            boolean valid = true;
            for (CourseSelection cs : s2.getCourseSelections()) {
              if (s1.collidesWith(cs)) {
                valid = false;
              }
            }
            if (valid) {
              // We found a valid match. Let's add them to the final list.
              List<CourseSelection> temp1 = s1.getCourseSelections();
              List<CourseSelection> temp2 = s2.getCourseSelections();
              Schedule result = null;
              for (CourseSelection cs : temp1) {
                if (result == null) {
                  result = new Schedule(cs);
                } else {
                  result.addCourseSelection(cs);
                }
              }
              for (CourseSelection cs : temp2) {
                result.addCourseSelection(cs);
              }
              finalSchedules.add(result);
            }
          }
        }
      }
    }
    return finalSchedules;
  }