HackerRank task Sales by Match doesn't pass tests - go

I solved Sales by Match problem in this way:
package main
import (
"fmt"
)
func main() {
var amount int
_, _ = fmt.Scanf("%d", &amount)
pairs := 0
set := make(map[int]bool)
for i := 0; i < amount; i++ {
var number int
_, _ = fmt.Scanf("%d", &number)
if set[number] {
set[number] = false
pairs++
} else {
set[number] = true
}
}
println(pairs)
}
I tested it with the following input:
9
10 20 20 10 10 30 50 10 20
Here's the result:
So, as you can see, everything works fine. But when I run the tests I see the following result:
I don't understand why they are not passed, so, please, can anyone explain what's the problem in my solution? Thanks in advance I would appreciate any help

Change println(pairs) to fmt.Print(pairs)because println writes to stderr and hackerrank looks at stdout for the result.

Related

Why does fmt.Scan() behave in a weird way?

I'm trying to validate the user input. If the user inputs an integer number it works like expected. However, if the user inputs a non-integer string, the variable userTickets gets assigned value 0, but prints Try again! It must be more than zero: many times. To be exact, it prints len(input) times and I don't understand why.
Also tried achieving desired result using fmt.Scanf("%d", &usertickets) but got an identical result.
Why does it behave this way and how can I write a workaround for it?
package main
import "fmt"
func main() {
var remainingTickets uint = 50
var userTickets uint
fmt.Print("Enter the number of tickets you want to purchase: ")
fmt.Scan(&userTickets)
for userTickets > remainingTickets {
fmt.Printf("We only have %v tickets available!\n", remainingTickets)
fmt.Print("Try again! Enter the number of tickets: ")
fmt.Scan(&userTickets)
}
for userTickets == 0 {
fmt.Print("Try again! It must be more than zero: ")
fmt.Scan(&userTickets)
}
fmt.Printf("Remaining tickets: %v\n", remainingTickets-userTickets)
}
Scan is able to determine that the input isn't numeric without reading the entire contents of stdin. This is why you validation logic loops for len(input) when non-numeric. While you can use a Scanner as well (and people do recommend that approach), below is an approach similar to yours. Note that all validation checking is done within a single "for" loop as well:
package main
import (
"fmt"
"strconv"
)
func main() {
var remainingTickets uint64 = 50
fmt.Print("Enter the number of tickets you want to purchase: ")
for {
var userTickets string
fmt.Scanln(&userTickets)
// parse to make sure we get a positive (unsigned) integer
u64, err := strconv.ParseUint(userTickets,10,64)
// make sure it's a postive integer and not equal to zero
if err != nil || u64==0{
fmt.Print("Try again! You must enter a number greater than zero: ")
continue
}
// check to make sure we have enough tickets left
if u64 > remainingTickets {
fmt.Printf("We only have %v tickets available!\n", remainingTickets)
fmt.Print("Try again! Enter the number of tickets: ")
continue
}
// update remaining tickets
remainingTickets -= u64
break
}
fmt.Printf("Remaining tickets: %d\n", remainingTickets)
}

How to increase (or access) Go bleve search engine results?

When I try to make a search query with bleve I always get 10 or less results. How can I increase this limit or make a search between all the data?
Here is code example, where I expect to get 35 results, but getting 10 (ps calc.Rand() function is giving random bytes):
package search
import (
"testing"
"github.com/blevesearch/bleve/v2"
)
func TestSearcher(t *testing.T) {
mapping := bleve.NewIndexMapping()
searcher, _ := bleve.New("search/src", mapping)
for i := 0; i < 35; i++ {
searcher.Index(string(calc.Rand()), "stuff")
}
query := bleve.NewMatchQuery("stuff")
search := bleve.NewSearchRequest(query)
searchRez, _ := searcher.Search(search)
t.Error(len(searchRez.Hits))
}
Result I get:
--- FAIL: TestSearcher (2.33s)
/Users/ ... /search/search_test.go:86: 10
Result I expect:
--- FAIL: TestSearcher (2.33s)
/Users/ ... /search/search_test.go:86: 35
How do I access all the 35 values, that are stored by this index?
Set the field Size on SearchRequest:
Size/From describe how much and which part of the result set to return.
search := bleve.NewSearchRequest(query)
search.Size = 35 // or the page size you want
searchRez, _ := searcher.Search(search)
fmt.Println(len(searchRez.Hits)) // prints 35
or with pagination, you set the field From incrementally based on page size. A contrived example:
count, _ := searcher.DocCount()
for i := 0; i < int(count); i += 10 /* page size */ {
search.From = i
searchRez, _ := searcher.Search(search)
fmt.Println(len(searchRez.Hits)) // prints 10 10 10 5
}

