Recursive function with for in Mathematica does not work - recursion

Why does this recursive function not work?
Code:
Clear[i];
Clear[v];
final= 4;
Recursion = Function[{v},
For[i = 1, i <= 2, i++,
Print["Current level ", v ];
Print["Try: ", i];
If[v == final,
Print["End"];,
Recursion[v + 1]; (*else-case*)
];
Print["Back! i:", i];
];
]
Recursion[1];
Out:
0: Current level 1
1: Try: 1
2: Current level 2
3: Try: 1
4: Current level 3
5: Try: 1
6: Current level 4
7: Try: 1
8: End
9: Back! i:1
10: Current level 4
11: Try: 2
12: End
13: Back! i:2
14: Back! i:3
15: Back! i:4
16: Back! i:5
Heeelp
In the 14th line, "i" should be =2, current level: 3 and try: 2.. then i=1, then i=2.. like a binary tree.
Why is this happening?!

Your iterator i is getting incremented inside the recursion, which is why it is counting to 5, higher than its set limit of 2.
You can make i a function of v to make it behave separately in each recursion, i.e.
final = 4;
Recursion = Function[v,
For[i[v] = 1, i[v] <= 2, i[v]++,
Print["Current level ", v];
Print["Try: ", i[v]];
If[v == final, Print["End"], Recursion[v + 1]];
Print["Back! i[", v, "]:", i[v]]]];
Recursion[1]
This should make it easier for you to see what is happening, although I think you will need to restructure your code when you do see what it's doing.

