19
\$\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
  • String 1: "abcdef", String 2: "acf"
  • 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\$
  • 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
  • 7
    \$\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\$ – pizzapants184 Oct 27 '19 at 20:18

44 Answers 44

1
2
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!

| improve this answer | |
\$\endgroup\$
  • 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\$ – my pronoun is monicareinstate 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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Fails for ["abcdef", "acf"] (should be truthy, but is falsey in your program). \$\endgroup\$ – Kevin Cruijssen Jan 22 at 8:03
1
\$\begingroup\$

Clojure, 39 Bytes

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

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 9 bytes

n/{$.&}/=

Try it online!

Takes input as two newline-separated strings.

Explanation:

n/         Split by newline
  {   }/   For each word
   $.&     Sorted setwise intersection between it and itself
        =  Compare
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is incorrect... it is checking that both strings contain the same set of characters, but should be checking that the set of characters contained in the first string is a superset of that of the second string. (Also doesn't work with UTF-8, but I'm not sure GolfScript can do so?) \$\endgroup\$ – Deadcode Jan 20 at 8:10
1
\$\begingroup\$

Perl 5, 46 bytes

sub{local$_=pop.'␀'.pop;/^((.)(?=.*␀.*\2))*␀/}

Try it online!

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

If side effects and absence of use strict are allowed it becomes 45 bytes:

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

Try it online!

If the side effect of modifying $_ is allowed, it becomes 41 bytes:

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

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 4 bytes

Pretty basic solution, disregarding the existing longer solution. Also, I beat CJam!

~\-!

Try it online!

Explanation

~    # Dump items of list to the stack
 \-  # Swap and find the difference
   ! # Negate the result
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Works for ASCII, but fails with the test case suggested by @pizzapants184 - "πŸ˜€πŸ˜πŸ˜†" "πŸ˜€πŸ˜πŸ˜†πŸ€€" - is it possible to make this answer work for UTF-8? \$\endgroup\$ – Deadcode Jan 20 at 7:58
  • \$\begingroup\$ I'm not sure whether GolfScript could do so. \$\endgroup\$ – user85052 Jan 20 at 8:19
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
| improve this answer | |
\$\endgroup\$
  • \$\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!

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Welcome to the site! How does this take input? \$\endgroup\$ – Ad Hoc Garf Hunter Jan 23 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\$ – adrian.nastase Jan 23 at 20:36
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!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Scala, 46 bytes

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

Try it online!

| improve this answer | |
\$\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!

| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Java, 90 Bytes

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

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

| improve this answer | |
\$\endgroup\$
0
\$\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!

| improve this answer | |
\$\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.