func (n NoteMap) Replaced(from, to core.Sequenceable) core.Sequenceable {
	if core.IsIdenticalTo(n, from) {
		return to
	}
	notelike, ok := n.Target.Value().(core.NoteConvertable)
	if !ok {
		return n
	}
	note, err := notelike.ToNote()
	if err != nil {
		return n
	}
	return NoteMap{
		Target:        core.On(note.Replaced(from, to)),
		Indices:       n.Indices,
		indicesFormat: n.indicesFormat,
		maxIndex:      n.maxIndex}
}
Replaced is part of Replaceable
package op
import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"github.com/emicklei/melrose/core"
	"github.com/emicklei/melrose/notify"
)
const (
	formatDotAndBangs = iota
	formatNumbers
)
type NoteMap struct {
	Target        core.HasValue
	Indices       []int
	indicesFormat int
	maxIndex      int
}
func NewNoteMap(indices string, note core.HasValue) (NoteMap, error) {
	idx := []int{}
	var parsed [][]int
	format := formatNumbers
	var maxIndex int
	if strings.ContainsAny(indices, "!.") {
		parsed = parseIndices(convertDotsAndBangs(indices))
		format = formatDotAndBangs
		maxIndex = len(indices)
	} else if strings.ContainsAny(indices, "1234567890 ") {  
		parsed = parseIndices(indices)
	} else {
		return NoteMap{}, errors.New("bad syntax NoteMap; must have digits,spaces OR dots and exclamation marks")
	}
	for _, each := range parsed {
		idx = append(idx, each[0])
	}
	max := sliceMax(idx)
	if max > maxIndex {
		maxIndex = max
	}
	return NoteMap{
		Target:  note,
		Indices: idx,
		indicesFormat: format,
		maxIndex:      maxIndex,
	}, nil
}
func convertDotsAndBangs(format string) string {
	var b bytes.Buffer
	for i, each := range []rune(format) {
		if each == '.' {
			fmt.Fprintf(&b, "  ")
		} else {
			fmt.Fprintf(&b, "%d ", i+1)
		}
	}
	return b.String()
}
func (n NoteMap) formattedIndices(format int) string {
	var b bytes.Buffer
	if format == formatDotAndBangs {
		for i := 1; i <= n.maxIndex; i++ {
			found := false
			for _, each := range n.Indices {
				if each == i {
					found = true
					break
				}
			}
			if found {
				fmt.Fprintf(&b, "!")
			} else {
				fmt.Fprintf(&b, ".")
			}
		}
	} else {
		for i, each := range n.Indices {
			if i > 0 {
				fmt.Fprintf(&b, " ")
			}
			fmt.Fprintf(&b, "%d", each)
		}
	}
	return b.String()
}
func (n NoteMap) Storex() string {
	st, ok := n.Target.(core.Storable)
	if !ok {
		st, ok = n.Target.Value().(core.Storable)
	}
	if ok {
		return fmt.Sprintf("notemap('%s',%s)", n.formattedIndices(n.indicesFormat), st.Storex())
	}
	return ""
}
func (n NoteMap) Inspect(i core.Inspection) {
	if n.indicesFormat == formatDotAndBangs {
		i.Properties["nrs"] = n.formattedIndices(formatNumbers)
	} else {
		i.Properties["dots"] = n.formattedIndices(formatDotAndBangs)
	}
	n.S().Inspect(i)
}
func sliceMax(indices []int) int {
	max := 0
	for _, each := range indices {
		if each > max {
			max = each
		}
	}
	return max
}
func (n NoteMap) S() core.Sequence {
	var note core.Note
	notelike, ok := n.Target.Value().(core.NoteConvertable)
	if !ok {
		seq, ok := n.Target.Value().(core.Sequenceable)
		if !ok {
			notify.Console.Errorf("cannot map %v (%T)", n.Target.Value(), n.Target.Value())
			return core.EmptySequence
		}
		notes := seq.S()
		if len(notes.Notes) == 0 || len(notes.Notes[0]) == 0 {
			return core.EmptySequence
		}
		note = notes.Notes[0][0]
	} else {
		var err error
		note, err = notelike.ToNote()
		if err != nil {
			notify.Panic(err)
			return core.EmptySequence
		}
	}
	notes := make([]core.Note, n.maxIndex)
	for i := range notes {
		notes[i] = note.ToRest()
	}
	for _, each := range n.Indices {
		notes[each-1] = note
	}
	return core.BuildSequence(notes)
}