หน้าเว็บ

วันพุธที่ 11 ธันวาคม พ.ศ. 2556

integrate period algorithm : java

เป็น algorithm ที่ผมคิดขึ้นมาเอง  เพื่อเอาไว้รวม (ผนวก) ช่วงข้อมูลที่มีการเหลื่อมกัน ให้เป็นอันเดียวกันครับ

period timeline


initial period : period {start, end}
  1. 50 - 65
  2. 85 - 90
  3.   0 - 20
  4. 80 - 85
  5. 70 - 100
  6. 15 - 40
  7.   5 - 30
  8. 50 - 55
success period (integrated)
  1.   0 - 40
  2. 50 - 65
  3. 70 - 100

4 steps of algorithm 
(sort, change, remove and integrate)


1. sort periods

ทำการจัดเรียง periods ใหม่ทั้งหมด  โดยจัดเรียงตาม period start จากน้อยไปหามาก
ถ้า period start มีค่าเท่ากัน  ให้จัดเรียงตาม period end จากน้อยไปหามาก

before
  1. 50 - 65
  2. 85 - 90
  3.   0 - 20
  4. 80 - 85
  5. 70 - 100
  6. 15 - 40
  7.   5 - 30
  8. 50 - 55
after
  1.   0 - 20
  2.   5 - 30
  3. 15 - 40
  4. 50 - 55
  5. 50 - 65
  6. 70 - 100
  7. 80 - 85
  8. 85 - 90
private void sortPeriods() {
   periodList = new ArrayList<>(periodSet);

   Collections.sort(periodList, new Comparator<Period>() {
       @Override
       public int compare(Period period1, Period period2) {
           if (period1.getStart() == period2.getStart()) {
               return (int) (period1.getEnd() - period2.getEnd());
           }

           return (int) (period1.getStart() - period2.getStart());
       }
   });
}
2. change overlap

ในกรณีที่ period start ปัจจุบัน มีค่าน้อยกว่า period end ของตัวก่อนหน้า
ให้ทำการเปลี่ยน period start นั้น  ให้มีค่าเท่ากันกับ period end ของตัวก่อนหน้า

before
  1.   0 - 20
  2.   5 - 30  (20 - 30)
  3. 15 - 40  (30 - 40)
  4. 50 - 55
  5. 50 - 65  (55 - 65)
  6. 70 - 100
  7. 80 - 85  (100 - 85)
  8. 85 - 90
after
  1.    0 - 20
  2.   20 - 30
  3.   30 - 40
  4.   50 - 55
  5.   55 - 65
  6.   70 - 100
  7. 100 - 85
  8.   85 - 90
private void changeOverlap() {
    if (periodList.size() > 1) {
        for (int i = 1; i < periodList.size(); i++) {
            Period before = periodList.get(i - 1);
            Period current = periodList.get(i);

            if (current.getStart() < before.getEnd()) {
                current.setStart(before.getEnd());
            }
        }
   }
}
3. remove incorrect / sub period

ทำการลบ period ที่มีค่าไม่ถูกต้องออกไป เช่น
period ที่มี start มากกว่าหรือเท่ากับ end หรือ
period นั้น เป็น sub period ของ period อื่นๆ

before
  1.    0 - 20
  2.   20 - 30
  3.   30 - 40
  4.   50 - 55
  5.   55 - 65
  6.   70 - 100
  7. 100 - 85  incorrect (100 > 85 or start > end)
  8.   85 - 90  sub period (70 - 100)
after
  1.   0 - 20
  2. 20 - 30
  3. 30 - 40
  4. 50 - 55
  5. 55 - 65
  6. 70 - 100
private void removeIncorrect() {
    if (periodList.size() > 1) {
        for (int i = 1; i < periodList.size(); i++) {
            Period periodI = periodList.get(i);
            for (int j = i + 1; j < periodList.size(); j++) {
                Period periodJ = periodList.get(j);
                if(isIncorrect(periodJ) || isSubPeriod(periodJ, periodI)){
                    periodList.remove(periodJ);
                }
            }
        }
    }
}

private boolean isIncorrect(Period period){
   return period.getStart() >= period.getEnd();
}

private boolean isSubPeriod(Period period1, Period period2){
   return period1.getStart() >= period2.getStart() && period1.getEnd() <= period2.getEnd();
}
4. integrate periods

ทำการยุบรวม period ที่เหลือให้เป็น period เดียวกัน

before
  1.   0 - 20  (1)
  2. 20 - 30  (1)
  3. 30 - 40  (1)
  4. 50 - 55  (2)
  5. 55 - 65  (2)
  6. 70 - 100 (3)
after
  1.   0 - 40
  2. 50 - 65
  3. 70 - 100
