# Bounce-modulo two numbers

The graph of the modulo operation ($y = x \mod k$) looks like this:

This is a very useful function, as it allows us to create "wrapping" behavior. However, it is very cumbersome when I want to use it to create an appearance of "bouncing" between two walls. The graph of the "bounce" function ($y = \text{bounce} (x, k)$) looks like this:

The period of the graph of $y = x \mod k$ is $k$. The period of the graph of $y = \text{bounce} (x, k)$ is $2k$, because it moves upwards for $k$ units, and then moves downwards for another $k$ units, before returning to where it started. For both functions, the minimum value for $y$ is 0, and the maximum is $k$ (Actually, for the modulus function with integral inputs, it's $k-1$). In addition, for both functions, the value where $x=0$ is 0.

## The challenge

Given an integer $x$ and a positive integer $k$, return an integer or floating-point approximation of $y = \text{bounce} (x, k)$.

This is , so the shortest valid submission (counted in bytes) wins.

## Test Cases

x,  k -> bounce(x, k)
0, 14 ->            0
3,  7 ->            3
14, 14 ->           14
15, 14 ->           13
-13, 14 ->           13 (12.999997 etc would be an acceptable answer)
-14, 14 ->           14
191,  8 ->            1
192,  8 ->            0

Bonus points for a Fourier-based approach in Fourier.

• "For both functions, the minimum value for x is 0, and the maximum is k" is just plain wrong. Jul 16, 2017 at 5:47
• @PeterTaylor Whoops. I means the result. Jul 16, 2017 at 5:49
• Oops, that's what I thought it said already. It's still wrong. k % k = 0 Jul 16, 2017 at 5:51
• @PeterTaylor Oh, I understand your question. I had originally designed this with floating-point in mind, then switched to just ints after. Will edit. Jul 16, 2017 at 6:05
• @PeterTaylor If the arguments are floats, then the maximum is a number arbitrarily close to k. Jul 16, 2017 at 6:07

# x86-64 Machine Code, 18 bytes

97
99
31 D0
29 D0
99
F7 FE
29 D6
A8 01
0F 45 D6
92
C3

This code defines a function in x86-64 machine language that computes bounce(x, k). Following the System V AMD64 calling convention used on Gnu/Unix systems, the x parameter is passed in the EDI register, while the k parameter is passed in the ESI register. As with all x86 calling conventions, the result is returned in the EAX register.

To call this from C, you would prototype it as follows:

int Bounce(int x, int k);

Try it online!

Ungolfed assembly mnemonics:

; Take absolute value of input 'x' (passed in EDI register).
; (Compensates for the fact that IDIV on x86 returns a remainder with the dividend's sign,
; whereas we want 'modulo' behavior---the result should be positive.)
xchg   eax, edi      ; swap EDI and EAX (put 'x' in EAX)
cdq                  ; sign-extend EAX to EDX:EAX, effectively putting sign bit in EDX
xor    eax, edx      ; EAX ^= EDX
sub    eax, edx      ; EAX -= EDX

; Divide EDX:EAX by 'k' (passed in ESI register).
; The quotient will be in EAX, and the remainder will be in EDX.
; (We know that EAX is positive here, so we'd normally just zero EDX before division,
; but XOR is 2 bytes whereas CDQ is 1 byte, so it wins out.)
cdq
idiv   esi

; Pre-emptively subtract the remainder (EDX) from 'k' (ESI),
; leaving result in ESI. We'll either use this below, or ignore it.
sub    esi, edx

; Test the LSB of the quotient to see if it is an even number (i.e., divisible by 2).
; If not (quotient is odd), then we want to use ESI, so put it in EDX.
; Otherwise (quotient is even), leave EDX alone.
test   al, 1
cmovnz edx, esi

; Finally, swap EDX and EAX to get the return value in EAX.
xchg   eax, edx
ret

Note that the first section (that takes the absolute value) could have equivalently been written:

; Alternative implementation of absolute value
xchg    eax, edi
neg     eax
cmovl   eax, edi

which is the exact same number of bytes (6). The performance should be similar, perhaps slightly faster (except on certain Intel chips, where conditional moves are slow).

XCHG is, of course, relatively slow and would not be preferred over MOV except in code golfing (since the XCHG is 1-byte when one of the operands is the accumulator, whereas a register-register MOV is always 2 bytes).

# Jelly, 3 bytes

æ%A

Try it online!

Built-ins ftw.

### Explanation

æ% is a useful built-in here. I don't know how to describe it, so I'll just provide the output for some inputs:

As x goes from 0 to infinity, xæ%4 goes 0,1,2,3,4,(-3,-2,-1,0,1,2,3,4,) where the part in parentheses is repeated to infinity both ways.

# Python 2, 29 27 bytes

lambda x,k:abs(x%k-x/k%2*k)

Try it online!

# Python 3, 27 bytes

lambda x,k:k-abs(k-x%(k*2))

Try it online!

## JavaScript (ES6), 36 32 bytes

k=>f=x=>x<0?f(-x):x>k?k-f(k-x):x

Recursively bounces x against 0 and k, so very much in the spirit of the challenge.

## Ruby, 40 bytes 32 bytes

b=->(x,k){(x/k+1)%2>0?x%k:k-x%k}

Try it online!

### Explanation

Hi, this is my first answer on this site! This code is based on the observation that the bounce function behaves exactly like modulo when (n-1)k <= x < nk and n is odd, and behaves like a reversed modulo operation when n is even. (x/k+1) is the smallest integer greater than x/k (which is x/k+1 rounded down to an integer). Therefore, (x/k+1) finds the n mentioned above. %2>0 checks to see if n is odd or even. If n mod 2 > 0, then n is odd. If n mod 2 = 0, then n is even. If n is odd, then the bounce function should equal x mod k. If n is even, the bounce function should be the reverse, equal to k - x mod k. The whole expression (x/k+1)%2>0?x%k:k-x%k finds n, then executes the x mod k if it is odd, and executes k - x mod k otherwise.

The answer was improved based on a suggestion from Cyoce.

• You can convert this to a lambda. Instead of def b(x,k) ... end use ->x,k{...} Jul 20, 2017 at 7:23
• And since you're dealing with integers, .to_i isn't necessary. Jul 20, 2017 at 7:25

# Mathematica, 19 bytes

Abs@Mod[#,2#2,-#2]&

# Pyth, 5 bytes

aa%Ey

Verify all testcases.

# J, 25 bytes

Hint:

This is just regular modulo on the ladder numbers. For example, in the case of 5: 0 1 2 3 4 5 4 3 2 1

Here is a (not yet well-golfed) solution in J. Will try to improve tomorrow:

[ ((|~ #) { ]) (i.@>:,}:@i.@-) @ ]

compressed: [((|~#){])(i.@>:,}:@i.@-)@]

compressed2: [((|~#){])(<:|.|@}.@i:)@]

Try it online!

• I feel like i: can be used here, but I haven't tried a solution yet Jul 16, 2017 at 16:46
• @ConorO'Brien check out my compressed2 version, it saves a few bytes using i:. Just haven't had time to update the main one and provide an explanation. I expect an expert could shave off another 4 or 5 bytes at least... Jul 16, 2017 at 16:48
• ((|~#){])]-|@}:@i: for 18 bytes Jul 16, 2017 at 22:20
• @miles beautiful, tyvm Jul 16, 2017 at 22:28

# QBIC, 2530 27 bytes

g=abs(:%:)~a'\b%2|?b-g\?g

Did a bit of restructuring...

## Explanation

g=abs(   )  let g be the absolute value of
%    the (regular) modulo between
: :   input a read from cmd line, and input b read from cmd line
~a \ b%2    IF the int division of A and B mod 2 (ie parity test) yields ODD
'          (int divisions need to be passed to QBasic as code literals, or ELSE...)
|?b-g       THEN print bouncy mod
\?g         ELSE print regular mod
• Does QBIC do something different for MOD operations than other Basic implementations do? Other Basics return MOD with the same sign as the dividend; that would fail when x is -13 and k is 14. Jul 16, 2017 at 9:18
• @CodyGray Nope, it gave -13. Fixed now. Jul 16, 2017 at 9:25
• Don't you need abs both times?
– Neil
Jul 16, 2017 at 9:31
• @Neil do you have a testcase for that? Jul 16, 2017 at 9:33
• @Neil nvm, I've fixed it by restructuring the whole thing. Jul 16, 2017 at 9:43

# C89, 40 bytes

t;f(x,k){t=abs(x%k);return x/k%2?k-t:t;}

A C port of my x86 machine code answer, this defines a function, f, that calculates the bounce-modulo for the parameters x and k.

It uses C89's implicit-int rule, so that both parameters, the global variable t, and the function's return value are all implicitly of type int. The global variable t is just used to hold a temporary value, which ends up saving bytes, compared to repeating the computation on either side of the conditional operator.

The abs function (absolute value) is provided in the <stdlib.h> header, but we don't have to include it here, again thanks to C89's implicit-int rule (where the function is implicitly declared and assumed to return int).

Try it online!

Ungolfed version:

#include <stdlib.h>

int Bounce(int x, int k)
{
int mod = abs(x % k);
return (x/k % 2) ? k-mod : mod;
}

Looking at this in light of my hand-tuned machine code, compilers actually generate pretty good output for this. I mean, they should; it's a pretty simple function to optimize! I did uncover a minor bug in GCC's x86-64 optimizer, though, where it curiously produces larger code when you tell it to optimize for size and smaller code when you tell it to optimize for speed.

• m;f(x,k){m=abs(x%k);x=x/k%2?k-m:m;} is shorter Jul 16, 2017 at 18:12
• Except that it doesn't actually return a value, @cows, other than under certain ill-defined circumstances due to a quirk of the GCC code generator on x86 targets. It's a template I see people use here, but it doesn't work for me, any more than pulling random garbage off the stack that just happens to be the correct answer. Jul 17, 2017 at 5:07

Try it online!

(!)=mod;x#k|odd$xdivk=k-x!k|1<2=x!k How to use: Call as 15#14 for non-negative left arguments and as (-13)#14 for negative left arguments, because Haskell would interpret -13#14 as -(13#14) if you are using something like ghci. The TIO-link simply takes two command-line arguments. Explanation: First redefines the binary infix operator ! to be the same as mod. Haskell's mod always outputs a non-negative value, so we don't need the abs that other solutions here do. It then checks whether x/k (integer division) is odd and if so, returns k-x mod k (ie the back-bounce) or else it returns x mod k. • This is probably just a matter of taste, but I personally prefer not defining ! since it doesn't save any bytes over x#k|odd$xdivk=k-xmodk|1<2=xmodk Jul 20, 2017 at 3:32

# PHP, 40 50 bytes

damn dollars. damn import overhead. :)

integer version:

[,$x,$k]=$argv;$y=abs($x)%$k;echo$x/$k&1?$k-$y:$y; or [,$x,$k]=$argv;echo[$y=abs($x)%$k,$k-$y][$x/$k&1]; float version, 56 bytes: Replace abs($x)%$k with fmod(abs($x),$k). edit: fixed results for negative x • "Damn dollars". Yeah, money stinks... Jul 16, 2017 at 9:44 • How about €argv or £argv? Those would look nice :x Jul 16, 2017 at 12:12 # Vyxal, 5 bytes d%ε¹ε Try it Online! ## How? d%ε¹ε d # Double the (implicit) first input % # Modulo the (implicit) second input by this ε # Take the absolute difference of this and the (implicit) first input ¹ε # Take the absolute difference of this and the first input again # Common Lisp, 41 bytes (lambda(x k)(- k(abs(-(mod x(* k 2))k)))) Try it online! # C (gcc), 43 53 bytes Edit: Fixed negative issue int f(int x,int y){return x/y%2?abs(y-x%y):abs(x%y);} Try it Online! • This provides the wrong answer for (-13, 14) (-13 instead of 13). The modulus and remainder operations behave different on negative numbers. Jul 16, 2017 at 7:30 # R, 28 bytes pryr::f(abs((x-k)%%(2*k)-k)) Which evaluates to the function: function (k, x) abs((x - k)%%(2 * k) - k) Which appears to be the method that most solutions use. I didn't look at them before making this. # MMIX, 20 bytes (5 instrs) "xxd --jelly" 00000000: 1c02 0001 fe00 0006 24ff 0100 6600 02ff ÷£¡¢“¡¡©$”¢¡f¡£”
00000010: f801 0000                                ẏ¢¡¡

disassembly and commentary

bounce  DIV  $2,$0,$1 // f:rR = x /% k GET$0,rR          // rv = rR
SUB  $255,$1,$0 // t = k - rv CSOD$0,$2,$255     // if(f odd) rv = t
POP  1,0            // return rv

Not entirely sure what this does if k is negative, but it's probably the negative of bounce(x,k).