Challenge of finding 3 pairs in array - go

The length L at the time of joining, when the length of the bar of the N (1 ≦ N ≦ 5000) is supplied from standard input, is the L by connecting three lengths among the N number of bars please write a program to find the total number of combinations of. However, and the length of the individual bars, length was pieced together (L) is a positive integer, is sufficient handle range in 32bit integer. In addition, it has all the length of the bar different things.
for example)
input:
15
5
8
4
10
3
2
output:
2 //{{2, 3, 10}, {3, 4, 8}}
example 2)
input :
35
10
13
12
17
10
4
18
3
11
5
7
output:
6 //{{4, 13, 18}, {5, 12, 18}, {5, 13, 17}, {7, 10, 18}, {7, 11, 17}, {10, 12, 13}}
and my answer is here
package main
import (
"fmt"
"sort"
)
func main() {
input_count := 0
var target int
var count int
var v int
var array []int
for read_count, _ := fmt.Scan(&v); read_count != 0; read_count, _ = fmt.Scan(&v) {
if 0 == input_count {
target = v
} else if 1 == input_count {
count = v
array = make([]int, count)
} else {
array[input_count-2] = v
}
input_count++
}
sort.Ints(array)
fmt.Println(Calculate(target, count, array))
}
func Except(pair []int, count int, array []int) []int {
except := make([]int, count-pair[2])
except_index := 0
on := false
for _, v := range array {
if on {
except[except_index] = v
except_index++
}
if v == pair[1] {
on = true
}
}
return except
}
func ListUp(target int, count int, array []int) [][]int {
max := array[count-1]
list := make([][]int, Fact(count-1))
list_index := 0
for i, h := range array {
if count > i+1 && target > h+array[i+1] {
for j, v := range array[i+1:] {
if count > i+j+1 && target <= max+h+v && target > h+v {
list[list_index] = []int{h, v, i + j + 1}
list_index++
}
}
}
}
return list
}
//func Calculate(target int, count int, array []int) [][]int {
func Calculate(target int, count int, array []int) int {
// var answers [][]int
answer_count := 0
for _, pair := range ListUp(target, count, array) {
if 3 == len(pair) {
pair_sum := pair[0] + pair[1]
if target-pair_sum >= array[0] {
for _, v := range Except(pair, count, array) {
if target == pair[0]+pair[1]+v {
// answers = append(answers, []int{pair[0], pair[1], v})
answer_count++
}
}
}
}
}
return answer_count
}
func Fact(n int) int {
if n == 0 {
return 0
}
return n + Fact(n-1)
}
Does anyone who can refactor the code?
and you should refactor it
if input
https://github.com/freddiefujiwara/horiemon-challenge-codeiq/blob/master/sample4.txt
then output
1571200
in 10 seconds
current status is here
time ./horiemon-challenge-codeiq < sample4.txt
1571200
real 6m56.584s
user 6m56.132s
sys 0m1.578s
very very slow.

Your time of almost seven minutes is very, very slow. Ten seconds is slow. One second is more reasonable, a tenth of a second is good. For example, using an O(N*N) algorithm,
package main
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"sort"
"strconv"
"strings"
)
func triples(l int, b []int) int {
t := 0
sort.Ints(b)
// for i < j < k, b[i] <= b[j] <= b[k]
for i := 0; i < len(b)-2; i++ {
x := b[i]
if x > l {
break
}
lx := l - x
j, k := i+1, len(b)-1
y := b[j]
z := b[k]
for j < k {
yz := y + z
switch {
case lx > yz:
j++
y = b[j]
case lx < yz:
k--
z = b[k]
default:
// l == b[i]+b[j]+b[k]
t++
j++
k--
y = b[j]
z = b[k]
}
}
}
return t
}
func readInput() (l int, b []int, err error) {
r := bufio.NewReader(os.Stdin)
for {
line, err := r.ReadString('\n')
line = strings.TrimSpace(line)
if err == nil && len(line) == 0 {
err = io.EOF
}
if err != nil {
if err == io.EOF {
break
}
return 0, nil, err
}
i, err := strconv.Atoi(string(line))
if err == nil && i < 0 {
err = errors.New("Nonpositive number: " + line)
}
if err != nil {
return 0, nil, err
}
b = append(b, i)
}
if len(b) > 0 {
l = b[0]
b = b[1:]
if len(b) > 1 {
n := b[0]
b = b[1:]
if n != len(b) {
err := errors.New("Invalid number of bars: " + strconv.Itoa(len(b)))
return 0, nil, err
}
}
}
return l, b, nil
}
func main() {
l, b, err := readInput()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
t := triples(l, b)
fmt.Println(t)
}
Output:
1571200
real 0m0.164s
user 0m0.161s
sys 0m0.004s
For comparison, your program,
Output:
1571200
real 9m24.384s
user 16m14.592s
sys 0m19.129s

