g.kov
g.kov

Reputation: 333

Is there a better way to get substring in PARI/gp?

? substr(s,n,m)=concat(Vec(s)[n..n+m-1])
%1 = (s,n,m)->concat(Vec(s)[n..n+m-1])
? s="h0getcwdfailedNosuchfileordirectory"
%2 = "h0getcwdfailedNosuchfileordirectory"
? substr(s,4,8)
%3 = "etcwdfai"

Question: Is there a better way (built-in function?) to get substring in PARI/gp?

Upvotes: 0

Views: 222

Answers (2)

138 Aspen
138 Aspen

Reputation: 173

/* Returns a substring of str starting at s with length n */
ssubstr(str, s = 1, n = 0) = {
    my(vt = Vecsmall(str), ve, vr, vtn = #str, n1);
    if (vtn == 0, return(""));
    if (s < 1 || s > vtn, return(str));
    n1 = vtn - s + 1; if (n == 0, n = n1); if (n > n1, n = n1);
    ve = vector(n, z, z - 1 + s); vr = vecextract(vt, ve); return(Strchr(vr));
}

/* Checks if subStr is a substring of mainStr */
isSubstring(mainStr, subStr) = {
    mainLen = #Vecsmall(mainStr);
    subLen = #Vecsmall(subStr);
    for (startPos = 1, mainLen - subLen + 1,
        if (ssubstr(mainStr, startPos, subLen) == subStr,
            return(1); /* True: subStr found in mainStr */
        )
    );
    return(0); /* False: subStr not found */
}


print(ssubstr("StackOverflow",2,3));
print(ssubstr("StackOverflow",2));
print(isSubstring("StackOverflow", "Stack"));
print(isSubstring("Stack", "StackOverflow"));

Try it online!

Upvotes: 0

K.B.
K.B.

Reputation: 911

Not really. Here's a faster hack (also using less memory)

substr2(s,n,m)=strchr(Vecsmall(s)[n..n+m-1])

Timing this on your example:

? substr2(s,4,8)
%1 = "etcwdfai"
? for(i=1,10^6,substr(s,4,8))
time = 536 ms.
? for(i=1,10^6,substr2(s,4,8))
time = 266 ms.

Upvotes: 2

Related Questions