t,r;h(a,b){r=b?h(b,a%b):a;}c(n){n=n<2?:h(t=c(n-1),n)<2?t-~n:t/r;}
Attempt This Online!
This is based on py3programmer's answer; I'm posting this mostly for their benefit since they say they didn't fully understand the golfing suggestions I gave.
Here's their current version:
h(a,b){if(b){return h(b,a%b);}else{return a;}}c(n){if(n<2){return 1;}if(h(c(n-1),n)<2){return c(n-1)+n+1;}else{return c(n-1)/h(c(n-1),n);}}
The first thing I did was convert the if
/else
statements into ?
/:
conditional expressions. You can read x?y:z
as "if x then y, otherwise z".
h(a,b){return b?h(b,a%b):a;}c(n){return n<2?1:h(c(n-1),n)<2?c(n-1)+n+1:c(n-1)/h(c(n-1),n);}
GCC has a non-standard extension to C that lets you use x?:z
to mean "if x, then x, otherwise z":
h(a,b){return b?h(b,a%b):a;}c(n){return n<2?:h(c(n-1),n)<2?c(n-1)+n+1:c(n-1)/h(c(n-1),n);}
Another quirk of GCC, when used in -O0
optimisation mode (which is the default), is that the CPU register used for the return value of a function is the same as the one used for its first parameter. As a result, we can replace return
statements with assignments to the first parameter for both functions:
h(a,b){a=b?h(b,a%b):a;}c(n){n=n<2?:h(c(n-1),n)<2?c(n-1)+n+1:c(n-1)/h(c(n-1),n);}
Then I noticed that the value c(n-1)
is reused quite a lot, so I extracted it into a temporary variable:
t;h(a,b){a=b?h(b,a%b):a;}c(n){n=n<2?:h(t=c(n-1),n)<2?t+n+1:t/h(t,n);}
I declared it as a global variable, because that doesn't require a type in the declaration, but it makes no difference in functionality.
Then I made use of this tip which states that x+y+1
can be shortened to x-~y
(because ~y
is equivalent to -y - 1
)
t;h(a,b){a=b?h(b,a%b):a;}c(n){n=n<2?:h(t=c(n-1),n)<2?t-~n:t/h(t,n);}
I also noticed that h(t,n)
is reused, so I modified h
to store its result in a global variable r
as well as providing it as a return value. We can then use r
instead of calling h
again:
t,r;h(a,b){r=a=b?h(b,a%b):a;}c(n){n=n<2?:h(t=c(n-1),n)<2?t-~n:t/r;}
As pointed out by Kevin Cruijssen in a comment, the a=
assignment turns out to be unnecessary. Why, exactly, is beyond me, but it seems GCC just stores the value in the return register by happenstance.
t,r;h(a,b){r=b?h(b,a%b):a;}c(n){n=n<2?:h(t=c(n-1),n)<2?t-~n:t/r;}