Calculate Phi (not Pi)

Regex (.NET), 122 113 bytes

^(?=((?=.*$(?<=^(\3+(.+.))(.*?(?>(.\4)?)))).)+(.*))((?=.*(?=\6$)(?<=(?!(.+.)\8*(?=\6$)(?<=^\8+))(.+?(?>\9?)))).)+

Assuming input and output are in unary, and the output is taken from the main match of the regex.

Breakdown of the regex:

  • ^(?=((?=.*$(?<=^(\3+(.+.))(.*?(?>(.\4)?)))).)+(.*)) calculates π̅(x) and captures the rest of the string in capturing group 6 for assertion in the second part.

    • .*$ sets the pointer to the end of the string so that we have the whole number x in one direction.
    • (?<=^(\3+(.+.))(.*?(?>(.\4)?))) matches from right to left and checks for composite number by looping from x to 0.
      • (.*?(?>(.\4)?)) is a "variable" which starts from 0 in the first iteration and continues from the number in previous iteration and loops up to x. Since the smallest composite number is 4, (.\4)? never fails to match if capturing group 4 is available.
      • ^(\3+(.+.)) checks what is left by the "variable" above (i.e. x - "variable") whether it is a composite number.
  • ((?=.*(?=\6$)(?<=(?!(.+.)\8*(?=\6$)(?<=^\8+))(.+?(?>\9?)))).)+ calculates φ(π̅(x)), by limiting the left-to-right operations with (?=\6$).

    • .*(?=\6$) sets the pointer to position π̅(x). Let's denote y = π̅(x).
    • (?<=(?!(.+.)\8*(?=\6$)(?<=^\8+))(.+?(?>\9?))) matches from right to left and checks for relative prime by looping from (y - 1) to 0
      • (.+?(?>\9?)) is a "variable" which starts from 1 in the first iteration and continues from the number in previous iteration and loops up to y
      • (?!(.+.)\8*(?=\6$)(?<=^\8+)) matches from left to right 1 and checks whether the "variable" and y are relative prime.
        • (.+.)\8*(?=\6$) picks a divisor of "variable" which is larger than 1, and a side effect is that we have whole number y on the left.
        • (?<=^\8+) checks whether the divisor of "variable" is also the divisor of y.

1 In .NET, look-ahead sets the direction to LTR instead of following the current direction; look-behind sets the direction to RTL instead of reversing the direction.

Test the regex at RegexStorm.

Revision 2 drops non-capturing groups and uses atomic groups instead of conditional syntax.


GS2, 12 10 bytes

V@'◄l.1&‼l

The source code uses the CP437 encoding. Try it online!

Test run

$ xxd -r -ps <<< 564027116c2e3126136c > phinotpi.gs2
$ wc -c phinotpi.gs2 
10 phinotpi.gs2
$ gs2 phinotpi.gs2 <<< 1000
552

How it works

V          Read an integer n from STDIN.
 @         Push a copy of n.
  '        Increment the copy of n.
   ◄l      Push 1 and call primes; push the list of all primes below n+1.
     .     Count the primes.
      1    Subtract the count from n.
       &   Decrement to account for 1 (neither prime nor composite).
        ‼l Push 3 and call primes; apply Euler's totient function.

J, 15 14 bytes

5 p:<:-_1 p:>:

This is a tacit, monadic verb. Try it online with J.js.

How it works

                Right argument: y
            >:  Increment y.
       _1 p:    Calculate the number of primes less than y+1.
    <:          Decrement y.
      -         Calculate the difference of the results to the left and right.
5 p:            Apply Euler's totient function to the difference.