mirror of
https://github.com/golang/go
synced 2024-11-22 12:14:42 -07:00
9f17353250
based on suggestion from arvindht@gmail.com R=r, rsc, r1 https://golang.org/cl/157091
177 lines
5.0 KiB
Go
177 lines
5.0 KiB
Go
/*
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of "The Computer Language Benchmarks Game" nor the
|
|
name of "The Computer Language Shootout Benchmarks" nor the names of
|
|
its contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/* The Computer Language Benchmarks Game
|
|
* http://shootout.alioth.debian.org/
|
|
*
|
|
* contributed by The Go Authors.
|
|
*/
|
|
|
|
package main
|
|
|
|
import "fmt"
|
|
import "flag"
|
|
|
|
const (
|
|
blue = iota;
|
|
red;
|
|
yellow;
|
|
ncol;
|
|
)
|
|
|
|
var complement = [...]int{
|
|
red | red<<2: red,
|
|
red | yellow<<2: blue,
|
|
red | blue<<2: yellow,
|
|
yellow | red<<2: blue,
|
|
yellow | yellow<<2: yellow,
|
|
yellow | blue<<2: red,
|
|
blue | red<<2: yellow,
|
|
blue | yellow<<2: red,
|
|
blue | blue<<2: blue,
|
|
}
|
|
|
|
var colname = [...]string{
|
|
blue: "blue",
|
|
red: "red",
|
|
yellow: "yellow",
|
|
}
|
|
|
|
// information about the current state of a creature.
|
|
type info struct {
|
|
colour int; // creature's current colour.
|
|
name int; // creature's name.
|
|
}
|
|
|
|
// exclusive access data-structure kept inside meetingplace.
|
|
// if mate is nil, it indicates there's no creature currently waiting;
|
|
// otherwise the creature's info is stored in info, and
|
|
// it is waiting to receive its mate's information on the mate channel.
|
|
type rendez struct {
|
|
n int; // current number of encounters.
|
|
mate chan<- info; // creature waiting when non-nil.
|
|
info info; // info about creature waiting.
|
|
}
|
|
|
|
// result sent by each creature at the end of processing.
|
|
type result struct {
|
|
met int;
|
|
same int;
|
|
}
|
|
|
|
var np = flag.Int("n", 600, "count")
|
|
var N int
|
|
|
|
func main() {
|
|
flag.Parse();
|
|
N = *np;
|
|
|
|
for c0 := 0; c0 < ncol; c0++ {
|
|
for c1 := 0; c1 < ncol; c1++ {
|
|
fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]])
|
|
}
|
|
}
|
|
|
|
pallmall([]int{blue, red, yellow});
|
|
pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue});
|
|
}
|
|
|
|
func pallmall(cols []int) {
|
|
fmt.Print("\n");
|
|
|
|
// invariant: meetingplace always contains a value unless a creature
|
|
// is currently dealing with it (whereupon it must put it back).
|
|
meetingplace := make(chan rendez, 1);
|
|
meetingplace <- rendez{n: 0};
|
|
|
|
ended := make(chan result);
|
|
msg := "";
|
|
for i, col := range cols {
|
|
go creature(info{col, i}, meetingplace, ended);
|
|
msg += " " + colname[col];
|
|
}
|
|
fmt.Println(msg);
|
|
tot := 0;
|
|
// wait for all results
|
|
for _ = range (cols) {
|
|
result := <-ended;
|
|
tot += result.met;
|
|
fmt.Println(result.met, spell(result.same, true));
|
|
}
|
|
fmt.Println(spell(tot, true));
|
|
}
|
|
|
|
// in this function, variables ending in 0 refer to the local creature,
|
|
// variables ending in 1 to the creature we've met.
|
|
func creature(info0 info, meetingplace chan rendez, ended chan result) {
|
|
c0 := make(chan info);
|
|
met := 0;
|
|
same := 0;
|
|
for {
|
|
var othername int;
|
|
// get access to rendez data and decide what to do.
|
|
switch r := <-meetingplace; {
|
|
case r.n >= N:
|
|
// if more than N meetings, then send our result data and exit.
|
|
meetingplace <- rendez{n: r.n};
|
|
ended <- result{met, same};
|
|
return;
|
|
case r.mate == nil:
|
|
// no creature waiting; wait for someone to meet us,
|
|
// get their info and send our info in reply.
|
|
meetingplace <- rendez{n: r.n, info: info0, mate: c0};
|
|
info1 := <-c0;
|
|
othername = info1.name;
|
|
info0.colour = complement[info0.colour|info1.colour<<2];
|
|
default:
|
|
// another creature is waiting for us with its info;
|
|
// increment meeting count,
|
|
// send them our info in reply.
|
|
r.n++;
|
|
meetingplace <- rendez{n: r.n, mate: nil};
|
|
r.mate <- info0;
|
|
othername = r.info.name;
|
|
info0.colour = complement[info0.colour|r.info.colour<<2];
|
|
}
|
|
if othername == info0.name {
|
|
same++
|
|
}
|
|
met++;
|
|
}
|
|
}
|
|
|
|
var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
|
|
|
|
func spell(n int, required bool) string {
|
|
if n == 0 && !required {
|
|
return ""
|
|
}
|
|
return spell(n/10, false) + " " + digits[n%10];
|
|
}
|