← Home
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type Node struct {
	leaf bool
	name string
	op   byte
	l    int
	r    int
}

type OpKey struct {
	op byte
	l  int
	r  int
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)

	nodes := make([]Node, 0, 2*n+10)
	leafID := make(map[string]int)
	opID := make(map[OpKey]int)

	var getLeaf func(string) int
	getLeaf = func(name string) int {
		if id, ok := leafID[name]; ok {
			return id
		}
		id := len(nodes)
		nodes = append(nodes, Node{leaf: true, name: name})
		leafID[name] = id
		return id
	}

	getOp := func(op byte, l, r int) int {
		key := OpKey{op: op, l: l, r: r}
		if id, ok := opID[key]; ok {
			return id
		}
		id := len(nodes)
		nodes = append(nodes, Node{op: op, l: l, r: r})
		opID[key] = id
		return id
	}

	curTerm := make(map[string]int)
	var cur func(string) int
	cur = func(name string) int {
		if id, ok := curTerm[name]; ok {
			return id
		}
		id := getLeaf(name)
		curTerm[name] = id
		return id
	}

	used := make(map[string]bool)
	used["res"] = true

	for i := 0; i < n; i++ {
		var line string
		fmt.Fscan(in, &line)

		eq := strings.IndexByte(line, '=')
		lhs := line[:eq]
		rhs := line[eq+1:]

		used[lhs] = true

		pos := strings.IndexAny(rhs, "$^#&")
		if pos == -1 {
			used[rhs] = true
			curTerm[lhs] = cur(rhs)
		} else {
			a := rhs[:pos]
			op := rhs[pos]
			b := rhs[pos+1:]
			used[a] = true
			used[b] = true
			curTerm[lhs] = getOp(op, cur(a), cur(b))
		}
	}

	root := cur("res")

	if nodes[root].leaf {
		if nodes[root].name == "res" {
			fmt.Fprintln(out, 0)
		} else {
			fmt.Fprintln(out, 1)
			fmt.Fprintf(out, "res=%s\n", nodes[root].name)
		}
		return
	}

	chars := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	tempCount := 0
	nextTemp := func() string {
		for {
			x := tempCount
			tempCount++
			a := chars[(x/(62*62))%62]
			b := chars[(x/62)%62]
			c := chars[x%62]
			name := string([]byte{'Z', a, b, c})
			if !used[name] {
				used[name] = true
				return name
			}
		}
	}

	dest := make([]string, len(nodes))
	visited := make([]bool, len(nodes))
	lines := make([]string, 0, len(nodes))

	dest[root] = "res"

	var nameOf func(int) string
	nameOf = func(id int) string {
		if nodes[id].leaf {
			return nodes[id].name
		}
		return dest[id]
	}

	var dfs func(int)
	dfs = func(id int) {
		if nodes[id].leaf || visited[id] {
			return
		}
		dfs(nodes[id].l)
		dfs(nodes[id].r)
		if dest[id] == "" {
			dest[id] = nextTemp()
		}
		lines = append(lines, fmt.Sprintf("%s=%s%c%s", dest[id], nameOf(nodes[id].l), nodes[id].op, nameOf(nodes[id].r)))
		visited[id] = true
	}

	dfs(root)

	fmt.Fprintln(out, len(lines))
	for _, line := range lines {
		fmt.Fprintln(out, line)
	}
}