As Chris observes you need to localize i within the function, but I recommend you use Module to localize i. v is already localized by Function itself so you do not need Clear. Also, avoid starting user function names with a capital letter, as by convention those are reserved for system functions.
final = 4;
recursion =
Function[{v},
Module[{i},
For[i = 1, i <= 2, i++,
Print["Current level ", v];
Print["Try: ", i];
If[v == final, Print["End"], recursion[v + 1]];
Print["Back! i:", i];
]]];
recursion[1];
Beyond this, the problem doesn't appear to require For and would be better written with Do. Also, you may want to choose a different structure: either a function defined with DownValues (meaning f[x_] := ... rather than f = Function[...]), or a Function using Slot (#) where #0 can be used for recursion. I will illustrate both methods for you.
DownValues
recursion2[v_Integer] :=
Do[
Print["Current level ", v];
Print["Try: ", i];
If[v == final, Print["End"], recursion2[v + 1]];
Print["Back! i:", i],
{i, 2}
]
Pure Function with Slot
Here # (also written #1) represents the single parameter of the function, and #0 is used to represent the function itself. See Slot for more.
recursion3 =
Do[
Print["Current level ", #];
Print["Try: ", i];
If[# == final, Print["End"], #0[# + 1]];
Print["Back! i:", i],
{i, 2}
] &;

Related

Error in for loop - attempt to select less than one element in integerOneIndex

I'm trying to translate a C routine from an old sound synthesis program into R, but have indexing issues which I'm struggling to understand (I'm a beginner when it comes to using loops).
The routine creates an exponential lookup table - the vector exptab:
# Define parameters
sinetabsize <- 8192
prop <- 0.8
BP <- 10
BD <- -5
BA <- -1
# Create output vector
exptab <- vector("double", sinetabsize)
# Loop
while(abs(BD) > 0.00001){
BY = (exp(BP) -1) / (exp(BP*prop)-1)
if (BY > 2){
BS = -1
}
else{
BS = 1
}
if (BA != BS){
BD = BD * -0.5
BA = BS
BP = BP + BD
}
if (BP <= 0){
BP = 0.001
}
BQ = 1 / (exp(BP) - 1)
incr = 1 / sinetabsize
x = 0
stabsize = sinetabsize + 1
for (i in (1:(stabsize-1))){
x = x + incr
exptab [[sinetabsize-i]] = 1 - (BQ * (exp(BP * x) - 1))
}
}
Running the code gives the error:
Error in exptab[[sinetabsize - i]] <- 1 - (BQ * (exp(BP * x) - 1)) :
attempt to select less than one element in integerOneIndex
Which, I understand from looking at other posts, indicates an indexing problem. But, I'm finding it difficult to work out the exact issue.
I suspect the error may lie in my translation. The original C code for the last few lines is:
for (i=1; i < stabsize;i++){
x += incr;
exptab[sinetabsize-i] = 1.0 - (float) (BQ*(exp(BP*x) - 1.0));
}
I had thought the R code for (i in (1:(stabsize-1))) was equivalent to the C code for (i=1; i< stabsize;i++) (i.e. the initial value of i is i = 1, the test is whether i < stabsize, and the increment is +1). But now I'm not so sure.
Any suggestions as to where I'm going wrong would be greatly appreciated!
As you say, array indexing in R starts at 1. In C it starts at zero. I reckon that's your problem. Can sinetabsize-i ever get to zero?

Is it possible to decode a SPAMCAUSE field in a mail header?

I'd like to decode this string:
X-OVH-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeelgedrvdduucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfenuceurghilhhouhhtmecufedttdenucgohfhorhgsihguuggvnhfjughrucdlhedttddm
How can I do this?
There is a Tor hidden service you can use to decode the tag located at http://6jbnmws2zq2m2fsfmpwnssgsrxovohgggphymkd4df2pgcw7ccrdy6ad.onion
According to it, the X-OVH-SPAMCAUSE you gave translates to this:
Vade Retro 01.394.21 AS+AV+AP+RT Profile: OVH; Bailout: 300; ^ForbiddenHdr (500)
Starting from lkraider's great Python answer, I improved the accuracy. It turns out that the offset characters (c..g) are alternately appended and prepended. So instead of just checking if one of them is in the pair, it is necessary to differentiate between, e.g., fh and hf, by keeping track of even or odd pairs.
def decode(msg):
text = ""
for i in range(0, len(msg), 2):
# add position as extra parameter
text += unrot(msg[i: i + 2], i // 2)
return text
def unrot(pair, pos, key=ord('x')):
# "even" position => 2nd char is offset
if pos % 2 == 0:
# swap letters in pair
pair = pair[1] + pair[0]
# treat 1st char as offset
offset = (ord('g') - ord(pair[0])) * 16
# map to original character
return chr(sum(ord(c) for c in pair) - key - offset)
print(decode('gggruggvucftvghtrhho'))
https://gist.github.com/DoubleYouEl/e3de97293ce3d5452b3be7a336a06ad7
Looks to be some obfuscation by rotating chars. I made an attempt at it using Python. It's not perfect but mostly seems to work:
def decode(msg):
text = []
for i in range(0, len(msg), 2):
text.append(unrot(msg[i: i + 2]))
return str.join('', text)
def unrot(pair, key=ord('x')):
offset = 0
for c in 'cdefgh':
if c in pair:
offset = (ord('g') - ord(c)) * 16
break
return chr(sum(ord(c) for c in pair) - key - offset)
print(decode('gggruggvucftvghtrhho'))
https://gist.github.com/lkraider/9530798a695586fc1580d0728966f6f0
I improved the given Python solutions by Ikraider and DoubleYou and added a JavaScript solution, too.
Python:
def Decode(msg):
return ''.join([chr(ord(msg[i * 2]) + ord(msg[i * 2 + 1]) - 1768 + ord(msg[i * 2 + 1 - (i & 1)]) * 16) for i in range(len(msg) // 2)])
print(Decode('gggruggvucftvghtrhho'))
JavaScript:
function Decode(msg)
{
return Array(msg.length >> 1).fill(0).map((_, i) => String.fromCharCode(msg[i * 2].charCodeAt(0) + msg[i * 2 + 1].charCodeAt(0) - 1768 + (msg[i * 2 + 1 - (i & 1)].charCodeAt(0) << 4))).join('');
}
console.log(Decode('gggruggvucftvghtrhho'));

Reversing print order using recurion

Right now, I have the following pseudocode
Printstations(fastest, path, lastpath, n)
print "fastest solution requires" + fastest + "time units"
print "line' + lastpath +"station" + n
for j = n downto 2
print "line" + path[lastpath, j] + "station" + j-1
lastpath = path[lastpath, j]
a sample output would be:
fastest solution requires 14 time units:
line 1, station 4
line 2, station 3
line 2, station 2
line 1, station 1
I need to reverse the order of that printout using recursion.
basically, I need it to read:
fastest solution requires 14 time units:
line 1, station 1
line 2, station 2
line 2, station 3
line 1, station 4
Thanks.
So in essence, the station order needs to change from reading 4 down to 1 to being station 1 to 4, because of the sample, the line order doesn't appear to change but that it because in essence the line numbers here create a palindrome. I haven't really been able to get anything coherent down yet. I am confused as to how recursion could change the order.
I came up with this:
PrintStations(fastest, path, lastpath, n)
if n = 0
print "fastest solution requires" + fastest + "time units"
else
PrintStations(fastest, path, path[lastpath, n], n-1)
print "line" + lastpath + "station" + n
I think that may work, not entirely sure though.
You are on the right track. Your current output looks like this:
fastest solution requires 14 time units:
line 1, station 4
line 2, station 3
line 2, station 2
line 1, station 1
And you want to have such an output:
fastest solution requires 14 time units:
line 1, station 1
line 2, station 2
line 2, station 3
line 1, station 4
In order to achieve this using a recursion, you need to change your current solution:
PrintStations(fastest, path, lastpath, n)
if n = 0
COMMENT: incorrect, because this will be the last printed text,
COMMENT: this line should be called once at the begining
COMMENT: or even better before the recursive call is executed
print "fastest solution requires" + fastest + "time units"
else
COMMENT: better change the order of the resursive call and the print
PrintStations(fastest, path, path[lastpath, n], n-1)
print "line" + lastpath + "station" + n
This will print the line faster solution requires ... at the end of the execution and not at the begining. I am assuming that you start with n and not 0, because if you start with 0 the resursive call is never reached.
A general approach using recursion is to extract the function that calls itself and execute it initially from another function, because you need a start point.
You can create a function called PrintSolution, that takes the same arguments as your PrintStations function and call the PrintStations once from within.
This would be also the right place to print the fastest solution ... text:
COMMENT: this is now your starting point
PrintSolution(fastest, path, lastpath, n)
print "fastest solution requires" + fastest + "time units"
PrintStations(fastest, path lastpath, n)
Your PrintStations will also become smaller and easier to write/read:
PrintStations(fastest, path, lastpath, n)
COMMENT: execution break condition is n == 0
if n > 0
COMMENT: print current path and station
print "line" + lastpath + "station" + n
COMMENT: call print station with next/previous path to print
PrintStations(fastest, path, path[lastpath, n], n-1)
There are of course other possibilities to create the recursive function. A solution that does not require a second function could look like this:
variable m = n
PrintStations(fastest, path, lastpath, n)
COMMENT: execution break condition is n == 0
if (n = m)
COMMENT: first call
print "fastest solution requires" + fastest + "time units"
if n > 0
COMMENT: print current path and station
print "line" + lastpath + "station" + n
COMMENT: call print station with next/previous path to print
PrintStations(fastest, path, path[lastpath, n], n-1)
In this case you need the initial value of the n variable in order to print the first line only once.
The resursive call is equivalent to the iteration, because it operates also sequentially on the given data structure:
print(3);
COMMENT: equivalent to for (i = 3; i <= 1; i--) => 3 -> 2 -> 1
for i = 3 downto 1
out i
COMMENT: 3 -> 2 -> 1
print(n)
if (n > 0)
print(n-1);
out n
COMMENT: reverse the print - 1 -> 2 -> 3
variable m = n
print(n)
if (n <= m)
print(n+1);
out n
Another possibility would be to give the break condition constant as a parameter:
print(n, m)
if (n <= m)
print(n+1, m);
out n
COMMENT: initial call: print(1, 3)
Without precise description and more information (or at least the data) about the path array, it is difficult to write a working solution, but the pseudocode goes in the right direction.

Minimum Weight Triangulation Taking Forever

so I've been working on a program in Python that finds the minimum weight triangulation of a convex polygon. This means that it finds the weight(The sum of all the triangle perimeters), as well as the list of chords(lines going through the polygon that break it up into triangles, not the boundaries).
I was under the impression that I'm using the dynamic programming algorithm, however when I tried using a somewhat more complex polygon it takes forever(I'm not sure how long it takes because I haven't gotten it to finish).
It works fine with a 10 sided polygon, however I'm trying 25 and that's what is making it stall. My teacher gave me the polygons so I assume that the 25 one is supposed to work as well.
Since this algorithm is supposed to be O(n^3), the 25 sided polygon should take roughly 15.625 times longer to calculate, however it's taking way longer seeing that the 10 sided seems instantaneous.
Am I doing some sort of n operation in there that I'm not realizing? I can't see anything I'm doing, except maybe the last part where I get rid of the duplicates by turning the list into a set, however in my program I put a trace after the decomp before the conversion happens, and it's not even reaching that point.
Here's my code, if you guys need anymore info just please ask. Something in there is making it take longer than O(n^3) and I need to find it so I can trim it out.
#!/usr/bin/python
import math
def cost(v):
ab = math.sqrt(((v[0][0] - v[1][0])**2) + ((v[0][1] - v[1][1])**2))
bc = math.sqrt(((v[1][0] - v[2][0])**2) + ((v[1][1] - v[2][1])**2))
ac = math.sqrt(((v[0][0] - v[2][0])**2) + ((v[0][1] - v[2][1])**2))
return ab + bc + ac
def triang_to_chord(t, n):
if t[1] == t[0] + 1:
# a and b
if t[2] == t[1] + 1:
# single
# b and c
return ((t[0], t[2]), )
elif t[2] == n-1 and t[0] == 0:
# single
# c and a
return ((t[1], t[2]), )
else:
# double
return ((t[0], t[2]), (t[1], t[2]))
elif t[2] == t[1] + 1:
# b and c
if t[0] == 0 and t[2] == n-1:
#single
# c and a
return ((t[0], t[1]), )
else:
#double
return ((t[0], t[1]), (t[0], t[2]))
elif t[0] == 0 and t[2] == n-1:
# c and a
# double
return ((t[0], t[1]), (t[1], t[2]))
else:
# triple
return ((t[0], t[1]), (t[1], t[2]), (t[0], t[2]))
file_name = raw_input("Enter the polygon file name: ").rstrip()
file_obj = open(file_name)
vertices_raw = file_obj.read().split()
file_obj.close()
vertices = []
for i in range(len(vertices_raw)):
if i % 2 == 0:
vertices.append((float(vertices_raw[i]), float(vertices_raw[i+1])))
n = len(vertices)
def decomp(i, j):
if j <= i: return (0, [])
elif j == i+1: return (0, [])
cheap_chord = [float("infinity"), []]
old_cost = cheap_chord[0]
smallest_k = None
for k in range(i+1, j):
old_cost = cheap_chord[0]
itok = decomp(i, k)
ktoj = decomp(k, j)
cheap_chord[0] = min(cheap_chord[0], cost((vertices[i], vertices[j], vertices[k])) + itok[0] + ktoj[0])
if cheap_chord[0] < old_cost:
smallest_k = k
cheap_chord[1] = itok[1] + ktoj[1]
temp_chords = triang_to_chord(sorted((i, j, smallest_k)), n)
for c in temp_chords:
cheap_chord[1].append(c)
return cheap_chord
results = decomp(0, len(vertices) - 1)
chords = set(results[1])
print "Minimum sum of triangle perimeters = ", results[0]
print len(chords), "chords are:"
for c in chords:
print " ", c[0], " ", c[1]
I'll add the polygons I'm using, again the first one is solved right away, while the second one has been running for about 10 minutes so far.
FIRST ONE:
202.1177 93.5606
177.3577 159.5286
138.2164 194.8717
73.9028 189.3758
17.8465 165.4303
2.4919 92.5714
21.9581 45.3453
72.9884 3.1700
133.3893 -0.3667
184.0190 38.2951
SECOND ONE:
397.2494 204.0564
399.0927 245.7974
375.8121 295.3134
340.3170 338.5171
313.5651 369.6730
260.6411 384.6494
208.5188 398.7632
163.0483 394.1319
119.2140 387.0723
76.2607 352.6056
39.8635 319.8147
8.0842 273.5640
-1.4554 226.3238
8.6748 173.7644
20.8444 124.1080
34.3564 87.0327
72.7005 46.8978
117.8008 12.5129
162.9027 5.9481
210.7204 2.7835
266.0091 10.9997
309.2761 27.5857
351.2311 61.9199
377.3673 108.9847
390.0396 148.6748
It looks like you have an issue with the inefficient recurision here.
...
def decomp(i, j):
...
for k in range(i+1, j):
...
itok = decomp(i, k)
ktoj = decomp(k, j)
...
...
You've ran into the same kind of issue as a naive recursive implementation of the Fibonacci Numbers, but the way this algorithm works, it'll probably be much worst on the run time. Assuming that is the only issue with you're algorithm, then you just need to use memorization to ensure that the decomp is only calculated once for each unique input.
The way to spot this issue is to print out the values of i, j and k as the triple (i,j,k). In order to obtain a runtime of O(N^3), you shouldn't see the same exact triple twice. However, the triple (22, 24, 23), appears at least twice (in the 25), and is the first such duplicate. That shows the algorithm is calculating the same thing multiple times, which is inefficient, and is bumping up the performance well past O(N^3). I'll leave figuring out what the algorithms actual performance is to you as an exercise. Assuming there isn't something else wrong with the algorithm the algorithm should eventually stop.

2 Dimentional array dereferencing ,how to evaluate through pointers

a[2][3] = {{-3,14,5},{1,-10,8}}
*(a[j]+k)
*(a[j+k-2])
(*(a+j))[k])
(*(a+k-1))[j]
*((*(a+j))+k))
(**(a+j)+k)
*(&a[0][0]+j+k)
when i printf these i get
Output:
8
1
8
-10
8
3
1
respectively
Please if anyone can explain in detail how the values are coming ,i am a new starter please pardon me for bad formatting here and also bothering you for with so much work :)
I assume j == 1 and k == 2:
*(a[j]+k) == *(a[1]+2) :
a[1] = {1, -10, 8};
So a[1]+2 is a pointer to 8, and *(a[1]+2) == 8
*(a[j+k-2]) == *(a[1+2-2]) == *(a[1]):
a[1] = {1, -10, 8}
Since *a[1] is the value of the first element in a[1], the expression evaluates to 1
(*(a+j))[k] == (*(a+1))[2]:
a+1 is a pointer to the second element in a, so *(a+1) == a[1] = {1, -10, 8}
a[1][2] == 8
(*(a+k-1))[j] == (*(a+2-1))[1] == (*(a+1))[1]:
*(a+1) == a[1] (see the last answer)
a[1][1] == -10
*((*(a+j))+k) == *((*(a+1))+2):
*(a+1) == a[1], so the expressions is equivalent to *(a[1]+2)
*(a[1]+2) is equivalent to a[1][2] for the same reasoning as above, which is 8
(**(a+j)+k) == (**(a+1)+2):
*(a+1) = a[1]
**(a+1) = a[1][0] == 1
Adding 2 to that gives 3
*(&a[0][0]+j+k) == *(&a[0][0]+1+2) == *(&a[0][0]+3):
&a[0][0] == a[0]
*(a[0]+3) == a[0][3];
This last one is returning 1, because it is extending in memory past the end of a[0] into a[1], and you're getting a[1][0]. I think this behavior is actually undefined though. It depends on whether the C standard guarantees that an initialized 2D array will be allocated sequentially in memory or not, and could result in a Segmentation fault or worse.

Resources