whatcanGOwrong
This commit is contained in:
+183
@@ -0,0 +1,183 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
/*
|
||||
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"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
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 n = 600
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if flag.NArg() > 0 {
|
||||
n, _ = strconv.Atoi(flag.Arg(0))
|
||||
}
|
||||
|
||||
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]])
|
||||
}
|
||||
}
|
||||
fmt.Print("\n")
|
||||
|
||||
pallmall([]int{blue, red, yellow})
|
||||
pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue})
|
||||
}
|
||||
|
||||
func pallmall(cols []int) {
|
||||
|
||||
// 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.Printf("%v%v\n", result.met, spell(result.same, true))
|
||||
}
|
||||
fmt.Printf("%v\n\n", 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 no more meetings left, 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]
|
||||
}
|
||||
Reference in New Issue
Block a user