You are given a string of uppercase and lowercase letters.

Prime groups is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Print the first group of 3 letters in the string where all pairs of absolute differences between the letters' character codes is a prime.

If there are no combinations in the string which satisfy the condition, print Not found.

Do this for the following strings:

['riOtjuoq', 'wjtiOxtj', 'akwercjoeiJ', 'Weej', 'Aek', 'jjgja']

The expected output is:

rto
Not found.
ecj
Not found.
Not found.
Not found.

Extra credit: Same as above, but extend your code to support groups of 2 letters.

The expected output is:

rt
wj
ar
Wj
Not found.
jg

C

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool isPrime(int n) {
    int i;

    if (n < 2)
        return false;

    for (i = 2; i * i <= n; i++)
        if (n % i == 0)
            return false;

    return true;
}

void firstPrimeGroup3(char* word) {
    int i, j, k, n = strlen(word);

    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            for (k = j + 1; k < n; k++) {
                if (isPrime(abs(word[i] - word[j])) &&
                    isPrime(abs(word[i] - word[k])) &&
                    isPrime(abs(word[j] - word[k]))) {
                    printf("%c%c%c\n", word[i], word[j], word[k]);
                    return;
                }
            }
        }
    }
    printf("Not found.\n");
}

void firstPrimeGroup2(char* word) {
    int i, j, n = strlen(word);

    for (i = 0; i < n; i++) {
        for (j = i + 1; j < n; j++) {
            if (isPrime(abs(word[i] - word[j]))) {
                printf("%c%c\n", word[i], word[j]);
                return;
            }
        }
    }
    printf("Not found.\n");
}

int main() {
    int i;
    char* testCases[] = {"riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"};

    for (i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++)
        firstPrimeGroup3(testCases[i]);

    printf("\n");

    for (i = 0; i < sizeof(testCases) / sizeof(testCases[0]); i++)
        firstPrimeGroup2(testCases[i]);

    return 0;
}
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    private static bool IsPrime(int n)
    {
        if (n <= 1) return false;
        for (int i = 2; i * i <= n; i++)
            if (n % i == 0)
                return false;
        return true;
    }

    private static bool AllDiffsPrime(char[] chars)
    {
        for (int i = 0; i < chars.Length; i++)
            for (int j = i + 1; j < chars.Length; j++)
                if (!IsPrime(Math.Abs(chars[i] - chars[j])))
                    return false;
        return true;
    }

    private static IEnumerable<T[]> Subsets<T>(T[] arr, int k)
    {
        if (k <= 0) yield break;
        int[] a = Enumerable.Range(0, k).ToArray();
        int n = arr.Length;
        while (true) {
            yield return a.Select(i => arr[i]).ToArray();
            if (a[0] == n - k) break;
            int i = k - 1;
            while (a[i] == n - k + i) i--;
            a[i]++;
            for (int j = i + 1; j < k; j++) a[j] = a[j - 1] + 1;
        }
    }

    private static string FirstPrimeGroup(string s, int k)
    {
        foreach (var subset in Subsets<char>(s.ToCharArray(), k))
            if (AllDiffsPrime(subset))
                return new string(subset);
        return "Not found.";
    }

    static void Main()
    {
        string[] testCases = ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"];

        foreach (var testCase in testCases)
            Console.WriteLine(FirstPrimeGroup(testCase, 3));

        Console.WriteLine();

        foreach (var testCase in testCases)
            Console.WriteLine(FirstPrimeGroup(testCase, 2));
    }
}
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
#include <cstdint>
#include <iostream>
#include <string>
#include <vector>

bool is_prime(const uint32_t& number) {
	if ( number < 2 || number % 2 == 0 ) {
		return number == 2;
	}
	uint32_t k = 3;
	while ( k * k <= number ) {
		if ( number % k == 0 ) {
			return false;
		}
		k += 2;
	}
	return true;
}

template <typename T>
void print_vector(const std::vector<T>& vec) {
	std::cout << "[";
	for ( uint32_t i = 0; i < vec.size() - 1; ++i ) {
		std::cout << vec[i] << ", ";
	}
	std::cout << vec.back() << "]" << std::endl;
}

