Find the 10-adic cube root of 3

24

1

I like to think of a 10-adic number as a number that goes infinitely to the left, or an integer modulo a very very large power of 10.

Things carry infinitely to the left and vanish. To see what I mean, note that ...6667 * 3 = 1 in the 10-adic land, since the "2" that carries to the left goes to infinity.

Addition and multiplication make sense for 10-adic numbers, since the last n digits of the sum/product only depend on the last n digits of the summands/multiplicands.


Given n, you need to print the last n digits of the 10-adic cube root of 3, i.e. x satisfiying x*x*x = 3.

It ends:

...878683312291648481630318492665160423850087895134587

Your code must terminate for n=1000 before submission.

Let's say that if the number you need to print begins with zero, then you don't need to print the leading zeroes, since it isn't actually the point to print extra zeroes.


This is . Shortest answer in bytes wins.

Leaky Nun

Posted 2018-06-07T10:24:54.223

Reputation: 45 011

OEIS A225404 – Leaky Nun – 2018-06-07T13:52:24.160

1Do we need to print leading zeros as well? Most answers (including my Java answer) are currently failing for those. i.e. n=12 outputting 87895134587 instead of 087895134587. Personally I would make it optional, since it would invalidate almost all answers.. – Kevin Cruijssen – 2018-06-07T13:56:16.607

@KevinCruijssen done – Leaky Nun – 2018-06-07T14:14:43.940

Answers

26

Python 2, 33 bytes

lambda k:pow(3,10**k*2/3+1,10**k)

Try it online!

The pow function efficiently computes the modular exponent 3**(10**k*2/3+1)%10**k.

We're asked to find a solution to r**3 = 3 (mod 10**k). We want to find an exponent e for which the map x -> x**e is inverse to cubing x -> x**3 working mod 10**k, just as the decryption and encryption exponents in RSA cancel to produce the original value. This means that (x**3)**e = x (mod 10**k) for all x. (We'll assume throughout that gcd(x,10) = 1.) Then, we can recover r by inverting the cubing to get r = 3**e (mod 10**k).

Expanding out (r**3)**e = r (mod 10**k), we get

r**(3*e-1) = 1 (mod 10**k)

We're looking for an exponent 3*e-1 that guarantees that multiplying that many copies gives us 1.

Multiplication modulo 10**k forms a group for invertible numbers, that is those with gcd(x,10) = 1. By Lagrange's Theorem, x**c = 1 where c is the count of elements in the group. For the group modulo N, that count is the Euler totient value φ(N), the number of values from 1 to N that are relatively prime to N. So, we have r**φ(10**k) = 1 (mod 10**k). Therefore, its suffices for 3*e-1 to be a multiple of φ(10**k).

We compute

