My [sub] strings are hiding!

21

Introduction

A while ago a lost SO user posted a question here and its now been deleted but I think it would make a good challenge so here it goes...

Challenge

Write a full program or function that takes two strings and checks whether any permutation of the first string is a sub-string of the second string.

Input

Two strings, a string and a sub-string to test for (you may choose the order).

Output:

A truthy value if the string contains any permutation of the sub-string.
A falsey value if the string does not contain any permutations of the the sub-string.
The test is case sensitive.

Examples/Test cases

         sub-string    string          
input    d!rl          Hello World!
output   truthy

input    Pog           Programming Puzzles & Code Golf
output   falsey

input    ghjuyt        asdfhytgju1234
output   truthy

Notts90 supports Monica

Posted 2017-05-26T11:51:03.487

Reputation: 1 211

Must the truthy and falsey value be consistent or just appropriately truthy or falsey? – Erik the Outgolfer – 2017-05-26T13:17:27.423

@EriktheOutgolfer just appropriate is fine. – Notts90 supports Monica – 2017-05-26T15:04:08.933

Answers

14

Brachylog, 2 bytes

sp

Try it online!

Explanation

Input variable = "Hello World!", Output variable = "d!rl"

(?)s        Take a substring of the Input variable
    p(.)    It is a permutation of the Output variable

Fatalize

Posted 2017-05-26T11:51:03.487

Reputation: 32 976

4Right tool for the job. – isaacg – 2017-05-27T08:52:30.753

7

JavaScript (ES6), 77 bytes

(s,t)=>t&&[...t.slice(0,s.length)].sort()+''==[...s].sort()|f(s,t.slice(1))

Returns 1 or 0.

Snippet

f=

(s,t)=>t&&[...t.slice(0,s.length)].sort()+''==[...s].sort()|f(s,t.slice(1))

console.log(f('d!rl','Hello World!'))                   //1
console.log(f('Pog','Programming Puzzles & Code Golf')) //0
console.log(f('ghjuyt','asdfhytgju1234'))               //1

Rick Hitchcock

Posted 2017-05-26T11:51:03.487

Reputation: 2 461

2This is much faster than the versions that use permutations. – David Conrad – 2017-05-26T17:20:57.453

6

05AB1E, 3 bytes

όZ

Try it online!

-1 byte thanks to Emigna.

Explanation:

όZ 2 inputs
œ                  permutations of the first input
 å  Is each of the                                 in the second input?
  Z Take the maximum of the resulting boolean list

Erik the Outgolfer

Posted 2017-05-26T11:51:03.487

Reputation: 38 134

I don't think you need . – Emigna – 2017-05-26T12:02:19.543

Not sure if it's my phone but TIO seems broken, says language not found. – Notts90 supports Monica – 2017-05-26T12:03:44.330

@Notts90 It's TIO v2 not TIO Nexus, try to clear your cache. It works for me. – Erik the Outgolfer – 2017-05-26T12:04:11.907

@Emigna Apparently "vectorized" means the second argument not the first... – Erik the Outgolfer – 2017-05-26T12:05:19.017

2

If only you'd put the crossed out 4

– Neil A. – 2017-05-26T14:42:31.640

@NeilA. The crossed out 4 doesn't appear as a regular 4 at least for me. – Erik the Outgolfer – 2017-05-26T15:16:17.813

6

Python 2, 67 66 bytes

Takes input as two strings, substring first.

a=sorted
lambda s,S:a(s)in[a(S[n:n+len(s)])for n in range(len(S))]

TFeld

Posted 2017-05-26T11:51:03.487

Reputation: 19 246

1Save a byte by naming sorted. – Jonathan Allan – 2017-05-26T12:56:12.390

5

Jelly, 5 bytes

Œ!ẇ€Ṁ

Try it online!

-1 thanks to Emigna for encouraging me to retry golfing.

Explanation:

