4
\$\begingroup\$

I've created this code in the golfing language Vyxal to do FizzBuzz:

100 ( n 1 + →currentvalue
←currentvalue 15 % 0 = [
  `FizzBuzz`,
  | ←currentvalue 5 % 0 = [
    `Buzz`,
    | ←currentvalue 3 % 0 = [
      `Fizz`,
      | ←currentvalue ,

Try it Online!

We loop 100 times. n is the 0-indexed iteration number, but we want the 1-indexed iteration number, so we add 1 and store it to the variable currentvalue. Then, we check if this is divisible by 15, 5, or 3 and print the corresponding text, otherwise printing currentvalue.

This is mostly equivalent to the following pseudocode:

100 times
  currentvalue = iterationnumber + 1
  if currentvalue % 15 == 0
    print 'FizzBuzz'
  else if currentvalue % 5 == 0
    print 'Buzz'
  else if currentvalue % 3 == 0
    print 'Fizz'
  else
    print currentvalue

I'm a bit dissatisfied with the need for three nested conditionals, and I feel like the code would be nicer if I didn't have to use the currentvalue variable.

I'm looking for tips on making this more readable and idiomatic, not shorter, unless it helps with the other two points.

Thanks for helping!

\$\endgroup\$
6
  • \$\begingroup\$ This is a comment because I don't have much to say, but I'd recommend closing your loops and other structures. It's like having a Java class where you write class Foo { public void bar() {. without any }} at the end. \$\endgroup\$
    – ruse
    Aug 7 at 22:09
  • \$\begingroup\$ Well, for one, you don't need to use a variable if you just duplicate your value three times before the first [ block. \$\endgroup\$ Aug 7 at 22:09
  • \$\begingroup\$ @hyper-neutrino Oh true. Maybe make an answer? \$\endgroup\$
    – emanresu A
    Aug 7 at 22:10
  • \$\begingroup\$ I will once I have some more details to contribute; I don't have time right now. \$\endgroup\$ Aug 7 at 22:12
  • \$\begingroup\$ You can also put the , outside the if statement if you close it. \$\endgroup\$
    – ruse
    Aug 7 at 22:13
4
\$\begingroup\$

Firstly, it doesn't really make sense to push 100, run a ( block, and then do n 1 + when you could instead just use ɾ to get the range 1, 2, ..., 100: 100 ɾ (. Now, you are looping from 1 to 100, which makes a lot more sense. In fact, in the comments, I mentioned how by duplicating the computed currentvalue thrice, you could just pop off the stack instead of using ←currentvalue, but this way, n will be the correct value (or you could save it in the for loop using (x|...).

Also, as pointed out by exedraj/lyxal (the creator of this language), it is better to use a map lambda as this creates the list and lets you manipulate it later, rather than just outputting within the for loop.

Thus, we can do this:

100 ɾ ƛ
    n 15 % 0 = [
        `FizzBuzz` |
        n 3 % 0 = [
            `Fizz` |
            n 5 % 0 = [
                `Buzz` |
                n
    ]]]
; ⁋

(Also, just stylistically, I like to put the %3 first and %5 second because it's called FizzBuzz after all, not BuzzFizz. Though this doesn't matter. Also, you should close your structures if you want it to be more idiomatic and readable rather than golfed.)

Then, IMO it actually makes more sense to nest the %3 and %5 checks within each other rather than using %15 - this makes it clearer that FizzBuzz is output when it is divisible by both (which is equivalent to being divisible by 15 (or generally the LCM) here but this is more explicit).

Also, there's a built-in for checking divisibility. I don't think % 0 = is actually any better. It's probably more readable for someone who doesn't know what Vyxal's built-ins are, but idiomatically, you should be using instead.

100 ɾ ƛ
    n 3 Ḋ [
        n 5 Ḋ [ `FizzBuzz` | `Fizz` ] |
        n 5 Ḋ [ `Buzz` | n ]
    ]
; ⁋

(You could store n 5 Ḋ into a variable but there's honestly no point because those two expressions can't both be run, so you wouldn't actually be introducing any optimizations.)

Finally, my personal preference for the FizzBuzz problem has always been to just build a string by combining the relevant components, and if that string is empty, returning n itself. Firstly, this makes it clearer what's going on (to me), where basically you say "if it's divisible by 3, output Fizz, if it's divisible by 5, output Buzz", and thus if it's divisible by both, both Fizz and Buzz are output. Secondly, this makes it more extendable.

100 ɾ ƛ ⟨3 | 5⟩ Ḋ ⟨`Fizz` | `Buzz`⟩ * ∑ n ∨ ; ⁋

Here, we take n, check divisibility by 3 and 5 in parallel (₍₃₅ is shorter but that isn't as clear), and then replicate by ["Fizz", "Buzz"] using * and then sum the strings together. Finally, we take logical or with n in case of empty string (note that is logical OR, not a lowercase letter v). Finally, we output each line.

It's mostly up to preference which one to use, and Vyxal doesn't have an established set of best practices anyway, but the main takeaway is to use the proper looping values; if you have to alter your loop value and save to a variable, you probably should've done that outside the loop so you can just use n and have it be the proper correct value.

The other reason I like the last one is this:

2 3 5 W →factors
`Yeet` `Fizz` `Buzz` W →strings

100 ɾ ƛ
    n ←factors Ḋ ←strings * ∑ n ∨
; ⁋

Try It Online!

It's easy to extend.

( means "join on newline"; you can also use ¶ j or `\n` j for more clarity. Or, of course, just use the j flag.)

\$\endgroup\$
2
  • \$\begingroup\$ Just two little things I'd add: a) (dyadic maximum) can be used in place of in this case and b) wrapping everything in ƛ and joining on newlines (using , ¶j or `\n`j) is, imo, more idiomatic - it allows implicit reuse of the context variable, and returns a list instead of printing each item on its own. \$\endgroup\$
    – lyxal
    Aug 8 at 0:40
  • \$\begingroup\$ @exedraj I know about dyadic maximum from your golfed answer on the code golf post, but is it actually better? I still feel like dyadic OR makes it clearer that it's substituting an empty string for that, whereas dyadic maximum depends on the ordering of different types and that's not immediately obvious/intuitive. I agree with using map lambda though. \$\endgroup\$ Aug 8 at 2:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.