# S-99-93

P93 (***) Arithmetic puzzle: Given a list of integer numbers, find a correct way of inserting arithmetic signs such that the result is a correct equation. The idea to the problem is from Roland Beuret. Thanx.

Example: With the list of numbers [2,3,5,7,11] we can form the equations 2-3+5+7 = 11 or 2 = (3*5+7)/11 (and ten others!).

• (p93 '(2 3 5 7 11) '() '() '())
• 2 = 3-(5+(7-11))
• 2 = 3-(5+7-11)
• 2 = 3-(5+7)+11
• 2-(3-(5+7)) = 11
• 2 = 3-5-(7-11)
• 2 = 3-5-7+11
• 2-(3-5-7) = 11
• 2-(3-5)+7 = 11
• 2*(3-5) = 7-11
• 2 = (3*5+7)/11
• 2-3+(5+7) = 11
• 2-3+5+7 = 11
``` ; remaining = list of number still to add
; val-stack = evaluated numbers on stack
; str-stack = expression strings corresponding to val-stack
; prec-stack = precedence of stack for parenthesis
; 0 = number, 1 = mul and div, 2 = add and sub
; if left op is <= current, no need to paren
; if right op is < current, no need to paren
(define (p93 remaining val-stack str-stack prec-stack)
(if (and (null? remaining) (= (length val-stack) 2) )
; time to check for equality
(cond ((= (first val-stack) (second val-stack))
(display (second str-stack))
(display " = ")
(display (first str-stack))
(newline)))
(begin
(cond ((not (null? remaining))
; push another number (precedence 2) on the stack, increasing depth by 1
(p93 (cdr remaining)
(cons (car remaining) val-stack)
(cons (number->string (car remaining)) str-stack)
(cons 2 prec-stack))))
(cond ((>= (length val-stack) 2)
; try each operator on the top two stack elements, push result, strings, and precedence
(let ((try-op (lambda (op-func op-str op-prec)
(p93 remaining
(cons (op-func (second val-stack) (first val-stack)) (cddr val-stack))
(cons (parenth (second str-stack) (second prec-stack) (first str-stack) (first prec-stack) op-str op-prec) (cddr str-stack))
(cons op-prec (cddr prec-stack))))))
(try-op + "+" 0)
(try-op - "-" 0)
(try-op * "*" 1)
(cond ( (not (= (first val-stack) 0))
(try-op / "/" 1)))))))))
(define (parenth left-str left-prec right-str right-prec op-str op-prec)
(string-append
(if (>= left-prec op-prec)
left-str
(string-append "(" left-str ")"))
op-str
(if (> right-prec op-prec)
right-str
(string-append "(" right-str ")"))))
(define first car)