Omnimaga

Calculator Community => TI Calculators => Lua => Topic started by: Munchor on June 15, 2011, 09:33:10 am

Title: Lua Routines
Post by: Munchor on June 15, 2011, 09:33:10 am
It seems like there is no topic for us to group our TI-Nspire Lua routines. Feel free to post here your Lua routines, whether they are directly connected to Nspire or not. Don't forget to try and optimize other people's functions if you can.

To start, how about a function that checks if a number is prime or not? I tried to find one online but I couldn't, so I ended up making my own.

Check if a number is prime
Input:   One argument, an integer
Output: true or false, whether the argument is a prime or not

Code: [Select]
function isPrime(n)
    --[[Check if an integer n is a prime or not--]]
    if n==1 then return false end --1 is not a prime
    for i = 2, math.sqrt(n) do
    if n % i == 0 then
    return false
    end
    end
    return true
end
Title: Re: Lua Routines
Post by: Jim Bauwens on June 15, 2011, 10:12:13 am
My version:
Code: [Select]
function isPrime(n)
    return math.eval("isprime("..n..")")
end

I don't know if its faster though.
Title: Re: Lua Routines
Post by: pianoman on June 15, 2011, 06:30:46 pm
Code: [Select]
function isPrime(n)
    --[[Check if an integer n is a prime or not--]]
    if n==1 then return false end --1 is not a prime
    for i = 2, math.sqrt(n) do
    if n % i == 0 then
    return false
    end
    end
    return true
end
What exactly does the math.sqrt do?
Title: Re: Lua Routines
Post by: AngelFish on June 15, 2011, 06:37:43 pm
It limits the number of times the loop will check, since one of the factors of any number n is at most sqrt(n).

That said, the routine given will take a loooong time for large primes.
Title: Re: Lua Routines
Post by: pianoman on June 15, 2011, 06:50:30 pm
What happens if the square root is irrational?
Title: Re: Lua Routines
Post by: AngelFish on June 15, 2011, 07:08:12 pm
It doesn't compute the actual square root, only an approximation to it. That means that the interpreter will always see a rational number, whether or not the true square root actually is rational.
Title: Re: Lua Routines
Post by: pianoman on June 15, 2011, 07:08:40 pm
Oh, got it. Thanks!
Title: Re: Lua Routines
Post by: Munchor on June 20, 2011, 05:06:40 am
Draw a triangle
Input:   Graphics Context, x, y, length of side
Result:  Draws a triangle at (x,y) in the screen with each side having length of l

Code: [Select]
function drawTriangle(gc,x,y,l)
    gc:drawLine(x,y,x+l,y)
    gc:drawLine(x, y, x+(l/2), y-(l*0.5))
    gc:drawLine(x+(l/2), y-(l*0.5), x+l, y)
end

All the sides of the triangle are of equal length and the (x,y) coordinates are of the left point of the triangle.

Now, I know this is not very hard math (simple trigonometry) but I think it might be useful for someone :) Any optimizations?

Here's how it works:

(http://img.removedfromgame.com/imgs/drawTriangle.png)
Title: Re: Lua Routines
Post by: Ashbad on June 21, 2011, 09:46:47 pm
Pause for an exact amount of time, in milliseconds

Code: [Select]
WaitMS = function(milliseconds)
   while (stime = math.abs(timer.GetMilliSecCounter()+milliseconds))<
            math.abs(timer.getMilliSecCounter()) do end
   return true
end
Title: Re: Lua Routines
Post by: calc84maniac on June 21, 2011, 11:26:31 pm
Draw a triangle
Input:   Graphics Context, x, y, length of side
Result:  Draws a triangle at (x,y) in the screen with each side having length of l

Code: [Select]
function drawTriangle(gc,x,y,l)
    gc:drawLine(x,y,x+l,y)
    gc:drawLine(x, y, x+(l/2), y-(l*0.5))
    gc:drawLine(x+(l/2), y-(l*0.5), x+l, y)
end

All the sides of the triangle are of equal length and the (x,y) coordinates are of the left point of the triangle.

Now, I know this is not very hard math (simple trigonometry) but I think it might be useful for someone :) Any optimizations?