Œ!ẇ€Ṁ Main link, dyadic
Œ!               the permutations of the left argument
  ẇ€  Is each of                                      in the right argument?
    Ṁ Maximum of boolean values 

Erik the Outgolfer

Posted 2017-05-26T11:51:03.487

Reputation: 38 134

5

Japt, 10 7 bytes

á d!èV

Try it online


Explanation

á d@VèX  
         :Implicit input of (sub)string U
á        :Create an array of all possible permutations of U
  d      :Map over the array, checking if any element returns true for...
   @     :the function that checks..
     è   :the number of matches...
      X  :of current element (permutation) X...
    V    :in main string V.
         :(0 is falsey, anything else is truthy)
         :Implicit output of result

Shaggy

Posted 2017-05-26T11:51:03.487

Reputation: 24 623

5

Java 8, 266 244 bytes

import java.util.*;Set l=new HashSet();s->p->{p("",p);for(Object x:l)if(s.contains(x+""))return 1>0;return 0>1;}void p(String p,String q){int n=q.length(),i=0;if(n<1)l.add(p);else for(;i<n;)p(p+q.charAt(i),q.substring(0,i)+q.substring(++i,n));}

Explanation:

Try it here.

java.util.*;                   // Required import for Set and HashSet

Set l=new HashSet();           // Class-level Set

s->p->{                        // Method (1) with two String parameters and boolean return-type
  p("",p);                     //  Put all permutations in the class-level Set
  for(Object x:l)              //  Loop over the permutations:
    if(s.contains(x+""))       //   If the input String contains one of the permutations:
      return 1>0;//true        //    Return true
                               //  End of loop (implicit / single-line body)
  return 0>1;//false           //  Return false
}                              // End of method (1)

void p(String p,String q){     // Method (2) with two String parameters and no return-type
  int n=q.length(),i=0;        //  Two temp integers
  if(n<1)                      //  If `n` is zero:
    l.add(p);                  //   Add this permutation of the String to the Set
  else                         //  Else:
    for(;i<n;                  //   Loop over `n`
      p(p+q.charAt(i),q.substring(0,i)+q.substring(++i,n))
                               //    Recursive-call with permutation parts
    );                         //   End of loop (no body)
}                              // End of method (2)

Kevin Cruijssen

Posted 2017-05-26T11:51:03.487

Reputation: 67 575

In C# a void lambda is Action<params> instead of Func<params, returnVal>. I assume it would be something similar. – TheLethalCoder – 2017-05-26T13:48:33.297

1@TheLethalCoder You're right. Should use Consumer and accept(...) instead of Function and apply(...) when I want to have a lambda with a parameter and no return-type. I'm currently learning Java 8. :) But since I'll have to change void p(String p,String q), p("",p); and p(p+q.ch...,q.sub...) to p->q->, p.apply("").accept(p); and p.apply(p+q.ch...).accept(q.sub...) it is shorter to use a combination of lambda for the main method, and just a Java 7 void p(String p,String q) method for the recursive-method. – Kevin Cruijssen – 2017-05-26T14:16:00.127

Nice, at least you figured it out – TheLethalCoder – 2017-05-26T14:17:30.480

I used a Function<String, Predicate<String>> in mine. – David Conrad – 2017-05-26T18:58:45.380

4

Python, 60 bytes

An altered form of TFeld's answer - go give some credit!

s=sorted
f=lambda u,t:s(u)==s(t[:len(u)])or t and f(u,t[1:])

Recursive function returning the boolean True (truthy) or an empty string (falsy).

Try it online!

sorts the substring, u, and the same length of the front of the string, t, (using a slice t[:len(u)]) if they are the same then True is returned, otherwise if t is still truthy (not empty) recurses with a dequeued t (using a slice, t[1:]). If t does become empty the and is not executed and this empty t is returned.

Jonathan Allan

Posted 2017-05-26T11:51:03.487

Reputation: 67 804

You can also have lambda as parameter : lambda u,t,s=sorted: for an one-liner, no byte saved though – Rod – 2017-05-26T14:02:50.460