Convert string to int in GO

I am trying to convert a number into a slice of its digit in Go. My code is like this
stn := strconv.Itoa(2342)
starr := make([]int,0)
for i3,_ := range stn {
temp,_ := strconv.Atoi(stn[i3])
starr = append(starr,temp )
}
fmt.Println(starr)
The error is: "cannot use stn[i3] (type byte) as type string in argument to strconv.Atoi". I am used to Python so I try to follow the idea from Python but it does not seem to work. Reall appreciate any help
Answering the question behind the question, here's how you might convert an int into a slice of digits in go instead of using string conversions.
func digitSlice(input int) []int {
output := []int{}
for input > 0 {
output = append([]int{input % 10}, output...)
input = input / 10
}
return output
}
https://play.golang.org/p/tCLISl7Djah

Using testing.Benchmark does not produce any output

I'm using testing.Benchmark to manually run a couple benchmarks but the result object is always empty.
Am I missing something here?
Here's an example:
package main
import "testing"
func main() {
result := testing.Benchmark(func(parentB *testing.B) {
parentB.Run("example", func(b *testing.B) {
for n := 0; n < b.N; n++ {
println("ok")
}
})
})
println(result.String())
}
This will print ok a couple times and then 0 0 ns/op but the benchmark clearly did run something.
I think you are doing everything right. Doc of testing.Benchmark() says:
Benchmark benchmarks a single function. Useful for creating custom benchmarks that do not use the "go test" command.
If f calls Run, the result will be an estimate of running all its subbenchmarks that don't call Run in sequence in a single benchmark.
Looking into the implementation (Go 1.7.4):
func Benchmark(f func(b *B)) BenchmarkResult {
b := &B{
common: common{
signal: make(chan bool),
w: discard{},
},
benchFunc: f,
benchTime: *benchTime,
}
if !b.run1() {
return BenchmarkResult{}
}
return b.run()
}
This line:
if !b.run1() {
return BenchmarkResult{}
}
b.run1() is supposed to run your passed function once, and detect if it has sub-benchmarks. Yours has. It returns a bool whether more runs are needed. Inside run1():
if b.hasSub || b.finished {
// ...
return true
}
It properly tells it has sub-benchmark, and Benchmark() –with noble simplicity– just returns an empty BenchmarkResult:
if !b.run1() {
return BenchmarkResult{}
}
I do believe that either this is a bug (or rather "incomplete" feature), or doc is incorrect. I suggest to file an issue here: https://github.com/golang/go/issues
Eddited the answer to clarify:
My guess is that you are using go run to run the test. That will not produce any result. In order to run the code exatly as it is written you need to use
go test -bench=. and I think it should work.
The file must be named test_xxx.go where xxx is whatever you want.
If you restucture you code a litle bit it can be run as a single function benchmark:
package main
import "testing"
func main() {
myTest()
}
func myTest() {
fn := func(b *testing.B) {
for n := 0; n < b.N; n++ {
println("ok")
}
}
result := testing.Benchmark(fn)
println(result.String())
}

Golang Revel Job spec every 1st monday on every month

I'm using golang revel and I need a job to be run every first monday of every month, a quartz cron spec for that would look like this:
0 0 0 ? 1/1 MON#1
But robfig/cron doesn't accept a spec like that, hence neither revel/jobs.
Anyone knows how can I solve that [using revel jobs]?
To me, the easiest solution would be something like this:
func (e SomeStruct) Run() {
t := time.Now().Local()
day_num, _ := t.Day()
if day_num <= 7 {
fmt.Println("Hello, playground")
}
}
func init() {
revel.OnAppStart(func() {
jobs.Schedule("0 0 * * 1", SomeStruct{})
})
Where you simply run the job EVERY monday, but in the job itself, check if it's the FIRST monday before you actually do anything. There may be a better way (not very familiar with Revel), but glancing through how their jobs work this would work and it's not like it will be a performance issue.
To check for the first Monday in the month,
package main
import (
"fmt"
"time"
)
func IsFirstMonday() bool {
t := time.Now().Local()
if d := t.Day(); 1 <= d && d <= 7 {
if wd := t.Weekday(); wd == time.Monday {
return true
}
}
return false
}
func main() {
fmt.Println(IsFirstMonday())
}

Resources