TI-Nspire & Lua / スクリプティングのヒント / メタテーブルを使う 9 of 9 / メモ化する

参考:

-- 竹内函数を定義する。これをメモ化してみる。
function tarai(x, y, z)
   if x <= y then
      return y
   else
      return tarai(tarai(x - 1, y, z), tarai(y - 1, z, x), tarai(z - 1, x, y))
   end
end 

-- メモ化函数を定義する。
function memorize(func)
   local mem = {} -- 計算結果を記憶しておくためのテーブルを用意する。
   setmetatable(mem, {__mode = "v"}) -- そのテーブルを「(値の) 弱いテーブル」にする。弱いテーブルにする意味は今回はあまりない。
   return function(...)
              -- 引数をキーとして過去の計算結果を参照し、
              -- 計算結果が見つかればそれを返す。
              -- 見つからなければ新たに計算して返すとともに記憶しておく。
             local key = table.concat({...}, ",") 
             local result = mem[key]
             if result == nil then
                result = func(...)
                mem[key] = result
             end
             return result
          end
end

------------------
-- 確かめてみる --
------------------
-- メモ化しない場合:
do
local startTime = timer.getMilliSecCounter()
local a = tarai(12,6,0)
local stopTime = timer.getMilliSecCounter()
local elapsedTime = stopTime - startTime
print("case 1. output: "..a..", elapsed time: "..elapsedTime.." msec")
end

-- メモ化した場合:
tarai = memorize(tarai)
do
local startTime = timer.getMilliSecCounter()
local a = tarai(12,6,0)
local stopTime = timer.getMilliSecCounter()
local elapsedTime = stopTime - startTime
print("case 2. output: "..a..", elapsed time: "..elapsedTime.." msec")
end

-- メモ化した竹内函数をもう一度同じ初期値で計算した場合:
do
local startTime = timer.getMilliSecCounter()
local a = tarai(12,6,0)
local stopTime = timer.getMilliSecCounter()
local elapsedTime = stopTime - startTime
print("case 3. output: "..a..", elapsed time: "..elapsedTime.." msec")
end

f:id:ti-nspire:20170219103427p:plain

TI-Nspire & Lua / スクリプティングのヒント / メタテーブルを使う 8 / スタックを実装する

参考: お気楽 Lua プログラミング超入門

Stack = class()
function Stack:init(size)
   self.buff = {}
   self.size = size or math.huge
end
function Stack:push(val)
   if #self.buff < self.size then
      table.insert(self.buff, val)
   else
      error("Error: Stack is full.", 0) -- 上限を超えて push したときにエラーを出す。 
   end
end
function Stack:pop()
   if #self.buff > 0 then
      return table.remove(self.buff)
   else
      error("Error: Stack is empty.", 0) -- 空のスタックから pop したときにエラーを出す。
   end
end


-- 確かめてみる。
stack = Stack(10)
for i = 1, 5 do -- 1 から順番に push する。
   stack:push(i)
   print(i)
end
while true do -- 最後に push した値から順番に pop する。
   print(stack:pop())
end

f:id:ti-nspire:20170217081215p:plain
 

-- 確かめてみる。
stack = Stack(5)
for i = 1, 999 do -- 1 から順番に push する。
   stack:push(i)
   print(i)
end

f:id:ti-nspire:20170217080541p:plain

TI-Nspire & Lua / スクリプティングのヒント / メタテーブルを使う 7 / メタテーブルを直接使わずにクラスを利用する

Nspired Lua は class() ライブラリーが実装してあるのでメタテーブルを直接使わずにクラスが記述できる。

Class = class()
function Class:init(a, b)
   self[1] = a
   self[2] = b
end
function Class:setValue(where, what)
   rawset(self, where, what)
end


-- 確認してみる。
instTable_1 = Class(111, 222)
instTable_2 = Class("ABC", "DEF")
print("test_1: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

instTable_1:setValue(1, 333)
print("test_2: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

instTable_2:setValue(2, "GHI")
print("test_3: ", instTable_1[1], instTable_1[2], instTable_2[1], instTable_2[2])

instTable_2:setValue(-10000, "ZZZ")
print("test_4: ")
for k, v in pairs(instTable_1) do
   print(k, v)
end
for k, v in pairs(instTable_2) do
   print(k, v)
end

-- class() ライブラリーで作られるクラスももちろんテーブルである。
print("test_5:")
print(Class)
--print(type(Class))
for k, v in pairs(Class) do
   print(k, v)
end

f:id:ti-nspire:20170215092022p:plain