Omnimaga
Calculator Community => TI Calculators => Lua => Topic started 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
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
-
My version:
function isPrime(n)
return math.eval("isprime("..n..")")
end
I don't know if its faster though.
-
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?
-
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.
-
What happens if the square root is irrational?
-
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.
-
Oh, got it. Thanks!
-
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
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)
-
Pause for an exact amount of time, in milliseconds
WaitMS = function(milliseconds)
while (stime = math.abs(timer.GetMilliSecCounter()+milliseconds))<
math.abs(timer.getMilliSecCounter()) do end
return true
end
-
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
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?
-
Pause for an exact amount of time, in milliseconds
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).
-
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.
-
It probably does, as it doesn't react to anything while its looping (read: the calc freezes).
-
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.
-
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 :)
-
True. Another way to do it would be this:
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.
-
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.
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
-
Ashbad, thats quite a good way :)
-
Ashbad, I don't really see how that works, can you give me an example please? Thanks
-
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
-
Pause for an exact amount of time, in milliseconds
WaitMS = function(milliseconds)
while (stime = math.abs(timer.GetMilliSecCounter()+milliseconds))<
math.abs(timer.getMilliSecCounter()) do end
return true
end
This gives:
')' expected near '='
-
Don't use that one. Use a custom-made implementation of this that fits your application-specific needs instead:
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
-
Don't use that one. Use a custom-made implementation of this that fits your application-specific needs instead:
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'
-
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 ;)
-
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:
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.
-
I would not place it in on.paint, as it will redefine it every time it is run.
I would do this:
function setGrey(shade)
platform.gc():setColorRGB((shade*255)/16,(shade*255)/16,(shade*255)/16)
end
or
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).
-
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.
-
BrownyTCat and Jim Bauwens, I love you!
-
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.
-
I haven't posted many routines here, but its ok for me :)