g | x | w | all
Bytes Lang Time Link
11205AB1E legacy250627T033718ZLucenapo
538R220613T213030ZDominic
347Python220613T192930Zloopy wa
112Husk220613T153422ZDominic
02222 bytes total220613T162106ZCong Che
9312Python220613T071647Zpxeger
6511JavaScript ES6220613T084517ZArnauld
011Retina220613T131325Zm90
224x86 32bit machine code220613T124311Zm90
014Octave220613T124249Zflawr
6612Zsh220613T070530Zpxeger
012Brachylog220613T090941ZFatalize
167sh + coreutils220613T095142Zmatteo_c
336Factor220613T094158Zchunes
034Haskell220613T092335Zmatteo_c
336Charcoal220613T091111ZNeil
003BQN220613T080246ZBubbler
112Vyxal220613T074836Zemanresu
8412Retina220613T073648ZNeil
003J220613T073244ZAdá
004APL Dyalog Unicode220613T073106ZAdá
224K ngn/k220613T072435ZBubbler
007Wolfram Language Mathematica220613T070516Zatt
007Pascal FPC220613T062216Ztsh
017Julia220613T051359ZCzylabso
112Jelly220613T045452ZAnders K

05AB1E (legacy), 1+1=2 bytes

·

Try it online!

Doubles the input.

É

Try it online!

Given input % 2.

R, 5 + 3 = 8 bytes

nchar
abs

Attempt This Online!

Commutative for positive values & zero, non-commutative for negative values (since the minus sign is counted as a character by nchar).

Python, 3+4 = 7 bytes

abs

hash

These two builtins commute for most integers.

But not all:

The following depends on an implementation detail of CPython; I didn't find an official spec, below I give my best guess:

hash maps integers onto themselves modulo 2**61-1 (which appears to be the 9th Mersenne prime; also, this may depend on the bitness (32/64 etc.) of the C long of the platform) while keeping the sign (so -4 does not map to 2**61-5 but to -4). Therefore hash(-n)==-hash(n) for all integers except those which equal +/-1 modulo 2**61-1 because in the underlying C implementation -1 is used as an error indicator. So, whenever the hash would be -1, -2 is returned instead.

Minimal demo at TIO

Husk, 1+1 = 2 bytes

ṗ
¬

Try it online!

There are several 1+1 bytes pairs that work in Husk (including a port of the absolute-value/offset approach [a/] that separates a/b by positive/negative values, and some other interesting approaches).

But I like this one best: and ¬ are commutative only for prime numbers, and non-commutative for all positive non-prime integers.

ṗ    # index of x in the infinite list of primes, or zero if non-prime
D    # logical NOT

So:

ṗ¬   # outputs zero for all nonzero inputs
¬ṗ   # outputs 1 for non-primes, zero for prime numbers

22 bytes total

R, 15 bytes

\(x)round(x,-2)

Attempt This Online!

R, 7 bytes

\(x)x^2

Attempt This Online!

Commutes for x 0 mod 100, doesn't for x 0 mod 10 but not 0 mod 100.

Python, 9 + 3 = 12 bytes

\$ f(x) = \operatorname{bitwise\_or}(x, 1) = \begin{cases} x & x \text{ is odd} \\ x + 1 & x \text{ is even} \end{cases} \$

1 .__or__

Attempt This Online!

\$ g(x) = \lvert x \rvert = \begin{cases} x & x \ge 0 \\ -x & x \le 0 \end{cases} \$

abs

Attempt This Online!

Commutes for all \$ x \$ except negative even numbers.

If \$ x \$ is positive or odd, then at least one of \$ f \$ and \$ g \$ will act as the identity function \$ \operatorname{id} \$ and return \$ x \$ unchanged. In that case, clearly, they commute:

$$ h(\operatorname{id}(x)) = h(x) = \operatorname{id}(h(x)) $$

JavaScript (ES6), 6 + 5 = 11 bytes

These functions commute for odd negative values and for even non-negative values. They do not commute for the other cases.

f=
x=>x%2 // 6 bytes
g=
x=>~x  // 5 bytes

Try it online!

Explanation

The sign of the modulo in JS is the sign of the numerator. So the functions are more formally defined as:

