Need Help With Coding Challenges

Introduction

So I decided to start doing coding challenges so that I could improve my coding. With this post, I decided that I could get feedback on what I did so that I could improve my scripting skills.


Coding Challenge 1 - The FizzBuzz Problem

Challenge Creator: Eos
Knowledge Required: A good understanding of for loops, and if statements.
Challenge Description: Count upwards from 1 to 100, however:

  • If the number is a multiple of 3, output Fizz instead.
  • If the number is a multiple of 5, output Buzz instead.
  • If both conditions are fulfilled, output FizzBuzz instead.

NOTE: This is a test on how cleanly you write code - I’m not looking for just any solution.

Hints:

  • You should not have to write an if statement for every test case.

My Code

local number = 0

function calculateFizzBuzz(number)
    if number/3 == math.floor(number/3) then
        print("Fizz")
    elseif number/5 == math.floor(number/5) then
        print("Buzz")
    elseif number/3 == math.floor(number/3) and number/5 == math.floor(number/5) then
        print("FizzBuzz")
    else
        print("none lol")
    end
end

for i = 1, 100 do
    number = i
    
    local ifMultiple = calculateFizzBuzz(number)
    print(ifMultiple)
end

Coding Challenge 2 - Say Bomb = Explode

Challenge Creator: BEN54OUDOU
Knowledge Required: None
Challenge Description: If you say :Bomb in the chat you explode
Hints: None

My Code

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(char)
		player.Chatted:Connect(function(message)
			if string.sub(message, 0, 1) == ":" then
				message:lower()
				if message:find("bomb") then
					local explosion = Instance.new("Explosion")
					explosion.Position = char.PrimaryPart.Position
					explosion.Parent = char.PrimaryPart
					explosion = nil
				end
			end
		end)
	end)
end)
1 Like

You can check if a number is divisible by another number by using:

if number % x == 0 then

Replace x with 3 and 5. The % operator is called the modulo operator, and it’s used to get the remainder of 2 numbers.

In FizzBuzz, if a number isn’t divisible by 3 or 5 then you’re supposed to print the number.

For the command one, a better way to check commands would be:

local prefix = ':'

game.Players.PlayerAdded:Connect(function(player)
    local character = player.Character or player.CharacterAdded:Wait()
    player.Chatted:Connect(function(msg)
        local lowered = string.lower(msg)
        local args = lowered:split(' ')
        if string.sub(args[1], 1,1) == prefix then
        local command = string.sub(args[1], 2)
            if command == 'bomb' then
                --bomb code
            end
        end
    end)
end)

This way, it’s easier to add more commands in the future, but that’s just my preference.

1 Like

I notice in the 2nd Challenge, you missed setting the message to message:lower(), it should be:
message = message:lower()

1 Like

You’re looking for cleaner code? Ok!

1. FizzBuzz

Here’s your starting code:

local number = 0

function calculateFizzBuzz(number)
    if number/3 == math.floor(number/3) then
        print("Fizz")
    elseif number/5 == math.floor(number/5) then
        print("Buzz")
    elseif number/3 == math.floor(number/3) and number/5 == math.floor(number/5) then
        print("FizzBuzz")
    else
        print("none lol")
    end
end

for i = 1, 100 do
    number = i
    
    local ifMultiple = calculateFizzBuzz(number)
    print(ifMultiple)
end

First, let’s take a look at your calculateFizzBuzz function.
First note on that, the way you’re checking divisibility works, but there’s a much more concise way to do it. The modulo operator (%) gets the remainder of a number divided by another number. For instance, 3 % 2 evaluates to 1. This is the way most people check divisibility. Obviously, whether to change or not is a matter of personal preference, but I find it more readable to use the modulo.
Second, according to your hint, you shouldn’t have to use an if statement for every condition. Since it’s not too many conditions, it really doesnt matter, but since the hint says to eliminate if statements, we’ll do that. We can use string concatenation, then, to get rid of the if that compares both conditions at the same time.
The resulting function is here:

local calculateFizzBuzz(number)
    local result = ""

    if number % 3 == 0 then
        result ..= "Fizz"
    end

    if number % 5 == 0 then
        result ..= "Buzz"
    end

    return
        if result == "" then number -- Yes, you can do this!
        else result
end

Then, let’s take a look at your loop. You’ve got a lot of unnecessary things there. You really just need the following:

for i = 1, 100 do
    print( calculateFizzBuzz(i) )
end

The whole resulting code then looks like this:

local calculateFizzBuzz(number)
    local result = ""

    if number % 3 == 0 then
        result ..= "Fizz"
    end

    if number % 5 == 0 then
        result ..= "Buzz"
    end

    return
        if result == "" then number -- Yes, you can do this!
        else result
end

for i = 1, 100 do
    print( calculateFizzBuzz(i) )
end

Note that that’s just an example of what it might look like. This isn’t the correct answer — there is no one correct answer. Admittedly, it’s a tad stylized to how I personally would complete the challenge.

2. :bomb

@zCrxtix , in his reply, made a whole command parsing system. If you intended on making more commands in the future with this, that’d be great! However, the challenge just calls for :bomb. Nothing else. So, we’re going to follow the “You Ain’t Gonna Need It” principle and just check for :bomb.

Note that you’re adding a new .Chatted event every single time the character respawns. We really just need one of those.
Secondly, you’ve got a heck of a way to check if the message says “:bomb”… Since that’s all we’re looking for, why not just string.lower(message) == ":bomb"? More concise, makes it clear exactly what you’re going for.
Third, I personally would like to separate out the explosion creation into a new function. Separating each bit out into its own function makes it easier to follow the separation of concerns principle later on down the line when you build onto your code, but since it’s just a small challenge, it’s really just a matter of personal preference. Here’s the resulting code (I’ve made a few more changes than the ones listed above, but the ones listed above are probably the most important):

local Players = game:GetService("Players")

local function explodeCharacter(character)
    local explosion = Instance.new("Explosion")
    explosion.Position = character.HumanoidRootPart.Position
    explosion.Parent = workspace
end

Players.PlayerAdded:Connect(function(player)
    player.Chatted:Connect(function(message)
        if string.lower(message) ~= ":bomb" then return end -- This is called a guard clause, where instead of wrapping code in a conditional, you exit the function early if the condition isn't met. Helps avoid annoying, complex nesting.
        if not player.Character then return end

        explodeCharacter(player.Character)
    end)
end)
2 Likes

Use modulo to determine weather a number is divisible by something, if it equals 0 then it is. ex. 15 % 5 comes up to 0 do it is divisible by 5. 16 % 5 comes up to 1 so you know its not divisible by 5.