CS 245 - Programming Languages

Lab 5

Go packages

This lab is mostly a review of stuff you have already seen, but not used much in Go. In particular, several packages containing useful stuff that is not a part of the language.

Command Line Args

Recall that to get the command line args in Go, you look at the Args variable in the os package, as is illustrated in the following very short program.
package main
import (
    "fmt"
    "os"
)

func main() {
    fmt.Println(os.Args)
}

String conversion

strconv.Atoi() converts a string containing a number to an int. It returns two values, the number itself, and an error value in case there it was unable to convert the string into an int. The error value returned is nil if successful. The program below tests to see if err is nil before printing the value of the integer command line argument. For instance:
package main
import ( "fmt"
         "strconv"
)
func main() {
	v1,err1 := strconv.Atoi("3")
	if err1==nil {
		fmt.Printf("%d\n", v1)
	}
	v2,e2 := strconv.Atoi("this fails")
	if e2==nil {
		fmt.Printf("%d\n", v2)
	} else {
		fmt.Printf("ERR: %v\n", e2)
	}
}

Random Numbers

A random number generator can be perceived of as consisting of two parts: a very long array of random numbers and a pointer to the current location in the array. (It does not work this way, but it is a useful metaphor.) When you get a random number, the function returns the value at the current position in the very long array and increments the position.

So, when you want a random number, you first have to create the array and set where in the array you want to read. In Go, this requires two commands as shown in the following little example. Once those two commands have been executed, you use the thing returned to actually get random numbers. Note that if you do the exact same thing to create the array and choose a location in that array, then you will get the exact same sequence of random numbers. For this reason, it is common why you want reasonably random numbers to create the array and set the position using the current system clock time (as shown below).
package main
import (
	"fmt"
	"math/rand"
	"time"
)
func main() {
	s1 := rand.NewSource(time.Now().UnixNano())
	r1 := rand.New(s1)
	fmt.Printf("%d\n", r1.Intn(100))
}

Exercise

Collecting Cards in Candy

A candy company wishes to run a promotion in the next quarter. Every candy wrapper will contain a picture of a player from the Women's National Soccer Team. There are 28 players on the roster, plus 7 coaches, making a total of 35 pictures. Pictures will be randomly inserted in each candy wrapper. The company hopes that kids buying their candy will engage in collecting all 35 pictures and placing them in a picture album (sold separately by the company). Each picture will carry a unique number (from 0..34).

Before running with the idea the company wants to examine how this promotion might improve sales of its candy.

Write a program in Go that performs a simulation to determine the number of candies a kid would have to purchase in order to collect all 35 cards. Your program should input the number of pictures (i.e., 35) on the command line. Further, your program should assume that an equal of number of cards are printed and that a sufficient number are printed so that getting one instance of a card has no effect on the probability of getting another instance that same card.
$ go run collector.go 35
The program will print out the expected number of candies (XXX) that kids will purchase to collect all 35 cards. Here is a possible design:
  1. Write a function collect(c) that will perform a simulation of collecting c cards. It will return the total number of candies bought in order to collect all 35 cards.
  2. Once written, you can use collect(c) to perform several trials (for instance one million, and keep track of the number of candies bought
                n = Number of cards to collect
                trials = 1000000
                sum = 0
                do trials times: 
                   sum = sum + collect(n)
                output sum/trials 
                
    as the average number of candies to buy in order to collect n cards. As the number of trials increases, the data will start to converge on a good estimate of the expected number of candies a kid would have to buy. Suggestion: write your program in a way such that it runs correctly but possibly rather slowly (ie do not worry about efficiency.) Once your program is running correctly think about efficiency; one million trials of a slow program could take quite a long time. (In particular, the biggest gain in efficiency of the program will be to to require O(1) time to calculate the number of distinct cards seen rather than O(m) where m is the number of distinct cards.)
  3. Run the program with 1,000,000 trials to compute the number of candies required to be bought in order to collect 35, 100 pictures, and 500 pictures.

What to hand in

You candy card program. As far as you get in 80 minutes. Do not spend more than 80 minutes on this program. If you have estimates, send those as well.

Send your program to gtowell@brynmawr.edu