$$\begin{align}&f(x)=\cases{0&if $x$ is even\\-1&if $x<0$ and $x$ is odd\\1&if $x>0$ and $x$ is odd}\\ &g(x)=-x-1\end{align}$$

For odd negative values, we have: \$\cases{g(f(x))=g(-1)=0\\f(g(x))=f(-x-1)=0}\$

For even negative values, we have: \$\cases{g(f(x))=g(0)=-1\\f(g(x))=f(-x-1)=1}\$

For odd non-negative values, we have: \$\cases{g(f(x))=g(1)=-2\\f(g(x))=f(-x-1)=0}\$

For even non-negative values, we have: \$\cases{g(f(x))=g(0)=-1\\f(g(x))=f(-x-1)=-1}\$

Generalization

We can actually use any modulo \$m>1\$ for \$f\$, making the non-commutative cases more and more sparse as \$m\$ increases (but obviously, we'd still get infinitely many of them).

Try it online! (example with \$m=5\$)

Retina, 0 + 1 = 1 byte

Try it online!

This is a Count stage that matches an empty string at the start, between every two consecutive digits, and at the end. This produces the number of digits plus 1.


.

Try it online!

This is a Count stage that matches every digit, producing the number of digits.


Applying these in the two possible orders gives \$\mathrm{ndigits}(\mathrm{ndigits}(n))+1\$ and \$\mathrm{ndigits}(\mathrm{ndigits}(n)+1)\$, which are equal if and only if \$\mathrm{ndigits}(n)\$ is 1 less than a power of 10.

x86 32-bit machine code, 2 + 2 = 4 bytes

40 C3
98 C3

Try it online!

Uses the regparm(1) calling convention – argument in EAX, result in EAX.

In assembly:

inc eax; ret\$f\$ simply adds 1 to a number.

cwde; ret\$g\$ sign-extends the low 16 bits of EAX, duplicating bit 15 into all the higher bits.

If the low 15 bits are not all 1, these two functions do not interact, thus they commute.

If the low 16 bits are 1111 1111 1111 1111, either order of functions results in 0.

If the low 16 bits are 0111 1111 1111 1111, applying \$f\$ then \$g\$ results in -32768, while applying \$g\$ then \$f\$ results in 32768.

Octave, 14 bytes

I haven't seen anyone use this one yet, it might work better in another language. (And it is definitely possible to do better in Octave!)

@(x)x<0
@(x)x>0

The key here is that true == 1 and false == 0. Try it online!

Zsh, 6 + 6 = 12 bytes

tr 1 2

Attempt This Online!

tr 2 3

Attempt This Online!

The first program replaces 1s with 2s; the second replaces 2s with 3s. These commute only for numbers not containing the digit 1.


Old answer:

Zsh, 10 + 10 = 20 bytes

\$ f(x) = \lfloor \frac x 2 \rfloor \$

<<<$[$1/2]

Attempt This Online!

\$ g(x) = 2x \$

<<<$[$1*2]

Attempt This Online!

For even \$ x \$, \$ f(x) = \frac x 2 \$, so \$ g(f(x)) = x \$.

But for odd \$ x \$, /2 rounds downwards, so \$ f(x) = f(x-1) \$, so \$ g(f(x)) = x - 1 \ne x \$

\$ g(x) \$ is always even, so for all \$ x \$, \$ f(g(x)) = x \$.

Therefore, \$ f(g(x)) = g(f(x)) \$ if and only if \$ x \$ is even.

Brachylog, 1 byte (or 2 bytes if including call modifier)

b

Try it online!

I don’t know exactly if that’s bending the rules or not, let me know.

In this single program, f(x) is b - behead, with a given input and an unknown output, and g(x) is also b - behead, but with a given output and an unknown input.

You can run f(g(x) with ↰₁~↰₁ in the header, and g(f(x)) with ~↰₁↰₁. This is why I’m ok with this being scored as 2 bytes, as you need to use ~ to "reverse" the program’s calling order.

Explanation

b asserts that its output is the input without the first element.

Obviously, there are infinitely many positive integers that start with a leading 1, and infinitely many positive integers that don’t.

sh + coreutils, 16 + 7 bytes

(cat;echo +1)|bc
tr -d -

The first function adds one to the number given in input; the second function calculates the absolute value. The composition here is intended as piping the output of one into the other, that is:

echo -n "-12" | (cat;echo +1)|bc | tr -d -
echo -n "-12" | tr -d - | (cat;echo +1)|bc

Factor, 3 + 3 = 6 bytes

abs
?1+

Try it online!

Absolute value and increment. (?1+ is a single word/function that always increments integers by one or changes f [Factor's canonical false value] to 0.) Factor does not come with a 'normal' increment word, such as 1+ in Forth.

Haskell, 3 + 4 bytes

abs
(+1)

If x is non-negative the functions commute, otherwise they do not.

Haskell, 4 + 8 bytes

(*2)
(`div`2)

If x is even, the functions commute. If x is odd, (``div`` 2) $ (*2) x is equl to x, while (*2) $ (``div`` 2) x is equal to x-1.

Charcoal, 3 + 3 = 6 bytes

I↔N

Try it online! Link is to verbose version of code.

I⊕N

Try it online! Link is to verbose version of code.

Another port of @att's Mathematica answer.

BQN, 3 bytes (SBCS)

|¬
|

Try it online!

abs(1-x) and abs(x) respectively. f(g(x)) = abs(1-abs(x)) and g(f(x)) = abs(abs(1-x)) = abs(1-x). The results differ if and only if x is negative.

   F←|¬
   G←|
   x←¯10+↕20
   (F G x)≍(G F x)
┌─                                           
╵  9  8 7 6 5 4 3 2 1 0 1 0 1 2 3 4 5 6 7 8  
  11 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8  
                                            ┘

Vyxal, 1 + 1 = 2 bytes

f(x) = and g(x) = ȧ.

ȧ is absolute value and is decrement, so \$f(g(x))\$ = \$\left|x-1\right|\$ and \$g(f(x))\$ = \$ \left|x\right| - 1\$, which are the same only on positive integers.

Retina, 8 + 4 = 12 bytes

V`[1-9]+

Try it online! Link includes test cases. Explanation: Reverses all runs of non-zero digits.

L`.$

Try it online! Link includes test cases. Explanation: Outputs the last digit, without a sign.

The functions commute in a lot of cases such as the trivial ones of the input being a multiple of 10 or a repdigit.

J, 3 bytes

|  absolute value

>: increment

Try it online!

See att's answer for explanation.

APL (Dyalog Unicode), 4 bytes

| absolute value

1∘+ increment (lit. 1 curried to plus)

Try it online!

See att's answer for explanation.

K (ngn/k), 2 + 2 = 4 bytes

0=
1>

Try it online!

g is boolean negation when the domain is limited to booleans (0 and 1). f(x) and g(x) are the same for x>=0 and different otherwise, and the same can be said for g(f(x)) (negation of f(x)) and f(g(x)) (negation of g(x)).

4 bytes is optimal in ngn/k since any monadic function is at least two bytes long.

Czylabson Asa's mod-2 and mod-3 are also the same length in K: 2! and 3!.

Wolfram Language (Mathematica), 7 bytes

Abs
#+1&

Try it online!

\$(f\circ g)(x)=|x+1|\$, the distance of \$x\$ from \$-1\$. \$(g\circ f)(x)=|x|+1\$, one more than the distance of \$x\$ from \$0\$. These are equal when \$x\ge0\$, and unequal when \$x<0\$.

Plot of abs(x) vs x+1

I suspect this is minimal. Trig functions such as Sin unfortunately are not \$\mathbb Z\to\mathbb Z\$.

Pascal (FPC), 7 bytes

succ
odd

Try it online!

succ acted as \$x \rightarrow x+1\$; while odd acted as \$x \rightarrow x \bmod 2\$. So succ(odd(x)) = odd(succ(x)) iff x is even.

Julia, 17

f(n)=n%2;g(n)=n%3

consider the numbers of form 6k and 6k+3.

ATO

Jelly, 1 + 1 = 2 bytes

\$f(x) = x \bmod 2\$ (Try it online!).

\$g(x) = 2x\$ (Try it online!). These functions commute only for even input.