Section titled Problem
Problem
- given input array of string contains release version that must follow
x.y.z
form. x.y.z
must be integer with positive values- sort by latest release
Section titled Solution
Solution
See in playground https://go.dev/play/p/_nFWNUOcDCu.
The process is straigtforward
- Parse string into semver struct
- Sort using custom slice and implement required sorting interface
Len
,Swap
andLess
, refers to https://pkg.go.dev/sort#example-package - Revert back to array of string where version string follows
x.y.z
format
package main
import (
"fmt"
"sort"
"strconv"
"strings"
)
// Semver represents a semantic version in the format x.y.z
type Semver struct {
Major int
Minor int
Patch int
}
func (s Semver) ToString() string {
return fmt.Sprintf("%d.%d.%d", s.Major, s.Minor, s.Patch)
}
// NewSemver returns a new Semver instance with the specified major, minor, and patch values.
func NewSemver(major int, minor int, patch int) Semver {
return Semver{
Major: major,
Minor: minor,
Patch: patch,
}
}
// ParseSemver takes a string representation of a semantic version in the format x.y.z and returns a new Semver instance.
func ParseSemver(version string) (Semver, error) {
parts := strings.Split(version, ".")
if len(parts) != 3 {
return Semver{}, fmt.Errorf("invalid version format: %s", version)
}
major, minor, patch := 0, 0, 0
var err error
if major, err = strconv.Atoi(parts[0]); err != nil || major < 0 {
return Semver{}, fmt.Errorf("invalid major version: %s", parts[0])
}
if minor, err = strconv.Atoi(parts[1]); err != nil || minor < 0 {
return Semver{}, fmt.Errorf("invalid minor version: %s", parts[1])
}
if patch, err = strconv.Atoi(parts[2]); err != nil || patch < 0 {
return Semver{}, fmt.Errorf("invalid patch version: %s", parts[2])
}
return NewSemver(major, minor, patch), nil
}
// Versions is a slice of Semver instances
type Versions []Semver
func (v Versions) Len() int {
return len(v)
}
func (v Versions) Less(i, j int) bool {
if v[i].Major != v[j].Major {
return v[i].Major < v[j].Major
}
if v[i].Minor != v[j].Minor {
return v[i].Minor < v[j].Minor
}
return v[i].Patch < v[j].Patch
}
func (v Versions) Swap(i, j int) {
v[i], v[j] = v[j], v[i]
}
func solution(input []string) []string {
var versions Versions
for _, v := range input {
semver, err := ParseSemver(v)
if err == nil {
versions = append(versions, semver)
}
}
sort.Sort(sort.Reverse(versions))
result := []string{}
for _, v := range versions {
result = append(result, v.ToString())
}
return result
}
func main() {
input := []string{"1.0.0", "2.0.0", "0.1.0", "3.0.0", "invalid", "1.2.3", "1.2.3-rc", "1.-1.2"}
result := solution(input)
fmt.Println(result)
}