ive tuned
package main
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"sort"
"strconv"
"strings"
)
type triple struct {
x, y, z int
}
func triples(l int, n []int, list bool) (nt int, t []triple) {
num_of_list := len(n)
for i := 0; i < num_of_list-2; i++ {
x := n[i]
if x > l {
break
}
for j := i + 1; j < num_of_list-1; j++ {
y := x + n[j]
if y > l {
break
}
pos := sort.SearchInts(n[j:], l-y)
if j < pos+j && pos+j < num_of_list && n[pos+j] == l-y {
nt++
}
}
}
return nt, t
}
func readInput() (l int, n []int, err error) {
r := bufio.NewReader(os.Stdin)
for {
line, err := r.ReadString('\n')
line = strings.TrimSpace(line)
if err == nil && len(line) == 0 {
err = io.EOF
}
if err != nil {
if err == io.EOF {
break
}
return 0, nil, err
}
i, err := strconv.Atoi(string(line))
if err == nil && i < 0 {
err = errors.New("Nonpositive number: " + line)
}
if err != nil {
return 0, nil, err
}
n = append(n, i)
}
if len(n) > 0 {
l = n[0]
n = n[1:]
}
sort.Ints(n)
for i := 1; i < len(n); i++ {
if n[i] == n[i-1] {
copy(n[i:], n[i+1:])
n = n[:len(n)-1]
}
}
return l, n, nil
}
func main() {
l, n, err := readInput()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
list := false
nt, t := triples(l, n, list)
fmt.Println(nt)
if list {
fmt.Println(t)
}
}

Related

How to find sum of integers using recursion(without loops) in Golang?

Program should ask values "number of numbers" and "numbers" for each "number of inputs", answers are sum of squares of these numbers. My code works but it shows answers in wrong order, how to make it work properly? Outputs should be shown after all inputs.
I think its easier to understand this program by reading inputs and outputs:
Enter the number of inputs // output
2 // input
Enter the number of numbers // output
2 // input
Enter the numbers // output
1 2 // input (second ans)
Enter the number of numbers // output
2 // input
Enter the numbers
2 3 // input (first ans)
ans = 13 // ans = 2^2 + 3^2
ans = 5 () // ans = 1^2 + 2^2
MyCode:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Println(`Enter the number of inputs`)
n, _ := reader.ReadString('\n')
n = strings.TrimRight(n, "\r\n")
test_cases, err := strconv.Atoi(n)
if err != nil {
fmt.Println(err)
}
process_test_case(test_cases, reader)
}
func process_test_case(test_cases int, reader *bufio.Reader) {
fmt.Println(`Enter the number of numbers`)
_, _ = reader.ReadString('\n')
fmt.Println(`Enter the numbers`)
input, _ := reader.ReadString('\n')
input = strings.TrimRight(input, "\r\n")
arr := strings.Split(input, " ")
test_cases -= 1
if test_cases != 0 {
process_test_case(test_cases, reader)
}
fmt.Println("ans = ", process_array(arr, 0))
}
func process_array(arr []string, result int) int {
num, _ := strconv.Atoi(arr[0])
if len(arr) > 1 {
next := arr[1:]
if num < 0 {
num = 0
}
result = num*num + process_array(next, result)
return result
} else {
if num >= 0 {
return num * num
}
return 0
}
}
How to find sum of integers using recursion (without loops) in Go?
The program should ask "number of numbers" and "numbers" for each "number of inputs", answers are sum of squares of these numbers.
Here is an answer to the question, a recursive solution in Go:
$ go run sumsq.go
Enter the number of inputs:
2
Enter the number of numbers:
2
Enter the numbers:
1
2
Enter the number of numbers:
2
Enter the numbers:
2
3
Sum of Squares:
5
13
$
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func readInt(r *bufio.Reader) int {
line, err := r.ReadString('\n')
line = strings.TrimSpace(line)
if err != nil {
if len(line) == 0 {
return 0
}
}
i, err := strconv.Atoi(line)
if err != nil {
return 0
}
return i
}
func nSquares(n int, r *bufio.Reader) int {
if n == 0 {
return 0
}
i := readInt(r)
return i*i + nSquares(n-1, r)
}
func nNumbers(n int, r *bufio.Reader, sums *[]int) int {
if n == 0 {
return 0
}
fmt.Println("\nEnter the number of numbers: ")
i := readInt(r)
fmt.Println("Enter the numbers: ")
*sums = append(*sums, nSquares(i, r))
return nNumbers(n-1, r, sums)
}
func nInputs(r *bufio.Reader) []int {
fmt.Println("Enter the number of inputs: ")
i := readInt(r)
sums := make([]int, 0, i)
nNumbers(i, r, &sums)
return sums
}
func sumSqrs(sums []int) {
if len(sums) == 0 {
return
}
fmt.Println(sums[0])
sumSqrs(sums[1:])
}
func main() {
r := bufio.NewReader(os.Stdin)
fmt.Println()
sums := nInputs(r)
fmt.Println("\nSum of Squares:")
sumSqrs(sums)
fmt.Println()
}
I have created a sample code for your scenario. You can modify it by using bufio.NewReader(os.Stdin)
func process_array(arr []string) int {
res := 0
for _, v := range arr {
num, err := strconv.Atoi(v)
if err != nil {
panic(err)
}
fmt.Println("num :", num)
res += num * num
}
return res
}
func process_test_case() int {
fmt.Println(`Enter the number of numbers`)
num := 2
fmt.Println("number of numbers :", num)
fmt.Println(`Enter the numbers`)
input := "1 2"
fmt.Println("the numbers :", input)
arr := strings.Split(input, " ")
res := process_array(arr)
return res
}
func main() {
fmt.Println(`Enter the number of inputs`)
test_cases := 1
fmt.Println("number of inputs :", test_cases)
for test_cases >= 1 {
res := process_test_case()
fmt.Println(res)
test_cases -= 1
}
}
You can run it here : https://go.dev/play/p/zGkAln2ghZp
OR
As commented by #phonaputer you can change the sequence. Return the slice and print it from the end.
I think this code answer your title of the question:
package main
import "fmt"
func SumValues(x int, y ...int) (sum int) {
q := len(y) - 1
sum = y[q - x]
if x < q {
sum += SumValues(x + 1, y...)
}
return sum
}
func main() {
sum := SumValues(0,1,2,3,4,5)
fmt.Println("Sum is:", sum)
}

