21
\$\begingroup\$

Introduction:

Inspired by this silly meme video, which states 'COLD BEER', but is slightly too large for the scrolling advertisement board, causing it to display either 'COLD BEE' or 'OLD BEER' instead.

Challenge:

Given a dictionary-list of words, output all ordered pairs of words which can form new words if you'd remove the first letter of the first word in the pair and last letter of the last/second word in the pair.

Or, perhaps a more straight-forward explanation and implementation approach:

  1. Filter the input-list so all words with its first letter removed form a new valid word from the list.
  2. Filter the input-list again so all words with its last letter removed form a new valid word from the list.
  3. Take the cartesian product of these two filtered list, to create a list of all ordered pairs of these words (making sure to not use the same word twice!).

Challenge rules:

  • I/O is flexible.
  • It's possible there are no valid pairs to be made from the input, in which case the result is an empty list.
  • The output pairs should be ordered. So with the example, ["cold","beer"] is valid, but ["beer","cold"] is not (unless eer and col both would have been part of the input-list as well).
  • The input-list won't contain duplicates. But make sure to not use a single word as a pair. E.g. ["beer","bee","eer"] won't result in ["beer","beer"] but [] instead.

General Rules:

  • This is , so the shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code (e.g. TIO or ATO).
  • Also, adding an explanation for your answer is highly recommended.

Test Cases:

Input: ["this", "is", "a", "test", "using", "the", "example", "cold", "beer", "with", "bee", "and", "old"]
Output: [["cold","beer"]]

Input: ["this", "eyes", "his", "eyesight", "eye", "is", "flow", "ear", "low", "earn"]
Output: [["this","eyes"],["this","earn"],["his","eyes"],["his","earn"],["flow","eyes"],["flow","earn"]]

Input: ["cold", "postal", "this", "his", "blow", "beer", "percentage", "old", "inside", "low", "exposed", "insider", "bee", "destiny"]
Output: [["cold","beer"],["cold","insider"],["this","beer"],["this","insider"],["blow","beer"],["blow","insider"]]

Input: ["no", "possible", "result", "here"]
Output: []

Input: ["beer","bee","eer"]
Output: []

asked May 21, 2024 at 14:20
\$\endgroup\$
6
  • 6
    \$\begingroup\$ Why isn't ["his","eyes"] in the second example? I have [["this","eyes"],["this","earn"],["his","eyes"],["his","earn"],["flow","eyes"],["flow","earn"]] for that one. \$\endgroup\$ Commented May 21, 2024 at 14:58
  • 1
    \$\begingroup\$ recommended test case: ["cold","beer","old","bee","hosts","ghost","ghosts"] \$\endgroup\$ Commented May 21, 2024 at 16:25
  • \$\begingroup\$ From the first test case, wouldn't "this" and "is" be correct? They would give "this i" and "his is". Or have I misunderstood? \$\endgroup\$ Commented May 21, 2024 at 23:07
  • 1
    \$\begingroup\$ @Adám Oops, you're completely correct. I've fixed it. \$\endgroup\$ Commented May 21, 2024 at 23:17
  • 1
    \$\begingroup\$ @AaronF i isn't part of the input-list. And from this to is you're also removing two letters instead of just one. \$\endgroup\$ Commented May 21, 2024 at 23:18

15 Answers 15

9
\$\begingroup\$

Python 3, 59 bytes

lambda d:[[i,j]for i in d for j in d-{i}if{i[1:],j[:-1]}<d]

Try it online!

answered May 21, 2024 at 15:12
\$\endgroup\$
6
\$\begingroup\$

Jelly, 11 bytes

œ!2ḊṖƭ€fƑ\Ƈ

Try it online!

Don't love resorting to ƭ for this.

œ!2 Permutations without replacement of 2 elements.
 Ƈ Filter the pairs to those which
 fƑ are unchanged by filtering to the wordlist
 \ after
 Ḋ ƭ€ removing the first character of the first word
 Ṗ and the last character of the second.
