Range modifications: Difference between revisions

Content added Content deleted
m (added whitespace.)
(Added solution for Action!)
Line 192: Line 192:
remove 7 => 1-5,10-25,27-30
remove 7 => 1-5,10-25,27-30


</pre>

=={{header|Action!}}==
<lang Action!>DEFINE PTR="CARD"
TYPE Range=[BYTE low,high]
TYPE Ranges=[
PTR data
INT count]

PROC InitRanges(Ranges POINTER rs PTR d)
rs.data=d rs.count=0
RETURN

PROC CheckIndex(Ranges POINTER rs INT index)
IF index<0 OR index>=rs.count THEN
Break()
FI
RETURN

PTR FUNC GetItemPtr(Ranges POINTER rs INT index)
CheckIndex(rs,index)
RETURN (rs.data+2*index)

PROC PrintRanges(Ranges POINTER rs)
Range POINTER r
INT i

IF rs.count=0 THEN
Print("empty")
ELSE
FOR i=0 TO rs.count-1
DO
IF i>0 THEN Print(",") FI
r=GetItemPtr(rs,i)
PrintF("%B-%B",r.low,r.high)
OD
FI
RETURN

PROC AppendRange(Ranges POINTER rs BYTE l,h)
Range POINTER r

rs.count==+1
r=GetItemPtr(rs,rs.count-1)
r.low=l r.high=h
RETURN

PROC InsertRange(Ranges POINTER rs INT index BYTE l,h)
Range POINTER r1,r2
INT i

IF index=rs.count THEN
AppendRange(rs,l,h)
RETURN
FI

CheckIndex(rs,index)
rs.count==+1
i=rs.count-1
WHILE i>index
DO
r1=GetItemPtr(rs,i-1)
r2=GetItemPtr(rs,i)
r2.low=r1.low r2.high=r1.high
i==-1
OD
r1=GetItemPtr(rs,index)
r1.low=l r1.high=h
RETURN

PROC DeleteRange(Ranges POINTER rs INT index)
Range POINTER r1,r2
INT i

CheckIndex(rs,index)
FOR i=index TO rs.count-2
DO
r1=GetItemPtr(rs,i+1)
r2=GetItemPtr(rs,i)
r2.low=r1.low r2.high=r1.high
OD
rs.count==-1
RETURN

BYTE FUNC InRange(Range POINTER r BYTE n)
IF r.low<=n AND n<=r.high THEN
RETURN (1)
FI
RETURN (0)

INT FUNC FindRange(Ranges POINTER rs BYTE n)
Range POINTER r
INT i

FOR i=0 TO rs.count-1
DO
r=GetItemPtr(rs,i)
IF n<=r.high THEN
RETURN (i)
FI
OD
RETURN (rs.count)

PROC Add(Ranges POINTER rs BYTE n)
Range POINTER r,r2
INT i

IF rs.count=0 THEN
AppendRange(rs,n,n) RETURN
FI
FOR i=0 TO rs.count-1
DO
r=GetItemPtr(rs,i)
IF n<r.low-1 THEN
InsertRange(rs,i,n,n) RETURN
ELSEIF n=r.low-1 THEN
r.low=n RETURN
ELSEIF n<=r.high THEN
RETURN
ELSEIF n=r.high+1 THEN
r.high=n
IF i<rs.count-1 THEN
r2=GetItemPtr(rs,i+1)
IF n=r2.low OR n+1=r2.low THEN
r.high=r2.high
DeleteRange(rs,i+1)
FI
FI
RETURN
ELSEIF i=rs.count-1 THEN
AppendRange(rs,n,n)
RETURN
FI
OD
RETURN

PROC Remove(Ranges POINTER rs BYTE n)
Range POINTER r
BYTE h
INT i

IF rs.count=0 THEN
RETURN
FI
FOR i=0 TO rs.count-1
DO
r=GetItemPtr(rs,i)
IF n<=r.low-1 THEN
RETURN
ELSEIF n=r.low THEN
r.low=n+1
IF r.low>r.high THEN
DeleteRange(rs,i)
FI
RETURN
ELSEIF n<r.high THEN
h=r.high
r.high=n-1
InsertRange(rs,i+1,n+1,h)
RETURN
ELSEIF n=r.high THEN
r.high=n-1
RETURN
FI
OD
RETURN

PROC TestAdd(Ranges POINTER rs BYTE n)
PrintF("%E Add %B -> ",n)
Add(rs,n)
PrintRanges(rs)
RETURN

PROC TestRemove(Ranges POINTER rs BYTE n)
PrintF("%E Remove %B -> ",n)
Remove(rs,n)
PrintRanges(rs)
RETURN

PROC Main()
CARD ARRAY d(20)
Ranges rs

InitRanges(rs,d)
PrintRanges(rs)
TestAdd(rs,77)
TestAdd(rs,79)
TestAdd(rs,78)
TestRemove(rs,77)
TestRemove(rs,78)
TestRemove(rs,79)

PutE() PutE()
InitRanges(rs,d)
AppendRange(rs,1,3)
AppendRange(rs,5,5)
PrintRanges(rs)
TestAdd(rs,1)
TestRemove(rs,4)
TestAdd(rs,7)
TestAdd(rs,8)
TestAdd(rs,6)
TestRemove(rs,7)

PutE() PutE()
InitRanges(rs,d)
AppendRange(rs,1,5)
AppendRange(rs,10,25)
AppendRange(rs,27,30)
PrintRanges(rs)
TestAdd(rs,26)
TestAdd(rs,9)
TestAdd(rs,7)
TestRemove(rs,26)
TestRemove(rs,9)
TestRemove(rs,7)
RETURN</lang>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Range_modifications.png Screenshot from Atari 8-bit computer]
<pre>
empty
Add 77 -> 77-77
Add 79 -> 77-77,79-79
Add 78 -> 77-79
Remove 77 -> 78-79
Remove 78 -> 79-79
Remove 79 -> empty

1-3,5-5
Add 1 -> 1-3,5-5
Remove 4 -> 1-3,5-5
Add 7 -> 1-3,5-5,7-7
Add 8 -> 1-3,5-5,7-8
Add 6 -> 1-3,5-8
Remove 7 -> 1-3,5-6,8-8

1-5,10-25,27-30
Add 26 -> 1-5,10-30
Add 9 -> 1-5,9-30
Add 7 -> 1-5,7-7,9-30
Remove 26 -> 1-5,7-7,9-25,27-30
Remove 9 -> 1-5,7-7,10-25,27-30
Remove 7 -> 1-5,10-25,27-30
</pre>
</pre>