It looks like I didn’t understand the code after all. → in the c++ seem to be doing something, but I don’t know what it is.
EDIT: I checked with Visual Studio, there’s no patterns, so I don’t think unrolling it is possible. There’s no clear pattern yet. It is confirmed that FindFactors() in the C++ has been successful replicated. It’s printFactors() that is the problem.
EDIT: I think I have 1:1 conversion, but for some reason, it doesn’t work.
Reasonings on why I think it works. It uses pos==endval which means it will stop the loop once pos meets endval. The same condition as the c++ version. endval is not modified. Variables are updated inside count for loop, and this mean it should go right back at the beginning.
current_factor=1;
pos=0;
endval=da_size(#$primeFactors)-1;
while(1,
if(pos==endval,break(););
use_inc=1;
while(pos!=endval&&!(I[#$primeFactors,pos])[1],
++pos;
);
for( count=(I[#$primeFactors,pos])[1],!count,--count,
current_factor*=(I[#$primeFactors,pos])[0];
da_push(#$factors,current_factor);
++pos;
use_inc=0;
break();
);
if(use_inc,++pos);
);
I think the problem occurs inside the for() within while(1,....);. Strangely, print(variable) inside it returns nothing. Zilch. Not even a 0. That’s why da_push() does nothing.
Full Code
#@cli rep_find_factors_of: num_0...
rep_find_factors_of:
1,1,1,2 :: primeFactors
1,1,1,1 :: factors
eval "
v=$1;
square=int(sqrt(v));
for(n=2,n<=square&&n<=n,++n,
isPrime=1;
for(p=0,p<da_size(#$primeFactors),++p,
prime=(I[#$primeFactors,p])[0];
sqr(prime)>n?break();
!(n%prime)?(
isPrime=0;
break();
);
);
isPrime?(
count=0;
while(!(v%n),
++count;
v/=n;
);
da_push(#$primeFactors,[n,count]);
count?square=int(sqrt(v));
);
);
v!=1?(da_push(#$primeFactors,[v,1]));
current_factor=1;
pos=0;
endval=da_size(#$primeFactors)-1;
while(1,
if(pos==endval,break(););
use_inc=1;
while(pos!=endval&&!(I[#$primeFactors,pos])[1],
++pos;
);
for( count=(I[#$primeFactors,pos])[1],!count,--count,
current_factor*=(I[#$primeFactors,pos])[0];
da_push(#$factors,current_factor);
++pos;
use_inc=0;
break();
);
if(use_inc,++pos);
);"
EDIT: Ah, my mistake is translating the auto pos->second inside for loop in the C++ code. What it seems is that auto access the index pos, and then retrieve the pair.second, and within the for loop, it modifies the pair.second. That seem hard to translate.
And I give up, there’s no translating printFactors()…
EDIT: Maybe, I’m thinking of this in the wrong way.
From the description of how the code works : “The best approach here is probably to calculate the prime factorization of the number and then printing out the products of all possible combinations of those prime factors.”
So, to find a iteration version of said code, I need to do the above.
48 → 2,2,2,2,3
The patterns goes like:
2
6
4
12
8
24
16
48
3
Here’s my observation of what is happening:
2
2*3=6
2*2=4
2*2*3=12
2*2*2=8
2*2*2*3=24
2*2*2*2=16
2*2*2*2*3=48
3
As for 60:
<<2,2>><<3,1>><<5,1>>
1
2 = 2
6 = 2*3
30 = 2*3*5
10 = 2*5
4 = 2*2
12 = 2*2*3
60 = 2*2*3*5
20 = 2*2*5
3 = 3
15 = 5*3
5 = 5
So, all I have to do is write a code that use da_push, and do the following behavior. Maybe one without needing to sort after can be made. Not sure how to write it though. The order does not matter at all.
More information, it seems that I make the above as some sort of graph.
2 | 3 | 5
---------
2 | 1 | 1
---------
1 | 0 | 0 = 2 * 1 = 2
1 | 1 | 0 = 2 * 3 = 6
1 | 1 | 1 = 2 * 3 * 5 = 30
1 | 0 | 1 ....
2 | 0 | 0
2 | 1 | 0
2 | 1 | 1
2 | 0 | 1
0 | 1 | 0
0 | 1 | 1
0 | 0 | 1
So, I’m closer to making a iterative function to doing this.
This means my current code (Added graph image for use to try to do the above)
#@cli rep_find_factors_of: num_0...
rep_find_factors_of:
1,1,1,2 :: primeFactors
1,1,1,1 :: graph
1,1,1,1 :: factors
eval "
pos_first(v)=(I[#$primeFactors,v])[0];
pos_second(v)=(I[#$primeFactors,v])[1];
v=$1;
square=int(sqrt(v));
for(n=2,n<=square&&n<=n,++n,
isPrime=1;
for(p=0,p<da_size(#$primeFactors),++p,
prime=(I[#$primeFactors,p])[0];
sqr(prime)>n?break();
!(n%prime)?(
isPrime=0;
break();
);
);
isPrime?(
count=0;
while(!(v%n),
++count;
v/=n;
);
da_push(#$primeFactors,[n,count]);
count?square=int(sqrt(v));
);
);
v!=1?(da_push(#$primeFactors,[v,1]));
#The for loop below is used to remove all multi-channel index with a zero at the second channel.
for(p=da_size(#$primeFactors)-1,p>-1,--p,
if(!(I[#$primeFactors,p])[1],
da_remove(#$primeFactors,p);
);
);
resize(#$graph,da_size(#$primeFactors),1,1,1,0);
"
One more graph to see how it works:
3 | 5 | 7 | 11
--------------
3 | 1 | 3 | 2
--------------
1 | 0 | 0 | 0
1 | 1 | 0 | 0
1 | 1 | 1 | 1
1 | 1 | 1 | 2
1 | 1 | 2 | 0
1 | 1 | 2 | 1
1 | 1 | 2 | 2
1 | 1 | 3 | 0
1 | 1 | 3 | 1
1 | 1 | 3 | 2
1 | 1 | 0 | 1
1 | 1 | 0 | 2
1 | 0 | 1 | 0
1 | 0 | 1 | 1
1 | 0 | 1 | 2
1 | 0 | 2 | 0
1 | 0 | 2 | 1
1 | 0 | 2 | 2
....
With a help from someone, there’s this non-recursive c++ code:
Code to non-recursive version of printFactors()
void PrintFactors2(uint64_t factor, PrimeFactors &fs) {
auto pos = fs.begin();
auto end = fs.end();
std::vector<std::tuple<uint64_t, uint64_t, uint64_t, PrimeFactors::const_iterator> > stack;
stack.push_back(std::make_tuple(factor, pos->first, pos->second, pos));
while (stack.size() > 0) {
auto top = stack.back();
stack.pop_back();
uint64_t tval = 0;
if (stack.size() > 0) {
auto prev = stack.back();
tval = std::get<0>(prev);
}
auto fac = std::get<0>(top) * std::get<1>(top);
if (std::get<2>(top) > 0) {
std::cout << fac << std::endl;
stack.push_back(std::make_tuple(fac,
std::get<1>(top),
std::get<2>(top)-1,
std::get<3>(top)));
auto p = std::get<3>(top);
++p;
if (p != end) {
stack.push_back(std::make_tuple(fac,
p->first,
p->second,
p));
}
} else if (tval > 0) {
auto p = std::get<3>(top);
++p;
if (p != end) {
stack.push_back(std::make_tuple(tval,
p->first,
p->second,
p));
}
} else {
auto p = std::get<3>(top);
++p;
if (p != end) {
stack.push_back(std::make_tuple(factor,
p->first,
p->second,
p));
}
}
}
}