
FizzBuzz in J, Explained - wyc
https://wycd.net/posts/2017-01-19-fizz-buzz-and-triangles-in-j.html
======
RodgerTheGreat
Paraphrasing an earlier Reddit post, here's how it might look in K3.

Generate a range of numbers up to 20 (for brevity), inclusive:

    
    
          1+!20
        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
    

Apply a function ({x!/:3 5}), which takes an element modulo 3 and 5, to the
range:

    
    
          {x!/:3 5}1+!20
        (1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2
         1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0)
    

Taking the negation (~) shows us the places the elements divide evenly:

    
    
          {~x!/:3 5}1+!20
        (0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0
         0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1)
    

Convert these into base-2 indices:

    
    
          {2 _sv~x!/:3 5}1+!20
        0 0 2 0 1 2 0 0 2 1 0 2 0 0 3 0 0 2 0 1
    

We can then use those indices to select from a list. Note the addition of a
map ('), because if we continue performing all these operations in parallel we
won't have access to x as some particular item of the list:

    
    
          {(x;"Buzz";"Fizz";"FizzBuzz")2 _sv~x!/:3 5}'1+!20
        (1;2;"Fizz";4;"Buzz";"Fizz";7;8;"Fizz";"Buzz";11;"Fizz";13;14;"FizzBuzz";16;17;"Fizz";19;"Buzz")

~~~
Avshalom
To translate that as literally as possible into Dyalog

    
    
      fizzbuzz ← {
        {(⍵ 'buzz' 'fizz' 'fizzbuzz')[1+2⊥0=3 5∘.|⍵]}¨⍵
      }
    

called as

    
    
      fizzbuzz ⍳100
    

or just

    
    
      {(⍵ 'buzz' 'fizz' 'fizzbuzz')[1+2⊥0=3 5∘.|⍵]}¨⍳100
    

with unnecessary parens

    
    
      {(⍵ 'buzz' 'fizz' 'fizzbuzz')[1+(2⊥(0=((3 5)∘.|⍵)))]}¨⍳100

~~~
jxy
Since you are using ¨, ⍵ is a scalar, so you don't need the ∘.

Translated back to J

    
    
      ((;'Buzz';'Fizz';'FizzBuzz'"_){~2#.0=3 5|])"0>:i.100
    

The boxed list in J feels a bit cumbersome compared to mixed arrays in APL.

~~~
Avshalom
Fair enough. Like most APL I wrote it backwards until it worked.

------
bithive123
"Doesn’t it make sense that in mathematics, we use the integral symbol instead
of A.Integral(B)?"

In my experience the obscure notation is what made college math hard for me to
learn. As a programmer I really wish there was a math textbook that used
A.Integral(B) type notation to teach concepts, because I think I could have
been good at math.

I realize that people who start with math have the opposite experience; my
physicist friend complains that whenever he has to use a CLI or write code
everything seems arbitrary and confusing to him.

~~~
ninkendo
Agreed. And to me it's not just the math notation that bugs me, but the
tendency of mathematicians (and perhaps by extension, physicists) to _always_
use one-letter variables.

In software development, you'd get torn apart in code review if your variables
are all one letter long. Why is math so terse?

~~~
imh
I think it's pattern matching and intuition. If I see y = k/x, I can
immediately process what that looks like. Further, I can take advantage of
tons of conventions that make it read differently from a = b/c or even y =
z/x. The conventions take some getting used to, but after a while writing out
dependentVariable = divideBy(constant, independentVariable) would get super
tedious and it's absolutely not instantly pattern matchable. Especially when
you're working out some manipulation where you have to write the same variable
a zillion times, and maybe even depending on your brain's pattern matching and
inspiration to kick in. Hell, at this point I even use a shorthand for cos and
sin for those reasons.

------
bloaf
I have had several opportunities to write Mathematica code in a style similar
to this. Specifically, building up functions to map over entire lists rather
than iterating over them.

Each step feels very intuitive and satisfying. But when you just look at the
end result of any non-trivial example, it nearly always looks unreadable. I
found myself needing to work quite hard to understand functions I myself had
written, even if I was only interrupted by lunch.

------
101km

      > 1{::(('FizzBuzz';'Fizz';'Buzz';":) 1337)
    
      Fizz
    

Is equivalent to:

    
    
      > ['FizzBuzz', 'Fizz', 'Buzz', 1337][1]
    
      Fizz
    

In a language with less foreign syntax. You can make it more familiar by
putting the index on the right side of the array with '~':

    
    
      (('FizzBuzz';'Fizz';'Buzz';":) 1337){::~1
    
      Fizz
    

This is the modulo bit:

    
    
      (0 i.~15 3 5|])

~~~
caioariede
I think comparing it with other languages may make it easier to grasp.
Sometimes it's good to test it in a language you are used to. The selector
expression could be represented in Python like this:

    
    
      a = lambda n: [n % x for x in [15, 3, 5]].index(0)

~~~
101km
Yep, I started writing this out (first in js, but it doesn't map well, python
list comprehensions do) but you beat me to it. :)

Now great, you can get the weird syntax and unroll it if you squint. Why is it
written like this? Isn't it wasteful to test against all three cases (15,3,5)
instead of returning early?

Probably has something to do with 'thinking in arrays' and how its a cheap
comparison and that there's probably matrix multiplication or bit twiddling
going on under there. That's the interesting bit to me.

To get the feel for an array language. This fizzbuzz example is actually
surprisingly interesting because of that.

~~~
caioariede
In fact, it's still not the same. In Python, the following expression will
raise a ValueError.

    
    
      > a(2)
    

In J, it will return the length of the array, as stated in the post.

------
empath75
'explained' I read it twice and still don't understand what it's doing.

~~~
wyc
Author here. Sorry to hear that. If you want to let me know where I lost you
via email or here, I'd be happy to revise it to be clearer.

I think it takes a certain skill to overcome the curse of already knowing
something and then explaining it, and I'll definitely have some blind spots.

Thanks for reading it twice!

~~~
acqq
Consider that on HN there are surely people who read about J the first time,
or if they have read something somewhere, they already forgot it and they
won't go through the whole tutorial (which is not small) before reading the
article.

For example, I guess that the

FB"0 >:i.100

is a kind-of for loop, even if I also guess it's not called as such in J, but
I wouldn't be able to explain how it exactly works, except that >: is bigger
or equal, which I glimpsed from some first page of the tutorial, and i. should
mean index of, according to your text? But searching 100 in what? Or is it
some new word?

Then, why was 1337 introduced in the explanation at all? I failed to
understand, reading the text not too slowly.

Thanks for posting the article here, it's refreshing.

~~~
Avshalom
FB"0 basically means apply FB to each cell in an array. i.100 makes an array
of numbers 0...99 and >: increments every number in that array by 1

So it's mapping FB over the numbers 1 to 100.

Now I don't know j very well so I don't know why this evaluates as (FB"0)
(>:i.100) instead of (FB") (0>:i.100) but I guess " is special

1337 is just a stand in number. To try the algorithm without mapping it to an
array.

So the algorithm is this make an array of [fizzbuzz fizz buzz x]. Then make an
array of x mod 15, 3, 5. Find the first instance of 0 in that second array and
use that index to select fizz,buzz etc. If there isn't a zero (0 i.
secondarray) returns the length of secondarray which is 3, the same index as x
in the first array.

~~~
acqq
Thanks! So I made more than one bad guess. So >: can be monadic, increment and
dyadic, bigger or equal. And i. can be a generator or an index of.

But how to avoid reading the wrong meaning? If I'm reading right to left, I
read 100, then I see i. then see something on the left of i. then why is it
not a dyadic i. ? Because there is no parenthesis?

~~~
klibertp
> But how to avoid reading the wrong meaning?

The only thing other than "practice" you can do is to use built-in J
expression pretty-printer. It shows you a graph of an expression, grouping
verbs with their arguments. I don't remember how to get to it exactly, I think
it was somewhere in foreigns.

EDIT: it's even mentioned in the article, don't know how I missed it: 5!:4

~~~
acqq
Thanks. I've seen it but now that you mentioned I really liked to also
understand what that means semantically:

5!:4 <'FB'

I see here:

[http://www.jsoftware.com/help/dictionary/dx005.htm](http://www.jsoftware.com/help/dictionary/dx005.htm)

That every combination of two numbers means something special.

[http://www.jsoftware.com/help/dictionary/dx018.htm](http://www.jsoftware.com/help/dictionary/dx018.htm)

Wow.

------
klibertp
There's a blog post about FizzBuzzBazz (note the third value) in LiveScript, I
posted a comment there, with J version[1], looking like this:

    
    
        fu=:(3&|),(5&|),:(7&|)
        g1=:(,&'zz')"1>;:'Fi Bu Ba'
        ((0=fu i.101){"1(3 1$<''),.(,.<"1 g1)),<"0 i.101
    

Well, what else can I say? J is really fun to play with.

It's also not true that it cannot be maintainable or readable. J crazy parsing
rules and other language features make it very flexible, on the level of Lisp,
TCL, PERL, Smalltalk or Io. This means it can be a completely unreadable mess,
as well as a readable and maintainable code, depending on who writes it. I
made an attempt at writing readable - articulate - J:
[https://klibert.pl/posts/literate_j.html](https://klibert.pl/posts/literate_j.html)

[1]
[http://livescript.net/blog/fizzbuzzbazz.html#comment-1145818...](http://livescript.net/blog/fizzbuzzbazz.html#comment-1145818066)

~~~
kazinator
That cryptic code, ironically, doesn't appear significantly shorter, if at
all, than the FizzBuzz solutions in some ordinary, readable languages. What's
the point?

------
throwaway7645
I really like the concepts in APL/J. It's probably why I'm so excited to see
more array oriented support in Perl6. Keep up the postings.

~~~
protomyth
If you enjoy APL/J then you might want to check out F-Script on OS X. It was
pretty fun for combining arrays with Smalltalk like syntax and might provide
you with some amusement.

------
bkase
I found your post very compelling. I have tried messing around with the APL
derivatives (J and K and Q), but never created anything substantial. I didn't
know you could view the AST like that, and it did really help in your
explanation. I'm definitely going to check out an APL again! Thank you for the
great post!

------
taeric
I tried my hand at a terse fizz buzz, once.
[https://twitter.com/taeric/status/250060748548624385](https://twitter.com/taeric/status/250060748548624385)

Not really hard to come up with, but does take effort. Would be difficult to
go through that for all programs.

------
alimw
It's been a while since I used J, but as I recall it's more idiomatic (though
sometimes trickier) to write a function that works directly with arrays than
to write a function that works with scalars and then to map it over an array.

------
johnvaluk
If the string 'FizzBuzz' appears in your code, you have failed FizzBuzz.

~~~
taeric
How do you mean?

~~~
Spivak
Typically, because there is (usually, not always) a more elegant solution when
one recognizes 15 = 5 × 3 so you can avoid the need for a separate case to
handle divisibility by 15.

~~~
taeric
Ah, I misread that to be either fizz or buzz.

------
chx
:('Equilateral';'Isoceles';'Irregular';'Impossible'){::~3&,@<:@#@~.{~2&*@(>./)<+/

Belongs in [https://www.stilldrinking.org/programming-
sucks](https://www.stilldrinking.org/programming-sucks)

In other words: I would not want to work with a language like this because I
know most of the work is maintenance and it's hell if you need to work with
something this sigil heavy.

~~~
klibertp
What you say is true for most languages, however, it's different for J. The
sigils you see _are_ the _whole_ language - there are only around 20 sigils,
which are the core functions of the language. You only need to learn and
remember them, you can then work your way through any kind of J code. It may
go slowly at the beginning, but as you get used to the most often occurring
ways of composing them you get faster.

In other words: you can't really say anything about how it feels to work with
J without working with it for some time. This may be true to some extent with
other languages, but J is unique/different enough to make this point
especially true.

~~~
chx
There are a billion things against a sigil only language: it's near impossible
to give you a helpful IDE (in a word-like language you can use autocomplete
but how do you give ideas whether the user should use @ or ^ at a given
point?), it's near impossible to search for code examples and such (the other
day I was looking for code in any language at all that uses /PZ/u as a regular
expression without success), you need to think twice before using any of the
standard shell utilities on them and so on.

~~~
avmich
> it's near impossible to give you a helpful IDE (in a word-like language you
> can use autocomplete

What autocomplete you need in J? For verbs and conjunctions which are at most
2 letters long?

> how do you give ideas whether the user should use @ or ^ at a given point?

In the same way as IDE helps you to choose . or exp() ? They are completely
different concepts, how can you mix them?

> it's near impossible to search for code examples and such

I think it's a common problem for complex code examples, in any language. You
may, though, search for comments.

From
[http://www.jsoftware.com/help/jforc/foreword.htm#_Toc1917342...](http://www.jsoftware.com/help/jforc/foreword.htm#_Toc191734286)
:

> C is a computer language; it lets you control the things the computer does.
> J is a language of computation: it lets you describe what needs to be done
> without getting bogged down in details

I think it's a great help. J doesn't just reduces typing; it also reduces the
amount of things one needs to keep in the head to solve the problem.

