DEV Community

The easiest problem you cannot solve.

JavaScript Joel on October 08, 2018

Given the following code: const K = a => b => a const cat = 'cat' const dog = 'dog' Calling K like this will output c...
Collapse
 
kspeakman profile image
Kasey Speakman • • Edited

In FP, there is a fairly common operation for this called flip. Here is a solution I tested in Chrome console.

const flip = f => a => b => f(b)(a)
flip(K)(cat)(dog)
// "dog"
Collapse
 
joelnet profile image
JavaScript Joel •

I did not consider this as a possible solution!

GIF of Simon Cowell exclaiming "Brilliant"

Collapse
 
entrptaher profile image
Md Abu Taher • • Edited

There is no restriction to call K, right?

K(K)(cat)(dog)()
K(dog)()

Done! Both of these should output dog.

Update: You can actually put anything you want instead of cat. Or complicate it even more with infinite recursive inputs.

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

Very creative!

Collapse
 
joelnet profile image
JavaScript Joel •

There is no restriction to call K, right?

There is also a solution with a single call to K :)

Collapse
 
theodesp profile image
Theofanis Despoudis •

"cat and dog must appear exactly once."

That violates

K(dog)()
K(K)()(dog)()
K(K(K)()(dog))(K)()

Collapse
 
entrptaher profile image
Md Abu Taher •

I was the first to solve his problem :D
He changed the rules after I posted my solution.
Check the comments.

Collapse
 
joelnet profile image
JavaScript Joel •

I added that rule in afterwards. These solutions were valid at the time he posted, so I'll give him credit for the creativity :)

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

?

Collapse
 
entrptaher profile image
Md Abu Taher •

Brilliant.

Collapse
 
joelnet profile image
JavaScript Joel •

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

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
 
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
 
themindfuldev profile image
Tiago Romero • • Edited

These are less clever yet might be valid solutions:

K('')(cat)+K(dog)()
K()(cat);K(dog)()
Collapse
 
themindfuldev profile image
Tiago Romero •

One more:

K([cat,dog])()[1];
Collapse
 
joelnet profile image
JavaScript Joel •

lol. Clearly I have to get better at writing rules! Technically these qualify!

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
 
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
 
theoutlander profile image
Nick Karnik •

This call makes no sense in reality, but it will yield the desired output:

K.call(1,2)()
Collapse
 
joelnet profile image
JavaScript Joel •

Pretty interesting solution. You are binding the first value to this so that the a gets set as your second argument. Very creative!

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 ;)

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
 
handsomeone profile image
Zhou Qi •

Comma operator:

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

Extra hearts for the comma operator. Kudos!

 
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
 
vonheikemen profile image
Heiker •

I give up. This is still within the rules, right?

K.bind(null, [cat, dog].pop())()()
Collapse
 
joelnet profile image
JavaScript Joel •

lol. not what I was looking for, but I would say it technically meets the rules.

Very creative!

Collapse
 
joelnet profile image
JavaScript Joel •

Awesome work!

You found the clue I left, the K combinator! And it does come from the SKI calculus.

So many interesting solutions!

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?