Skip to content

Instantly share code, notes, and snippets.

@ohkawa
Last active January 2, 2016 01:38
Show Gist options
  • Select an option

  • Save ohkawa/dcb5b768caaf1024f39a to your computer and use it in GitHub Desktop.

Select an option

Save ohkawa/dcb5b768caaf1024f39a to your computer and use it in GitHub Desktop.
Goでバケットソートアルゴリズム(ビット列を使用) ref: http://qiita.com/ohkawa/items/269507985b3ae10cbff9
package main
import (
"bufio"
"fmt"
"log"
"math"
"os"
"strconv"
"time"
)
// エラー共通処理
func failOnError(err error) {
if err != nil {
log.Fatal("Error:", err)
}
}
// 整数をbit配列で表した場合の位置(xバイト目のy番目のbit)を返却する
func getAddress(num int) (uint, uint) {
return uint(num / 8), uint(num % 8)
}
// ファイルから整数を読み取り、
// 入力ファイルに整数iがあればi番目のビットを1(オン)にしたByte配列を返す
func fromFile(filePath string) []byte {
f, err := os.Open(filePath)
failOnError(err)
defer f.Close()
// 最大値が判明している場合は最初からその分メモリを確保すれば良い
// 最大値が不明な場合はいちいちメモリを確保し直す必要がある?=逆に遅くなる可能性も
size := math.Pow10(7)/8 + 1
lines := make([]byte, int(size))
scanner := bufio.NewScanner(f)
for scanner.Scan() {
num, _ := strconv.Atoi(scanner.Text())
index, order := getAddress(num)
x := 1 << order
b := lines[index]
lines[index] = b | byte(x)
}
if err := scanner.Err(); err != nil {
failOnError(err)
}
return lines
}
// 整数iをi番目のビットを1(オン)にすることで表現したByte配列を、
// 該当する整数に戻して出力する
func writeByteList(path string, list []byte) {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
failOnError(err)
defer f.Close()
var writer *bufio.Writer
writer = bufio.NewWriter(f)
index := 0
for _, b := range list {
for order := 0; order < 8; order++ {
x := 1 << uint(order)
ret := b & byte(x)
if ret > 0 {
writer.WriteString(strconv.Itoa(index) + "\n")
}
index++
}
}
writer.Flush()
}
func main() {
start := time.Now() // 処理時間 計測開始
bytes := fromFile("/var/tmp/sample.csv")
writeByteList("/var/tmp/output2.csv", bytes)
fmt.Println(time.Since(start)) // 処理時間 計測完了
}
package main
import (
"bufio"
"fmt"
"log"
"os"
"sort"
"strconv"
"time"
)
// エラー共通処理
func failOnError(err error) {
if err != nil {
log.Fatal("Error:", err)
}
}
// ファイルから整数を読み取りint配列を返す
func fromFile(filePath string) []int {
f, err := os.Open(filePath)
failOnError(err)
defer f.Close()
lines := make([]int, 0)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
num, _ := strconv.Atoi(scanner.Text())
lines = append(lines, num)
}
if err := scanner.Err(); err != nil {
failOnError(err)
}
return lines
}
// int配列を\n区切りでファイル出力する
func writeIntList(path string, list []int) {
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
failOnError(err)
defer f.Close()
var writer *bufio.Writer
writer = bufio.NewWriter(f)
for _, v := range list {
writer.WriteString(strconv.Itoa(v) + "\n")
}
writer.Flush()
}
func main() {
start := time.Now() // 処理時間 計測開始
lines := fromFile("/var/tmp/sample.csv")
sort.Sort(sort.IntSlice(lines)) // Int配列の標準ソートを実施
writeIntList("/var/tmp/output.csv", lines)
fmt.Println(time.Since(start)) // 処理時間 計測完了
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment