Task: Range expansion





Java: import java.util.*;

class RangeExpander implements Iterator<Integer>, Iterable<Integer> {

    private static final Pattern TOKEN_PATTERN = Pattern.compile("([+-]?\\d+)-([+-]?\\d+)");

    private final Iterator<String> tokensIterator;

    private boolean inRange;
    private int upperRangeEndpoint;
    private int nextRangeValue;

    public RangeExpander(String range) {
        String[] tokens = range.split("\\s*,\\s*");
        this.tokensIterator = Arrays.asList(tokens).iterator();
    }

    @Override
    public boolean hasNext() {
        return hasNextRangeValue() || this.tokensIterator.hasNext();
    }

    private boolean hasNextRangeValue() {
        return this.inRange && this.nextRangeValue <= this.upperRangeEndpoint;
    }

    @Override
    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }

        if (hasNextRangeValue()) {
            return this.nextRangeValue++;
        }

        String token = this.tokensIterator.next();

        Matcher matcher = TOKEN_PATTERN.matcher(token);
        if (matcher.find()) {
            this.inRange = true;
            this.upperRangeEndpoint = Integer.valueOf(matcher.group(2));
            this.nextRangeValue = Integer.valueOf(matcher.group(1));
            return this.nextRangeValue++;
        }

        this.inRange = false;
        return Integer.valueOf(token);
    }

    @Override
    public Iterator<Integer> iterator() {
        return this;
    }

}

class RangeExpanderTest {
    public static void main(String[] args) {
        RangeExpander re = new RangeExpander("-6,-3--1,3-5,7-11,14,15,17-20");
        for (int i : re) {
            System.out.print(i + " ");
        }
    }
}






Fortran:       MODULE HOMEONTHERANGE
       CONTAINS	
        CHARACTER*200 FUNCTION ERANGE(TEXT)	
Can't return a character value of variable size.
         CHARACTER*(*) TEXT	
         CHARACTER*200 ALINE	
         INTEGER N,N1,N2	
         INTEGER I,I1		
          ALINE = ""		
          L = 0			
          I = 1			
          CALL FORASIGN		
Chug through another number or number - number range.
        R:DO WHILE(EATINT(N1))	
            N2 = N1			
            IF (PASSBY("-")) CALL EATINT(N2)	
            IF (L.GT.0) CALL EMIT(",")		
            DO N = N1,N2,SIGN(+1,N2 - N1)	
              CALL SPLOT(N)				
              IF (N.NE.N2) CALL EMIT(",")		
            END DO				
            IF (.NOT.PASSBY(",")) EXIT R	
          END DO R		
Completed the scan. Just return the result.
          ERANGE = ALINE(1:L)	
         CONTAINS	
          SUBROUTINE FORASIGN	
    1       IF (I.LE.LEN(TEXT)) THEN	
              IF (TEXT(I:I).LE." ") THEN	
                I = I + 1				
                GO TO 1					
              END IF			
            END IF			
          END SUBROUTINE FORASIGN	

          LOGICAL FUNCTION PASSBY(C)	
Could consider or ignore case for letters, but this is really for single symbols.
           CHARACTER*1 C	
            PASSBY = .FALSE.	
            IF (I.LE.LEN(TEXT)) THEN	
              IF (TEXT(I:I).EQ.C) THEN	
                PASSBY = .TRUE.		
                I = I + 1		
                CALL FORASIGN		
              END IF		
            END IF		
          END FUNCTION PASSBY	

          LOGICAL FUNCTION EATINT(N)	
           INTEGER N	
           INTEGER D	
           LOGICAL NEG	
            EATINT = .FALSE.	
            IF (I.GT.LEN(TEXT)) RETURN	
            N = 0			
            IF (PASSBY("+")) THEN	
              NEG = .FALSE.		
             ELSE			
              NEG = PASSBY("-")		
            END IF			
            IF (I.GT.LEN(TEXT)) RETURN	
Chug through digits. Can develop -2147483648, thanks to the workings of two's complement.
   10       D = ICHAR(TEXT(I:I)) - ICHAR("0")	
            IF (0.LE.D .AND. D.LE.9) THEN	
              N = N*10 + D			
              I = I + 1				
              IF (I.LE.LEN(TEXT)) GO TO 10	
            END IF			
            IF (NEG) N = -N		
            EATINT = .TRUE.		
            CALL FORASIGN		
          END FUNCTION EATINT	

          SUBROUTINE EMIT(C)	
           CHARACTER*1 C	
            L = L + 1		
            IF (L.GT.LEN(ALINE)) STOP "Ran out of ALINE
            ALINE(L:L) = C	
          END SUBROUTINE EMIT	

          SUBROUTINE SPLOT(N)	
           INTEGER N		
           CHARACTER*12 FIELD	
           INTEGER I		
            WRITE (FIELD,"(I0)") N	
            DO I = 1,12		
              IF (FIELD(I:I).LE." ") EXIT	
              CALL EMIT(FIELD(I:I))	
            END DO		
          END SUBROUTINE SPLOT	
        END FUNCTION ERANGE	
      END MODULE HOMEONTHERANGE

      PROGRAM POKE
      USE HOMEONTHERANGE
      CHARACTER*(200) SOME
      SOME = "-6,-3--1,3-5,7-11,14,15,17-20"
      SOME = ERANGE(SOME)
      WRITE (6,*) SOME	
      END