computing complexity of an anagram finder implementation

Given below code
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
s := []string{"eat", "tea", "tan", "ate", "nat", "bat"}
result := groupAnagrams(s)
fmt.Println(result)
}
func groupAnagrams(s []string) (out [][]string) {
tmp := map[string][]string{}
for _, v := range s {
x := strings.Split(v, "")
sort.Strings(x)
anagram := strings.Join(x, "")
items, ok := tmp[anagram]
if ok {
items = append(items, v)
tmp[anagram] = items
continue
}
tmp[anagram] = []string{v}
}
var keys []string
for key := range tmp {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
sort.Strings(tmp[key])
out = append(out, tmp[key])
}
return
}
And its tests here https://play.golang.org/p/k8F1-FAC_au
can you help figuring the complexity ?
In my understanding, and without checking thoroughly the documentation.
for _, v := range s { // o(n)
sort.Strings(keys) //o(log n)
x := strings.Split(v, "") / anagram := strings.Join(x, "") //o(n)
Are those correct ? Am i missing some ? How to compute the total ?
Do you account for total allocations when computing the complexity of a code ?
(not an answer, more like a formatted comment)
You get to choose what counts as "1 operation".
For example : in your for _, v := range s { ... } loop, I wouldn't count the processing of one single v value :
x := strings.Split(v, "")
sort.Strings(x)
anagram := strings.Join(x, "")
items, ok := tmp[anagram]
if ok {
items = append(items, v)
tmp[anagram] = items
continue
}
tmp[anagram] = []string{v}
as "1 operation". More like something that depends on len(v).
So the length of the items in your starting set will probably appear in your end formula.
this is not an answer, but, little insight as to anyone else having to deal with such things. may that help you.
I slightly revised stuff here and their, then gave a shot to a Godel-inspired scheme as described at https://stackoverflow.com/a/396077/11892070
-- main.go --
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
input := []string{"tan", "nat", "⌘", "日本語", "語日本"}
freq := map[rune]int{}
for _, word := range input {
x, err := hashWord(word, freq)
fmt.Println(word, "=>", x, "err=", err)
}
}
func groupAnagramsUsingSort(s []string, tmp map[string][]string, out [][]string) [][]string {
for k := range tmp {
delete(tmp, k)
}
for i := 0; i < len(out); i++ {
out[i] = out[i][:0]
}
out = out[:0]
for _, v := range s {
x := strings.Split(v, "")
sort.Strings(x)
anagram := strings.Join(x, "")
items, ok := tmp[anagram]
if ok {
items = append(items, v)
tmp[anagram] = items
continue
}
tmp[anagram] = []string{v}
}
for key := range tmp {
out = append(out, tmp[key])
}
return out
}
func groupAnagramsUsingHash(s []string, tmp map[int][]string, out [][]string) [][]string {
for k := range tmp {
delete(tmp, k)
}
for i := 0; i < len(out); i++ {
out[i] = out[i][:0]
}
out = out[:0]
freq := map[rune]int{}
for _, v := range s {
hash, _ := hashWord(v, freq)
items, ok := tmp[hash]
if ok {
items = append(items, v)
tmp[hash] = items
continue
}
tmp[hash] = []string{v}
}
for key := range tmp {
out = append(out, tmp[key])
}
return out
}
var primes = []int{2, 41, 37, 47, 3, 67, 71, 23, 5, 101, 61, 17, 19, 13, 31, 43, 97, 29, 11, 7, 73, 83, 79, 89, 59, 53}
var ErrNonASCII = fmt.Errorf("non ascii letter detected")
func getFrequencyMap(word string, freq map[rune]int) (map[rune]int, error) {
for k := range freq {
delete(freq, k)
}
for _, r := range word {
if r-97 < 0 || int(r-97) > len(primes) {
return nil, ErrNonASCII
}
x := freq[r]
freq[r] = x + 1
}
return freq, nil
}
func hashWord(word string, freq map[rune]int) (int, error) {
var err error
freq, err = getFrequencyMap(word, freq)
if err != nil {
return -1, err
}
product := 1
for letter, r := range freq {
product = product * primes[letter-97]
for e := 1; e < r; e++ {
product = product * product
}
}
return product, nil
}
-- main_test.go --
package main
import (
"reflect"
"sort"
"testing"
)
type expectation struct {
input []string
want [][]string
}
var expectations = []expectation{
expectation{
input: []string{"eat", "tea", "tan", "ate", "nat", "bat"},
want: [][]string{
[]string{"ate", "eat", "tea"},
[]string{"bat"},
[]string{"nat", "tan"},
},
},
expectation{
input: []string{"eaft", "tea", "taen", "ate", "nate", "batf"},
want: [][]string{
[]string{"batf"},
[]string{"eaft"},
[]string{"tea", "ate"},
[]string{"taen", "nate"},
},
},
expectation{
input: []string{""},
want: [][]string{
[]string{""},
},
},
expectation{
input: []string{"a"},
want: [][]string{
[]string{"a"},
},
},
}
func TestUsingSort(t *testing.T) {
tmp := map[string][]string{}
out := [][]string{}
for _, expectation := range expectations {
out = groupAnagramsUsingSort(expectation.input, tmp, out)
if len(out) != len(expectation.want) {
t.Fatalf("unexpected output,\nwanted=%#v\ngot =%#v\n", expectation.want, out)
}
for i := 0; i < len(out); i++ {
sort.Strings(out[i])
sort.Strings(expectation.want[i])
}
sort.Slice(out, func(i int, j int) bool {
return len(out[i]) < len(out[j])
})
sort.Slice(expectation.want, func(i int, j int) bool {
return len(expectation.want[i]) < len(expectation.want[j])
})
sort.Slice(out, func(i int, j int) bool {
return (len(out[i]) > 0 &&
len(out[j]) > 0 &&
out[i][0] < out[j][0])
})
sort.Slice(expectation.want, func(i int, j int) bool {
return (len(expectation.want[i]) > 0 &&
len(expectation.want[j]) > 0 &&
expectation.want[i][0] < expectation.want[j][0])
})
for i := 0; i < len(out); i++ {
if !reflect.DeepEqual(out[i], expectation.want[i]) {
t.Fatalf("unexpected output,\nwanted=%#v\ngot =%#v\n", expectation.want, out)
}
}
}
}
func TestUsingHash(t *testing.T) {
tmp := map[int][]string{}
out := [][]string{}
for _, expectation := range expectations {
out = groupAnagramsUsingHash(expectation.input, tmp, out)
if len(out) != len(expectation.want) {
t.Fatalf("unexpected output,\nwanted=%#v\ngot =%#v\n", expectation.want, out)
}
for i := 0; i < len(out); i++ {
sort.Strings(out[i])
sort.Strings(expectation.want[i])
}
sort.Slice(out, func(i int, j int) bool {
return len(out[i]) < len(out[j])
})
sort.Slice(expectation.want, func(i int, j int) bool {
return len(expectation.want[i]) < len(expectation.want[j])
})
sort.Slice(out, func(i int, j int) bool {
return (len(out[i]) > 0 &&
len(out[j]) > 0 &&
out[i][0] < out[j][0])
})
sort.Slice(expectation.want, func(i int, j int) bool {
return (len(expectation.want[i]) > 0 &&
len(expectation.want[j]) > 0 &&
expectation.want[i][0] < expectation.want[j][0])
})
for i := 0; i < len(out); i++ {
if !reflect.DeepEqual(out[i], expectation.want[i]) {
t.Fatalf("unexpected output,\nwanted=%#v\ngot =%#v\n", expectation.want, out)
}
}
}
}
func BenchmarkUsingSort(b *testing.B) {
tmp := map[string][]string{}
out := [][]string{}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, expectation := range expectations {
out = groupAnagramsUsingSort(expectation.input, tmp, out)
_ = out
}
}
}
func BenchmarkUsingHash(b *testing.B) {
tmp := map[int][]string{}
out := [][]string{}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, expectation := range expectations {
out = groupAnagramsUsingHash(expectation.input, tmp, out)
_ = out
}
}
}
Benchmark result
$ go test -bench=. -v .
=== RUN TestUsingSort
--- PASS: TestUsingSort (0.00s)
=== RUN TestUsingHash
--- PASS: TestUsingHash (0.00s)
goos: linux
goarch: amd64
BenchmarkUsingSort
BenchmarkUsingSort-4 344438 3315 ns/op 787 B/op 29 allocs/op
BenchmarkUsingHash
BenchmarkUsingHash-4 410810 2911 ns/op 496 B/op 17 allocs/op
PASS
ok _/home/clementauger/tmp 2.408s

