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

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

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

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

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

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

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

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

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

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

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

+: 98
196

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

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

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

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

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

Может кто-нибудь объяснить мне эти вещи, может быть, с английским объяснением того, как работает программа? Не то, как работает алгоритм, как он реализует алгоритм. Я помню, когда я играл в 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 ]

5 голосов
/ 17 октября 2011

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

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

В вашем примере m равно 2, v равно *, а 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 голосов
/ 19 сентября 2011

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

Наречия давно покинули область видимости:

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

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

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

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

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

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

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

На самом деле, 2&| y - это 1, если y - нечетное целое число, и 0, если это четное целое число, поэтому это тест на нечетные числа.

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

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

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

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

Monad (<. @ -:) = 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&*~ <@#) снова крюк. <@ # применяется монадически к <code>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

Наконец +/ is sum

   +/12 24 96 192
324
...