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\$ Commented Aug 7, 2021 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\$ Commented Aug 7, 2021 at 22:09
  • \$\begingroup\$ @hyper-neutrino Oh true. Maybe make an answer? \$\endgroup\$ Commented Aug 7, 2021 at 22:10
  • \$\begingroup\$ I will once I have some more details to contribute; I don't have time right now. \$\endgroup\$ Commented Aug 7, 2021 at 22:12
  • \$\begingroup\$ You can also put the , outside the if statement if you close it. \$\endgroup\$ Commented Aug 7, 2021 at 22:13

1 Answer 1

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\$ Commented Aug 8, 2021 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\$ Commented Aug 8, 2021 at 2:37

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.