DEV Community

JavaScript Joel
JavaScript Joel

Posted on

The easiest problem you cannot solve.

Given the following code:

const K = a => b => a
const cat = 'cat'
const dog = 'dog'
Enter fullscreen mode Exit fullscreen mode

Calling K like this will output cat

K(cat)(dog)
//=> "cat"
Enter fullscreen mode Exit fullscreen mode

How can you call K to output dog without swapping the order of cat and dog?

cat and dog must appear exactly once.

The Given cannot be modified.

// INVALID: Cannot swap order!
K(dog)(cat)

// NO CHEATING: May only appear once.
K.bind(null, dog)(cat)(dog)
Enter fullscreen mode Exit fullscreen mode

I know of two ways to solve this problem. Surprise me with another!

I should have also specified no bind, call, or apply, but the solutions are just too interesting :)

Hints: K in the problem is the K combinator, part of the SKI combinator calculus.

Spoilers are in the comments! BEWARE!

Many great solutions have been posted below! A lot I never considered. Also some very creative loopholes around the rules I created ;)

Here's one solution that went undiscovered. It's base64 encoded to hide the "spoiler". But if you are curious you can decode it using your console's atob function.

Syh4PT54KShjYXQpKGRvZyk=
Enter fullscreen mode Exit fullscreen mode

Cheers!

Latest comments (40)

Collapse
 
jrista profile image
Jon

Well, I looked up SKI combinators. If I am understanding it correctly, and if I've implemented S correctly here...I think the following would work:

const S = x => y => z => x(z)(y(z));
S(K)(K(cat))(dog); 

I am going to have to add "Learn SKI Combinators" to my list of things to do. :D

Collapse
 
joelnet profile image
JavaScript Joel

After you research SKI Combinators, look into Church Encoding.

Collapse
 
jochemstoel profile image
Jochem Stoel

Hey Joel, I enjoy your articles and I think you deliver a good contribution overall to this website but I would like to see you use better use cases in your examples than cats and dogs meowing. Not for me but for others less experienced. :)

Collapse
 
joelnet profile image
JavaScript Joel

But cats and dogs are the best ;)

 
joelnet profile image
JavaScript Joel • Edited

Exactly! That is definitely the I combinator. It works beautifuly with the K combinator in the problem to solve this problem.

Two parts of SKI combinator calculus!

Collapse
 
joelnet profile image
JavaScript Joel • Edited
eval(K.toString().replace('b', 'a'))(cat)(dog)

This one is pretty creative. Modifying the original K function to swap a and b. I like it.

Collapse
 
en0 profile image
Ian Laird • Edited

I didn't see this one in the comments

K(cat && dog)();
K()(cat)||dog;

And arrays are fun

K.call(null, [cat, dog].reverse()[0])();
K.apply(null, [cat, dog].reverse())();
K([ ...cat, ...dog].slice(3).join(""))();

Technically i think this follows the rules.

K({ cat: dog })()

And if the does then this should work too

K(`${cat} ${dog}`)()
Collapse
 
joelnet profile image
JavaScript Joel

Beautiful!

Collapse
 
metalbrain28 profile image
metalbrain28

Well...

K((function *() { yield(arguments); }))(cat)(dog).next().value[0];
Collapse
 
joelnet profile image
JavaScript Joel

Generators and iterators. quite a unique solution. I love it!

Collapse
 
kip13 profile image
kip • Edited
> K.call(null, (cat, dog))()
'dog'

> K.apply(null, [cat, dog].reverse())()
'dog'
> (cat, K(dog))()
'dog'
> K(((...args) => args[1])(cat, dog))()
'dog'
Collapse
 
joelnet profile image
JavaScript Joel

Congratulations

So many unique solutions. Fantastic!

Collapse
 
ajnasz profile image
Lajos Koszti
K(cat && dog)()

?

Collapse
 
joelnet profile image
JavaScript Joel

Technically within the rules and as valid as any other solution!

Collapse
 
entrptaher profile image
Md Abu Taher

Brilliant.

Collapse
 
motss profile image
Rong Sen Ng

Do you really need the second dog since you already .bind?

Collapse
 
joelnet profile image
JavaScript Joel

Maybe I do not understand, what is the second dog?

Collapse
 
handsomeone profile image
Zhou Qi

Comma operator:

K((cat, dog))()
Collapse
 
joelnet profile image
JavaScript Joel

Extra hearts for the comma operator. Kudos!