template <typename T>
void combinationsRecursive(const uint32_t& index, const uint32_t& r,
		             	   std::vector<T>& data, std::vector<std::vector<T>>& result, std::vector<T>& source) {
    if ( data.size() == r ) {
        result.emplace_back(data);
        return;
    }

    for ( uint32_t i = index; i < source.size(); ++i ) {
        data.emplace_back(source[i]);
        combinationsRecursive(i + 1, r, data, result, source);
        data.pop_back();
    }
}

template <typename T>
std::vector<std::vector<T>> combinations(std::vector<T>& source, const uint32_t& r) {
    std::vector<std::vector<T>> result;
    std::vector<T> data;
    combinationsRecursive(0, r, data, result, source);
    return result;
}

int main() {
	std::vector<std::string> words = { "riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja" };

	std::vector<std::string> result;

	std::cout << "Groups of 3 letters: ";
	for ( const std::string& word : words ) {
		std::string group3 = "Not found";
		std::vector<char> chars(word.begin(), word.end());

		for ( std::vector<char> combo : combinations(chars, 3) ) {
			if ( is_prime(std::abs(combo[0] - combo[1])) &&
				is_prime(std::abs(combo[0] - combo[2])) &&
				is_prime(std::abs(combo[1] - combo[2])) ) {
				std::string temp(combo.begin(), combo.end());
				group3 = temp;
				break;
			}
		}

		result.emplace_back(group3);
	}

	print_vector(result);
	result.clear();

	std::cout << "Groups of 2 letters: ";
	for ( const std::string& word : words ) {
		std::string group2 = "Not found";
		std::vector<char> chars(word.begin(), word.end());

	    for ( const std::vector<char>& pair : combinations(chars, 2) ) {
	    	if ( is_prime(std::abs(pair[0] - pair[1])) ) {
	    		std::string temp(pair.begin(), pair.end());
	    		group2 = temp;
	    		break;
	    	}
	    }

	    result.emplace_back(group2);
	}

	print_vector(result);
}
Output:
Groups of 3 letters: [rto, Not found, ecj, Not found, Not found, Not found]
Groups of 2 letters: [rt, wj, ar, Wj, Not found, jg]

D

import std.stdio, std.algorithm, std.range, std.math;

bool isPrime(int n) { return n >= 2 && iota(2, n).all!(i => n % i != 0); }

bool allDiffsPrime(char[] chars) {
    foreach (i, a; chars)
        foreach (j, b; chars[i + 1 .. $])
            if (!isPrime(abs(a - b)))
                return false;
    return true;
}

struct Subsets(T) {
    T[] arr;
    int n, k;
    int[] a;
    bool done;

    this(T[] arr, int k) {
        this.arr = arr;
        this.k = k;
        n = cast(int)arr.length;
        a = iota(k).array;
        done = (k <= 0 || k > n);
    }

    @property bool empty() { return done; }

    @property T[] front() { return a.map!(i => arr[i]).array; }
    
    void popFront() {
        int i = k - 1;
        while (i >= 0 && a[i] == n - k + i) i--;
        if (i < 0) { done = true; return; }
        a[i]++;
        foreach (j; i + 1 .. k) a[j] = a[j-1] + 1;
    }
}

string firstPrimeGroup(string s, int k) {
    foreach(subset; Subsets!char(s.dup, k))
        if (allDiffsPrime(subset))
            return subset.dup;
    return "Not found.";
}

void main() {
    auto testCases = ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"];

    foreach (testCase; testCases)
        writeln(firstPrimeGroup(testCase, 3));
        
    writeln();

    foreach (testCase; testCases)
        writeln(firstPrimeGroup(testCase, 2));
}
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
func isprim n .
   if n < 2 : return 0
   for i = 2 to sqrt n : if n mod i = 0 : return 0
   return 1
.
func$ find t$ .
   for c$ in strchars t$ : t[] &= strcode c$
   for a in t[] : for b in t[] : for c in t[]
      if isprim abs (a - b) = 1 and isprim abs (b - c) = 1 and isprim abs (a - c) = 1
         return strchar a & strchar b & strchar c
      .
   .
.
for t$ in [ "riOtjuoq" "wjtiOxtj" "akwercjoeiJ" "Weej" "Aek" "jjgja" ]
   r$ = find t$
   if r$ = "" : r$ = "Not found."
   print r$
.
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.
Translation of: Python
#include "isprime.bas"

