Lua, 162 151 150 bytes
- -11 bytes thanks to my idea of using
load
instead of function(...) end
- -1 byte by omitting newline
l,p=...print(((math.ceil(load('return '..p:gsub('.',load'n=l:find(...,1,1)return n and n-1'))()-0.5)..''):gsub('%d',load'c=...+1 return l:sub(c,c)')))
Try it online!
Not shortest thing in the world (Lua forces you to be fancy quite hard, especially by huge keywords), but was pretty fun to create. Full program taking input as arguments and printing result.
Explanation
Introduction
l,p=...
Assign values from arguments to variables. Our dictionary is l
and expression is p
.
Following expression is quite hard to understand because it have a weird order of execution, so I'll explain it step-by-step:
Converting to normal numbers
p:gsub('.',
load'n=l:find(...,1,1)return n and n-1')
Perform replacement on expression string: take each symbol and pass it to function (load
proved itself to be shorted than normal declaration here).
Function finds position of occurrence in dict string for passed symbol using find
. ...
is first (and only) argument here as we're in vaarg function (any load
ed one is) that is our current symbol. Following arguments are required to make find
ignore special symbols (1
is just short value which evaluates as true
when converted to boolean): starting position (one is default here) and plain
, which actually disables pattern handling. Without those program fails on third test case due to %
being special.
If match is found, subtract one as Lua strings (and arrays btw) are 1-based. If no match is found, it will return nothing, resulting in no replacement being done.
Solving
math.ceil(load('return '..ABOVE)()-0.5)
Prepend return
to our expression to let it return result, calculate it by compiling as Lua function and calling it, perform rounding (this turned other way around to make it shorter).
It the end we get a numerical solution to our problem, only converting it back remains.
Making it crazy again
(ABOVE..'')
:gsub('%d',load'c=...+1 return l:sub(c,c)')
First line is a short way to convert number to string, so now we can call string methods in a short way. Let's do so!
Now gsub
is called again to replace everything back to insanity. This time %d
is used instead of .
as replacement pattern as our function may and must process only numbers (.
would result to error on negative numbers). This time function (load
ed again to save bytes) first adds 1
to its first (and only) vaargument, converting it to position in dict string, then returns character from it at that position.
Hooray, almost there!
Dramatic finale, or Why Brackets Matter
print((ABOVE))
Well… why two pairs of brackets anyways? It's time to talk about parall… eh, multiple return in Lua. Thing is that one function may return few values from one call (look at this meta question for more examples).
Here, last gsub
returned two values: answer string we need and amount of replacements done (count of digits actually, but who cares). If it wasn't for internal pair, both string and number would be printed, screwing us up. So here we sacrifice two bytes to omit second result and finally print product of this insanity factory.
Well, I've enjoyed explaining almost as much as golfing in first place, hope you got what's going on here.
@AdmBorkBork I should change that! Mistake! – Bill W – 2019-08-08T15:16:07.953
Yes, @Veskah, I should have specified (will edit after this comment). This is my first post here, so some mistakes certainly were made! I'll address space as well. – Bill W – 2019-08-08T15:17:34.177
9The 2nd test case suggests that the final output is rounded, otherwise the result would be
q.ioiopewioyetqorw...
. If so, what kind of rounding should be applied? – Arnauld – 2019-08-08T15:26:05.223Can we use proper mathematical symbols instead of
*
and/
? – Adám – 2019-08-08T15:27:34.6901@Arnauld Round to nearest integer. I should have been more clear, thanks for your comment. – Bill W – 2019-08-08T15:29:33.287
@Adám What did you have in mind? I'm trying to limit the number of symbols you can use as they are exceptions to what can be in the numeral system. – Bill W – 2019-08-08T15:31:06.107
@BillW please edit the challenge to clarify that we need to round to the nearest integer. Thanks! – Giuseppe – 2019-08-08T16:02:16.257
1Welcome to the site! How does the
/
operator work? From the example it seems to be some integer approximation of division but explaining it in the post is preferable to having to guess from incomplete examples. Similarly to what extent must-
be supported can the input ever contain two or more-
s in a row or a-
after another operator? A firm definition of what the input might look like rather than a vague intuition would be very nice. – Post Rock Garf Hunter – 2019-08-08T16:11:50.6502
To add to @SriotchilismO'Zaic 's point, we also have a sandbox for your benefit and ours; the intent is to let the community help refine challenges before they are posted. Nice idea for a challenge, though!
– Giuseppe – 2019-08-08T16:16:45.363@BillW You know, the normal symbols:
×
for multiplication and÷
for division. – Adám – 2019-08-08T16:21:00.2603Different languages are likely to evaluate the same equation differently, I'm not sure there is any way around it. For example, T-SQL returns
1
for5/3
, not2
, due to integer division (not rounding). This doesn't invalidate the challenge, but you may have to allow different acceptable answers for the same test case (see my T-SQL answer below). – BradC – 2019-08-08T16:30:39.593@BradC I thought that was implied. Same thing goes for order of execution. – Adám – 2019-08-08T16:45:30.950
2@Giuseppe Wow, I have browsed this stack for a long while and never knew of that! Would have definitely been helpful, especially as the first time poster (long time listener) that I am. Will keep note for next time! Thanks for your comment and answer. – Bill W – 2019-08-08T17:06:41.780
Oh I just realized, the values starting with
0
were screwing up my math because they were being treated as octal... – Patrick Roberts – 2019-08-09T00:58:07.487Bill for the last time go play outside! - Mom – Julien Lopez – 2019-08-09T06:55:57.887
2An interesting variation on this would be one that supports any number base, depending on the length of the first string in the input... – Darrel Hoffman – 2019-08-09T13:54:39.477