Пример #1
0
func (net UbuntuNetManager) writeNetworkInterfaces(dhcpConfigs DHCPInterfaceConfigurations, staticConfigs StaticInterfaceConfigurations, dnsServers []string) (bool, error) {
	sort.Stable(dhcpConfigs)
	sort.Stable(staticConfigs)

	networkInterfaceValues := networkInterfaceConfig{
		DHCPConfigs:       dhcpConfigs,
		StaticConfigs:     staticConfigs,
		HasDNSNameServers: true,
		DNSServers:        dnsServers,
	}

	buffer := bytes.NewBuffer([]byte{})

	t := template.Must(template.New("network-interfaces").Parse(networkInterfacesTemplate))

	err := t.Execute(buffer, networkInterfaceValues)
	if err != nil {
		return false, bosherr.WrapError(err, "Generating config from template")
	}

	changed, err := net.fs.ConvergeFileContents("/etc/network/interfaces", buffer.Bytes())
	if err != nil {
		return changed, bosherr.WrapError(err, "Writing to /etc/network/interfaces")
	}

	return changed, nil
}
// buildHuffman builds a Huffman tree using useCounts as a frequency table.
func buildHuffman(useCounts [129]int) (root *huffmanNode) {
	numNonZero := 0
	for _, count := range useCounts {
		if count != 0 {
			numNonZero++
		}
	}

	nodes := nodeList(make([]*huffmanNode, 0, numNonZero))
	for char, count := range useCounts {
		if count != 0 {
			nodes = append(nodes, &huffmanNode{rune(char), count, nil, nil})
		}
	}

	if len(nodes) < 2 {
		panic("cannot build a tree with a single node")
	}

	sort.Stable(nodes)

	for len(nodes) > 1 {
		parent := &huffmanNode{0, nodes[0].count + nodes[1].count, nodes[0], nodes[1]}
		nodes = nodes[1:]
		nodes[0] = parent

		sort.Stable(nodes)
	}

	return nodes[0]
}
Пример #3
0
func BenchmarkStableSortRepeat(b *testing.B) {
	for n := 0; n < b.N; n++ {
		s := newData()
		sort.Stable(customSort{s, func(x, y *Track) bool {
			if x.Title != y.Title {
				return x.Title < y.Title
			}
			return false
		}})
		sort.Stable(customSort{s, func(x, y *Track) bool {
			if x.Artist != y.Artist {
				return x.Artist < y.Artist
			}
			return false
		}})
		sort.Stable(customSort{s, func(x, y *Track) bool {
			if x.Album != y.Album {
				return x.Album < y.Album
			}
			return false
		}})
		sort.Stable(customSort{s, func(x, y *Track) bool {
			if x.Year != y.Year {
				return x.Year < y.Year
			}
			return false
		}})
	}
}
Пример #4
0
func jpfSortBy(arguments []interface{}) (interface{}, error) {
	intr := arguments[0].(*treeInterpreter)
	arr := arguments[1].([]interface{})
	exp := arguments[2].(expRef)
	node := exp.ref
	if len(arr) == 0 {
		return arr, nil
	} else if len(arr) == 1 {
		return arr, nil
	}
	start, err := intr.Execute(node, arr[0])
	if err != nil {
		return nil, err
	}
	if _, ok := start.(float64); ok {
		sortable := &byExprFloat{intr, node, arr, false}
		sort.Stable(sortable)
		if sortable.hasError {
			return nil, errors.New("error in sort_by comparison")
		}
		return arr, nil
	} else if _, ok := start.(string); ok {
		sortable := &byExprString{intr, node, arr, false}
		sort.Stable(sortable)
		if sortable.hasError {
			return nil, errors.New("error in sort_by comparison")
		}
		return arr, nil
	} else {
		return nil, errors.New("invalid type, must be number of string")
	}
}
Пример #5
0
func Benchmark_words_load(t *testing.B) {
	// wordlist was downloaded from http://www-personal.umich.edu/~jlawler/wordlist
	f, err := os.Open("d:\\wordlist.txt")
	if err != nil {
		t.Skip()
		return
	}
	defer f.Close()

	s := bufio.NewScanner(f)
	words := make([]string, 0, 80000)
	for s.Scan() {
		txt := s.Text()
		words = append(words, txt)
	}
	sort.Stable(byStringLengthDesc(words))

	tree := NewPrefixedTree("")
	for i := range words {
		tree.Put(words[i], i)
	}

	of, err := os.Create("d:\\wordlist.json")
	panicif(err)
	defer of.Close()
	of.WriteString(tree.String())

	t.Log("Nodes: ", tree.NodeCount())
	t.Log("Max fanout: ", tree.root.MaxFanout())

	histogram := make(map[int]int)
	tree.root.visit(func(n *Node) bool {
		count := len(n.Nodes)
		histogram[count] += 1
		return true
	})

	kvs := make([]kv, len(histogram))
	i := 0

	for k, v := range histogram {
		kvs[i] = kv{k, v}
		i++
	}
	sort.Stable(byFanout(kvs))
	for i := range kvs {
		t.Logf("%+v", kvs[i])
	}
	t.Logf("=====")
	sort.Stable(byCount(kvs))
	for i := range kvs {
		t.Logf("%+v", kvs[i])
	}

	tree.root.Walk("abating", func(path string, h int) bool {
		t.Logf("%d(%s): %s ", h, path, words[h])
		return true
	})
}
Пример #6
0
func SortIcons(icons []Icon, sizeDescending bool) {
	// Order after sorting: (width/height, bytes, url)
	sort.Stable(byURL(icons))
	sort.Stable(byBytes(icons))

	if sizeDescending {
		sort.Stable(sort.Reverse(byWidthHeight(icons)))
	} else {
		sort.Stable(byWidthHeight(icons))
	}
}
Пример #7
0
func Sort(e *State, T miniprofiler.Timer, series *Results, order string) (*Results, error) {
	// Sort by groupname first to make the search deterministic
	sort.Sort(ResultSliceByGroup(series.Results))
	switch order {
	case "desc":
		sort.Stable(sort.Reverse(ResultSliceByValue(series.Results)))
	case "asc":
		sort.Stable(ResultSliceByValue(series.Results))
	default:
		return nil, fmt.Errorf("second argument of order() must be asc or desc")
	}
	return series, nil
}
Пример #8
0
func sortGroups(groups [][]*assets.Group) (err error) {
	defer func() {
		if r := recover(); r != nil {
			err = r.(error)
		}
	}()
	// Sort each group list by priority
	for _, v := range groups {
		sort.Stable(groupsByPriority(v))
	}
	// Sort the list of all groups by priority
	sort.Stable(groupListByPriority(groups))
	return
}
Пример #9
0
// Given a list of Ceritifcates in order of listing preference, pretty-prints
// the cert common name, fingerprint, and expiry
func prettyPrintCerts(certs []*x509.Certificate, writer io.Writer) {
	if len(certs) == 0 {
		writer.Write([]byte("\nNo trusted root certificates present.\n\n"))
		return
	}

	sort.Stable(certSorter(certs))

	table := getTable([]string{
		"GUN", "Fingerprint of Trusted Root Certificate", "Expires In"}, writer)

	for _, c := range certs {
		days := math.Floor(c.NotAfter.Sub(time.Now()).Hours() / 24)
		expiryString := "< 1 day"
		if days == 1 {
			expiryString = "1 day"
		} else if days > 1 {
			expiryString = fmt.Sprintf("%d days", int(days))
		}

		certID, err := trustmanager.FingerprintCert(c)
		if err != nil {
			fatalf("Could not fingerprint certificate: %v", err)
		}

		table.Append([]string{c.Subject.CommonName, certID, expiryString})
	}
	table.Render()
}
Пример #10
0
func TestRequestSorting(t *testing.T) {
	sampleRequests := []request.Request{
		request.Request{
			Timestamp:   "012400",
			Description: "Fourth",
		},
		request.Request{
			Timestamp:   "012400",
			Description: "Fifth",
		},
		request.Request{
			Timestamp:   "012346",
			Description: "Second",
		},
		request.Request{
			Timestamp:   "012345",
			Description: "First",
		},
		request.Request{
			Timestamp:   "012347",
			Description: "Third",
		},
	}
	sort.Stable(requestsByTimestamp(sampleRequests))
	descriptions := []string{}
	for _, r := range sampleRequests {
		descriptions = append(descriptions, r.Description)
	}
	if !(descriptions[0] == "First" && descriptions[1] == "Second" && descriptions[2] == "Third" && descriptions[3] == "Fourth" && descriptions[4] == "Fifth") {
		t.Fatalf("Review request ordering failed. Got %v", sampleRequests)
	}
}
Пример #11
0
// Fetch queries the Consul API defined by the given client and returns a slice
// of Node objects
func (d *CatalogNodes) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) {
	d.Lock()
	if d.stopped {
		defer d.Unlock()
		return nil, nil, ErrStopped
	}
	d.Unlock()

	if opts == nil {
		opts = &QueryOptions{}
	}

	consulOpts := opts.consulQueryOptions()
	if d.DataCenter != "" {
		consulOpts.Datacenter = d.DataCenter
	}

	consul, err := clients.Consul()
	if err != nil {
		return nil, nil, fmt.Errorf("catalog nodes: error getting client: %s", err)
	}

	var n []*api.Node
	var qm *api.QueryMeta
	dataCh := make(chan struct{})
	go func() {
		log.Printf("[DEBUG] (%s) querying Consul with %+v", d.Display(), consulOpts)
		n, qm, err = consul.Catalog().Nodes(consulOpts)
		close(dataCh)
	}()

	select {
	case <-d.stopCh:
		return nil, nil, ErrStopped
	case <-dataCh:
	}

	if err != nil {
		return nil, nil, fmt.Errorf("catalog nodes: error fetching: %s", err)
	}

	log.Printf("[DEBUG] (%s) Consul returned %d nodes", d.Display(), len(n))

	nodes := make([]*Node, 0, len(n))
	for _, node := range n {
		nodes = append(nodes, &Node{
			Node:            node.Node,
			Address:         node.Address,
			TaggedAddresses: node.TaggedAddresses,
		})
	}
	sort.Stable(NodeList(nodes))

	rm := &ResponseMetadata{
		LastIndex:   qm.LastIndex,
		LastContact: qm.LastContact,
	}

	return nodes, rm, nil
}
Пример #12
0
// Compress merges any unmerged data into the summary
func (digest *MergingDigest) Compress() {
	if len(digest.unmerged) == 0 {
		return
	}
	sort.Stable(sortByMean(digest.unmerged))
	sum := int64(0)
	m := 0
	i := 0
	j := 0
	digest.merged = digest.merged[:0]
	for i < len(digest.summary) && j < len(digest.unmerged) {
		if digest.summary[i].Mean <= digest.unmerged[j].Mean {
			sum, m = digest.collapse(sum, m, digest.summary[i])
			i++
		} else {
			sum, m = digest.collapse(sum, m, digest.unmerged[j])
			j++
		}
	}
	for i < len(digest.summary) {
		sum, m = digest.collapse(sum, m, digest.summary[i])
		i++
	}
	for j < len(digest.unmerged) {
		sum, m = digest.collapse(sum, m, digest.unmerged[j])
		j++
	}
	digest.merged, digest.summary = digest.summary, digest.merged
	digest.unmerged = digest.unmerged[:0]
}
Пример #13
0
func (h *LogrusHandler) joinKVs(skipUnchanged bool, sep string) []string {

	kv := make([]string, 0, len(h.Fields))
	for k, v := range h.Fields {
		if !h.Opts.shouldShowKey(k) {
			continue
		}

		if skipUnchanged {
			if lastV, ok := h.last[k]; ok && lastV == v {
				continue
			}
		}

		kstr := rgbterm.FgString(k, h.Opts.KeyRGB.R, h.Opts.KeyRGB.G, h.Opts.KeyRGB.B)

		var vstr string
		if h.Opts.Truncates && len(v) > h.Opts.TruncateLength {
			vstr = v[:h.Opts.TruncateLength] + "..."
		} else {
			vstr = v
		}
		vstr = rgbterm.FgString(vstr, h.Opts.ValRGB.R, h.Opts.ValRGB.G, h.Opts.ValRGB.B)
		kv = append(kv, kstr+sep+vstr)
	}

	sort.Strings(kv)

	if h.Opts.SortLongest {
		sort.Stable(byLongest(kv))
	}

	return kv
}
Пример #14
0
// Given a list of KeyStores in order of listing preference, pretty-prints the
// root keys and then the signing keys.
func prettyPrintTargets(ts []*notaryclient.Target, writer io.Writer) {
	if len(ts) == 0 {
		writer.Write([]byte("\nNo targets present in this repository.\n\n"))
		return
	}

	sort.Stable(targetsSorter(ts))

	table := tablewriter.NewWriter(writer)
	table.SetHeader([]string{"Name", "Digest", "Size (bytes)"})
	table.SetBorder(false)
	table.SetColumnSeparator(" ")
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetCenterSeparator("-")
	table.SetAutoWrapText(false)

	for _, t := range ts {
		table.Append([]string{
			t.Name,
			hex.EncodeToString(t.Hashes["sha256"]),
			fmt.Sprintf("%d", t.Length),
		})
	}
	table.Render()
}
Пример #15
0
// Sort stable sorts the pages given the receiver's sort order.
func (by pageBy) Sort(pages Pages) {
	ps := &pageSorter{
		pages: pages,
		by:    by, // The Sort method's receiver is the function (closure) that defines the sort order.
	}
	sort.Stable(ps)
}
Пример #16
0
// Called by the TableView to sort the model.
func (m *ServerListModel) Sort(col int, order walk.SortOrder) error {
	m.sortColumn, m.sortOrder = col, order

	sort.Stable(m)

	return m.SorterBase.Sort(col, order)
}
Пример #17
0
// Given a list of KeyStores in order of listing preference, pretty-prints the
// root keys and then the signing keys.
func prettyPrintKeys(keyStores []trustmanager.KeyStore, writer io.Writer) {
	var info []keyInfo

	for _, store := range keyStores {
		for keyID, keyIDInfo := range store.ListKeys() {
			info = append(info, keyInfo{
				role:     keyIDInfo.Role,
				location: store.Name(),
				gun:      keyIDInfo.Gun,
				keyID:    keyID,
			})
		}
	}

	if len(info) == 0 {
		writer.Write([]byte("No signing keys found.\n"))
		return
	}

	sort.Stable(keyInfoSorter(info))

	tw := initTabWriter([]string{"ROLE", "GUN", "KEY ID", "LOCATION"}, writer)

	for _, oneKeyInfo := range info {
		fmt.Fprintf(
			tw,
			fourItemRow,
			oneKeyInfo.role,
			truncateWithEllipsis(oneKeyInfo.gun, maxGUNWidth, true),
			oneKeyInfo.keyID,
			truncateWithEllipsis(oneKeyInfo.location, maxLocWidth, true),
		)
	}
	tw.Flush()
}
Пример #18
0
// Pretty-prints the list of provided Roles
func prettyPrintRoles(rs []*data.Role, writer io.Writer, roleType string) {
	if len(rs) == 0 {
		writer.Write([]byte(fmt.Sprintf("\nNo %s present in this repository.\n\n", roleType)))
		return
	}

	// this sorter works for Role types
	sort.Stable(roleSorter(rs))

	tw := initTabWriter([]string{"ROLE", "PATHS", "KEY IDS", "THRESHOLD"}, writer)

	for _, r := range rs {
		var path, kid string
		pp := prettyPaths(r.Paths)
		if len(pp) > 0 {
			path = pp[0]
		}
		if len(r.KeyIDs) > 0 {
			kid = r.KeyIDs[0]
		}
		fmt.Fprintf(
			tw,
			fourItemRow,
			r.Name,
			path,
			kid,
			fmt.Sprintf("%v", r.Threshold),
		)
		printExtraRoleRows(tw, pp, r.KeyIDs)
	}
	tw.Flush()
}
Пример #19
0
// UpdateMany adds multiple new metadata for the given GUN. RethinkDB does
// not support transactions, therefore we will attempt to insert the timestamp
// last as this represents a published version of the repo.  However, we will
// insert all other role data in alphabetical order first, and also include the
// associated timestamp checksum so that we can easily roll back this pseudotransaction
func (rdb RethinkDB) UpdateMany(gun string, updates []MetaUpdate) error {
	// find the timestamp first and save its checksum
	// then apply the updates in alphabetic role order with the timestamp last
	// if there are any failures, we roll back in the same alphabetic order
	var tsChecksum string
	for _, up := range updates {
		if up.Role == data.CanonicalTimestampRole {
			tsChecksumBytes := sha256.Sum256(up.Data)
			tsChecksum = hex.EncodeToString(tsChecksumBytes[:])
			break
		}
	}

	// alphabetize the updates by Role name
	sort.Stable(updateSorter(updates))

	for _, up := range updates {
		if err := rdb.UpdateCurrentWithTSChecksum(gun, tsChecksum, up); err != nil {
			// roll back with best-effort deletion, and then error out
			rollbackErr := rdb.deleteByTSChecksum(tsChecksum)
			if rollbackErr != nil {
				logrus.Errorf("Unable to rollback DB conflict - items with timestamp_checksum %s: %v",
					tsChecksum, rollbackErr)
			}
			return err
		}
	}
	return nil
}
Пример #20
0
func (whisper *Whisper) UpdateMany(points []*TimeSeriesPoint) (err error) {
	// recover panics and return as error
	defer func() {
		if e := recover(); e != nil {
			err = errors.New(e.(string))
		}
	}()

	// sort the points, newest first
	reversePoints(points)
	sort.Stable(timeSeriesPointsNewestFirst{points})

	now := int(time.Now().Unix()) // TODO: danger of 2030 something overflow

	var currentPoints []*TimeSeriesPoint
	for _, archive := range whisper.archives {
		currentPoints, points = extractPoints(points, now, archive.MaxRetention())
		if len(currentPoints) == 0 {
			continue
		}
		// reverse currentPoints
		reversePoints(currentPoints)
		whisper.archiveUpdateMany(archive, currentPoints)

		if len(points) == 0 { // nothing left to do
			break
		}
	}
	return
}
Пример #21
0
func (by OIby) Sort(taxonomy OrderedTaxonomy) {
	ps := &orderedTaxonomySorter{
		taxonomy: taxonomy,
		by:       by, // The Sort method's receiver is the function (closure) that defines the sort order.
	}
	sort.Stable(ps)
}
Пример #22
0
Файл: gas.go Проект: moshee/gas
// ParseAcceptHeader parses and sort a list of accepted media types as appears
// in the client's Accept header. If an error is encountered, ParseAcceptHeader
// will do the best it can with the rest and return the first error
// encountered.
func ParseAcceptHeader(h string) (accepts AcceptList, e error) {
	types := strings.Split(h, ",")
	accepts = make(AcceptList, 0, len(types))

	for _, t := range types {
		mediaType, params, err := mime.ParseMediaType(t)
		if err != nil {
			if e == nil {
				e = fmt.Errorf("ParseAcceptHeader: %v", err)
			}
			continue
		}
		a := AcceptHeader{Type: mediaType}
		if q, ok := params["q"]; ok {
			qval, err := strconv.ParseFloat(q, 32)
			if err != nil {
				if e == nil {
					e = fmt.Errorf("ParseAcceptHeader: %v", err)
				}
				continue
			}
			a.Q = float32(qval)
		} else {
			a.Q = 1.0
		}
		accepts = append(accepts, a)
	}

	sort.Stable(accepts)
	return
}
Пример #23
0
func TestSpecCoverage(t *testing.T) {
	if !*coverSpec {
		t.Skip()
	}

	loadSpecOnce.Do(loadSpec)

	var (
		list     []specPart
		cv       = defaultSpecCoverage.coverage
		total    = len(cv)
		complete = 0
	)

	for sp, touched := range defaultSpecCoverage.coverage {
		if touched {
			complete++
		} else {
			list = append(list, sp)
		}
	}
	sort.Stable(bySpecSection(list))

	if testing.Short() && len(list) > 5 {
		list = list[:5]
	}

	for _, p := range list {
		t.Errorf("\tSECTION %s: %s", p.section, p.sentence)
	}

	t.Logf("%d/%d (%d%%) sentances covered", complete, total, (complete/total)*100)
}
Пример #24
0
func TestInterfaceIPSorting(t *testing.T) {
	sortedIIPs := getTestIPs()
	var unsortedIIPs = make([]interfaceIP, len(sortedIIPs))
	copy(unsortedIIPs, sortedIIPs)

	// Shuffle unsortedIIPs
	rand.Seed(1) // Deterministic
	for i := range unsortedIIPs {
		j := rand.Intn(i + 1)
		unsortedIIPs[i], unsortedIIPs[j] = unsortedIIPs[j], unsortedIIPs[i]
	}

	// Do Stable Sort
	sort.Stable(ByInterfaceThenIP(unsortedIIPs))

	if !reflect.DeepEqual(unsortedIIPs, sortedIIPs) {
		t.Errorf("Interface IPs are not sorted as expected")

		t.Log("=== EXPECTED ===")
		for _, ip := range sortedIIPs {
			t.Logf("%s: %s", ip.Name, ip)
		}

		t.Log("=== ACTUAL ===")
		for _, ip := range unsortedIIPs {
			t.Logf("%s: %s", ip.Name, ip)
		}
	}
}
Пример #25
0
func (r *reconcile) disjoinTargets() (hostnameTargetMapping map[string]*storage.Target, err error) {
	var targets []*storage.Target

	r.store.VisitTargets(func(t *storage.Target) error {
		targets = append(targets, t)
		return nil
	})

	sort.Stable(sort.Reverse(targetSorter(targets)))

	// Hostname-target mapping.
	hostnameTargetMapping = map[string]*storage.Target{}
	for _, tgt := range targets {
		tgt.Satisfy.ReducedNames = nil
		for _, name := range tgt.Satisfy.Names {
			_, exists := hostnameTargetMapping[name]
			if !exists {
				hostnameTargetMapping[name] = tgt
				tgt.Satisfy.ReducedNames = append(tgt.Satisfy.ReducedNames, name)
			}
		}
	}

	// Debugging information.
	for name, tgt := range hostnameTargetMapping {
		log.Debugf("disjoint hostname mapping: %s -> %v", name, tgt)
	}

	return
}
Пример #26
0
func (mx *mux) topServers(key *engine.BackendKey) ([]engine.Server, error) {
	metrics := map[string]*sval{}
	for _, f := range mx.frontends {
		if key != nil && key.Id != f.backend.backend.Id {
			continue
		}
		for _, s := range f.backend.servers {
			val, ok := metrics[s.URL]
			if !ok {
				sval, err := newSval(s)
				if err != nil {
					return nil, err
				}
				metrics[s.URL] = sval
				val = sval
			}
			if err := f.watcher.collectServerMetrics(val.m, val.u); err != nil {
				return nil, err
			}
		}
	}
	servers := make([]engine.Server, 0, len(metrics))
	for _, v := range metrics {
		stats, err := engine.NewRoundTripStats(v.m)
		if err != nil {
			return nil, err
		}
		v.srv.Stats = stats
		servers = append(servers, *v.srv)
	}
	sort.Stable(&serverSorter{es: servers})
	return servers, nil
}
Пример #27
0
func (by MenuEntryBy) Sort(menu Menu) {
	ms := &MenuSorter{
		menu: menu,
		by:   by, // The Sort method's receiver is the function (closure) that defines the sort order.
	}
	sort.Stable(ms)
}
Пример #28
0
// Sort sorts the entries collection.
func (fe *FuzzyEntries) Sort() {
	// If this method is left undefined, when fe.Sort() is called, the
	// Entries.Sort method will be called. In its context, the receiver is
	// Entries, therefore, Entries.Less, and not FuzzyEntries.Less, will be
	// called during sorting.
	sort.Stable(fe)
}
Пример #29
0
// splitIntoRuns breaks the values into runs of contiguous sequences.
// For example, given 1,2,3,5,6,7 it returns {1,2,3},{5,6,7}.
// The input slice is known to be non-empty.
func splitIntoRuns(values []Value) [][]Value {
	// We use stable sort so the lexically first name is chosen for equal elements.
	sort.Stable(byValue(values))
	// Remove duplicates. Stable sort has put the one we want to print first,
	// so use that one. The String method won't care about which named constant
	// was the argument, so the first name for the given value is the only one to keep.
	// We need to do this because identical values would cause the switch or map
	// to fail to compile.
	j := 1
	for i := 1; i < len(values); i++ {
		if values[i].value != values[i-1].value {
			values[j] = values[i]
			j++
		}
	}
	values = values[:j]
	runs := make([][]Value, 0, 10)
	for len(values) > 0 {
		// One contiguous sequence per outer loop.
		i := 1
		for i < len(values) && values[i].value == values[i-1].value+1 {
			i++
		}
		runs = append(runs, values[:i])
		values = values[i:]
	}
	return runs
}
Пример #30
0
//SolveZipfSong returns the answer to the solution, given that the right arguments has been provided.
//Otherwise it will return an error.
//songs: value range from 1 to maximum of 50000 songs.
//selection: value range from 1 to (length of songs) - 1.
func (z *ZipfSong) SolveZipfSong(selection int32) ([]QualitySong, error) {
	total := int32(len(z.songs))
	//As prescribed in the puzzle rules
	if total == 0 && total > 5e4 && selection <= 0 && selection > total {
		return nil, fmt.Errorf("Bad arguments: [selection: %d, total: %d]. Bounds are (1 ≤ total ≤ 50000, 1 ≤ selection ≤ total)", selection, total)
	}
	result := make(qualitySongs, len(z.songs))
	var i int64
	for _, k := range z.songs {
		f_i := k.Played
		if f_i < 0 || f_i > 10e12 {
			//As prescribed in the puzzle rules
			return nil, fmt.Errorf("Song name: %s has been played: %d times, which is out of bounds: 0 ≤ fi ≤ 10^12", k.Name, k.Played)
		}
		name := strings.TrimSpace(k.Name) //There would be no whitespace, since we control our test cases, but just for a saftey.
		if len(name) > 30 {
			//As prescribed in the puzzle rules
			return nil, fmt.Errorf("Song named: %s exceeds the name length of maximum 30 characters", k.Name)
		}
		if !correctTextFormat(name) {
			//As prescribed in the puzzle rules
			return nil, fmt.Errorf("Song named: %s is not the correct format: [a-z0-9_]", k.Name)
		}
		result[i] = QualitySong{float64(f_i * (i + 1)), name}
		i++

	}
	sort.Stable(result)            //Preferring Stable method over the Sort, because Sort does not guarantee ordering, and I am not sure if the ordering matters.
	return result[:selection], nil //You may wonder, why I return a []QualitySong instead of the predefined type qualitySongs. That is because I am not interested in exposing the sort inheritance.
}