Slashdot Mirror


Solving the Knight's Tour Puzzle In 60 Lines of Python

ttsiod writes "When I was a kid, I used to play the Knight's Tour puzzle with pen and paper: you simply had to pass once from every square of a chess board, moving like a Knight. Nowadays, I no longer play chess; but somehow I remembered this nice little puzzle and coded a 60-line Python solver that can tackle even 100x100 boards in less than a second. Try beating this, fellow coders!"

70 of 311 comments (clear)

  1. awesome by sofar · · Score: 5, Funny

    too bad that your code will break with the next python version.

    1. Re:awesome by orkybash · · Score: 3, Interesting
    2. Re:awesome by Falstius · · Score: 4, Funny

      Thanks for that link, the new print command makes a lot more sense than the old one.

    3. Re:awesome by earthbound+kid · · Score: 2, Interesting

      Here's code you can put in your Python 2.x code today to future proof it against the change to xrange:

      try:
            range = xrange
      except NameError:
            pass

      After that, just write range in your code and it will automatically use the equivalent of Python 2's xrange. If you're running Python 2.6, you can use a print function (instead of a print keyword) by adding from __future__ import print_function to your header as well, and you're good to go for a large number of Python 3 switching problems.

    4. Re:awesome by mollymoo · · Score: 2, Insightful

      Nah, "for index in range(1, 100):" makes a bloated memory list of 1,2,3,4,5,6,7...99,100 whereas xrange(1,100) is memory-efficient iterator that just returns an incremented value upon each loop.

      A valid concern for large lists and essential knowledge for Python programmers, but for the the 64 element list you need to represent a chess board, who really gives a shit? Just write the clean, future-proof code and let the machine do the hard work. You're trading programmer convenience for machine time by using Python anyway.

      --
      Chernobyl 'not a wildlife haven' - BBC News
  2. Easy by Anonymous Coward · · Score: 5, Funny

    C-x C-m KnightsPuzzle

    1. Re:Easy by RAMMS+EIN · · Score: 5, Informative

      While your humor is appreciated, I feel compelled to point out that it should be

      M-x knights-puzzle

      Lisp doesn't use CamelCase.

      --
      Please correct me if I got my facts wrong.
    2. Re:Easy by Simon+Brooke · · Score: 2, Interesting

      Lisp doesn't use CamelCase.

      Don't show off your ignorance too much. LISP has used CamelCase for at least thirty years. Admittedly neither Scheme nor Common LISP conventionally use it, but InterLISP certainly does.

      --
      I'm old enough to remember when discussions on Slashdot were well informed.
  3. All done. by DeadDecoy · · Score: 3, Interesting

    There. I did it in one line of code.
    #!/usr/bin/env python import sys g_sqSize = -1 # the board size, passed at runtime g_board = [] # the board will be constructed as a list of lists def main(): global g_sqSize if len(sys.argv) != 2: g_sqSize = 8 # Default: Fill the normal 8x8 chess board else: try: g_sqSize = int(sys.argv[1]) # or, the NxN the user wants except: print "Usage: " + sys.argv[0] + " " sys.exit(1) for i in xrange(0, g_sqSize): g_board.append(g_sqSize*[0]) # Fill the board with zeroes Fill(0,0,1) # Start the recursion with a 1 in the upper left print "No solution found" # if the recursion returns, it failed def InRangeAndEmpty(ty,tx): # check if coordinates are within the board return ty>=0 and tx>=0 and ty

    1. Re:All done. by Anonymous Coward · · Score: 5, Funny

      Except you commented out all of the code.

    2. Re:All done. by somenickname · · Score: 5, Funny

      There. I did it in one line of code.

      That doesn't look like perl to me...

    3. Re:All done. by gparent · · Score: 4, Funny

      Woosh.

    4. Re:All done. by Kingrames · · Score: 4, Funny

      From experience, commenting out the code makes it better. :P

      --
      If you can read this, I forgot to post anonymously.
    5. Re:All done. by svank · · Score: 3, Funny

      In my experience, every line commented out makes the program run faster. My programs tend to run instantly if I comment the entire thing! Using a # must invoke an incredible optimization engine! Why don't they use it by default?

  4. What would Michael Knight do? by Anonymous Coward · · Score: 4, Funny

    He'd hop into KITT and go anywhere he damn well pleases.

  5. Nice. And a Mathematica implementation... by gardyloo · · Score: 2, Interesting
  6. Try lisp by FlyingBishop · · Score: 4, Insightful

    Advantages that have nothing to do with libraries, and can be traced back to the combination of (a) functional programming and (b) the perfect syntax that Python offers. I would truly be amazed to see anyone writing the same logic in C++ in anything less than 3 times the lines of code I wrote in Python.

    Though I have better things to do than actually try, looking over the code FTFA, I have to say that I think a transliteration of this code into Scheme or Lisp would actually look cleaner than Python. And I do know that that would deal with the problem the writer ran into, namely that Python has an absurdly low recursion limit.

    I do like Python's syntax (for anything under 100 lines of code) but calling it a model of functional programming is just silly.

    1. Re:Try lisp by maxume · · Score: 2, Interesting

      His code:

          # recurse using our neighbours, trying first the ones with the
          # least amount of free neighbours, i.e. the "loners"
          for ty,tx in sorted(emptyNeighbours, key=lambda c: reduce(
          lambda x,y: x+y,
          map(lambda j: InRangeAndEmpty(c[0]+j[0], c[1]+j[1]) and 1 or 0,
              jumps))):
              Fill(ty,tx,counter+1)

      Idiomatic python(or at least more-so):

          def sort_key(c):
              return sum(InRangeAndEmpty(c[0]+j[0], c[1]+j[1]) for j in jumps)

          # recurse using our neighbours, trying first the ones with the
          # least amount of free neighbours, i.e. the "loners"
          for ty,tx in sorted(emptyNeighbours, key=sort_key):
              Fill(ty,tx,counter+1)

      The nest of lambdas that he wrote the article about isn't the clearest way to write it in python (the reduce( lambda x,y: x+y,...) instead of sum(...) is particularly fun). In my code, wrapping the InRangeAndEmpty in an int() might be preferred, I'm not sure (all that would do is make it clear that the sum is counting the number of squares that are in range and empty).

      --
      Nerd rage is the funniest rage.
    2. Re:Try lisp by BlueCodeWarrior · · Score: 3, Interesting

      I won't pretend to remember Lisp inventor John McCarthy's exact words which is odd because there were only about ten but he simply asked if Python could gracefully manipulate Python code as data. "No, John, it can't," said Peter and nothing more, graciously assenting to the professor's critique, and McCarthy said no more though Peter waited a moment to see if he would and in the silence a thousand words were said.

      http://smuglispweeny.blogspot.com/2008/02/ooh-ooh-my-turn-why-lisp.html

  7. better algo by Coneasfast · · Score: 5, Informative

    Apparently, this isn't NP-complete. There is an algorithm that can solve this in O(n) time, see here: http://mathworld.wolfram.com/KnightsTour.html

    This will save a LOT of time for larger boards. Try to implement this.

    --
    Marge, get me your address book, 4 beers, and my conversation hat.
    1. Re:better algo by eulernet · · Score: 4, Interesting

      The ultimate algorithm is called Warnsdorf's heuristic:
      http://www.delphiforfun.org/programs/knights_tour.htm
      It solves all possible orders (>100x100) in less than a second.

      The algorithm cited in the article is really shitty, because it requires recursion.

      Hint: I implemented an algorithm to enumerate all magic knight tours (magic, like in magic squares):
      http://magictour.free.fr/

    2. Re:better algo by misterpib · · Score: 3, Interesting

      A non-recursive Python version which uses Warnsdorf's heuristic:
      http://github.com/pib/scripts/tree/master/knight.py

      It's faster than the one in TFA as well, though it has no backtracking, so it won't find some solutions once you get bigger than 76x76, but at least it doesn't overflow the stack.

      It also will tell you whether it found an open, closed, or incomplete path.

    3. Re:better algo by seann · · Score: 5, Funny

      Wait a second. What's wrong with recursion?

      --
      I'm a big retard who forgot to log out of Slashdot on Mike's computer! LOOK AT ME.
    4. Re:better algo by DarkOx · · Score: 3, Informative

      Nothing is wrong with it at all. In a traditional compiled language its often the most efficent way to write something and it often gets you the most efficent compiled code and when it does not most compilers will be smart enough to build a loop construct when the go to the assembler stage.

      If you are using an interpreted langague like python or my favoirte Dialect( needs more respect ) then you have to be a little careful with it because these have a "soft stack" that can only get so deep. They have to keep track of how deep they are and where that have been, rather then just a beq and jmp on some register value, so they know what to do next. Mosty interpreters have a fixed stack depth although some manage to abstact this to linked list like structures internally and can keep going until the heap is exhasted. In any case you can't search to big a space recusively or it will fail.

      --
      Repeal the 17th Amendment TODAY! Also Please Read http://www.gnu.org/philosophy/right-to-read.html
    5. Re:better algo by Anonymous+Brave+Guy · · Score: 2, Funny

      I don't know. What's wrong with recursion?

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  8. Re:OK by $RANDOMLUSER · · Score: 3, Funny

    I blow my nose at you, so-called "Arthur King", you and all your silly English K-nigg-its.

    --
    No folly is more costly than the folly of intolerant idealism. - Winston Churchill
  9. 28 lines in Prolog :-) by Anonymous Coward · · Score: 5, Interesting

    wrapper(Size, [X, Y], Path) :-
            X == 1,
            Y == 1,
            Depth is Size * Size - 1,
            worker(Size, [X, Y], Depth, [], ReversedPath),
            reverse(ReversedPath, Path),
            write(Path), nl.
    worker(_, State, 0, CurrentPath, [State|CurrentPath]).
    worker(Size, State, Depth, CurrentPath, FinalPath) :-
            DepthM1 is Depth - 1,
            move_generator(Size, State, NewState),
            not(checker(NewState, CurrentPath)),
            worker(Size, NewState, DepthM1, [State|CurrentPath], FinalPath).
    checker(State, [State|_]).
    checker(State, [_|StateList]) :-
            checker(State, StateList).
    move_generator(Size, [X, Y], [NewX, NewY]) :-
            move(MoveX, MoveY),
            NewX is X + MoveX, NewX == 1,
            NewY is Y + MoveY, NewY == 1.
    move(1, 2).
    move(2, 1).
    move(2, -1).
    move(1, -2).
    move(-1, -2).
    move(-2, -1).
    move(-2, 1).
    move(-1, 2).

    1. Re:28 lines in Prolog :-) by phantomfive · · Score: 5, Insightful
      Yeah, and here's one in Java that does the same thing but with an animated GUI (with only 10 more lines of code!). Thus the claim from the article is a bit much:

      I would truly be amazed to see anyone writing the same logic in C++ in anything less than 3 times the lines of code I wrote in Python. And even if this is somehow possible (using external libraries like BOOST, I'd wager), the code will take longer to write, and it will be far more difficult to comprehend or refactor...

      And I'd wager that this guy has never worked on huge projects. Any chunk of code that is less than a hundred lines is not going to be difficult to refactor; in fact, such a short piece of code probably gets longer and more confusing by adding object oriented structure (notice his code isn't encapsulated into a class or anything). The real advantages of structured programming isn't seen until you have a large project that has constantly changing requirements. That is where flexibility REALLY makes a difference.

      I would also argue that any modern language gives you everything you need to write good, flexible code, and the quality of the code produced is more closely related to the skill of the programmer, than it is to the programming language itself.

      In fact, for myself, it would not be an exaggeration to say I can write more flexible code in assembly now than I could five years ago in any language. Of course, it would be well structured assembly, not the wild mess of code I've written in previous years. YMMV.

      --
      Qxe4
    2. Re:28 lines in Prolog :-) by RedWizzard · · Score: 4, Interesting

      It can be done concisely in functional languages, e.g. Haskell:

      knights :: Int -> [[(Int,Int)]]
      knights n = loop (n*n) [[(1,1)]]
              where loop 1 = map reverse . id
                      loop i = loop (i-1) . concatMap nextMoves

                      nextMoves already@(x:xs) = [next:already | next <- possible]
                              where possible = filter (\x -> on_board x && not (x `elem` already)) $ jumps x

                      jumps (x,y) = [(x+a, y+b) | (a,b) <- [(1,2), (2,1), (2,-1), (1,-2), (-1,-2), (-2,-1), (-2,1), (-1,2)]]
                      on_board (x,y) = (x >= 1) && (x <= n) && (y >= 1) && (y <= n)

      (from http://www.haskell.org/haskellwiki/99_questions/90_to_94).

    3. Re:28 lines in Prolog :-) by IamTheRealMike · · Score: 5, Interesting

      Yeah, that sort of assertion bugs me. My own experience has been the exact opposite - attempting to understand large Python programs that have evolved over a number of years is damn near impossible. I know, I've tried. The terseness of the language and the absolute lack of explicit typing means you can't just open up a random function and understand what's going on. You often have to trace backwards through the code just to discover what it's attempting to do.

      Typically Python programmers try and paper over this problem with tons of doc comments. Problem is that like any comment, they can get out of date, and often aren't useful anyway. If I had a dollar for every time I've seen:

      foo: The foo to bar.

      in a Python doc comment, I'd be a rich guy. What is a foo exactly? A class? A tuple? A list of tuples of classes? Or worse, any of the above?

      In contrast, I've found it very easy to dive right into some of the large C++ code bases we have at work and immediately understand what the code does and how it does it, largely because C++ is more explicit and the (partly redundant) specification of type information means you can rapidly find how different components interact. Redundant comments are kept to a minimum. Comprehension is radically improved.

      This is very useful when attempting to understand error messages, for instance. My absolute worst nightmare troubleshooting wise is running a giant Python script and getting a type error 20 frames deep, because I know it could easily burn an afternoon just untangling the mess. More explicit languages rarely seem to have this problem.

    4. Re:28 lines in Prolog :-) by omuls+are+tasty · · Score: 3, Insightful

      That Java code is only 10 lines longer, but it doesn't include the code for some other classes it uses to solve the problem.

      But anyhow, you're missing his point. The basic backtracking algorithm for the problem is simple in any language, and could indeed be made much shorter in Java (w/o the entire search framework). He's talking about improving the search with a heuristic (in his case, what is known as a "minimum remaining values" search heuristic among the AI folks). But he's still probably wrong, as you'd only need to write a Comparator in Java, or overload the operator< in C++ to achieve the same effect, and my guess is it'd only take you about 2x the Python code for the same functionality.

      But, IMHO, the problem is not so much the increase in code, it's the shift in thinking which you have to undergo to make your code in Java. You just want to sort a bloody list based on a certain criteria, but now you have to make a class, encode your state data in it, and define a comparator function. Basically the brain -> program mapping is most of the time so much more direct in Python (and other similar languages) than the high-level assembly family of C languages that it isn't even funny. I sometimes feel like being put in a straitjacket when I have to write some Java or C++. Don't get me wrong, I definitely agree that a lousy programmer can make a mess in any programming language (I've written my share of bad code) and that a good programmer can write good code in any programming language (save for COBOL), but why torture yourself?

      A good indicator for me is the source code for problems in the AIMA book, check out the different versions and see which ones convey the meaning and ideas more clearly.

    5. Re:28 lines in Prolog :-) by setagllib · · Score: 2, Informative

      I don't know if you're just being ironic, but your Java code isn't even correct with respect to AWT/Swing threading semantics. You're supposed to create Swing objects only in the AWT event loop thread, using EventQueue.runLater() or one of its wrappers. I guess you're using Thread.sleep() later to get around the threading bugs you just created, but since your code is uncommented it's hard to tell.

      --
      Sam ty sig.
    6. Re:28 lines in Prolog :-) by Tack · · Score: 3, Insightful

      in a Python doc comment, I'd be a rich guy. What is a foo exactly? A class? A tuple? A list of tuples of classes? Or worse, any of the above?

      This is certainly one of the practical drawbacks of duck-typing. But name-based polymorphism is exceedingly powerful, and with great power comes great responsibility. (Namely, to document one's arguments and return values properly.)

    7. Re:28 lines in Prolog :-) by vampiro369 · · Score: 2, Insightful

      In contrast, I've found it very easy to dive right into some of the large C++ code bases we have at work and immediately understand what the code does and how it does it, largely because C++ is more explicit and the (partly redundant) specification of type information means you can rapidly find how different components interact. Redundant comments are kept to a minimum. Comprehension is radically improved.

      This is very useful when attempting to understand error messages, for instance. My absolute worst nightmare troubleshooting wise is running a giant Python script and getting a type error 20 frames deep, because I know it could easily burn an afternoon just untangling the mess. More explicit languages rarely seem to have this problem.

      So you're saying C is better than python just because you're better at C?

      I have no problem finding what a function does in python. I can go as far as telling you that it is easier contributing in large projects written in python than contributing in large projects written in C. I'm sure that almost everyone (excluding those impaired by Oppositional Defiant Disorder) will agree that scripting languages have had a huge impact on programming because code is easier to write, easier to maintain, etc. It has everything to do with readibility.

      Perl, PHP, Python, Ruby ... the list goes on and on. Millions have benefited from using these and other languages and yet, you claim you find it harder using python than C? And your best defense on readability is claiming that type specification is of uttermost importance?

      If you find it hard to understand code because you have to open a file and close it and open another and "damn this wasn't it, better close it and grep -R again", USE AN IDE. There are lots out there and they're reaaaally worth it. Some of them even take you the object's definition (file AND line no.) when you double-click on the name!

      C++ has its uses. It would be downright stupid to try and use python for everything. But using C for everything is downright stupid too. My absolute worst nightmare is getting a Segmentation Fault when adding functionality to 15,000+ lines C code. I know, I've tried. And 15,000+ lines of code written a few years ago. Worst. And written by a bad programmer. Worst yet.

      The assumptions here should be quite clear: A bored individual decided to tackle a problem he/she finds interesting. He used previously acquired knowledge only. His programming tool was python. The first try was good but sloppy. The second one ran blazingly fast (compared to the first one) and it was still below the 65-lines mark. Good enough, right? He didn't set out to write a paper on the best Knight's Tour algorithm. He didn't even set out to point out that python was better than any other language! He could tackle the problem in a few hours and present a working solution to a crowd that can read the code, understand it and use it and I think python excels in accomplishing that.

      But I guess you're writing an OS and scripting doesn't suit you...

  10. Perl by Anonymous Coward · · Score: 5, Interesting


    #!/usr/bin/perl
    use Chess;

    $knight = Chess::Piece::Knight->new();
    $board = Chess::Board->new(100, 100, setup => {
                    $knight => "a1";
    });

    $knight->tour()->show();

    1. Re:Perl by berend+botje · · Score: 5, Informative
      I thought you were being a smart-ass. You weren't:

      Chess::Piece::Knight.

      Perl is awesome!

    2. Re:Perl by Anonymous Coward · · Score: 2, Informative

      (Note: I'm the GP AC.)

      Heh. That's funny, but actually, I *was* being a smartass. Don't get me wrong, I love Perl, but the example above is completely made up. (And looking into the Chess package on CPAN, it appears that there is no preimplemented way to generate knight's tours, either.)

      Still, I'm glad to hear that Perl's reputation for there being a module for anything and everything on CPAN still lives, at least. ;)

  11. dump the recursion by Jecel+Assumpcao+Jr · · Score: 4, Interesting

    With the "added intelligence" of the second version, the recursive search devolved into a linear one since the very first attempt at each step will lead to a good solution (add a print to the backtracking part and see if this isn't the case).

    So you might as well convert the recursion into a loop and eliminate the stack overflows for large boards.

  12. A trivial backtracking algorithm and... by berend+botje · · Score: 5, Insightful

    Is submitter really thinking he is special because he implemented a trivial backtracking algorithm that every first semester CS student has done?

    1. Re:A trivial backtracking algorithm and... by jellomizer · · Score: 5, Funny

      Of course like all other programmers he thinks he is better then everyone else.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
  13. OMG by l3v1 · · Score: 3, Funny

    Now let's see, they taught us about this problem back when I was a six- or seven-grader (~'90-91, can't recall exactly) as one of the illustrations for backtracking (yes, I know we can do it without backtracking, that was not the point then I guess). Go figure.

    --
    I am putting myself to the fullest possible use, which is all I can think that any conscious entity can ever hope to do.
  14. Re:Python uses lambda calculus? by Free+the+Cowards · · Score: 4, Informative

    Alas, Python lambdas are very limited, only allowing a single expression. If you need a function that does two things, you can't use lambda anymore. This is not a great hardship as Python allows you to declare inner-scoped functions and you can use that instead, but it's still annoying. I do recommend Python though, as it's a great language even with the occasional shortcoming.

    --
    If you mod me Overrated, you are admitting that you have no penis.
  15. Re:J solution by jackharrer · · Score: 2, Interesting

    It's even less readable that PERL. Shit, I didn't think it's possible. And I used to "program" in PERL...

    --

    "an experienced, industrious, ambitious, and often, quite often, picturesque liar" - Mark Twain
  16. Re:evolve or die by Anonymous Coward · · Score: 2, Informative

    Yawn.

    Another claim that Perl is "in its last throes".

  17. ...and then there's APL by shking · · Score: 4, Interesting

    Here's a solution in 14 lines of APL. I'm pretty sure they could've made it shorter, but readability would've been even worse. APL has been called a "write-only language".

    --
    -- "At Microsoft, quality is job 1.1" -- PC Magazine, Nov. 1994
  18. Re:Least.. Readable.. Code.. Ever... by gardyloo · · Score: 2, Interesting

    That's because you're looking at some MathML code. What one actually types into Mathematica, and sees in Mathematica (or sees in a raw text file version IF the "InputForm" of the code is looked at) is the following. Unfortunately, the code ends suddenly because slashcode somehow doesn't allow more to be shown. BAAAAAD slashcode.

          Complaining about the readability of what you posted is like complaining about the raw HTML which goes into this webpage.

    KnightTour[rows_Integer, columns_Integer, start_List, end_List:{}, HidePaths_Integer:0] :=
          Module[{sR = rows+1, sC = columns+1, i = 0, j = 0, path, endMoves, tree = {0}, SNew, KnightMoves, FeasibleMoves, area},

                      path = If[IntegerQ[start[[1]]], {start}, start];

            endMoves = If[end != {}, If[IntegerQ[end[[1]]],{end},end], {}];

                            area = (rows*columns) - Length[endMoves];

            KnightMoves[lis_List] := KnightMoves[lis] = Complement[
                    Cases[ Map[ lis +#&, {{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}],
                                {x_/; 0

  19. Pentominoes Quine in Perl by Speare · · Score: 4, Interesting
    I know it's a joke to refer to "obfuscated Perl" but this was my one attempt at doing something silly with it. http://www.halley.cc/ed/linux/scripts/quine.html
    • It finds solutions to the 6x10 pentominoes board (exhaustively)
    • To find places that pieces will fit, it employs regular expressions
    • To draw pieces into the board, it employs an embedded tape-driven LOGO-like turtle language
    • It prints solutions as a specially formatted quine of its own source code
    • Any printed solution can be run separately
    • It takes hours and hours to find solutions
    --
    [ .sig file not found ]
  20. I had to solve it in C by gillbates · · Score: 5, Interesting

    As part of my undergrad education. Taking less than a second on today's hardware is nothing spectacular; the secret is in the algorithm: You rate the squares according to the number of moves available from that square and, when given a choice, pick the square with the least number of moves. This way, you don't work yourself into a dead-end situation as frequently. Combine this with a little backtracking, and you've got a nice example to show how algorithm selection has a much larger impact on runtime performance than language selection.

    Incidentally, 200 MHz was considered a fast CPU when I did it, and I remember it taking 8 billion moves and all night without finding a solution. Until, that is, we implemented the preferential choice part of the algorithm. After that, it was pretty much instantaneous.

    --
    The society for a thought-free internet welcomes you.
  21. Re:Python has "perfect syntax"? by Intron · · Score: 2, Interesting

    http://anthonyf.wordpress.com/2006/07/07/solving-the-knights-tour

    I think even if you didn't know any lisp you would find this solution to be pretty readable.

    --
    Intron: the portion of DNA which expresses nothing useful.
  22. Re:Python uses lambda calculus? by RAMMS+EIN · · Score: 2, Interesting

    Not to stir up old debates again, but if you like Lisp, you might be better off going for Ruby than for Python. Coming from a Scheme background, I find Ruby to be the more elegant language.

    Python is a great language, but my feeling about it is that it's designed to support one way of programming (and not even completely - it's sort of ambivalent between procedural and object-oriented). This is fine, and has the advantage off encouraging consistency among programs from different authors. However, I feel there is a better way: just give programmers building blocks and let the programmers compose them in any way they like. I feel Ruby does this, and the result is a language in which you can elegantly build your program in any way you like. In particular, I feel pure functional style is more natural in Ruby than in Python.

    --
    Please correct me if I got my facts wrong.
  23. He mixed tabs and spaces by Anonymous Coward · · Score: 2, Interesting

    Not cool.

  24. Re:Doing it without CS teaching? by jellomizer · · Score: 4, Insightful

    Yes, but a lot of this stuff really isn't worth posting online. Espectially Slashdot I have created many algorithms myself without the need to post it for slashdot acceptance. Some interesting compression algorithms, Memory management algorithms... Whatever that I feel like exploring today. But it is for my own personal knowledge not for public viewing of my code as my method will be to prove some particular point to myself nor will it be efficient or complete, and any attempt to have it posted like the guy who posted this thread will just get critized for anything that is not the best as it could possibly be.

    --
    If something is so important that you feel the need to post it on the internet... It probably isn't that important.
  25. printf by hdon · · Score: 3, Interesting

    A basic print command is needed not a printf replacement.

    Point of fact: Python has the sexiest sprintf() support available. Observe..

    >>> print "I ate %d %s in %.3f seconds" % (99,'hotdogs',62.0895)
    I ate 99 hotdogs in 62.090 seconds

    1. Re:printf by Anonymous Coward · · Score: 4, Funny

      No output, and your font is all wrong.

      *ducks*

    2. Re:printf by Anonymous Coward · · Score: 3, Funny

      It will run 1/10th the speed of Python?

    3. Re:printf by earthbound+kid · · Score: 3, Funny

      You misspelled puts? ;-D

  26. Re:evolve or die by RightSaidFred99 · · Score: 4, Insightful

    Well, here's the thing. Perl was used for _everything_ there for a while, sysadmins who thought they were developers were developing full blown applications in Perl and finding, surprise surprise, that it wasn't real maintainable. So I think we're seeing less of that these days. But Perl is not dying, that's silly. If anything Perl is just being relegated to what it's _really_ good at, and that's UNIX automation tasks and quick throw-away scripts, and _sometimes_ smallish applications. There's really no better language for these types of things.

  27. I hope a firehose exploit was involved. by Vexorian · · Score: 5, Insightful

    I take the point of the blog plug was that I shouldn't be able to do it in C++ with 60 lines....

         1    #include <set>
         2    #include <iostream>
         3    #include <cassert>
         4    using namespace std;
         5
         6    int dx[8]={1,1,-1,-1,2,2,-2,-2}, dy[8]={2,-2,2,-2,1,-1,1,-1};
         7    int D[50][50];
         8    int N,C;
         9
        10    #define valid(x,y) ((x>=0) && (x<N) && (y>=0) && (y<N) && (D[x][y]==-1 ) )
        11
        12    bool show()
        13    {
        14        for (int i=N;i--;)
        15        {
        16            for (int j=N;j--;)
        17                cout<<"\t"<<D[i][j];
        18            cout<<"\n";
        19        }
        20        return true;
        21    }
        22
        23    bool rec(int x, int y)
        24    {
        25        D[x][y]=C++;
        26        if(C==N*N)
        27            return show();
        28
        29        set< pair<int, pair<int,int> > > poss;
        30        for (int r=8;r--;)
        31            if(valid(x+dx[r], y+dy[r]))
        32            {
        33                int neighb=0;
        34                for (int t=8;t--;)
        35                    neighb+= valid(x+dx[r]+dx[t],y+dy[r]+dy[t] );
        36                poss.insert( make_pair(neighb, make_pair(x+dx[r],y+dy[r] ) ));
        37            }
        38
        39        for (typeof(poss.begin()) q=poss.begin(); q!=poss.end(); q++) //hence the reason I am waiting for c++0x
        40            if (rec(q->second.first, q->second.second))
        41                return true;
        42
        43        D[x][y]=-1;
        44        C--;
        45
        46        return false;
        47    }
        48
        49    void solve(int n)
        50    {
        51        N=n, C=0;
        52        memset(D,-1,sizeof(D));
        53        assert(rec(0,0)) ;
        54    }
        55
        56    int main()
        57    {
        58        int n;
        59        while((cin>>n) && (n>0))
        60            solve(n);
        61        return 0;
        62    }

    The bastards! Those darn brackets force me to have 2 extra lines :(

    --

    Copyright infringement is "piracy" in the same way DRM is "consumer rape"
    1. Re:I hope a firehose exploit was involved. by chris_7d0h · · Score: 2, Insightful

      Well C(++) doesn't force you to use new lines at all for most purposes. In the PP's example the exception would be the pre-processor directives.
      So, the PP's solution would fit in just 4 lines of code, way fewer than the 60 required for the Python example, but what does that prove w.r.t. either language implementation of the algorithm?

      Lines of code is a real stupid measurement for complexity, productivity, maintainability and / or elegance and I really wish people would stop using it like that.

      --
      In a society that believes in nothing, fear becomes the only agenda ~ Bill Durodié
  28. Improvements to the heuristic by nneonneo · · Score: 2, Interesting

    TFA has basically stumbled upon Warnsdorff's algorithm. It's a great method, but it doesn't work for really large boards due to blind alleys. There's another method available which uses decomposition to achieve a linear running time(in # of squares), but which is quite a bit more complex to implement. There's a nice tweak to the algorithm which can get much farther than the unmodified original: in the event of a tie (where two candidates have the same number of open neighbours), break the tie by choosing the square farthest from the center. This substantially extends the maximum size of the board (to what, I don't know, because it's worked for everything up to around 450x450, which is past what was described by Arnd Roth).

  29. Knuth by /dev/trash · · Score: 2, Funny

    He's preached against premature optimization for years.

    1. Re:Knuth by pizzach · · Score: 2, Funny

      Holy crap! My prof said that comments should make no difference in the speed that the program runs at, but your code is blazing fast!

      --
      Once you start despising the jerks, you become one.
  30. MAJOR version by CarpetShark · · Score: 2, Informative

    The code will break with the next MAJOR version, not revision. That's entirely normal -- it's actually pretty much what version (as opposed to revision) means.

  31. Re:Python uses lambda calculus? by harry666t · · Score: 2, Informative

    Not doable.

    The colon in lambda is like a guy with a Vista laptop on a LUG meeting. The whole lambda syntax construct is an expression, and def's, if's, while's and all the other guys begin a block of statements (and are statements themselves). In Python, you simply cannot cleanly embed a statement within an expression -- you'd need braces of some kind (and suggesting that to the devs would be like asking to be crucified). Just think, how would this look like:

    map(lambda x:
      if abs(x) > 5:
        spam(x)
    , [3,-3,5,-5])

    With braces, you could write this like map(lambda x {if abs(x) > 5 {spam(x)}}, [3,-3,5,-5]), but well, try "from __future__ import braces".

    And btw, what is the return value of the if statement?... -- exactly.

    Just define a regular function :)

    ==

    But it's still cool to sometimes try and think why Guido or others haven't yet implemented a seemingly obvious feature X. Here's an interesting post about explicit self:

    http://neopythonic.blogspot.com/2008/10/why-explicit-self-has-to-stay.html

    (oh, and BTW: list comprehensions, "x if b else y", other lambdas, are all expressions, so if you'd really want to, you can still do a lot with lambdas (loops, fancy nested if's, etc) -- you may even wrap most of the statements (if, while, import, try, exec) into functions and then try to write whole program as a one great expression... Lisp-style. Just for fun ^^)

  32. Re:Python has "perfect syntax"? by mkcmkc · · Score: 2, Interesting

    I like Lisp a lot, and I certainly prefer its syntax to Java or C (or--god help us all--C++), but I still think that it is clearly less readable than Python.

    If there's a serious argument against this, it must be Lisp's macro capabilities...
     

    --
    "Not an actor, but he plays one on TV."
  33. 1 line from the future (.NET 4.0) by saddino · · Score: 2, Funny

    object[] finalBoard = System.Math.KnightsTour(64);

  34. 3D chess by jagdish · · Score: 2, Interesting

    But does it work with 3 dimensional chess?

  35. Half in size-Double in speed...with Perl by evariste.galois · · Score: 2, Funny

    Can't copy n' paste the code here because I get the message: "Try not to use so many 'junky' words"! So, this is how Slashdot behaves to the language that brought it to life. Anyway,you can find the Perl script here.

  36. Batteries included by XNormal · · Score: 3, Interesting

    There is an elegant Knight's Tour solver right inside your Python distribution. You can find it at /usr/lib/python2.5/test/test_generators.py. Written by Tim Peters (a.k.a. timbot).

    --
    Stop worrying about the risks of nuclear power and start worrying about the risks of not using nuclear power.
  37. Re:evolve or die by xorsyst · · Score: 2, Insightful

    If anything Perl is just being relegated to what it's _really_ good at, and that's UNIX automation tasks and quick throw-away scripts, and _sometimes_ smallish applications.

    Yes, like this smallish application

    --
    Get free bitcoins: http://freebitco.in