Jump to content

Range modifications: Difference between revisions

Added solution for Action!
m (added whitespace.)
(Added solution for Action!)
Line 192:
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>
 
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.