issue with a for loop in smalltalk - smalltalk

I have a method to calculate the exponent, but it doesnt like the c := c * a. If i do something like c := a. it works and im unsure why its behaving this way when i try and do c := c *a.. Im new to Smalltalk, so maybe its just something im missing. Im using Pharo as my implementaton.
testPow: i1 exp: i2
"Testing exponent. i1 and i2 are integers, we calculate and then return the value as a Church numeral"
| a b c |
a := i1.
b := i2.
1 to: b do: [ :i |
c:= c*a.
].
^c.

You need to initialise c before using it. With your statement:
c := a
it works because a has a value. With:
c := c * a
it won't work because the first time through the loop, c will not be initialised to anything useful.
Just change your initialisation section to:
a := i1.
b := i2.
c := 1.

In the sample c is pointing to nil because c was not initialized. And nil (which is an object) doesn't understand the message *. Look at the values in the debugger when the exception is thrown.

Related

How should you calculate partial derivative ∂f/∂x using first the chain rule & directly in MAPLE?

If f(u,v) = vsinu+v^2, u(x,y)=tan^−1􏰀(y􏰁/x), v=sqrt(􏰂x^2 + y^2)
Calculate using chain rule and directly substituting for u(x,y), v(x,y).
Your syntax is not altogether clear to me, but I am guessing you are trying to achieve something like this:
uveqs := [u(x,y)=arctan(y/x), v(x,y)=sqrt(x^2+y^2)]:
f := v(x,y)*sin(u(x,y))+v(x,y)^2:
Differentiate f with respect to x (noticing the effect of the chain-rule),
K := diff(f,x):
diff(v(x,y),x) * sin(u(x,y))
+ v(x,y) * diff(u(x,y),x) * cos(u(x,y))
+ 2*v(x,y) * diff(v(x,y),x)
Now substitute for u(x,y) and v(x,u), and simplify,
S1 := eval(K,uveqs):
simplify(S1);
2 x
Alternatively, first substitute for u(x,y) and v(x,y) into f itself,
fxy := eval(f,uveqs):
(x^2+y^2)^(1/2)*y/x/(1+y^2/x^2)^(1/2)+x^2+y^2
And then differentiate with respect to x, and simplify,
S2 := diff(fxy,x):
simplify(S2);
2 x
If you have trouble understanding the mechanisms, you might also compare these two pairs of operations,
diff( v(x,y), x );
eval( %, uveqs );
and,
eval( v(x,y), uveqs );
diff( %, x );

Unrestricted Grammar: { sss | s exists in {a,b}* }

