2025年10月6日 星期一

Lua table中,key宣告時自帶string

 7 kyu Turn with a Compass

這題不算難,但是我用Lua在table宣告初使值,犯了錯誤,
如下:

> a = {'t' = 1}

stdin:1: '}' expected near '='

這邊't' = 1錯誤,
t應該不用宣告為string, 而是table中的key會自帶string,
修正如下:

> a = {t = 1}

這樣就正確了。
補充說明,
如果要設定a[1]的值如下:

> a = {1 = 12}

stdin:1: '}' expected near '='

> a = {[1] = 12}

> a[1]

12


另外這題我寫的程式碼不是很精簡,
但還是寫出來了,如下:
local function direction(facing, turn)
  local d = {N = 0, 
             NE = 45,
             E = 90,
             SE= 135,
             S = 180,
             SW= 225,
             W = 270,
             NW= 315}
  local t = (d[facing] + turn) % 360
  if 0 == t then
    return 'N'
  elseif 45 == t then
    return 'NE'
  elseif 90 == t then
    return 'E'
  elseif 135 == t then
    return 'SE'
  elseif 180 == t then
    return 'S'
  elseif 225 == t then
    return 'SW'
  elseif 270 == t then 
    return 'W'
  elseif 315 == t then
    return 'NW'
  end
end

return direction

2025年10月1日 星期三

7 kyu:Set the Alarms Up 別人簡潔的寫法

 嘗試練習7 kyu: Set the Alarms Up

使用Lua語言,題目是設定連續鬧鐘,如果不是寫成程式,
就數學上,大概只會用到小學數學。

我自己的寫法是:

local function set_the_alarms_up(time, n)
  local t = os.time{year=1970, month=1, day=1, hour=0}
  local hours = string.sub(time, 1, 2)
  local hour = tonumber(hours)
  local ms = string.sub(time, 4, 5)
  local m = tonumber(ms)
  t = t + m*60 + hour*3600
  local a = {os.date("%H:%M", t)}
  for i = 2, n do
    a[i] = os.date("%H:%M", t + 300*(i-1))
  end
  return a
end

return set_the_alarms_up

Note: 

1. os.time設定值,是以秒為單位

2. 在Unix system 0值在00:00:00 UTC, January 1, 1970,但要注意台灣的時區是+08:00

所以台灣的os.time{year=1970, month=1, day=1, hour=0}不是0,而是-28800


看到別人的寫法:

local function set_the_alarms_up(time, n)
  local res, h, m = {}, time:match "^(%d+):(%d+)$"
  for i = 1, n do
    res[i] = os.date("%H:%M", (h * 60 + m + 5 * (i - 1)) * 60)
  end
  return res
end

return set_the_alarms_up

其中local res, h, m = {}, time:match "^(%d+):(%d+)$"

這行我覺得寫得很精簡,

GPT 5解釋如下:

這一行 Lua 寫法:

local res, h, m = {}, time:match "^(%d+):(%d+)$"

可以分成兩部分來看:


1. 左邊變數定義

local res, h, m = ...
  • local:表示這些變數是區域變數 (scope 只在當前程式塊內)

  • res:被初始化為 {},也就是一個新的空 table。

  • h, m:會由右邊 time:match(...) 的結果來賦值。


2. 右邊字串模式匹配

time:match "^(%d+):(%d+)$"

這是 Lua 的 字串方法,等同於:

string.match(time, "^(%d+):(%d+)$")
  • ^:匹配字串開頭

  • %d+:匹配一個或多個數字

  • ::匹配冒號字元本身

  • $:匹配字串結尾

所以這個 pattern 會匹配 「數字:數字」 這種格式,例如 "12:34"。

由於有兩個括號捕獲組 (%d+),string.match 會返回兩個結果:

  • 第一個捕獲 → h

  • 第二個捕獲 → m


3. 綜合起來

如果:

time = "12:34"

那麼執行後:

res = {} -- 空表 h = "12" -- 字串 "12" m = "34" -- 字串 "34"

👉 簡單說:
這行程式碼同時做了兩件事:

  1. 建立一個空表 res

  2. 從字串 time 中解析出「小時」和「分鐘」(字串型態),分別放到 h 和 m 裡。


另外為何time:match "^(%d+):(%d+)$"的函式不用括號?

GPT 5 解釋如下:

這個是 Lua 的語法糖 (syntactic sugar) 👍

在 Lua 裡,如果一個函式呼叫 只有一個參數,而這個參數是:

  • 一個 字串常值

  • 或是一個 table 常值

那麼可以省略小括號 ()。


範例:

print("hello") -- 一般寫法 print "hello" -- 語法糖,省略括號 f({x=1, y=2}) -- 一般寫法 f {x=1, y=2} -- 語法糖,省略括號

套用到你的程式

time:match("^(%d+):(%d+)$") -- 正常呼叫 time:match "^(%d+):(%d+)$" -- 語法糖,省略括號

這兩行 完全一樣,只是簡潔寫法。


👉 所以你看到的 time:match "^(%d+):(%d+)$" 只是 Lua 的簡化呼叫方式,函式其實還是有接到參數的。


Lean 4 極簡教學 (Using VS Code on macOS)

 1. Install Lean Environment: https://lean-lang.org/install/ 試著完Step one, two, three 2. 在VS code下,建一新的project: 取名Hello_World 3. 嘗試執行Main.lea...