Clean modular increment

I can increment a number modularly in a filter (so for instance 3 → 4 → 5 → 1 → 2 → 3, in mod 5) using this:

 :map[add[1]remainder[5]] :map[match[0]then[5]else{!!title}]

For instance,

{{{ [enlist[1 2 3 4 5]] :map[add[1]remainder[5]] :map[match[0]then[5]else{!!title}] }}}

yields 2 3 4 5 1

But I feel as though there must be something simpler. Am I missing a more elegant technique?

(Note that I can’t hard-code a mapping; my actual length is not 5, but rather 1000, and I might well change to something larger.)

To get the wraparound effect, I don’t suppose you need anything more complex than

:map[subtract[1]remainder[5]add[1]]

EDIT: Oh, if you’re just trying to increment each value (with the modular wraparound), you would not even need that first subtract[1] operation:

:map[remainder[5]add[1]]

The range-operator may be an option: https://tiddlywiki.com/#range%20Operator

Yes, that would work for increment, and I should have seen that.

I don’t see how that would help, except in generating an example. Am I missing something?

Thank you both for the help. I’m afraid I oversimplified the problem, thinking that if I solved increment, I could easily apply it to add(2), add(3), add(4), subtract(1), subtract(2), subtract(3), and so on. @springer: your edit is an elegant way to deal with increment, but I don’t think it expands to the general problem.

Perhaps this is a better phrasing of my general problem:

Is there a simple wikitext way to add or subtract numbers modulo some number – let’s say 5 – given that I want values in the range 1 - 5 and not 0 - 4, as remainder generates?

This works, but feels inelegant:

<$let addend=2 modulus=5>
{{{ [range<modulus>] :map[add<addend>remainder<modulus>] :map[match[0]then<modulus>else{!!title}] }}}
</$let>

yielding

3 4 5 1 2

The range call (or my earlier enlist) is just for demonstration. I will have a number, and would like to add or subtract 1 (and/or 2, 3, or other small integers) from each of them, modulo some value, but returning positive numbers and not zero.

If there’s nothing more elegant, this is not terrible. But I feel as though I’m likely missing a simpler approach.

I’m still baffled why add[1] at the end of the filter feels inelegant to you?

(You could integrate the filter into a function or procedure that makes everything quick to type, if it’s about compactness and easy legibility of your code…)

(Also, are you sure that whatever happens next based on this filter result could not work with the value set 0–4 rather than 1–5? Either way, this modulo-math question doesn’t seem like it should be a major speed bump for your project!)

1 Like

Mostly because I forgot to pair it with your subtract, focusing on your edited version, which is really only for increment.

subtract 1operationmoduloadd 1

is elegant and I should have realized that. Sorry.

I then realized that of course remainder isn’t truly a modulo operator, as it will yield negative results for negative inputs, where mod n can only take the values 0, 1, … (n - 1), I can fix this by adding the modulus another time and then taking another remainder, but I’m losing the elegance again. I will bury the following in a function or procedure or something:

:map[subtract[1]add<addend>remainder<modulus>add<modulus>remainder<modulus>add[1]

Of course I could, but then I’d have to add the one back in there. In my case, I don’t think it would make sense.

No, of course not. I already had a working solution. It simply felt clunky.

Thank you again for your help, and for persisting through my mental block!

1 Like