What would be a way to construct an unrestricted grammar for sss? I know that in order to construct ss, you need to construct ss^r and then re-reverse the second string, but how would that be done for sss?
There may be a few bugs in this but the idea should get you on the right track.
// section 1
S := LTR
T := ATWX | BTYZ | N
// section 2
WW' := W'W
WY' := Y'W
YW' := W'Y
YY' := Y'Y
// section 3
WX' := W'X'
WZ' := W'Z'
YX' := Y'X'
YZ' := Y'Z'
// section 4
XW' := W'X
XX' := X'X
XY' := Y'X
XZ' := Z'X
ZW' := W'Z
ZX' := X'Z
ZY' := Y'Z
ZZ' := Z'Z
// section 5
XR := X'R
ZR := Z'R
// section 6
NW' := W'N
NX' := X'N
NY' := Y'N
NZ' := Z'N
NR := Q
// section 7
AQ := Qa
W'Q := Qa
X'Q := Qa
BQ := Qb
Y'Q := Qb
Z'Q := Qb
LQ := e
Section 1 sets out the basic scheme. We're going to mark the beginning and end of our working space with L and R to be perfectly explicit. T is our working space and L and R are the left and right markers. Our working space can add either three as (these are what A, W, and X will become later) or add three bs (these are what B, Y and Z will become later) or it can quit by generating the special nonterminal N. N is going to be what turns our string of nonterminals into a string of terminals, as we'll see later.
So we need xxx for x in (a+b)*. A and B get added to the end of the first x because of the way we set up the productions. The job of section 2 is to make sure that the W and Y get added to the end of the second x. Unfortunately, our productions put the W and Y at the beginning of the second x so, without correction, we'd end up with xx^R. Section 2 corrects this problem by "floating" the W and Y to the right as long as they are to the left of a W or Y that has already found its proper place. Ws and Ys can't pass each other and so this guarantees they will end up in the proper sequence once the music stops.
Section 3 shows how the symbols in the second occurrence of x find their correct positions. Basically, they move to the right (based on section 2) until they find symbols of the third x that are in their proper places. Since the symbols of the second x have their proper place before the symbols of the third x, the last possible right before either symbol of the third x (X or Z) is the right position for every symbol of the second x. So we float right all the way to the end of the second x.
We repeat the process for the third x in section 4, although we have to let these symbols (X and Z) float past all the symbols from the second or third x that have already found their proper places. These symbols can't pass themselves and so by the same logic as we saw in section 2 we'll get the symbols in the correct sequence.
Section 5 says when to stop floating symbols that make up the third x to the right. Remember the end of working space marker R? The last symbol of the third x occurs all the way at the right, right before R. So that's when we know we have found the proper place for the symbol.
Section 6 begins the process of finishing off our derivation. We have a lovely string of nonterminals and we want to turn these into terminals. The first thing we do is float N to the right past the well-placed symbols of the second and third xs all the way to the end of string marker R. We don't need R for anything, so we transform N into Q. As we'll see in the next section Q is what makes the magic happen.
Section 7 outlines how Q floats left back through the entire string of nonterminals that have found their proper place all the way to L, changing the nonterminals to the proper terminal along the way. Once it finds L, it obliterates both nonterminals leaving only a string of terminal symbols in its wake. The derivation is complete.
To illustrate the process, let's generate aabaabaab.
S
-> LTR
-> LATWXR
-> LAATWXWXR
-> LAABTYZWXWXR
-> LAABNYZWXWXR
-> LAABNYZWXWX'R
-> LAABNYZWXW'X'R
-> LAABNYZWW'XX'R
-> LAABNYZWW'X'XR
-> LAABNYZWW'X'X'R
-> LAABNYZW'WX'X'R
-> LAABNYZW'W'X'X'R
-> LAABNYW'ZW'X'X'R
-> LAABNYW'W'ZX'X'R
-> LAABNYW'W'X'ZX'R
-> LAABNYW'W'X'X'ZR
-> LAABNYW'W'X'X'Z'R
-> LAABNW'YW'X'X'Z'R
-> LAABNW'W'YX'X'Z'R
-> LAABNW'W'Y'X'X'Z'R
-> LAABW'NW'Y'X'X'Z'R
-> LAABW'W'NY'X'X'Z'R
-> LAABW'W'Y'NX'X'Z'R
-> LAABW'W'Y'X'NX'Z'R
-> LAABW'W'Y'X'X'NZ'R
-> LAABW'W'Y'X'X'Z'NR
-> LAABW'W'Y'X'X'Z'Q
-> LAABW'W'Y'X'X'Qb
-> LAABW'W'Y'X'Qab
-> LAABW'W'Y'Qaab
-> LAABW'W'Qbaab
-> LAABW'Qabaab
-> LAABQaabaab
-> LAAQbaabaab
-> LAQabaabaab
-> LQaabaabaab
-> aabaabaab

Maple Sequence Length

