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