private void integratePeriods() {
    if (periodList.size() > 1) {
        for (int i = 1; i < periodList.size(); i++) {
            Period before = periodList.get(i - 1);
            Period current = periodList.get(i);

            if (current.getStart() == before.getEnd()) {
                current.setStart(before.getStart());
                periodList.remove(before);
                i--;
            }
        }
   }
}
success!

full code

Period.java
package com.blogspot.na5cent.learning.integrateperiodalgorthm;

/**
 *
 * @author recrow
 */
public class Period {

    private long start;
    private long end;

    public Period(long start, long end) {
        this.start = start;
        this.end = end;
    }

    public long getStart() {
        return start;
    }

    public void setStart(long start) {
        this.start = start;
    }

    public long getEnd() {
        return end;
    }

    public void setEnd(long end) {
        this.end = end;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 47 * hash + (int) (this.start ^ (this.start >>> 32));
        hash = 47 * hash + (int) (this.end ^ (this.end >>> 32));
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Period other = (Period) obj;
        if (this.start != other.start) {
            return false;
        }
        if (this.end != other.end) {
            return false;
        }
        return true;
    }
}
PeriodIntegrator.java
package com.blogspot.na5cent.learning.integrateperiodalgorthm;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author redcrow
 */
public class PeriodIntegrator {

    private Set<Period> periodSet;
    private List<Period> periodList;

    public PeriodIntegrator() {
        periodSet = new HashSet<>();
    }

    public PeriodIntegrator addPeriod(Period period) {
        periodSet.add(period);
        return this;
    }

    public PeriodIntegrator addAllPeriods(List<Period> periodList){
        periodSet.addAll(periodList);        
        return this;
    }

    private void sortPeriods() {
        periodList = new ArrayList<>(periodSet);
        showPeriods("initial periods", periodList);

        Collections.sort(periodList, new Comparator<Period>() {
            @Override
            public int compare(Period period1, Period period2) {
                if (period1.getStart() == period2.getStart()) {
                    return (int) (period1.getEnd() - period2.getEnd());
                }

                return (int) (period1.getStart() - period2.getStart());
            }
        });

        showPeriods("step 1 >> sort periods", periodList);
    }

    private void changeOverlap() {
        if (periodList.size() > 1) {
            for (int i = 1; i < periodList.size(); i++) {
                Period before = periodList.get(i - 1);
                Period current = periodList.get(i);

                if (current.getStart() < before.getEnd()) {
                    current.setStart(before.getEnd());
                }
            }
        }

        showPeriods("step 2 >> change overlap", periodList);
    }

    private void removeIncorrect() {
        if (periodList.size() > 1) {
            for (int i = 1; i < periodList.size(); i++) {
                Period periodI = periodList.get(i);
                for (int j = i + 1; j < periodList.size(); j++) {
                    Period periodJ = periodList.get(j);
                    if(isIncorrect(periodJ) || isSubPeriod(periodJ, periodI)){
                        periodList.remove(periodJ);
                    }
                }
            }
        }

        showPeriods("step 3 >> remove incorrect", periodList);
    }

    private boolean isIncorrect(Period period){
        return period.getStart() >= period.getEnd();
    }

    private boolean isSubPeriod(Period period1, Period period2){
        return period1.getStart() >= period2.getStart() && period1.getEnd() <= period2.getEnd();
    }

    private void showPeriods(String operationName, List<Period> periodList) {
        System.out.println("");
        System.out.println(operationName);
        System.out.println("-------------------------------------------------");

        for (Period period : periodList) {
            System.out.println("period {" + period.getStart() + ", " + period.getEnd() + "}");
        }
    }

    private void integratePeriods() {
        if (periodList.size() > 1) {
            for (int i = 1; i < periodList.size(); i++) {
                Period before = periodList.get(i - 1);
                Period current = periodList.get(i);

                if (current.getStart() == before.getEnd()) {
                    current.setStart(before.getStart());
                    periodList.remove(before);
                    i--;
                }
            }
        }

        showPeriods("step 4 >> integrate periods", periodList);
    }

    public List<Period> integrate() {
        sortPeriods();
        changeOverlap();
        removeIncorrect();
        integratePeriods();
        
        return periodList;
    }
}
IntegratePeriodAlgorthm.java
package com.blogspot.na5cent.learning.integrateperiodalgorthm;

/**
 *
 * @author redcrow
 */
public class IntegratePeriodAlgorthm {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        new PeriodIntegrator()
                .addPeriod(new Period(5, 30))
                .addPeriod(new Period(15, 40))
                .addPeriod(new Period(50, 65))
                .addPeriod(new Period(50, 55))
                .addPeriod(new Period(0, 20))
                .addPeriod(new Period(70, 100))
                .addPeriod(new Period(80, 85))
                .addPeriod(new Period(85, 90))
                .integrate();
    }
}
run code


ไม่มีความคิดเห็น:

แสดงความคิดเห็น