I'm trying to create a basic program in Maple that runs the Collatz sequence when given a number (n) from the user. For those that don't know, the Collatz sequence is basically "If the number given is odd, do 3n + 1, if it is even, divide by 2 and continue to do so for every answer. Eventually, the answer will reach 1"
I'm trying to grab the number of iterations that the sequence is performed, say if the sequence is run through 10 times, it prints that out. Here is my current code:
Collatz := proc (n::posint)
if type(n, even) then (1/2)*n
else 3*n+1
end if
end proc
CollSeq := proc (n::posint)
local i;
i := n;
while 1 < i do
lprint(i);
i := Collatz(i)
end do
end proc
This so far works, and if the proc CollSeq(50) is entered, it will perform the Collatz sequence on 50 until it reaches 1. The bit I am stuck on is the length of the sequence. I have read around and learned that I might be able to use the nops([]) function of Maple to get the length of the sequence. Here is what I have tried:
CollLen := proc (n::posint)
local c;
c := CollSeq(n);
print(nops([c]))
end proc
I have a feeling this is horribly wrong. Any help would be much appreciated.
Many Thanks
Your function fails to return the actual sequence of values. You need to accumulate it as you go through the loop.
CollSeq := proc (n::posint)
local i, s;
i := n;
s := i;
while 1 < i do
lprint(i);
i := Collatz(i);
s := s, i;
end do;
s;
end proc
The lprint() command just prints its argument to the terminal (showing it on screen), it DOES not save it in a list. And nops() or a better command numelems() counts the number of elements in a list! So putting nops around something that has lprint will not count the number of things. Instead of using lprint in your second function (procedure), define a list, or better than list, an array and in the lprint-line, use a command to append the new number to your growing collection. If you want to see these numbers, just print this collection. Now this time, your third function can have a meaning and it will work as you expected.
Here is the closest fix to your codes.
Collatz := proc( n :: posint )
if type(n, even) then
return( n/2 ):
else
return( 3*n+1 ):
end if:
end proc:
CollSeq := proc ( n :: posint )
local
i :: posint,
c :: 'Array'( posint ):
i := n:
c := Array([]):
while 1 < i do
ArrayTools:-Append( c, i ):
i := Collatz( i ):
end do:
return( c ):
end proc:
CollLen := proc ( n :: posint )
local c :: posint:
c := CollSeq( n ):
return( numelems( c ) ):
end proc:
Here is a screenshot of using them in a Maple worksheet.
Why do I use an array and not a list? Because if you use a list which is immutable, each time you want to add an element to it, in fact it is defining a new list. It is not a memory efficient way, while array is mutable and your edits modifies the array itself. See the help pages on these in Maple.
And looking at your codes, it seems you have the same problem that some of my students in their first programming course usually have, return and print are not the same thing. If you really want a "print" action, that is fine, but you should not expect that the printed value be the output of the function unless you are using a return line inside the function that returns the same value of the print as well. For example you can have print(c): before return(c): in the second function above. So it both prints the sequence on the terminal and returns it to be used by another function or line of code.

Programming in Maple for first time: "Illegal use of formal parameter"

I keep getting that error. Here's the code (it's for GCD):
Euc := proc (a, b)
if b = 0 then a;
else c := b;
d := a mod b;
b := d; a := c;
end if;
end proc;
I never use Maple because it gives me a headache and the documentation is a nightmare, but this assignment has to be done all in Maple... if I'm having trouble with simple GCD, I don't see me writing RSA and El Gamal by Wednesday :s
edit: Fixed it with
Euc := proc (a, b)
if b = 0 then a;
else c := b;
d := a mod b;
Euc(c,d);
end if;
end proc;
But any I'd still like to know what the problem was, in case I have to do something similar again.
Your first version attempted to assign to the formal parameters of the procedure. That was the problem.
Suppose you call your original Euc and pass in 12 for parameter a and 8 for parameter b. Inside the body of Euc, as it runs in this instance, a evaluates to 12 and a does not evaluate to a name to which you can make an assignment. When you try and make an assignment to a or b inside Euc then you see that error.

The while language