@cat the assignment is required since the function is recursive. – Jonathan Allan – 2017-05-28T14:50:14.480

4

Pyth, 9 8 bytes

sm}dQ.pE

-1 byte thanks to @Erik_the_Outgolfer

Takes two quoted strings, the second of which is the substring.

Try it!

KarlKastor

Posted 2017-05-26T11:51:03.487

Reputation: 2 352

OP said that it can be just truthy/falsey, not necessarily consistent, so you can use s instead of }1. – Erik the Outgolfer – 2017-05-26T15:17:47.040

3

CJam, 13 12 bytes

le!lf{\#)}:+

Try it online!

I feel like CJam is really limited compared to other golfing languages, but maybe it's just me being bad...

I'm thinking about moving to another. 05AB1E seems fun.

Fixed small bug thanks to Erik the Outgolfer
Cut one bite because non-zero numbers are truthy

Explanation:

l                 Read substring
 e!               Generate all permutations
   l              Read string
    f{            For each permutation
      \#            Check if it is in the string (returns -1 if not found)
        )           Add one
         }        End for
          :+      Sum the whole found/not found array

FrodCube

Posted 2017-05-26T11:51:03.487

Reputation: 539

I think this is invalid, what about inputs a and abc? – Erik the Outgolfer – 2017-05-26T13:34:56.233

@EriktheOutgolfer You are right. It should be a >=0 instead of >0 – FrodCube – 2017-05-26T13:37:28.393

1But you can do W>. – Erik the Outgolfer – 2017-05-26T13:38:33.977

@EriktheOutgolfer would le!lf{\#)}:+ be considered a valid solution? It should output 0 if the string is not found and some positive number otherwise. Is a non-zero number a valid truthy? – FrodCube – 2017-05-26T13:44:47.303

You can use ) instead of W>, per OP's clarification. – Erik the Outgolfer – 2017-05-26T15:19:02.343

3

Mathematica, 55 50 bytes

-5 bytes from user202729