answered May 21, 2024 at 16:25
\$\endgroup\$
5
\$\begingroup\$

Haskell, 54 bytes

f w=[[x,y]|x<-w,y<-w,x/=y,elem(tail x)w,elem(init y)w]

Attempt This Online!

answered May 21, 2024 at 17:08
\$\endgroup\$
5
\$\begingroup\$

Charcoal, (削除) 34 (削除ここまで) 32 bytes

WS⊞υιFυEΦυ¬∨=ικ−⟦Φιν✂κ0±1⟧υ++ι κ

Try it online! Link is to verbose version of code. Explanation:

WS⊞υι

Input the words.

Loop over all of the words.

EΦυ¬∨=ικ−⟦Φιν✂κ0±1⟧υ++ι κ

Loop over all of the words except where both words are the same or either the suffix of the first word or the prefix of the second word are not present in the list.

answered May 21, 2024 at 15:20
\$\endgroup\$
5
\$\begingroup\$

R, (削除) 76 (削除ここまで) 69 bytes

Edit: -1 byte thanks to @int 21h -- Glory to Ukraine --.

\(W,`?`=\(i)W[sub(i,"",W)%in%W],x=merge(?"^.",?".$"))x[x[,1]!=x[,2],]

Attempt This Online!

The final filtering condition looks ugly to me, but I can't think of anything shorter.

answered May 22, 2024 at 11:48
\$\endgroup\$
2
  • 1
    \$\begingroup\$ -1 byte by replacing substr withsub+regex \$\endgroup\$ Commented Jun 4, 2024 at 13:22
  • 1
    \$\begingroup\$ @int21h--GlorytoUkraine-- nice idea, thanks! \$\endgroup\$ Commented Jun 4, 2024 at 13:30
4
\$\begingroup\$

Arturo, 55 bytes

