Recent

Author Topic: A came across this today at my work.  (Read 1837 times)

TomTom

  • Full Member
  • ***
  • Posts: 170
A came across this today at my work.
« on: March 08, 2019, 08:30:16 pm »
[EDIT] I solved it ... kind of... I've added boolean variable that is set to true if range was set. Now I can add whole output to stringlist and delete duplicates... but there is still problem with last range not being found...

Code: Pascal  [Select][+][-]
  1. procedure TForm1.btnGOClick(Sender: TObject);
  2. var
  3.    lowC, highC, tmpLow, tmpHigh, x,i,lastindex: integer;
  4.    ResRange:string;
  5.    rfound: Boolean;
  6. begin
  7.   rfound:=false;
  8.   target.lines.clear;
  9.   lastIndex:=0;
  10.   X:=0;
  11.   for i := 0 to source.lines.count-1 do
  12.   Begin
  13.  
  14.     lowC := StrToInt(Source.Lines.Strings[i]);
  15.     HighC := StrToInt(Source.Lines.Strings[i+1]);
  16.     X:=i;
  17.     if lowc+1=highc then
  18.        Begin
  19.          tmpLow := lowC;
  20.          X:=i;
  21.          While StrToInt(Source.Lines.Strings[X])+1 = StrToInt(Source.Lines.Strings[X+1]) do
  22.          Begin
  23.            tmpHigh :=  StrToInt(Source.Lines.Strings[X+1]);
  24.            Inc(X);
  25.          end;
  26.         if rfound=false then begin
  27.          ResRange := tmpLow.ToString+'-'+tmpHigh.ToString;
  28.          rfound:=true;
  29.         end;
  30.        end
  31.           else
  32.            Begin
  33.              rfound:=false;
  34.              if lowC<>tmpHigh then
  35.                 begin
  36.                 ResRange := Lowc.ToString;
  37.            end else ResRange := tmpLow.ToString+'-'+tmpHigh.ToString;
  38.     Target.lines.Add(resRange);
  39.   end;
  40.  
  41.   end;
  42. end;
  43.  
  44.  






-------------------------------------
Today I met with this situation at my work. My co-worker had this list (of folders). Well it was much longer but for purpose of this subject let say it was sth like this
Code: [Select]
1001
1005
1007
1008
1013
1014
1015
1017
1023
1029
1031
1032
1037
1038
1039
1040

He needed to quickly write it in form of ranges like this
Code: [Select]
1001
1005
1007-1008
1013-1015
1017
1023
1029
1031-1032
So I thought I could help him.

I made this but it... well it doesn't work so good. I have few problems.

I get this output :
Code: [Select]
1001
1005
1007-1008
1007-1008
1013-1015
1014-1015
1014-1015
1017
1023
1029
1031-1032
1031-1032


As You can see some values are repeated unnecessary after range has been set and last range is not present :S

Here is my code  Source and Target are TMemo.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.btnGOClick(Sender: TObject);
  2. var
  3.    lowC, highC, tmpLow, tmpHigh, x,i,lastindex: integer;
  4.    ResRange:string;
  5. begin
  6.  
  7.   target.lines.clear;
  8.   lastIndex:=0;
  9.   X:=0;
  10.   for i := 0 to source.lines.count-1 do
  11.   Begin
  12.  
  13.     lowC := StrToInt(Source.Lines.Strings[i]);
  14.     HighC := StrToInt(Source.Lines.Strings[i+1]);
  15.  
  16.     if lowc+1=highc then
  17.        Begin
  18.          tmpLow := lowC;
  19.          X:=i;
  20.  
  21.          While StrToInt(Source.Lines.Strings[X])+1 = StrToInt(Source.Lines.Strings[X+1]) do
  22.          Begin
  23.  
  24.            tmpHigh :=  StrToInt(Source.Lines.Strings[X+1]);
  25.            Inc(X);
  26.  
  27.          end;
  28.  
  29.          ResRange := tmpLow.ToString+'-'+tmpHigh.ToString;
  30.  
  31.        end
  32.           else
  33.            Begin
  34.              if lowC<>tmpHigh then
  35.                 ResRange := Lowc.ToString;
  36.            end;
  37.     if resRange<>'' then
  38.     Target.lines.Add(resRange);
  39.  
  40.  
  41.  
  42.     end;
  43. end;
  44.  