Function comb(n As Integer, r As Integer) As Integer
    If r < 0 Or r > n Then Return 0
    If r = 0 Or r = n Then Return 1

    Dim As Double f = 1
    For i As Integer = n To n - r + 1 Step -1
        f *= i
    Next
    For i As Integer = 1 To r
        f /= i
    Next

    Return Cint(f)
End Function

Sub combinations(s As String, k As Integer, result() As String)
    Dim As Integer i, cnt = 0, n = Len(s)
    
    If k < 1 Or k > n Then
        Redim result(-1 To -1)
        Return
    End If

    Redim result(comb(n, k) -1)
    Dim As Integer idx(k-1)
    For i = 0 To k-1 : idx(i) = i : Next
    
    Do
        Dim As String combi = ""
        For i = 0 To k-1
            combi &= Mid(s, idx(i)+1, 1)
        Next
        result(cnt) = combi
        cnt += 1
        
        Dim As Integer posic = k-1
        While posic >= 0 And idx(posic) = n - k + posic
            posic -= 1
        Wend
        If posic < 0 Then Exit Do
        idx(posic) += 1
        For i = posic + 1 To k-1
            idx(i) = idx(i-1) + 1
        Next
    Loop
End Sub

Function diffs(s As String, number As Integer) As Boolean
    Dim As Integer i, j, d, c = 0, n = Len(s)
    
    For i = 1 To n-1
        For j = i+1 To n
            d = Abs(Asc(Mid(s,i,1)) - Asc(Mid(s,j,1)))
            If isPrime(d) Then c += 1
        Next
    Next

    Return c = comb(number, 2)
End Function

Sub runTests(tests() As String, number As Integer)
    For i As Integer = 0 To Ubound(tests)
        Dim As String result()
        combinations(tests(i), number, result())
        Dim As Boolean allPrime = False
        For j As Integer = 0 To Ubound(result)
            If diffs(result(j), number) Then
                Print result(j)
                allPrime = True
                Exit For
            End If
        Next
        If Not allPrime Then Print "Not allPrime."
    Next
End Sub

' Tests
Dim As String tests(5) = {"riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"}

Print "Three character prime groups:"
runTests(tests(), 3)
Print !"\nTwo character prime groups:"
runTests(tests(), 2)

Sleep
Output:
Three character prime groups:
rto
Not allPrime.
ecj
Not allPrime.
Not allPrime.
Not allPrime.

Two character prime groups:
rt
wj
ar
Wj
Not allPrime.
jg
import Data.List
import Data.Char

isPrime :: Int -> Bool
isPrime n
  | n < 2 = False
  | n == 2 = True
  | otherwise = 0 == length [i | i <- [2..floor(sqrt (fromIntegral n))], n `mod` i == 0]

filterSubs len list = [t | t <- subsequences list, len == length t]
pairs = filterSubs 2
triplets = filterSubs 3
isPrimePair (x:y:[]) = isPrime $ abs (ord x - ord y)
dispHead list = case list of
  [] -> "Not found."
  x:xs -> x

main = do
  putStrLn "Prime Triples:"
  mapM_ putStrLn $ map ((\x -> "* " ++ x) . dispHead . primeTriples) inputs
  putStrLn "\nPrime Doubles:"
  mapM_ putStrLn $ map ((\x -> "* " ++ x) . dispHead . primeDoubles) inputs

  where
    inputs = ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"]
    primeTriples text = [ts | ts <- triplets text, all isPrimePair $ pairs ts]
    primeDoubles text = [ts | ts <- pairs text, isPrimePair ts]
Output:
Prime Triples:
* rto
* Not found.
* ecj
* Not found.
* Not found.
* Not found.

Prime Doubles:
* rt
* wj
* ar
* Wj
* Not found.
* jg
import module java.base;

public final class PrimeGroups {

	public static void main() {
		 List<String> words = List.of( "riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja" );
		 IO.println("Three character prime groups: " + primeGroups(words, 3));
		 IO.println("Two character prime groups: " + primeGroups(words, 2));
	}
	
