-2^2 (infix notation) should translate to -2 2 ^ (postfix notation). It does as expected however when evaluating that postfix it evaluates to 4 not -4 which is what is expected.
I'm using Lua and here's my precedence & associativity tables:
-- Precedence table for different operators
local PRECEDENCE = {
[Token.Type.MINUS] = 0,
[Token.Type.PLUS] = 0,
[Token.Type.ASTERIK] = 1,
[Token.Type.SLASH] = 1,
[Token.Type.CARET] = 2,
[Token.Type.UMINUS] = 3
}
-- Associativity table for different operators
-- 0 = LTR (Left To Right)
-- 1 = RTL (Right To Left)
local ASSOCIATIVITY = {
[Token.Type.MINUS] = 0,
[Token.Type.PLUS] = 0,
[Token.Type.ASTERIK] = 0,
[Token.Type.SLASH] = 0,
[Token.Type.CARET] = 1,
[Token.Type.UMINUS] = 1
}
When trying to evaluate -2^2 my output queue looks like this:
{
2,
UMINUS,
2,
CARET
}
Here's my parser. It's worth noting that queue and stack are "classes" with their respective functionality.
--[[
Parse tokens
]]
function Parser:parse()
self:preprocess() -- Convert valid MINUS tokens into UMINUS
while (self.token) do
local token = self.token
if (token.type == Token.Type.NUMBER) then
self.queue:enqueue(tonumber(token.value))
elseif (isOperator(token)) then -- PLUS, MINUS, SLASH, ASTERIK, UMINUS, CARET
while (not self.stack:isEmpty()
and ASSOCIATIVITY[token.type]
and PRECEDENCE[token.type]
and ASSOCIATIVITY[self.stack:top().type]
and PRECEDENCE[self.stack:top().type]
and ((ASSOCIATIVITY[token.type] == 0 and PRECEDENCE[token.type] <= PRECEDENCE[self.stack:top().type])
or (ASSOCIATIVITY[token.type] == 1 and PRECEDENCE[token.type] < PRECEDENCE[self.stack:top().type]))) do
self.queue:enqueue(self.stack:pop())
end
self.stack:push(token)
elseif (token.type == Token.Type.LPAREN) then
self.stack:push(token)
elseif (token.type == Token.Type.RPAREN) then
while (self.stack:top().type ~= Token.Type.LPAREN) do
self.queue:enqueue(self.stack:pop())
end
self.stack:pop()
end
self:next() -- Move to the next token
end
while (not self.stack:isEmpty()) do
self.queue:enqueue(self.stack:pop())
end
return self.queue
end
What am I doing wrong? I tried an online calculator here and I also get 4 yet I know the correct output should be -4 for that expression.
To get the result you expect, the carat must have a higher precedence than unary minus. That's how it works in Lua's operator precedence. The postfix notation for -2^2 should actually be 2 2 ^ UMINUS. Remember that the square of any real number is always positive. You could just swap the precedence levels:
[Token.Type.CARET] = 3,
[Token.Type.UMINUS] = 2,
Related
Quick explanation, I have recently started using codewars to further improve my programming skills and my first challenge was to make a roman numeral decoder, I went through many versions because I wasnt satisfied with what I had, So I am asking if there is an easier way of handling all the patterns that roman numerals have, for example I is 1 but if I is next to another number it takes it away for example V = 5 but IV = 4.
here is my CODE:
function Roman_Numerals_Decoder (roman)
local Dict = {I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000}
local number = 0
local i = 1
while i < #roman + 1 do
local letter = roman:sub(i,i) -- Gets the current character in the string roman
if roman:sub(i,i) == "I" and roman:sub(i + 1,i + 1) ~= "I" and roman:sub(i + 1,i + 1) ~= "" then -- Checks for the I pattern when I exists and next isnt I
number = number + (Dict[roman:sub(i +1,i + 1)] - Dict[roman:sub(i,i)]) -- Taking one away from the next number
i = i + 2 -- Increase the counter
else
number = number + Dict[letter] -- Adds the numbers together if no pattern is found, currently checking only I
i = i + 1
end
end
return number
end
print(Roman_Numerals_Decoder("MXLIX")) -- 1049 = MXLIX , 2008 = MMVIII
at the moment I am trying to get 1049 (MXLIX) to work but I am getting 1069, obviously I am not following a rule and I feel like its more wrong then it should be because usually if its not correct its 1 or 2 numbers wrong.
The algorithm is slightly different: you need to consider subtraction when the previous character has less weight than the next one.
function Roman_Numerals_Decoder (roman)
local Dict = {I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, M = 1000}
local num = 0
local i = 1
for i=1, #roman-1 do
local letter = roman:sub(i,i) -- Gets the current character in the string roman
local letter_p = roman:sub(i+1,i+1)
if (Dict[letter] < Dict[letter_p]) then
num = num - Dict[letter] -- Taking one away from the next number
print("-",Dict[letter],num)
else
num = num + Dict[letter] -- Adds the numbers together if no pattern is found, currently checking only I
print("+",Dict[letter],num)
end
end
num = num + Dict[roman:sub(-1)];
print("+",Dict[roman:sub(-1)], num)
return num
end
print(Roman_Numerals_Decoder("MXLIX")) -- 1049 = MXLIX , 2008 = MMVIII
In order not to get rusty I want to refresh my knowledge of pure ruby by solving some algorithms. I can't solve a larger algorithm without solving a smaller one like the example below.
Have the function missing_digit(str) take the str parameter, which will be a simple mathematical formula with three numbers, a single operator (+, -, *, or /) and an equal sign (=) and return the digit that completes the equation. In one of the numbers in the equation, there will be an x character, and your program should determine what digit is missing. For example, if str is "3x + 12 = 46" then your program should output 4.
Examples
Input: "4 - 2 = x"
Output: 2
Input: "1x0 * 12 = 1200"
Output: 0
I think I found the solution for python but I can't find the corresponding Ruby code anywhere.
Python and Ruby are quite similar, though trying to convert this without some basic TDD would have been difficult. Here is the converted to Ruby file from your python example. I would refactor this code but the simple tests here pass, those given in your linked example.
string_math_x.rb
class StringMathX
def self.calculate(str)
exp = str.split()
first_operand = exp[0]
operator = exp[1]
second_operand = exp[2]
resultant = exp[-1]
# If x is present in resultant
if resultant[/x/]
first_operand = first_operand.to_i
second_operand = second_operand.to_i
if operator == '+'
res = first_operand + second_operand
elsif operator == '-'
res = first_operand - second_operand
elsif operator == '*'
res = first_operand * second_operand
else
res = first_operand / second_operand
end
return res
end
# If x in present in operands
# If x in the first operand
if first_operand == 'x'
x = first_operand.to_i
second_operand = second_operand.to_i
if operator == '+'
res = resultant - second_operand
elsif operator == '-'
res = resultant + second_operand
elsif operator == '*'
res = resultant / second_operand
else
res = resultant / second_operand
end
# If x is in the second operand
else
x = second_operand.to_i
first_operand = first_operand.to_i
if operator == '+'
res = resultant-first_operand
elsif operator == '-'
res = first_operand - second_operand
elsif operator == '*'
res = resultant.to_i / first_operand.to_i
else
res = first_operand.to_i / resultant.to_i
end
end
res = res.to_s
k = 0
for i in [*0..x]
if i == x
result = res[k]
break
else
k += 1
end
end
result.to_i
end
end
./test/test.rb
require 'minitest/autorun'
require_relative '../lib/string_math_x'
class StringMathXTest < Minitest::Test
def test_basic_subtration
input = '4 - 2 = x'
assert(StringMathX.calculate(input) == 2, 'outputs 2')
end
def test_whats_up_returns_doc
input = '1x0 * 12 = 1200'
assert(StringMathX.calculate(input) == 0, 'outputs 0')
end
end
To run this you may need to gem install minitest
Then run ruby test/test.rb
def findx(str)
s = str.sub('=', '==')
i = s.index('x')
pre = s[0,i]
post = s[i+1..-1]
('0'..'9').find { |d| eval(pre+d+post) rescue nil }&.to_i
end
findx("4 - 2 = x") #=> 2
findx("1x0 * 12 = 1200") #=> 0
findx("3**x = 81") #=> 4
findx("1/x == 2.0").nil? #=> true
rescue nil is needed in case division by zero is performed. & is the safe harbor operator. It returns nil, disregarding all that follows, if the part before it returns nil.
I am working on some assembly program analysis task using Z3. And I am trapped in simulating the semantics of x86 opcode bsf.
The semantics of bsf operand1 operand2 is defined as searches the source operand (operand1) for the least significant set bit (1 bit).
Its semantics can be simulated in C as:
if(operand1 == 0) {
ZF = 0;
operand2 = Undefined;
}
else {
ZF = 0;
Temporary = 0;
while(Bit(operand1, Temporary) == 0) {
Temporary = Temporary + 1;
operand2 = Temporary;
}
}
Right now, suppose each operand (e.g., register) maintains a symbolic expression, I am trying to simulate the above semantics in Z3Py. The code I wrote is something like this (simplified):
def aux_bsf(x): # x is operand1
if simplify(x == 0):
raise Exception("undefined in aux_bsf")
else:
n = x.size()
for i in range(n):
b = Extract(i, i, x)
if simplify(b == 1):
return BitVecVal(i, 32)
raise Exception("undefined in bsf")
However, I find that the evaluation of simplify(x==0) (e.g., x equals BitVecVal(13, 32) + BitVec("symbol1", 32),) is always equal to True. In other words, I am always trapped in the first exception!
Am I doing anything wrong here..?
====================================================
OK, so I think what I need is something like:
def aux_bsf(x):
def aux(x, i):
if i == 31:
return 31
else:
return If(Extract(i, i, x) == 1, i, aux(x, i+1))
return aux(x, 0)
simplify(x == 0) returns an expression, it does not return True/False, where False = 0. Python would treat an expression reference as a non-zero value and therefore take the first branch. Unless 'x' is a bit-vector constant, simplification would not return a definite value. The same issue is with simplify(b == 1).
You could encode such functions as a relation between operand1 and operand2, e.g., something along the lines of:
def aux_bsf(s, x, y):
for k in range(x.size()):
s.Add(Implies(lsb(k, x), y == k)
def lsb(k, x):
first0 = True
if k > 0:
first0 = Extract(x, k-1,0) == 0
return And(Extract(x,k,k) == 1, first0)
You can also use uninterpreted functions for the cases where aux_bsf is under-specified.
For example:
def aux_bsf(x):
bv = x.sort()
bsf_undef = Function('bsf-undef', bv, bv)
result = bsf_undef(x)
for k in reverse(range(bv.size()))
result = If(Extract(x, k, k) == 1), BitVecVal(k, bv), result)
return result
def reverse(xs):
....
I'm trying to find a way to do element-by-element comparison in Lua using the standard < operator. For example, here's what I'd like to do:
a = {5, 7, 10}
b = {6, 4, 15}
c = a < b -- should return {true, false, true}
I already have code working for addition (and subtraction, multiplication, etc). My issue is that Lua forces the result of a comparison to a boolean. I don't want a boolean, I want a table as the result of the comparison.
Here is my code so far, with addition working, but less-than comparison not working:
m = {}
m['__add'] = function (a, b)
-- Add two tables together
-- Works fine
c = {}
for i = 1, #a do
c[i] = a[i] + b[i]
end
return c
end
m['__lt'] = function (a, b)
-- Should do a less-than operator on each element
-- Doesn't work, Lua forces result to boolean
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
end
a = {5, 7, 10}
b = {6, 4, 15}
setmetatable(a, m)
c = a + b -- Expecting {11, 11, 25}
print(c[1], c[2], c[3]) -- Works great!
c = a < b -- Expecting {true, false, true}
print(c[1], c[2], c[3]) -- Error, lua makes c into boolean
The Lua programming manual says that the result of the __lt metamethod call is always converted to a boolean. My question is, how can I work around that? I heard that Lua is good for DSL, and I really need the syntax to work here. I think it should be possible using MetaLua, but I'm not really sure where to start.
A coworker suggested that I just use << instead with the __shl metamethod. I tried it and it works, but I really want to use < for less than, rather than a hack using the wrong symbol.
Thanks!
You only have two choices to make this work with your syntax:
Option 1: Patch the Lua core.
This is probably going to be very difficult, and it'll be a maintenance nightmare in the future. The biggest issue is that Lua assumes on a very low level that the comparison operators <, >, ==, ~= return a bool value.
The byte-code that Lua generates actually does a jump on any comparison. For example, something like c = 4 < 5 gets compiled to byte-code that looks much more like if (4 < 5) then c = true else c = false end.
You can see what the byte-code looks like with luac -l file.lua. If you compare the byte-code of c=4<5 with c=4+5 you'll see what I mean. The addition code is shorter and simpler. Lua assumes you'll do branching with comparisons, not assignment.
Option 2: Parse your code, change it, and run that
This is what I think you should do. It would be very hard, expect most of the work is already done for you (using something like LuaMinify).
First of all, write a function you can use for comparisons of anything. The idea here is to do your special comparison if it's a table, but fall back on using < for everything else.
my_less = function(a, b)
if (type(a) == 'table') then
c = {}
for i = 1, #a do
c[i] = a[i] < b[i]
end
return c
else
return a < b
end
end
Now all we need to do is replace every less than operator a<b with my_less(a,b).
Let's use the parser from LuaMinify. We'll call it with the following code:
local parse = require('ParseLua').ParseLua
local ident = require('FormatIdentity')
local code = "c=a*b<c+d"
local ret, ast = parse(code)
local _, f = ident(ast)
print(f)
All this will do is parse the code into a syntax tree, and then spit it back out again. We'll change FormatIdentity.lua to make it do the substitution. Replace the section near line 138 with the following code:
elseif expr.AstType == 'BinopExpr' then --line 138
if (expr.Op == '<') then
tok_it = tok_it + 1
out:appendStr('my_less(')
formatExpr(expr.Lhs)
out:appendStr(',')
formatExpr(expr.Rhs)
out:appendStr(')')
else
formatExpr(expr.Lhs)
appendStr( expr.Op )
formatExpr(expr.Rhs)
end
That's all there is to it. It will replace something like c=a*b<c+d with my_less(a*b,c+d). Just shove all your code through at runtime.
Comparisons in Lua return a boolean value.
There is nothing you can do about it short of changing the core of Lua.
Can you put up with a bit verbose v()-notation:
v(a < b) instead of a < b ?
local vec_mt = {}
local operations = {
copy = function (a, b) return a end,
lt = function (a, b) return a < b end,
add = function (a, b) return a + b end,
tostring = tostring,
}
local function create_vector_instance(operand1, operation, operand2)
local func, vec = operations[operation], {}
for k, elem1 in ipairs(operand1) do
local elem2 = operand2 and operand2[k]
vec[k] = func(elem1, elem2)
end
return setmetatable(vec, vec_mt)
end
local saved_result
function v(...) -- constructor for class "vector"
local result = ...
local tp = type(result)
if tp == 'boolean' and saved_result then
result, saved_result = saved_result
elseif tp ~= 'table' then
result = create_vector_instance({...}, 'copy')
end
return result
end
function vec_mt.__add(v1, v2)
return create_vector_instance(v1, 'add', v2)
end
function vec_mt.__lt(v1, v2)
saved_result = create_vector_instance(v1, 'lt', v2)
end
function vec_mt.__tostring(vec)
return
'Vector ('
..table.concat(create_vector_instance(vec, 'tostring'), ', ')
..')'
end
Usage:
a = v(5, 7, 10); print(a)
b = v(6, 4, 15); print(b)
c = a + b ; print(c) -- result is v(11, 11, 25)
c = v(a + b); print(c) -- result is v(11, 11, 25)
c = v(a < b); print(c) -- result is v(true, false, true)
As others have already mentioned, there is no straight-forward solution to this. However, with the use of a generic Python-like zip() function, such as the one shown below, you can simplify the problem, like so:
--------------------------------------------------------------------------------
-- Python-like zip() iterator
--------------------------------------------------------------------------------
function zip(...)
local arrays, ans = {...}, {}
local index = 0
return
function()
index = index + 1
for i,t in ipairs(arrays) do
if type(t) == 'function' then ans[i] = t() else ans[i] = t[index] end
if ans[i] == nil then return end
end
return table.unpack(ans)
end
end
--------------------------------------------------------------------------------
a = {5, 7, 10}
b = {6, 4, 15}
c = {}
for a,b in zip(a,b) do
c[#c+1] = a < b -- should return {true, false, true}
end
-- display answer
for _,v in ipairs(c) do print(v) end
I'm currently getting familiar with the LPeg parser module. For this I want to match a version string (e.g. 11.4) against a list.
Such a list is a string with a tight syntax that can also contain ranges. Here is an EBNF-like, but in any case quite simple grammar (I write it down because LPeg code below can be a bit difficult to read):
S = R, { ',', R }
R = N, [ '-', N ]
N = digit+, [ '.', digit+ ]
An example string would be 1-9,10.1-11,12. Here is my enormous code:
local L = require "lpeg"
local LV, LP, LC, LR, floor = L.V, L.P, L.C, L.R, math.floor
local version = "7.25"
local function check(a, op, b)
if op and a+0 <= version and version <= b+0 then
return a..op..b -- range
elseif not op and floor(version) == floor(a+0) then
return a -- single item
end
end
local grammar = LP({ "S",
S = LV"R" * (LP"," * LV"R")^0,
R = LV"V" * (LC(LP"-") * LV"V")^-1 / check,
V = LC(LV"D" * (LP"." * LV"D")^-1),
D = (LR("09")^1),
})
function checkversion(str)
return grammar:match(str)
end
So you would call it like checkversion("1-7,8.1,8.3,9") and if the current version is not matched by the list you should get nil.
Now, the trouble is, if all calls to check return nothing (meaning, if the versions do not match), grammar:match(...) will actually have no captures and so return the current position of the string. But this is exactly what I do not want, I want checkversion to return nil or false if there is no match and something that evaluates to true otherwise, actually just like string:match would do.
If I on the other hand return false or nil from check in case of a non-match, I end up with return values from match like nil, "1", nil, nil which is basically impossible to handle.
Any ideas?
I think you can or + it with a constant capture of nil:
grammar = grammar + lpeg.Cc(nil)
This is the pattern I eventually used:
nil_capturing_pattern * lpeg.Cc(nil)
I incorporated it into the grammar in the S rule (Note that this also includes changed grammar to "correctly" determine version order, since in version numbering "4.7" < "4.11" is true, but not in calculus)
local Minor_mag = log10(Minor);
local function check(a, am, op, b, bm)
if op then
local mag = floor(max(log10(am), log10(bm), Minor_mag, 1))+1;
local a, b, v = a*10^mag+am, b*10^mag+bm, Major*10^mag+Minor;
if a <= v and v <= b then
return a..op..b;
end
elseif a == Major and (am == "0" or am == Minor) then
return a.."."..am;
end
end
local R, V, C, Cc = lpeg.R, lpeg.V, lpeg.C, lpeg.Cc
local g = lpeg.P({ "S",
S = V("R") * ("," * V("R"))^0 * Cc(nil),
R = (V("Vm") + V("VM")) * (C("-") * (V("Vm") + V("VM")))^-1 / check,
VM = V("D") * Cc("0"),
Vm = V("D") * "." * V("D"),
D = C(R("09")^1),
});
Multiple returns from match are not impossible to handle, if you catch them in a way that makes handling them easier. I added a function matched that does that, and added the fallback return of false to your check.
do
local L = require "lpeg"
local LV, LP, LC, LR, floor = L.V, L.P, L.C, L.R, math.floor
local version = 6.25
local function check(a, op, b)
if op and a+0 <= version and version <= b+0 then
return a..op..b -- range
elseif not op and floor(version) == floor(a+0) then
return a -- single item
end
return false
end
local grammar = LP({ "S",
S = LV"R" * (LP"," * LV"R")^0,
R = LV"V" * (LC(LP"-") * LV"V")^-1 / check,
V = LC(LV"D" * (LP"." * LV"D")^-1),
D = (LR("09")^1),
})
local function matched(...)
local n = select('#',...)
if n == 0 then return false end
for i=1,n do
if select(i,...) then return true end
end
return false
end
function checkversion(ver,str)
version = ver
return matched(grammar:match(str))
end
end
I enclosed the whole thing in do ... end so that the local version which is used here as an upvalue to check would have constrained scope, and added a parameter to checversion() to make it clearer to run through few test cases. For example:
cases = { 1, 6.25, 7.25, 8, 8.5, 10 }
for _,v in ipairs(cases) do
print(v, checkversion(v, "1-7,8.1,8.3,9"))
end
When run, I get:
C:\Users\Ross\Documents\tmp\SOQuestions>q18793493.lua
1 true
6.25 true
7.25 false
8 true
8.5 true
10 false
C:\Users\Ross\Documents\tmp\SOQuestions>
Note that either nil or false would work equally well in this case. It just feels saner to have collected a list that can be handled as a normal Lua array-like table without concern for the holes.