R lazy evaluation - lazy-evaluation

I'm reading Hadley Wickham's materials about function, in the part of lazy evaluation. I can't understand the example. I search the stackoverflow and find someone ask a familiar question. But my question is different from it. Let me quote that bit:
add <- function(x) {
function(y) x + y
}
adders <- lapply(1:10, add)
adders[[1]](10)
adders[[10]](10)
I don't understand the variable y. Nobody gives values to y. But the "add" can still work. So I do some test.
1)
> add <- function(x) {
+ function(y){
+ cat("y =",y,",x =",x,"\n")
+ x + y
+ }
+ }
> adders <- lapply(1:10, add)
> adders[[1]](10)
y = 10 ,x = 10
[1] 20
> adders[[10]](10)
y = 10 ,x = 10
[1] 20
>
2)
> adders <- lapply(1:17, add)
> adders[[1]](10)
y = 10 ,x = 17
[1] 27
> adders[[10]](10)
y = 10 ,x = 17
[1] 27
3)
> adders[[1]](12)
y = 12 ,x = 17
[1] 29
> adders[[1]](13)
y = 13 ,x = 17
[1] 30
> adders[[2]](12)
y = 12 ,x = 17
[1] 29
> adders[[2]](13)
y = 13 ,x = 17
so the value of "y" seem to have relation to the content inside "()"
4)
> x1 <- 2
> add(x1)
function(y){
cat("y =",y,",x =",x,"\n")
x + y
}
<environment: 0x0000000009c90c30>
>
I want to understand where does y get the value from? Thx in advance.
And I also define another function as follows:
5)
> add2 <- function(x) {
+ function(y){
+ function(z){
+ cat("z =",z,"y =",y,",x =",x,"\n")
+ x + y + z
+ }
+ }
+ }
> adders2 <- lapply(1:17, add2)
> adders2[[1]](12)
function(z){
cat("z =",z,"y =",y,",x =",x,"\n")
x + y + z
}
<environment: 0x0000000009da0378>
> adders2[[1]](13)
function(z){
cat("z =",z,"y =",y,",x =",x,"\n")
x + y + z
}
<environment: 0x0000000009dbabf0>
> adders2[[2]](12)
function(z){
cat("z =",z,"y =",y,",x =",x,"\n")
x + y + z
}
<environment: 0x0000000009dc71c0>
> adders2[[2]](13)
function(z){
cat("z =",z,"y =",y,",x =",x,"\n")
x + y + z
}
<environment: 0x0000000009dd39c8>
>
under what condition can I use add2()?

Related

Is it possible to define an efficient hyper-operation sequence as a recursive squaring function over 2-adics in Haskell?

Let's define a 2-adic in Haskell as its infinite binary expansion:
data Adic = O Adic | I Adic deriving Show
We can represent finite numbers as follows:
zero = O zero
one = I zero
neg1 = I neg1
And we can easily define Inc and Add for Adic:
inc :: Adic -> Adic
inc (O a) = I a
inc (I a) = O (Inc a)
add :: Adic -> Adic -> Adic
add (O a) (O b) = O (add a b)
add (O a) (I b) = I (add a b)
add (I a) (O b) = I (add a b)
add (I a) (I b) = I (inc (add a b))
We can convert adics to ints follows:
a2i :: Int -> Adic -> Int
a2i 1 (O x) = 0
a2i 0 (I x) = -1
a2i s (O x) = 2 * i2a (s - 1) x
a2i s (I x) = 2 * i2a (s - 1) x + 1
This allows us to do basic arithmetic. For example:
print $ a2i 64 (add one neg1)
Would print 0, after computing 1 + -1 on 2-adics.
Now, I'm interested in the hyper-operation sequence function, i.e.:
hyp :: Int -> Adic -> Adic -> Adic
hyp 0 a b = add a b
hyp 1 a b = mul a b
hyp 2 a b = exp a b
hyp 3 a b = tet a b
...
An efficient way to implement it is by generalizing the exponentiation by squaring algorithm, as follows:
hyp :: Int -> Adic -> Adic -> Adic
hyp 0 a b = add a b
hyp s a 1 = a
hyp s a (O b) = let r = hyp s a b in hyp (s - 1) r r
hyp s a (I b) = let r = hyp s a (Inc b) in hyp (s - 1) r r
To visualize the function above, below is the evaluation of hyp 2 4 4, i.e., 4^4:
4^4 =
4^2 * 4^2 =
4^1 * 4^1 * 4^1 * 4^1 =
4 * 4 * 4 * 4 =
4*4 * 4*4 =
(4*2 + 4*2) * (4*2 * 4*2) =
(4*1 + 4*1 + 4*1 + 4*1) * (4*1 + 4*1 + 4*1 + 4*1) =
(4 + 4 + 4 + 4) * (4 + 4 + 4 + 4) =
16*16 =
16*8 + 16*8 =
16*4 + 16*4 + 16*4 + 16*4 =
16*2 + 16*2 + 16*2 + 16*2 + 16*2 + 16*2 + 16*2 + 16*2 =
16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 + 16*1 =
16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 16 =
256
Sadly, the function above doesn't actually work, because the hyp s a 1 = a line attempts to match an Adic against the Int 1, which makes no sense. What it should do, instead, is match against the 2-adic number 1. The problem is: 2-adics are infinite, so we can't match them. We can't even create an is one function. As such, while the function above seems elegant and efficient, it, as far as I can tell, can't be constructed. My question is: am I right in concluding hyp can't be implemented that way, or am I missing something? Is there an alternative approach that would let this work?

