Fabrice's weblog

Tools and Source

News

My .NET Toolbox
An error occured. See the script errors signaled by your web browser.
No tools selected yet
.NET tools by SharpToolbox.com

Read sample chapters or buy LINQ in Action now!
Our LINQ book is also available on AMAZON

.NET jobs

Emplois .NET

Tuneo

ASP.NET Hosting transatlantys

Contact

Me

Others

Selected content

Archives

Using LINQ to solve puzzles

Do you want to see LINQ used for something else than querying a database for customers or for querying an array of dummy strings? After Derek Slager who showed us how he calculates baseball statistics with LINQ, here is another different use of LINQ. Luke Hoban, Program Manager for the C# Compiler, shows how LINQ can be used to solve puzzles.

The diagram below provided by Luke shows a mobile. It consists in a bunch of weights (A-M) hanging from a system of bars. Each weight has an integer value between 1 and 13, and the goal is to figure out what each weight must be for the the diagram below to balance correctly as shown:

                          |
                          |
              +--+--+--+--+--+--+--+
              |                    |
              |                    |
           +--+--+--+--+--+        |
           |     L        M        |
           |                       |
  +--+--+--+--+--+--+     +--+--+--+--+--+
  H              |  I     |  J        K  |
                 |        |              |
        +--+--+--+--+--+  |     +--+--+--+--+--+
        E              F  |     G              |
                          |                    |
              +--+--+--+--+--+  +--+--+--+--+--+--+
              A              B  C                 D

The puzzle can be solved relatively easily using a LINQ query:

var solveForWeights =
  from a in Enumerable.Range(1, 13)
  join b in Enumerable.Range(1, 13) on 4 * a equals b
  from c in Enumerable.Range(1, 13)
  join d in Enumerable.Range(1, 13) on 5 * c equals d
  from e in Enumerable.Range(1, 13)
  join f in Enumerable.Range(1, 13) on 3 * e equals 2 * f
  join g in Enumerable.Range(1, 13) on 2 * (c + d) equals 3 * g
  from h in Enumerable.Range(1, 13)
  join i in Enumerable.Range(1, 13) on 3 * h - 2 * (e + f) equals 3 * i
  from j in Enumerable.Range(1, 13)
  join k in Enumerable.Range(1, 13) on 3 * (a + b) + 2 * j - 2 * (g + c + d) equals k
  from l in Enumerable.Range(1, 13)
  join m in Enumerable.Range(1, 13) on (h + i + e + f) - l equals 4 * m
  where (4 * (l + m + h + i + e + f) == 3 * (j + k + g + a + b + c + d))
  select new { a, b, c, d, e, f, g, h, i, j, k, l, m,
               Total = a + b + c + d + e + f + g + h + i + j + k + l + m };

solveForWeights.ToList().ForEach(result => Console.WriteLine(result));

This is an interesting approach and an innovative use of LINQ! See the details in Luke's post



Cross-posted from http://linqinaction.net

Comments

Ayende Rahien said:

You have a weird definition of "relatively easily".

# March 28, 2007 7:49 PM

Richard LOPES said:

This is crazy !

LINQ is going to be a very big thing ! I wish Java had such great features in the language. C# really gets my preference.

# March 29, 2007 12:51 AM

Fabrice Marguerie said:

Ayende, I used "relatively" on purpose. It all depends on how much you grok LINQ. What I find interesting is the declarative approach it allows.

# March 29, 2007 4:24 AM

commenter said:

Title should be 'how to use LINQ to baffle human beings with less-than-four-figure IQs'.

# March 30, 2007 7:19 AM

Fabrice Marguerie said:

Oh well, ok. Let's stick to Customers and Products then. I just find it fun to see something different.

# March 30, 2007 8:05 AM

commenter said:

No worries - I'm just slightly bitter that this flies way over my head :-)

# March 30, 2007 8:20 AM

Fabrice Marguerie said:

I must admit that this not the kind of code that comes naturally to my mind either. But, hey, it's a puzzle :-)

# March 30, 2007 9:07 AM

FAF said:

Which 1 is puzzle, your code or that tree :P

# April 2, 2007 11:12 AM

Harsh Truth said:

Uneducated Microsoft monkeys, if you knew Prolog, you wouldn't be that baffled.

# July 16, 2007 5:24 PM

Fabrice Marguerie said:

"Uneducated Microsoft monkeys, if you knew Prolog, you wouldn't be that baffled."

I admit it, I'm baffled for not being omniscient.

# July 16, 2007 5:47 PM

chris_allen said:

:-use_module(library(clpfd)).

/*

(SWI) Prolog equivalent - more or less

*/

solveForWeights :-

       Vars = [A,B,C,D,E,F,G,H,I,J,K,L,M],

       Vars ins 1..13

       ,B #= 4 * A

,D #= 5 * C

,3 * E #= 2 * F

,3 * G #= 2 * (C + D)

,3* H - 2 * (E + F) #= 3 * I

,3 * (A + B) + 2 * J - 2 * (G + C + D) #= K

,(H + I + E + F) - L #= 4 * M

,(4 * (L + M + H + I + E + F) #= 3 * (J + K + G + A + B + C + D))

,label(Vars)

,write(Vars)

.

# September 30, 2011 12:00 PM