StringFreeQ[#2,""<>#&/@Permutations@Characters@#]&

Returns False if a permutation of the first input is in the second string. Returns True if a permutation of the first input is not in the second string.

Explanation:

                                    Characters@#   - split first string into array of characters
                       Permutations@               - make all permutations
               ""<>#&/@                            - join each array of characters together to form a single string
StringFreeQ[#2,                                 ]& - Check if any of these string is in the second input string

Ian Miller

Posted 2017-05-26T11:51:03.487

Reputation: 727

The output only needs to be "truthy/falsey" not literal True/False. – Ian Miller – 2017-05-27T08:24:13.747

Thanks for reminder about Characters. – Ian Miller – 2017-05-27T08:24:29.857

3

Java 9 JShell, 160 bytes

p->q->IntStream.range(0,q.length()-p.length()+1).anyMatch(
    i->Arrays.equals(
        q.substring(i,i+p.length()).chars().sorted().toArray(),
        p.chars().sorted().toArray()))

(newlines inserted for readability)

Try it online!

Note: JShell includes a number of imports by default. As a Java 8 or Java 9 solution, it would be necessary to import:

import java.util.*;import java.util.stream.*;

For an extra 45 bytes, or 205 bytes total. The TIO link above is to a Java 9 program since TIO doesn't currently have JShell (and it's not clear to me how JShell would work on TIO).

David Conrad

Posted 2017-05-26T11:51:03.487

Reputation: 1 037

Java 9 is a thing now? :| – CalculatorFeline – 2017-05-27T17:58:38.330

@CalculatorFeline The early access builds have been available for quite some time, but the official release date is 2017-07-27.

– David Conrad – 2017-05-28T00:21:28.927

2

C#, 320 bytes

using System.Linq;s=>u=>p(u.ToArray(),0,u.Length-1).Any(p=>s.Contains(p));w=(c,a,b)=>{if (a!=b)(var t=c[a];c[a]=c[b];c[b]=t;)};System.Collections.Generic.IEnumerable<string>p(char[]l,int k,int m){if(k==m)yield return new string(l);else for(int i=k;i<=m;){w(l,k,i);foreach(var c in p(l,k+1,m))yield return c;w(l,k,i++);}}

I'm sure calculating the permutations can be a lot shorter but I can't see how at the moment.

Formatted/Full version:

void test()
{
    Func<string, Func<string, bool>> f = s => u =>
        p(u.ToArray(), 0, u.Length - 1).Any(p => s.Contains(p));

    Console.WriteLine(f("Hello World!")("d!rl"));
    Console.WriteLine(f("Programming Puzzles & Code Golf")("Pog"));
    Console.WriteLine(f("asdfhytgju1234")("ghjuyt"));
}

System.Collections.Generic.IEnumerable<string>p(char[] l, int k, int m)
{
    Action<char[], int, int> w = (c, a, b) =>
    {
        if (a != b)
        {
            var t = c[a];
            c[a] = c[b];
            c[b] = t;
        }
    };

    if (k == m)
        yield return new string(l);

    else
        for (int i = k; i <= m;)
        {
            w(l, k, i);

            foreach (var c in p(l, k + 1, m))
                yield return c;

            w(l, k, i++);
        }
}

TheLethalCoder

Posted 2017-05-26T11:51:03.487

Reputation: 6 930

yeah, unfortunately using linq often makes things longer than simple for(..){} – Ewan – 2017-05-27T11:09:58.043

2

Ruby, 69 bytes

->a,b{r=nil;a.chars.each_cons(b.size){|q|r||=q.sort==b.chars.sort};r}

Try it online!

Alex

Posted 2017-05-26T11:51:03.487

Reputation: 371

2

Perl 6, 48 bytes

{$^a.contains(any $^b.comb.permutations».join)}

Returns an or-junction of each permutation's presence as a substring. For example, with arguments "Hello World!" and "d!l", returns:

any(False, False, False, False, True, False)

...which "collapses" to True in a boolean context. That is, junctions are truthy values.

Sean

Posted 2017-05-26T11:51:03.487

Reputation: 4 136

2

PHP>=7.1, 91 Bytes

for([,$x,$y]=$argv;~$p=substr($y,$i++,strlen($x));)$t|=($c=count_chars)($x)==$c($p);echo$t;

Testcases

Jörg Hülsermann

Posted 2017-05-26T11:51:03.487

Reputation: 13 026

1Try ~$p instead of a&$p. – Titus – 2017-05-27T07:50:42.030

When I try to run your code using the link it says unexpected , – Notts90 supports Monica – 2017-05-27T07:58:25.810

@Notts90 Please use a PHP Version over 7.1 – Jörg Hülsermann – 2017-05-27T09:10:39.367

@JörgHülsermann that works, it had defaulted to 7.0.3 – Notts90 supports Monica – 2017-05-27T09:12:25.720

1

Haskell, 54 bytes

import Data.List
s#t=any(`isInfixOf`s)$permutations t

Using the power of Data.List for both isInfixOf as well as permutations.

maple_shaft

Posted 2017-05-26T11:51:03.487

Reputation: 421

1

R, 103 bytes

function(w,x,y=u(w),z=u(x)){for(i in 1:n(w)){F=F|!sum(setdiff(y[1:n(x)+i-1],z))};F}
u=utf8ToInt
n=nchar

Try it online!

Returns TRUE for truthy and NA for falsey.

ngm

Posted 2017-05-26T11:51:03.487

Reputation: 3 974

0

APL (Dyalog), 18 bytes

{∨/(∧/⍺∊⊢)¨⍵,/⍨⍴⍺}

Try it online!

user41805

Posted 2017-05-26T11:51:03.487

Reputation: 16 320

0

MATL, 10 bytes

Y@Z{w&Xfma

Try it on MATL Online

sundar - Reinstate Monica

Posted 2017-05-26T11:51:03.487

Reputation: 5 296