For #47 (see 1st Post)
Code:
listIncrDecrElement
@from http://www.wiki4hp.com/doku.php?id=rpl:start
\<<
PICK3 PICK3
GET + PUT
\>>
\<<
@input
"lvMaxValue" DROP
"lvPosList" DROP
@local var
DUP "lvOrigPosList" DROP
DUP SIZE "lvPosListSize" DROP
0 "lvElement" DROP
0 "lvCarry" DROP
0 "lvIsThereCarry" DROP
\->
lvMaxValue
lvPosList
lvOrigPosList @if the current list goes overflow
lvPosListSize
lvElement
lvCarry
lvIsThereCarry
\<<
@TODO: check the carry with MAP and then addition between list operatons.
@ - get the initial list
@ - add one via list operation, do { 1 3 3 } plus { 0 0 1 } => { 1 3 4 }
@ - check if there is overflow with a map operation
@ { 1 3 4 } produces { 0 0 1 }
@ - check if there is carry with \GSLIST on the overflow. If { 0 0 1 } > 0 then we continue
@ - roll the carry { 0 0 1 } -> { 0 1 0 } but be careful if there is carry in the leading position, it should end.
@ say maxvalue of 3: { 1 1 } -> { 1 2 } -> { 1 3 } converted to { 2 1 } -> { 2 2 } -> { 2 3 } converted to { 3 2 }
@ it should stop.
@ Thus the carry in leading position, if detected, should never be rolled.
@ - trim the values of the original number, still with map, note that the overflowing value should go to 1
@ { 1 3 4 } -> { 1 3 1 }
@ - add the carry
@ { 1 3 1 } -> { 1 4 1 }
@ - verify if there is overflow again with map
@ { 1 4 1 } yields { 0 1 0 }
@ - repeat the steps before as long as there is carry
@ - No carry or carry in the leading position means that the process should end.
@ - 11:41 13.03.2023 not able to use MAP as it wants to change flags and thus is unpractical
@ (I should save and restore flags if needed and I don't want to)
@increment the list by 1
lvPosList
lvPosListSize
1
listIncrDecrElement
'lvPosList' STO
1 'lvIsThereCarry' STO @setting it to 1 to let the while go.
WHILE
lvPosList 1 GET
lvMaxValue >
NOT
@ check if the leading position is over the maxValue, if yes, it should stop
@ note that the leading position can overflow only due to the carry
@ process, because the incrementing the list by 1 affects only the trailing element.
lvIsThereCarry @this starts with 1, then get reset to zero for each check
AND
REPEAT
@ check if there is carry
0 'lvIsThereCarry' STO
1 lvPosListSize
FOR lvPos @MAP doesn't work without changing flags
IF @could use IFTE but less readable
lvPosList lvPos GET
lvMaxValue > @if it is bigger than the maxvalue
THEN
1 @leave carry, as we increment always by 1, there could be only 1 as carry
1 'lvIsThereCarry' STO @even overriding is ok
ELSE
0 @no carry
END
NEXT
lvPosListSize \->LIST
'lvCarry' STO
IF
lvIsThereCarry @only if there is carry, we can spare operations (also to debug)
THEN
@trim the original list, remove the extra values (from 1 3 4 } -> { 1 3 1 } if maxvalue is 3)
1 lvPosListSize
FOR lvPos @MAP doesn't work without changing flags
lvPosList lvPos GET
DUP @the value read in the list
IF @could use IFTE but less readable
lvMaxValue > @if it is bigger than the maxvalue
THEN
DROP @removed the original value used by DUP
1 @leaves 1
END
@else it leaves the value used by DUP
NEXT
lvPosListSize \->LIST
'lvPosList' STO
@roll the carry and add it if needed
lvPosList @prepare for the add
@roll the carry to then add it.
lvCarry LRLLD @the first position will always have a value of 0, otherwise the program exited already,
@thus can be rolled down.
@then add it, '+' does concatenation so it doesn#t work.
ADD
'lvPosList' STO
END
END
@report the result
IF
lvPosList 1 GET
lvMaxValue >
THEN
lvOrigPosList
ELSE
lvPosList
END
\>>
\>>