Given two strings: a string s
and an alphabet a
, implement string projection in the shortest code possible.
String projection returns a string o
that contains the characters in s
that are in a
. The order of the characters in o
must match the order of characters in s
. So if s = "abcd"
and a = "12da34"
, o = "ad"
, since only "ad"
is shared between s
and a
.
You will need to handle when a
is empty (outputs empty string, since no character in s
can match empty string).
Test Cases
"string", "alphabet" => "output"
-------------------------------
"abcd", "12da34" => "ad"
"hello, world!", "aeiou" => "eoo"
"hello, world!", "abcdefghijklmnopqrstuvwxyz" => "helloworld"
"Hello, World!", "abcdefghijklmnopqrstuvwxyz" => "elloorld" (case sensitivity)
"Hello, World!", "abcdef" => "ed"
"Hello, World!", "!,. \n\t" => ", !" (newline, tab)
"172843905", "abc123" => "123"
"fizzbuzz", "" => ""
"fizzbuzz", "fizzbuzz" => "fizzbuzz"
"", "fizzbuzz" => ""
"fizzbuzz", "zzzzz" => "zzzz"
"", "" => "" (two empty strings)
Winning Criteria
This is code-golf, so shortest code wins!
47 Answers 47
Haskell + hgl, 5 bytes
fl<fe
Pretty straight forward. fl
filters fe
checks if something is an element. Ends up being the same as the vanilla Haskell answer.
Reflection
This is a very simple task so there's not a lot to be said but:
- I'm not sure why
e
was given the shorter name thanfe
.fe
is almost certainly the more useful of the two and probably they should be swapped. - Since this is such a simple task, hgl should probably follow the lead of the golfing langs and make this a builtin.
- There are a bunch of builtins that are similar to this task like
nx
, but the descriptions were not the clearest.
Scala, 8 bytes
_.filter
This is an expression of type String => Set[Char] => String
. It uses the fact that a Set[T]
is a function T => Boolean
, which is used the predicate here.
brev, 34 bytes
(as-list(c lset-intersection eq?))
Brev imports all of srfi-1 by default. The partial application combinator c applies eq? and then the as-list combinator makes the list operator work on (and return) strings (and other stuff) as if they were lists.
Dart (2.18.4), 55 bytes
f(s,a)=>s.split('').where((e)=>!!a.contains(e)).join();
Go, 104 bytes
import."strings"
func f(s,a string)(o string){for i:=range s{r:=s[i:i+1]
if Contains(a,r){o+=r}}
return}
Japt, (削除) 3 (削除ここまで) 2 bytes
fV
Takes input strings as character arrays
3 bytes w/ strings for input:
oV1
oV1
o : only keep characters in first input and
V : second input
1 : case sensitive
-
1\$\begingroup\$ Welcome to Japt :) \$\endgroup\$Shaggy– Shaggy2022年12月24日 20:03:02 +00:00Commented Dec 24, 2022 at 20:03
-
\$\begingroup\$ You could do this in 2 by taking input as arrays of characters. \$\endgroup\$Shaggy– Shaggy2022年12月24日 20:12:30 +00:00Commented Dec 24, 2022 at 20:12
-
\$\begingroup\$ @Shaggy Thanks, forgot you are allowed to do that lol. This is my first Japt answer I've posted, but I've been messing around with it for a week or two, since I mostly just write JS answers \$\endgroup\$noodle person– noodle person2022年12月26日 00:27:31 +00:00Commented Dec 26, 2022 at 0:27
POSIX Shell + Utilities, 26 bytes
printf %s "1ドル"|tr -cd "2ドル"
Fundamentally, the operation is tr -cd alphabet
, all of 11 bytes on the right side of the pipe; more than half of the space is spent on turning the specified calling convention into data in a file. Unclear if taking the input from the standard input stream is allowed.
The tr alphabet accepts \n
and \t
for line and tab, but the spec does comment that it means a literal one, I think? Either work, but.
Transcript of test cases:
$ cat c.sh; echo; wc -c c.sh
printf %s "1ドル"|tr -cd "2ドル"
26 c.sh
$ ./c.sh "abcd" "12da34"; echo
ad
$ ./c.sh "hello, world!" "aeiou"; echo
eoo
$ ./c.sh "hello, world!" "abcdefghijklmnopqrstuvwxyz"; echo
helloworld
$ ./c.sh "Hello, World!" "abcdefghijklmnopqrstuvwxyz"; echo
elloorld
$ ./c.sh "Hello, World!" "abcdef"; echo
ed
$ ./c.sh "Hello, World!" "!,.
"; echo
, !
$ ./c.sh "172843905" "abc123"; echo
123
$ ./c.sh "fizzbuzz" ""; echo
$ ./c.sh "fizzbuzz" "fizzbuzz"; echo
fizzbuzz
$ ./c.sh "" "fizzbuzz"; echo
$ ./c.sh "fizzbuzz" "zzzzz"; echo
zzzz
$ ./c.sh "" ""
```
Racket, 79 bytes
(define(p s a)(apply string(for/list([c s]#:when(string-contains? a(~a c)))c)))
Explanation
We create a function called p
that receives two inputs s
and a
which are the string to match and the string of what to match respectively. We loop through the characters of s
and see whether each character appears in a
. When a character does appear, we accumulate that character into a list. Once the list is obtained, we convert the characters to a single string.
(define (projection s a)
(apply string
(for/list ([char s] #:when (string-contains? a (~a char)))
char)))
Conclusion
Have an amazing weekend!
J, 5 4 bytes
e.#[
-1 byte thanks to seeing the word "filter" in Jonathan's Jelly answer
Filter by #
element of e.
.
JavaScript (Node.js), 41 bytes
Presently invalid as does not handle alphabets containing -
or ]
. (as pointed out by Deadcode)
s=>a=>s.replace(RegExp(`[^${a}]`,'g'),'')
-
\$\begingroup\$ This fails when given an
a
string containing-
or]
. There's a really neat way around this in Perl, but I don't there is in JavaScript. \$\endgroup\$Deadcode– Deadcode2022年08月08日 02:35:02 +00:00Commented Aug 8, 2022 at 2:35 -
\$\begingroup\$ @Deadcode, Thanks for pointing this out! I don't think there's an easy way around that. If I think of something I'll update the answer. \$\endgroup\$Matthew Jensen– Matthew Jensen2022年08月08日 02:38:21 +00:00Commented Aug 8, 2022 at 2:38
-
\$\begingroup\$ @MatthewJensen you could change
a
toa.replace(/-|]|\\/g,"\\$&")
inside the template literal while you're trying to think of a better solution \$\endgroup\$Samathingamajig– Samathingamajig2022年08月08日 16:02:13 +00:00Commented Aug 8, 2022 at 16:02
awk
24-bytes solution — it's not all that short but it gets the job done*
— *some bugs still exist
echo 'abcd 12da34' |
awk 'gsub("[^"$NF"]",_,$--NF)'
ad
echo 'hello, world!=naeiou' |
awk 'gsub("[^"$NF"]",_,$--NF)' FS== | awk NF=NF FS= OFS='\n' | awk '!__[$_]++' ORS=
- or
awk 'gsub("[^"$!_ "]",_,$NF) gsub("[^"$NF"]",_,$!_)($_=$NF)' FS==
eo
-
\$\begingroup\$ Which code block is your solution? Put that at the top so it's clear that it's your solution. \$\endgroup\$bigyihsuan– bigyihsuan2022年12月25日 18:17:27 +00:00Commented Dec 25, 2022 at 18:17
-
\$\begingroup\$ @bigyihsuan : i don't really have one solution just yet, since those approaches always had minor gaps in the set of test cases, and i'm still trying to come up with an
awk
solution that is all encompassing without using loops, which would be my last resort \$\endgroup\$RARE Kpop Manifesto– RARE Kpop Manifesto2022年12月25日 21:16:41 +00:00Commented Dec 25, 2022 at 21:16
intersection/3
\$\endgroup\$