| Bytes | Lang | Time | Link |
|---|---|---|---|
| 082 | Python 3 | 250328T092904Z | smots-18 |
| 001 | Unary | 141217T222904Z | Optimize |
| 026 | Common Lisp 23 | 141217T214602Z | coredump |
Python 3, 82 AST stmt./expr. tokens
from ast import parse, stmt, expr, iter_child_nodes
def f(node, node_list=[]):
# node: str | AST
# node_list: list[AST] = []
# # Just uncomment this whole section to get normal code I guess
# # Did you know: I can't have a docstring because that costs 1 node
# if isinstance(node, AST):
# # Undefined behaviour here
# # (I exploit that this doesn't change node to save bytes)
# parsed_node = parse(node)
# else:
# # Just a string
# parsed_node = parse(node)
# for child in iter_child_nodes(parsed_node):
# # So basically, just this:
for child in iter_child_nodes(parse(node)):
# Add this child (in place)
node_list+=child,
# Add the recursive-children of this child
# (ignore return value here)
f(child,node_list)
# Return sum of
return sum(
# Amount of fields
len(n._fields)
# per every node in node_list
for n in node_list
# that is either a statement or an expression
if isinstance(n,(stmt,expr))
)
It feels really weird to not be golfing...
Unfortunately, only usable once (as node_list=[] is initialised but never reset on future calls)
f(node) takes in anything acceptable to ast.parse (e.g. string of Python code) and returns the number of statement/expression fields in it. f(node,[<stuff>, ...]) recursively appends all children of the given node to the given list, then gets the number of stmt/expr fields for EACH node.
Tried to keep it as close to the spirit as possible while remaining 'official' (That's really subjective anyways.) Strange details resulting from this include (iirc) a having 3 tokens but import antigravity having only 1 token.
Uses a technically undefined implementation detail whereby ast.parse uses compile(), but only the latter "officially" supports ast.Module types. Don't be surprised if this breaks on newer Python versions or specific implementations
Without most comments (but still readable):
from ast import parse, stmt, expr, iter_child_nodes
def f(node, node_list=[]):
# node: str | AST
# node_list: list[AST] = []
for child in iter_child_nodes(parse(node)):
node_list+=child,
f(child,node_list)
return sum(
len(n._fields)
for n in node_list
if isinstance(n,(stmt,expr))
)
Unary, 1
The program is a string of 47297560408284 zeroes
i.e.
000000000000000000000000000000000000000000.... 47297560408284 times
A brainfuck quivalent code would be
+[>+<+++++]>--.
which just prints 1
as in unary, the whole program is made up of just 0 which are all a single token.
Common Lisp - 23 26
Here is the example answer:
(labels ((sum (s form)
(if (typep form 'sequence)
(max (1+ s) (reduce #'sum form :initial-value s))
(1+ s))))
(defmacro atomic-count (form) (sum 0 form)))
And here we can see the macro scoring itself:
(atomic-count
(labels ((sum (s form)
(if (typep form 'sequence)
(max (1+ s) (reduce #'sum form :initial-value s))
(1+ s))))
(defmacro atomic-count (form) (sum 0 form))))
=> 26
NB. This never terminates (or, badly) with cyclic expressions built with #1= and #1# reader macros.
(edit) Empty sequences should count as 1 token