Here's how it works:

(http://img.removedfromgame.com/imgs/drawTriangle.png)
If that's really an equilateral triangle, shouldn't the square root of 3 be involved somehow?
Title: Re: Lua Routines
Post by: Jim Bauwens on June 22, 2011, 02:59:33 am
Pause for an exact amount of time, in milliseconds

Code: [Select]
WaitMS = function(milliseconds)
   while (stime = math.abs(timer.GetMilliSecCounter()+milliseconds))<
            math.abs(timer.getMilliSecCounter()) do end
   return true
end

Wouldn't that use extremely many resources?
I would suggest to run the code in a coroutine, and call a routine that pauses it and sets the timer to the amount of seconds you want. Then when the on.timer get called it resumes the coroutine. This is the way I do it in my oncalc Lua console, and it works good (Doesn't interrupt everything, and it will still catch user input).
Title: Re: Lua Routines
Post by: Ashbad on June 22, 2011, 07:45:05 am
Well, it should't really use that many resources :P plus, my routine would be better if it got rid of the horrible on.event things that would happen at the same time of the loop.
Title: Re: Lua Routines
Post by: Jim Bauwens on June 22, 2011, 08:13:10 am
It probably does, as it doesn't react to anything while its looping (read: the calc freezes).
Title: Re: Lua Routines
Post by: Ashbad on June 22, 2011, 08:20:16 am
Well, that's the point :P. It's supposed to stop all execution for that amount of time, like a pausing loop in z80 assembly that denies interrupt execution does.
Title: Re: Lua Routines
Post by: Jim Bauwens on June 22, 2011, 08:46:11 am
Well, that is what you call a busy sleep. You can't have this kind of stuff on a computer, as it will takes lots of cpu power. And with nspire Lua you can have multiple script apps (basic multitasking), so this isn't the best solution.
Well, it actually depends on what you want to do :)
Title: Re: Lua Routines
Post by: Ashbad on June 22, 2011, 08:57:36 am
True.  Another way to do it would be this:

Code: [Select]
global_flags = {is_paused = nil}

setupBeginNoBreakPause = function(milliseconds)
   global_flags.is_paused = timer.start(milliseconds/1000)
end
   
-- all events are surrounded with a limited that doesn't allow anything to happen while the flag is set

function on.timer
   if global_flags.is_paused
      global_flags.is_paused = nil
   end

end


A bit more messy, but preserves all processing.
Title: Re: Lua Routines
Post by: Munchor on June 22, 2011, 09:54:02 am
Quote
If that's really an equilateral triangle, shouldn't the square root of 3 be involved somehow?

I don't have to, I basically use trigonometry to find out the height of the triangle and remove that height to the Y position and I get the Y position of the upper vertex and then I can use the drawLine functions to effectively draw the triangle.

I rechecked my routine and I happen to think the following one is better, I was using cos( instead of sin( in the wrong place.

Code: [Select]
function drawTriangle(gc,x,y,l)
gc:drawLine(x,y,x+l,y)
gc:drawLine(x, y, x+(l/2), y+(l*math.sin(60)))
gc:drawLine(x+(l/2), y+(l*math.sin(60)), x+l, y)
end
Title: Re: Lua Routines
Post by: Jim Bauwens on June 22, 2011, 01:41:02 pm
Ashbad, thats quite a good way :)
Title: Re: Lua Routines
Post by: Munchor on June 22, 2011, 05:21:06 pm
Ashbad, I don't really see how that works, can you give me an example please? Thanks
Title: Re: Lua Routines
Post by: Ashbad on June 22, 2011, 08:51:43 pm
Well, I don't code in Lua anymore and I don't even own an Nspire, so I'm going blind here -- however, I can explain how it works.

You start by setting up a global table of non-linear flags that can accessed throughout the program, and you set the first one, which corresponds to saying if the timer is paused or not, to nil.  You then make a function that restarts the main timer an make it tick at a frequency defined by the milliseconds parameter.  All events cannot run while the flag is set (I simply set the flag by having it hold the current timer's key or whatever it uses to access the ticking, which normally is a no-no for flags but it saves space) and when the the timer ticks once, it resets the flag and allows for normal event execution.

Events a cool things in Lua, but in cases of timers and such, they can be really annoying and get in the way x.x
Title: Re: Lua Routines
Post by: BrownyTCat on June 25, 2011, 10:08:38 pm
Pause for an exact amount of time, in milliseconds

Code: [Select]
WaitMS = function(milliseconds)
   while (stime = math.abs(timer.GetMilliSecCounter()+milliseconds))<
            math.abs(timer.getMilliSecCounter()) do end
   return true
end

This gives:
')' expected near '='
Title: Re: Lua Routines
Post by: Ashbad on June 25, 2011, 10:11:38 pm
Don't use that one.  Use a custom-made implementation of this that fits your application-specific needs instead:


Code: [Select]
global_flags = {is_paused = nil}

setupBeginNoBreakPause = function(milliseconds)
   global_flags.is_paused = timer.start(milliseconds/1000)
end
   
-- all events are surrounded with a limited that doesn't allow anything to happen while the flag is set

function on.timer
   if global_flags.is_paused
      global_flags.is_paused = nil
   end

end

Title: Re: Lua Routines
Post by: BrownyTCat on June 25, 2011, 10:31:10 pm
Don't use that one.  Use a custom-made implementation of this that fits your application-specific needs instead:


Code: [Select]
global_flags = {is_paused = nil}

setupBeginNoBreakPause = function(milliseconds)
   global_flags.is_paused = timer.start(milliseconds/1000)
end
   
-- all events are surrounded with a limited that doesn't allow anything to happen while the flag is set

function on.timer
   if global_flags.is_paused
      global_flags.is_paused = nil
   end

end



'(' expected near 'if'
Title: Re: Lua Routines
Post by: Ashbad on June 25, 2011, 10:40:23 pm
Simply inside of all your events, make it so once the global flag is set to a non-nil value, the event execution ends and don't allow them to be triggered by starting all code within the blocks with a "if global_flags.is_paused ~= nil" checker.  Simple as that ;)
Title: Re: Lua Routines
Post by: BrownyTCat on June 25, 2011, 10:42:34 pm
Simply inside of all your events, make it so once the global flag is set to a non-nil value, the event execution ends and don't allow them to be triggered by starting all code within the blocks with a "if global_flags.is_paused ~= nil" checker.  Simple as that ;)
/me 's head exploded.

Grayscale calc owners, place this in your on.paint(gc) loop:
Code: [Select]
function setGrey(shade)
gc:setColorRGB((shade*255)/16,(shade*255)/16,(shade*255)/16)
end
That makes it so you can set the shade of grey like so: 0=black, 8=middle, 16=white.
Title: Re: Lua Routines
Post by: Jim Bauwens on June 26, 2011, 04:05:24 am
I would not place it in on.paint, as it will redefine it every time it is run.
I would do this:
Code: [Select]
function setGrey(shade)
platform.gc():setColorRGB((shade*255)/16,(shade*255)/16,(shade*255)/16)
end
or
Code: [Select]
function setGrey(gc, shade)
gc:setColorRGB((shade*255)/16,(shade*255)/16,(shade*255)/16)
end

And put both of those functions OUTSIDE of on.paint.
The first one platform.gc() to get the graphical context (valid if called from on.paint), and the second one ask's gc as a parameter (might be a bit faster).
Title: Re: Lua Routines
Post by: Munchor on June 26, 2011, 06:21:29 am
Yeah Jim Bauwens's seems better because it would use lots of cycles and we want our programs to run fast, so defining it once is better.
Title: Re: Lua Routines
Post by: pianoman on July 01, 2011, 12:09:06 pm
BrownyTCat and Jim Bauwens, I love you!
Title: Re: Lua Routines
Post by: Adriweb on July 09, 2011, 12:30:26 pm
Hey, I just saw this topic and wanted to share with you guys what I had done on my side, without knowledge of what existed here :

https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua (https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua)

If that's ok with you, I'd want to add some of the routines from this topic in BetterLuaAPI. Of course, credits will be written.
Title: Re: Lua Routines
Post by: Jim Bauwens on July 09, 2011, 03:53:12 pm
I haven't posted many routines here, but its ok for me :)