Most efficient method of finding the number of common factors of two numbers

I have two numbers for example the numbers are 12 and 16.
factors of 12 are 1, 2, 3, 4, 6, 12
factors of 16 are 1, 2, 4, 8, 16
common factors of these two numbers are 1, 2 and 4.
So the number of common factors are 3. I need to build a Go program for finding the number common factors of two numbers. But the program should be efficient and with minimum number of loops or without loops.
I will provide my code and you can also contribute and suggest with another best methods.
package main
import "fmt"
var (
fs []int64
fd []int64
count int
)
func main() {
commonFactor(16, 12)
commonFactor(5, 10)
}
func commonFactor(num ...int64) {
count = 0
if num[0] < 1 || num[1] < 1 {
fmt.Println("\nFactors not computed")
return
}
for _, val := range num {
fs = make([]int64, 1)
fmt.Printf("\nFactors of %d: ", val)
fs[0] = 1
apf := func(p int64, e int) {
n := len(fs)
for i, pp := 0, p; i < e; i, pp = i+1, pp*p {
for j := 0; j < n; j++ {
fs = append(fs, fs[j]*pp)
}
}
}
e := 0
for ; val&1 == 0; e++ {
val >>= 1
}
apf(2, e)
for d := int64(3); val > 1; d += 2 {
if d*d > val {
d = val
}
for e = 0; val%d == 0; e++ {
val /= d
}
if e > 0 {
apf(d, e)
}
}
if fd == nil {
fd = fs
}
fmt.Println(fs)
}
for _, i := range fs {
for _, j := range fd {
if i == j {
count++
}
}
}
fmt.Println("Number of common factors =", count)
}
Output is :
Factors of 16: [1 2 4 8 16] Factors of 12: [1 2 4 3 6 12]
Number of common factors = 3
Factors of 5: [1 5] Factors of 10: [1 2 5 10]
Number of common factors = 2
Goplayground
Answer 1, with no loops just recursion
package main
import (
"fmt"
"os"
"strconv"
)
func factors(n int, t int, res *[]int) *[]int {
if t != 0 {
if (n/t)*t == n {
temp := append(*res, t)
res = &temp
}
res = factors(n, t-1, res)
}
return res
}
func cf(l1 []int, l2 []int, res *[]int) *[]int {
if len(l1) > 0 && len(l2) > 0 {
v1 := l1[0]
v2 := l2[0]
if v1 == v2 {
temp := append(*res, v1)
res = &temp
l2 = l2[1:]
}
if v2 > v1 {
l2 = l2[1:]
} else {
l1 = l1[1:]
}
res = cf(l1, l2, res)
}
return res
}
func main() {
n, err := strconv.Atoi(os.Args[1])
n2, err := strconv.Atoi(os.Args[2])
if err != nil {
fmt.Println("give a number")
panic(err)
}
factorlist1 := factors(n, n, &[]int{})
factorlist2 := factors(n2, n2, &[]int{})
fmt.Printf("factors of %d %v\n", n, factorlist1)
fmt.Printf("factors of %d %v\n", n2, factorlist2)
common := cf(*factorlist1, *factorlist2, &[]int{})
fmt.Printf("number of common factors = %d\n", len(*common))
}
However, this blows up with larger numbers such as 42512703
replacing the func that do the work with iterative versions can cope with bigger numbers
func factors(n int) []int {
res := []int{}
for t := n; t > 0; t-- {
if (n/t)*t == n {
res = append(res, t)
}
}
return res
}
func cf(l1 []int, l2 []int) []int {
res := []int{}
for len(l1) > 0 && len(l2) > 0 {
v1 := l1[0]
v2 := l2[0]
if v1 == v2 {
res = append(res, v1)
l2 = l2[1:]
}
if v2 > v1 {
l2 = l2[1:]
} else {
l1 = l1[1:]
}
}
return res
}
func Divisors(n int)int{
prev := []int{}
for i := n;i > 0;i--{
prev = append(prev,i)
}
var res int
for j := prev[0];j > 0;j--{
if n % j == 0 {
res++
}
}
return res
}

