27
\$\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, 2019 at 21:28
  • \$\begingroup\$ Test cases with repeating letters would also be good. \$\endgroup\$
    – xnor
    Oct 25, 2019 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, 2019 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\$
    – N. Virgo
    Oct 26, 2019 at 19:58
  • 9
    \$\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, 2019 at 20:18

51 Answers 51

1
2
1
\$\begingroup\$

Japt -!, 3 bytes

VkU

Try it

VkU   U = first string, V = second
Vk    Remove all characters in V
  U   that are present in U
-!    If the string is empty, return true, else false
\$\endgroup\$
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, 2019 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\$
    – Luatic
    Oct 28, 2019 at 17:56
  • \$\begingroup\$ I think it doesn't fulfill challenge requirements then: "given two strings". I like the idea tho! \$\endgroup\$ Oct 28, 2019 at 18:02
  • \$\begingroup\$ @val A string essentially is a list of characters. But I could add a solution for strings too. \$\endgroup\$
    – Luatic
    Oct 28, 2019 at 18:03
  • \$\begingroup\$ @val added, at the cost of two additional bytes \$\endgroup\$
    – Luatic
    Oct 28, 2019 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, 2019 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, 2020 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, 2019 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\$
    – Wheat Wizard
    Jan 23, 2020 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, 2020 at 20:36
1
\$\begingroup\$

Wolfram Language (Mathematica), 7 bytes

SubsetQ

Try it online!

SubsetQ does not account for multiplicity.

\$\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, 2021 at 1:25
1
\$\begingroup\$

Vyxal, 2 bytes

Try it online or verify all test cases.

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

Perl 5, 46 41 39 bytes

-2 bytes thanks to dingledooper

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 48 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  [email protected].
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\$
0
\$\begingroup\$

Factor + math.unicode, 3 bytes

Try it online!

An alias for superset?.

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

Thunno 2 !, 1 byte

Try it online!

Explanation

   # Implicit input
ṗ  # Set difference
   # Logical NOT
   # Implicit output
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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