$->_[permutate.by:2_|select'p->_⊃@[drop p0円chop p1円]]

Requires modern Arturo, hence the online playground won't run this yet. Here's a screenshot of running this locally:

enter image description here

Explanation

$->_[...] ; a function taking an arg named _
permutate.by:2_ ; get permutations of length two
| ; then...
select'p-> ; select pairs p where...
_⊃ ; the input is a superset of...
@[...] ; a list with...
drop p0円 ; first word in pair w/o first letter
chop p1円 ; second word in pair w/o last letter
lyxal
35.6k2 gold badges69 silver badges148 bronze badges
answered May 22, 2024 at 11:03
\$\endgroup\$
4
\$\begingroup\$

Brachylog, 15 bytes

{⊇Ċp.bhkt∈v?∧}f

Try it online!

Explanation

{ }f Find all:
 ⊇Ċ Take a couple of 2 words [a, b] from the input
 Ċp. Output is either [a, b] or [b, a]
 .bhkt Remove the first letter of a and the last letter of b
 (or vice-versa if the output is [b, a])
 ∈v?∧ Verify that these 2 new words are in the original input
answered May 23, 2024 at 8:53
\$\endgroup\$
3
\$\begingroup\$

Ruby, 58 bytes

->w{w.permutation(2).select{|a,b|[a[1..-1],b.chop]-w==[]}}

Try it online!

answered May 23, 2024 at 5:38
\$\endgroup\$
2
\$\begingroup\$

Perl 5 -a, 84 bytes

$"=',';map{/(.(.*)),((.*).)/;say if1ドルne3ドル&&(grep2ドルeq$_,@F)*grep4ドルeq$_,@F}<{@F},{@F}>

Try it online!

answered May 21, 2024 at 23:05
\$\endgroup\$
2
\$\begingroup\$

Japt, (削除) 14 (削除ここまで) 12 bytes

I'm stupidly out of practice; I'm sure there's a better way.

ï
f@m ̧øX ̧s1J

Try it

answered May 29, 2024 at 21:05
\$\endgroup\$
2
\$\begingroup\$

Dart, (削除) 206 (削除ここまで) 204 bytes

List<dynamic>f(var l){var x=[];for(var i=0;i<l.length;i++)for(var j=0;j<l.length;j++)if(l[i]!=l[j]&&l.contains(l[i].substring(1))&&l.contains(l[j].substring(0,l[j].length-1)))x.add([l[i],l[j]]);return x;}

Goes through all pairs of words, checks whether they're a valid pair, returns the answer as a list of pairs.

Previous (thanks Kevin for -2 bytes):

List<dynamic>f(var l){var x=[];for(var i=0;i<l.length;i++)for(var j=0;j<l.length;j++)if(l[i]!=l[j])if(l.contains(l[i].substring(1))&&l.contains(l[j].substring(0,l[j].length-1)))x.add([l[i],l[j]]);return x;}
answered Jun 4, 2024 at 0:11
\$\endgroup\$
1
  • \$\begingroup\$ The two if-conditions can be combined by changing the second )if( to an additional &&. Also, I do't know Dart too well, but perhaps all && can also become & using bitwise-ANDs? \$\endgroup\$ Commented Jun 4, 2024 at 13:24
1
\$\begingroup\$

JavaScript (Node.js), 77 bytes

f=(x,a)=>x.flatMap(b=>a!=b&x.includes(b.slice(!a,a&&-1))?a?[[a,b]]:f(x,b):[])

Try it online!

-3B from Arnauld

answered May 21, 2024 at 14:26
\$\endgroup\$
1
  • 3
    \$\begingroup\$ a?-1:1/0 could be just a&&-1 \$\endgroup\$ Commented May 21, 2024 at 16:26
1
\$\begingroup\$

F#, 168 bytes

let p(d:string seq)=Seq.allPairs(d|>Seq.where(fun w->Seq.contains(w.Substring 1)d))(d|>Seq.where(fun w->Seq.contains(w.Remove(w.Length-1))d))|>Seq.where(fun(f,l)->f<>l)

Gets the two sets of words, pairs them with Seq.allPairs, and finally removes the duplicates. Had to use some strong typing, otherwise there would be compiler errors.

Try it online!

answered Jun 3, 2024 at 22:14
\$\endgroup\$
1
\$\begingroup\$

jq, 93 bytes

. as $L|def m(f):map(select(f|IN($L[])));[m(.[1:]),m(.[:-1])]|combinations|select(.[0]!=.[1])

Attempt This Online!

. as $L | # Bind the full list to $L
def m(f): # Function m selects all elements which are in
 map(select(f | IN($L[]))); # the list after applying the given filter
[m(.[1:]), m(.[:-1])] # Generate lists of possible first and second words
| combinations # Take the Cartesian product of the two lists
| select(.[0] != .[1]) # Filter out any ["foo","foo"] cases
answered Jun 5, 2024 at 15:45
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 12 bytes

ãʒÙ` ̈s¦‚åJT-

Try it online or verify all test cases.

Explanation:

ã # Cartesian product to create all possible pairs of the (implicit) input-list
 ʒ # Filter it by:
 # For valid pairs:
 Ù # Uniquify, which is a no-op for valid pairs
 ` # Pop and push both words separately to the stack
 ̈ # Remove the last letter from the top word
 s # Swap so the first word is at the top
 ¦ # Remove the first letter of this word
 ‚ # Pair the two strings together
 å # Check for both strings whether they're in the (implicit) input-list
 J # Join this pair of checks together
 T- # Subtract 10
 # (only 1 is truthy in 05AB1E)
 # For pairs using the same word twice:
 Ù # Uniquify, so a singleton remains
 ` # Pop and push this word to the stack
 ̈ # Remove the last letter from this word
 s # Swap so the (implicit) input-list is at the top of the stack
 ¦ # Remove the first string from the list
 ‚ # Pair the list together with the word
 å # Check for each inner string whether they're in the (implicit) input-list
 J # Join the inner list of checks together
 T- # Subtract 10 from values in the pair
 # (a pair will always be falsey, since only 1 is truthy in 05AB1E)
 # (after which the list of valid pairs is output implicitly)
answered Oct 4, 2024 at 14:00
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.