Task: Safe primes and unsafe primes

C: #include <stdbool.h>
#include <stdio.h>

int primes[] = {
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
    101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
    211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331
};
#define PCOUNT (sizeof(primes) / sizeof(int))

bool isPrime(int n) {
    int i;

    if (n < 2) {
        return false;
    }

    for (i = 0; i < PCOUNT; i++) {
        if (n == primes[i]) {
            return true;
        }
        if (n % primes[i] == 0) {
            return false;
        }
        if (n < primes[i] * primes[i]) {
            return true;
        }
    }

    for (i = primes[PCOUNT - 1] + 2; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }

    return true;
}

int main() {
    int beg, end;
    int i, count;

    
    
    beg = 2;
    end = 1000000;
    count = 0;
    printf("First 35 safe primes:\n");
    for (i = beg; i < end; i++) {
        if (isPrime(i) && isPrime((i - 1) / 2)) {
            if (count < 35) {
                printf("%d ", i);
            }
            count++;
        }
    }
    printf("\nThere are  %d safe primes below  %d\n", count, end);

    beg = end;
    end = end * 10;
    for (i = beg; i < end; i++) {
        if (isPrime(i) && isPrime((i - 1) / 2)) {
            count++;
        }
    }
    printf("There are %d safe primes below %d\n", count, end);

    
    
    beg = 2;
    end = 1000000;
    count = 0;
    printf("\nFirst 40 unsafe primes:\n");
    for (i = beg; i < end; i++) {
        if (isPrime(i) && !isPrime((i - 1) / 2)) {
            if (count < 40) {
                printf("%d ", i);
            }
            count++;
        }
    }
    printf("\nThere are  %d unsafe primes below  %d\n", count, end);

    beg = end;
    end = end * 10;
    for (i = beg; i < end; i++) {
        if (isPrime(i) && !isPrime((i - 1) / 2)) {
            count++;
        }
    }
    printf("There are %d unsafe primes below %d\n", count, end);

    return 0;
}



C#: using static System.Console;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public static class SafePrimes
{
    public static void Main() {
        HashSet<int> primes = Primes(10_000_000).ToHashSet();
        WriteLine("First 35 safe primes:");
        WriteLine(string.Join(" ", primes.Where(IsSafe).Take(35)));
        WriteLine($"There are {primes.TakeWhile(p => p < 1_000_000).Count(IsSafe):n0} safe primes below {1_000_000:n0}");
        WriteLine($"There are {primes.TakeWhile(p => p < 10_000_000).Count(IsSafe):n0} safe primes below {10_000_000:n0}");
        WriteLine("First 40 unsafe primes:");
        WriteLine(string.Join(" ", primes.Where(IsUnsafe).Take(40)));
        WriteLine($"There are {primes.TakeWhile(p => p < 1_000_000).Count(IsUnsafe):n0} unsafe primes below {1_000_000:n0}");
        WriteLine($"There are {primes.TakeWhile(p => p < 10_000_000).Count(IsUnsafe):n0} unsafe primes below {10_000_000:n0}");

        bool IsSafe(int prime) => primes.Contains(prime / 2);
        bool IsUnsafe(int prime) => !primes.Contains(prime / 2);
    }

    
    static IEnumerable<int> Primes(int bound) {
        if (bound < 2) yield break;
        yield return 2;

        BitArray composite = new BitArray((bound - 1) / 2);
        int limit = ((int)(Math.Sqrt(bound)) - 1) / 2;
        for (int i = 0; i < limit; i++) {
            if (composite[i]) continue;
            int prime = 2 * i + 3;
            yield return prime;
            for (int j = (prime * prime - 2) / 2; j < composite.Count; j += prime) composite[j] = true;
        }
        for (int i = limit; i < composite.Count; i++) {
            if (!composite[i]) yield return 2 * i + 3;
        }
    }

}