exalysis icon indicating copy to clipboard operation
exalysis copied to clipboard

Valid solution fails to compile under Exalysis

Open bitfield opened this issue 6 years ago • 0 comments

Solution 17070203b36548d8aa7b2cd0e1c24802 compiles and passes tests when you run go test in the solution, but running Exalysis gives a compilation failure:

go test
PASS
ok      _/Users/john/git/bitfield/exercism/users/ksimon1/go/robot-name  0.006s

exalysis

Hi there!

This looks very good!

Could you have a look at the following point so I can approve the solution?
- Unfortunately, this solution does not compile correctly. Did you run the tests? Maybe you accidentally submitted an incomplete solution? If you're having trouble getting your program to compile, you can always ask me for help!

Here's the source:

//Package robotname implements functions for creating robot
package robotname

import (
	"fmt"
	"math/rand"
	"time"
)

//Robot hold informations about robot
type Robot struct {
	name string
}

var robotNamesList = make(map[string]bool)

const (
	letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	//26 letters - len(11010) == 5
	letterIDBits = 5
	//binary masK 11111
	letterIDMask = 1<<letterIDBits - 1
	//how many times we can iterate in 63 bit number with letter binary mask
	maxLettersMask = 63 % letterIDBits
	numbers        = "0123456789"
	//10 numbers - len(1010) == 4
	numbersIDBits = 4
	//binary mask 1111
	numberIDMask = 1<<numbersIDBits - 1
	//how many times we can iterate in 63 bit number with number binary mask
	maxNumbersMask  = 63 % numbersIDBits
	numberOfLetters = 2
	numberOfNumbers = 3
)

//Name returns robot name
//if name doesn't exist, it generates new one
func (r *Robot) Name() (string, error) {
	if r.name == "" {
		var err error
		r.name, err = getNewName()
		if err != nil {
			return "", err
		}
	}
	return r.name, nil
}

//Reset resets robot name
func (r *Robot) Reset() string {
	r.name = ""
	return r.name
}

//getNewName returns new random name. If limit of name is reached returns error
func getNewName() (string, error) {
	name := ""
	for {
		if len(robotNamesList) == maxNames {
			return "", fmt.Errorf("Max number of names reached")
		}
		name = generateRandomName()
		if ok := robotNamesList[name]; !ok {
			robotNamesList[name] = true
			break
		}
	}
	return name, nil
}

//new pseudo-random Source seeded with the given value of time.Now() in unix timestamp
var src = rand.NewSource(time.Now().UnixNano())

//generateRandomName generate new name in format AA111
func generateRandomName() string {
	b := make([]byte, 5)
	var cache int64
	remain := 0
	i := numberOfLetters - 1
	for i >= 0 {
		//if we exhaust 63 bit random number, create new one
		if remain == 0 {
			cache, remain = rand.Int63(), maxLettersMask
		}
		//if bitwise AND operation is in interval
		if id := int(cache & letterIDMask); id < len(letters) {
			//save new letter
			b[i] = letters[id]
			i--
		}
		//shift random number
		cache >>= letterIDBits
		remain--
	}
	//calculate if we can still use old random number
	remain = (remain * letterIDBits) % numbersIDBits
	i = numberOfNumbers - 1

	for i >= 0 {
		//if we exhaust 63 bit random number, create new one
		if remain == 0 {
			cache, remain = rand.Int63(), maxNumbersMask
		}
		//if bitwise AND operation is in interval
		if id := int(cache & numberIDMask); id < len(numbers) {
			//save new letter
			b[i+2] = numbers[id]
			i--
		}
		//shift random number
		cache >>= letterIDBits
		remain--
	}

	return string(b)
}

bitfield avatar Feb 23 '19 17:02 bitfield