Code Golf Asked on November 30, 2021
The Cantor function is continuous everywhere and constant almost everywhere, but has an average slope of 1:
The function can be found recursively:
$f_0(x)=x$
$f_{n+1}(x)=left{begin{matrix}frac{1}{2}f_n(3x)&xin[0,frac{1}{3})\ frac{1}{2}&xin[frac{1}{3},frac{2}{3})\ frac{1}{2}+frac{1}{2}f_n(3x-2)&xin[frac{2}{3},1] end{matrix}right.$
The Cantor function is the limit of this process, $limlimits_{ntoinfty} f_n(x)$:
Given real x (which can assume the form of a float or rational number) of the interval $[0,1]$ and nonnegative integer n, return $f_n(x)$.
This is code-golf so the shortest answer in bytes wins.
Assume only valid input will be given.
Error should be under one ten-thousandth (±0.0001) for the test cases.
In: 0.3 3
Out: 0.3875
In: 0.1 0
Out: 0.1
In: 0.29 4
Out: 0.375
In: 0.11 5
Out: 0.2415625
sub f{my$b=pop;my$a=pop;$b--?($a<1/3?f(3*$a,$b):$a<2/3?1:1+f(3*$a-2,$b))/2:$a}
Answered by Xcali on November 30, 2021
Saved 4 bytes thanks to the man himself Arnauld!!!
float f(n,x)float x;{x*=3;x=n--?(x<1?f(n,x):x<2?1:1+f(n,x-2))/2:x/3;}
Answered by Noodle9 on November 30, 2021
3Im*1‰`s3в¹£εTYèsi1V]2βY≠i+}¹o/
Takes the loose inputs in the order $n,x$.
Port of @LuisMendo's MATL answer, so make sure to upvote him as well!
Try it online or verify all test cases.
Explanation:
3Im # Push 3 to the power of the first input-integer
* # Multiply it by the (implicit) input-decimal
1‰ # Get the divmod-1 to split the integer and decimal parts
`s # Pop and push them separated to the stack in reversed order
3в # Convert the integer part to base-3 as list
¹£ # Only leave the first input-integer amount of base-3 digits
ε # Map this list to:
T # Push 10
Yè # Index `Y` into this
# (`Y` is 2 by default, which wraps modulair indices into the 1)
si # If the current digit we're mapping over is 1:
1V # Set `Y` to 1
] # Close both the if-statement and map
2β # Convert the resulting list from base-2 to an integer
Y≠i } # If `Y` is NOT 1:
+ # Add the decimal part that's still on the stack
¹o/ # And divide this by 2 to the power the first input-integer
# (after which the result is output implicitly)
Answered by Kevin Cruijssen on November 30, 2021
-6 bytes thanks to Robin Ryder, +1 byte to fix bug spotted by Neil, -2 bytes thanks to Giuseppe
f=function(x,n,y=x*3)`if`(n,(min(f(y%%2,n-1),1)+!y<2)/2,x)
Un-golfed:
cantor=f=function(x,n){
y=3*x # define y=3*x
# to save characters later.
if(n==0){ x } # if n==0 just return x
else { # otherwise
(
min( # whichever is smaller of:
cantor(y%%2,n-1), # - call self using y mod 2
# (this works for the first & last thirds
# but gives a result >1 for middle third)
1) # - 1 (to fix the middle third)
+(y>=2) # for the top third we need to add 1 to
# the result of the self call
)
/2 # finally, we divide all above results by 2
}
}
Answered by Dominic van Essen on November 30, 2021
Expects (n)(x)
.
n=>g=x=>n--?((x*=3)<1?g(x):x<2||1+g(x-2))/2:x
n => // outer function taking n
g = x => // inner recursive function taking x
n-- ? // decrement n; if it was not equal to 0:
( // compute f_n(x):
(x *= 3) < 1 ? // multiply x by 3; if the result is less than 1:
g(x) // use g(x)
: // else:
x < 2 || // use 1 if x is less than 2
1 + g(x - 2) // otherwise, use 1 + g(x - 2)
) / 2 // in all cases, divide the result by 2
: // else:
x // stop recursion and return f_0(x) = x
Answered by Arnauld on November 30, 2021
{⊥1⊥1⌊⊤1∘≠⍛× ,3⊤⍵×3*⍺}÷2*⊣
Inline tacit function, which can be used as n f x
.
Uses the method described in Luis Mendo's MATL answer. I changed one part of the algorithm:
[2, 2.1]
.) Later, at the step where 2s are changed into 1s, all digits ≥2
are reduced by 1 instead, and (+2 bytes) the fractional part of the last digit is removed if its integer part is 1.{⊥1⊥1⌊⊤1∘≠⍛× ,3⊤⍵×3*⍺}÷2*⊣ ⍝ Left: n, Right: x
{ ⍵×3*⍺} ⍝ 3^n*x
3⊤ ⍝ Convert to base 3; last digit may have fractional part
0, ⍝ Prepend 0 to avoid error on ⊤ over an empty array
1∘≠⍛× ⍝ Keep each digit unless at least one 1 appears somewhere on its left
⊤ ⍝ Convert each digit to binary
1⌊ ⍝ Clamp all digits >1 to 1 (effectively cuts the fractional part of
⍝ the last digit if its integer part is 1)
1⊥ ⍝ Treat the binary of each digit as base 1 and convert back to a number
⍝ Since all numbers are <3, effectively "decrement if ≥2"
⊥ ⍝ Treat as base 2 and convert to single number
÷2*⊣ ⍝ Divide by 2^n
Answered by Bubbler on November 30, 2021
3y^i*1&3_YAt1=f"O@QJh(wkw]XB+wW/
Inputs are n
, then x
.
Try it online! Or verify all test cases.
The code uses a non-recursive approach, based on the procedure for computing the Cantor function $f_infty(x)$ that appears in Wikipedia, modified so that it computes $f_n(x)$ instead:
for
loop instead of an if
branch for step 4 saved quite a few bytes. The value for the branch condition (index of first $1$) needed to be used within the branch code (to replace subsequent digits by $0$). This is cumbersome in MATL, as the if
branch consumes (pops) its condition. Instead, the loop solves this more elegantly: since the branch condition was either empty or a vector of indices of $1$s in $B$, it can be looped over: if it's empty the loop is simply not entered. And then the loop variable can be used within the loop code. The fact that the loop, unlike the conditional branch, may iterate several times (if there are more than one $1$ digit) is not harmful here, because the substitutions in step 4 are idempotent: they simply overwrite some of the previous $0$s with new $0$s.for
loop. Specifically, if the loop is entered, the decimal part $F$ should not be added later on. To implement this, the loop iteration replaces $F$ (previously stored in the stack) by $0$. This is done by a round-down operation (k
), which is convenient because it uses only 1 byte and is, again, idempotent: the result remains equal to $0$ in all iterations after the first.XB
) treats any digit other than $0$ as if it were $1$, which is useful for steps 5 and 6.3 % Step 1. Push 3
y % Implicit input: n. Duplicate from below: pushes n below and
% above the 3
^ % Power: gives 3^n
i* % Input: x. Multiply: gives x*3^n
1 % Step 2. Push 1
& % Two-output modulus: gives modulus (F) and quotient (M)
3_YA % Step 3. Convert to base 3, with digis 0, 1, 2
t1= % Step 4 and part of step 7. Duplicate. Compare each entry with 1
f % Vector (possibly empty) of indices of true values; that is,
% positions of digit 1
" % For each index k
O % Push 0
@Q % Push k+1
Jh( % Write 0 at positions k+1, k+2, ..., end
wkw % Swap, round down, swap. This replaces F by 0
] % End
XB % Steps 5 and 6. Convert from binary to decimal, with digit 2
% interpreted as 1
+ % Part of step 7. Add F, or 0
wW/ % Step 8. Swap (brings n to top), 2 raised to that, divide
% Implicit display
Answered by Luis Mendo on November 30, 2021
Nθ≔↨×NX³θ³ηI∕↨²Eη∧¬№…ηκ¹§⟦ι¹⊖ι⟧ιX²θ
Try it online! Link is to verbose version of code. Based on the Wikipedia entry, I convert the 3ⁿx
to base 3, then massage the digits so that the result can be interpreted as base 2 and divided by 2ⁿ
. Takes input in the order n
, x
. Explanation:
Nθ
Input n
.
≔↨×NX³θ³ηI∕
Multiply x
by 3ⁿ
and convert it to base 3. The last entry includes any remaining fractional part.
Eη∧¬№…ηκ¹§⟦ι¹⊖ι⟧ι
Map over the digits. If there was a previous 1
then set this digit to zero, otherwise map the digit to itself, 1
, or subtract 1
, depending on the floor of the digit. This ensures that the last digit (with the remaining fractional part) is converted correctly.
I∕↨²...X²θ
Convert from base 2, divide by 2ⁿ
, and output the final decimal as a string.
Previous 34-byte solution did not work for x=1
, as it only considered the decimal part of x
:
Nθ≔×NX³θη≔⁻η⌊ηζFθ≔⊘§⟦ζ¹⊕ζ⟧∕ηX³ιζIζ
Try it online! Link is to verbose version of code. Takes input in the order n
, x
. Explanation:
Nθ
Input n
.
≔×NX³θη
Multiply x
by 3ⁿ
.
≔⁻η⌊ηζ
Take the decimal part of that.
Fθ
Loop n
times.
≔⊘§⟦ζ¹⊕ζ⟧∕ηX³ιζ
Depending on the next base 3 digit of the above product, replace the decimal part with half of itself, half of 1, or half of the sum.
Iζ
Output the final decimal as a string.
Answered by Neil on November 30, 2021
{×⍺×1-⍵:2÷⍨(1∘≤+(1≠⌊)×(⍺-1)∇⊢-⌊)3×⍵⋄⍵}
Combines the cases of the recurrence using
$$ f_{n+1}(x) = frac{1}{2}begin{cases} 0+1×f_n(3x-0), xin[0,1/3) \ 1+0×f_n(3x-1), xin[1/3,2/3)\ 1+1×f_n(3x-2), xin[2/3,1] end{cases} $$
which can be condensed (note $u=3x$) to
$$
f_{n+1}left(frac{1}{3}uright) = frac{1}{2}big(
(u<1)+(lfloor urfloorneq 1)×f_n(u-lfloor u rfloor)big)
$$ (since comparisons resolve to True=1 or False=0). This fails for x=1
since then ⌊u
is 3 instead of 2. Using ceiling instead of floor would then fail for x=0
, so it ends up shorter to check specifically for x=1
.
{ ... } ⍺=n; ⍵=x
×⍺×1-⍵: ⍝ If n>0 or x≠1:
3×⍵ ⍝ Let u=3x
(⍺-1)∇⊢-⌊ ⍝ f(n-1, u-floor(u)) (`1∘|` ←→ `⊢-⌊`)
(1≠⌊)× ⍝ Multiply by 1 unless floor(u)=1
1∘≤+ ⍝ Add 1 unless 1 > u
2÷⍨ ⍝ Half of this
⋄ ⍝ Else:
⍵ ⍝ x
Answered by fireflame241 on November 30, 2021
f=lambda n,x:n and(1<x*3<2or x//.5+f(n-1,3*x%1))/2or x
Python 3 is used just for the /2
to do float division; Python 2 would be a byte longer with /2.
.
Answered by xnor on November 30, 2021
_2çH+.
ñH¥.ç<2$?<1$?
×3çɗ⁸⁹?’}
A full program accepting $x$ and $n$ which prints a floating-point representation of $f_n(x)$
Answered by Jonathan Allan on November 30, 2021
f=lambda n,x:n and[f(n-1,e:=3*x),1+e//2*f(n-1,e-2)][e>1]/2or x
Answered by ovs on November 30, 2021
1 byte saved thanks to @FryAmTheEggman
f=lambda n,x:n and((1<=(t:=x*3))+f(n-1,t-2*(t>=2))*(t>=2or 1>t))/2or x
Answered by Uriel on November 30, 2021
of course mathematica has a built-in for this: CantorStaircase[x]
but you cannot choose n
x_~f~0:=x
x_~f~n_:=If[(y=3x)<1,f[y,n-1]/2,If[y<2,.5,.5+f[y-2,n-1]/2]]
@JonathanAllan saved 2 bytes
Here is also another approach from @att which is great!
If[#2<1,#,If[1<3#<2,1,(s=Boole[2#>1])+#0[3#-2s,#2-1]]/2]&
Answered by ZaMoC on November 30, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP