2025年11月2日 星期日

Lua基本運算的簡潔寫法

 7 kyu: Dot Calculator

這題是用"."點的數目表示數字,並給operator做運算。
我的寫法是:
return function(equation)
    local temp, s1, s2, op = 0, 0, 0, nil
    for i = 1, #equation do
      local c = equation:sub(i, i)
      if '+' == c or '-' == c or '*' == c or '/' == c then
        op = c
        if temp > 0 then
          s1 = temp
        end
        temp = 0
      elseif '.' == c then
        temp = temp + 1
      end
    end
    s2 = temp
    if '+' == op then
      s2 = s1 + s2
    elseif '-' == op then
      s2 = s1 - s2
    elseif '*' == op then
      s2 = s1 * s2
    elseif '/' == op then
      s2 = s1 // s2
    end
    local s = ""
    for i = 1, s2 do
      s = s .. '.'
    end
    return s  
end
別人簡潔的寫法是:
return function(equation)
    return ('.'):rep(load('return '..equation:gsub('%.+', string.len))())
end
  • 看了別人的code,才知道gsub裡準備取代的字串長度,可以用string.len.
  • string.gsub(s, pattern, repl [, n]) performs global substitutions in string sIt replaces all occurrences of pattern with repl.
    • repl: The replacement value. This can be a string, a table, or a function.
      • If repl is a string, it replaces the matched pattern. Special characters like % have meaning (e.g., %1 refers to the first capture).
      • If repl is a table, the table is indexed with the first capture, and the corresponding value is used as the replacement.
      • If repl is a function, it is called for each match, with the captures as arguments, and its return value is used as the replacement. (string.len是function)
  • 另外:
  • load
    This function compiles a chunk of Lua code from a string and returns it as a function. It does not execute the code immediately.

string.rep is a function in Lua's standard string library that repeats a given string a specified number of times.

2025年10月27日 星期一

用Lua, 驗證格式正確性

 7 kyu, Validate the Euro bill

這題是驗證一串英數字的格式正確性,

我的解法是:

local function strn(ch)
  return ch:byte() - 64
end

local function validate_euro(serial_number)
  local s = 0
  local first = strn(serial_number:sub(1, 1))
  local second = strn(serial_number:sub(2, 2))
  if nil == first or nil == second then
    return false
  else
    s = first + second
    for i = 3, #serial_number do
      local cnum = tonumber(serial_number:sub(i, i))
      if nil == cnum then
        return false
      else
        s = s + cnum
      end
    end
    local ans = 0
    while s > 9 do
      while s > 0 do
        ans = ans + s % 10
        s = s // 10
      end
      s = ans
      ans = 0
    end
    if 7 == s then 
      return true
    else
      return false
    end
  end
end

return validate_euro

不過這題有特解,別人的解法是:

local function validate_euro(serial_number)
  local sum = 0
  for c in serial_number:gmatch "." do
    sum = sum + c:byte()
  end
  return sum % 9 == 3
end

return validate_euro

首先,題目如下:

The serial number of every Euro bill contains 2 uppercase latin letters at the start and the following 10 digits.

1. Sum every digit in a serial number.
2. Get the English Alphabetical position of the two letters. (A - 1, B - 2, C - 3 and etc.).
3. Add those numbers to the already existing sum of digits.
4. Sum the result's digits up. If the sum is not 1-digit number, keep summing the new number's digits, until the result is 1-digit number.

If the eventual result equals 7, you're holding a real Euro bill. 

以上加總的方式,可以用num % 9來取代,因為
設 num = a + 10*b + 100*c + 1000*d (千位數)

= a + b + c + d + 9*b + 99*c + 999*d

顯然num % 9 = (a + b + c + d) % 9 + 9*(b + 11*c + 111*d) % 9

= (a + b + c + d) % 9

如果num為其它位數,依此類推,

所以(a + b + c + d) % 9 = num % 9

跟一般的數字加總相比,當餘數為9時num % 9 為0,
餘數為1~8時,跟一般的數字加總一樣。

但是別人的code是取得ascii的文數字,

"0":48

"A":65

"A":65是當作1, 所以是64 + 1 = 65

題目是2碼英文字,10碼數字,所以

num = 64 + 64 + 48*10 + a + b + c + d + e + f + g + h + i + j

= 608 + a + b + c + d + e + f + g + h + i + j

當文數字序號正確時,是剩下7,

所以num % 9 = 608 % 9 + ( a + b + c + d + e + f + g + h + i + j) % 9

= 5 + 7 = 12

超過個位數,再相加: 1 + 2 = 3

所以return sum % 9 == 3

Lua基本運算的簡潔寫法

 7 kyu: Dot Calculator 這題是用"."點的數目表示數字,並給operator做運算。 我的寫法是: return function ( equation ) local temp , s1 , s2 , op = 0 , 0...