Monday, September 2, 2013

Problem 35 & a redo of 24: A new use of J and a replacement

My last use of J was for problem 24, where the solution in J was trivial: the problem asked for the 1000000th Lexicographic permutation of the digits 0-9, and that is just a primitive feature of the language...
999999 A.i.10
done, solved in J. While this is certainly a big "bang for my buck" use of J, I felt as though I ought to use it for something fancier...mostly just because I wanted a chance to actually use J again. So, I decided to take on problem 35 - problem 35 asks for the count of circular primes below 1000000 (circular primes being numbers all of whose rotations are prime) This seemed perfect for J, as rotations of lists are also primitives (the nth rotation of list m is just n |. m). So, armed with this and a nice way of converting lists to integers and integers to lists (list to integer is 10#. ; integer to list is 10&#.^:_1), and the very nice primitive isprime function (1 p: x returns 1 if x is prime, 0 otherwise), I wrote a nice little solution: sadly not a one liner as I couldn't figure out how to make f an implicit function, but a 2 liner isn't too bad (and it runs in about 3s; I had it running in about 90 before I realized I was iterating over all integers less than 1 million when I ought to just iterate over primes)
f =: 3 : '*./ 1 p: 10#.(1 (|.&((10&#.^:_1)y))\ i.#((10&#.^:_1)y))'
+/ f"0 p:i.(p:^:_1) 1e6
Now, I have a solution to problem 35 in J, and I needed to in turn write a non-J solution to 24. I considered learning assembly for this one...but assembly language looks hard, so I decided to skip it for now and just write a nice, quick, easy solution in a familiar language that can always be swapped out later: I solved problem 24 in python.

def fac(x):
    return 1 if x < 2 else x * fac(x-1)

#p is the list of predetermined digits (in order)
#rem is the list of digits left
def NthLP(N, p, rem):
    if len(rem) == 1:
        return p + rem
    numDigits = len(p)
    k = fac(9 - numDigits)
    timesDivided = int(N / k)
    p.append(rem[timesDivided])
    rem.remove(p[-1])
    return NthLP09(N % k, p, rem)

digits = NthLP09(int(999999), [], [i for i in range(0,10)])
s = ""
for d in digits:
    s += str(d)
print s

No comments:

Post a Comment