0

I'm using the standard lua 5.4.4 distribution and interpreter, no libraries, etc.

I'm attempting to write a script to evaluate user defined values of the Collatz Conjecture (TLDR at the bottom)

I want the script to read a user input (this part works so I didn't include it) and based on that input, set a starting number (ognumber), and a range of numbers to try

then, i want it to iterate through every number between the ognumber and the range (in increments of 1) for every iteration, i want it to check if each number is odd or even, do some math with the result being "newnumber", then set number = newnumber to try the result of the previous operation.

The problem I'm facing is that when I call the function, it doesn't end. it gets stuck continuously trying the same number, it doesn't return number, and it doesn't set number = newnumber.

function isodd(number, newnumber, ResultsPath, results)
        newnumber = math.floor(number * 3 + 1)
        print(number..' x 3 + 1 = '..newnumber)
        local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
        writetoresultsfile:write('      '..number..' x 3 + 1 = '..newnumber..'\n')
        writetoresultsfile:close()
        number = math.floor(newnumber)
        return number
end

function iseven(number, newnumber, ResultsPath, results)
        newnumber = math.floor(number / 2)
        print(number..' / 2 = '..newnumber)
        local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
        writetoresultsfile:write('      '..number..' / 2 = '..newnumber..'\n')
        writetoresultsfile:close()
        number = math.floor(newnumber)
        return number
end

for number = ognumber, range, 1 do
    local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    writetoresultsfile:write('    <List name = "Attempt '..ognumber..'"> \n')
    writetoresultsfile:close()
    print('Trying '..number)
    
    while(number > 1) do
        if(number % 2 ~= 0) then
            isodd(number, newnumber, ResultsPath, results)
        else
            iseven(number, newnumber, ResultsPath, results)
        end
    end
    ognumber = ognumber + 1
    number = ognumber
end

if(ognumber == range + 1) then
    local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    resultsfile:write('  </Table>\n')
    resultsfile:write('</Data>\n')
    resultsfile:close()
end

This is what shows up when I run the script using function()

This script works, but I wanted to achieve the same thing using functions

for number = ognumber, range, 1 do
    local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    writetoresultsfile:write('    <List name = "Attempt '..ognumber..'"> \n')
    writetoresultsfile:close()
    print('Trying '..number)
    
    while(number > 1) do
        if(number % 2 ~= 0) then
            newnumber = math.floor(number * 3 + 1)
            print(number..' x 3 + 1 = '..newnumber)
            local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
            writetoresultsfile:write('      '..number..' x 3 + 1 = '..newnumber..'\n')
            writetoresultsfile:close()
            number = newnumber
        else
            newnumber = math.floor(number / 2)
            print(number..' / 2 = '..newnumber)
            local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
            writetoresultsfile:write('      '..number..' / 2 = '..newnumber..'\n')
            writetoresultsfile:close()
            number = newnumber
        end
    end
    ognumber = ognumber + 1
    number = ognumber
end

if(ognumber == range + 1) then
    local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    resultsfile:write('  </Table>\n')
    resultsfile:write('</Data>\n')
    resultsfile:close()
end

This is what it shows when I don't use function()

Edit: This Script works using the advice Shingo gave me

function isodd(number, ResultsPath, results)
        newnumber = math.floor(number * 3 + 1)
        print(number..' x 3 + 1 = '..newnumber)
        local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
        writetoresultsfile:write('      '..number..' x 3 + 1 = '..newnumber..'\n')
        writetoresultsfile:close()
        number = math.floor(newnumber)
        return number
end

function iseven(number, ResultsPath, results)
        newnumber = math.floor(number / 2)
        print(number..' / 2 = '..newnumber)
        local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
        writetoresultsfile:write('      '..number..' / 2 = '..newnumber..'\n')
        writetoresultsfile:close()
        number = math.floor(newnumber)
        return number
end

for number = ognumber, range, 1 do
    local writetoresultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    writetoresultsfile:write('    <List name = "Attempt '..ognumber..'"> \n')
    writetoresultsfile:close()
    print('Trying '..number)
    
    while(number > 1) do
        if(number % 2 ~= 0) then
            number = isodd(number, ResultsPath, results)
        else
            number = iseven(number, ResultsPath, results)
        end
    end
    ognumber = ognumber + 1
    number = ognumber
end

if(ognumber == range + 1) then
    local resultsfile = io.open(ResultsPath..'3n+1-'..results..'.xml', 'a')
    resultsfile:write('  </Table>\n')
    resultsfile:write('</Data>\n')
    resultsfile:close()
end

TLDR about the Collatz Conjecture for those interested: The Collatz Conjecture states that for any positive integer, if you apply 2 rules to it, will always return to 1.

The rules are: if the previous number is even, the next number is one half of the previous number. If the previous number is odd, the next number is 3 times the previous number plus 1

1 Answer 1

1

Although you return number from the function, it won't be updated out of the scope, you need accept it like this (same as iseven):

number = isodd(number, newnumber, ResultsPath, results)

Moreover newnumber is only used inside the function, so it's not necessary to be an argument. The function could be change to:

function isodd(number, ResultsPath, results)
    local newnumber = math.floor(number * 3 + 1)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that worked wonderfully! Just for clarification, anything that happens within a function will always be scoped locally to the function?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.