コード例 #1
0
ファイル: input_test.go プロジェクト: shields/saseat
func TestReadGuests(t *testing.T) {
	g, err := saseat.ReadGuests(strings.NewReader(guestsFile))
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(g, expectedGuests) {
		t.Errorf("got: %q\nwant: %q\n", g, expectedGuests)
	}
}
コード例 #2
0
ファイル: main.go プロジェクト: shields/saseat
func main() {
	rand.Seed(time.Now().UnixNano())

	flag.Parse()
	if *guestFlag == "" || *prefFlag == "" || *tableFlag == "" {
		fmt.Fprintln(os.Stderr, "all flags are required")
		os.Exit(2)
	}

	// Load guests file.
	f, err := os.Open(*guestFlag)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	guests, err := saseat.ReadGuests(f)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	// Load prefs file.
	f, err = os.Open(*prefFlag)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	prefs, err := saseat.ReadPrefs(f)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if err = prefs.CheckGuests(guests); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	// Create tables, packing the guests to them in random order.
	var tables []saseat.Table
	perm := rand.Perm(len(guests))
	seated := 0
	for _, s := range strings.Split(*tableFlag, ",") {
		capacity, err := strconv.ParseInt(s, 0, 10)
		if err != nil {
			fmt.Fprintln(os.Stderr, "bad table capacity %q: %v", s, err)
			os.Exit(1)
		}
		if capacity <= 0 || capacity%2 != 0 {
			fmt.Fprintln(os.Stderr, "only positive even table sizes supported")
			os.Exit(1)
		}
		t := saseat.NewTable(int(capacity))
		for i := 0; i < int(capacity/2) && seated < len(guests); i++ {
			t.Left[i] = guests[perm[seated]]
			seated++
		}
		for i := 0; i < int(capacity/2) && seated < len(guests); i++ {
			t.Right[i] = guests[perm[seated]]
			seated++
		}
		t.Rescore(prefs)
		tables = append(tables, t)
	}
	if seated != len(guests) {
		fmt.Fprintf(os.Stderr, "seats for only %v of %v guests", seated, len(guests))
		os.Exit(1)
	}

	// Let's anneal!
	temp := 250.0
	reported := time.Now()
	iter := 1
	for ; ; iter++ {
		// Cooling.
		if iter%1000000 == 0 {
			temp *= 0.98
		}

		if time.Now().Sub(reported) > 1*time.Second {
			report(tables)
			fmt.Printf("Iteration %d, temperature %.1f\n\n\n", iter, temp)
			reported = time.Now()
		}

		// Spend more time trying to optimize within tables instead of
		// swapping people around the room.
		if rand.Float64() > 0.1 {
			i := rand.Intn(len(tables))
			t := copyTable(&tables[i])
			t.Swap(&t, 2)
			t.Rescore(prefs)
			if accept(t.Score, tables[i].Score, temp) {
				tables[i] = t
			}
		} else {
			i1 := rand.Intn(len(tables))
			i2 := rand.Intn(len(tables))
			if i1 == i2 {
				continue
			}
			t1 := copyTable(&tables[i1])
			t2 := copyTable(&tables[i2])
			t1.Swap(&t2, -1)
			t1.Rescore(prefs)
			t2.Rescore(prefs)
			if accept(t1.Score+t2.Score, tables[i1].Score+tables[i2].Score, temp) {
				tables[i1] = t1
				tables[i2] = t2
			}
		}
	}

	report(tables)
}