1 kyu

Simple Interactive Interpreter

998 of 2,404Wintermute
Description
Loading description...
Interpreters
Algorithms
  • Please sign in or sign up to leave a comment.
  • RieBI Avatar

    Your C# "tokenize" method is a mess. For some unknown reason it adds closing parenthese ")" to the end of the input. Also, the regex is a complete mess too, it does not parse numbers at all and there are other issues with it.

    Why even have such starting code if it is wrong?

  • tiagotlima Avatar

    How perform operations between numbers and functions
    x * function x y
    function x y * y

    and function and function
    functionA x y * functionB y x

  • BlockArtig2_0 Avatar

    Definetly a Tough Kata, but worth it. I learned a lot from this one :D

  • artemyev Avatar

    Looks like not all inputs are displayed in log for C#.
    For example in "conflicts" tests i can see only:

    input("fn x => 0") == <> was ok
    Test Failed
    input("f = 5") == <> and not <5> => wrong solution, aborted!
    

    But with Console.WriteLine(input) i can see:

    x = 0
    fn f => 1
    fn x => 0
    input("fn x => 0") == <> was ok
    f = 5
    Test Failed
    input("f = 5") == <> and not <5> => wrong solution, aborted!
    

    Also in "variables" tests in log i can see input("y") == <> and not <25> => wrong solution, aborted!
    But in previous "function" tests with Console.WriteLine(input) (not in default log) i can see

    x = 23
    y = 25
    z = 0
    ...
    

    So I thought there should be different scopes for different sections of the tests. If not, then the answer in "variables" tests should be y = 25

  • zwhy Avatar

    This comment has been hidden.

  • JoshuaCF Avatar

    How should the expression 5 + abc 2 + 5 3, where abc is a function with two parameters, be evaluated? This expression is permissible by the grammar, however the language spec lists + as a higher priority than functions. Intuitively, I'd want to just evaluate the function first, but that seems to go against what is explicitly stated, unless I'm misunderstanding how priority works.

    Edit: To anyone else wondering about how the priority properly works, function calls are the highest priority. Then, the operations in the table follow accordingly. Function assignment is the lowest priority.

  • lutre69 Avatar

    The error handling… This one was harder than expected, writing it while learning to type in Dvorak made it even harder :)

  • existslambda Avatar

    Please enable newer versions of Node for the JavaScript version of this kata, as it is in Simpler Interactive Interpreter. Coming from there and then having to rewrite larger parts of the existing code, because one used features that are not available in Node 8, is an unnecessary obstacle.

  • asm-jaime Avatar

    Not bad one. Can easy solve it after solve the 'Parsing and evaluation of mathematical expressions(c#)'.

  • LewisSaber Avatar

    Should have added test to check if function params are passed in right order

  • alf_aleshkov Avatar

    I think a lot needs to be done in this kata, but overall it's good. I got a lot of satisfaction while solving that kata and 2 kyu Simple Interactive Interpreter. Wanna to solve something same

  • nomennescio Avatar

    ENBF grammar is missing description of how tokens are separated by whitespace.

  • Velvacaine Avatar

    I think fn add x y => x + z should be valid because z could later be defined as a function, and the description doesn't define any scope limitations for functions.

    > fn add x y => x + z
    > fn z => 1
    > add 1 2
    2
    

    (Of course exceptions would be if add was already a variable, or if x or y were already functions, but I don't think that's true for the test case)

    Another unclear point IMO; are functions allowed to define local variables, and if so, can it then read them? I don't see anything in the description disallowing this.

    fn ex => (y=3)*y
    

    If this is allowed, it's another case where evaluating a function for validity before a function is executed more difficult.

  • AliakseiYakubuk Avatar

    As far as I can see, suggested syntax does not support such statements:

    avg(a, avg(b, avg(c, d)))
    

    I had a good time while working on this kata, but realizing that you cannot do something more powerful because of the poor function call syntax saddens me a bit

  • WinterShiver Avatar

    Suppose

    fn apply f x => f x
    fn incr x => x + 1
    

    Since function calls are right associative, then how can we parse apply incr 1 into apply incr 1 but not apply (incr 1)?

  • louisr Avatar

    Hi. I'm surprised by these two test cases that seem to contradict each other: fn x => 0 must raise an error according to the button test, fn one => 1 must be a valid function with no arguments and always return 1 according to the attempt.

    In my opinion the first test case means 'a function must have a name' but in that case x could be considered to be the name of a function..

    Should the test case be modified? How did you managed this?

  • fantajeon Avatar

    It takes one weeks for solving this problem. I've got alot of things about Rust.

  • alexc19 Avatar

    I had fun solving this. It is not super hard if one already knows the classic technique. Supporting functions makes it indeed harder than the 2 kyu version. I'm only partially happy with my code, I think I could get rid of some redundancy with some good refactoring.

  • Persa Avatar

    I dont understand this is note valid 'fn x => 0 x() = 0 and fn one = 1 is valid name of funciton = x x dont have any argument ı think this should be valid to

  • pl3onasm Avatar

    Currently input("avg 4 2 + avg 10 30") with output 13.0 is accepted, whereas you would like it to be 23.0 It's the difference between avg 4 (2+avg 10 30) = 13.0 and (avg 4 2) + (avg 10 30) = 23.0

  • wittor Avatar

    This comment has been hidden.

  • user5853455 Avatar

    Kotlin translation added :D

  • user7531853 Avatar

    not the value of the global variable, when evaluating the epxression.

    Did you mean expression?

  • ivysola Avatar

    This comment has been hidden.

  • _Evgene_96_ Avatar

    Please can help you learn how to solve the same problems at least approximately, I mean what topics you need to know ideally, or maybe some articles to read, that's how you got to this level(very important), please write!, here's my mail: zhenya.orlov86@mail.ru

  • DunetsNM Avatar
    1. No tests where previously declared variables are used as function arguments? e.g. avg x y. Seems like a basic use case and grammar allows it.
    2. There's a test where function invocation used as argument e.g. avg echo 2 echo 5 echo 7, but again no variables in sight. How about avg echo x echo 2 echo y, it would require truly context-aware parsing that needs to distinguish vars from funcs and understand number of parameters, atm it's more or less easy to hack it through
  • bdw429s Avatar

    The original author is inactive. Any chance of getting some eyes on my CFML Translation? Thanks!

  • bdw429s Avatar

    Having completed this in JavaScript, I noticed some of the tests enforced typing, meaning if my code returned "5" instead of 5, the test failed. The input is tokenized into all strings to start wtih and it didn't seem right to make any assumptions about types, nor did the instructions give any direction in the typing system of the language we were supposed to be implementing. Is this an oversight in the JS test cases to enforce numeric returns or a valid requirement that just wasn't explicitly stated in the dsecription?

  • pointbazaar Avatar

    love the kata. There is so much in there to learn. Grammar transformations, applying Visitor pattern, ...

    There are some ambiguities such as order of evaluation, e.g. "4 / 2 * 3" is 6.0 according to the kata, but could be 2/3 also, but these can be resolved through debug statements.

  • S.py Avatar

    I do not believe the problem description uniquely specifies the result of the following:

    fn f x y => x * y
    f 2 3 + 4
    

    This could either return 10 or 9, depending on whether it is evaluated as (f 2 3) + 4, or f 2 (3 + 4).

    Function calls should thus be added to the precedence table.

  • EugZol Avatar

    It should be mentioned explicitly in the problem description that all calculations are to be made with floats, not integers.

    It is reasonable to assume by default that "5 / 3 = 1", especially given that Ruby works in that manner.

  • EugZol Avatar

    The following test case should be added (or similar):

    fn f1 a1 a2 => a1 * a2
    fn f2 a1 a2 a3 => a1 * a2 * a3
    f2 f2 1 2 3 f1 4 5 f1 6 7
    # => 5040
    

    This will check that function composition is parsed correctly, i.e. above expression is parsed as f2 (f2 1 2 3) (f1 4 5) (f1 6 7).

    Without that explicit test wrong programs will fail at random tests, leading to tedious and exhausting debugging.

  • drseg Avatar

    Another weird Ruby issue:

    My solution passes, but only if I evaluate the input string before calling my code (for example by printing it, or just by evaluating it without doing anything with the output). If I don't do that, tests 12 14 and 16 counting back from the end consistently fail. Weird, no?

  • drseg Avatar

    After passing the first 318 tests I'm getting the following error in Ruby. It appears to be in the test code because my code is never actually called by the test that rasies this.

    <NoMethodError: undefined method to_postfix' for main:Object> main.rb:483:in helper_3' main.rb:399:in solution' main.rb:629:in block (3 levels) in

    ' main.rb:626:in times' main.rb:626:in block (2 levels) in
    ' /runner/frameworks/ruby/cw-2.rb:180:in wrap_error' /runner/frameworks/ruby/cw-2.rb:72:in it' main.rb:514:in block in <main>' /runner/frameworks/ruby/cw-2.rb:55:in block in describe' /runner/frameworks/ruby/cw-2.rb:46:in measure' /runner/frameworks/ruby/cw-2.rb:51:in describe' main.rb:513:in `
    '

  • 为世人降下祝福 Avatar

    May I be able to know on which test case I get all shown test cases PASSED(Passed: 27 Failed: 0 Exit Code: 1) but TIMEOUT? Am I allowed to know the input of the 28th test case?

  • phaul Avatar

    Oh, boi. Got so far, user tests are passing. Then on the random tests I realize that my parser is right associative so 6/3/2 is 4 not 1.

  • matejv Avatar

    Clojure Translation. Please, review and approve.

  • qwertyu123 Avatar

    Can function change arity after overwriting? I mean if I have > fn f a => a > fn g a b => a + b > fn F a b => f g a b then F = f (g a b); but if I'll overwrite f and g: > fn f a b => a + b > fn g a => a then F becomes F = f (g a) b and that breaks AST tree for F. When I started to code I thinked that if we have > fn f a => b and then we have > fn g a b => f a b on input we should return error, but now I'm not sure.

    Should I store functions as strings and recompile them at each call? In that case I'll need to accept almost any function as I cannot correctly detect another function calls in it and then return error only when function is used; or should I check function correctness when it's provided to me?

  • user6890112 Avatar

    Feels extremely hard (and my solutions has lots of code), but definitely a nice challenge! Also nice how Rust works out here, I think it really shines here compared to e.g. C++/Javascript/Python/etc.

    By the way: could the Rust version be updated? The newer Rust version is ergonomically much nicer!

  • ZedHu Avatar

    Too much detail not show in desciption, the grammar shouldn be much clear, i really dislike the scope design and function call design ... but this kata is really great kata!

  • rehsals Avatar

    It's stated that function can access only the variables defines in it's arguments list. But what about a function calling other functions? Is it allowed?

  • FArekkusu Avatar

    C++ translation. Please, review and approve.

  • FArekkusu Avatar

    Ruby translation. Please, review and approve.

  • user6793616 Avatar

    Should x = 13 + y = 3 + 1 be allowed in the sense of x = 13 + (y = 3 + 1)? The grammar rules seem to allow it, but with the given precedence rules it would semantically not work as it would be interpreted as x = ((13 + y) = (3 + 1)). It would work if = has lower precedence over the other operators that occur to the right of it, but would have the highest precedence over all operators occurring to the left of it.

  • DDews Avatar

    For Java, tests will not compile if you have input method throw an Exception.

    Can get tests to compile by throwing Error, but then assertFail tests fail due to the error thrown.

  • notliam Avatar

    Nice kata, though missing some test cases that would make it super difficult. By the end my code was not the most elegant, and would probably fail some additional test cases.

  • NightyNight Avatar

    Which error should I raise out when I'm using Python?..

  • frogamic Avatar

    I am unclear about the function precedence: if the following input is received > func 1 + 5, is that taken to mean > (func 1) + 5 or > func (1 + 5)

  • psv Avatar

    C translation has been published.

    Could anyone review and approve it, please?

  • testAccount2019 Avatar

    This comment has been hidden.

  • milo-farrell Avatar

    Please correct me if i am wrong but doesn't this

    identifier ::= letter | '' { identifier-char } identifier-char ::= '' | letter | digit

    mean that an identifier can only have one letter if it starts with a letter not an underscore, in the tests the function names (which are id identifiers) have names like 'avg' which would seem to violate this. I may have the wrong end of the stick here so please correct me if i'm wrong.

  • rmunn Avatar

    This comment has been hidden.

  • joh_pot Avatar

    Great kata! Thanks for publishing it.

  • dramforever Avatar

    This comment has been hidden.

  • ggmoy Avatar

    Ruby-Translation kumited!

    https://www.codewars.com/kumite/58e6ab740446a02a34000198?sel=58e6ab740446a02a34000198

    Could you check and approve it, please?

  • DSchwettmann Avatar

    Finally managed to find both the time and determination to complete this.

    Hilariously enough, my solution is a fair bit shorter, and yet very descriptive and simple, then a few other solutions.

  • metalbot Avatar

    Extremely enjoyable kata. Thanks for taking the time to put this together with a clear problem statement and nice tests.

  • nomennescio Avatar

    The non-terminal for 'number' is incorrect, as it allows for empty strings. The correct one should be (using 'T+' for '(T {T})' ) number := digit+ [ '.' digit+ ] | '.' digit+

  • elmar.peise Avatar

    I think there should be a test that uses the result of a funciton call as an operand. E.g.:

    >2 + avg 1 3
        4
    
  • dnesting Avatar

    I can't get this test to pass for Python 3:

    input: 'fn add x y => x + z'

    This should raise an error, and when I test this by hand with this exact input, my code correctly raises the error about z not being recognized. All of my other tests pass. Advice? Is there a problem or quirk with this test?

  • kreitzo Avatar

    Does anyone know how I can remove this kata as 'completed' from my account? A friend completed it for funs sake and it doesn't reflect my level so would like it removed

  • ksceriath Avatar

    What should be the outcome in such a case :

    F1 x F2 y + 1

    is it F1(x,F2(y+1)) or is it F1(x,F2(y))+1 ?

    The grammer isn't clear about this.

  • flatplate Avatar

    Hey, I'm coding in python and I don't really know what to return for an error. My code returns a few error messages now but I guess they aren't accepted. And I also saw Strikeskids post about this. Is there a problem with the kata or is it just me?

  • darekl Avatar

    Nice kata series. Looks like I've learned something new about regular expressions. Thanks.

  • cactus Avatar

    The unit test definition seems to be out of date with the version of HSpec used:

    /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:40:20:
        Ambiguous occurrence `pendingWith'
        It could refer to either `SimpleInteractiveInterpreter.Test.pendingWith',
                                 defined at /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:71:1
                              or `Test.Hspec.pendingWith',
                                 imported from `Test.Hspec' at /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:4:1-17
                                 (and originally defined in `hspec-1.12.1:Test.Hspec.Core.Type')
    
  • cactus Avatar

    The unit test definition seems to be out of date with the version of HSpec used:

    /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:40:20:
        Ambiguous occurrence `pendingWith'
        It could refer to either `SimpleInteractiveInterpreter.Test.pendingWith',
                                 defined at /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:71:1
                              or `Test.Hspec.pendingWith',
                                 imported from `Test.Hspec' at /tmp/haskell11634-20-12vowd8/SimpleInteractiveInterpreter/Test.hs:4:1-17
                                 (and originally defined in `hspec-1.12.1:Test.Hspec.Core.Type')
    
  • bugman4 Avatar

    python kata:

    test.assert_equals(interpreter.input("avg avg 6 10 echo 2"), 5)

    Should this case be tested?

  • computerguy103 Avatar

    This comment has been hidden.

  • computerguy103 Avatar

    This comment has been hidden.

  • ronyhe Avatar

    Wow, this was such a great challenge! While the description is very thorough, I do have one suggestions:

    • The description implied that errors are to be handled by displaying error messages. However, the tests passes only when excpetions were raised. Please disambiguate

    Once again, I really enjoyed this. Thanks a lot for taking the time to make this happen!

  • dnolan Avatar

    Great Kata! I really enjoyed this.

  • bajdcc Avatar

    Very nice Kata with Compiling Theory. Deal with it using LL(n). And there are something about Operator Combination a=(b=1)/right or (6/3)*2/left. Dynamic Function is very interesting. A function is a block/namespace + an expression. Eval a function is to eval an expression(There are no blocks). Parsing function/invoke: func-with-n-args arg1 arg2 ... argn -> func-with-n-args exp1 exp2 ... expn

    So, wrote Expr class(AST), think about grammar(LL(n) recursion, need Compiling Theory) and start.

  • user8052336 Avatar

    There are no tests in the kata using invalid identifiers for variables and function names i.e.

    Interpreter().input("3 = 4")

  • Deffe Avatar
    identifier ::= letter | '_' { identifier-char }
    identifier-char ::= '_' | letter | digit
    

    It is mean that identifier can include more than one char only if it starts with _. Is it mistake?

  • lodborg Avatar

    Very nice and thorough description, but I think it should also specify the operator precedence with regards to function arguments. For example

    fn module x y => x % y
    modulo 42 8 + 5
    # should this be treated as 42%(8+5) or as (42%8)+5
    

    I think, the logical thing would be for it to behave like this (see below), but a specific mention in the description might help avoiding ambiguity

    Also, adding a few test cases about that might be very nice.

    # This should be treated as 42%(8+5)
    modulo 42 8 + 5
    # If we wanted (42 % 8)+5 we should have written
    (modulo 42 8) + 5
    
  • lodborg Avatar

    That was a really nice kata, had a lot of fun with it. And it took me more time than I thought it would. I will definitely have a look at some compiler theory - now I'm hooked.

  • nmagre Avatar

    I'm stuck with functions(InterpreterTest) test case.

    x = 23
    y = 25
    z = 0
    fn one => 1
    input: 'fn one => 1' expected: but was:<0.0>
    

    My code return 0.0 when a function is added (I didn't see in description what it should return). fn one => 1 looks fine for me so I return 0.0 but I guess an Exception is expected.
    conflicts test case pass and there is almost the same situation E.g : fn f => 1

    Can someone tell me why ? or what is expected ?

  • Ivana Avatar

    Nice Kata.

  • zhuli19901106 Avatar

    That was a real challenge. Took me over four hours to put it right. And I don't wanna read that code I wrote one more time. It's simply a mess... Perhaps I should've learned compiler theory at college.

    Anyway, thanks for providing such interesting problems!

  • sonofneil Avatar

    Great kata!

    4nyN4m3Fun is a valid function name?

    Thanks!

  • CIS 122 Avatar

    This was a fun kata! One suggestion is to include a list of error conditions you should check for and throw, since there were a few that I either missed in the problem description, or that weren't specified (for example, the requirement that the parameters to a function be uniquely named). Other than that, nice job!

  • joebandenburg Avatar

    This kata has a great description and set of tests. Good job :)

  • Aditu_V Avatar

    How should the state of (x=3) + (x=2) look after evaluation? {'x':2}? Or just left as undefined behaviour as it is in C?

  • idubrov Avatar

    Translated into Java.

  • heythisisdave Avatar

    This comment has been hidden.

  • daddepledge Avatar

    A top notch problem. Well defined, lucid with plenty of tests.

    Helped improve my python.

    Thanks.

  • nooga Avatar

    I get the following error:

    [eval]:53
    })();});
           
    SyntaxError: Unexpected end of input
        at Object. ([eval]-wrapper:6:22)
        at 
        at evalScript (node.js:536:25)
        at startup (node.js:80:7)
        at node.js:906:3
    

    No matter what my program is. Even with preloaded solution, example test cases.

  • outergod Avatar

    This comment has been hidden.

  • Dundee Avatar

    Very nice and well prepared Kata. Thanks!

  • tko Avatar

    I think the tests could cover few more corner cases, e.g. each of the following should probably be throwing errors

    (fn = 1)
    (fn f => 1)
    fn f => fn + 1
    fn fn => 1
    fn f a a => a
    
  • smbape Avatar

    Hello, awesome test.

    The are 3 cases that failed on present solutions at the time I am writing this.

    [expression, expected] ["9", 9] ["-9", -9] [ '-9/-3*4', 12 ]

  • SeaShore Avatar

    Is the javascript Function constructor disabled? it appears to work in the test cases but doesnt work when I submit the solution.

  • computerguy103 Avatar

    There's an error in the pre-loaded test cases:

    Test.expectError(function() { interpreter.input("avg = 5");
    

    Should be:

    Test.expectError(function() { interpreter.input("avg = 5"); });
    
  • computerguy103 Avatar

    What's the precedence for function calls? You don't specify in the description.

    E.g.

    fn twice x => 2 * x
    twice 5 + 2
    

    Should that calculate 5 + 2 first, use 7 as the argument for twice, and return 14? Or should it perform twice 5 first, then add 10 + 2, resulting in 12?

    edit: I made my solution execute function calls last, along with = (and they both associate from right to left). So twice 5 + 2 would be 14. This is the most logical, since multi-argument functions would have to execute the function call last anyway - e.g. x = twice avg 2 + 3 5 + 6, which should result in x having the value 16.

  • Strikeskids Avatar

    Your python test bench cases that check for an error are missing a string error message argument. This causes the test bench code to instantly fail when you try to test your code.

  • Fraye Avatar

    This comment has been hidden.

  • F. S. Avatar

    I enjoyed this kata very much. The only thing lacking in the description is which objects may be accessed from where:

    • Is is allways possible to create variables by assigning to them (e.g. 1+(x=2) with x undeclared)?
    • May functions access global variables (according to the test cases, the global variable z should be rejected as unknown)? May they access other functions? Should there be a test for loop-calls (since it is not possible to terminate recursion)?
    • Assume function A is declared to call a function B. If A gets redefined, which function B should be evaluated when A is called? What happens, if the redefined B has a different number of arguments?

    The test cases can be passed by short-cutting many features of the language. Functions calling other functions don't need to be supported to pass the tests as well as functions without arguments. The simplest solution just would switch-case the finite number of test cases and return the appropriate result. My solution rejects ' ' as input, which seems unintended.

    There should be at least one randomized test, preferably with functions having an unpredictable number of arguments and in unpredictable composition. Eventually, the interpreter should reject an input like '1 2', which is currently not tested. e.g. in my solution, parsing is done as far as possible and then the result is returned to the caller. The outer function must check that the whole input is read. If I left this check out, the result of evaluating '1 2' would be '1', but throwing an error makes more sense to me.

  • destel Avatar

    Seems it's not possible to build AST for function calls at compile time. For examle expression "a b c" can be treated as "a(b, c)" or "a(b(c))". Of course at runtime we can parse such expressions, since defined variables and functions are known. So, what is the proper way to parse "a b c" expression?

  • SteveRuble Avatar

    This kata is great. Hard enough to be really interesting, but not an overwhelming task. The tests are very well put together.

    Minor issues:

    In the tests for argument count it should say "too" instead of "to" in the message.

    The tests for argument count don't have complete coverage. My solution passes the test, but I realized after I submitted it that it would fail if the test was of >avg echo 1 echo 2 echo 4 rather than just having literal numbers as arguments.