For my theory of computing languages class, we got a homework assignment to implement a piece of code in a language that only has while statements for flow control (no if statements). This is mainly to prove that you can write a Turing-complete language with only a while loop.
For those of you who can understand language grammars, here are the language rules:
S -> S;S | while C do S od | id := E
E -> E + T | T | E - T
T -> T * F | F | F / T
F -> id | cons | (E)
C -> E = E | E > E | E < E | E >= E | E <= E | E != E | C and C | C or C | not(C)
This is copied from my class notes, so don't blame me if something is missing or incorrect!
The piece of code to implement is this:
if d = 0 do
x := 1
else
x := a / d
At any rate, if you want to go ahead and write that using the language rules above, go ahead. Otherwise, go ahead and write it in whatever language you're most comfortable in. But there are a few caveats!
No if statements or any other kind of flow control other than while loops.
No cheating: the grammar above doesn't include any break statements, return statements, or exceptions. Don't use them.
I've got my piece of code written for this (which I'll post just to prove this isn't a show me teh codez post). I'm kinda curious what anyone else can come up with though.
It can be done with a single while loop, but it is not that clear:
while d == 0 do
d := 1;
a := 1
od
x := a / d;
Explanation, if d = 0, then d will be 1, also a will be 1. This ends the loop.
Now x is set to a / d which is fine, because if d was 0, a / d evaluates to 1.
Here's my code:
continue := True
while d = 0 and continue do
x := 1
continue := False
od
while d != 0 and continue do
x := a/d
continue := False
od
Would this work?
td := d
x := 1
while td != 0 do
x := a / d
td := 0
od
To be Turing Complete, you need to support both selection and iteration. While loops obviously iterate. Selection can be accomplished by making it go through the loop once if the condition is true, and not at all otherwise.
So worst case you can do everything you need to by applying those techniques. I'd imagine some complicated control flows would get ugly fast though. :-)
Without using details of the true or false branches, and without repeating the predicate:
statementIncomplete := True
while d = 0 and statementIncomplete do
x := 1
statementIncomplete := False
od
while statementIncomplete do
x := a/d
statementIncomplete := False
od
This is an expansion of Eamon's answer.
The semantics of if <condition> then <stmt> else <stmt> fi is the following:
evaluate <condition>;
if it was true, execute the statement between then and else;
otherwise, execute the statement between else and fi.
The semantics of while <condition> do <stmt> od is the following:
evaluate <condition>;
if false, the while statement is done executing;
otherwise, execute the statement between do and od, and execute the while statement again.
To express if A then B else C in terms of while, perform the following transformation:
Let gensymN be a name not used for any other variable; then emit the following code
gensymN := 0;
while gensymN = 0 and A do B; gensymN = 1; od;
while gensymN = 0 do C; gensymN = 1; od
The semantics of this program is:
Assign 0 to gensymN.
Evaluate gensymN = 0 and A (it's true iff A is true)
If true, then:
execute B
execute gensymN = 1
evaluate gensymN = 0 and A (it's false)
evaluate gensymN = 0 (it's false)
else (if gensymN = 0 and A was false):
evaluate gensymN = 0 (it's true)
execute C
execute gensymN := 1
evaluate gensymN = 0 (it's false)
Observe the following substructure of the above:
It (effectively) evaluates A;
If true, it executes B, otherwise C.
Apart from A, B and C, the program (fragment) only fiddles with gensymN, which is not present in the input program.
Hence this program has the same semantics as
if A then B else C fi; gensymN := 1
One footnote: if A is true when evaluated, it will be evaluated once again (unless and is short-circuiting). If the language allows storing booleans in variables, one can introduce one more dummy variable and do dummy := A; <insert the above program here, with dummy instead of A>. Then the two evaluations of dummy are essentially just a load. If evaluating boolean expressions cannot have side effects, preventing the second evaluation is not necessary for correctness; it may (or may not) be an optimization.
Take the above as a "soft proof", with the provisos of the preceding paragraph, that this is a correct fully general translation of if to while. The full generality sets this (= Eamon's) answer apart from the others, in my view.