Home > Software design >  Lua Function stuck in a loop
Lua Function stuck in a loop

Time:11-15

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

CodePudding user response:

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)
  • Related