{Curly Numbers};
Pyth, 35 32 bytes - 10% = 28.8
.x.U+jb`HZ*R\;.[Z2jsz4i/R\;cz\}4
Try it online: Demonstration or Test Suite
edit: As it turned out, I accidentally can also handle improper Curly Numbers. Wasn't planned at all. ;-)
Explanation:
There are two expressions in the code. The first one converts a number into a Curly Number, and the second one converts a Curly Number into a regular number. .x
handles, which expression gets printed. It will try to print the first expression. If there are any non-digits in the input, the first expression fails (via Exception). .x
catches the Exception and prints the second one.
.U+jb`HZ*R\;.[Z2jsz4 # number to Curly Number
sz read the input and converts it to an int
j 4 convert to base 4
.[Z2 pad zeros on the left, until length is >= 2
*R\; convert each digit to ";"s
lets call this list of ";"s Y
.U reduce this list, start with b=Y[0],
Z iterates over Y[1], Y[2], ...,
update b in each step with:
jb`H put b into curly brackets
+ Z and append Z
i/R\;cz\}4 # Curly Number to regular number
cz\} split the input by "}"
/R\; count the ";"s in each string
i 4 convert this list from base 4 to base 10
CJam, 51 47 44 41 bytes
r_'{-_@={i4bYUe[';f*{{}s@*\+}*}{'}/:,4b}?
Try it online: sample run | test suite
How it works
r e# Read a token from STDIN.
_'{- e# Remove all left curly brackets from a copy of the token.
_@ e# Copy the modified token and rotate the original on top of it.
= e# Check for equality.
{ e# If the strings were equal:
i4b e# Convert to integer, then to base 4.
YUe[ e# Left-pad the resulting array with zeroes to a length of 2.
';f* e# Replace each digit with that many semicolons.
{ e# For each string of semicolons but the first:
{}s e# Push the string "{}".
@ e# Rotate the first string or the result of the previous
e# iteration on top of the stack.
* e# Join, i.e., surround the string with curly brackets.
\+ e# Append the current string of semicolons to the result.
}* e#
}{ e# Else:
'}/ e# Split the modified input at right curly brackets.
:, e# Replace each run of 0 to 3 semicolons by its length.
4b e# Convert from base 4 to integer.
}? e#
Python 2, 167 bytes - 10% = 150.3
d=lambda x:("{"+d(x//4)+"}"if x>3 else"")+";"*(x%4)
c=lambda n:"{}"*(int(n)<4)+d(int(n))if n.isdigit()else reduce(lambda x,y:x*4+y,[x.count(";")for x in n.split("}")])
In this implementation, c
is the function that satisfies the requirements. It returns a string if given an nonnegative integer as input, or an integer if given a curly number as input.