« Last Edit: March 08, 2019, 09:08:29 pm by TomTom »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: A came across this today at my work.
« Reply #1 on: March 08, 2019, 09:31:35 pm »
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   SysUtils, Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   TIntegerArray = array of Integer;
  13.  
  14.   TBooleanArray = array of Boolean;
  15.  
  16.   TForm1 = class(TForm)
  17.     Memo1: TMemo;
  18.     procedure FormCreate(Sender: TObject);
  19.   private
  20.     procedure ProcessNumbers;
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. { TForm1 }
  31.  
  32. procedure TForm1.FormCreate(Sender: TObject);
  33. begin
  34.   Memo1.Clear;
  35.   ProcessNumbers;
  36. end;
  37.  
  38. procedure TForm1.ProcessNumbers;
  39. var
  40.   i: Integer;
  41.   inAdjacentSeq: Boolean = False;
  42.   range: String = '';
  43.   iArr: TIntegerArray;
  44.   bArr: TBooleanArray = Nil;
  45. begin
  46.   iArr := TIntegerArray.Create(1001,1005,1007,1008,1013,1014,1015,1017,1023,1029,1031,1032,1037,1038,1039,1040);
  47.  
  48.   SetLength(bArr, Length(iArr));
  49.   for i := 0 to High(iArr)-1 do
  50.     bArr[i] := iArr[Succ(i)] = Succ(iArr[i]);
  51.  
  52.   for i := 0 to High(iArr) do
  53.     begin
  54.       case bArr[i] of
  55.         True:  begin
  56.                  case inAdjacentSeq of
  57.                    True: ;
  58.                    False: begin
  59.                             range := IntToStr(iArr[i]);
  60.                             inAdjacentSeq := True;
  61.                           end;
  62.                  end;
  63.                end;
  64.         False: case inAdjacentSeq of
  65.                  True:  begin
  66.                           range := range + '-' + IntToStr(iArr[i]);
  67.                           Memo1.Lines.Add(range);
  68.                           inAdjacentSeq := False;
  69.                         end;
  70.                  False: Memo1.Lines.Add(IntToStr(iArr[i]));
  71.                end;
  72.       end;
  73.     end;
  74. end;
  75.  
  76. end.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: A came across this today at my work.
« Reply #2 on: March 09, 2019, 06:20:57 am »
Another possibility:
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, sysutils;
  3.  
  4. procedure ListToRanges(Source, Target: TStrings);
  5. type
  6.   TStates = (StartState, SingleValueOrRangeState, FindEndOfRangeState);
  7. var
  8.   s: string;
  9.   n, start, prev: integer;
  10.   state: TStates;
  11. begin
  12.   state := StartState;
  13.   for s in Source do
  14.   begin
  15.     n := s.ToInteger;
  16.     case state of
  17.       StartState:
  18.       begin
  19.         start := n;
  20.         state := SingleValueOrRangeState;
  21.       end;
  22.       SingleValueOrRangeState:
  23.       begin
  24.         if n-prev = 1 then
  25.           state := FindEndOfRangeState
  26.         else
  27.         begin
  28.           Target.Add('%d',[prev]);
  29.           start := n;
  30.         end;
  31.       end;
  32.       FindEndOfRangeState:
  33.       begin
  34.         if n-prev <> 1 then
  35.         begin
  36.           Target.Add('%d-%d',[start,prev]);
  37.           start := n;
  38.           state := SingleValueOrRangeState;
  39.         end;
  40.       end;
  41.     end;
  42.     prev := n;
  43.   end;
  44.  
  45.   case state of
  46.     SingleValueOrRangeState: Target.Add('%d',[prev]);
  47.     FindEndOfRangeState: Target.Add('%d-%d',[start,prev]);
  48.   end;
  49. end;

 

TinyPortal © 2005-2018