Как я могу реализовать алгоритм группировки в J? - PullRequest
3 голосов
/ 05 марта 2012

Я пытаюсь реализовать A006751 в J. Это довольно легко сделать в Haskell, что-то вроде:

concat . map (\g -> concat [show $ length g, [g !! 0]]) . group . show

(Очевидно, это не завершено, но это основное сердцеНа это я потратил около 10 секунд, поэтому относитесь к этому соответствующим образом. Я могу довольно легко реализовать все это в J, но часть, которая ускользает от меня, - это хороший идиоматический алгоритм J, который соответствует функции group в Haskell.Я могу написать неуклюжий, но это не похоже на хороший J.

Кто-нибудь может реализовать Haskell group в хорошем J?

Ответы [ 2 ]

4 голосов
/ 05 марта 2012

Группы обычно создаются с наречи /..

   1 1 2 1 </. 'abcd'
┌───┬─┐
│abd│c│
└───┴─┘

Как видите, это не последовательно. Просто сделайте так, чтобы ваш ключ был последовательным (по сути, определяя, отличается ли элемент от следующего, и делайте промежуточную сумму полученных 0 и 1):

   neq =. 13 : '0, (}. y) ~: (}: y)'
   seqkey =. 13 : '+/\neq y'
   (seqkey 1 1 2 1) </. 'abcd'
┌──┬─┬─┐
│ab│c│d│
└──┴─┴─┘

Тогда мне нужна функция, которая подсчитывает элементы (#) и сообщает мне, что они из себя представляют ({. Просто выбрать первое). Я получил вдохновение от nubcount :

   diffseqcount =. 13 : ',(seqkey y) (#,{.)/. y'
   diffseqcount 2
1 2
   diffseqcount 1 2
1 1 1 2
   diffseqcount 1 1 1 2
3 1 1 2

Если вы хотите n-й результат, просто используйте power:

   diffseqcount(^:10) 2  NB. 10th result
1 3 2 1 1 3 2 1 3 2 2 1 1 3 3 1 1 2 1 3 2 1 2 3 2 2 2 1 1 2
3 голосов
/ 06 марта 2012

Я согласен, что /. (Ключ) - это лучший общий метод применения глаголов к группам в J. Альтернативой в этом случае, когда нам нужно сгруппировать одинаковые последовательные числа, является двоичный ;. (Cut):

   1 1 0 0 1 0 1 <(;.1) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘

Мы можем сформировать лады для использования в качестве левого аргумента следующим образом:

   1 , 2 ~:/\ 3 1 1 1 2 2 3   NB. inserts ~: in the running sets of 2 numbers 
1 1 0 0 1 0 1

Соединение двух вместе:

   (] <;.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
┌─┬─────┬───┬─┐
│3│1 1 1│2 2│3│
└─┴─────┴───┴─┘

Использованиетот же механизм, что был предложен ранее:

   ,@(] (# , {.);.1~ 1 , 2 ~:/\ ]) 3 1 1 1 2 2 3
1 3 3 1 2 2 1 3

Если вы ищете красивую J-реализацию последовательности «посмотри и скажи», я бы предложил тот, что в Rosetta Code :

   las=: ,@((# , {.);.1~ 1 , 2 ~:/\ ])&.(10x&#.inv)@]^:(1+i.@[)
   5 las 1           NB. left arg is sequence length, right arg is starting number
11 21 1211 111221 312211
...