I have to check the variable values by using TLA+ in TLC. For example
Res_Word == {"_","N"}
variables my_variable = "Some_valueONE"
Check == my_variable \in Res_Word
* means check it if variable contains some of the specific value as required in set.
what is your specific problem with the provided approach? Here's a PlusCal example.
---- MODULE test ----
EXTENDS Integers, Sequences, TLC, FiniteSets
(* --algorithm test
variables res_positive_match = "N", res_negative_match = "Y";
define
Res_Word == {"_","N","M"}
NotInResWord == res_negative_match \in Res_Word
end define;
begin P:
print <<"res_positive_match:", res_positive_match \in Res_Word>>;
print <<"res_negative_match:", res_negative_match \in Res_Word, "NotInResWord:", NotInResWord>>;
print <<"sets matching:", {"N","_"} \subseteq Res_Word>>;
end algorithm; *)
\* BEGIN TRANSLATION
\* END TRANSLATION
=====
Which outputs something like:
<<"res_positive_match:", TRUE>>
<<"res_negative_match:", FALSE, "NotInResWord:", FALSE>>
<<"sets matching:", TRUE>>
Related
I understand that for variable part select, there can't be a variable on both sides of the colon:
a_vect[ 8*i +: 8] // == a_vect[(8*i+7) : 8*i]
However, I need to convert this code:
a_vect[(i*16+3)%64 : (i*16)%64]
How do I deal with the "%64" on both sides of the colon?
The +3 won't cause the mod to wrap, so just remove it:
a_vect[(i*16)%64 +: 4]
(If it did, the original code wouldn't work anyway.)
Alternatively, you can use shift operation:
temp = (a_vect >> ((i*16)%64));
If temp variable is not defined as 4-bit, use:
temp = (a_vect >> ((i*16)%64)) & 4'hF;
a_vect[(i*16+3)%64 : (i*16)%64]
when elaborated
i=0 ==> a_vect[3:0]
i=1 ==> a_vect[19:16]
i=2 ==> a_vect[35:32]
i=3 ==> a_vect[51:48]
i=4 ==> a_vect[3:0]
u can use this type
for(genvar i=0;i<64;i+16)
a_vect[i+:4]
I am having some issues with some code I wrote for this problem:
“Write a function namedd calc that will evaluate a simple arithmetic expression. The input to your program will be a string of the form:
operand1 operator operand2
where operand1 and operand2 are non-negative integers and operator is a single-character operator, which is either +, -, or *. You may assume that there is a space between each operand and the operator. You may further assume that the input is a valid mathemat- ical expression, i.e. your program is not responsible for the case where the user enters gibberish.
Your function will return an integer, such that the returned value is equal to the value produced by applying the given operation to the given operands.
Sample execution:
calc("5 + 10") # 15
“You may not use the split or eval functions in your solution.
Hint: the hard part here is breaking the input string into its three component. You may use the find and rfind functions to find the position of the first and last space, and then use the slice operator (that is, s[startindex:endindex]) to extract the relevant range of characters. Be careful of off-by-one errors in using the slice operator.
Hint: it’s best to test your code as you work. The first step should be to break the input string into its three components. Write a program that does that, have it print out the operator and the two operands on separate lines, and test it until you are convinced that it works. Then, modifying it to perform the desired mathematical operation should be straightforward. Test your program with several different inputs to make sure it works as you expect.”
Here is my code:
def calc(exp):
operand1 = int(exp[:1])
operand2 = int(exp[4:6])
operator = exp[2:3]
if(operator == "+"):
addition = operand1+operand2
return addition
if(operator == "-"):
subtraction = operand1-operand2
return subtraction
if(operator == "*"):
multiplication = operand1*operand2
return multiplication
print(calc("5 + 10"))
print(calc("4 - 8"))
print(calc("4 * 3"))
My code does not fully meet the criteria of this question. It only works for single digit numbers. How can I make my code work for any number?
Like:
“504 + 507”
”5678 + 76890”
and so on?
Thank you. Any help is appreciated.
As the hint says, get the position of the first and last space of the expression, use it to extract the operand and the operators, and then evaluate accordingly.
def calc(exp):
#Get the position for first space with find
low_idx = exp.find(' ')
#Get the position for last space with rfind
high_idx = exp.rfind(' ')
#Extract operators and operand with slice, converting operands to int
operand1 = int(exp[0:low_idx])
operator = exp[low_idx+1:high_idx]
operand2 = int(exp[high_idx:])
result = 0
#Evaluate based on operator
if operator == '+':
result = operand1 + operand2
elif operator == '-':
result = operand1 - operand2
elif operator == '*':
result = operand1 * operand2
return result
print(calc("5 + 10"))
print(calc("4 - 8"))
print(calc("4 * 3"))
print(calc("504 + 507"))
print(calc("5678 + 76890"))
#15
#-4
#12
#1011
#82568
The answer is in the specification:
You may use the find and rfind functions to find the position of the first and last space, and then use the slice operator (that is, s[startindex:endindex]) to extract the relevant range of characters.
find and rfind are methods of string objects.
You could split it into three components using this code: (note: this doesn't use split or eval)
def splitExpression(e):
numbers = ["1","2","3","4","5","6","7","8","9","0"] # list of all numbers
operations = ["+","-","*","/"] # list of all operations
output = [] # output components
currentlyParsing = "number" # the component we're currently parsing
buildstring = "" # temporary variable
for c in e:
if c == " ":
continue # ignore whitespace
if currentlyParsing == "number": # we are currently parsing a number
if c in numbers:
buildstring += c # this is a number, continue
elif c in operations:
output.append(buildstring) # this component has reached it's end
buildstring = c
currentlyParsing = "operation" # we are expecting an operation now
else:
pass # unknown symbol!
elif currentlyParsing == "operation": # we are currently parsing an operation
if c in operations:
buildstring += c # this is an operation, continue
elif c in numbers:
output.append(buildstring) # this component has reached it's end
buildstring = c
currentlyParsing = "number" # we are expecting a number now
else:
pass # unknown symbol!
if buildstring: # anything left in the buffer?
output.append(buildstring)
buildstring = ""
return output
Usage: splitExpression("281*14") returns ["281","*","14"]
This function also accepts spaces between numbers and operations
You can simply take the string and use the split method for the string object, which will return a list of strings based on some separator.
For example:
stringList = "504 + 507".split(" ")
stringList will now be a list such as ["504", "+", "507"] due to the separator " " which is a whitespace. Then just use stringList[1] with your conditionals to solve the problem. Additionally, you can use int(stringList[0]) and int(stringList[2]) to convert the strings to int objects.
EDIT:
Now I realized that your problem said to use find() instead of split(). Simply use the logic above but instead find(" ") the first whitespace. You will then need to find the second whitespace by slicing past the first whitespace using the two additional arguments available for find().
You need to split the string out instead of hard coding the positions of the indexes.
When coding you want to try to make your code as dynamic as possible, that generally means not hard coding stuff that could be a variable or in this case could be grabbed from the spaces.
Also in the if statements I modified them to elif as it is all one contained statement and thus should be grouped.
def calc(exp):
vals = exp.split(' ')
operand1 = int(vals[0])
operand2 = int(vals[2])
operator = vals[1]
if operator == '+':
return operand1+operand2
elif operator == '-':
return operand1-operand2
else:
return operand1*operand2
Is it possible to initialize list using macros and then with another macro generate 2 sets of functions in 2 different modules based on that list?
Pseudo code example:
defmodule ABC do
defmacro rules() do
quote do
defrule("a")
|> defrule("b")
|> defrule("c")
end
end
end
defmodule BasicTokenizer do
use TokenizerBuilder
require ABC
ABC.rules()
|> deftokenizer()
end
defmodule ExtendedTokenizer do
use TokenizerBuilder
require ABC
ABC.rules()
|> defrule("d")
|> deftokenizer()
end
import ExUnit.Assertions, only: [assert: 1, assert: 2]
assert BasicTokenizer.tokenize("a") == "a"
assert BasicTokenizer.tokenize("b") == "b"
assert BasicTokenizer.tokenize("c") == "c"
assert ExtendedTokenizer.tokenize("a") == "a"
assert ExtendedTokenizer.tokenize("b") == "b"
assert ExtendedTokenizer.tokenize("c") == "c"
assert ExtendedTokenizer.tokenize("d") == "d"
I tried following approach but I'm stuck in deftokenizer:
defmodule TokenizerBuilder do
defmacro __using__(_) do
quote do
require unquote(__MODULE__)
import unquote(__MODULE__)
end
end
defmacro defrule(str) do
quote do
[unquote(str)]
end
end
defmacro defrule(rules, str) do
quote do
Enum.concat(unquote(rules), [unquote(str)])
end
end
defmacro deftokenizer(rules) do
# rules is AST, how to get builded list value outside quote?
Enum.each(rules, fn(str) ->
quote do
def tokenize(unquote(str)) do
unquote(str)
end
end
end)
end
end
It's hard to tell exactly what you're asking for but consider this code:
iex(1)> f = &String.upcase/1
&String.upcase/1
iex(2)> g = &String.trim/1
&String.trim/1
iex(3)> h = &String.reverse/1
&String.reverse/1
iex(4)> fs = [f,g,h]
[&String.upcase/1, &String.trim/1, &String.reverse/1]
iex(5)> r = for f <- fs, do: f.("hello")
["HELLO", "hello", "olleh"]
I mean if you're trying to build a list of functions to apply to a value, then this may work. I think there are ways to build a list of functions to apply to a value without having to resort to macros to do so. But your use case is far from clear to me.
I want to build a constructor with keyword arguments inside of a macro, and the first keyword argument needs to be for an expression. I am having trouble putting that expression into the expression. Here's what I mean. Say I have a type
type Test
ex
end
which holds an expression. I want to make a constructor where origex = :(a * b) is the default from a keyword argument. I tried
#eval :(Test(ex=$origex) = Test(origex))
But if you look at the expression that makes:
Test(ex=a * b) = begin # console, line 1:
Test(origex)
end
you see that it won't work because the a*b needs to still be an expression. So I tried
#eval :(Test(ex=:($origex)) = Test(origex))
but this has the odd expression
Test(ex=$(Expr(:quote, :($(Expr(:$, :origex)))))) = begin # console, line 1:
Test(origex)
end
which also won't eval. Instead I need to get
Test(ex=:(a * b)) = begin # console, line 1:
Test(origex)
end
as the expression to eval, but I don't know how to get that expression into an expression.
I think the following is what you want. You seem to have had a few mistakes:
julia> type Test
ex::Expr
end
julia> orig_ex = :(a + b)
:(a + b)
julia> new_ex = Meta.quot(orig_ex)
:($(Expr(:quote, :(a + b))))
julia> code = :( Test(; ex=$new_ex) = Test(ex) )
:(Test(; ex=$(Expr(:quote, :(a + b)))) = begin # REPL[4], line 1:
Test(ex)
end)
julia> eval(code)
Test
julia> Test()
Test(:(a + b))
I was writing a macro #vcomp (vector comprehension) based on Python's list comprehensions with a conditional clause to filter elements in a succinct way.
macro vcomp(comprehension::Expr, when::Symbol, condition)
comp_head, comp_args = comprehension.head, comprehension.args
comp_head ∉ [:comprehension, :typed_comprehension] && error("#vcomp not a comprehension")
when ≠ :when && error("#vcomp expected `when`, got: `$when`")
T = comp_head == :typed_comprehension ? comp_args[1] : nothing
if VERSION < v"0.5-"
element = comp_head == :comprehension ? comp_args[1] : comp_args[2]
sequence = comp_head == :comprehension ? comp_args[2] : comp_args[3]
else
element = comp_head == :comprehension ? comp_args[1].args[1] : comp_args[2].args[1]
sequence = comp_head == :comprehension ? comp_args[1].args[2] : comp_args[2].args[2]
end
result = T ≠ nothing ? :($T[]) : :([])
block = Expr(:let, Expr(:block,
Expr(:(=), :res, result),
Expr(:for, sequence,
Expr(:if, condition,
Expr(:call, :push!, :res, element))),
:res))
return esc(block)
end
Used like this:
julia> #vcomp Int[i^3 for i in 1:10] when i % 2 == 0
5-element Array{Int64,1}:
8
64
216
512
1000
Which expand to this:
julia> macroexpand(:(#vcomp Int[i^3 for i in 1:15] when i % 2 == 0))
:(let
res = Int[]
for i = 1:15
if i % 2 == 0
push!(res,i ^ 3)
end
end
res
end)
I was expecting to be able to write block like this:
block = quote
let
res = $result
for $sequence
if $condition
push!(res, $element)
end
end
res
end
end
Which gives the following error:
ERROR: syntax: invalid iteration specification
Instead of the way I came up with:
block = Expr(:let, Expr(:block,
Expr(:(=), :res, result),
Expr(:for, sequence,
Expr(:if, condition,
Expr(:call, :push!, :res, element))),
:res))
However I was able to do it using Expr(:for, ...) directly as shown above and as far as I understand this is a parser error (is this a bug?). I have also been unable to find examples of this kind of interpolation, this is what I've tried:
julia> ex₁ = :(i in 1:10)
:($(Expr(:in, :i, :(1:10))))
julia> ex₂ = :(i = 1:10)
:(i = 1:10)
julia> quote
for $ex₁
ERROR: syntax: invalid iteration specification
julia> quote
for $ex₂
ERROR: syntax: invalid iteration specification
Construct whole expression and inspect it:
julia> ex₃ = quote
for i in 1:10
print(i)
end
end
quote # none, line 2:
for i = 1:10 # none, line 3:
print(i)
end
end
julia> ex₃.args
2-element Array{Any,1}:
:( # none, line 2:)
:(for i = 1:10 # none, line 3:
print(i)
end)
julia> ex₃.args[2].args
2-element Array{Any,1}:
:(i = 1:10)
quote # none, line 3:
print(i)
end
julia> ex₃.args[2].args[1]
:(i = 1:10)
julia> ex₃.args[2].args[1] == ex₂ # what's the difference then?
true
This works but is less readable:
julia> ex₄ = Expr(:for, ex₁, :(print(i)))
:(for $(Expr(:in, :i, :(1:10)))
print(i)
end)
julia> ex₅ = Expr(:for, ex₂, :(print(i)))
:(for i = 1:10
print(i)
end)
julia> eval(ex₃)
12345678910
julia> eval(ex₄)
12345678910
julia> eval(ex₅)
12345678910
Is there a way I can use the more terse syntax instead? I find the current implementation difficult to read and reason about compared to what I was expecting to write.
First of all, I belive that comprehensions with guards are coming to Julia (in v0.5?).
To answer your question: The parser wants to be able to verify that its input is syntactically correct without looking into the actual value that is interpolated. Try eg
x, y = :i, :(1:10)
quote
for $x = $y
end
end
Now the parser can recognize the relevant parts of the syntax. (And you should get the same AST if you use for $x in $y instead.)