| /* |
| 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 ( |
| "flag"; |
| "fmt"; |
| "os"; |
| ) |
| |
| var n = flag.Int("n", 600, "count") |
| |
| type Color int |
| |
| const ( |
| blue Color = iota; |
| red; |
| yellow; |
| ) |
| |
| func (c Color) String() string { |
| return []string{"blue", "red", "yellow"}[c] |
| } |
| |
| func complement(c1, c2 Color) Color { |
| switch c1 << 2 | c2 { |
| case blue << 2 | blue: |
| return blue |
| case blue << 2 | red: |
| return yellow |
| case blue << 2 | yellow: |
| return red |
| case red << 2 | blue: |
| return yellow |
| case red << 2 | red: |
| return red |
| case red << 2 | yellow: |
| return blue |
| case yellow << 2 | blue: |
| return red |
| case yellow << 2 | red: |
| return blue |
| case yellow << 2 | yellow: |
| return yellow |
| } |
| fmt.Println("invalid colors", c1, c2); |
| os.Exit(2); |
| return 0 |
| } |
| |
| func printColors(c1, c2 Color) { |
| fmt.Printf("%s + %s -> %s\n", c1, c2, complement(c1, c2)); |
| } |
| |
| func printColorTable() { |
| printColors(blue, blue); |
| printColors(blue, red); |
| printColors(blue, yellow); |
| printColors(red, blue); |
| printColors(red, red); |
| printColors(red, yellow); |
| printColors(yellow, blue); |
| printColors(yellow, red); |
| printColors(yellow, yellow); |
| } |
| |
| type Referee struct { |
| rendezCount int; |
| cham []*Chameneos; |
| rendez chan *Chameneos; |
| done chan int; |
| } |
| |
| func NewReferee() *Referee { |
| ref := new(Referee); |
| ref.cham = make([]*Chameneos, 0, 100); |
| ref.rendez = make(chan *Chameneos); |
| ref.done = make(chan int); |
| go ref.Serve(); |
| return ref; |
| } |
| |
| func (ref *Referee) Serve() { |
| for i := 0; i < *n; i++ { |
| c1 := <-ref.rendez; |
| c2 := <-ref.rendez; |
| c1.col, c2.col = complement(c1.col, c2.col), complement(c2.col, c1.col); |
| c1.rendez <- c2; |
| c2.rendez <- c1; |
| } |
| for i := 0; i < len(ref.cham); i++ { |
| c := <-ref.rendez; |
| c.rendez <- nil; |
| } |
| ref.done <- 1; |
| } |
| |
| func (ref *Referee) Add(ch *Chameneos) { |
| n := len(ref.cham); |
| ref.cham = ref.cham[0:n+1]; |
| ref.cham[n] = ch; |
| } |
| |
| type Chameneos struct { |
| index int; |
| col Color; |
| rendez chan *Chameneos; |
| count int; |
| same int; |
| ref *Referee; |
| } |
| |
| func (c *Chameneos) Init(index int, ref *Referee, col Color) *Chameneos { |
| c.index = index; |
| c.ref = ref; |
| c.col = col; |
| c.rendez = make(chan *Chameneos); |
| go c.Serve(); |
| return c; |
| } |
| |
| func (c *Chameneos) Serve() { |
| for { |
| c.ref.rendez <- c; |
| c1 := <- c.rendez; |
| if c1 == nil { |
| break |
| } |
| if c1.index == c.index { |
| c.same++ |
| } |
| c.count++; |
| } |
| } |
| |
| func play(ref *Referee, color []Color) { |
| cham := make([]Chameneos, len(color)); |
| for i, c := range color { |
| fmt.Printf(" %s", c); |
| ref.Add(cham[i].Init(i, ref, c)); |
| } |
| fmt.Printf("\n"); |
| <-ref.done; |
| total := 0; |
| for _, c := range cham { |
| total += c.count; |
| fmt.Printf("%d %s\n", c.count, say(c.same)); |
| } |
| fmt.Printf("%s\n", say(total)); |
| } |
| |
| var words = []string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"} |
| |
| func say(n int) string { |
| digits := fmt.Sprint(n); |
| s := ""; |
| for _, c := range digits { |
| s += " " + words[c-'0']; |
| } |
| return s; |
| } |
| |
| func main() { |
| flag.Parse(); |
| printColorTable(); |
| fmt.Print("\n"); |
| play(NewReferee(), []Color{blue, red, yellow}); |
| fmt.Print("\n"); |
| play(NewReferee(), []Color{blue, red, yellow, red, yellow, blue, red, yellow, red, blue}); |
| } |