Evaluating Parentheses and Brackets as Integers
CJam, 23
q"])(""1]:*0]:+["4/ers~
With BIG credits to Dennis! Try it online
Explanation:
The program converts the input to a CJam expression then evaluates it.
[…]
becomes […1]:*
(append 1 and multiply)
(…)
becomes […0]:+
(append 0 and add)
q read input
"])(" characters we want to replace
"1]:*0]:+[" replacement strings, concatenated
4/ split into strings of length 4: ["1]:*" "0]:+" "["]
er replace (transliterate) the 3 characters with the 3 strings
s convert the result (mixed characters and strings) to string
~ evaluate
Common Lisp - 98
(lambda(s)(eval(read-from-string(#1=ppcre:regex-replace-all"\\["(#1#"]"(#1#"\\("s"(+")")")"(*"))))
- Replace
(
by(+
- Replace
[
by(*
- Replace
]
by)
- Read from string
- Eval
This requires cl-ppcre
library to be loaded in current lisp image.
Explanation
Functions *
and +
are variadic and return their neutral value when given no arguments.
For your examples, the evaluated lisp form are the following ones:
(+ (*) (+ (+)) (+ (*) (*)) (* (+)) (* (+ (* (*) (*)) (*) (*)) (+ (*) (*))))
=> 9
and
(* (+ (*) (*) (*) (*) (*)) (+ (*) (*) (*)) (+ (*) (*) (*))
(+ (+ (+ (+ (+ (+ (*) (*))))))))
=> 90
Without regexes - 183 bytes
(lambda(s)(do(r(x(coerce s'list))c)((not x)(eval(read-from-string(coerce(reverse r)'string))))(setq c(pop x))(push(case c(#\[ (push #\* r)#\()(#\] #\))(#\( (push #\+ r) #\()(t c))r)))
C'mon, Lisp - 16 bytes (experimental)
+((<r*([<r)]<rRE
Other languages are so terse that I am tempted to make my own golfing language based on Common Lisp, for shorter string manipulations. Currently there is no spec, and the eval function is the following one:
(defun cmon-lisp (expr &rest args)
(apply
(lambda (s)
(let (p q)
(loop for c across expr
do (case c
(#\< (push (pop p) q))
(#\r
(let ((a1 (coerce q 'string)) (a2 (coerce p 'string)))
(setf p nil
q nil
s
(cl-ppcre:regex-replace-all
(cl-ppcre:quote-meta-chars a1) s a2))))
(#\R
(setf s
(if (string= s "")
nil
(read-from-string s))))
(#\E (setf s (eval s)))
(t (push c p))))
s))
args))
Tests:
(cmon-lisp "+((<r*([<r)]<rRE" "([] [] ([] []))")
=> 4
- there is an implicit argument called
s
and two stacks,p
andq
. - characters in source code are pushed to
p
. <
: pops fromp
and pushes toq
.r
: replaces ins
(must be a string) from characters inq
to charactes inp
; result is stored ins
;p
andq
are emptied.R
: read from strings
, store result in variables
.E
: eval forms
, store result ins
.
Pyth, 35 34 33 bytes
L?*F+1yMbqb+YbsyMbyvsXzJ"])"+R\,J
Demonstration.
1 byte thanks to @Jakube.
We start by parsing the input. The input format is close to Python, but not quite. We need commas after each parenthesized or bracketed group. The comma at the end of a bracketed group is unnecessary, but harmless. To accomplish this, we use this code:
vsXzJ"])"+R\,J
X Translate
z in the input
"])" the characters "])"
J which we will save to J to
J J
+R\, with each character mapped to itself plus a ",".
s Combine the list to a string.
v Evaluate as a Python literal.
This will leave an extra ,
at the end of the string, which will wrap the whole object in a tuple, but this is harmless, because the tuple will be summed, and so have a value equal to its element.
Now that the string is parsed, we must find its value. This is done using a user defined function, y
, which is called on the parsed object. the function is defined as follows:
L?*F+1yMbqb+YbsyMb
L Define a function, y(b), which returns the following:
? qb+Yb We form a ternary whose condition is whether the input, b,
equals the inputplus the empty list, Y. This is true if
and only if b is a list.
yMb If so, we start by mapping y over every element of b.
*F+1 We then take the product of these values. The +1 ensures
that the empty list will return 1.
yMb Otherwise, we start by mapping y over every element of b.
s Then, we sum the results.