Почему J-фраза '(2&*~) 15 7 3 1' производит таблицу, и почему эта конкретная таблица?

(2&*~) 15 7 3 1 

Выше фраза. В конце есть след и окончательный результат. Я понимаю, что эта фраза является монадой, я понимаю, что из-за ~ она имеет левый и правый аргумент. То же самое происходит, если вы запустите '15 7 3 1(2&*) 15 7 3 1'. Я также понял, что правильная таблица - это степени от 2 до 1, 3, 7, 15, а остальные записи - это их базовое число, умноженное на степень 2, но я просто не понимаю, почему.

В соответствующей заметке это фраза умножения ethopian на веб-сайте Rosetta Code (на самом деле, я тоже так далеко пытался это выяснить) и '(1>.<. @ -:) ^: а: "это фраза.

(1>.<.@-:)^:a: 27
27 13 6 3 1

но (1>.<. @ -:) ^: 27 возвращает самореализованную версию, и я ожидаю, что она будет выполняться 27 раз.

В заключительном из трех связанных вопросов (все они связаны с разложением кода умножения Этопиана), полный код дается как:

double =:  2&*
halve  =:  %&2           NB.  or the primitive  -:
odd    =:  2&|

ethiop =:  +/@(odd@] # (double~ <@#)) (1>.<.@halve)^:a:

и это может быть тривиально заменено как:

ethiop =:  +/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

И это прекрасно работает! Окрыленный успехом, я полностью упал со скалы, когда подумал, что в командной строке работает монадный двойник:

+: 98
196

И оператор double должен быть быстрее, чем оператор double с прикрепленной константой, может быть, double просто сдвигает, так что я думаю, что

ethiop =:  +/@(2&|@] # (+:~ <@#)) (1>.<.@-:)^:a:

Будет работать... но это не так.

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

Единственная хорошая вещь - то, что глагол "нечетный" не имеет ничего общего с проверкой на нечетное число.

Может кто-нибудь объяснить мне эти вещи, может быть, с английским объяснением того, как работает программа? Не как алгоритм работает, как он реализует алгоритм. Я помню, когда я играл в IBM 1130 APL в 1970 году. Это был интерпретатор APL, который работал в 8 тысячах слов, разумеется, он был ограничен. Например, у него был бросок, но не было сделки. Интерпретатор вводил и выводил из памяти память, поддерживаемую наложением 1130 кода, он разделял бы ваши подпрограммы на группы, а когда одна группа вызывала другую, он загружал новую группу с диска (да, псевдо-свопинг в 8 Кб). Поэтому я написал версии соглашения, используя различные схемы, и случайно мы натолкнулись на вариант, который можно вводить и выводить без поиска, и эту версию, независимо от того, насколько плохо написано, сколько строк и сколько действий интерпретатора будут выполняться в 10 раз быстро, как и любой другой. Я понятия не имел, что я делаю, я буду продолжать добавлять бессмысленные задания и разбивать выражения между строками или комбинировать их, пока не получу тот, который будет работать без поиска. (52 сделки 52, которые искали, могли занять 45 секунд).

А потом прошлой ночью я вычислил 150-тысячное число Фибоначчи в J. Это должна была быть 64-битная версия, и это заняло один час 17 минут. Я использовал точную арифметику, число имеет 31349 цифр, и он начинается 1012838344936638038...... И я понял, что 1130 никогда не смог бы рассчитать это, число не соответствовало бы, потому что вам нужно три из них, и самый большой из них был сделан было 32 тыс. 16-битных слов. Я хочу выучить язык, который может это сделать, но в документе чего-то не хватает, которого я просто не понимаю.

 trace '(2&*) 15 7 3 1' 
 --------------- 4 Conj -------
 2
 &
 *
 2&*
 --------------- 3 Adverb -----
 2&*
 ~
 2&*~
 --------------- 8 Paren ------
 (
 2&*~
 )
 2&*~
 --------------- 0 Monad ------
 2&*~
 15 7 3 1
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2
 ==============================
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2

Сноска Фибоначчи:

]t150k=:6!:2 'a150k =: $ ":r150k=: {:  (,+/@(_2&{.) )^:150000 (0x 1x)'
4631.62

0 60 60 #: t150k
1 17 11.6167
r150k
10128383449366380384728502706681008427227914006240871521944866167854579423510169
50198752571599303492471943589300904953648270811064370506598260395645679940891823
17307901573781852234222080308236027906733606532470814177610613237408102006595571
1949713927351702...
a150k
31349

