引き続き第2章も解いていきます。
第2章はUnixコマンドの基礎ということで、以下のテキストファイルを読み込んで処理を行う内容と
なっています。
高知県	江川崎	41	2013-08-12
埼玉県	熊谷	40.9	2007-08-16
岐阜県	多治見	40.9	2007-08-16
山形県	山形	40.8	1933-07-25
山梨県	甲府	40.7	2013-08-10
和歌山県	かつらぎ	40.6	1994-08-08
静岡県	天竜	40.6	1994-08-04
山梨県	勝沼	40.5	2013-08-10
埼玉県	越谷	40.4	2007-08-16
群馬県	館林	40.3	2007-08-16
群馬県	上里見	40.3	1998-07-04
愛知県	愛西	40.3	1994-08-05
千葉県	牛久	40.2	2004-07-20
静岡県	佐久間	40.2	2001-07-24
愛媛県	宇和島	40.2	1927-07-22
山形県	酒田	40.1	1978-08-03
岐阜県	美濃	40	2007-08-16
群馬県	前橋	40	2001-07-24
千葉県	茂原	39.9	2013-08-11
埼玉県	鳩山	39.9	1997-07-05
大阪府	豊中	39.9	1994-08-08
山梨県	大月	39.9	1990-07-19
山形県	鶴岡	39.9	1978-08-03
愛知県	名古屋	39.9	1942-08-02
10. 行数のカウント
行数をカウントせよ。確認にはwcコマンドを用いよ。
→1行ずつ読み込んだらスライスに入れて、要素数をカウントすればいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	open := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	file := open("../data/hightemp.txt")
	fmt.Println(len(file))
}
参考:Go でファイルや標準入力からテキストを一行ずつ読む
http://www.yunabe.jp/tips/golang_readlines.html
11. タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ。
→読み込んだのを1行ずつ、strings.Replaceでスペースに置換すればおk
package main
import (
	"bufio"
	"fmt"
	"os"
	"strings"
)
func main() {
	open := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	for _, v := range open("../data/hightemp.txt") {
		fmt.Println(strings.Replace(v, "\t", " ", -1))
	}
}
12. 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ。
→1行ずつ読むときにタブでスプリットする。配列の0番目と1番目がそれぞれ1列目と2列目になるのでそれをファイルに書き込めばいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
	"strings"
)
func main() {
	arr1, arr2 := []string{}, []string{}
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	for _, v := range read("../data/hightemp.txt") {
		tmp := strings.Fields(v)
		arr1 = append(arr1, tmp[0])
		arr2 = append(arr2, tmp[1])
	}
	write := func(text string, data []string) {
		f, err := os.Create(text)
		if err != nil {
			panic(err)
		}
		w := bufio.NewWriter(f)
		for _, v := range data {
			fmt.Fprint(w, v, "\n")
		}
		w.Flush()
	}
	write("col1.txt", arr1)
	write("col2.txt", arr2)
}
13. col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ。確認にはpasteコマンドを用いよ。
→col1.txt、col2.txtをそれぞれ読み取って、2個のスライスを引数にファイルに書けばいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	arr1, arr2 := []string{}, []string{}
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	arr1 = read("col1.txt")
	arr2 = read("col2.txt")
	write := func(row1, row2 []string, text string) {
		f, err := os.Create(text)
		if err != nil {
			panic(err)
		}
		w := bufio.NewWriter(f)
		for i, _ := range row1 {
			fmt.Fprint(w, row1[i], "\t", row2[i], "\n")
		}
		w.Flush()
	}
	write(arr1, arr2, "merge.txt")
}
14. 先頭からN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ。
→N行分までFor文で出力さすればいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	text := read("../data/hightemp.txt")
	n, _ := strconv.Atoi(os.Args[1])
	for i := 0; i < n; i++ {
		fmt.Println(text[i])
	}
}
15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ。
→末尾だからN行目以降、NからFor文回せばいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	text := read("../data/hightemp.txt")
	n, _ := strconv.Atoi(os.Args[1])
	for i := len(text) - n; i < len(text); i++ {
		fmt.Println(text[i])
	}
}
16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ。
→行数 / N の値で割り切れたときにファイルに書けばいいんじゃね。
24行を4分割すると、24 / 4 = 6 だから、For文回したときに6で割り切れた時にファイルに書けば
6行ずつファイルに4分割されんじゃね?
package main
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	write := func(row []string, text string) {
		f, err := os.Create(text)
		if err != nil {
			panic(err)
		}
		w := bufio.NewWriter(f)
		for _, v := range row {
			fmt.Fprint(w, v, "\n")
		}
		w.Flush()
	}
	text := read("../data/hightemp.txt")
	n, _ := strconv.Atoi(os.Args[1])
	splitcnt := len(text) / n
	tmp := []string{}
	for i := 1; i <= len(text); i++ {
		tmp = append(tmp, text[i-1])
		if i%splitcnt == 0 {
			write(tmp, strconv.Itoa(i)+".txt")
			tmp = []string{}
		}
	}
}
17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ。
→mapにkeyに1列目を入れてって集合を出せばいいんじゃね
package main
import (
	"bufio"
	"fmt"
	"os"
	"strings"
)
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	makemap := func(arr []string) map[string]bool {
		tmp := make(map[string]bool)
		for _, v := range arr {
			_, ok := tmp[v]
			if ok == false {
				tmp[v] = true
			}
		}
		return tmp
	}
	txt := read("../data/hightemp.txt")
	var row1 = []string{}
	for _, v := range txt {
		tmp := strings.Fields(v)
		row1 = append(row1, tmp[0])
	}
	for i, _ := range makemap(row1) {
		fmt.Println(i)
	}
}
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ)。確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい)。
→1列目~4列目をひとまず構造体にセットして、3列目の温度でソートさせるインターフェイスを↓の記事見ながら実装するべさ
package main
import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)
type Hightemp struct {
	pref string
	town string
	temp float64
	date string
}
type ByTemp []Hightemp
func (a ByTemp) Len() int {
	return len(a)
}
func (a ByTemp) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a ByTemp) Less(i, j int) bool {
	return a[i].temp < a[j].temp
}
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	txt := read("../data/hightemp.txt")
	arr := []Hightemp{}
	for _, v := range txt {
		tmp := strings.Fields(v)
		ondo, _ := strconv.ParseFloat(tmp[2], 64)
		tmp1 := Hightemp{tmp[0], tmp[1], ondo, tmp[3]}
		arr = append(arr, tmp1)
	}
	sort.Sort(ByTemp(arr))
	for _, v := range arr {
		fmt.Printf("%v\t%v\t%v\t%v\n", v.pref, v.town, v.temp, v.date)
	}
}
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ。確認にはcut, uniq, sortコマンドを用いよ。
→1列目の文字列とカウント回数のmapを作成して構造体にいれてソートさせればいいんじゃね?
18と同じようなことを出現回数でやればよくね。
package main
import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strings"
)
type Hightemp struct {
	pref string
	cnt  int
}
type ByCnt []Hightemp
func (a ByCnt) Len() int {
	return len(a)
}
func (a ByCnt) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}
func (a ByCnt) Less(i, j int) bool {
	return a[i].cnt > a[j].cnt
}
func main() {
	read := func(path string) []string {
		f, err := os.Open(path)
		if err != nil {
			fmt.Fprintf(os.Stderr, "File %s could not read: %v\n", path, err)
		}
		defer f.Close()
		lines := []string{}
		scanner := bufio.NewScanner(f)
		for scanner.Scan() {
			lines = append(lines, scanner.Text())
		}
		if serr := scanner.Err(); serr != nil {
			fmt.Fprintf(os.Stderr, "File %s scan error: %v\n", path, err)
		}
		return lines
	}
	makemap := func(arr []string) map[string]int {
		tmp := make(map[string]int)
		for _, v := range arr {
			_, ok := tmp[v]
			if ok == false {
				tmp[v] = 1
			} else {
				tmp[v] = tmp[v] + 1
			}
		}
		return tmp
	}
	txt := read("../data/hightemp.txt")
	var row1 = []string{}
	for _, v := range txt {
		tmp := strings.Fields(v)
		row1 = append(row1, tmp[0])
	}
	arr := []Hightemp{}
	for i, v := range makemap(row1) {
		tmp := Hightemp{i, v}
		arr = append(arr, tmp)
	}
	sort.Sort(ByCnt(arr))
	for _, v := range arr {
		fmt.Printf("%v %v\n", v.pref, v.cnt)
	}
}