φ(10**k) = φ(5**k) φ(2**k)= 4 * 5**(k-1) * 2**(k-1) = 4 * 10**(k-1)`

So, we want 3*e-1 to be a multiple of 4 * 10**(k-1)

3*e - 1 = r * 4 * 10**(k-1)
e = (4r * 10**(k-1) + 1)/3

Many choices are possible for r, but r=5 gives the short expression

e = (2 * 10**k + 1)/3

with e a whole number. A little golfing using floor-division shortens e to 10**k*2/3+1, and expressing r = 3**e (mod 10**k) gives the desired result r.

xnor

Posted 2018-06-07T10:24:54.223

Reputation: 115 687

1I would like to see a more detailed explanation on how this works, very nice answer! – user41805 – 2018-06-07T15:43:53.873

Should (r**3)**e = x (mod 10**k) be (r**3)**e = r (mod 10**k)? Also is it just a coincidence that (2 * 10**k + 1)/3 = 1/3 (mod 10**k)? – H.PWiz – 2018-06-08T01:46:34.720

@H.PWiz Yes, thanks, I fixed it. I'm not sure if it being an inverse for 3 is a coincidence. It's certainly not enough, as replacing the 2 with other values doesn't work. – xnor – 2018-06-08T01:57:40.277

@xnor I think it is enough. You should be able to replace to replace 2 with any number x = 2 (mod 3) – H.PWiz – 2018-06-08T02:23:40.210

As usual, maths win! – Olivier Grégoire – 2018-06-08T13:07:36.153

18

Python 2 (PyPy), 55 50 bytes

-5 bytes thanks to @H.P. Wiz!

n=p=1;exec"p*=10;n+=3*(3-n**3)%p;"*input();print n

Try it online!

Calculates (non-bruteforcing) digit by digit, so it's faster than brute force.

Version without exec

Explanation

(Thanks @Leaky Nun and @user202729 for figuring this out)

First, observe that n**3 is an involution modulo 10 (i.e. if the function is called f, then f(f(n)) == n). This can be confirmed using an exhaustive search.

We can use mathematical induction to find the next digit.
Let dn be the nth digit of the number (from the right).

d13 ≡ 3  (mod 10)
 d1 ≡ 33 (mod 10)
    ≡ 27 (mod 10)
    ≡ 7  (mod 10)

Now, assume we know the number up to the kth digit, x

              x3 ≡ 3 (mod 10k)
  (dk+1·10k + x)3 ≡ 3 (mod 10k+1)
3·dk+1x2·10k + x3 ≡ 3 (mod 10k+1) (Binomial expansion.)
(Note that the other two terms can be ignored since they are 0 mod 10k+1)
3·dk+1x2·10k + x3 ≡ 3 (mod 10k+1)

We know that:

       x ≡ 7      (mod 10)
      x2 ≡ 49     (mod 10)
         ≡ 9      (mod 10)
  x2·10k ≡ 9·10k  (mod 10k+1)
3·x2·10k ≡ 27·10k (mod 10k+1)
         ≡ 7·10k  (mod 10k+1)

Substituting this in:

3·dk+1x2·10k + x3 ≡ 3                  (mod 10k+1)
  7·dk+1·10k + x3 ≡ 3                  (mod 10k+1)
             dk+1 ≡ (3 - x3) ÷ (7·10k) (mod 10)
                 ≡ (3 - x3) ÷ (7·10k) (mod 10)
           ∴ dk+1 ≡ 3·(3 - x3) ÷ 10k   (mod 10) (3 is the inverse of 7 mod 10)

ASCII-only

Posted 2018-06-07T10:24:54.223

Reputation: 4 687

Actually this solution is likely to be optimal. (for most languages where the formula is less verbose than brute forcing) Explanation can be found somewhere in chat, although quite scattered.

– user202729 – 2018-06-07T11:00:29.640

If you aimed to golf the "non-exec" solution, this works for 62 bytes as a full program instead of a function

– Mr. Xcoder – 2018-06-07T12:53:37.360

This only prints the last 11 digits for n=12 and n=13. – Emigna – 2018-06-07T13:41:19.023

@user202729 I don't think it would be optimal. You don't need to compute the entirety of n**3 to compute n**3/p, for example. – Leaky Nun – 2018-06-07T13:46:14.107

@LeakyNun Optimal in terms of code size... – user202729 – 2018-06-07T13:47:33.410

4

× and x look really quite similar in some fonts, and make the maths extremely hard to read. May I suggest using · (centre dot) instead of × ? (And, obviously, it would be nice to have MathJax).

– Peter Taylor – 2018-06-07T16:06:04.913

1save 5 bytes – H.PWiz – 2018-06-07T16:40:50.507

(H.PWiz later noted that my solution fails for n<3) – user41805 – 2018-06-07T19:52:39.313

6

Wolfram Language (Mathematica), 21 bytes

PowerMod[3,1/3,10^#]&

Try it online!

alephalpha

Posted 2018-06-07T10:24:54.223

Reputation: 23 988

4

05AB1E, 17 13 bytes

7IGD3mN°÷7*θì

Port of @ASCII-only's Python 2 (PyPy) answer.
-4 bytes AND bug-fixed for outputs with leading zeros thanks to @Emigna, by replacing T%N°*+ with θì.

Try it online.

Explanation:

7               # Start result-string `r` at '7'
IG              # Loop `N` in the range [1, input)
  D3m           #  `r` to the power 3
       ÷        #  Integer-divided with
     N°         #  10 to the power `N`
        7*      #  Multiplied by 7
          θì    #  Then take the last digit of this, and prepend it to the result `r`
                # Implicitly output result `r` after the loop

Kevin Cruijssen

Posted 2018-06-07T10:24:54.223

Reputation: 67 575

H.P.Wiz has golfed my approach, and the challenge no longer requires leading zeroes so you may be able to golf it more? – ASCII-only – 2018-06-08T00:44:50.340

@ASCII-only Perhaps, but not sure how. @Emigna has already golfed T%N°*+ to θì for me, and the leading zero 'fix' was just a nice bonus with this approach. – Kevin Cruijssen – 2018-06-08T06:51:00.447

4

Java (JDK 10), 106 bytes

n->n.valueOf(3).modPow(n.valueOf(2).multiply(n=n.TEN.pow(n.intValue())).divide(n.valueOf(3)).add(n.ONE),n)

Try it online!

Credits

Olivier Grégoire

Posted 2018-06-07T10:24:54.223

Reputation: 10 647

1166 bytes by changing the loop to for(int l=0,d;++l<=n; and changing BigInteger I=null; to var I=new BigInteger("3"); which we can re-use. – Kevin Cruijssen – 2018-06-07T11:47:07.067

11 more byte to save by changing the loop to for(int l=0,d;l++<n;). – Kevin Cruijssen – 2018-06-07T12:11:31.850

4

Java 8, 158 156 141 136 135 bytes

n->{var t=n.valueOf(3);var r=n.ONE;for(int i=0;i++<n.intValue();)r=r.add(t.subtract(r.pow(3)).multiply(t).mod(n.TEN.pow(i)));return r;}

Port of @ASCII-only's Python 2 (PyPy) answer.
-2 bytes thanks to @Neil.
-20 bytes thanks to @ASCII-only.

NOTE: There is already a much shorter Java answer by @OlivierGrégoire using an algorithmic approach utilizing modPow.

Try it online.

Explanation:

n->{                            // Method with BigInteger as both parameter and return-type
  var t=n.valueOf(3);           //  Temp BigInteger with value 3
  var r=n.ONE;                  //  Result-BigInteger, starting at 1
  for(int i=0;i++<n.intValue();)//  Loop `i` in the range [1, n]
    r=r.add(                    //   Add to the result-BigDecimal:
       t.subtract(r.pow(3))     //    `t` subtracted with `r` to the power 3
       .multiply(t)             //    Multiplied by 3
       .mod(n.TEN.pow(i)));     //    Modulo by 10 to the power `i`
  return r;}                    //  Return the result-BigInteger

Kevin Cruijssen

Posted 2018-06-07T10:24:54.223

Reputation: 67 575

Oh, you used that algorithm too? I'll rollback my answer and add you changes ;) – Olivier Grégoire – 2018-06-07T11:53:32.773

java.math.BigInteger u=null,r=u.valueOf(7),t=r;? – Neil – 2018-06-07T12:20:22.800

@Neil Of course.. thanks. I had java.math.BigInteger t=null,r=u.valueOf(7);t=r; initially before I added the u to save some bytes. – Kevin Cruijssen – 2018-06-07T12:23:45.110

I saved some bytes on ASCII-only's answer – H.PWiz – 2018-06-07T20:21:36.983

@H.PWiz one less variable :P

– ASCII-only – 2018-06-08T00:16:51.700

144 – ASCII-only – 2018-06-08T00:18:17.660

I think some bytes could be saved by taking a BigInteger as an argument but IDK if that's acceptable – ASCII-only – 2018-06-08T00:20:27.663

1141? – ASCII-only – 2018-06-08T00:25:13.183

@ASCII-only Thanks. Your 141 answer outputs the last n-1 digits though, instead of n. But that was an easy fix. :) – Kevin Cruijssen – 2018-06-08T07:00:08.950

@ASCII-only taking a BigInteger is acceptable if it's a useful parameter. In this case, you may take n as a BigInteger if that's better for you. Just don't keep n an int and pass a null to the method, just to have access to BigInteger without declaring it. – Olivier Grégoire – 2018-06-08T08:17:09.893

In that case, 136

– ASCII-only – 2018-06-08T08:47:07.713

1*modpow, not modpod :P – ASCII-only – 2018-06-08T09:32:30.800

@ASCII-only Woops.. xD – Kevin Cruijssen – 2018-06-08T09:40:40.543

2

dc, 15

3?Ar^d2*3/1+r|p

Uses modular exponentiation, like @xnor's answer.

Try it online!

TIO calculates input=1000 in 21s.

Digital Trauma

Posted 2018-06-07T10:24:54.223

Reputation: 64 644

2

Pyth, 12

.^3h/y^TQ3^T

Try it online!

Again, using modular exponentiation, like @xnor's answer.

Digital Trauma

Posted 2018-06-07T10:24:54.223

Reputation: 64 644

2

Haskell, 37 bytes

1 byte saved thanks to ASCII-only!

(10!1!!)
n!x=x:(n*10)!mod(9-3*x^3+x)n

Try it online!

I use a similar approach to ASCII-only, but I avoid using division

H.PWiz

Posted 2018-06-07T10:24:54.223

Reputation: 10 962

137? – ASCII-only – 2018-06-07T23:59:36.280

1

Pyth, 23 bytes

Of course, this uses ASCII-only's approach.

K7em=+K*%*7/^K3J^TdTJtU

Try it here!

Mr. Xcoder

Posted 2018-06-07T10:24:54.223

Reputation: 39 774

1@DigitalTrauma Oh >_< I swear I haven't noticed your answer lol... I first had a port of ASCII's solution, then I saw xnor's and I ported it directly to golf it :P I guess I will rollback to the initial revision, though. – Mr. Xcoder – 2018-06-08T07:43:31.450

1

Charcoal, 26 22 bytes

≔⁷ηFN≧⁺﹪׳⁻³Xη³Xχ⊕ιηIη

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

≔⁷η

Initialise the result to 7. (Doesn't have to be 7, but 0 doesn't work.)

FN

Loop over the number of required digits.

        η       Current result.
       X ³     Take the cube. 
     ⁻³         Subtract from 3.
   ׳           Multiply by 3.
            ⊕ι  Increment the loop index.
          Xχ    Get that power of 10.
  ﹪             Modulo
≧⁺            η Add to the result.

Now uses @H.P.Wiz's approach to save 4 bytes.

Iη

Print the result.

Here's a 28-byte brute-force version that takes cube roots of arbitrary values:

FN⊞υ⊟Φχ¬﹪⁻XI⁺κ⭆⮌υμ³IηXχ⊕ι↓Iυ

Try it online! Link is to verbose version of code. First input is number of digits, second is value to root.

Neil

Posted 2018-06-07T10:24:54.223

Reputation: 95 035

H.P.Wiz has updated (read: golfed) my approach. Also, stringmap shouldn't be needed anymore since Leaky Nun has updated the requirements. also the first link also points to the brute force version >_> – ASCII-only – 2018-06-08T00:34:32.693

@ASCII-only Thanks, I've fixed the links and ported H.P.Wiz's approach, but I needed StringMap to concatenate k with the reversed list as a base 10 number. – Neil – 2018-06-08T08:25:22.050

Hmm. I would have thought just doing it the plain number way may have been golfier. I guess not though – ASCII-only – 2018-06-08T08:44:05.957

@ASCII-only For the previous version I used Base(Reverse(u), 10) but prefixing k would have cost 4 bytes while doing it as a string only costs 2 bytes resulting in a 1-byte saving after taking the Cast into account. – Neil – 2018-06-08T09:06:43.773

1

J, 33 bytes

f=:3 :'((10x^y)|]+3*3-^&3)^:y 1x'

TIO

port of @ASCII-only's answer but using fixed modulo 10^n throughout

jayprich

Posted 2018-06-07T10:24:54.223

Reputation: 391

0

Jelly, 23 18 17 bytes

*3:×7DṪ×+⁸
R⁵*çƒ7

Try it online!

I know ƒ will be useful.

user202729

Posted 2018-06-07T10:24:54.223

Reputation: 14 620