I'm attempting to solve AoC problem 12 part 2 in Smalltalk. The specific aren't super relevant, but here's the relevant portion of a single-dimensional version of the model I'm using for the problem:
Object subclass: Moon [
| X XX Xin |
init [
X := 0. XX := 0. Xin := 0.
]
Moon class >> new [ | moon | moon := super new. moon init. ^moon]
x: xx [
X := xx. XX := 0. Xin := xx.
]
kinetic [ ^ (XX abs) ]
initialState [ | killmeNow |
killmeNow := ((self kinetic) == 0).
killmeNow := killmeNow and: (Xin == X).
^killmeNow
]
]
moonA := Moon new.
moonA x: 1.
moonA initialState printNl.
As the variable names just might suggest, I'm failing at the highly complex task of checking if a number equals zero and a second number equals a third number. No amount of refactoring of this statement seems to change the ultimate outcome:
Object: true error: did not understand #value
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
True(Object)>>doesNotUnderstand: #value (SysExcept.st:1448)
True>>and: (True.st:116)
Moon>>initialState (omg.st:15)
UndefinedObject>>executeStatements (omg.st:22)
What is the #Value that (self kin == 0) is receiving, why is it not True, and how do I fix this?
The argument of the and: message must be a Block (and you are passing a Boolean). Just change your code like this
killmeNow := killmeNow and: [Xin == X]. "squared brackets rather that parentheses"
You could also have written the same more succinctly as
initialState [
^self kinetic = 0 and: [Xin = X]
]
but, of course, this is secondary. Note that I've used = instead of == because both have a slightly different semantics and you don't need object identity in these tests (even though == will work as well in your case).
For the sake of completeness, let me mention that there is way to and Booleans: the binary message & does that. So, you could have written
^(self kinetic = 0) & (Xin = X).
The precedence rules of the Smalltalk syntax allow you to remove the parentheses around self kinetic = 0 because here the main message is = which is also binary. The parantheses aroung Xin = X cannot be removed, otherwise & would take precedence over the last occurrence of =.
Related
I have an example of a code and not sure what way is the best to use.
For example I have
if (x = 1) and (y = 2) and (if abc = false then check if z = 3) then
begin
...
check only
if x = 1
if y = 2
if abc = false check z = 3. if abc = true then dont check z = 3
i am not sure if i am explaining the best but hopefuly people will understand.
I want to know if this is possible or the best way to do it. Keeping in mind that rather than in example where its x, y, z and abc. there can be more in my use.
I currently have structure as...which i dont think is practical, and think theres a better way but i am not sure
if (abc = false) then
begin
if (x = 1) and (y = 2) and (z = 3) then
begin
...
end
else
begin
if (x = 1) and (y = 2) then
begin
...
Thanks in advance
I think you're looking for or. Now you will check that x must be 1, y must be 2, and if abc is false, z must be 3.
If abc = true, z can still be three, but it won't be checked.
Note that I just wrote abc instead of abc = true. Since it's a Boolean (true/false) already, that's allowed.
Also note how the operations are grouped using parentheses. The total sub-expression abc or (z=3) must return true for the total expression to return true.
Furthermore the sequence of the terms is significant - they are evaluated left-to-right. If the term (abc or (z=3)) is replaced by the logically-equivalent term ((z=3) or abc) then z=3 will be evaluated.
if (x = 1) and (y = 2) and (abc or (z = 3)) then
// Your magic goes here
Test program body to prove sequence is important
function z : Integer;
begin
writeln('Z being evaluated');
result := x + y;
end;
begin
x := 1;y := 2;
abc := true;
if (x=1) and (y=2) and (abc or (z=3)) then
writeln ('evaluated true')
else
writeln ('evaluated false');
writeln('done');
readln;
end.
Neither of your code samples compile, because neither is using the proper syntax.
This should get you started:
if (x = 1) and (y = 2) then
begin
if (abc) then
// Handle abc = True
else
begin
if (z = 3) then
// Handle abc = false and z = 3
else
// Handle abc = false and z <> 3
end;
end;
Well as it generally says, I have the following situation. I wrote a "main.lua" file, which includes the other file with an object definition having the following method:
function self:Process(vRef,vOut,bNeg)
mErrO = mErrN
mErrN = (bNeg and (vOut-vRef) or (vRef-vOut)) -- Refresh error state
logStatus(nil,"MER= "..mErrO.." > "..mErrN)
local errS = getSign(mErrN)
-- P-Term
logStatus(nil,"S P: >> "..tostring(errS))
local errP = mErrN; logStatus(nil,"0 P: >> "..tostring(errP))
errP = errP^mpP; logStatus(nil,"1 P: >> "..tostring(errP))
errP = math.abs(errP); logStatus(nil,"2 P: >> "..tostring(errP))
errP = errP*errS; logStatus(nil,"3 P: >> "..tostring(errP))
As you all may see, if we have like (-198^1.01), the result must be ( respectively ) (-208.75257542111). I added the following line in the "main.lua" file:
local a = (-198^1.01)
local b = ( 198^1.01)
local c = ( 0^1.01)
logStatus(nil,"-------------Pow: {"..a..","..b..","..c.."}")
However, these are calculated correctly. I thin it is somehow related by the object and the fact that the ZeroBrane must be using an older version of Lua. Strangely when the power argument is 1,2,3,4 ... It works fine. The program output is as follows:
-------------Pow: {-208.75257542111,208.75257542111,0}
MER= 0 > -198
S P: >> -1
0 P: >> -198
1 P: >> nan
2 P: >> nan
3 P: >> nan
Any answer will be appreciated !
In your first code
local errP = mErrN; --> -198
errP = errP^mpP; --> nan
the expression being calculated is (-198)^1.01.
It is nan according to math definition of raising to power and according to the man page of pow():
pow(x, y) returns a NaN and raises the "invalid" floating-point exception for finite x < 0 and finite non-integer y.
In your second code
local a = (-198^1.01)
the expression is -(198^1.01) according to Lua operators precedence.
This expression equals to -208.75...
Probably you would want to calculate math.abs(x)^y * (x<0 and -1 or 1) instead of x^y
I am playing around with the KMP algorithm in f sharp. While it works for patterns like "ATAT" (result will be [|0; 0; 1; 2;|]) , the first while loop enters a deadlock when the first 2 characters of a string are the same and the 3rd is another, for example "AAT".
I understand why: first, i gets incremented to 1. now the first condition for the while loop is true, while the second is also true, because "A" <> "T". Now it sets i to prefixtable.[!i], which is 1 again, and here we go.
Can you guys give me a hint on how to solve this?
let kMPrefix (pattern : string) =
let (m : int) = pattern.Length - 1
let prefixTable = Array.create pattern.Length 0
// i : longest proper prefix that is also a suffix
let i = ref 0
// j: the index of the pattern for which the prefix value will be calculated
// starts with 1 because the first prefix value is always 0
for j in 1 .. m do
while !i > 0 && pattern.[!i] <> pattern.[j] do
i := prefixTable.[!i]
if pattern.[!i] = pattern.[j] then
i := !i+1
Array.set prefixTable j !i
prefixTable
I'm not sure how to repair the code with a small modification, since it doesn't match the KMP algorithm's lookup table contents (at least the ones I've found on Wikipedia), which are:
-1 for index 0
Otherwise, the count of consecutive elements before the current position that match the beginning (excluding the beginning itself)
Therefore, I'd expect output for "ATAT" to be [|-1; 0; 0; 1|], not [|0; 0; 1; 2;|].
This type of problem might be better to reason about in functional style. To create the KMP table, you could use a recursive function that fills the table one by one, keeping track of how many recent characters match the beginning, and start running it at the second character's index.
A possible implementation:
let buildKmpPrefixTable (pattern : string) =
let prefixTable = Array.zeroCreate pattern.Length
let rec run startIndex matchCount =
let writeIndex = startIndex + matchCount
if writeIndex < pattern.Length then
if pattern.[writeIndex] = pattern.[matchCount] then
prefixTable.[writeIndex] <- matchCount
run startIndex (matchCount + 1)
else
prefixTable.[writeIndex] <- matchCount
run (writeIndex + 1) 0
run 1 0
if pattern.Length > 0 then prefixTable.[0] <- -1
prefixTable
This approach isn't in danger of any endless loops/recursion, because all code paths of run either increase writeIndex in the next iteration or finish iterating.
Note on terminology: the error you are describing in the question is an endless loop or, more generally, non-terminating iteration. Deadlock refers specifically to a situation in which a thread waits for a lock that will never be released because the thread holding it is itself waiting for a lock that will never be released for the same reason.
Hello experienced pythoners.
The goal is simply to read in my own files which have the following format, and to then apply mathematical operations to these values and polynomials. The files have the following format:
m1:=10:
m2:=30:
Z1:=1:
Z2:=-1:
...
Some very similar variables, next come the laguerre polynomials
...
F:= (12.58295)*L(0,x)*L(1,y)*L(6,z) + (30.19372)*L(0,x)*L(2,y)*L(2,z) - ...:
Where L stands for a laguerre polynomial and takes two arguments.
I have written a procedure in Python which splits apart each line into a left and right hand side split using the "=" character as a divider. The format of these files is always the same, but the number of laguerre polynomials in F can vary.
import re
linestring = open("file.txt", "r").read()
linestring = re.sub("\n\n","\n",str(linestring))
linestring = re.sub(",\n",",",linestring)
linestring = re.sub("\\+\n","+",linestring)
linestring = re.sub(":=\n",":=",linestring)
linestring = re.sub(":\n","\n",linestring)
linestring = re.sub(":","",linestring)
LINES = linestring.split("\n")
for LINE in LINES:
LINE = re.sub(" ","",LINE)
print "LINE=", LINE
if len(LINE) <=0:
next
PAIR = LINE.split("=")
print "PAIR=", PAIR
LHS = PAIR[0]
RHS = PAIR[1]
print "LHS=", LHS
print "RHS=", RHS
The first re.sub block just deals with formatting the file and discarding characters that python will not be able to process; then a loop is performed to print 4 things, LINE, PAIR, LHS and RHS, and it does this nicely. using the example file from above the procedure will print the following:
LINE= m1=1
PAIR= ['m1', '1']
LHS= m1
RHS= 1
LINE= m2=1
PAIR= ['m2', '1']
LHS= m2
RHS= 1
LINE= Z1=-1
PAIR= ['Z1', '-1']
LHS= Z1
RHS= -1
LINE= Z2=-1
PAIR= ['Z2', '-1']
LHS= Z2
RHS= -1
LINE= F= 12.5*L(0,x)L(1,y) + 30*L(0,x)L(2,y)L(2,z)
PAIR=['F', '12.5*L(0,x)L(1,y) + 30*L(0,x)L(2,y)L(2,z)']
LHS= F
RHS= 12.5*L(0,x)L(1,y) + 30*L(0,x)L(2,y)L(2,z)
My question is what is the next best step to process this output and use it in a mathematical script, especially assigning the L to mean a laguerre polynomial? I tried putting the LHS and RHS into a dictionary, but found it troublesome to put F in it due to the laguerre polynomials.
Any ideas are welcome. Perhaps I am overcomplicating this and there is a much simpler way to parse this file.
Many thanks in advance
Your parsing algorithm doesn't seem to work correctly, as the RHS of your variables dont produce the expected result.
Also the first re.sub block where you want to format the file seems overly complicated. Assuming every statement in your input file is terminated by a colon, you could get rid of all whitespace and newlines and seperate the statements using the following code:
linestring = open('file.txt','r').read()
strippedstring = linestring.replace('\n','').replace(' ','')
statements = re.split(':(?!=)',strippedstring)[:-1]
Then you iterate over the statements and split each one in LHS and RHS:
for st in statements:
lhs,rhs = re.split(':=',st)
print 'lhs=',lhs
print 'rhs=',rhs
In the next step, try to distinguish normal float variables and polynomials:
#evaluate rhs
try:
#interpret as numeric constant
f = float(rhs)
print " ",f
except ValueError:
#interpret as laguerre-polynomial
summands = re.split('\+', re.sub('-','+-',rhs))
for s in summands:
m = re.match("^(?P<factor>-?[0-9]*(\.[0-9]*)?)(?P<poly>(\*?L\([0-9]+,[a-z]\))*)", s)
if not m:
print ' polynomial misformatted'
continue
f = m.group('factor')
print ' factor: ',f
p = m.group('poly')
for l in re.finditer("L\((?P<a>[0-9]+),(?P<b>[a-z])\)",p):
print ' poly: L(%s,%s)' % (l.group("a"),l.group("b"))
This should work for your given example file.
My SPSS Syntax code below does not produce the results intended. Even when reason is equal to 15 or 16, it will flag ped.crossing.with.signal to 1.
COMPUTE ped.crossing.with.signal = 0.
IF ((ped.action = 1 | ped.action = 2) AND (reason ~= 15 | reason ~= 16)) ped.crossing.with.signal = 1.
EXECUTE.
When I do it like this, it works... but why?
COMPUTE ped.crossing.with.signal = 0.
IF (ped.action = 1 | ped.action = 2) ped.crossing.with.signal = 1.
IF (reason = 15 | reason = 16) ped.crossing.with.signal = 0.
EXECUTE.
It's not a wonky result, but rather the correct application of boolean algebra which is explained by De Morgan's Laws.
The expression (reason ~= 15 | reason ~= 16) is equivalent to ~(reason = 15 and reason = 16) which in this case can never evaluate to false (because a single variable can't hold two values). Logically, the correct expression to use would be (reason ~= 15 & reason ~= 16) or ~(reason = 15 | reason = 16) although as pointed out already using the any function is more straightforward.
Your syntax looks good but in fact is logically not as you intend as Jay points out in his answer.
Also, you can simplify the syntax as follow to avoid complicated Boolean negations:
COMPUTE ped.crossing.with.signal = ANY(ped.action, 1, 2) AND ANY(reason, 15, 16)=0.
Using a single COMPUTE command in this way shall make your processing more efficient/faster, not to mention more parsimonious code also.