go.dev: fix go playground on homepage
Copied the playground example files to the go.dev content directory to fix the homepage playground. This works locally because requests to /doc are passed to the golang.org content directory but breaks on app engine when requests go to go.dev/doc. Change-Id: I858b7fca905bbacd0acbf8ea33d1a5188fbd3773 Reviewed-on: https://go-review.googlesource.com/c/website/+/359214 Trust: Jamal Carvalho <jamal@golang.org> Run-TryBot: Jamal Carvalho <jamal@golang.org> Reviewed-by: Julie Qiu <julie@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Website-Publish: DO NOT USE <dmitshur@google.com>
This commit is contained in:
Родитель
714a425135
Коммит
103d89b8bc
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// fib returns a function that returns
|
||||
// successive Fibonacci numbers.
|
||||
func fib() func() int {
|
||||
a, b := 0, 1
|
||||
return func() int {
|
||||
a, b = b, a+b
|
||||
return a
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
f := fib()
|
||||
// Function calls are evaluated left-to-right.
|
||||
fmt.Println(f(), f(), f(), f(), f())
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// You can edit this code!
|
||||
// Click here and start typing.
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello, 世界")
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// An implementation of Conway's Game of Life.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Field represents a two-dimensional field of cells.
|
||||
type Field struct {
|
||||
s [][]bool
|
||||
w, h int
|
||||
}
|
||||
|
||||
// NewField returns an empty field of the specified width and height.
|
||||
func NewField(w, h int) *Field {
|
||||
s := make([][]bool, h)
|
||||
for i := range s {
|
||||
s[i] = make([]bool, w)
|
||||
}
|
||||
return &Field{s: s, w: w, h: h}
|
||||
}
|
||||
|
||||
// Set sets the state of the specified cell to the given value.
|
||||
func (f *Field) Set(x, y int, b bool) {
|
||||
f.s[y][x] = b
|
||||
}
|
||||
|
||||
// Alive reports whether the specified cell is alive.
|
||||
// If the x or y coordinates are outside the field boundaries they are wrapped
|
||||
// toroidally. For instance, an x value of -1 is treated as width-1.
|
||||
func (f *Field) Alive(x, y int) bool {
|
||||
x += f.w
|
||||
x %= f.w
|
||||
y += f.h
|
||||
y %= f.h
|
||||
return f.s[y][x]
|
||||
}
|
||||
|
||||
// Next returns the state of the specified cell at the next time step.
|
||||
func (f *Field) Next(x, y int) bool {
|
||||
// Count the adjacent cells that are alive.
|
||||
alive := 0
|
||||
for i := -1; i <= 1; i++ {
|
||||
for j := -1; j <= 1; j++ {
|
||||
if (j != 0 || i != 0) && f.Alive(x+i, y+j) {
|
||||
alive++
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return next state according to the game rules:
|
||||
// exactly 3 neighbors: on,
|
||||
// exactly 2 neighbors: maintain current state,
|
||||
// otherwise: off.
|
||||
return alive == 3 || alive == 2 && f.Alive(x, y)
|
||||
}
|
||||
|
||||
// Life stores the state of a round of Conway's Game of Life.
|
||||
type Life struct {
|
||||
a, b *Field
|
||||
w, h int
|
||||
}
|
||||
|
||||
// NewLife returns a new Life game state with a random initial state.
|
||||
func NewLife(w, h int) *Life {
|
||||
a := NewField(w, h)
|
||||
for i := 0; i < (w * h / 4); i++ {
|
||||
a.Set(rand.Intn(w), rand.Intn(h), true)
|
||||
}
|
||||
return &Life{
|
||||
a: a, b: NewField(w, h),
|
||||
w: w, h: h,
|
||||
}
|
||||
}
|
||||
|
||||
// Step advances the game by one instant, recomputing and updating all cells.
|
||||
func (l *Life) Step() {
|
||||
// Update the state of the next field (b) from the current field (a).
|
||||
for y := 0; y < l.h; y++ {
|
||||
for x := 0; x < l.w; x++ {
|
||||
l.b.Set(x, y, l.a.Next(x, y))
|
||||
}
|
||||
}
|
||||
// Swap fields a and b.
|
||||
l.a, l.b = l.b, l.a
|
||||
}
|
||||
|
||||
// String returns the game board as a string.
|
||||
func (l *Life) String() string {
|
||||
var buf bytes.Buffer
|
||||
for y := 0; y < l.h; y++ {
|
||||
for x := 0; x < l.w; x++ {
|
||||
b := byte(' ')
|
||||
if l.a.Alive(x, y) {
|
||||
b = '*'
|
||||
}
|
||||
buf.WriteByte(b)
|
||||
}
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func main() {
|
||||
l := NewLife(40, 15)
|
||||
for i := 0; i < 300; i++ {
|
||||
l.Step()
|
||||
fmt.Print("\x0c", l) // Clear screen and print field.
|
||||
time.Sleep(time.Second / 30)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// Peano integers are represented by a linked
|
||||
// list whose nodes contain no data
|
||||
// (the nodes are the data).
|
||||
// http://en.wikipedia.org/wiki/Peano_axioms
|
||||
|
||||
// This program demonstrates that Go's automatic
|
||||
// stack management can handle heavily recursive
|
||||
// computations.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Number is a pointer to a Number
|
||||
type Number *Number
|
||||
|
||||
// The arithmetic value of a Number is the
|
||||
// count of the nodes comprising the list.
|
||||
// (See the count function below.)
|
||||
|
||||
// -------------------------------------
|
||||
// Peano primitives
|
||||
|
||||
func zero() *Number {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isZero(x *Number) bool {
|
||||
return x == nil
|
||||
}
|
||||
|
||||
func add1(x *Number) *Number {
|
||||
e := new(Number)
|
||||
*e = x
|
||||
return e
|
||||
}
|
||||
|
||||
func sub1(x *Number) *Number {
|
||||
return *x
|
||||
}
|
||||
|
||||
func add(x, y *Number) *Number {
|
||||
if isZero(y) {
|
||||
return x
|
||||
}
|
||||
return add(add1(x), sub1(y))
|
||||
}
|
||||
|
||||
func mul(x, y *Number) *Number {
|
||||
if isZero(x) || isZero(y) {
|
||||
return zero()
|
||||
}
|
||||
return add(mul(x, sub1(y)), x)
|
||||
}
|
||||
|
||||
func fact(n *Number) *Number {
|
||||
if isZero(n) {
|
||||
return add1(zero())
|
||||
}
|
||||
return mul(fact(sub1(n)), n)
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Helpers to generate/count Peano integers
|
||||
|
||||
func gen(n int) *Number {
|
||||
if n > 0 {
|
||||
return add1(gen(n - 1))
|
||||
}
|
||||
return zero()
|
||||
}
|
||||
|
||||
func count(x *Number) int {
|
||||
if isZero(x) {
|
||||
return 0
|
||||
}
|
||||
return count(sub1(x)) + 1
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Print i! for i in [0,9]
|
||||
|
||||
func main() {
|
||||
for i := 0; i <= 9; i++ {
|
||||
f := count(fact(gen(i)))
|
||||
fmt.Println(i, "! =", f)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Concurrent computation of pi.
|
||||
// See https://goo.gl/la6Kli.
|
||||
//
|
||||
// This demonstrates Go's ability to handle
|
||||
// large numbers of concurrent processes.
|
||||
// It is an unreasonable way to calculate pi.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(pi(5000))
|
||||
}
|
||||
|
||||
// pi launches n goroutines to compute an
|
||||
// approximation of pi.
|
||||
func pi(n int) float64 {
|
||||
ch := make(chan float64)
|
||||
for k := 0; k < n; k++ {
|
||||
go term(ch, float64(k))
|
||||
}
|
||||
f := 0.0
|
||||
for k := 0; k < n; k++ {
|
||||
f += <-ch
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func term(ch chan float64, k float64) {
|
||||
ch <- 4 * math.Pow(-1, k) / (2*k + 1)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// A concurrent prime sieve
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Send the sequence 2, 3, 4, ... to channel 'ch'.
|
||||
func Generate(ch chan<- int) {
|
||||
for i := 2; ; i++ {
|
||||
ch <- i // Send 'i' to channel 'ch'.
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the values from channel 'in' to channel 'out',
|
||||
// removing those divisible by 'prime'.
|
||||
func Filter(in <-chan int, out chan<- int, prime int) {
|
||||
for {
|
||||
i := <-in // Receive value from 'in'.
|
||||
if i%prime != 0 {
|
||||
out <- i // Send 'i' to 'out'.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The prime sieve: Daisy-chain Filter processes.
|
||||
func main() {
|
||||
ch := make(chan int) // Create a new channel.
|
||||
go Generate(ch) // Launch Generate goroutine.
|
||||
for i := 0; i < 10; i++ {
|
||||
prime := <-ch
|
||||
fmt.Println(prime)
|
||||
ch1 := make(chan int)
|
||||
go Filter(ch, ch1, prime)
|
||||
ch = ch1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
// This program solves the (English) peg
|
||||
// solitaire board game.
|
||||
// http://en.wikipedia.org/wiki/Peg_solitaire
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const N = 11 + 1 // length of a row (+1 for \n)
|
||||
|
||||
// The board must be surrounded by 2 illegal
|
||||
// fields in each direction so that move()
|
||||
// doesn't need to check the board boundaries.
|
||||
// Periods represent illegal fields,
|
||||
// ● are pegs, and ○ are holes.
|
||||
|
||||
var board = []rune(
|
||||
`...........
|
||||
...........
|
||||
....●●●....
|
||||
....●●●....
|
||||
..●●●●●●●..
|
||||
..●●●○●●●..
|
||||
..●●●●●●●..
|
||||
....●●●....
|
||||
....●●●....
|
||||
...........
|
||||
...........
|
||||
`)
|
||||
|
||||
// center is the position of the center hole if
|
||||
// there is a single one; otherwise it is -1.
|
||||
var center int
|
||||
|
||||
func init() {
|
||||
n := 0
|
||||
for pos, field := range board {
|
||||
if field == '○' {
|
||||
center = pos
|
||||
n++
|
||||
}
|
||||
}
|
||||
if n != 1 {
|
||||
center = -1 // no single hole
|
||||
}
|
||||
}
|
||||
|
||||
var moves int // number of times move is called
|
||||
|
||||
// move tests if there is a peg at position pos that
|
||||
// can jump over another peg in direction dir. If the
|
||||
// move is valid, it is executed and move returns true.
|
||||
// Otherwise, move returns false.
|
||||
func move(pos, dir int) bool {
|
||||
moves++
|
||||
if board[pos] == '●' && board[pos+dir] == '●' && board[pos+2*dir] == '○' {
|
||||
board[pos] = '○'
|
||||
board[pos+dir] = '○'
|
||||
board[pos+2*dir] = '●'
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// unmove reverts a previously executed valid move.
|
||||
func unmove(pos, dir int) {
|
||||
board[pos] = '●'
|
||||
board[pos+dir] = '●'
|
||||
board[pos+2*dir] = '○'
|
||||
}
|
||||
|
||||
// solve tries to find a sequence of moves such that
|
||||
// there is only one peg left at the end; if center is
|
||||
// >= 0, that last peg must be in the center position.
|
||||
// If a solution is found, solve prints the board after
|
||||
// each move in a backward fashion (i.e., the last
|
||||
// board position is printed first, all the way back to
|
||||
// the starting board position).
|
||||
func solve() bool {
|
||||
var last, n int
|
||||
for pos, field := range board {
|
||||
// try each board position
|
||||
if field == '●' {
|
||||
// found a peg
|
||||
for _, dir := range [...]int{-1, -N, +1, +N} {
|
||||
// try each direction
|
||||
if move(pos, dir) {
|
||||
// a valid move was found and executed,
|
||||
// see if this new board has a solution
|
||||
if solve() {
|
||||
unmove(pos, dir)
|
||||
fmt.Println(string(board))
|
||||
return true
|
||||
}
|
||||
unmove(pos, dir)
|
||||
}
|
||||
}
|
||||
last = pos
|
||||
n++
|
||||
}
|
||||
}
|
||||
// tried each possible move
|
||||
if n == 1 && (center < 0 || last == center) {
|
||||
// there's only one peg left
|
||||
fmt.Println(string(board))
|
||||
return true
|
||||
}
|
||||
// no solution found for this board
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
if !solve() {
|
||||
fmt.Println("no solution found")
|
||||
}
|
||||
fmt.Println(moves, "moves tried")
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// Go's concurrency primitives make it easy to
|
||||
// express concurrent concepts, such as
|
||||
// this binary tree comparison.
|
||||
//
|
||||
// Trees may be of different shapes,
|
||||
// but have the same contents. For example:
|
||||
//
|
||||
// 4 6
|
||||
// 2 6 4 7
|
||||
// 1 3 5 7 2 5
|
||||
// 1 3
|
||||
//
|
||||
// This program compares a pair of trees by
|
||||
// walking each in its own goroutine,
|
||||
// sending their contents through a channel
|
||||
// to a third goroutine that compares them.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
// A Tree is a binary tree with integer values.
|
||||
type Tree struct {
|
||||
Left *Tree
|
||||
Value int
|
||||
Right *Tree
|
||||
}
|
||||
|
||||
// Walk traverses a tree depth-first,
|
||||
// sending each Value on a channel.
|
||||
func Walk(t *Tree, ch chan int) {
|
||||
if t == nil {
|
||||
return
|
||||
}
|
||||
Walk(t.Left, ch)
|
||||
ch <- t.Value
|
||||
Walk(t.Right, ch)
|
||||
}
|
||||
|
||||
// Walker launches Walk in a new goroutine,
|
||||
// and returns a read-only channel of values.
|
||||
func Walker(t *Tree) <-chan int {
|
||||
ch := make(chan int)
|
||||
go func() {
|
||||
Walk(t, ch)
|
||||
close(ch)
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// Compare reads values from two Walkers
|
||||
// that run simultaneously, and returns true
|
||||
// if t1 and t2 have the same contents.
|
||||
func Compare(t1, t2 *Tree) bool {
|
||||
c1, c2 := Walker(t1), Walker(t2)
|
||||
for {
|
||||
v1, ok1 := <-c1
|
||||
v2, ok2 := <-c2
|
||||
if !ok1 || !ok2 {
|
||||
return ok1 == ok2
|
||||
}
|
||||
if v1 != v2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// New returns a new, random binary tree
|
||||
// holding the values 1k, 2k, ..., nk.
|
||||
func New(n, k int) *Tree {
|
||||
var t *Tree
|
||||
for _, v := range rand.Perm(n) {
|
||||
t = insert(t, (1+v)*k)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func insert(t *Tree, v int) *Tree {
|
||||
if t == nil {
|
||||
return &Tree{nil, v, nil}
|
||||
}
|
||||
if v < t.Value {
|
||||
t.Left = insert(t.Left, v)
|
||||
return t
|
||||
}
|
||||
t.Right = insert(t.Right, v)
|
||||
return t
|
||||
}
|
||||
|
||||
func main() {
|
||||
t1 := New(100, 1)
|
||||
fmt.Println(Compare(t1, New(100, 1)), "Same Contents")
|
||||
fmt.Println(Compare(t1, New(99, 1)), "Differing Sizes")
|
||||
fmt.Println(Compare(t1, New(100, 2)), "Differing Values")
|
||||
fmt.Println(Compare(t1, New(101, 2)), "Dissimilar")
|
||||
}
|
Загрузка…
Ссылка в новой задаче