← Home
For problem statement at 0-999/0-99/30-39/39/problemG.txt this is a correct solution, but verifier at 0-999/0-99/30-39/39/verifierG.go ends with case 1: runtime error: exit status 2

exit status 1 can you fix the verifier? package main

import (
	"io"
	"os"
	"strconv"
	"strings"
)

const (
	numKind = iota
	varKind
	callKind
	binKind
)

type Expr struct {
	kind       int
	val        int
	op         byte
	left, right *Expr
}

type Cond struct {
	kind       int
	left, right *Expr
}

type Stmt struct {
	cond *Cond
	expr *Expr
}

type Parser struct {
	s string
	i int
}

func (p *Parser) expect(t string) {
	if !strings.HasPrefix(p.s[p.i:], t) {
		panic("parse")
	}
	p.i += len(t)
}

func (p *Parser) parseFunction() []Stmt {
	p.expect("intf(intn){")
	var stmts []Stmt
	for p.i < len(p.s) && p.s[p.i] != '}' {
		stmts = append(stmts, p.parseStmt())
	}
	p.expect("}")
	return stmts
}

func (p *Parser) parseStmt() Stmt {
	if strings.HasPrefix(p.s[p.i:], "return") {
		p.i += len("return")
		e := p.parseExpr()
		p.expect(";")
		return Stmt{expr: e}
	}
	p.expect("if(")
	c := p.parseLogical()
	p.expect(")")
	p.expect("return")
	e := p.parseExpr()
	p.expect(";")
	return Stmt{cond: c, expr: e}
}

func (p *Parser) parseLogical() *Cond {
	l := p.parseExpr()
	if strings.HasPrefix(p.s[p.i:], "==") {
		p.i += 2
		r := p.parseExpr()
		return &Cond{kind: 2, left: l, right: r}
	}
	if p.s[p.i] == '<' {
		p.i++
		r := p.parseExpr()
		return &Cond{kind: 0, left: l, right: r}
	}
	p.i++
	r := p.parseExpr()
	return &Cond{kind: 1, left: l, right: r}
}

func (p *Parser) parseExpr() *Expr {
	return p.parseSum()
}

func (p *Parser) parseSum() *Expr {
	node := p.parseProduct()
	for p.i < len(p.s) {
		c := p.s[p.i]
		if c != '+' && c != '-' {
			break
		}
		p.i++
		r := p.parseProduct()
		node = &Expr{kind: binKind, op: c, left: node, right: r}
	}
	return node
}

func (p *Parser) parseProduct() *Expr {
	node := p.parseMultiplier()
	for p.i < len(p.s) {
		c := p.s[p.i]
		if c != '*' && c != '/' {
			break
		}
		p.i++
		r := p.parseMultiplier()
		node = &Expr{kind: binKind, op: c, left: node, right: r}
	}
	return node
}

func (p *Parser) parseMultiplier() *Expr {
	if strings.HasPrefix(p.s[p.i:], "f(") {
		p.i += 2
		arg := p.parseExpr()
		p.expect(")")
		return &Expr{kind: callKind, left: arg}
	}
	if p.s[p.i] == 'n' {
		p.i++
		return &Expr{kind: varKind}
	}
	start := p.i
	for p.i < len(p.s) && p.s[p.i] >= '0' && p.s[p.i] <= '9' {
		p.i++
	}
	v, _ := strconv.Atoi(p.s[start:p.i])
	return &Expr{kind: numKind, val: v}
}

func evalExpr(e *Expr, n int, memo []int) int {
	switch e.kind {
	case numKind:
		return e.val
	case varKind:
		return n
	case callKind:
		return memo[evalExpr(e.left, n, memo)]
	default:
		l := evalExpr(e.left, n, memo)
		r := evalExpr(e.right, n, memo)
		switch e.op {
		case '+':
			return (l + r) & 32767
		case '-':
			return (l - r) & 32767
		case '*':
			return (l * r) & 32767
		default:
			return l / r
		}
	}
}

func evalCond(c *Cond, n int, memo []int) bool {
	l := evalExpr(c.left, n, memo)
	r := evalExpr(c.right, n, memo)
	switch c.kind {
	case 0:
		return l < r
	case 1:
		return l > r
	default:
		return l == r
	}
}

func evalFunc(stmts []Stmt, n int, memo []int) int {
	for _, st := range stmts {
		if st.cond == nil || evalCond(st.cond, n, memo) {
			return evalExpr(st.expr, n, memo)
		}
	}
	return 0
}

func isSpace(c byte) bool {
	switch c {
	case ' ', '\n', '\r', '\t', '\v', '\f':
		return true
	}
	return false
}

func main() {
	data, _ := io.ReadAll(os.Stdin)
	i := 0
	for i < len(data) && isSpace(data[i]) {
		i++
	}
	j := i
	for j < len(data) && data[j] >= '0' && data[j] <= '9' {
		j++
	}
	target, _ := strconv.Atoi(string(data[i:j]))
	rest := data[j:]

	buf := make([]byte, 0, len(rest))
	for _, c := range rest {
		if !isSpace(c) {
			buf = append(buf, c)
		}
	}

	p := Parser{s: string(buf)}
	stmts := p.parseFunction()

	memo := make([]int, 32768)
	ans := -1
	for n := 0; n < 32768; n++ {
		memo[n] = evalFunc(stmts, n, memo)
		if memo[n] == target {
			ans = n
		}
	}

	os.Stdout.WriteString(strconv.Itoa(ans))
}