 # Project Euler #1 in J

Feb 27th, 2016
614
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. NB. Project Euler #1 in J.
2.
3. +/I.+./0=3 5|"0 1 i.1e3
4.
5. NB. To break it down. J is evaluated from right to left, so the first thing that gets evaluated is...
6.
7. 1e3 NB. This is just another way of saying 1000
8.
9. NB. The verb i. gives us all the numbers from 0 up to the argument minus 1, so...
10.
11. i.1e3
12. 0 1 2 3 4 5 6 7 NB. and so on
13.
14. NB. Now it starts to get interesting. The verb | gives us the so-called "residue", the remainder on dividing a non-negative number by a positive one. So, 2 | 5 gives us 1, because 5 is divisible by 2 twice with a remainder of 1. The quotation mark is one of the many conjunctions in J. It changes the so-called rank of the verb, which describes how it applies to arguments of a different shape (atom, list, matrix, etc.) A little too complex to go into here, but ...
15.
16. 3 5|"0 1 i.1e3
17.
18. NB. means that the individual members of the list 3 and 5 are applied to each of the numbers produced by i.1e3, producing a matrix of two lists, as follows:
19.
20. 0 1 2 0 1 2 0 1 2 NB. and so on
21. 0 1 2 3 4 0 1 2 3 NB. and so on
22.
23. NB. The first list consists of the remainder of i.1e3 when divided by 3, the second the remainder when divided by 5. Now, we add ...
24.
25. 0 = 3 5|"0 1 i.1e3
26.
27. NB. This transforms our matrix such that for each entry that is equal to 0, 1 is output, otherwise 0. (J uses 0 and 1 for booleans.) Thus ...
28.
29. 1 0 0 1 0 0 1 0 0 NB. and so on
30. 1 0 0 0 0 1 0 0 0 NB. and so on
31.
32. NB. Next, we add +./, which needs a bit of explanation. +. is logical or, so 1 +. 0 is 1, 0 +. 0 is 0, 1 +. 1 is 1, and so on. However, we want to apply it to these lists, so we can use the / adverb to do so. / applies its verb between each element of a list. Our matrix is actually a list of lists, so the first argument would be the top list, and the second argument the bottom one. Something like...
33.
34. 1 0 0 1 0 0 1 0 0
35. +.
36. 1 0 0 0 0 1 0 0 0
37.
38. NB. When +. is applied between two list, it's the same as applying it to each element in the list at the same position, so it's like ...
39.
40. 1 +. 1
41. 0 +. 0
42. 0 +. 0
43. 1 +. 0
44. NB. and so on
45.
46. NB. The first row in my pseudocode above is the first element in each list, the second is the second, etc. This collapses our list down to one:
47.
48. +./0 = 3 5 |"0 1 i.1e3
49. NB. produces ...
50. 1 0 0 1 0 1 1 0 0 1 1 NB. and so on
51.
52. NB. Now we have a single list. The number 1 means that the number is divisible by 3 or 5, 0 means it's divisible by neither. Now we add the verb I. back into the mix. Given a list of numbers 0 1 0 0 1, I. returns the corresponding 0-based natural number if the list contains a 1, otherwise it returns nothing. So I. 0 1 0 0 1 returns 1 4. Applying this to our list gets the list of numbers divisible by either 3 or 5:
53.
54. I.+./0 = 3 5|"0 1 i.1e3
55. 0 3 5 6 9 10 12 15 18 20 21 NB. and so on
56.
57. NB. Now we just have to sum them, which we can do using the same / adverb we used above. +/ 2 3 5 is the same as 2 + 3 + 5, so ...
58.
59. +/I.+./0 = 3 5"0 1 i.1e3
60. 233168
RAW Paste Data