Reverse the isometric projection algorithm

I've got this code:
const a = 2; // always > 0 and known in advance
const b = 3; // always > 0 and known in advance
const c = 4; // always > 0 and known in advance
for (let x = 0; x <= a; x++) {
for (let y = 0; y <= b; y++) {
for (let z = 0; z <= c; z++) {
for (let p = 0; p <= 1; p++) {
for (let q = 0; q <= 2; q++) {
let u = b + x - y + p;
let v = a + b + 2 * c - x - y - 2 * z + q;
let w = c + x + y - z;
}
}
}
}
}
The code generates (a+1)*(b+1)*(c+1)*2*3 triplets of (u,v,w), each of them is unique. And because of that fact, I think it should be possible to write reversed version of this algorithm that will calculate x,y,z,p,q based on u,v,w. I understand that there are only 3 equations and 5 variables to get, but known boundaries for x,y,z,p,q and the fact that all variables are integers should probably help.
for (let u = ?; u <= ?; u++) {
for (let v = ?; v <= ?; v++) {
for (let w = ?; w <= ?; w++) {
x = ?;
y = ?;
z = ?;
p = ?;
q = ?;
}
}
}
I even managed to produce the first line: for (let u = 0; u <= a + b + 1; u++) by taking the equation for u and finding min and max but I'm struggling with moving forward. I understand that min and max values for v are depending on u, but can't figure out the formulas.
Examples are in JS, but I will be thankful for any help in any programming language or even plain math formulas.
If anyone is interested in what this code is actually about - it projects voxel 3d model to triangles on a plain. u,v are resulting 2d coordinates and w is distance from the camera. Reversed algorithm will be actually a kind of raytracing.
UPDATE: Using line equations from 2 points I managed to create minmax conditions for v and code now looks like this:
for (let u = 0; u <= a + b + 1; u++) {
let minv = u <= a ? a - u : -a + u - 1;
let maxv = u <= b ? a + 2 * c + u + 2 : a + 2 * b + 2 * c - u + 3;
for (let v = minv; v <= maxv; v++) {
...
}
}
I think I know what to do with x, y, z, p, q on the last step so the problem left is minw and maxw. As far as I understand those values should depend both on u and v and I must use plane equations?
If the triplets are really unique (didn't check that) and if p and q always go up to 1 and 2 (respectively), then you can "group" triplets together and go up the loop chain.
We'll first find the 3 triplets that where made in the same "q loop" : the triplets make with the same x,y,z,p. As only q change, the only difference will be v, and it will be 3 consecutive numbers.
For that, let's group triplets such that, in a group, all triplets have the same u and same w. Then we sort triplets in groups by their v parameters, and we group them 3 by 3. Inside each group it's easy to assign the correct q variable to each triplet.
Then reduce the groups of 3 into the first triplet (the one with q == 0). We start over to assign the p variable : Group all triplets such that they have same v and w inside a group. Then sort them by the u value, and group them 2 by 2. This let's us find their p value. Remember that each triplet in the group of 3 (before reducing) has that same p value.
Then, for each triplet, we have found p and q. We solve the 3 equation for x,y,z :
z = -1 * ((v + w) - a - b - 3c -q)/3
y = (w - u + z + b - c - p)/2
x = u + y - b - p
After spending some time with articles on geometry and with the huge help from Wolfram Alpha, I managed to write needed equations myself. And yes, I had to use plane equations.
const a = 2; // always > 0 and known in advance
const b = 3; // always > 0 and known in advance
const c = 4; // always > 0 and known in advance
const minu = 0;
const maxu = a + b + 1;
let minv, maxv, minw, maxw;
let x, y, z, p, q;
for (let u = minu; u <= maxu; u++) {
if (u <= a) {
minv = a - u;
} else {
minv = -a + u - 1;
}
if (u <= b) {
maxv = a + 2 * c + u + 2;
} else {
maxv = a + 2 * b + 2 * c - u + 3;
}
for (let v = minv; v <= maxv; v++) {
if (u <= b && v >= a + u + 1) {
minw = (-a + 2 * b - 3 * u + v - 2) / 2;
} else if (u > b && v >= a + 2 * b - u + 2) {
minw = (-a - 4 * b + 3 * u + v - 5) / 2;
} else {
minw = a + b - v;
}
if (u <= a && v <= a + 2 * c - u + 1) {
maxw = (-a + 2 * b + 3 * u + v - 1) / 2;
} else if (u > a && v <= -a + 2 * c + u) {
maxw = (5 * a + 2 * b - 3 * u + v + 2) / 2;
} else {
maxw = a + b + 3 * c - v + 2;
}
minw = Math.round(minw);
maxw = Math.round(maxw);
for (let w = minw; w <= maxw; w++) {
z = (a + b + 3 * c - v - w + 2) / 3;
q = Math.round(2 - (z % 1) * 3);
z = Math.floor(z);
y = (a + 4 * b + q - 3 * u - v + 2 * w + 3) / 6;
p = 1 - (y % 1) * 2;
y = Math.floor(y);
x = (a - 2 * b - 3 * p + q + 3 * u - v + 2 * w) / 6;
x = Math.round(x);
}
}
}
This code passes my tests, but if someone can create better solution, I would be very interested.

Algorithm for expressing given number as a sum of two squares

My problem is as follows:
I'm given a natural number n and I want to find all natural numbers x and y such that
n = x² + y²
Since this is addition order does not matter so I count (x,y) and (y,x) as one solution.
My initial algorithm is to assume that y>x, for all x compute y²=n-x² and check if y is a natural number using binary search on y².
for(x=1;2*x*x<n;x++)
{
y_squared=n-x*x;
if(isSquare(y_squared)==false)
continue;
//rest of the code
}
Is there any improvement for my algorithm? I already checked if n can have solutions using two squares theorem, but I want to know how many there are.
My algorithm is O(sqrt(n) * log(n) )
Thanks in advance.
You can reduce this to O(sqrt(n)) this way:
all_solutions(n):
x = 0
y = floor(sqrt(n))
while x <= y
if x * x + y * y < n
x++
else if x * x + y * y > n
y--
else
// found a match
print(x, y)
x++
y--
This algorithm will find and print all possible solutions and will always terminate for x <= sqrt(n / 2) and y >= sqrt(n / 2), leading to at most sqrt(n / 2) + (sqrt(n) - sqrt(n / 2)) = sqrt(n) iterations being performed.
A variation of Paul's, keeping track of the sum of squares and adjusting it just with additions/subtractions:
Pseudo-code: (evaluate x++ + x and y-- + y left-to-right, or do it like in the Python code below)
x = 0
y = floor(sqrt(n))
sum = y * y
while x <= y
if sum < n
sum += x++ + x
else if sum > n
sum -= y-- + y
else
print(x, y)
sum += 2 * (++x - y--)
Java:
static void allSolutions(int n) {
int x = 0, y = (int) Math.sqrt(n), sum = y * y;
while (x <= y) {
if (sum < n) {
sum += x++ + x;
} else if (sum > n) {
sum -= y-- + y;
} else {
System.out.println(x + " " + y);
sum += 2 * (++x - y--);
}
}
}
Python:
from math import isqrt
def all_solutions(n):
x = 0
y = isqrt(n)
sum = y ** 2
while x <= y:
if sum < n:
x += 1
sum += 2 * x - 1
elif sum > n:
sum -= 2 * y - 1
y -= 1
else:
# found a match
print(x, y)
x += 1
sum += 2 * (x - y)
y -= 1
Demo:
>>> all_solutions(5525)
7 74
14 73
22 71
25 70
41 62
50 55

For integers A>0, B>0, N>0, find integers x>0,y>0 such that N-(Ax+By) is smallest non-negative

Example :
A=5, B=2, N=12
Then let x=2, y=1, so 12 - (5(2) + 2(1)) = 0.
Another example:
A=5, B=4, N=12
Here x=1, y=1 is the best possible. Note x=2, y=0 would be better except that x=0 is not allowed.
I'm looking for something fast.
Note it's sufficient to find the value of Ax+By. It's not necessary to give x or y explicitly.
If gcd(A,B)|N, then N is your maximal value. Otherwise, it's the greatest multiple of gcd(A,B) that's smaller than N. Using 4x+2y=13 as an example, that value is gcd(4,2)*6=12 realized by 4(2)+2(2)=12 (among many solutions).
As a formula, your maximal value is Floor(N/gcd(A,B))*gcd(A,B).
Edit: If both x and y must be positive, this may not work. However, won't even be a solution if A+B>N. Here's an algorithm for you...
from math import floor, ceil
def euclid_wallis(m, n):
col1 = [1, 0, m]
col2 = [0, 1, n]
while col2[-1] != 0:
f = -1 * (col1[-1] // col2[-1])
col2, col1 = [x2 * f + x1 for x1, x2 in zip(col1, col2)], col2
return col1, col2
def positive_solutions(A, B, N):
(x, y, gcf), (cx, cy, _) = euclid_wallis(A, B)
f = N // gcf
while f > 0:
fx, fy, n = f*x, f*y, f*gcf
k_min = (-fx + 0.) / cx
k_max = (-fy + 0.) / cy
if cx < 0:
k_min, k_max = k_max, k_min
if floor(k_min) + 1 <= ceil(k_max) - 1:
example_k = int(floor(k_min) + 1)
return fx + cx * example_k, fy + cy * example_k, n
if k_max <= 1:
raise Exception('No solution - A: {}, B: {}, N: {}'.format(A, B, N))
f -= 1
print positive_solutions(5, 4, 12) # (1, 1, 9)
print positive_solutions(2, 3, 6) # (1, 1, 5)
print positive_solutions(23, 37, 238) # (7, 2, 235)
A brute-force O(N^2 / A / B) algorithm, implemented in plain Python3:
import math
def axby(A, B, N):
return [A * x + B * y
for x in range(1, 1 + math.ceil(N / A))
for y in range(1, 1 + math.ceil(N / B))
if (N - A * x - B * y) >= 0]
def bestAxBy(A, B, N):
return min(axby(A, B, N), key=lambda x: N - x)
This matched your examples:
In [2]: bestAxBy(5, 2, 12)
Out[2]: 12 # 5 * (2) + 2 * (1)
In [3]: bestAxBy(5, 4, 12)
Out[3]: 9 # 5 * (1) + 4 * (1)
Have no idea what algorithm that might be, but I think you need something like that (C#)
static class Program
{
static int solve( int a, int b, int N )
{
if( a <= 0 || b <= 0 || N <= 0 )
throw new ArgumentOutOfRangeException();
if( a + b > N )
return -1; // Even x=1, y=1 still more then N
int x = 1;
int y = ( N - ( x * a ) ) / b;
int zInitial = a * x + b * y;
int zMax = zInitial;
while( true )
{
x++;
y = ( N - ( x * a ) ) / b;
if( y <= 0 )
return zMax; // With that x, no positive y possible
int z = a * x + b * y;
if( z > zMax )
zMax = z; // Nice, found better
if( z == zInitial )
return zMax; // x/y/z are periodical, returned where started, meaning no new values are expected
}
}
static void Main( string[] args )
{
int r = solve( 5, 4, 12 );
Console.WriteLine( "{0}", r );
}
}

how to add expressions and do numerical calculation in Maxima?

I would like to ask:
how I can add expressions in Maxima? i.e. I have:
A = x + y;
B = 2*x + 2*y;
How to get Maxima to give me (A + B)?
how I can do numerical calculation in Maxima? I want to assign
x = 1;
b = 2;
How to get the numerical value of (A + B)?
(1) assignment in Maxima uses the colon symbol (i.e., ":") not the equal sign ("=").
(2) there are a couple of ways to evaluate with specific values.
(2a) subst([x = ..., y = ...], foo) where foo is some expression such as foo : A + B.
(2b) ev(foo, x = ..., y = ...)
So:
(%i1) A : x + y;
(%o1) y + x
(%i2) B : 2*x + 2*y;
(%o2) 2 y + 2 x
(%i3) foo : A + B;
(%o3) 3 y + 3 x
(%i4) subst ([x = 1, y = 2], foo);
(%o4) 9
(%i5) ev (foo, x = 1, y = 2);
(%o5) 9
Yet another way to substitute values into a formula is with the '' operator as follows:
(%i57) A : 2*a+b ; B : a-b;
(%o57) b + 2 a
(%o58) a - b
(%i59) a : 4; b : 10;
(%o59) 4
(%o60) 10
(%i61) A;
(%o61) b + 2 a
(%i62) ''A;
(%o62) 18
(%i63) ''B;
(%o64) - 6
(%i65) ''A + ''B;
(%o65) 12
(%i66) ''(A+B);
(%o66) 12

Resources