Anonymous user
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>
|