Go 解題 Package (ft. 106年技藝競賽)
tags: Go
Package
category: Programming
description: Go 解題 Package (ft. 106年技藝競賽)
created_at: 2021/08/11 13:00:00
set: 技藝競賽
Source
Github: https://github.com/LaiJunBin/go-solve-kit
上面有比較詳細的文件
前言
Go
滿多東西都得自己實作的,解題起來就覺得有一點冗長,想說實現一些東西讓他寫起來更像 JavaScript
或是 VB LINQ
,而做了這個 Package
在以前技藝競賽的時候規定使用 VB
,所以當時那種語法寫習慣了也覺得很方便,在PHP好像叫做流暢的介面(?),當時我是106年的,所以就拿106年的題目開刀吧,不然光做沒拿來用感覺也怪怪的,畢竟要做了才知道哪裡有不足需要加功能。
安裝
$ go get github.com/laijunbin/go-solve-kit
引入
import (
sk "github.com/laijunbin/go-solve-kit"
)
看看幾個範例
Example 1: 從標準輸入讀取兩個數並加總
func main() {
sum := sk.LineInput().Split(" ")[:2].ToIntArray().Sum()
fmt.Println(sum)
}
Example 2: 沒有要幹嘛,就是產生1~5的數字全部平方然後過濾留下偶數
func main() {
nums := []int {1, 2, 3, 4, 5}
output := sk.FromIntArray(nums).Map(func(v sk.Int, _ int) interface{} {
return v * v
}).Filter(func(v sk.Type, _ int) bool {
return v.ToInt() % 2 == 0
}).ToStringArray().Join("\n")
fmt.Println(output)
}
輸出:
4
16
Example 3: 還是沒有要幹嘛,而且不太好形容
func main() {
array2D := sk.NewArray(5).Map(func(_ sk.Type, i int) interface{} {
return sk.NewRange(1, 5, 2).Map(func(v sk.Int, j int) interface{} {
return v.ValueOf() * i
})
})
fmt.Println(array2D)
fmt.Println(array2D.Get(2, 2).ToInt())
fmt.Println(array2D.Get(4, 1).ToInt())
fmt.Println("-------------------")
fmt.Println(array2D)
fmt.Println(array2D.Length())
fmt.Println(array2D.Flatten())
fmt.Println(array2D.Flatten().Length())
}
輸出:
[{[{0} {0} {0}]} {[{1} {3} {5}]} {[{2} {6} {10}]} {[{3} {9} {15}]} {[{4} {12} {20}]}]
10
12
-------------------
[{[{0} {0} {0}]} {[{1} {3} {5}]} {[{2} {6} {10}]} {[{3} {9} {15}]} {[{4} {12} {20}]}]
5
[{0} {0} {0} {1} {3} {5} {2} {6} {10} {3} {9} {15} {4} {12} {20}]
15
開始解技藝競賽的題目
第一題: 計算含有 s 或 S 字母的字數
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
count := sk.LineInput().Split(" ").Filter(func(s sk.String, _ int) bool {
return s.ToLower().Contains("s")
}).Length()
fmt.Println(count)
})
}
第二題: 給一個羅馬數字符號,轉為整數數字
func main() {
keys := sk.FromStringArray([]string {"I", "V", "X", "L", "C", "D", "M"})
values:= sk.FromIntArray([]int {1, 5, 10, 50, 100, 500, 1000})
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
val := 0
data := sk.LineInput().TrimSpace().Split("")
data.ForEach(func(s sk.String, i int) {
if i == data.Length().ValueOf() - 1 {
val += values[keys.IndexOf(s.ValueOf())].ValueOf()
} else {
currentIndex := keys.IndexOf(s.ValueOf())
nextIndex := keys.IndexOf(data[i+1].ValueOf())
sign := sk.If(currentIndex < nextIndex, -1, 1).(int)
val += values[currentIndex].ValueOf() * sign
}
})
fmt.Println(val)
})
}
第三題: 信用卡卡號
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
sum := sk.LineInput()[:16].Split("").ToIntArray().Map(func(v sk.Int, i int) interface{} {
val := v.ValueOf()
n := sk.If(i % 2 == 0, 2, 1).(int)
return sk.If(val * n >= 10, val * n - 9, val * n)
}).ToIntArray().Sum()
isValid := sk.If(sum % 10 == 0, "T", "F")
fmt.Println(isValid)
})
}
第四題: 幾 A 幾 B
func GetNumbers(nums sk.StringArray, current string) sk.TypeArray{
if nums.Length() == 0 {
return sk.NewArray(1).Fill(current)
}
return nums.Map(func(s sk.String, i int) interface{} {
return GetNumbers(nums.Filter(func(_ sk.String, j int) bool {
return i != j
}), current + s.ValueOf())
}).Flatten()
}
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
data := sk.LineInput().Split(",")
nums, i, j := data[0].Split(""), data[1].ToInt() - 1, data[2].ToInt() - 1
numbers := GetNumbers(nums, "").ToStringArray()
num1, num2 := numbers[i], numbers[j]
A, B := 0, 0
num1.Split("").ForEach(func(s sk.String, i int) {
index := num2.IndexOf(s.ValueOf())
if i == index.ValueOf() {
A += 1
} else {
B += 1
}
})
fmt.Println(fmt.Sprintf("%vA%vB", A, B))
})
}
第五題: 網段廣播位址
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
data := sk.LineInput().Split("/").Map(func(s sk.String, _ int) interface{} {
return s.Split(".").ToIntArray()
})
ip, mask := data[0].ToIntArray(), data[1].ToIntArray()
output := ip.Map(func(v sk.Int, i int) interface{} {
return v | (255 - mask[i])
}).ToStringArray().Join(".")
fmt.Println(output)
})
}
第六題: 大數排序問題
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
nums := sk.LineInput().Split(", ")
sortedNums := nums.Copy()
sortedNums.SortBy(func(x, y sk.String) bool {
if x.Length() == y.Length() {
return x.Split("").Some(func(_ sk.String, i int) bool {
return x[i] < y[i]
})
}
return x.Length() < y.Length()
})
indexes := nums.Map(func(num sk.String, _ int) interface{} {
return sortedNums.IndexOf(num.ValueOf()) + 1
}).ToStringArray().Join(", ")
fmt.Println(indexes)
})
}
第七題: 樹
func Dfs(graph map[sk.Int]sk.IntArray, visited map[sk.Int]struct{}, node sk.Int, paths sk.IntArray) sk.IntArray {
if paths.Contains(node.ValueOf()) {
if paths.Slice(0, -2).Contains(node.ValueOf()) {
return paths[paths.IndexOf(node.ValueOf()):]
}
return sk.IntArray{}
}
visited[node] = struct{}{}
for _, nextNode := range graph[node] {
if result := Dfs(graph, visited, nextNode, append(paths, node)); result.Length() > 0 {
return result
}
}
return sk.IntArray{}
}
func GetCycleNodes(graph map[sk.Int]sk.IntArray) sk.IntArray {
visited := make(map[sk.Int]struct{}, 0)
for node := range graph {
if _, visit := visited[node]; visit {
continue
}
if result := Dfs(graph, visited, node, sk.IntArray{}); result.Length() > 0 {
return result
}
}
return sk.IntArray{}
}
func main() {
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
edges := sk.LineInput().Split(" ")
graph := make(map[sk.Int]sk.IntArray, 0)
edges.ForEach(func(s sk.String, _ int) {
edge := s.Split(",").ToIntArray()
if _, ok := graph[edge[0]]; !ok {
graph[edge[0]] = sk.IntArray{}
}
if _, ok := graph[edge[1]]; !ok {
graph[edge[1]] = sk.IntArray{}
}
graph[edge[0]] = append(graph[edge[0]], edge[1])
graph[edge[1]] = append(graph[edge[1]], edge[0])
})
cycleNodes := GetCycleNodes(graph)
cycleNodes.Sort()
if cycleNodes.Length() > 0 {
fmt.Println(cycleNodes.ToStringArray().Join(", "))
} else {
fmt.Println(sk.If(edges.Length().ValueOf() + 1 == len(graph), "T", "F"))
}
})
}
第八題: 後序運算式(postfix)
func main() {
operators := sk.FromStringArray([]string {"+", "-", "*", "/"})
sk.NewArray(sk.LineInput().ToInt().ValueOf()).ForEach(func(_ sk.Type, _ int) {
expression := sk.LineInput().Split(" ")
stack := sk.IntArray{}
for i := 0; i < expression.Length().ValueOf(); i++ {
if operators.Contains(expression[i].ValueOf()) {
b := stack.Pop()
a := stack.Pop()
switch expression[i].ValueOf() {
case "+":
stack.Append((a + b).ValueOf())
break
case "-":
stack.Append((a - b).ValueOf())
break
case "*":
stack.Append((a * b).ValueOf())
break
case "/":
stack.Append((a / b).ValueOf())
break
}
} else {
stack.Append(expression[i].ToInt().ValueOf())
}
}
fmt.Println(stack.Pop())
})
}
總結
雖然這些題目沒有特別難,但是如果以原生的 Go
下去解的話應該都會長滿多的,或是顯得雜亂一些,使用這一包 Package
來做程式碼就相對優美了一些。雖然也有可能是每個人習慣不同
目前還沒有做 Map
型別的包裝,但是可以像是第七題那樣自己稍微包一下,還是可以正常使用。
最後更新時間: 2021年08月11日.