gpcg
combine multiple files into one
gpcg
は,Go で競技プログラミングをする Gopher のためのツールです.
複数ファイルにまたがる Go のコードを 1 つのファイルにまとめます.
このツールは未完成です
以下のようなディレクトリ構造において,複数ファイルにまたがる Go のコードを一つにまとめ,提出用のコード gen.go
を生成します.
├── a.go // コンテスト中にコーディングするファイル
├── gen
│ └── gen.go // 生成されるコード
├── go.mod
└── lib // ライブラリ群.コンテスト前に用意するコード.
├── mod_inv.go
└── union_find.go
- ライブラリのコードは,
lib
以下に,package 名をlib
として保存してください lib
で定義された,1. 関数,2. 構造体,3. 変数 のうち,使用されたものを生成します.a.go
で定義された識別子と名前が衝突しないように,lib
以下で定義された識別子は rename されます.- main 関数は,
a.go
という名前で保存してください.
go get -u github.com/monkukui/gpcg/cmd/gpcg
このツールは未完成です 手元で動作確認をするためには,以下の手順で行ってください.
gpcg を install してください.
go get github.com/monkukui/gpcg/cmd/gpcg
gpcg の動作確認をするためのディレクトリを用意しました.
以下のリポジトリを git clone
してください.
https://github.com/monkukui/gpcg-sample-directory
git clone git@github.com:monkukui/gpcg-sample-directory.git
cd gpcg-sample-directory
ファイルを確認してください(もしくは,コードに変更を加えてください)
AtCoder Beginner Contest 177 D の問題を解くことを想定しています.
使用するライブラリは union_find.go
です.
go run a.go
などをして,問題の sample が通ることを確認してください.
a.go
package main
import (
"bufio"
"fmt"
"os"
alib "a/lib"
)
func main() {
r := bufio.NewReader(os.Stdin)
w := bufio.NewWriter(os.Stdout)
defer w.Flush()
var n, m int
fmt.Fscan(r, &n, &m)
uf := alib.NewUnionFind(n)
for i := 0; i < m; i++ {
var a, b int
fmt.Fscan(r, &a, &b)
a--
b--
uf.Union(a, b)
}
ans := 0
for i := 0; i < n; i++ {
if ans < uf.Size(i) {
ans = uf.Size(i)
}
}
fmt.Fprintln(w, ans)
}
lib/union_find.go
package lib
type UnionFind struct {
par []int
}
func NewUnionFind(N int) *UnionFind {
u := new(UnionFind)
u.par = make([]int, N)
for i := range u.par {
u.par[i] = -1
}
return u
}
func (u UnionFind) Find(x int) int {
if u.par[x] < 0 {
return x
}
u.par[x] = u.Find(u.par[x])
return u.par[x]
}
func (u UnionFind) Union(x, y int) {
xr := u.Find(x)
yr := u.Find(y)
if xr == yr {
return
}
if u.Size(yr) < u.Size(xr) {
yr, xr = swap(yr, xr)
}
u.par[yr] += u.par[xr]
u.par[xr] = yr
}
func (u UnionFind) Same(x, y int) bool {
return u.Find(x) == u.Find(y)
}
func (u UnionFind) Size(x int) int {
return -u.par[u.Find(x)]
}
// not exported but used
func swap(a int, b int) (int, int) {
return b, a
}
// exported but not used
func UnUsedFunction() string {
return "I am unused exported function"
}
// not exported and not used
func unUsedFunction() string {
return "I am unused unexported function"
}
// token.VAR
var hoge = 10
var Hoge = 10
// token.CONST
const huga = 100
const Huga = 100
var (
v1 = 1
V2 = 2 // exported
v3 = 3
v4 = 4
)
var (
UnUsedVar1 = 1
UnUsedVar2 = 2
UnUsedVar3 = 3
)
const (
C1 = 1
C2 = 2
C3 = 3
C4 = 4
)
const (
UnUsedConst1 = 1
UnUsedConst2 = 2
UnUsedConst3 = 3
)
いよいよ,コードを自動生成します.
gen/gen.go
gpcg -main a.go -lib lib -gen gen/gen.go
を実行してください.
gpt: generate code successfully✨
となれば成功です.
gen/gen.go
の中身を確認してください.
package main
import (
"bufio"
"fmt"
"os"
)
func generated_alib_swap(a int, b int) (int, int) {
return b, a
}
func (u generated_alib_UnionFind) Size(x int) int {
return -u.par[u.Find(x)]
}
func (u generated_alib_UnionFind) Union(x, y int) {
xr := u.Find(x)
yr := u.Find(y)
if xr == yr {
return
}
if u.Size(yr) < u.Size(xr) {
yr, xr = generated_alib_swap(yr, xr)
}
u.par[yr] += u.par[xr]
u.par[xr] = yr
}
func (u generated_alib_UnionFind) Find(x int) int {
if u.par[x] < 0 {
return x
}
u.par[x] = u.Find(u.par[x])
return u.par[x]
}
func generated_alib_NewUnionFind(N int) *generated_alib_UnionFind {
u := new(generated_alib_UnionFind)
u.par = make([]int, N)
for i := range u.par {
u.par[i] = -1
}
return u
}
type generated_alib_UnionFind struct{ par []int }
func main() {
r := bufio.NewReader(os.Stdin)
w := bufio.NewWriter(os.Stdout)
defer w.Flush()
var n, m int
fmt.Fscan(r, &n, &m)
uf := generated_alib_NewUnionFind(n)
for i := 0; i < m; i++ {
var a, b int
fmt.Fscan(r, &a, &b)
a--
b--
uf.Union(a, b)
}
ans := 0
for i := 0; i < n; i++ {
if ans < uf.Size(i) {
ans = uf.Size(i)
}
}
fmt.Fprintln(w, "ans = ", ans)
}
/* this code was generated by the code below
package main
import (
"bufio"
"fmt"
"os"
alib "a/lib"
)
func main() {
r := bufio.NewReader(os.Stdin)
w := bufio.NewWriter(os.Stdout)
defer w.Flush()
var n, m int
fmt.Fscan(r, &n, &m)
uf := alib.NewUnionFind(n)
for i := 0; i < m; i++ {
var a, b int
fmt.Fscan(r, &a, &b)
a--
b--
uf.Union(a, b)
}
ans := 0
for i := 0; i < n; i++ {
if ans < uf.Size(i) {
ans = uf.Size(i)
}
}
fmt.Fprintln(w, "ans = ", ans)
}
*/
このコードは,AtCoder Beginner Contest 177 D で提出すると AC(正当)を得られることを確認しています.