	private static List<String> primeGroups(List<String> words, int size) {
	    List<String> result = new ArrayList<String>();
	    for ( String word : words ) {
	    	String found = "Not found";
	        List<Character> chars = word.chars().mapToObj( i -> (char) i ).toList();
	        
	        for ( List<Character> combo : combinations(chars, size) ) {
	        	if ( IntStream.range(0, size).allMatch( i -> 
	        		IntStream.range(i + 1, size).allMatch( j ->
	        			isPrime.test(Math.abs(combo.get(i) - combo.get(j))) ) ) ) {
	        		found = combo.stream().map(String::valueOf).collect(Collectors.joining());
	        		break;
	        	}
	        }	        
	        result.addLast(found);
	    }	    
	    return result;
	}
	
	private static <T> List<List<T>> combinations(List<T> list, int choose) {
		List<List<T>> combinations = new ArrayList<List<T>>();
	    List<Integer> combination = IntStream.range(0, choose).boxed().collect(Collectors.toList());	    
	    while ( combination.get(choose - 1) < list.size() ) {   	
	        combinations.add(combination.stream().map( i -> list.get(i) ).toList());	
	        int temp = choose - 1;
	        while ( temp != 0 && combination.get(temp) == list.size() - choose + temp ) {
	            temp -= 1;
	        }
	        combination.set(temp, combination.get(temp) + 1);
	        for ( int i = temp + 1; i < choose; i++ ) {
	        	combination.set(i, combination.get(i - 1) + 1);
	        }
	    }	
	    return combinations;
	}
	
	private static Predicate<Integer> isPrime = p -> p > 1 &&
		IntStream.rangeClosed(2, (int) Math.sqrt(p)).noneMatch( i -> p % i == 0 );

}
Output:
Three character prime groups: [rto, Not found, ecj, Not found, Not found, Not found]
Two character prime groups: [rt, wj, ar, Wj, Not found, jg]
import Combinatorics: combinations
import Primes: isprime

function primegroups(words, siz)
    results = ""
    for word in words
        found = "Not found"
        for combo in unique!(collect(combinations(word, siz)))
            if all(isprime(abs(Int32(combo[i]) - Int32(combo[j]))) for i in 1:siz, j in 1:siz if i < j)
                found = join(combo)
                break
            end
        end
        results *= found * "\n"
    end
    return results
end

const words = ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"]

println("Three character prime groups:")
println(primegroups(words, 3))

println("Two character prime groups:")
println(primegroups(words, 2))
Output:

Same as Raku example.

allDiffsPrimeQ[numbers_] := And @@ PrimeQ[Abs[Subtract @@@ Subsets[numbers, {2}]]];

firstPrimeGroup[s_, k_] := Module[{t},
    t = SelectFirst[Subsets[ToCharacterCode[s], {k}], allDiffsPrimeQ];
    If[t === Missing["NotFound"], "Not found.", FromCharacterCode[t]]];

