I'm converting Ruby code to D and am running into issues.
Would appreciate what needs to be done to get it to compile/run correctly.
Here's the Ruby code:
# Enable YJIT if using CRuby >= 3.3"
RubyVM::YJIT.enable if RUBY_ENGINE == "ruby" and RUBY_VERSION.to_f >= 3.3
def prime_pairs_lohi(n)
return puts "Input not even n > 2" unless n.even? && n > 2
return (pp [n, 1]; pp [n/2, n/2]; pp [n/2, n/2]) if n <= 6
# generate the low-half-residues (lhr) r < n/2
lhr = 3.step(n/2, 2).select { |r| r if r.gcd(n) == 1 }
ndiv2, rhi = n/2, n-2 # lhr:hhr midpoint, max residue limit
lhr_mults = [] # for lhr values not part of a pcp
# store all the powers of the lhr members < n-2
lhr.each do |r| # step thru the lhr members
r_pwr = r # set to first power of r
break if r > rhi / r_pwr # exit if r^2 > n-2, as all others are too
while r < rhi / r_pwr # while r^e < n-2
lhr_mults << (r_pwr *= r) # store its current power of r
end
end
# store all the cross-products of the lhr members < n-2
lhr_dup = lhr.dup # make copy of the lhr members list
while (r = lhr_dup.shift) && !lhr_dup.empty? # do mults of 1st list r w/others
ri_max = rhi / r # ri can't multiply r with values > this
break if lhr_dup[0] > ri_max # exit if product of consecutive r’s > n-2
lhr_dup.each do |ri| # for each residue in reduced list
break if ri > ri_max # exit for r if cross-product with ri > n-2
lhr_mults << r * ri # store value if < n-2
end # check cross-products of next lhr member
end
# convert lhr_mults vals > n/2 to their lhr complements n-r,
# store them, those < n/2, in lhr_del; it now holds non-pcp lhr vals
lhr_del = lhr_mults.map { |r_del| (r_del > ndiv2 ? n - r_del : r_del) }
pp [n, (lhr -= lhr_del).size] # show n and pcp prime pairs count
pp [lhr.first, n-lhr.first] # show first pcp prime pair of n
pp [lhr.last, n-lhr.last] # show last pcp prime pair of n
end
def tm; t = Time.now; yield; Time.now - t end # to time runtime execution
n = ARGV[0].to_i # get n value from terminal
puts tm { prime_pairs_lohi(n) } # show execution runtime as last output
Here's my D code.
module prime_pairs;
import std;
//import std.datetime.stopwatch : StopWatch;
//import std.stdio : readf, write, writeln, readln;
//import std.numeric : gcd;
void prime_pairs_lohi(uint n) {
if ((n|1) == 1 || n < 4) return writeln("Input not even n > 2");
//if (n <= 6) return { writel([n, 1]); writeln([n/2, n/2]); writeln([n/2, n/2])}
// generate the low-half-residues (lhr) r < n/2
lhr = [];
auto ndiv2 = n/2;
auto rhi = n-2;
auto r = 3;
while (r < ndiv2) {
if (gcd(r,n) == 1) lhr ~= r;
r += 2;
}
lhr_mults = []; // for lhr values not part of a pcp
// store all the powers of the lhr members < n-2
foreach(r; lhr) { // step thru the lhr members
r_pwr = r; // set to first power of r
if (r > rhi/r_pwr) break; // exit if r^2 > n-2, as all others are too
while (r < rhi/r_pwr) { // while r^e < n-2
lhr_mults ~=(r_pwr *= r); // store its current power of r
} }
// store all the cross-products of the lhr members < n-2
lhr_dup = lhr.dup; // make copy of the lhr members list
while ((r = lhr_dup.shift) && lhr_dup.length != 0) {
ri_max = rhi / r; // ri can't multiply r with values > this
if (lhr_dup[0] > ri_max) break; // exit if product of consecutive r’s > n-2
foreach(ri; lhr_dup) { // for each residue in reduced list
if (ri > ri_max) break; // exit for r if cross-product with ri > n-2
lhr_mults ~= r * ri; // store value if < n-2
} } // check cross-products of next lhr member
// convert lhr_mults vals > n/2 to their lhr complements n-r,
// store them, those < n/2, in lhr_del; it now holds non-pcp lhr vals
lhr_del = lhr_mults.map { |r_del| (r_del > ndiv2 ? n - r_del : r_del) }
lhr -= lhr_del;
writeln("[", n,", ", lhr.length,"]"); // show n and pcp prime pairs count
writeln("[", lhr[0], ", ", n-lhr[0], "]"); // show first pcp prime pair of n
writeln("[", lhr[$-1],", ",n-lhr[$-1],"]"); // show last pcp prime pair of n
}
void main() {
ulong[] x;
foreach (_; 0 .. 1) { ulong a; readf!" %d"(a); x ~= a; }
n = x[0];
auto stopWatchExecution = StopWatch();
stopWatchExecution.start();
prime_pairs_lohi(n);
stopWatchExecution.stop();
writeln(stopWatchExecution.peek());