Как реорганизовать это в J?

Мое решение для новичков в Project Euler #1

+/((0=3|1+i.1000-1) +. (0=5|1+i.1000-1)) * (1+i.1000-1)

Я знаю, что это можно реорганизовать и преобразовать в функцию, я не знаю, как это сделать, и мне пришлось бы прочитать все лабораторные работы, чтобы изучить это.


person Jader Dias    schedule 12.10.2009    source источник


Ответы (2)


Нет необходимости «обрабатывать ноль», потому что добавление нуля не изменит ответ, поэтому вы можете просто использовать i. для создания списка чисел ниже 1000, например:

   i. 10
0 1 2 3 4 5 6 7 8 9

J лучше всего работает с массивами, поэтому вы должны одновременно запрашивать остаток (|) от 3 и 5, вы можете использовать ранг ("), чтобы контролировать, как аргументы передаются в остаток:

   3 5 |"0 1 i. 10
0 1 2 0 1 2 0 1 2 0
0 1 2 3 4 0 1 2 3 4

|"0 1 говорит передать левый аргумент | по одному элементу за раз, одновременно передавая правые аргументы построчно. Поскольку правый аргумент состоит только из одной строки, он повторно передается каждому из элементов левого аргумента.

Теперь мы можем сделать 0= для всего массива:

   0 = 3 5 |"0 1 i. 10
1 0 0 1 0 0 1 0 0 1
1 0 0 0 0 1 0 0 0 0

Вставьте условие ИЛИ между двумя элементами (строками) массива:

  +./ 0 = 3 5 |"0 1 i. 10
1 0 0 1 0 1 1 0 0 1

Получите индекс каждого 1 в списке/векторе:

  I. +./ 0 = 3 5 |"0 1 i. 10
0 3 5 6 9

И сумма:

 +/ I. +./ 0 = 3 5 |"0 1 i. 10

23

Вы можете довольно легко сделать это явной функцией/глаголом:

   euler1=: verb define
+/ I. +./ 0 = 3 5 |"0 1 i. y
)

Или, как только вы освоите неявное J, вы можете определить:

   euler1=: +/@I.@(+./)@(0 = 3 5 |"0 1 i.)
person Tikkanz    schedule 01.10.2011
comment
Единственное, что я хотел бы добавить к этому ясному ответу, это то, что |"0 1 можно записать как |/ (таблица модулей). Табличное наречие / может прояснить некоторые алгоритмы, в которых основная функция является скалярной (т. е. ранга 0). - person Dan Bron; 09.07.2013

  • Рефакторинг 0= (увеличит размер программы)

+/((3|1+i.1000-1)+.&(0=])5|1+i.1000-1)*1+i.1000-1

  • Рефакторинг 1+i.1000-1

+/(((3|])+.&(0=[)5|])1+i.1000-1)*1+i.1000-1

  • Повторный рефакторинг 1+i.1000-1

+/(*(3|])+.&(0=[)5|])1+i.1000-1

Единственное, что я пока не смог отрефакторить, это оператор |

person Jader Dias    schedule 12.10.2009