2 ответа

Решение

Ответ задокументирован под Облигацией (&), где для диадического использования отмечена следующая идентичность:

x m & v y ↔ m & v ^: xy

В вашем примере м 2, это *и x и y являются списком из четырех чисел 15 7 3 1,

Формулировка в правой части равенства включает в себя ^:x ("к степени х"), что то же самое, что взять глагол и применить его х раз. Глагол 2&* так оно применяется пятнадцать раз. А также семь раз. А также трижды. И тоже один раз. Результаты этих четырех приложений составляют четыре строки выходных данных.

Сосредоточив внимание на третьем и используя скобки для акцента, вот что происходит.

   (2&* (2&* (2&* (15 7 3 1))))
  120 56 24 8

который так же, как

   (2&*)^:3 (15 7 3 1)
120 56 24 8

который так же, как

   (3) 2&* (15 7 3 1)
120 56 24 8

Давайте применим все неотрицательные целые числа через 3, чтобы увидеть шаблон:

   (0 1 2 3) 2&* (15 7 3 1)
 15  7  3 1
 30 14  6 2
 60 28 12 4
120 56 24 8

На этом этапе сходство с вашей исходной таблицей может сделать значение этой таблицы доступным:

   (15 7 3 1) 2&* (15 7 3 1)
491520 229376 98304 32768
  1920    896   384   128
   120     56    24     8
    30     14     6     2

Происходит то же самое, просто чаще, потому что вы дали более высокие цифры.

Это всего лишь начальный удар по вашим вопросам, так как до сих пор никто не ответил:

Наречия давно вышли из сферы применения:

(2&*~) <-> ((2&*)~)

Двоичный регистр функции, возвращаемой связью, приводится в действие:

(x m&v y) <-> ((m&v)^:x y)

2&* удваивает аргумент каждый раз, когда он применяется, так что питание 2&* умножает свой аргумент на степень 2,

(1>.<.@-:)^: 27 определяет глагол (так как ^: является соединением), но не запускает его. В оригинальной фразе foo^:a: был глагол, и 27 Аргумент. когда a: правильный аргумент ^: это просто бежит, пока не сходится.

одновалентный +: удваивает свой аргумент, но диадические случаи 2&* а также +: никак не связаны и не могут быть взаимозаменяемы. Обратите внимание, что double~ это левая сторона крючка, который всегда называется двоичным.

Единственная хорошая вещь - то, что глагол "нечетный" не имеет ничего общего с проверкой на нечетное число.

На самом деле, 2&| y является 1 если y нечетное целое число и 0 если это четное целое число, значит, это тест на нечетные числа.

Теперь, чтобы попытаться объяснить, что делает алгоритм на простом английском языке, давайте посмотрим на это по фразам, используя 12 ethiop 27 В качестве примера:

+/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

это крюк В хуках правая часть всегда является монадой, а левая часть всегда диадой.

(1 >. (<. @ -:)) ^: a:

монада (<. @ -:) знак равно floor @ half, делит пополам аргумент и округляет, а затем 1 >. (<. @ -: возвращает минимум этого и 1, ^:a: продолжает идти до сходимости и составляет список результатов. таким образом (1 >. (<. @ -:)) ^: a: 27 является 27 несколько раз вдвое, пока не достигнет 1, уступая 27 13 6 3 1

Теперь давайте посмотрим на левую половину крючка. (2&|@] # (2&*~ <@#)) является диадическим форком, аргументы которого являются левым аргументом ethiop и результат правой части вышеупомянутого крючка.

2&|@] является 1 если его правильный аргумент нечетен, 0 иначе. Для аргумента 27 13 6 3 1 результат 1 1 0 1 1

(2&*~ <@#) снова крюк <@ # применяется монадически к 27 13 6 3 1и коробки длины, возвращая (<5), Тогда мы доберемся до 2&*~, который, как мы видели, запитан в диадике, так что это (после ~ переключает аргументы) +:^:(<5) 12,

f^:m, когда m в штучной упаковке, делает f<: >m раз, принося mсписок результатов (если m пусто, и в этом случае он работает до сходимости). Так что это даст 12 * 2 ^ i.5

Тогда средняя часть вилки просто #, который с логическим левым аргументом просто фильтрует свой правый аргумент, в этом случае оставляя 12 * те степени 2, для которых 27 нечетно.

   1 1 0 1 1 # 12 24 48 96 192
12 24 96 192

в заключение +/ является sum

   +/12 24 96 192
324
Другие вопросы по тегам