help with prime pairs code

Jabari Zakiya jzakiya at gmail.com
Sun Feb 2 03:22:00 UTC 2025


On Sunday, 2 February 2025 at 01:39:34 UTC, user1234 wrote:
> On Sunday, 2 February 2025 at 01:12:59 UTC, user1234 wrote:
>> On Saturday, 1 February 2025 at 21:56:23 UTC, Jabari Zakiya 
>> wrote:
>>> On Saturday, 1 February 2025 at 00:21:22 UTC, user1234 wrote:
>>>> On Friday, 31 January 2025 at 20:05:54 UTC, Jabari Zakiya 
>>>> wrote:
>>>>> [...]
>>>>
>>>> A first draft of the translation, not very idiomatic D code:
>>>>
>>>> ```d
>>>> module prime_pairs;
>>>> import std;
>>>>
>>>> [...]
>>>
>>> Thank you very much!
>>>
>>> As you can see, D is not my primary language, but I respect 
>>> its speed and readability.
>>> I also have a faster Crystal version, almost identical (96%) 
>>> to the Rudy code.
>>
>> yeah Crystal is in my scope. Whyle I'm usualy not into dynamic 
>> typed langs, there's something I like in the Crystal lang.
>
> [Gradual 
> typing](https://en.wikipedia.org/wiki/Gradual_typing#:~:text=Gradual%20typing%20allows%20software%20developers,static%20typing%20to%20be%20used.)
>
> That's the shit I like with Crystal.

Here's the Crystal version of the Ruby code.

```
# Compile: crystal build --release --mcpu native 
prime_pairs_lohi.cr
# Run as: ./prime_pairs_lohi 123_456_780

     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 = 3u64.step(to: n//2, by: 2).select { |r| r if r.gcd(n) 
== 1 }.to_a
       ndiv2, rhi = n//2, n-2           # lhr:hhr midpoint, max 
residue limit
       lhr_mults = [] of typeof(n)      # 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

       # remove from lhr its lhr_mults, convert vals > n/2 to lhr 
complements first
       lhr -= lhr_mults.map { |r_del| r_del > ndiv2 ? n - r_del : 
r_del }

       pp [n, lhr.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.monotonic; yield; Time.monotonic - t end  # time 
code execution

     def gen_pcp
       n = (ARGV[0].to_u64 underscore: true) # get n input from 
terminal
       puts tm { prime_pairs_lohi(n) }       # show execution 
runtime as last output
     end

gen_pcp
```

Add this to the D code to take terminal input and to time 
execution.
I don't know if this is most idiomatic, but it works.


     import std.datetime.stopwatch : StopWatch;
     void main() {
       int n;
       readf("%s", &n);
       auto stopWatchExecution = StopWatch();
       stopWatchExecution.start();
       prime_pairs_lohi(n);
       stopWatchExecution.stop();
       writeln(stopWatchExecution.peek());
     }


The D version is way slower, because of the array operations.
For an input of 1000000 (1M): D: 12+ secs; Crystal: 0.036 secs.

In Ruby|Crystal you can just do: lhr -= lhr_mult
to remove elements of one array from another, and not one at a 
time.
I assume there's a D equivalent?!?

As n increases so do those arrays, and the times become much 
longer.



More information about the Digitalmars-d-learn mailing list