23
\$\begingroup\$

Introduction

Every string has an "alphabet", composed of the characters that make it up. For example, the alphabet of \$abcaabbcc\$ is \${a, b,c}\$. There are two operations you can do with alphabets: getting the alphabet of a string, and seeing if another string has a given alphabet.

Challenge

Given two strings, you must write a function that finds the alphabet of the first string, and returns a truthy or falsy value based on whether that alphabet makes up the second string, ie. if the alphabet of the first string is the same as that of the second. However, the function should also return a truthy value if the alphabet of the first string is a superset of, or contains, the alphabet of the second.

  • The two strings will be of variable length. They might be empty. If they are, their alphabets are considered and empty list/set. Any valid unicode string could be an input.
  • The function must return a truthy or falsy value. Any type of output is OK, as long as, when converted to a boolean in your language (or the equivalent), it is true.

Examples

  • String 1: "abcdef", String 2: "defbca"
    Output: truthy
  • String 1: "abc", String 2: "abc123"
    Output: falsy
  • String 1: "", String 2: ""
    Output: truthy
  • String 1: "def", String 2: "abcdef"
    Output falsy
  • String 1: "abcdef", String 2: "abc"
    Output truthy
  • String 1: "πŸ˜€πŸ˜πŸ˜†", String 2: "πŸ˜πŸ˜†πŸ˜€"
  • Output: truthy

Rules

This is , so shortest answer in bytes wins!

The Catalogue