How to improve execution time in go

I was writing this code for "competitive Programming". It consisted of only 1 loop but gave "Time Limit Exceed" if n = 100000. Can Go be considered for competitive Programming?
fmt.Scanln(&n, &k, &m)
for i := 0; i < n; i++ {
fmt.Scanf("%d", &z)
if m >= 0 {
if z > x {
x = z
m--
}
if i == n-1 {
m++
}
} else {
if cnt == 0 {
x = 0
}
x += z
cnt++
}
}
if m == 0 {
f = float64(x / (n - m))
}
if k < m {
x += k
} else {
x += m
}
f = float64(x)
fmt.Println(f)
"codeforces.com/problemset/problem/1111/B -- Average Superhero Gang Power"
Go execution time can be improved to milliseconds for n = 100000, under the 1 second time limit.
For example, a complete solution to the problem,
// Problem - 1111B - Codeforces
// B. Average Superhero Gang Power
// http://codeforces.com/problemset/problem/1111/B
package main
import (
"bufio"
"fmt"
"io"
"os"
"sort"
"strconv"
)
func readInt(s *bufio.Scanner) (int, error) {
if s.Scan() {
i, err := strconv.Atoi(s.Text())
if err != nil {
return 0, err
}
return i, nil
}
err := s.Err()
if err == nil {
err = io.EOF
}
return 0, err
}
func main() {
s := bufio.NewScanner(os.Stdin)
s.Split(bufio.ScanWords)
var n, k, m int
var err error
n, err = readInt(s)
if err != nil {
panic(err)
}
if n < 1 || n > 10e5 {
panic("invalid n")
}
k, err = readInt(s)
if err != nil {
panic(err)
}
if k < 1 || k > 10e5 {
panic("invalid k")
}
m, err = readInt(s)
if err != nil {
panic(err)
}
if m < 1 || m > 10e7 {
panic("invalid m")
}
a := make([]int, n)
sum := int64(0)
for i := 0; i < n; i++ {
ai, err := readInt(s)
if err != nil {
panic(err)
}
if ai < 1 || ai > 10e6 {
panic("invalid a")
}
a[i] = ai
sum += int64(ai)
}
sort.Slice(a, func(i, j int) bool {
return a[i] > a[j]
})
i, ik := 0, k
for ; m > 0; m-- {
j := len(a) - 1
if j >= 1 && (int64(n-1)*(1+sum) < int64(n)*(sum-int64(a[j]))) {
// delete
sum -= int64(a[j])
a = a[:j]
} else {
// increment
sum++
a[i]++
ik--
if ik <= 0 {
ik = k
i++
if i >= len(a) {
break
}
}
}
}
// fmt.Println(sum, len(a))
avg := float64(sum) / float64(len(a))
fmt.Printf("%.20f\n", avg)
}
Output:
$ go run heroes.go
2 4 6
4 7
11.00000000000000000000
$
$ go run heroes.go
4 2 6
1 3 2 3
5.00000000000000000000
$
A benchmark for a cast of avengers with random powers, where n := 100000, k := 100, and m := 100000:
$ ls -s -h heroes.test
676K heroes.test
$ go build heroes.go
$ time ./heroes < heroes.test
708329.74652807507663965225
real 0m0.067s
user 0m0.038s
sys 0m0.004s
$

