3
((1&{~+/)*./\(=1&{))1 1 1 3 2 4 1

I always get Index Error.

The point is to output two numbers, one that is the same as the first number in the list, the second which is the same as the number of times that number is repeated.

So this much works:

*./\(=1&{)1 1 1 3 2 4 1
1 1 1 0 0 0 0

I compare the first number against the rest of the list. Then I do an insertion of an and compression - and this gives me a 1 so long as I have an unbroken string of 1's, once it breaks the and fails and the zeros come forth.

I thought that I could then add another set of parens, get the lead element from the list again, and somehow record those numbers, the eventual idea would be to have another stage where I apply the inverse of the vector to the original list, and then use $: to get back for a recursive application of the same verb. Sort of like the quicksort example, which I thought I sort of understood, but I guess I don't.

But I can't even get close. I will ask this as a separate question so that people get proper credit for answering.

Nick
  • 199
  • 6

4 Answers4

2

Were you looking for something like this?

f=.{.,+/@:({. E. ])

NB.f 1 1 1 3 2 4 1
NB.1 4
NMR
  • 21
  • 3
0

Part 1

There's the built in verb {. to get the first item from an array, so the first part's done.

Part 2

For the second part, we can combine this with e. which, if given a vector, returns a table showing where the elements occur:

   e. 1 3 1 1
1 0 1 1
0 1 0 0
1 0 1 1
1 0 1 1

Use the first row (or column!):

   {.e. 1 3 1 1
1 0 1 1

Sum this result:

   +/{.e. 1 3 1 1
3

Combine

Combining parts 1 and 2 into a 2-element list is achieved with dyadic , (append):

(result of {.) , (result of sum of first row (or column!) of e.)

I always cheat and use the explicit-to-tacit converter (13 :)for things like this:

   13 : '({.y) , +/{. e.y'
{. , [: +/ [: {. e.

But at this point you may notice that this is a bit heavy-handed with the [: (cap) and NMR's answer is cleaner.

Bonus for reading this far

If you return a boxed array (by using ; instead of ,), you can extend this function to lists of things other than numbers:

   f =: 13 : '({.y) ; +/{. e.y'
   f  'abracadabra'
┌─┬─┐
│a│5│
└─┴─┘
Community
  • 1
  • 1
Alex Shroyer
  • 3,499
  • 2
  • 28
  • 54
0

J is 0 indexed, so you want to try this instead:

((0&{~+/)*./\(=0&{))1 1 1 3 2 4 1
MPelletier
  • 16,256
  • 15
  • 86
  • 137
  • Or work something out with `{.` I'm not super with tacit expressions so I can't get it to work right, sorry. – MPelletier Sep 15 '11 at 21:57
  • That was stupid of me, wasn't it....but there should have been a number at index 1 that I could have compared to and gotten the wrong result... All I can say is that yesterday I was playing with NARS2000, which is a version of old style APL that is free but it uses 1 origin indexing. Well, now I can continue experimenting. – Nick Sep 16 '11 at 02:27
0
   (0&{ , +/@(*./\)@(= 0&{)) 1 1 1 3 2 4 1
1 3

I'm not quite sure from your question whether that is the initial result that you were trying for?

This might be a simpler way of getting the number of times the first element is repeated.

   =/\ 1 1 1 3 2 4 1
1 1 1 0 0 0 0

I get the impression that you are wanting to end up with something similar to the following? (which gives the count of the consecutive repeats in the list)

  ([: #/.~ 0 , [: +/\ 2 ~:/\ ]) 1 1 1 3 2 2 4 1
3 1 2 1 1
Tikkanz
  • 2,398
  • 15
  • 21