Commits

Markus Tzoe committed 096be75

problem b: bottle

Comments (0)

Files changed (3)

+package prism
+
+// problem b
+
+import (
+	"fmt"
+	"math"
+)
+
+type Prism struct {
+	vector    []float64
+	low, high float64
+}
+
+func New(a []float64, x0, x1 float64) *Prism {
+	p := new(Prism)
+	p.vector = initVector(a)
+	p.low = x0
+	p.high = x1
+	return p
+}
+
+func (id *Prism) Volume() float64 {
+	return volume(id.vector, id.low, id.high)
+}
+
+func (id *Prism) Distances(v float64) ([]float64, error) {
+	v0 := id.Volume()
+	if v > v0 {
+		return nil, fmt.Errorf("insufficient volume")
+	}
+	n := int(v0 / v)
+	if n > 8 {
+		n = 8
+	}
+	ds := make([]float64, n)
+	low := id.low
+	for i := 0; i < n; i++ {
+		k := float64(0.0001)
+		for volume(id.vector, low, low+k) < v {
+			k += 0.0001
+		}
+		low += k
+		ds[i] = low - id.low
+	}
+	return ds, nil
+}
+
+func initVector(a []float64) []float64 {
+	m := len(a) // 0 ~ n
+	matrix := make([][]float64, m)
+	for i := 0; i < m; i++ {
+		matrix[i] = make([]float64, m)
+		for j := 0; j < m; j++ {
+			matrix[i][j] = a[i] * a[j]
+		}
+	}
+	vec := make([]float64, 2*m-1)
+	for i := 0; i < 2*m-1; i++ {
+		vec[i] = 0
+		k := i - m + 1
+		if k < 0 {
+			k = 0
+		}
+		j := i - k
+		h := j
+		for k <= h {
+			vec[i] += matrix[k][j]
+			k++
+			j--
+		}
+	}
+	return vec
+}
+
+func volume(vec []float64, x0, x1 float64) float64 {
+	m := len(vec) // 0 ~ 2n+1
+	r := float64(0)
+	var c float64
+	for i := 0; i < m; i++ {
+		c = float64(i + 1)
+		r += vec[i] * (math.Pow(x1, c) - math.Pow(x0, c)) / c
+	}
+	return r * math.Pi
+}

bottle/bottle_test.go

+package prism
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+var _vol_ []string
+var _dis_ []string
+
+func init() {
+	_vol_ = make([]string, 4)
+	_dis_ = make([]string, 4)
+	_vol_[0] = "263.89"
+	_vol_[1] = "263.89"
+	_vol_[2] = "50.00"
+	_vol_[3] = "31.42"
+	_dis_[0] = "0.51 1.06 1.66 2.31 3.02 3.83 4.75 5.87"
+	_dis_[1] = "insufficient volume"
+	_dis_[2] = "2.00 4.00"
+	_dis_[3] = "3.18 6.37 9.55"
+}
+
+func TestVolume(t *testing.T) {
+	file, err := os.Open("sample.txt")
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	defer file.Close()
+	reader := bufio.NewReader(file)
+	var line, out string
+	var p *Prism
+	var a []float64
+	var b []string
+	var x0, x1, inc float64
+	i := 0
+	for {
+		_, err = reader.ReadString('\n')
+		if err != nil {
+			break
+		}
+		line, _ = reader.ReadString('\n')
+		b = strings.Fields(line)
+		a = make([]float64, len(b))
+		for i := 0; i < len(b); i++ {
+			a[i], _ = strconv.ParseFloat(b[i], 64)
+		}
+		line, _ = reader.ReadString('\n')
+		b = strings.Fields(line)
+		x0, _ = strconv.ParseFloat(b[0], 64)
+		x1, _ = strconv.ParseFloat(b[1], 64)
+		inc, _ = strconv.ParseFloat(b[2], 64)
+		p = New(a, x0, x1)
+		out = fmt.Sprintf("%.2f", p.Volume())
+		if out != _vol_[i] {
+			t.Errorf("Volume mismatch: got \"%v\", expected \"%v\"\n", out, _vol_[i])
+		}
+		fmt.Printf("Case %d: %s\n", i, out)
+		ds, err := p.Distances(inc)
+		if err != nil {
+			out = fmt.Sprintf("%s", err)
+		} else {
+			out = fmt.Sprintf("%.2f", ds)
+			out = out[1 : len(out)-1]
+		}
+		if out != _dis_[i] {
+			t.Errorf("Distance mismatch: got \"%v\", expected \"%v\"\n", out, _dis_[i])
+		}
+		fmt.Println(out)
+		i++
+	}
+	return
+}

bottle/sample.txt

+1
+4.0 -0.25
+0.0 12.0 25
+1
+4.0 -0.25
+0.0 12.0 300
+0
+1.7841241161782
+5.0 10.0 20
+0
+1.0
+0.0 10.0 10