How to compare two version number strings in golang

I have two strings (they are actually version numbers and they could be any version numbers)
a := "1.05.00.0156"
b := "1.0.221.9289"
I want to compare which one is bigger. How to do it in golang?
There is a nice solution from Hashicorp - https://github.com/hashicorp/go-version
import github.com/hashicorp/go-version
v1, err := version.NewVersion("1.2")
v2, err := version.NewVersion("1.5+metadata")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
Some time ago I created a version comparison library: https://github.com/mcuadros/go-version
version.CompareSimple("1.05.00.0156", "1.0.221.9289")
//Returns: 1
Enjoy it!
Here's a general solution.
package main
import "fmt"
func VersionOrdinal(version string) string {
// ISO/IEC 14651:2011
const maxByte = 1<<8 - 1
vo := make([]byte, 0, len(version)+8)
j := -1
for i := 0; i < len(version); i++ {
b := version[i]
if '0' > b || b > '9' {
vo = append(vo, b)
j = -1
continue
}
if j == -1 {
vo = append(vo, 0x00)
j = len(vo) - 1
}
if vo[j] == 1 && vo[j+1] == '0' {
vo[j+1] = b
continue
}
if vo[j]+1 > maxByte {
panic("VersionOrdinal: invalid version")
}
vo = append(vo, b)
vo[j]++
}
return string(vo)
}
func main() {
versions := []struct{ a, b string }{
{"1.05.00.0156", "1.0.221.9289"},
// Go versions
{"1", "1.0.1"},
{"1.0.1", "1.0.2"},
{"1.0.2", "1.0.3"},
{"1.0.3", "1.1"},
{"1.1", "1.1.1"},
{"1.1.1", "1.1.2"},
{"1.1.2", "1.2"},
}
for _, version := range versions {
a, b := VersionOrdinal(version.a), VersionOrdinal(version.b)
switch {
case a > b:
fmt.Println(version.a, ">", version.b)
case a < b:
fmt.Println(version.a, "<", version.b)
case a == b:
fmt.Println(version.a, "=", version.b)
}
}
}
Output:
1.05.00.0156 > 1.0.221.9289
1 < 1.0.1
1.0.1 < 1.0.2
1.0.2 < 1.0.3
1.0.3 < 1.1
1.1 < 1.1.1
1.1.1 < 1.1.2
1.1.2 < 1.2
go-semver is a semantic versioning library for Go. It lets you parse and compare two semantic version strings.
Example:
vA := semver.New("1.2.3")
vB := semver.New("3.2.1")
fmt.Printf("%s < %s == %t\n", vA, vB, vA.LessThan(*vB))
Output:
1.2.3 < 3.2.1 == true
Here are some of the libraries for version comparison:
https://github.com/blang/semver
https://github.com/Masterminds/semver
https://github.com/hashicorp/go-version
https://github.com/mcuadros/go-version
I have used blang/semver.
Eg: https://play.golang.org/p/1zZvEjLSOAr
import github.com/blang/semver/v4
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
// Options availabe
v1.Compare(v2) // Compare
v1.LT(v2) // LessThan
v1.GT(v2) // GreaterThan
This depends on what you mean by bigger.
A naive approach would be:
package main
import "fmt"
import "strings"
func main() {
a := strings.Split("1.05.00.0156", ".")
b := strings.Split("1.0.221.9289", ".")
for i, s := range a {
var ai, bi int
fmt.Sscanf(s, "%d", &ai)
fmt.Sscanf(b[i], "%d", &bi)
if ai > bi {
fmt.Printf("%v is bigger than %v\n", a, b)
break
}
if bi > ai {
fmt.Printf("%v is bigger than %v\n", b, a)
break
}
}
}
http://play.golang.org/p/j0MtFcn44Z
Based on Jeremy Wall's answer:
func compareVer(a, b string) (ret int) {
as := strings.Split(a, ".")
bs := strings.Split(b, ".")
loopMax := len(bs)
if len(as) > len(bs) {
loopMax = len(as)
}
for i := 0; i < loopMax; i++ {
var x, y string
if len(as) > i {
x = as[i]
}
if len(bs) > i {
y = bs[i]
}
xi,_ := strconv.Atoi(x)
yi,_ := strconv.Atoi(y)
if xi > yi {
ret = -1
} else if xi < yi {
ret = 1
}
if ret != 0 {
break
}
}
return
}
http://play.golang.org/p/AetJqvFc3B
Striving for clarity and simplicity:
func intVer(v string) (int64, error) {
sections := strings.Split(v, ".")
intVerSection := func(v string, n int) string {
if n < len(sections) {
return fmt.Sprintf("%04s", sections[n])
} else {
return "0000"
}
}
s := ""
for i := 0; i < 4; i++ {
s += intVerSection(v, i)
}
return strconv.ParseInt(s, 10, 64)
}
func main() {
a := "3.045.98.0832"
b := "087.2345"
va, _ := intVer(a)
vb, _ := intVer(b)
fmt.Println(va<vb)
}
Comparing versions implies parsing so I believe these 2 steps should be separate to make it robust.
tested in leetcode: https://leetcode.com/problems/compare-version-numbers/
func compareVersion(version1 string, version2 string) int {
len1, len2, i, j := len(version1), len(version2), 0, 0
for i < len1 || j < len2 {
n1 := 0
for i < len1 && '0' <= version1[i] && version1[i] <= '9' {
n1 = n1 * 10 + int(version1[i] - '0')
i++
}
n2 := 0
for j < len2 && '0' <= version2[j] && version2[j] <= '9' {
n2 = n2 * 10 + int(version2[j] - '0')
j++
}
if n1 > n2 {
return 1
}
if n1 < n2 {
return -1
}
i, j = i+1, j+1
}
return 0
}
import (
"fmt"
"strconv"
"strings"
)
func main() {
j := ll("1.05.00.0156" ,"1.0.221.9289")
fmt.Println(j)
}
func ll(a,b string) int {
var length ,r,l int = 0,0,0
v1 := strings.Split(a,".")
v2 := strings.Split(b,".")
len1, len2 := len(v1), len(v2)
length = len2
if len1 > len2 {
length = len1
}
for i:= 0;i<length;i++ {
if i < len1 && i < len2 {
if v1[i] == v2[i] {
continue
}
}
r = 0
if i < len1 {
if number, err := strconv.Atoi(v1[i]); err == nil {
r = number
}
}
l = 0
if i < len2 {
if number, err := strconv.Atoi(v2[i]); err == nil {
l = number
}
}
if r < l {
return -1
}else if r> l {
return 1
}
}
return 0
}
If you can guarantee version strings have same format (i.e. SemVer), you can convert to int and compare int. Here is an implementation for sorting slices of SemVer:
versions := []string{"1.0.10", "1.0.6", "1.0.9"}
sort.Slice(versions[:], func(i, j int) bool {
as := strings.Split(versions[i], ".")
bs := strings.Split(versions[j], ".")
if len(as) != len(bs) || len(as) != 3 {
return versions[i] < versions[j]
}
ais := make([]int, len(as))
bis := make([]int, len(bs))
for i := range as {
ais[i], _ = strconv.Atoi(as[i])
bis[i], _ = strconv.Atoi(bs[i])
}
//X.Y.Z
// If X and Y are the same, compare Z
if ais[0] == bis[0] && ais[1] == bis[1] {
return ais[2] < bis[2]
}
// If X is same, compare Y
if ais[0] == bis[0] {
return ais[1] < bis[1]
}
// Compare X
return ais[0] < bis[0]
})
fmt.Println(versions)
tested in go playground
// If v1 > v2 return '>'
// If v1 < v2 return '<'
// Otherwise return '='
func CompareVersion(v1, v2 string) byte {
v1Slice := strings.Split(v1, ".")
v2Slice := strings.Split(v2, ".")
var maxSize int
{ // Make them both the same size.
if len(v1Slice) < len(v2Slice) {
maxSize = len(v2Slice)
} else {
maxSize = len(v1Slice)
}
}
v1NSlice := make([]int, maxSize)
v2NSlice := make([]int, maxSize)
{
// Convert string to the int.
for i := range v1Slice {
v1NSlice[i], _ = strconv.Atoi(v1Slice[i])
}
for i := range v2Slice {
v2NSlice[i], _ = strconv.Atoi(v2Slice[i])
}
}
var result byte
var v2Elem int
for i, v1Elem := range v1NSlice {
if result != '=' && result != 0 { // The previous comparison has got the answer already.
return result
}
v2Elem = v2NSlice[i]
if v1Elem > v2Elem {
result = '>'
} else if v1Elem < v2Elem {
result = '<'
} else {
result = '='
}
}
return result
}
Convert "1.05.00.0156" to "0001"+"0005"+"0000"+"0156", then to int64.
Convert "1.0.221.9289" to "0001"+"0000"+"0221"+"9289", then to int64.
Compare the two int64 values.
Try it on the Go playground

Resources