The Stack Snippet at the bottom of this post generates the catalogue from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](https://esolangs.org/wiki/Fish), 121 bytes

/* Configuration */

var QUESTION_ID = 194869; // Obtain this from the url
// It will be like https://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 8478; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    else console.log(body);
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    lang = jQuery('<a>'+lang+'</a>').text();
    
    languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;
    if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body {
  text-align: left !important;
  display: block !important;
}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 500px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/all.css?v=ffb5d0584c5f">
<div id="language-list">
  <h2>Shortest Solution by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

\$\endgroup\$
11
  • 7
    \$\begingroup\$ Did you mean String 1: "abcdef", String 2: "def" for the last test case? \$\endgroup\$
    – Arnauld
    Oct 25 '19 at 21:28
  • \$\begingroup\$ Test cases with repeating letters would also be good. \$\endgroup\$
    – xnor
    Oct 25 '19 at 21:46
  • 8
    \$\begingroup\$ Then, it's basically the same test case as the 2nd one. You should add one where the 1st alphabet is a superset of the 2nd. \$\endgroup\$
    – Arnauld
    Oct 25 '19 at 22:10
  • 3
    \$\begingroup\$ "Any valid unicode string could be an input." <-- if unicode support is mandatory, you should include some unicode test cases. (I have a feeling some existing answers will fail them.) \$\endgroup\$
    – Nathaniel
    Oct 26 '19 at 19:58
  • 8
    \$\begingroup\$ Recommended test case: {"πŸ˜€πŸ˜πŸ˜†", "πŸ˜€πŸ˜πŸ˜†πŸ€€", falsey} (Explanation: πŸ˜€ is F0 98 9F 80 in UTF-8, πŸ€€ is F0 9F 80 80 in UTF-8; If an answer is checking the UTF-8 bytes instead of characters, it will return truthy) \$\endgroup\$ Oct 27 '19 at 20:18

48 Answers 48

1
2
1
\$\begingroup\$

R, 40 bytes

function(x,y,`+`=utf8ToInt)all(+y%in%+x)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Perl 6, 17 bytes

!(*Rβˆ–*)o**.comb

Try it online!

Also known as Raku. Anonymous code object taking two arguments and returning a boolean.

Explanation:

       **.comb   # Map each string to a list of characters
      o          # Then return if
  *Rβˆ–*           # The second argument set minus the first
!(    )          # Is empty?

\$\endgroup\$
1
\$\begingroup\$

Lua, 114 bytes

d=function(a,c,v)for _,k in ipairs(a) do c[k]=v end end
function l(a,b)c={};d(b,c,1);d(a,c);return not next(c) end

Try it online!

Couldn't get it shorter with plain Lua because lightweight Lua knows few builtins. If it needs to work with strings:

Lua, 116 bytes

function d(a,c,v)for _,k in a:gmatch"." do c[k]=v end end
function l(a,b)c={};d(b,c,1);d(a,c);return not next(c) end

Try it online!

\$\endgroup\$
6
  • \$\begingroup\$ I think you can't use ipairs on strings? \$\endgroup\$ Oct 28 '19 at 12:01
  • \$\begingroup\$ @val I can't. I expect the input to be a list/table with the characters. Else it would be around ~20 bytes longer I assume. \$\endgroup\$
    – LMD
    Oct 28 '19 at 17:56
  • \$\begingroup\$ I think it doesn't fulfill challenge requirements then: "given two strings". I like the idea tho! \$\endgroup\$ Oct 28 '19 at 18:02
  • \$\begingroup\$ @val A string essentially is a list of characters. But I could add a solution for strings too. \$\endgroup\$
    – LMD
    Oct 28 '19 at 18:03
  • \$\begingroup\$ @val added, at the cost of two additional bytes \$\endgroup\$
    – LMD
    Oct 28 '19 at 18:07
1
\$\begingroup\$

Julia 1.0, 19 bytes

x\y=all(c->c∈x,y)

Try it online!

Thought I beat python till I saw xnor's answer! Uses a generator to check if every character in y exists in (∈) x. Explanation: pass an anonymous function that checks if c is in x as the predicate to all, check that it returns true for all values in y.

Previous 22 byte solution: x\y=all(c∈x for c=y)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C# (.NET Core), 52 bytes 46 bytes 53 bytes

static bool f(string a, string b)=>b.All(a.Contains);

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Why not b.All(a.Contains)? Note that you have to write a function or a full program, not a snippet. Most of the time, C# answers use anonymous functions. In this case a valid answer would be a=>b=>b.All(a.Contains) (of type Func<string, Func<string, bool>>, a function that returns a function that returns the result) \$\endgroup\$ Nov 3 '19 at 5:14
1
\$\begingroup\$

05AB1E, 4 bytes

€Γͺ`Γ₯

Try it online! or verify all test cases

Explanation

€Γͺ    Remove duplicates and sort each input
  `   Dump alphabets to the stack
   Γ₯  Check if the 2nd alphabet is contained in the 1st one
\$\endgroup\$
1
  • \$\begingroup\$ Fails for ["abcdef", "acf"] (should be truthy, but is falsey in your program). \$\endgroup\$ Jan 22 '20 at 8:03
1
\$\begingroup\$

Clojure, 39 Bytes

(fn[a b](every? #(contains?(set a)%)b))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Keg, 13 7 5 4 3 bytes

-β‘«=

-1 byte due to the new β‘« operator that pushes an empty string

Answer History

4 bytes

-``=

Try it online!

-1 byte with trailing newline

And y'all thought W could beat Keg!

This one's a bit of a stretch, as it uses a footer and header to define a function. I'll explain later.

Answer History

7 bytes (SBCS)

α €α €^-``=

Try it online!

-6 bytes due to the fact I realised I could just compare the result to an empty string.

Explained

α €α €^-``=
α €α €      #Take the two input strings
  ^     #Reverse stack to place strings in correct input order
   -    #Subtract the first string from the second
    ``= #Compare the result to an empty string, pushing either 1 or 0

13 bytes (SBCS)

α €α €^-Γ·!&ΓΈ&[0|1

Try it online!

Uses features from Keg, Reg and Keg+!

Explained

α €α €^-Γ·!&ΓΈ&[0|1
α €α €              #Take the two strings as input
  ^             #Reverse the stack so that string subtraction works
   -Γ·           #Subtract first input from second and item split the result
     !          #Push the length of this splitted string
      &ΓΈ&       #Safely store this length in the register while clearing the stack
         [0|1   #Push 0 if there are still items otherwise 1 if empty string
\$\endgroup\$
1
  • \$\begingroup\$ You're using a code snippet if you don't include the code defining the function. \$\endgroup\$
    – user85052
    Oct 28 '19 at 12:33
1
\$\begingroup\$

Kotlin, 50 bytes

{s1:String,s2:String->s2.filter{it !in s1}.none()}

Try it online!

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Welcome to the site! How does this take input? \$\endgroup\$
    – Grain Ghost
    Jan 23 '20 at 14:07
  • \$\begingroup\$ @PostRockGarfHunter Thanks for letting me know. I've updated the answer by adding a Try it online! link so that the solution can be tested. I hope it's OK like this, as I've seen this approach used by others. \$\endgroup\$ Jan 23 '20 at 20:36
1
\$\begingroup\$

Wolfram Language (Mathematica), 7 bytes

SubsetQ

Try it online!

SubsetQ does not account for multiplicity.

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 51 bytes

f(a,b)int*a,*b;{return wcschr(a,*b)&&f(a,b+1)|!*b;}

Try it online!

In this 51 bytes version I tweaked a little bit the 53 bytes version (see below, former answer) thanks to && :

  • At each letter *b I check we can find it in string a.
  • If not, it means wcschr(a,*b) equal 0, so the program will not bother to execute the second part &&f(a,b+1) (that allows us to go deeper in the recursive) and so it return 0...
  • ...along with !*b | NOT of pointer b: if we had arrived at the end of b, the pointer is NULL so we return 0|!NULL <=> 0|1 <=> 1. If the pointer is not NULL (which means wcschr(a,*b) previously returned NULL before string a's \0) then we return 0|!PTR <=> 0|0 <=> 0

C (gcc), 53 bytes

f(a,b)int*a,*b;{return*b&&wcschr(a,*b)?f(a,b+1):!*b;}

Try it online!

This is a recursive function

  • wcschr(a,*b) looks for unicode character *b in string a, return NULL character is not found, else pointer to the character (!=NULL).
  • We keep looking if 1/ we are not at the end of string b (*b!=NULL) and 2/ while we keep finding our char *b in string a.
  • If both conditions are true we inspect our next character in string b f(a,b+1)
  • if not we return NOT of the pointer to *b : if we had arrived at the end of b then *b is NULL and our function return true, if not it means that wcschr failed before reaching end of string b.

NB: wcschr is the builtin function equivalent of strchr (man strchr)

#include <wchar.h>
#ifndef WCSCHR
# define WCSCHR __wcschr
#endif
/* Find the first occurrence of WC in WCS.  */
wchar_t *
WCSCHR (const wchar_t *wcs, const wchar_t wc)
{
  do
    if (*wcs == wc)
      return (wchar_t *) wcs;
  while (*wcs++ != L'\0');
  return NULL;
}
libc_hidden_def (__wcschr)
weak_alias (__wcschr, wcschr)
libc_hidden_weak (wcschr)
\$\endgroup\$
1
\$\begingroup\$

Java, 90 Bytes

(String[] a)->a[1].chars().filter(x->!a[0].contains((String.valueOf((char)x)))).count()<1;

Try it online!

Not great, but chars() helps some...

\$\endgroup\$
1
  • \$\begingroup\$ You can save 2 bytes by removing whitespace and the semicolon. \$\endgroup\$
    – Deadcode
    Apr 7 at 1:25
1
\$\begingroup\$

Perl 5, 46 41 bytes

sub{(pop.'␀'.pop)=~/^((.)(?=.*␀.*\2))*␀/}

Try it online!

This uses the ECMAScript / Python / universal regex from my pure regex answer (explained there). The unprintable character NUL (ASCII 0) is used as the delimiter, shown here as ␀.

\$\endgroup\$
1
\$\begingroup\$

Java, 57 49 bytes

(a,b)->(b+'␀'+a).matches("((.)(?=.*␀.*\\2))*␀.*")

Try it online!

This uses the ECMAScript / Python / universal regex from my pure regex answer.

An actual NUL (ASCII 0) character is used as the delimiter for maximum universality. This is inserted directly into the TIO test harness as actual NUL characters, but displayed above using the ␀ glyph for visibility.

\$\endgroup\$
0
\$\begingroup\$

Rust, 106 104 bytes

|a:&str,b:&str|{let c=|x:&str|x.chars().collect::<std::collections::HashSet<_>>();c(b).is_subset(&c(a))}

Try it online!

\$\endgroup\$
0
0
\$\begingroup\$

Scala, 46 bytes

(a:String,b:String)=>(b.toSet&~a.toSet)==Set()

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Prolog (SWI), 92 bytes

e(_,[]).
e(L,[H|T]):-member(H,L),e(L,T).
f(X,Y):-string_chars(X,A),string_chars(Y,B),e(A,B).

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 2.7 .pyc file, 130 bytes

Sorry, bytecode formats are just too much fun to pass up for simpler tasks

Hexdump because there's plenty of nulls :)

00000000: 03f3 0d0a fb0b 8b59 6300 0000 0000 0000  .......Yc.......
00000010: 0004 0000 0040 0000 0073 1a00 0000 7400  .....@...s....t.
00000020: 0074 0100 6302 0083 0000 8301 0003 8300  .t..c...........
00000030: 0083 0100 6b05 0046 2800 0000 0028 0200  ....k..F(....(..
00000040: 0000 7303 0000 0073 6574 7309 0000 0072  ..s....sets....r
00000050: 6177 5f69 6e70 7574 2800 0000 0028 0000  aw_input(....(..
00000060: 0000 2800 0000 0073 0000 0000 7308 0000  ..(....s....s...
00000070: 003c 6d6f 6475 6c65 3e00 0000 0073 0000  .<module>....s..
00000080: 0000                                     ..

Optimizations over the in built compiler:

  • Stack juggling the functions
  • Zero byte filename because it's valid
  • Crashing at the end because why spend a byte exiting cleanly

python-xdis output for the file:

# pydisasm version 4.1.0
# Python bytecode 2.7 (62211)
# Disassembled from Python 2.7.15+ (default, Jul  9 2019, 16:51:35)
# [GCC 7.4.0]
# Timestamp in code: 1502284795 (2017-08-09 13:19:55)
  0:
            LOAD_GLOBAL          (set)
            LOAD_GLOBAL          (raw_input)
            DUP_TOPX             2
            CALL_FUNCTION        0 (0 positional, 0 named)
            CALL_FUNCTION        1 (1 positional, 0 named)
            ROT_THREE
            CALL_FUNCTION        0 (0 positional, 0 named)
            CALL_FUNCTION        1 (1 positional, 0 named)
            COMPARE_OP           (>=)
            PRINT_EXPR

With bytes to make it easier to see where byte saves could be

# pydisasm version 4.1.0
# Python bytecode 2.7 (62211)
# Disassembled from Python 2.7.15+ (default, Jul  9 2019, 16:51:35)
# [GCC 7.4.0]
# Timestamp in code: 1502284795 (2017-08-09 13:19:55)
  0:           0 |74 00 00| LOAD_GLOBAL          (set)
               3 |74 00 01| LOAD_GLOBAL          (raw_input)
               6 |63 00 02| DUP_TOPX                  2
               9 |83 00 00| CALL_FUNCTION        (0 positional, 0 named)
              12 |83 00 01| CALL_FUNCTION        (1 positional, 0 named)
              15 |03      | ROT_THREE
              16 |83 00 00| CALL_FUNCTION        (0 positional, 0 named)
              19 |83 00 01| CALL_FUNCTION        (1 positional, 0 named)
              22 |6b 00 05| COMPARE_OP           (>=)
              25 |46      | PRINT_EXPR
\$\endgroup\$
1
2

Your Answer

By clicking β€œPost Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.