testCases = {"riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"};
Map[firstPrimeGroup[#, 3] &, testCases] // TableForm
Map[firstPrimeGroup[#, 2] &, testCases] // TableForm
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Prime_groups#
use warnings;
use ntheory qw( is_prime );

my @try = ('riOtjuoq', 'wjtiOxtj', 'akwercjoeiJ', 'Weej', 'Aek', 'jjgja');

for ( @try )
  {
  print /(.).*?(.).*?(.)(??{
    is_prime(abs(ord($1)-ord($2))) &&
    is_prime(abs(ord($1)-ord($3))) &&
    is_prime(abs(ord($2)-ord($3))) ? '' : '(*FAIL)'
    })/ ? "$1$2$3\n" : "Not found.\n";
  }

print "\n";

for ( @try )
  {
  print /(.).*?(.)(??{
    is_prime(abs(ord($1)-ord($2))) ? '' : '(*FAIL)'
    })/ ? "$1$2\n" : "Not found.\n";
  }
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
for n in {3,2} do
    printf(1,"Groups of %d letters:\n",n)
    for test in {"riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"} do
        string res = "Not found."
        -- aside: use a tagset to prevent de-duplication / reordering.
        for c in combinations(tagset(length(test)),n) do
            bool all_prime = true
            for pair in combinations(c,2) do
                integer {c1,c2} = extract(test,pair)
                if not is_prime(abs(c1-c2)) then
                    all_prime = false
                    exit
                end if
            end for
            if all_prime then res = extract(test,c); exit end if
        end for
        printf(1,"%s\n",{res})
    end for
end for
Output:

(same as Pluto, etc)

Groups of 3 letters:
rto
Not found.
ecj
Not found.
Not found.
Not found.
Groups of 2 letters:
rt
wj
ar
Wj
Not found.
jg
Translation of: Wren
Library: Pluto-perm
Library: Pluto-int
require "perm"
local int = require "int"

local tests = {"riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"}

print("Groups of 3 letters:")
for tests as test do
    local res = {}
    for comb.list(test:split(""), 3) as c do
        local all_prime = true
        for comb.list(c, 2) as pair do
            local delta = math.abs(pair[1]:byte() - pair[2]:byte())
            if !int.isprime(delta) then
                all_prime = false
                break
            end
        end
        if all_prime then res:insert(c) end
    end
    if #res > 0 then
        print(res[1]:concat(""))
    else
        print("Not found.")
    end
end

print("\nGroups of 2 letters:")
for tests as test do
    local res = {}
    for comb.list(test:split(""), 2) as pair do
        local delta = math.abs(pair[1]:byte() - pair[2]:byte())
        if int.isprime(delta) then res:insert(pair) end
    end
    if #res > 0 then
        print(res[1]:concat(""))
    else
        print("Not found.")
    end
end
Output:
Groups of 3 letters:
rto
Not found.
ecj
Not found.
Not found.
Not found.

Groups of 2 letters:
rt
wj
ar
Wj
Not found.
jg
# Print the first group of 3 characters
# within a string where all 3 pairs
# of their ord-code differences is a prime.

from itertools import combinations
import math

def a(a,b):
    return abs(a-b)

def is_prime(i):
    if i < 2: return False
    for n in range(2,i-1):
        if i % n == 0: return False
    return True

class Run:
    def __init__(self,tests,n):
        self.tests = tests
        self.number = n

    def diffs(self,s):
        L = list(map(ord,s))
        D = map(lambda x:a(x[0],x[1]),combinations(L,2))
        c = 0
        for i in D:
            if is_prime(i):
                c += 1
        return c == math.comb(self.number,2)

    def run_tests(self):
        for x in self.tests:
            comb = [''.join(i) for i in combinations(x, self.number)]
            for i in comb:
                if self.diffs(i):
                    print(i)
                    break
            else:
                print("Not found.")

tests = ['riOtjuoq', 'wjtiOxtj', 'akwercjoeiJ', 'Weej', 'Aek', 'jjgja']

runner = Run(tests, 3)
runner.run_tests()

print ('======')

runner = Run(tests, 2)
runner.run_tests()
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.
======
rt
wj
ar
Wj
Not found.
jg

R

library(stringr)

#Maximum difference in codes is 122-65=57, so only primes up to this value need to be used
#Only need to test divisibility up to 7 (57 is less than 11 squared)
testdivisors <- c(2,3,5,7)
primetest <- function(n) !(0 %in% (n%%testdivisors))
primes <- c(testdivisors, Filter(primetest, 8:57))

prime_group <- function(s, n){
  codes <- sapply(str_split_1(s, ""), utf8ToInt)
  groups <- combn(codes, n, simplify=FALSE)
  diffs <- lapply(groups, function(v) abs(v-c(v[-1], v[1])))
  for(d in diffs){
    if(all(d %in% primes)){
      out <- d |> names() |> str_flatten()
      return(out)
    }
  }  
  return("Not found.")
}

test_strings <- c("riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja")
allgroups <- function(n) sapply(test_strings, function(s) prime_group(s, n))
writeLines(c(allgroups(3), "", allgroups(2)))
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg
sub prime-groups ($word, $size = 3) {
   my $group;
   $word.ords.combinations($size).map: { $group = .chrs and last if all .combinations(2).map: { ([-] $_).abs.is-prime } }
   $group // 'Not found.'
}

my @words = <riOtjuoq wjtiOxtj akwercjoeiJ Weej Aek jjgja>;

say "Three character prime groups:";
say .&prime-groups(3) for @words;

say "\nTwo character prime groups:";
say .&prime-groups(2) for @words;
Output:
Three character prime groups:
rto
Not found.
ecj
Not found.
Not found.
Not found.

Two character prime groups:
rt
wj
ar
Wj
Not found.
jg
Translation of: Julia
use itertools::Itertools;
use primal::is_prime;

fn prime_groups(words: &[&str], siz: usize) -> String {
    let mut results = String::new();
    for word in words {
        let mut found = String::from("Not found");
        let chars: Vec<char> = word.chars().collect();
        for combo in chars.into_iter().combinations(siz).unique() {
            if (0..siz).all(|i| {
                (i + 1..siz).all(|j| is_prime((combo[i] as i32 - combo[j] as i32).abs() as u64))
            }) {
                found = combo.into_iter().collect();
                break;
            }
        }

        results.push_str(&found);
        results.push('\n');
    }
    results
}

fn main() {
    let words = vec!["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"];
    println!("Three character prime groups:\n{}", prime_groups(&words, 3));
    println!("Two character prime groups:\n{}", prime_groups(&words, 2));
}
Output:
Three character prime groups:
rto
Not found
ecj
Not found
Not found
Not found

Two character prime groups:
rt
wj
ar
Wj
Not found
jg
{"riOtjuoq" "wjtiOxtj" "akwercjoeiJ" "Weej" "Aek" "jjgja"}
Ps  =⊣°260

(("Nope"(∊Ps/-)⧅₂<)
| ("Nope"(/(∊Ps/-2)3)⧅₃<))
Output:
["rto"│"Nope"│"ecj"│"Nope"│"Nope"│"Nope"]
["rt"│"wj"│"ar"│"Wj"│"Nope"│"jg"]
Library: Wren-perm
Library: Wren-math
import "./perm" for Comb
import "./math" for Int

var tests = ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"]

System.print("Groups of 3 letters:")
for (test in tests) {
    var res = []
    for (comb in Comb.list(test.toList, 3)) {
        var allPrime = true
        for (pair in Comb.list(comb, 2)) {
            var delta = (pair[0].codePoints[0] - pair[1].codePoints[0]).abs
            if (!Int.isPrime(delta)) {
                allPrime = false
                break
            }
        }
        if (allPrime) res.add(comb)
    }
    if (res.count > 0) {
        System.print(res[0].join(""))
    } else {
        System.print("Not found.")
    }
}

System.print("\nGroups of 2 letters:")
for (test in tests) {
    var res = []
    for (pair in Comb.list(test.toList, 2)) {
        var delta = (pair[0].codePoints[0] - pair[1].codePoints[0]).abs
        if (Int.isPrime(delta)) res.add(pair)
    }
    if (res.count > 0) {
        System.print(res[0].join(""))
    } else {
        System.print("Not found.")
    }
}
Output:
Groups of 3 letters:
rto
Not found.
ecj
Not found.
Not found.
Not found.

Groups of 2 letters:
rt
wj
ar
Wj
Not found.
jg
string 0;

func IsPrime(N);
int  N, D;
[if N < 2 then return false;
if (N&1) = 0 then return N = 2;
if rem(N/3) = 0 then return N = 3;
D:= 5;
while D*D <= N do
    [if rem(N/D) = 0 then return false;
    D:= D+2;
    if rem(N/D) = 0 then return false;
    D:= D+4;
    ];
return true;
];

proc PrimePair(S);
char S;
int  I, J, L;
[L:= 0;  while S(L) do L:= L+1;
for I:= 0 to L-2 do
    for J:= I+1 to L-1 do
        if IsPrime(abs(S(I)-S(J))) then
            [ChOut(0, S(I));  ChOut(0, S(J));
            return;
            ];
Text(0, "Not found.");
];

proc PrimeTri(S);
char S;
int  I, J, K, L;
[L:= 0;  while S(L) do L:= L+1;
for I:= 0 to L-2 do
    for J:= I+1 to L-1 do
        if IsPrime(abs(S(I)-S(J))) then
            for K:= J+1 to L-1 do
                if IsPrime(abs(S(K)-S(I))) then
                    if IsPrime(abs(S(K)-S(J))) then
                        [ChOut(0, S(I));  ChOut(0, S(J));  ChOut(0, S(K));
                        return;
                        ];
Text(0, "Not found.");
];

int  Tests, T;
[Tests:= ["riOtjuoq", "wjtiOxtj", "akwercjoeiJ", "Weej", "Aek", "jjgja"];
for T:= 0 to 6-1 do
    [PrimeTri(Tests(T));
    CrLf(0);
    ];
CrLf(0);
for T:= 0 to 6-1 do
    [PrimePair(Tests(T));
    CrLf(0);
    ];
]
Output:
rto
Not found.
ecj
Not found.
Not found.
Not found.

rt
wj
ar
Wj
Not found.
jg