private void
        readPatientListAndAdmissionPartListAndRequiredPatientEquipmentListAndPreferredPatientEquipmentList()
            throws IOException {
      readConstantLine("PATIENTS:");
      List<Patient> patientList = new ArrayList<Patient>(patientListSize);
      List<AdmissionPart> admissionPartList = new ArrayList<AdmissionPart>(patientListSize);
      List<RequiredPatientEquipment> requiredPatientEquipmentList =
          new ArrayList<RequiredPatientEquipment>(patientListSize * equipmentListSize);
      List<PreferredPatientEquipment> preferredPatientEquipmentList =
          new ArrayList<PreferredPatientEquipment>(patientListSize * equipmentListSize);
      long admissionPartId = 0L;
      long requiredPatientEquipmentId = 0L;
      long preferredPatientEquipmentId = 0L;
      for (int i = 0; i < patientListSize; i++) {
        String line = bufferedReader.readLine();
        String[] lineTokens = splitByPipelineAndTrim(line, 6);

        String[] nightTokens = splitBySpace(lineTokens[1], 2);
        int firstNightIndex = Integer.parseInt(nightTokens[0]);
        int lastNightIndex = Integer.parseInt(nightTokens[1]);
        int patientNightListSize = lastNightIndex - firstNightIndex;
        // A patient with no nights in the planning horizon or no nights at all is ignored
        if (firstNightIndex >= nightListSize || patientNightListSize == 0) {
          continue;
        }

        String[] patientTokens = splitBySpace(lineTokens[0], 4);
        Patient patient = new Patient();
        patient.setId(Long.parseLong(patientTokens[0]));
        patient.setName(patientTokens[1]);
        patient.setAge(Integer.parseInt(patientTokens[2]));
        patient.setGender(Gender.valueOfCode(patientTokens[3]));
        int preferredMaximumRoomCapacity = Integer.parseInt(lineTokens[3]);
        patient.setPreferredMaximumRoomCapacity(
            preferredMaximumRoomCapacity == 0 ? null : preferredMaximumRoomCapacity);
        patientList.add(patient);

        String[] admissionPartTokens = splitBySpace(lineTokens[2]);
        int patientAdmissionPartListSize = Integer.parseInt(admissionPartTokens[0]);
        if (admissionPartTokens.length != ((patientAdmissionPartListSize * 2) + 1)) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain "
                  + ((patientAdmissionPartListSize * 2) + 1)
                  + " number of tokens after 2th pipeline (|).");
        }
        int nextFirstNightIndex = firstNightIndex;
        for (int j = 1; j < admissionPartTokens.length; j += 2) {
          long specialismId = Long.parseLong(admissionPartTokens[j]);
          int admissionPartNightListSize = Integer.parseInt(admissionPartTokens[j + 1]);
          if (nextFirstNightIndex >= nightListSize || admissionPartNightListSize == 0) {
            nextFirstNightIndex += admissionPartNightListSize;
            continue;
          }
          AdmissionPart admissionPart = new AdmissionPart();
          admissionPart.setId(admissionPartId);
          admissionPart.setPatient(patient);
          Specialism specialism = (specialismId == 0) ? null : idToSpecialismMap.get(specialismId);
          if (specialism == null) {
            throw new IllegalArgumentException(
                "Read line (" + line + ") has a non existing specialismId (" + specialismId + ").");
          }
          admissionPart.setSpecialism(specialism);
          int admissionPartFirstNightIndex = nextFirstNightIndex;
          Night admissionPartFirstNight = indexToNightMap.get(admissionPartFirstNightIndex);
          if (admissionPartFirstNight == null) {
            throw new IllegalStateException(
                "The admissionPartFirstNight was not found for admissionPartFirstNightIndex("
                    + admissionPartFirstNightIndex
                    + ").");
          }
          admissionPart.setFirstNight(admissionPartFirstNight);
          int admissionPartLastNightIndex = nextFirstNightIndex + admissionPartNightListSize - 1;
          // TODO Instead of ensureEnoughNights(lastNightIndex);
          // the official score function ignores any broken constraints after the planning horizon
          if (admissionPartLastNightIndex >= nightListSize) {
            admissionPartLastNightIndex = nightListSize - 1;
          }
          Night admissionPartLastNight = indexToNightMap.get(admissionPartLastNightIndex);
          if (admissionPartLastNight == null) {
            throw new IllegalStateException(
                "The admissionPartLastNight was not found for admissionPartLastNightIndex("
                    + admissionPartLastNightIndex
                    + ").");
          }
          admissionPart.setLastNight(admissionPartLastNight);
          admissionPartList.add(admissionPart);
          admissionPartId++;
          nextFirstNightIndex += admissionPartNightListSize;
        }
        int admissionPartNightListSizeSum = nextFirstNightIndex - firstNightIndex;
        if (patientNightListSize != admissionPartNightListSizeSum) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") has patientNightListSize ("
                  + patientNightListSize
                  + ") different from admissionPartNightListSizeSum("
                  + admissionPartNightListSizeSum
                  + ")");
        }

        String[] requiredPatientEquipmentTokens = splitBySpace(lineTokens[4]);
        if (requiredPatientEquipmentTokens.length != equipmentListSize) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain equal number of tokens ("
                  + requiredPatientEquipmentTokens.length
                  + ") as equipmentListSize ("
                  + equipmentListSize
                  + ") after 4th pipeline (|).");
        }
        List<RequiredPatientEquipment> requiredPatientEquipmentOfPatientList =
            new ArrayList<RequiredPatientEquipment>(equipmentListSize);
        for (int j = 0; j < requiredPatientEquipmentTokens.length; j++) {
          int hasEquipment = Integer.parseInt(requiredPatientEquipmentTokens[j]);
          if (hasEquipment == 1) {
            RequiredPatientEquipment requiredPatientEquipment = new RequiredPatientEquipment();
            requiredPatientEquipment.setId(requiredPatientEquipmentId);
            requiredPatientEquipment.setPatient(patient);
            requiredPatientEquipment.setEquipment(indexToEquipmentMap.get(j));
            requiredPatientEquipmentOfPatientList.add(requiredPatientEquipment);
            requiredPatientEquipmentList.add(requiredPatientEquipment);
            requiredPatientEquipmentId++;
          } else if (hasEquipment != 0) {
            throw new IllegalArgumentException(
                "Read line ("
                    + line
                    + ") is expected to have 0 or 1 hasEquipment ("
                    + hasEquipment
                    + ").");
          }
        }
        patient.setRequiredPatientEquipmentList(requiredPatientEquipmentOfPatientList);

        String[] preferredPatientEquipmentTokens = splitBySpace(lineTokens[5]);
        if (preferredPatientEquipmentTokens.length != equipmentListSize) {
          throw new IllegalArgumentException(
              "Read line ("
                  + line
                  + ") is expected to contain equal number of tokens ("
                  + preferredPatientEquipmentTokens.length
                  + ") as equipmentListSize ("
                  + equipmentListSize
                  + ") after 5th pipeline (|).");
        }
        List<PreferredPatientEquipment> preferredPatientEquipmentOfPatientList =
            new ArrayList<PreferredPatientEquipment>(equipmentListSize);
        for (int j = 0; j < preferredPatientEquipmentTokens.length; j++) {
          int hasEquipment = Integer.parseInt(preferredPatientEquipmentTokens[j]);
          if (hasEquipment == 1) {
            boolean alreadyRequired = (Integer.parseInt(requiredPatientEquipmentTokens[j]) == 1);
            // Official spec: if equipment is required
            // then a duplicate preffered constraint should be ignored
            if (!alreadyRequired) {
              PreferredPatientEquipment preferredPatientEquipment = new PreferredPatientEquipment();
              preferredPatientEquipment.setId(preferredPatientEquipmentId);
              preferredPatientEquipment.setPatient(patient);
              preferredPatientEquipment.setEquipment(indexToEquipmentMap.get(j));
              preferredPatientEquipmentOfPatientList.add(preferredPatientEquipment);
              preferredPatientEquipmentList.add(preferredPatientEquipment);
              preferredPatientEquipmentId++;
            }
          } else if (hasEquipment != 0) {
            throw new IllegalArgumentException(
                "Read line ("
                    + line
                    + ") is expected to have 0 or 1 hasEquipment ("
                    + hasEquipment
                    + ").");
          }
        }
        patient.setPreferredPatientEquipmentList(preferredPatientEquipmentOfPatientList);
      }
      patientAdmissionSchedule.setPatientList(patientList);
      patientAdmissionSchedule.setAdmissionPartList(admissionPartList);
      patientAdmissionSchedule.setRequiredPatientEquipmentList(requiredPatientEquipmentList);
      patientAdmissionSchedule.setPreferredPatientEquipmentList(preferredPatientEquipmentList);
    }
 public boolean isDifferentGender() {
   return leftAdmissionPart.getPatient().getGender()
       != rightAdmissionPart.getPatient().getGender();
 }