Advertisement
Revolucent

Project Euler #1 in J

Feb 27th, 2016
2,643
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
J 2.88 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement