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!"

311 comments

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

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

    1. Re:awesome by Anonymous Coward · · Score: 0

      Good job it'll take 2 seconds to update.

    2. Re:awesome by QUILz · · Score: 1

      I know you were trying to be funny but the code doesn't seem to be using any deprecated features or modules.

    3. Re:awesome by orkybash · · Score: 3, Interesting
    4. Re:awesome by Anonymous Coward · · Score: 1, Informative

      And the use of xrange()

    5. Re:awesome by Anonymous Coward · · Score: 0, Redundant

      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. So as you can see for almost all purposes they're the same, and so much so that for Python 3 they're transparently mapping range() with xrange().

    6. Re:awesome by Falstius · · Score: 4, Funny

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

    7. Re:awesome by Anonymous Coward · · Score: 0

      I'm aware of the difference between the two. But last I checked "xrange" will not exist at all in Python 3, having been renamed "range" (not merely mapped to it).

    8. Re:awesome by Anonymous Coward · · Score: 0
      2 seconds to fix:

      xrange = range

      tada!

    9. Re:awesome by jellomizer · · Score: 0, Flamebait

      Does it? Python is a prototype language, the fact that people use it for real applications is besides the point. It should be kept simple and basic to aid for faster prototyping of code. A basic print command is needed not a printf replacement.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    10. Re:awesome by IamTheRealMike · · Score: 1

      wtf? That has to be the most retarded backwards compatibility break I've ever seen.

    11. Re:awesome by earthbound+kid · · Score: 1, Informative

      I got it to run in Python 3, and here are the changes I need to make:

      1) The file was screwed up and used a tab instead of 8 spaces (a problem unrelated to Python 3).
      2) I had to change all the print statements into print functions by wrapping the argument in parentheses.
      3) I had to change xrange to range.
      4) I had to add from functools import reduce to the top of the file.

      Done. 4 changes made in 5 minutes, the hardest of which (#1) would have screwed up Python 2.x as well.

    12. Re:awesome by makapuf · · Score: 1

      but the 2to3 tool will make this simple transforms (xrange->range, print "foo"->print("foo") automatically.

    13. Re:awesome by Keeper+Of+Keys · · Score: 1

      Yep. Python is cool. Try doing that with one of PHP's many backwards-incompatible changes.

    14. Re:awesome by Spy+der+Mann · · Score: 1

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

      No need for a next python version. Just let the code grow and in any mo
      Traceback (most recent call last):
          File "", line 1, in
      TypeError: 'int' object is not callable

    15. Re:awesome by cheater512 · · Score: 1

      PHP 5 is pretty API stable.
      Sure they made some mistakes earlier, but they are fixed now.

    16. 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.

    17. Re:awesome by Tordek · · Score: 0

      Damn, :%s/\t/ /g was the hardest one? Maybe you should switch to a decent editor.

      Oh, btw, you can even copy a tab and paste it into the "search" textbox of the "Search and Replace" dialog on friggin Notepad.

      --
      Tordek, Dwarven Warrior - Juegos de Rol en Argentina
    18. Re:awesome by bnenning · · Score: 1

      Python is a prototype language, the fact that people use it for real applications is besides the point.

      Huh? Python is a general purpose language that can be used for many things, including prototyping.

      It should be kept simple and basic

      Agreed. Therefore, print should be a normal function that works like everything else, instead of a one-off magical statement.

      --
      How to solve most of our problems: 1.Lots of nuclear plants. 2.Cure aging.
    19. Re:awesome by earthbound+kid · · Score: 1

      Gee, thanks for assuming that I'm incompetent. No, I use an actual text editor (which even shows you the different between spaces and tabs and everything), not Notepad. Step one was the hardest because I assumed that I needed to replace the tabs with 4 spaces, like God intended, but when I ran it, I saw that it didn't work, and quickly realized that it was meant to be replaced with 8 spaces. All of the other steps worked the first time, which made step one the hardest relatively speaking, but none of the steps (including one) was especially hard. Maybe if I used a crappy text editor that doesn't distinguish tabs and spaces number one would have been actually hard, but if you program in Python without being aware of the difference between tabs and spaces the fault is your own.

    20. Re:awesome by zigamorph · · Score: 1

      Oh yes, they have fixed them with new mistakes. For example: the next version vill use \ as a separator in module names allowing you to write great looking code like: $foo = new test\foo\bar()

    21. Re:awesome by Detritus · · Score: 1
      Agreed. Therefore, print should be a normal function that works like everything else, instead of a one-off magical statement.

      Why? I can think of examples of both approaches. Putting some "magic" in the compiler allows you to do things that may be difficult or impossible to do in code written in the source language. This is often an issue with I/O statements. The C printf() function is an example of the problems of insisting that everything should be a normal function. In languages without support for variable length arguments lists, it's even uglier. You end up with "printString(), printInt(), printFloat(), printChar(), etc.", rather than "print <list-of-objects>".

      --
      Mea navis aericumbens anguillis abundat
    22. 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
    23. Re:awesome by alecwood · · Score: 0

      He's been modded "Funny" too, so I guess he's not the only one who thinks so.

      Not me though

      --
      Real happiness lies in the completion of work using your own brains and skills.
    24. Re:awesome by Count+Fenring · · Score: 1

      Although they are planning to introduce some new ones to keep things real.

    25. Re:awesome by bnenning · · Score: 1

      Putting some "magic" in the compiler allows you to do things that may be difficult or impossible to do in code written in the source language.

      Sure, things like Python's "lambda" and "yield" can't be done with normal functions, so they're properly statements with special compiler support. But writing to stdout is not magical at all; there's no reason for that specific task to have special syntax.

      --
      How to solve most of our problems: 1.Lots of nuclear plants. 2.Cure aging.
    26. Re:awesome by jellomizer · · Score: 1

      I never said it couldn't be used for general purpose but it is a Prototyping Language. As C is a Procedural Language, and Lisp is a Functional Language. You can do all sorts of things, in any type of language. But a prototype language sacrifices runtime performance for as rapid application development as possible. If you start tweaking the syntax around and make it more of an OOP/Procedural Language you loose many of its key advantages, in prototyping.

      Old python was great as you can write code without having to go crazy with syntax and the low level stuff. It allowed you to focus more on your idea and less on coding. The new stuff is making you focus more on you coding style.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    27. Re:awesome by Count+Fenring · · Score: 1

      Except that "Procedural" is about how the language is composed, and "Functional" is about how the language is composed, and "Prototype" is about how the language is intended to be used.

      Regardless of whether you are correct or not about the direction Python is taking and/or its effect on the language (no opinion, myself), the "Prototype language" thing doesn't work. You're not saying something about the language, you're talking about something the language is used for' and there's ample evidence (ask Google, for instance) that people are using the language for other things.

  2. Phisht! by ArsenneLupin · · Score: 0, Offtopic

    ha!

  3. 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. Re:Easy by Anonymous Coward · · Score: 0

      wishing for a "+1 pedant" mod...

    4. Re:Easy by maxwell+demon · · Score: 1

      And of course, LISP (whatever version) doesn't disallow using camelcase in your own function names, although some LISP versions don't distinguish between uppercase and lowercase characters. Emacs Lisp does distinguish, however, and therefore if you (or the authors of a corresponding package) decide to use CamelCase for the function name, then you just have to use it on invocation, too.

      --
      The Tao of math: The numbers you can count are not the real numbers.
  4. OK by dotslashdot · · Score: 1

    "rm -rf knights"

    1. Re:OK by plasticsquirrel · · Score: 1

      "rm -rf knights"

      rm: cannot remove `knights': No such file or directory

      Ummm.....

      --
      Systemd: the PulseAudio of init systems
    2. 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
    3. Re:OK by Anonymous Coward · · Score: 0

      Would almost be funny, but it's just plain wrong.

  5. 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?

    6. Re:All done. by Anonymous Coward · · Score: 1, Informative

      fixed for ya.

    7. Re:All done. by Tatarize · · Score: 1

      Just use a backtracking algorithm. It'd take about 30 lines in C++ and 40 years to execute. But, applying Moore's law we find that that becomes under a second in about 45 years... so I'm claiming victory.

      --

      It is no longer uncommon to be uncommon.
  6. What would Michael Knight do? by Anonymous Coward · · Score: 4, Funny

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

  7. Nice. And a Mathematica implementation... by gardyloo · · Score: 2, Interesting
    1. Re:Nice. And a Mathematica implementation... by Anonymous Coward · · Score: 0

      HEHE...Knights tour on an 8X8 grid is given in the cover of this book:
      http://www.amazon.com/Introductory-Graph-Theory-Gary-Chartrand/dp/0486247759/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1228194190&sr=8-1

      Just pick a starting square and remove an edge incident to that square.

      NOW GET OFF MY LAWN!!!

  8. 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 Anonymous Coward · · Score: 0

      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.

      The C version wouldn't be all that terrible either -- just use function pointers where he uses lambda functions.

    2. 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.
    3. 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

    4. Re:Try lisp by godefroi · · Score: 1

      Ugh. Python's syntax is everything that's wrong with Visual Basic, but even more.

      --
      Karma: Poor (Mostly affected by lame karma-joke sigs)
    5. Re:Try lisp by atraintocry · · Score: 1

      Python syntax can get wacky...especially with list comprehensions or generator sequences. You end up cramming a lot of logic into one line, and mixing in things like map or lambda leaves you with jumbles of parentheses and brackets.

      You don't actually have to do it the way it was done above (either example). You can always use a for or while loop bounded by the length of the list, where you do your truth test, store the result, and increase a counter variable. But Python programmers should be familiar with the functional tools as well as list comprehensions and generator expressions, so there's not much reason to write the extra code (LCs run much faster anyway).

      Doesn't VB use the same symbol for equivalence tests and assignment? IMO that automatically makes it worse than any language that keeps them separate.

    6. Re:Try lisp by godefroi · · Score: 1

      I'm referring to the significant whitespace. And the fact that spaces are the preferred significant whitespace. You like 8 character tab stops, I like 2. Why can't we use tabs and each have it look the way we want it?

      Also, I'm not defending VB here, they're both disasters.

      --
      Karma: Poor (Mostly affected by lame karma-joke sigs)
  9. 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 Anonymous Coward · · Score: 1, Insightful

      "This algorithm is rather complicated because it has to deal with many special cases, but has been implemented in Mathematica by A. Roth."

      This would pretty much defeat the fun of coding it in python.

    2. Re:better algo by Willbur · · Score: 1

      The Wolfram page notes two approaches. One is a heuristic approach that works well until the board gets large (76x76 is the size quoted). This is the algorithm implemented by Python code.

      The second approach is only referenced on the Wolfram page, not described in any detail. The text on that algorithm from the Wolfram page is:

      Recently, Conrad et al. (1994) discovered another linear time algorithm and proved that it solves the Hamiltonian path problem for all n >= 5. The Conrad et al. algorithm works by decomposition of the chessboard into smaller chessboards (not necessarily square) for which explicit solutions are known. This algorithm is rather complicated because it has to deal with many special cases, but has been implemented in Mathematica by A. Roth.

      Sounds hard to implement in 60 lines of python - especially when most of the 60 lines is UI.

    3. Re:better algo by gardyloo · · Score: 1

      True. But have you looked at the algorithm? It's remarkably simple, was written in 1992, and is totally generalized to any size chessboard (there is an example in Arnd Roth's implementation for a 180x180 board).

    4. 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/

    5. 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.

    6. Re:better algo by Chandon+Seldon · · Score: 1

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

      Wait a second. What's wrong with recursion?

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
    7. Re:better algo by Mostly+a+lurker · · Score: 1

      Recursion is not always bad. It often makes code much easier to understand, and a good compiler can sometimes optimize the recursion away in the object code.

    8. 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.
    9. Re:better algo by Anonymous Coward · · Score: 0

      A good compiler should *always* optimize away recursion, especially tail recursion, unless told not to. It just recycles the same chunk of stack over and over.

    10. 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
    11. Re:better algo by jonadab · · Score: 1

      > What's wrong with recursion?

      That depends on a variety of factors, including how your language/compiler/interpreter/runtime/whatever implements recursion. If the implementation is fully naive (no optimization at all), the main problem is that you use an amount of RAM proportional to the recursion depth, which can lead to a lot of swapping for large values of N. However, depending on exactly how your code uses the recursion, a more intelligent implementation may optimize away most of the memory usage.

      --
      Cut that out, or I will ship you to Norilsk in a box.
    12. Re:better algo by weetabeex · · Score: 1

      I've been coding C for a while now and recursion has always been presented to me as hell on earth. I'm sure most of the people who has ever created a recursive pow had a stack overflow at some point due to the amount of calls made.

      So, I don't get it: how can it be more efficient when used on compiled code?

    13. Re:better algo by Chandon+Seldon · · Score: 1

      I've been coding C for a while now and recursion has always been presented to me as hell on earth. I'm sure most of the people who has ever created a recursive pow had a stack overflow at some point due to the amount of calls made.

      See http://en.wikipedia.org/wiki/Tailcall

      The two cases where recursion is the cleanest solution are A.) when you would have needed an explicit stack or tree anyway and B.) when the obvious implementation is tail-recursive. This ends up being true for a surprisingly large number of algorithms, but "pow" really isn't one of them. Still, you might occasionally see something like the following:

      double pow_iter(double x, double n, double r) {
      if(n <= 0) return r;
      else return pow_iter(x, n - 1, r * x);
      }

      double pow(double x, double n) {
      return pow_iter(x, n, 1.0);
      }

      Which is more elegant than the while-loop solution if you look at things from a certain programming mindset.

      --
      -- The act of censorship is always worse than whatever is being censored. Always.
    14. Re:better algo by Anonymous Coward · · Score: 0

      Nothing (IMHO), although I tend to prefer iterative approaches when available. But surely you meant this:

      Wait zero seconds. What's wrong with recursion?

      If you don't reduce the problem size for every iteration you'll probably end up with an infinite recursion which is indeed problematic.

    15. Re:better algo by Anonymous Coward · · Score: 0

      OTOH, if the algorithm is branch-recursive, the time complexity is exponential in the stack depth, so the memory usage will only be a limiting factor if the language imposes unnecessarily low limits on stack usage (hint: it's unnecessary to restrict stack usage more than any other type of memory usage; RAM is RAM whether it's used for stack or heap).

    16. Re:better algo by shutdown+-p+now · · Score: 1

      Wait a second. What's wrong with recursion?

      Recursion.

    17. Re:better algo by nog_lorp · · Score: 1

      Always? There is not always a way to convert from a recursive algorithm to a non-recursive algorithm. For example, try writing a non-recursive function to calculate Ackermann numbers.

      On the other hand, most recursive algorithms can be unwrapped but doing so is non-trivial. There is no compiler that exists as yet that will optimize away any recursions that could possibly be made non-recursive.

    18. Re:better algo by oreaq · · Score: 1

      Or all those new super duper languages could do what everyone else did sometime in the 60s. They could implement proper tail recursion.

    19. 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.
    20. Re:better algo by maxwell+demon · · Score: 1

      I've been coding C for a while now and recursion has always been presented to me as hell on earth. I'm sure most of the people who has ever created a recursive pow had a stack overflow at some point due to the amount of calls made.

      Of course, those pow functions were just inefficient anyway. But then, their iterative pow function was probably very inefficient as well.

      The following pow function is recursive, but usually will not overflow the stack:

      double power(double x, unsigned n)
      {
        if (n==0)
          return 1.0;
        else if (n%2 == 0)
          return power(x*x, n/2);
        else
          return x*power(x-1);
      }

      Obviously this code isn't very well optimized, but then, it will still beat the normal iterative version if the exponent is very large.

      --
      The Tao of math: The numbers you can count are not the real numbers.
    21. Re:better algo by maxwell+demon · · Score: 1

      After some time, the computer gets bored and just to make life a bit more interesting gives you a segmentation fault.

      --
      The Tao of math: The numbers you can count are not the real numbers.
    22. Re:better algo by Nevyn · · Score: 1

      All recursion can be done by hand, using loops etc. see this google result for "Ackerman function non-recursive". This is approach can be much faster (and is never slower), but often much uglier than the "simple" recursive version. It also doesn't have the weird edge case failures though (for instance blowing the stack in C/python/etc. is basically unrecoverable).

      --
      ustr: Managed string API with ave. 44% overhead over strdup(), for 0-20B
    23. Re:better algo by DragonWriter · · Score: 1

      There is not always a way to convert from a recursive algorithm to a non-recursive algorithm.

      Yes, there is.

      On the other hand, most recursive algorithms can be unwrapped but doing so is non-trivial. There is no compiler that exists as yet that will optimize away any recursions that could possibly be made non-recursive.

      No one has designed a program that can convert every recursive program to a non-recursive one (and it may even be the case that this is impossible), but there is always a non-recursive equivalent available, otherwise, there couldn't be Turing-complete languages without recursion, which do exist.

    24. Re:better algo by Anonymous Coward · · Score: 0

      The post you are responding to specifically explains why Warnsdorf's heuristic is NOT the "ultimate" algorithm - it is just a heuristic that is simply wrong for large boards. The algorithm described in your parent post is just as fast, except it actually works in general.

    25. Re:better algo by KDR_11k · · Score: 1

      I have a hunch the conversion could be reduced to the halting problem in some way...

      Depending on the algorithm your "iterative" code could very well end up being a custom recursion implementation. If you do a depth search through a tree (or any mesh even) using a stack to remember the path you've taken you're effectively recursing even if you just use a while loop (to the CPU there's no difference anyway). After all a Turing Machine can implement a stack so just because it's computable and your language has no native recursion but is Turing-complete that wouldn't necessarily mean that you won't effectively implement recursion anyway.

      --
      Justice is the sheep getting arrested while an impartial judge declares the vote void.
    26. Re:better algo by 2short · · Score: 1

      "The ultimate algorithm is called Warnsdorf's heuristic..."

      In this, as with so much else, the ultimate algorithm is a lookup table. Back in school, I wrote such a program (in Pascal) in connection with a talk I gave based on this paper:

      http://www.jstor.org/pss/2690649

      which describes on exactly which NxM boards a knights tour is possible. Moreover, it decribes a method for taking a solution for an NxM board that meets certain criteria, and adding 4 rows or columns to it to produce a larger board that also meets those criteria. And it provides appropriate solutions for the 9 starting boards to which you can successively add sets of 4 rows/columns to get any board for which a tour is possible. All without any searching at all. My program spit out whatever order you wanted in roughly as fast as the answer could be output to the screen.

      True, writing out a (mostly) pre-generated solution to a problem is not as interesting a program as doing the (unnecessary) search. But for the math geeks out there it's a fun paper; the negative proof for the m=4 case is particularly nifty.

    27. Re:better algo by nog_lorp · · Score: 1

      That was pretty much my point. Mainly I wanted to point out that my parent earlier was flat out wrong - no compiler unwraps recursive functions always or even most of the time.

    28. Re:better algo by KDR_11k · · Score: 1

      The first part was supporting your point but I think when you said that every algorithm has an iterative counterpart that could very well be wrong as the reasoning that turing complete languages don't all support recursion and therefore recursion is not necessary isn't really correct since any turing complete language can implement recursion in some form even if it's not a native feature. After all, the CPU itself doesn't know recursion, it only knows the stack and conditional jumps to handle that.

      --
      Justice is the sheep getting arrested while an impartial judge declares the vote void.
  10. 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 Anonymous Coward · · Score: 0
    2. 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
    3. 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).

    4. 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.

    5. 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.

    6. 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.
    7. Re:28 lines in Prolog :-) by Anonymous Coward · · Score: 0

      Yeah, and here's one in Java that does the same thing but with an animated GUI (with only 10 more lines of code!).

      Bzzt. It uses a bunch of extra search classes in the same package.

    8. Re:28 lines in Prolog :-) by Anonymous Coward · · Score: 1, Interesting

      27 lines of Haskell. LogicT monad FTW!

      http://haskell.org/haskellwiki/The_Knights_Tour#LogicT_monad

    9. Re:28 lines in Prolog :-) by Alpha-Toxic · · Score: 1

      Well, I bit the bullet...
      This is what I managed to put together after 2 hours (most of the time went for looking for a greedy(er) algorithm)
      http://alpha-toxic.hit.bg/Knight.java
      About 100 lines of code, and is does 150x150 in less than 50ms (start it with "-Xss10240k" as the recursion is very deep and the default stack fills up at about 50x50)
      It's very ugly, not optimized (speed, lines, nothing), JAVA and still waaay faster than what the OP gives. Either he's not a very good programmer or python is not supposed to be used for that, perhaps both...

    10. Re:28 lines in Prolog :-) by phantomfive · · Score: 1

      Nice. Did your own sort, also.

      --
      Qxe4
    11. 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.)

    12. Re:28 lines in Prolog :-) by Vexorian · · Score: 1

      This year I have dedicated some time to learn python, basically, it is a fun language, and it is the first thing I choose for small programs aka scripts that do simple things, like generating a sequence, etc. functional stuff was also useful for a certain numerical methods homework I had to do previous semester.

      For simple things it is quite good, and it is fun to play with the syntax constructs, hence the reason it was a good choice for this simple algorithm.

      However, I would stay miles away from using it on anything that required more than 200 lines of script in a single file... I have already experienced what a nightmare python can be... You kind of get tired of having to wait 30 seconds of execution only to find out you didn't type a name correctly in the last method your program calls...

      --

      Copyright infringement is "piracy" in the same way DRM is "consumer rape"
    13. Re:28 lines in Prolog :-) by Coryoth · · Score: 1

      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...

      I presume you're a big fan of Eiffel, or JML for Java, or SPARK-Ada then, since they have even more explicit and detailed specification conveniently folded into the code such that it will not fall out of date...

    14. Re:28 lines in Prolog :-) by jonadab · · Score: 1

      If the algorithm can be implemented in 60 lines of Python or 70 lines of Java, it can probably be done in 10 lines of clear and maintainable Perl code, or 70 characters of golfed-down unmaintainable line noise.

      --
      Cut that out, or I will ship you to Norilsk in a box.
    15. Re:28 lines in Prolog :-) by sydneyfong · · Score: 1

      Amen.

      The lack of explicit typing not only stings when dealing with other people's code, in my experience it also makes debugging my own code harder.

      Since python does most type checking at runtime, you need to run your program (possibly for a few times), as compared to a simple compilation, to look for type-related bugs.

      So goes the saying: "It compiles! Ship it!". Might actually worked for languages like C++ or Java, but with python, don't even think about it.

      Disclaimer: python is actually my choice scripting language.

      --
      Don't quote me on this.
    16. Re:28 lines in Prolog :-) by chthonicdaemon · · Score: 1

      I suppose it's all down to what you know. I learned C++ and Pascal in school, then did a lot of Matlab for my Masters, which really got me into the dynamic typing thing, so Python seemed natural to me. Every time I try to do something in C++ now, I feel like I'm spending more time on defining types than on solving the problem. And the braces irritate the hell out of me.

      The reality is that one's history with programming affects the way one thinks about programming. If I had a dime for each time I've seen languages that I like being redone with "more natural syntax" where this basically means c-like syntax, I would be a rich man.

      By the way -- for solid typing, haskell is better than c++ any day. Type inference means you only have to define types where it is useful and strong typing with proper type handling in the standard prologue means you don't get the undebuggable mess that results from heavy use of the STL.

      I will give you this: there are well developed IDEs for the 'big program' languages that make it easier to develop a large program. For my needs as a researcher, there is no upside to c++. I've gone to Python with Fortran for the heavy lifting.

      --
      Languages aren't inherently fast -- implementations are efficient
    17. Re:28 lines in Prolog :-) by johanatan · · Score: 1

      I was taught (and believe it to be proper) to add lots of assertions of expected types in dynamically-typed languages. This addresses both your 'deep frame untangling' problem and your 'difficulty of random orientation' problem.

    18. 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...

    19. Re:28 lines in Prolog :-) by jomiolto · · Score: 1

      A few years back there was a smallish competition to code Knight's Tour in x86 assembler (limited to 8x8 board, though). The winning entries were only 46 bytes compiled to a DOS .com file. Fond memories, despite my entry being almost 60 bytes of bloat ;)

      Clicky here

    20. Re:28 lines in Prolog :-) by Jack9 · · Score: 1

      You can create all the SWING/AWT objects you want, anytime AFAIK. It's explicitly adding them to a visible component or model of a visible component, outside the event que, that gives you the unpredictable behavior.

      --

      Often wrong but never in doubt.
      I am Jack9.
      Everyone knows me.
    21. Re:28 lines in Prolog :-) by shutdown+-p+now · · Score: 1

      Well, except that it's not Warnsdorff's algorithm. In fact, this seems to just give a list of all possible paths a knight can take from (1,1), including those that do not cover the entire board (or at least I don't see the spot where it filters out the latter).

    22. Re:28 lines in Prolog :-) by Jeff250 · · Score: 1

      No, this is a common misconception. Sun themselves have had to fix many of their Swing examples on their site so that component creation is now on the EDT.

      Sun Swing Tutorial states:

      Why does not the initial thread simply create the GUI itself? Because almost all code that creates or interacts with Swing components must run on the event dispatch thread.

      Here is a blog that discusses this issue further. Point is, Swing component creation must occur on the EDT. Methods must explicitly say they are exempt from the single threading rule before you can exempt them.

    23. Re:28 lines in Prolog :-) by ttsiod · · Score: 1
      > I'd wager that this guy has never worked on huge projects

      And you would be wrong. I've worked in very large projects (in the Telecom industry), and am currently coding specialized C/C++ code generators for the European Space Agency (the kind that actually generate the static, speedy, typesafe code that is appropriate for many projects). I know what you are talking about, and I never implied that Python is the way to go for all kinds of problems. My site has just as much C++ stuff as it does Python (e.g. my realtime 3D renderers) - even x86 SSE asm! What I am trying to show people is that there are many kinds of problems where scripting languages are not only adequate, but in fact the best way to go about... Google uses and advocates Python a lot, and Eric Raymond (esr) explains why a lot better than I ever could (Why Python?). In this day and age, developing speed and code clarity is just as important (if not more) as execution speed. Try Python and you'll know what I mean, when I refer to developing speed... And as for code clarity, the world is moving towards dynamic and type-infering languages (Ocaml, F#) for a reason...

    24. Re:28 lines in Prolog :-) by RedWizzard · · Score: 1

      Well, except that it's not Warnsdorff's algorithm. In fact, this seems to just give a list of all possible paths a knight can take from (1,1), including those that do not cover the entire board (or at least I don't see the spot where it filters out the latter).

      Well, except that it's not Warnsdorff's algorithm.

      No, but neither is the 60 line Python version, right? The link I mentioned has a version using the Warnsdorff algorthim and it's similar in length to the Prolog version (which also doesn't implement Warnsdorff's algorithm, though I may be mistaken - I haven't used Prolog in about 15 years).

      In fact, this seems to just give a list of all possible paths a knight can take from (1,1), including those that do not cover the entire board (or at least I don't see the spot where it filters out the latter).

      It's the loop: it counts down from n^2 (where n is the number of squares per side). So the loop only ends successfully if the tour covers the entire board.

    25. Re:28 lines in Prolog :-) by shutdown+-p+now · · Score: 1

      No, but neither is the 60 line Python version, right?

      I didn't see it as it's slashdotted, but my impression from others' comments was that it was that. Anyway, here's my take on doing it in Haskell (GHC, specifically - as I recall, `on` is not in the Standard):

      import Data.Function
      import Data.List
       
      walk [] _ = []
      walk unwalked s =
          let accessible (x, y) = filter (\(x', y') -> abs((x - x') * (y - y')) == 2) unwalked in
          let s' = minimumBy (compare `on` length . accessible) (accessible s) in
          s' : (walk (delete s' unwalked) s')
       
      main =
          let start = (1, 1) in
          let unwalked = delete start [(x, y) | x <- [1..8], y <- [1..8]] in
          let path = walk unwalked start in
          print (reverse path)

      To conclude, the language itself matters little, so long as it provides some form of list comprehensions, and a standard library rich with higher-order list processing functions. Haskell is particularly good at both, but OCaml/F# is pretty close, and even something like C# can be reasonably concise here (thanks to LINQ).

    26. Re:28 lines in Prolog :-) by setagllib · · Score: 1

      My apologies, I meant invokeLater. Otherwise my point stands and I'm sure it's worth fixing all your code, since it's unlikely this is the only time you've made this mistake.

      --
      Sam ty sig.
    27. Re:28 lines in Prolog :-) by Detritus · · Score: 1

      60 bytes?! You must think that memory grows on trees! :-)

      I'm impressed, I'll have to check out the contest.

      --
      Mea navis aericumbens anguillis abundat
    28. Re:28 lines in Prolog :-) by MikeBabcock · · Score: 1

      Horror reading:

      In C: DJB's source of anything (one-letter variables, three letter functions, etc.) -- clean, well-organized and horrific all at once :)

      In C++: Hylafax.

      In Python: BitTorrent

      Your suggestions? :)

      --
      - Michael T. Babcock (Yes, I blog)
    29. Re:28 lines in Prolog :-) by Vexorian · · Score: 1
      Basically, that's one of the reasons this article is DARN overrated...

      If I were to use sort stuff in c++, I would do:

      sort( validMoves.begin(), validMoves.end() , byLesserNeighborgCount() )
      Sure I will have to make a functor for the byLesserNeighborgCount stuff, but here is the catch, my code is more readable than his python code! wha? That's right, I am not using totally made up terms like lambda just to save me a couple of extra lines in the functor, not only that, but my comparasion is forced to be one from another function, adding more modularity to the code and making the main recursive algorithm shorter... Plus by actually naming the functor it is clear what I actually am doing, I am sorting the possible moves by lesser neighborg count! Amazing is it?

      Of course, boost has lambda and like that code I posted down there, I could also exploit pair so I don't have to type the comparisons at all... But saving a couple of lines is totally irrelevant, the better objective is to make something that probably needs 2 extra lines but is actually readable by itself, I wouldn't even need to comment that code... Line count is worthless...

      --

      Copyright infringement is "piracy" in the same way DRM is "consumer rape"
    30. Re:28 lines in Prolog :-) by CarpetShark · · Score: 1

      You know, that's a really good argument, and one I've never considered before. I currently code in python, and generally love it. But the lack of explicit method signatures does bug me even though I find it a boon for rapid development. Probably, this is why. I've been considering taking java more seriously lately, or reverting to C++ (but I probably won't :D). Your comment probably will be the final nail in the coffin, one way or another.

    31. Re:28 lines in Prolog :-) by Jack9 · · Score: 1

      Er, I think you are still getting "creation" and "painting" confused. According to the blog:

      Swing Single Threading Rule (through 2003)
              Once a Swing component has been realized*, only the event-dispatching thread should affect or query the component.
              *Realized means that the component has been painted onscreen, or is ready to be painted. The methods setVisible(true) and pack cause a window to be realized, which in turn causes the components it contains to be realized.

      Again, I can create thousands of buttons on the fly. This doesn't affect the application/applet in any way other than consuming jvm/processor time and memory. It's only when I attempt to add them to a painted or PREVIOUSLY painted component (the blog uses the term "Realized" and fails to mention things that have dropped out of visibility and swing models, like a ListModel attached to a scrollpane) that you get unpredictable behavior.

      --

      Often wrong but never in doubt.
      I am Jack9.
      Everyone knows me.
    32. Re:28 lines in Prolog :-) by omuls+are+tasty · · Score: 1

      So one of the two fundamental approaches to defining computers is a "totally made up term", yet a "functor" is a perfectly sensible thing? Gotcha.

      Though I'd have to agree that using a lambda here has little advantage, a named function is much clearer. I think that generally, lambdas would make more sense in simpler examples, such as:

      l.sort(key=lambda x: weight[x])

      or more complex ones, where you'd need to use closures (well actually I'm using a closure right up there but... you know what I mean :))

    33. Re:28 lines in Prolog :-) by setagllib · · Score: 1

      I think you just can't read. Just a couple of paragraphs down in the blog, you get the updated rule which Sun now universally follow, and every maintained application is expected to follow as well. It solves real problems on real platforms, including Sun's own Solaris. Your theory can't disprove their practice.

      I have lots of my own anecdotal evidence of seemingly simple Swing GUIs (and even JOGL GUIs with a heavyweight AWT components) having non-deterministic bugs when the event loop is not used correctly, even just for initialisation. So I adhere to the rule and I have no further bugs, and I advise all friends and colleagues to do the same, and they report their bugs are fixed too. It can't be any more convincing than that.

      --
      Sam ty sig.
    34. Re:28 lines in Prolog :-) by Jack9 · · Score: 1

      I did not read that section. Interestingly enough, the guideline was changed to match a behavior on Solaris. Developing for Windows and OSX, there is no side effects in instantiation outside the event loop. That's more convincing, insofar as it's demonstrably true.

      --

      Often wrong but never in doubt.
      I am Jack9.
      Everyone knows me.
    35. Re:28 lines in Prolog :-) by Jeff250 · · Score: 1

      There is a counter-example to your claim in this Sun bug report where the reporter was using Java 6 on Windows XP. I suppose you could try to analyze the report and try to come up with an even more complex set of circumstances under which you might be able to instantiate Swing components outside the EDT, but trying to do that is just a Bad Idea.

      Sun does not say anywhere that you can instantiate Swing components outside the EDT for any operating system or for any system configuration. They specifically say to instantiate Swing components on the EDT. If instantiating Swing components outside the EDT has been working on any specific versions of your Java or your OS, then this is only accidentally the case, and you have no guarantee that it will work outside your setup for different (especially future) versions of your Java or your OS.

    36. Re:28 lines in Prolog :-) by setagllib · · Score: 1

      Are you just trying to prove a point? This is just sad. Everyone informed in the matter knows that this is how it should be done, based on real bug reports and real testing, by the authors and maintainers of the platform itself, as well as the industry at large. Just accept it and move on. What you're saying is far from demonstrably true, it's been regularly demonstrated false.

      I could understand your resistance if this was some huge change, but all you are required to do is move work from the constructor to run(), and in fact you can even do this as a wrapper in main, assuming your entry class already implements Runnable:

      public static void main(String[] args) {
              EventQueue.invokeLater(new Runnable() {
                      public void run() {
                              new BrokenApp().run();
                      }
              });
      }

      This kind of fix is not optional, it's just as important as any other thread synchronization. Yes it might not break often in your particular test setup, but incorrect usage has been known to fail on a variety of platforms, so why risk it?

      --
      Sam ty sig.
    37. Re:28 lines in Prolog :-) by Anonymous Coward · · Score: 0

      Yeah, and here's one in Java

      Cheating with
      SearchEngine se;

      SearchEngine also imports some other classes as well... (amounts to a good deal more)

    38. Re:28 lines in Prolog :-) by phantomfive · · Score: 1

      Well, you know, whether or not someone else managed to write a program in C++ in shorter lines, it's ok.........there was some interesting conversation to be had spurred on by your blog post. Better than another graduate student asking if he can get the rights to his code or not AGAIN.

      --
      Qxe4
  11. J solution by Anonymous Coward · · Score: 0

    I know nothing of the problem but have a look at http://www.jsoftware.com/jwiki/Essays/Knight's_Tour for a J version and some comments.

    Also,

    http://www.jsoftware.com/jwiki/Essays

    1. 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
    2. Re:J solution by Draykwing · · Score: 1

      Just by-the-by, there is no such thing as PERL. All acronyms for the language Perl's name are backronyms, and were created after the fact. Perl is the language, perl is the interpreter. Please refer to http://abelew.web.wesleyan.edu/perl_flame.html

  12. Python has "perfect syntax"? by Anonymous Coward · · Score: 1, Funny

    Please... Why do we need slashvertisements for programming languages on Slashdot?

    1. Re:Python has "perfect syntax"? by mkcmkc · · Score: 1, Troll

      It's not "perfect", but compared to the 40+ other languages I've used, it seems to be at or near the top, in terms of human readability.

      (Lisp has obvious advantages for machine readability, but it's quite rare that this is useful.)

      --
      "Not an actor, but he plays one on TV."
    2. 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.
    3. 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."
    4. Re:Python has "perfect syntax"? by dkixk · · Score: 1
      (ignore-errors (with-open-file (in *python*) (loop for symbol = (read in nil) while symbol)))
      • NIL
      • #<SB-INT:SIMPLE-READER-ERROR {10026C2661}>

      (ignore-errors (with-open-file (in *c++*) (loop for symbol = (read in nil) while symbol)))

      • NIL
      • #<SB-INT:SIMPLE-READER-ERROR {1002DDF151}>

      Personally, I can't read a lick of any of this but Python doesn't look any more readable than C++ to me. If there's a serious argument against this, it would be that a child of five would be able to read any Python code. Send somebody to fetch a child of five.

  13. 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: 0

      $ perl <> use Chess;
      >
      > $knight = Chess::Piece::Knight->new();
      > $board = Chess::Board->new(100, 100, setup => {
      > $knight => "a1";
      > });
      >
      > $knight->tour()->show();
      > EOF
      Can't locate Chess.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.0 /usr/local/share/perl/5.10.0 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at - line 1.
      BEGIN failed--compilation aborted at - line 1.

      You lose. The Python version didn't need any external modules.

    3. Re:Perl by FooAtWFU · · Score: 1

      The semicolon after $knight => "a1"; is more of an issue for me. And when you fix it, the message about 'Missing argument to Chess::Piece::new() at tour.pl line 4'. That said: what, are you afraid of CPAN? :P

      --
      The World Wide Web is dying. Soon, we shall have only the Internet.
    4. Re:Perl by jellomizer · · Score: 1

      What does the quality of the language have to do about a sister projected of keeping and storing 3rd party libraries. I actually hate it because of that because you get these perl apps and they assume that you have some stupid library installed and you need to keep on trying over and over again for the right library.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    5. Re:Perl by Anonymous Coward · · Score: 0


      #!/usr/bin/perl
      use Chess;

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

                      $knight => "a1";
      });

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

      Can't locate object method "tour" via package "Chess::Piece::Knight" at ./knight line 13.

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

    7. Re:Perl by Anonymous Coward · · Score: 0

      You lose. The Python version didn't need any external modules.

      WOOSH.

      (I'm the GP AC, BTW.) Dude, loosen up a bit! It was a *joke*. Y'know, because Perl has a reputation of having a module for everything already. So the joke was that it would have one for this, too.

      Got it?

      (In reality, while there is a Chess module - installable like any module, e.g. using the CPAN shell -, it doesn't provide this functionality, unfortunately.)

    8. Re:Perl by jlarocco · · Score: 1

      Because it saves time writing code and "standardizes" common functinality (like a Chess board abstraction). Both of those are indirect ways of saying CPAN makes complicated problems easier to solve. The whole point of writing software is to solve problems, and CPAN makes it easier. Why reinvent the wheel, even if it is only 60 lines of Python?

      Also: CPAN can automatically grab dependencies, so I'm not really sure what you're whining about in your second sentence.

    9. Re:Perl by Anonymous Coward · · Score: 0

      What does the quality of the language have to do about a sister projected of keeping and storing 3rd party libraries. I actually hate it because of that because you get these perl apps and they assume that you have some stupid library installed and you need to keep on trying over and over again for the right library.

      Actually, the assumption is you have enough intelligence to read the source, know what you are doing, and then be able to follow simple, straight forward processes for obtaining what you need.

    10. Re:Perl by onefriedrice · · Score: 1

      ... and you need to keep on trying over and over again for the right library.

      Or just read the requirements of the software you're installing. Maybe that would be too easy?

      --
      This author takes full ownership and responsibility for the unpopular opinions outlined above.
    11. Re:Perl by somenickname · · Score: 1

      Compiled code also assumes you have tons of shared libraries. If you are running an OS that has good package management, you generally don't care what language something is in or what dependencies it has if you are getting it out of the repos because that is handled for you. If you need to run some random perl script that is not in the repos, here is a tip for Debian based machines: Much of CPAN is mirrored in the repos and the perl module called Foo::Bar is very likely to be package libfoo-bar-perl.

    12. Re:Perl by jonadab · · Score: 1

      > Perl is awesome!

      Perl is a nice language. It's the CPAN that's awesome. If I had to pick between everything on sourceforge, and everything on the CPAN, I'd choose the latter without hesitation.

      --
      Cut that out, or I will ship you to Norilsk in a box.
    13. Re:Perl by Anonymous Coward · · Score: 0
    14. Re:Perl by joranbelar · · Score: 1

      Whoa there buddy, it's not quite that awesome. I don't see anywhere that the Knight class has any kind of "tour" method at all. Nor does the board allow you to set it up as 100x100. In fact based on the docs you linked to, the perl snippet above won't even run.

      Maybe the OP was just having some fun, but some may misunderstand and think this actually exists. The Chess module is just a way to represent a common game of chess, encapsulating the pieces, moves, and rules in an easy-to-read manner.

      Then again, maybe he's using an updated version ;-)

    15. Re:Perl by Anonymous Coward · · Score: 0

      Exactly where is Chess::Piece::Knight->tour() ? Its not a valid method in the latest Chess module.

  14. 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.

    1. Re:dump the recursion by Anonymous Coward · · Score: 0

      Well shit. If you're gonna make sense...

    2. Re:dump the recursion by Anonymous Coward · · Score: 0

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

      You used engineering induction to prove this did you?
      Look at the wolfram.com link given above and you'll see that backtracking is needed for n>76.

  15. 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.
    2. Re:A trivial backtracking algorithm and... by rrohbeck · · Score: 1

      I did this in high school you insensitive clod!

      Oh and it was in FORTRAN :P

    3. Re:A trivial backtracking algorithm and... by Anonymous Coward · · Score: 0

      He's wrong though, I'm a way better programmer than he is.

    4. Re:A trivial backtracking algorithm and... by FreeGamer · · Score: 1
      The problem is not so much with the pride the submitter takes in his solution - I'm sure he's not as arrogant as your joke implies - but it's in his blinded attitude towards (bordering on worship of) Python:

      Python has tremendous advantages... 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 sorting logic in C++ in anything less than 3 times the lines of code I wrote for in Python.

      Perfect syntax? I mean, come on, besides the fact that perfect means flawless and this being a subjective issue, Python's syntax is far from perfect. It's just better than C/C++. Each to their own. I tried using Python, and (as somebody who uses Java/JavaScript/XML regularly) it just wasn't fun. The submitter needs to learn to speak in relative terms i.e. "It's perfect for me."

  16. Python uses lambda calculus? by Spilver · · Score: 1

    I've seen people lauding Python for years but I have just considered it yet another scripting language (Perl is one of my favorites). Now I find out it is a functional language using lambdas (and maps), and Lisp having been one of my favorites years ago, this is going to be my next language to learn!

    1. 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.
    2. Re:Python uses lambda calculus? by Anonymous Coward · · Score: 0

      You might be interested in Higher-Order Perl

      Idea of the Book :
      Higher-Order Perl is about functional programming techniques in Perl. It's about how to write functions that can modify and manufacture other functions.

      http://hop.perl.plover.com/
      http://en.wikipedia.org/wiki/Higher-Order_Perl

    3. Re:Python uses lambda calculus? by harry666t · · Score: 1, Informative

      > If you need a function that does two things, you can't use lambda anymore.

      wtf? of course you could!

      lambda x,y: (spam(x), meth(y)) [-1]

      yeah, less readable etc but works. And yes, Python is even capable of executing interesting, obscure one-liners:

      http://mobile.slashdot.org/comments.pl?sid=1022735&cid=25689627

    4. 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.
    5. Re:Python uses lambda calculus? by maxume · · Score: 1

      Python is probably best described as multi-paradigm. Functions do happen to be first class objects (along with everything else), so a lot of stuff can be written in a functional style. The lambda keyword is little more than a way to declare a function without giving it a name.

      A downside compared to lisp is that it isn't really possible to declare something as static, so optimization and compilation are more problematic (it is possible to construct a stubborn object, but names/references to that object can simply be rebound to a more flexible object, so it is hard to rely on the object being stubborn).

      --
      Nerd rage is the funniest rage.
    6. Re:Python uses lambda calculus? by Free+the+Cowards · · Score: 1

      Nice technique, thanks, I'll have to remember that. Still, it would be nice if lambdas had the same basic syntax as regular functions so you could do multiple lines in the same way.

      --
      If you mod me Overrated, you are admitting that you have no penis.
    7. 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 ^^)

    8. Re:Python uses lambda calculus? by Free+the+Cowards · · Score: 1

      I understand the reasons why lambdas are the way they are, but that doesn't make it any better. A shortcoming that's really difficult to overcome is still a shortcoming, just a justified one.

      --
      If you mod me Overrated, you are admitting that you have no penis.
    9. Re:Python uses lambda calculus? by ShatteredArm · · Score: 1

      lambda x:
      if abs(x) > 5:
      spam(x)

      I always do this:

      lambda x: {True: spam(x), False: somethingelse(x)}[abs(x) > 5]

      Also works for non-booleans as well.

    10. Re:Python uses lambda calculus? by msuarezalvarez · · Score: 1

      It's not a shortcoming: it is a design decision.

    11. Re:Python uses lambda calculus? by Free+the+Cowards · · Score: 1

      False dichotomy. It's a design decision on the part of the language designers and it's a shortcoming in my eyes.

      --
      If you mod me Overrated, you are admitting that you have no penis.
    12. Re:Python uses lambda calculus? by jonadab · · Score: 1

      If you're into functional programming, you probably want to steer clear of Python, not because you can't do any functional programming in Python (you can, somewhat) but because you Shouldn't. The general mindset in the Python community is that There's One Best Way To Do Everything, and as a general rule it is Guido's Way that is Best. Guido's Way, it should be noted, is pretty much always Object Oriented, whether that's actually a good fit for your particular programming task or not.

      This doesn't make Python a bad language, necessarily. Some tasks are a good fit for Object Oriented programming and can be nicely implemented The Right Way in Python.

      But if your main thing is functional programming, Python is not a very good fit for that. Learn Haskell or something instead.

      Perl6, if it ever actually gets finished, is going to be really excellent for functional programming. I haven't checked on its progress lately, but the last time I did it was still a long way from done.

      Perl5 has some FP support (e.g., you can do sling around anonymous functions and lexical closures), but it doesn't go all the way. The OO support is similarly limited. The good news is you can freely intermix them and they actually work together very well, which is nifty.

      Ruby is said to have some FP support, but I don't know enough about it to comment beyond that. (It's on my TODO list, but right now there's a natural language taking up my language-learning time, so any new programming languages are on the back burner.)

      --
      Cut that out, or I will ship you to Norilsk in a box.
    13. Re:Python uses lambda calculus? by steveha · · Score: 1

      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,

      I'd like to call attention to this point, since everyone but you seems to have missed it.

      In Python, lambda expressions are so limited that they are really only useful for trivial purposes. People have asked Guido to improve lambda, but he hasn't. My understanding is that Python's parser somehow makes it hard to parse a multi-line lambda.

      The solution is very easy, however.

      The purpose of lambda is to create an anonymous function object, often with a closure. Well, in Python, it's trivial to create a function object by declaring a function; you can declare a function anywhere, including in a nested scope, and you can make closures. The only thing you can't do is declare a function with no name. So all you really need is a coding convention, such as: every function I wish was a lambda function will be called "anon_fn".

      Here's an example. We want to make a function that returns anonymous function objects that are adders: we will pass in a value x, and we want our adder function objects to remember that x, add it to some number n, and return the result. Once we have make_adder() we can make as many anonymous adder function objects as we wish.

      def make_adder(x):
      def anon_fn(n):
      return x + n
      return anon_fn

      The above example is trivial enough you could do it with a lambda:

      def make_adder(x):
      return lambda n: x + n

      But I prefer the Python version. In fact, I wouldn't actually use "anon_fn" as the name, I'd probably call the function "adder" and say "return adder".

      def make_adder(x):
      def adder(n):
      return x + n
      return adder

      make_adder() creates a function object. For a little while, inside make_adder(), this function object is bound to the name "adder", but that binding vanishes when make_adder() returns. The function object is returned, and now it's anonymous.

      So, to me the interesting question is not "when will Python get multi-line lambda?" To me, the question is "Why is it so important to be able to make a function that never was bound to a name for even a moment?" This isn't a flame, I'm actually wondering why this seems like such a big deal to so many people.

      P.S. As long as I'm beating the lambda horse, I might as well beat the closures horse as well.

      People argue that Python doesn't have "true" closures. I think it does, but the way it works may not be obvious.

      In Python, variables are really just names that have objects bound to them. If you think of the closure as the name, then closures are broken in Python. If you think of the closure as the object, not so broken.

      Here we want to make a function that returns anonymous function objects that are counters. Each counter function object should have an initial value, enclose that value, and when given a number n, add n to the current enclosed value and return the updated value.

      # this version seems reasonable but does not work
      def make_counter(initial_value):
      x = initial_value
      def counter(n):
      x += n
      return x
      return counter

      What's wrong here? The attempted closure is trying to use a name, "x", where Python needs an object. "x += n" really means "rebind the name 'x' with its previous value plus the value of 'n'". But when you enter counter(), the name x is not bound. Python will enclose the object bound to a name, but doesn't really keep the name binding part.

      --
      lf(1): it's like ls(1) but sorts filenames by extension, tersely
    14. Re:Python uses lambda calculus? by Anonymous Coward · · Score: 0

      Point of fact - calling Python lambdas "limited" is like calling water "flavourless". Python "lambdas" are in fact a lot less "limited" than the Church lambda functions for which they are named. A "lambda" that does two things is kind-of a contradiction in terms ;-).

    15. Re:Python uses lambda calculus? by Free+the+Cowards · · Score: 1

      A "function" that does two things is a contradiction in terms, and yet here we are....

      --
      If you mod me Overrated, you are admitting that you have no penis.
    16. Re:Python uses lambda calculus? by bnenning · · Score: 1

      To make this work, we need to pass in a "mutable" object, and then mutate the object and return the new value. To write this clearly, I like to use a class called "Obj" that simply returns a trivial class instance, and then I can set member variables (with names! that stay bound!).

      Sure, that works. It's still a kludgey workaround that results in you doing part of the compiler's job. And if I wanted to babysit the compiler all day, I'd be using Java. (ducks)

      To me, the question is "Why is it so important to be able to make a function that never was bound to a name for even a moment?" This isn't a flame, I'm actually wondering why this seems like such a big deal to so many people.

      I wouldn't say it's critically important; it's a convenience, just like anonymous list and dict literals. Python doesn't *need* to allow "foo([x,y])" since you could always do "arg=list(); arg.append(x); arg.append(y); foo(arg)". But that needlessly complicates the code by focusing on irrelevant details. Likewise, if a function is only needed in one place (say, as a callback for a UI event), it's often both more convenient and readable to just stick it inline.

      --
      How to solve most of our problems: 1.Lots of nuclear plants. 2.Cure aging.
    17. Re:Python uses lambda calculus? by steveha · · Score: 1

      Sure, that works. It's still a kludgey workaround that results in you doing part of the compiler's job.

      Yet, it's the best I have come up with do to this in Python. I already stipulated that other languages (specifically, Lisp) are easier with respect to this.

      Do you have a better way to do it in Python? Or a way to change Python to make this easier... that might actually get accepted into Python? If not, you're just complaining. Which you are of course free to do!

      Likewise, if a function is only needed in one place (say, as a callback for a UI event), it's often both more convenient and readable to just stick it inline.

      You sound like you think it would be sort of nice to have, which is about where I am on this issue. But some people seem to really care about this.

      Python isn't perfect, but in my opinion it's about 95% of the way there and I'm willing to live with the warts (such as the closures hack I documented). I haven't found anything I like better than Python for high-level coding.

      steveha

      --
      lf(1): it's like ls(1) but sorts filenames by extension, tersely
    18. Re:Python uses lambda calculus? by bnenning · · Score: 1

      Do you have a better way to do it in Python? Or a way to change Python to make this easier... that might actually get accepted into Python?

      Nope. I prefer the array workaround myself; either way, it's not a big deal.

      If not, you're just complaining.

      Yup :)

      Python isn't perfect, but in my opinion it's about 95% of the way there and I'm willing to live with the warts (such as the closures hack I documented). I haven't found anything I like better than Python for high-level coding.

      Completely agreed. The only downside is that after learning Python I'm much more frequently annoyed with Java.

      --
      How to solve most of our problems: 1.Lots of nuclear plants. 2.Cure aging.
  17. Heuristic by DohnJoe · · Score: 1

    did you add the heuristic to first try and visit the (harder to reach) edge fields? Gives a nice speedup if I remember correctly...

    1. Re:Heuristic by pklinken · · Score: 1

      Glad to see you paid attention in class, dear brother.

  18. 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.
    1. Re:OMG by Anonymous Coward · · Score: 0

      Times have really changed since the 90's. My 3 year old daughter finds the solution every so often in a box of Cracker Jacks, licks it, and tattoo's it to the back of her hand.

  19. evolve or die by mkcmkc · · Score: 0, Flamebait

    Yawn.

    A good language needs to occasionally shed unneeded features, or it will ossify into an unusable mess. (This is why Perl is dying.)

    --
    "Not an actor, but he plays one on TV."
    1. Re:evolve or die by Anonymous Coward · · Score: 2, Informative

      Yawn.

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

    2. 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.

    3. Re:evolve or die by renoX · · Score: 1

      Of course, the unmaintability of Perl's program has nothing to do with the ~#~#*#\@ design of the language itself, it must be the developpers.

      Same thing for APL surely?

      Face it: the language design have some consequence in maintainability.

    4. 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
    5. Re:evolve or die by LarsWestergren · · Score: 1

      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.

      I actually prefer Ruby for that sort of stuff, but maybe that's just me. ;)

      --

      Being bitter is drinking poison and hoping someone else will die

    6. Re:evolve or die by RightSaidFred99 · · Score: 1

      Yeah, a web templating system is indeed a small application. You don't actually think Amazon uses large Perl applications to run their business systems, do you?

    7. Re:evolve or die by RightSaidFred99 · · Score: 1

      That's exactly my point. Perl was developed for specific purposes. It's extremely effective when used for those purposes. When used beyond its scope it is far less effective. This is because of the language design - it's not meant to be maintainable in large systems.

      Conversely, it _can_ be maintainable. It's just that most "perl hackers" have no concept of this, and tend to want to use every obscure syntax of the language to make the program more terse. A good programmer (who may or may _not_ be a good perl hacker) can write reasonably maintainable programs in perl.

    8. Re:evolve or die by crucini · · Score: 1

      I've worked on both good and bad Perl. Perl's sigils are not an issue; neither are Lisp's parentheses or Python's whitespace. These things cease to annoy once you spend some time with the language.

      The reason there's a lot of bad Perl is the reason there's a lot of bad PHP: both languages enable beginning programmers to get things done.

  20. Least.. Readable.. Code.. Ever... by mkcmkc · · Score: 1

    Good grief! That has to be the most unreadable blob of code I've ever seen...

    Here's a taste of a relatively readable part:

    Cell[CellGroupData[{

    Cell["\<\
    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];
    \t
    \tendMoves = If[end != {}, If[IntegerQ[end[[1]]],{end},end], {}];
    \t
          \t area = (rows*columns) - Length[endMoves];
    \t
            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<x<sR, \
    y_/;0<y<sC}], endMoves];

    --
    "Not an actor, but he plays one on TV."
  21. Imagine... by DiLLeMaN · · Score: 0

    ...a beowulf cluster solving this puzzle.

    Actually, to go beyond mere meme-tossing: solving a knight's tour for a really large board with a beowulf... how would you do that?

    --
    /var/run/twitter.sock is a twitter socket puppet.
  22. ...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
    1. Re:...and then there's APL by v4vijayakumar · · Score: 1

      APL has been called a "write-only language".

      write-only..? how about execution..? ;)

    2. Re:...and then there's APL by Anonymous Coward · · Score: 0

      I think every language has been called "write-only" by someone. Usually someone who stopped learning the language when they knew enough of it for the task at hand, then encountered code written by someone who had learned more of it.

      For a language to deserve the "write-only" label, "typical" code needs to be incomprehensible even to someone who understands the language from top to bottom. The main factor is whether the meaning of a particular sequence of tokens can vary enormously depending upon context (e.g. the types of variables or, worse, the way in which the expression's value will be used).

    3. Re:...and then there's APL by shking · · Score: 1

      Execution? Do you mean execution of the program or the execution of Ken Iverson? You're too late for the latter... he died in 1984, at the age of 83.

      --
      -- "At Microsoft, quality is job 1.1" -- PC Magazine, Nov. 1994
    4. Re:...and then there's APL by Anonymous Coward · · Score: 0

      I would like to se it in Brain F**k =)

  23. 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

  24. Doing it without CS teaching? by jonaskoelker · · Score: 1

    It isn't anything special in particular. What _is_ special is doing it without receiving the instruction first.

    I think reinventing the wheel is a good thing in some situations; one is when you reinvent the wheel to study it but not use it. Another is when you reinvent the wheel without having been shown what a wheel is and how it works.

    It's a sign that you can think for yourself and come up with good solutions to the problems you want to solve independent of instruction.

    1. 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.
    2. Re:Doing it without CS teaching? by MikeBabcock · · Score: 1

      You should post them on Slashdot instead so you can feel low and stupid :-) I hear its great for your self-esteem.

      --
      - Michael T. Babcock (Yes, I blog)
  25. no backtracking by Dulimano · · Score: 1

    There is something about the OP's algorithm that I'm not sure he realized: It never backtracks. The 'choose the loneliest' method works even when applied in a greedy fashion. I did the following patch to artificially make the backtrack codepath run:

    Changed the
    key=lambda c: reduce(
    part to
    key=lambda c: random.random()*3+reduce(

    This means that the 'choose the loneliest' rule is broken sometimes. Backtracking is able to correct these mistakes sometimes, mostly if they did not happen too early in the search.

    1. Re:no backtracking by nneonneo · · Score: 1

      It does. Run it with a value of 163 or higher.

    2. Re:no backtracking by Dulimano · · Score: 1

      You are right. But it is a bit more complicated than that. For n less than 100, these are the values where the greedy method fails: 41,52,59,60,66,74,79,87,88,94,98. So, supposedly these are the values where backtracking helps. Unfortunately, in practice, it does not help at all: For these, the backtracking version of the algorithm does not terminate in a reasonable amount of time.

      An interesting question: The OP's implementation does not really care about how to break ties when it chooses the move with the best value. My list above depends on the implementation details. Wolfram MathWorld talks about n less than 76, not n less than 41, so maybe they know about a different implementation. Is there a local tie-breaking rule that leads to a successful greedy algorithm for all values of n?

    3. Re:no backtracking by nneonneo · · Score: 1

      This probably doesn't work for all values, but breaking ties by choosing the square farthest from the center substantially increases the effective range of the algorithm. I haven't yet found out how far it goes, but it seems to hold up all the way to 450x450.

  26. 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 ]
  27. 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.
    1. Re:I had to solve it in C by Anonymous Coward · · Score: 1, Interesting

      See also this sudoku solver
      http://www.youtube.com/watch?v=q1I7WKncE64

    2. Re:I had to solve it in C by Anonymous Coward · · Score: 0

      Did you try that for boards > 76x76?
      According to this : "The time needed for this algorithm grows roughly linearly with the number of squares of the chessboard, but unfortunately computer implementation show that this algorithm runs into blind alleys for chessboards bigger than 76Ã--76, despite the fact that it works well on smaller boards (Roth)"

    3. Re:I had to solve it in C by Alsee · · Score: 1

      The above linked video is nearly an hour long.

      He takes nearly the first half of that time before making grand announcement that the data structure will be... drumroll please... an 81 element array! He then lays out the top level design of a dumb-as-rocks guess-and-recursion approach, leaving several parts as homework, like testing weather placing a particular number in a certain spot would be legal. If you don't know enough programming to to fill in those details yourself, the video won't tell you how. If you do know enough programming that you *could* manage to write the most basic dumb-as-rocks guess-and-recursion sudoku solver on your own, you won't learn anything from the video.

      If you are ok with the basics of programming and manipulating arrays and know what recursion is, but you have no idea how to attempt a sudoku solver, then skipping to somewhere around the halfway point in the video and watching the rest might be worthwhile.

      -

      --
      - - You can't take something off the Internet! That's like trying to take pee out of a swimming pool.
  28. Python??? Try it getting that speed in Java. by mongoose(!no) · · Score: 1

    I love python, I use it all the time now, but back in high school, for AP Computer Science (I was the first class to take the Java AP test), we had to implement a recursive algorithm in Java to do it. It was fast, and could solve the problem for whatever size board we wanted. We found that a few board sizes were impossible.

    Anyhow, what's the point? I didn't think this was a hard problem at all when we did it.

  29. sum instead of reduce by pinkpuppy · · Score: 1

    Can't you replace the call to reduce(lambda x,y: x+y, ...) with sum(...)?

    1. Re:sum instead of reduce by pinkpuppy · · Score: 1

      Actually, the sum and map is better replaced with len and filter

      key=lambda c: len(filter(lambda j: InRangeAndEmpty(c[0]+j[0], c[1]+j[1]), jumps))

    2. Re:sum instead of reduce by nneonneo · · Score: 1

      Better yet, replace the whole thing with a generator expression wrapped in sum, thus removing map and the temporary array:

      key=lambda c:sum((int(InRangeAndEmpty(c[0]+j[0], c[1]+j[1])) for j in jumps))

      int(bool) turns True into 1 and False into 0, and is more readable than "and 1 or 0" (better yet, use the Python 2.5 conditional "1 if InRangeAndEmpty(...) else 0").

      I rewrote the code using a stack, to see how far it could get. It does 162x162 in linear time (w.r.t. the number of squares) and then, at 163x163, it abruptly stops being fast, as it begins to perform heavy backtracking -- it fails to fill in a region near the top-right corner. Hence, the heuristic (as written) is not powerful enough for all grids.

    3. Re:sum instead of reduce by maxume · · Score: 1

      Or a generator expression and sum.

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

      It might be even better to have a function called CountValidJumps or count_valid_jumps and pass that to the sort.

      --
      Nerd rage is the funniest rage.
  30. He mixed tabs and spaces by Anonymous Coward · · Score: 2, Interesting

    Not cool.

  31. A few lines of Mathematica by NSRaffy · · Score: 1

    ClearAll[solve, jump];
    $Jumps = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
    solve[n_] := (ClearAll[board]; Catch[jump[1, 1, 1, n]]; Array[board, {n, n}]);
    jump[x_, y_, z_, n_] /; 1 <= x <= n && 1 <= y <= n && ! ValueQ[board[x, y]] := (
       board[x, y] = z;
       If[z == n^2, Throw[1]];
       jump[x + #1, y + #2, z + 1, n] & @@@ $Jumps;
       board[x, y] =.;
       );
    Block[{$RecursionLimit = Infinity}, solve[5] // MatrixForm]

  32. stuff that matters by thc4k · · Score: 1

    seriously, is this "article" some bad joke?

    1. Re:stuff that matters by OrangeTide · · Score: 1

      Plenty of practical uses for this in graph theory.

      Although I'm not convinced that Python serves much practical purpose, like the 500 other trendy scripting languages out there. Perhaps when you ask "stuff that matters" you're only referring to Python? I'm not sure.

      --
      “Common sense is not so common.” — Voltaire
    2. Re:stuff that matters by k8to · · Score: 1

      Python is a language that you can write 98% of your code in. If that isn't practical, I'm not sure what is.

      You don't have to like it or use it, but it is a useful, pragmatic language. More so than most.

      --
      -josh
    3. Re:stuff that matters by OrangeTide · · Score: 1

      You can write 98% of your applications in any Turing complete programming language. Not sure why you'd choose a scripting language for it though.

      You don't have to use Python, nobody is forcing you to join the hype. There are plenty of languages out there that are easier, faster and more manageable. Some actually have useful object oriented features too.

      Python users will have to suffer my flames until they cease their unnecessary hypefest. You don't have to like it, but people will persist flaming Python, so you might as well learn to ignore it or reevaluate your personal choices.

      --
      “Common sense is not so common.” — Voltaire
    4. Re:stuff that matters by k8to · · Score: 1

      You misunderstood.

      Python is a good choice for 98% of programming tasks. Most languages are not easier nor mor more managable. Most are faster. Python has useful object oriented features.

      You seem to be willing to comment on Python without knowing much about it. I guess I should learn to ignore ignorant commentary, you're right.

      --
      -josh
  33. 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 HateBreeder · · Score: 1

      And here's the ruby version:

      print "I ate %d %s in %.3f seconds" % [99,'hotdogs',62.0895]

      Notice the difference?

      --
      Sigs are for the weak.
    2. Re:printf by Anonymous Coward · · Score: 4, Funny

      No output, and your font is all wrong.

      *ducks*

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

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

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

      You misspelled puts? ;-D

    5. Re:printf by raynet · · Score: 1

      And PHP version:


      printf('I ate %d %s in %.3f seconds', 99, 'hotdogs', 62.0895);

      --
      - Raynet --> .
    6. Re:printf by MikeBabcock · · Score: 1

      No no, observe:


      data = {'name': 'hdon', 'uid': 1104251}
      print "by %(name)s (%(uid)d)" % data

      Now ^ that's sexy. Dictionary handling in strings (that works for any string literal, anywhere in your code).

      --
      - Michael T. Babcock (Yes, I blog)
    7. Re:printf by godefroi · · Score: 1

      Yeah, I noticed:

      Console.Write("I ate {0} {1} in {2:f3} seconds", 99, "hotdogs", 62.0895);

      --
      Karma: Poor (Mostly affected by lame karma-joke sigs)
  34. 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 OrangeTide · · Score: 1

      Just change your coding style to have the { on the same line as if and for, which is a popular style, and you've done it.

      --
      “Common sense is not so common.” — Voltaire
    2. Re:I hope a firehose exploit was involved. by Anonymous Coward · · Score: 0

      You aren't forced to put brackets on new lines. (I prefer not to on almost everything except top-level blocks.)

    3. Re:I hope a firehose exploit was involved. by Solarhands · · Score: 1

      Or we could just let the code be easy to read since that's a major advantage of C++.

    4. Re:I hope a firehose exploit was involved. by rolfyone · · Score: 1

      noone forces you to put your open braces on the following line...

      that saves you at least 6 lines by my count :)

      noone forces whitespace in between statements - there's another 8(ish) lines.

    5. 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é
    6. Re:I hope a firehose exploit was involved. by Anonymous Coward · · Score: 0

      You can put that all on one line! :)

    7. Re:I hope a firehose exploit was involved. by 7+digits · · Score: 1

      That is C++, not C.

      You can have void main(), and save the "return 0;" line

      That'll get you to 61. But for any further improvment, I have no idea...

    8. Re:I hope a firehose exploit was involved. by wirelessbuzzers · · Score: 1

      Point taken, but he did also implement the heuristic, usage message, etc as part of the 60 lines.

      --
      I hereby place the above post in the public domain.
    9. Re:I hope a firehose exploit was involved. by Vexorian · · Score: 0, Troll
      I did implement the heuristic, I could implement the usage message: (coutStill I lost :( This demonstrates something:
      • python = no brackets = less lines = easier to refactor than c++ ...
      --

      Copyright infringement is "piracy" in the same way DRM is "consumer rape"
    10. Re:I hope a firehose exploit was involved. by Anonymous Coward · · Score: 0

      just in case anyone missed it there are more than 2 blank lines in there, and plenty of opportunity for stacking code on the same line.

      original code page has been "slashdotted" but it sounds to me like c++ did it in less lines :P
      (and will almost certainly run faster)

    11. Re:I hope a firehose exploit was involved. by Anonymous Coward · · Score: 0

      My little optimization . . . make the board slightly larger and premark those squares as visited. Take that, Nick!

    12. Re:I hope a firehose exploit was involved. by maxwell+demon · · Score: 1

      You can save the return 0; line, but you cannot have void main(). In C++, falling off main without return statement is equivalent to returning 0. (That's a special rule for main, not applicable to any other C++ function.) However, according to the C++ standard, a compiler which lets you write void main() without at least giving a warning is not conforming (but then, most compilers are non-conforming anyway because they don't implement export :-)).

      --
      The Tao of math: The numbers you can count are not the real numbers.
    13. Re:I hope a firehose exploit was involved. by rolfyone · · Score: 1

      My point was mainly that the pseudo standard for coding is 1 statement per line, and most people accept that.

      The grey area is whitespace (phrasing) and where brackets go...

      Anyway, ultimately yes at the end of the day i agree 100% with your assessment of 'measurement of complexity'.  It's a simple measurement,  but means very little.  You can see less than 60 lines cripple a computer, and sometimes you can see 100 000 lines of very efficient code, and people count comments as 'lines of code', and includes etc, which is terribly inaccurate.

      Better to look at algorithm complexity, but then python peeps can't go saying 'python is the best!'.

      The fact of the matter is python has no real advantage over other languages with a problem like this.  Every language has strong points, and if you want to show why a language is awesome you need to look at what the languages strengths are...  This specific problem is in no way playing to pythons strengths, it's just a procedural problem that can be implemented in almost any language in an efficient way (all the statements in py that were used map to or are in other languages).

    14. Re:I hope a firehose exploit was involved. by OrangeTide · · Score: 1

      Take out namespace std; and add .h to the includes. And you suddenly have an easy to read C program.
      Also, there is nothing particularly superior between one style of curly braces and another. As long as it is consistent it seems a like a trivial thing to focus on, especially considering that the code you posted would still be crystal clear without any formatting at all.

      --
      “Common sense is not so common.” — Voltaire
    15. Re:I hope a firehose exploit was involved. by Vexorian · · Score: 1
      Wow, slashdot cut my message, I was trying to say something like this:

      I did implement the heuristic, I could also implement the usage message: (printf("Type n or 0 to exit\n") That's an extra line! But then again the python guy was not counting the two extra lines he used to call main, and I am also counting a lot of blank lines in my program while his python code seems to have been stripped of those.

      After that it comes the sarcastic remark about no brackets == less line, etc... I guess a certain guy with mod points just doesn't have talent for catching up sarcasm...

      --

      Copyright infringement is "piracy" in the same way DRM is "consumer rape"
    16. Re:I hope a firehose exploit was involved. by mebrahim · · Score: 1
      Actually it is 6 lines of code (G++ 4.3 needed to be explicitly included):

      1 #include <set>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <cassert>
      5 #define valid(x,y) ((x>=0) && (x<N) && (y>=0) && (y<N) && (D[x][y]==-1 ) )
      6 using namespace std; int dx[8]={1,1,-1,-1,2,2,-2,-2}, dy[8]={2,-2,2,-2,1,-1,1,-1}; int D[50][50]; int N,C; bool show() { for (int i=N;i--;) { for (int j=N;j--;) cout<<"\t"<<D[i][j]; cout<<"\n"; } return true; } bool rec(int x, int y) { D[x][y]=C++; if(C==N*N) return show(); set< pair<int, pair<int,int> > > poss; for (int r=8;r--;) if(valid(x+dx[r], y+dy[r])) { int neighb=0; for (int t=8;t--;) neighb+= valid(x+dx[r]+dx[t],y+dy[r]+dy[t] ); poss.insert( make_pair(neighb, make_pair(x+dx[r],y+dy[r] ) )); } for (typeof(poss.begin()) q=poss.begin(); q!=poss.end(); q++) if (rec(q->second.first, q->second.second)) return true; D[x][y]=-1; C--; return false; } void solve(int n) { N=n, C=0; memset(D,-1,sizeof(D)); assert(rec(0,0)) ; } int main() { int n; while((cin>>n) && (n>0)) solve(n); return 0; }

      Hence KLoC sucks!

  35. 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).

  36. 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.
  37. Anonymous Coward by Anonymous Coward · · Score: 0

    Haskell solution, faster, shorter, uses less space.

    http://hpaste.org/12546

    Hooray for compilers.

    1. Re:Anonymous Coward by msuarezalvarez · · Score: 1

      See http://www.haskell.org/haskellwiki/99_questions/90_to_94 for the really obvious solution.

  38. 44 lines in commented and whitespaced C. by JoZZ · · Score: 1

    Timed with Debian on EEE 901 in HT mode (1.6 GHz Atom)

    real    0m0.726s
    user    0m0.724s
    sys     0m0.004s

    K&R (more or less), with tab-space=8 inside 79 cols. But commenting as original pyton (end of line commenting).

    -----
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int startx = 0, starty=0, size=0; /* The size of the thing, is set in main */
    /* How knights walk, changing this changes the time outcome :) */
    int jumps[][2] = {{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}};

    int walk(int *board, const int x, const int y, const int step)
    {
        board[x*size+y] = step; /* set our stamp here */
        if (step == size*size)
            return 1; /* Were done */
        for (int i=0;i<8;++i) { /* for each type of jump */
            int xx = x + jumps[i][0], yy = y + jumps[i][1]; /* set new position */
            if (xx < 0 || yy < 0 || xx >= size || yy >= size || board[xx*size+yy])
                continue; /* outch. been there or outside*/
            if (walk(board, xx, yy, step + 1))
                return 1; /* were finished, just return*/
        }
        board[x*size+y] = 0; /* we could not walk anywhere, reset and ... */
        return 0; /* move back indicating failure */
    }

    void draw(const int *board, int x, int y) /* Draw the board */
    {
        for (int i=0;i<size*size;++i) {
            printf(" %4d", board[i]);
            if (((i+1) % size) == 0)
                printf("\n");
        }
    }

    int main(int argc, char *argv[])
    {
        if (argc != 2 || ((size = atoi(argv[1])) == 0)) /* get size */
            return printf("use: %s <size>\n", argv[0]) + 1;
        printf("Board of size %dx%d\n", size, size);
        unsigned int board[size*size]; /* Alloc space for board */
        memset(board, 0, sizeof(int) * size * size); /* clear space */
        walk(board, startx, starty, 1); /* Start at defined start position */
        draw(board, -1, -1); /* Draw board that is done */
        return 0; /* Yay, done */
    }

    1. Re:44 lines in commented and whitespaced C. by Anonymous Coward · · Score: 0

      Now implement this so it weights its choice of move based on the least lonely of neighbors as the lambda and map functions do in the final version of the python code... Writing a simple recursive loop in C was never the challenge he was presenting. Also I think you'll find this runs significantly slower on a 100x100 board...

    2. Re:44 lines in commented and whitespaced C. by LanceUppercut · · Score: 1

      This is, of course, not even remotely K&R. The size of the board array is a run-time value, which immediately makes it C99. Also, since you were trying to be brief, why not use the aggregate initializer in the borad array (' = { 0 }'), instead of doing the memset hack?

  39. 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.

  40. /me waits for the 1-line J version. by toby · · Score: 1

    Memo to OP: Never, never, brag how short your code is, especially if you're using something as bloated as Python.

    There's always a more concise way. And a faster way.

    You're just asking for a beating, and well-deserved.

    --
    you had me at #!
  41. Here it is in 30. by TheMCP · · Score: 1

    > Try beating this, fellow coders!

    Here it is in 30 lines of Water. Oh, and it outputs in HTML.

    <class knights_tour size=8 board=opt >
        <method make> .<set board=.size.<for_each combiner=insert> .size.<for_each combiner=insert> false </for_each> </for_each> /> .<fill/>
            _subject
        </method>
        <method in_range_and_empty x=req y=req>
            <and .board.<has y/> .board.<get y/>.<has x/> .board.<get y/>.<get x/>.<not/> />
        </method>
        <method fill x=0 y=0 counter=0> .board.<get y/>.<set <do x/>=counter/>
            <if>
                counter.<is_not .size.<times .size/> />
                    <v <v -2 1/> <v -1 2/> <v 1 2/> <v 2 1/> <v 2 -1/> <v 1 -2/> <v -1 -2/> <v -2 -1/> />.<for_each>
                        <set new_y=y.<plus value.0/> new_x=x.<plus value.1/> />
                        <if> .<in_range_and_empty x=new_x y=new_y/> .<fill x=new_x y=new_y counter=counter.<plus 1/> /> </if>
                    </for_each>
            </if>
        </method>
        <method htm_inst>
            <set a_table=<table border=1/> /> .board.<for_each>
                <set a_row=<tr/>/>
                value.<for_each> a_row.<insert <td value/>/> </for_each>
                a_table.<insert a_row/>
            </for_each>
            a_table
        </method>
    </class>
    <knights_tour/>

    (My formatting is getting messed up. Should be 30. It's merging a few lines in the preview, but not in a way that would break anything.)

    1. Re:Here it is in 30. by msuarezalvarez · · Score: 1

      Urgh. That's an absurdly ugly language!

    2. Re:Here it is in 30. by TheMCP · · Score: 1

      That's what I thought about the Python example. I find Water to be very readable. But seriously, would you rather type a few angles, or write twice as much code? Every language has admirers and people who think it's ugly, the really important part is whether it facilitates programmers to get things done.

      It is, however, unfortunate that my line breaks got messed up. It should be slightly more readable than it shows. Also, to be honest, the line breaks and indentation are largely gratuitous, the parser generally ignores them. I could have made this "knight's tour in one line of Water" but it would have been a stupidly long line; I tried to put in logical line breaks to show a realistic scenario to compare to the Python example.

      And I forgot to mention, it runs in about two seconds on the interpreter, it should run an order of magnitude faster when compiled but I don't have the compiler installed at the moment.

    3. Re:Here it is in 30. by msuarezalvarez · · Score: 1

      I am sorry, but while python's beauty (or haskell's, or lisp's, or C's or whatever's beauty) is surely in the eyes of the beholder, that code you wrote is simply a product of a misunderstanding of the purpose and utility of SGML/XML notation.

      You should read about MUMPS. I guess you'll also enjoy it. It's another of those I-cannot-believe-they-are-serious syntaxes.

    4. Re:Here it is in 30. by TheMCP · · Score: 1

      It's not XML notation: XML is ambiguous in far too many ways, and was never intended for anything but markup. Water can be expressed in pure XML, but is usually written in ConciseXML, as was my example.

      And last I heard MUMPS had been renamed to "M". (Somebody should teach it to Judi Dench...) While you discount it, I know that companies that use it are very happy with it, and I'm told by people who work with it that it's very effective for handling data for the health care industry, which is what it's designed for.

      Computers are tools for getting stuff done, so I question your focus on whether or not the code is pretty over the fact that the code accomplishes the task in half the effort. (And I could knock off a few more lines if I want to work on it, I think.)

  42. Try Haskell by jamesswift · · Score: 1

    No idea how to do it but I'm seeing a pattern in these arguments.

    --
    i wish i could stop
  43. Pretty poor language, if it makes you think... by CarpetShark · · Score: 1

    It's a pretty poor language, if if makes its users confuse code that calls external modules with actual implementations.

  44. Cache of the Pages by ExtremePopcorn · · Score: 1

    The site is down, but here are some links from Google's cache: http://74.125.95.132/search?q=cache%3Attsiodras.googlepages.com%2Fknightstour.html http://74.125.95.132/search?q=cache%3Ahttp%3A%2F%2Fttsiodras.googlepages.com%2Fyield.html That's all I could get, I'm sorry. Apparently Google doesn't cache Python documents.

  45. someones solution in ruby... by rolfyone · · Score: 1

    http://rubyquiz.com/quiz27.html

    quite a nice solution in ruby - if you took the commenting out, it'd be pretty short...

    full credit to the owner of the page for the solution, i just figured someone would have a nice solution in ruby, and this came up through google.

  46. 1 line from the future (.NET 4.0) by saddino · · Score: 2, Funny

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

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

    But does it work with 3 dimensional chess?

  48. This is why Python zealots cannot be trusted :) by Anonymous Coward · · Score: 0

    Here's a C++ soution, coded in 25 minutes, using a much faster algorithm. It solves all sizes NxN 5<=N<=100 under a second, all sizes up to 1000x1000 in 12 seconds, a single 5000x5000 in 3 secs, and a 10,000x10,000 board in 12 seconds (all on my decent PC). I'd like to see the python version do that. Not only does this solve the original posters problem of doing the problem in less than 3 times the number of lines he used, it does it in less code than the original poster entirely and executes in drastically less time with no stack overflows.

    It's on :)

    // Chris Lomont, 2008, Knight Tour using Roth extension of Warnsdorff Algorithm
    // Solves NxN for 5<=N<=1000, N=5000, N=10000 (and others - check solutions)
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;

    void Solve(int n, bool show)
        {
        vector<int> board(n*n);
        for (int i = 0; i < n*n; ++i) board[i] = 8;
        for (int i = 2; i < n-2; ++i) {
            board[i] = board[n*n-i-1] = board[n*i] = board[n*i+n-1] = 4;
            board[i+n] = board[n*n-i-1-n] = board[n*i+1] = board[n*i+n-2] = 6; }
        board[0] = board[n-1] = board[n*n-1] = board[n*n-n] = 2;
        board[1] = board[n-2] = board[n] = board[2*n-1] = 3;
        board[n*n-2] = board[n*n-n+1] = board[n*n-n-1] = board[n*n-2*n] = 3;
        board[n+1] = board[2*n-2] = board[n*n-n-2] = board[n*n-2*n+1] = 4;
        int moves1[] = {2,-1,1,-2,-1,-2,-2,-1,-2,1,-1,2,1,2,2,1,  2,-1,1,-2};
        int * moves = moves1;
        int bad[] = {11,261,352,379,526,744,753,983,10000};
        if (find(bad,bad+9,n) != bad+9)
            moves+=2;
        int xpos = 0, ypos = 0, depth = 0;
        while (depth++ < n*n) {
            board[xpos*n+ypos] = -depth; // makes move
            int best = n*n, fx = xpos, fy = ypos;
            double dist = -1;
            for (int m = 0; m < 16; m += 2) {
                int nx = xpos + moves[m], ny = ypos + moves[m+1];  // next move
                if ((0 <= nx) && (nx < n) && (0 <= ny) && (ny < n) && (board[nx*n+ny]>=0)) {
                    --board[nx*n+ny];
                    double dx = nx-(n-1)/2.0, dy = ny - (n-1)/2.0;
                    if  (((board[nx*n+ny] <= best) && (dx*dx + dy*dy >= dist)) || (board[nx*n+ny] < best)) {
                        best = board[nx*n+ny];
                        dist = dx*dx+dy*dy;
                        fx = nx, fy = ny; } } }
            xpos = fx; ypos = fy; }
        if (show)
            for (int j = 0; j < n; ++j) {
                for (int i = 0; i < n; ++i) {
                    cout.width(3);
                    cout << -board[i+j*n] << ' '; }
                cout << endl; }
        }  // Solve

    int main(void)
        {
        Solve(8,true);
        for (int n = 5; n <= 1000; ++n)
            Solve(n,false);
        }

    1. Re:This is why Python zealots cannot be trusted :) by grikdog · · Score: 1

      Nice, thanks! Wish I had mod points to bump this up a notch or two.

      --
      ``Tension, apprehension & dissension have begun!'' - Duffy Wyg&, in Alfred Bester's _The Demolished Man_
  49. 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.

  50. How long to write it? by DavidHumus · · Score: 1

    This is the question techies never want to talk about though it's often more relevant than how quickly it runs. Here's a solution in J in fewer than 20 lines: http://www.jsoftware.com/jwiki/Essays/Knight's_Tour .

  51. Lua by Samah · · Score: 1

    Here's a working (although somewhat messy) implementation in Lua. I could probably optimise performance and/or LoC, but that's another exercise. :)
    It accepts an optional size parameter (defaults to 8), prints out the running time, and the solution if it's <= 16x16.
    http://pastebin.ca/1272049

    Running times on Ubuntu Feisty 32-bit on a P4 2.8:
    8x8 = 0.000s, or thereabouts...
    100x100 = 0.400s
    200x200 = 1.740s
    300x300 = 3.950s
    400x400 = 7.040s
    500x500 = 10.080s
    600x600 = 15.240s
    700x700 = 20.180s
    800x800 = 33.670s
    900x900 = 42.580s
    1000x1000 = 53.480s
    10000x10000 = ...still going :)

    --
    Homonyms are fun!
    You're driving your car, but they're riding their bikes there.
  52. 11 lines of code by slashnot007 · · Score: 1


    Nwide = 5
    def check_path(board,i1,i2,x,y,n):
        if board[x+i1][y+i2]<n: return False
        board[x+i1][y+i2] = n
        for j1,j2 in [ (1,2),(1,-2),(2,1),(2,-1),(-2,1),(-2,-1),(-1,2),(-1,-2) ] :
              if n==Nwide*Nwide-1 or check_path(board,j1,j2,x+i1,y+i2,n+1): return True
        board[x+i1][y+i2] = Nwide*Nwide+1
        return False
    for ii,jj in [ (i,j) for i in xrange((Nwide+1)/2) for j in xrange(i,(Nwide+1)/2) ]:
        board0 = [[  Nwide*Nwide+1 if  i >1 and i< Nwide+2  and j >1 and j<Nwide+2 else 0 for i in xrange(Nwide+4)] for j in xrange(Nwide+4) ]
        if check_path(board0,0,0,ii+2,jj+2,0) : print [ j[2:-2] for j in board0[2:-2] ]

    This is not speedy however.  It also does not take advantage of any symmetry assumptions other than the initial placement of the first move is restricted.

  53. Yup by Gazzonyx · · Score: 1

    [...]Every time I try to do something in C++ now, I feel like I'm spending more time on defining types than on solving the problem.

    That's actually the point of OOP. You shouldn't be 'forcing' anything to happen the way you would with a functional language. The point of OOP (pure object oriented programming... we're talking ivory tower for the moment) is that you define your objects and then define how they should interact with each other and then put the 'glue' in to interface them to each other on events.

    You pay more time up front to define the model and interactions for increased development speed as you move 'up' your interface stack. Done correctly, you should also have less edge cases and a more flexible framework because you've broken down your problem in to many, many smaller generic problems which have an encapsulated object that deals with them and other objects that can interface with first said object.

    The vast majority of single use code/quick fixes don't really need to be programmed in an OO language; but it pays off exponentially once you start getting over a few thousand lines of code. Like everything else in software development, there is no silver bullet, every project is unique, there usually isn't a single correct way to do something, but if you find yourself trying to screw in a lightbulb with a hammer, you're doing it the wrong way. Use whatever works for you that doesn't leave you muttering "... there must be a better way to do this!"

    --

    If I mod you up, it doesn't necessarily mean I agree with what you've said, sorry.

  54. 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.
  55. Reinventing A* by Anonymous Coward · · Score: 0

    Problems of this kind (search problems) are generally all about the big-Oh complexity of the solution. The "naive" approach described in the OP's link is a depth-first or brute-force search; prioritizing the search (in any way) makes it a breadth-first search. Usually the problem is all about finding the correct priority function.

    So for the most part, one's choice of language is arbitrary. Most of the work is done with pen and paper. Choice of language? Go with what you know - but also make an effort to know a little more every day, please! These "C++ vs Python" or "Java vs C#" arguments are at best amusing and at worst painful to watch.

    1. Re:Reinventing A* by omuls+are+tasty · · Score: 1

      It's not A*, A* deals with finding a path to the goal while minimizing the cost. There's no "cost" inherent to the Knight's Tour - all solutions are equal. It makes much more sense to model it as a constraint satisfaction problem (CSP).

      Also, "prioritizing the search" doesn't make anything breadth-first, it makes it some kind of priority search. Generally, these graph searches tend to depend only on the underlying structure: stack for depth-first, queue for bread-first, and priority queue for priority searches. Changing the priority function yields different types of priority searches (Dijkstra, greedy best-first, A*, etc).

  56. i am not a programer but i can beat you by Anonymous Coward · · Score: 0

    program start
    new knigth;
    knigth.movearound();
    program end

    only 4 lines you are a pgrogramer and need 60....

  57. Re:Why is he so proud of a line count? by Anonymous Coward · · Score: 0

    Actually your code could be anywhere from 53 lines if you remove the blank lines, or 56 if you just write out show and solve in the places that they are used. But then you would sacrifice good coding practices. So the moral of this story:

    Lines of code are not what makes good code.

    And bandwidth limits will pwn you for free.
    (Silly OP use a real hosting server.I hear blogger is pretty good.)

    Also don't brag with conditions. It's quite lame.

    Not to be paternalistic, but allow me to suggest writing this sorting code in C (using qsort?), or in C++ using STL's sort algorithm.

  58. reminds me of... by penguinbroker · · Score: 1

    pretty cool, off topic but it made me think of peter norvig's sudoku solver which is about 100 lines of python code and can solve even the hardest puzzles in <.02 seconds. btw, brute force approaches to diabolical sudoku puzzles are not physically possible, follow link to find out why.

    python is fantastic for writing concise, functional, and simple solutions to many search problems.

  59. Just F'n Great... by Daswolfen · · Score: 1

    You do know this is how Skynet starts, don't you.

    Expect a visit from the Conner's and River Tam any day now.

    --
    Don't rush me, Sonny. You rush a miracle man, you get rotten miracles.
  60. my favourite small code by Anonymous Coward · · Score: 0

    2 lines of javascript to print out the fibonacci series:

    for(b=(a=0)+1;;b+=(a+=b))
    document.write(a+'
    '+b+'
    ');

    and only 1 line taking out the line breaks.

    funny how most languages you can make programs in one line - this whole "no semi-colon" smuggery of python has removed that feature

  61. 7 lines of python by duffel · · Score: 1

    xdim,ydim = map(int,__import__("sys").argv[1:])
    def recurse((position, visited)):
            map(recurse,[(t,visited+[t]) for t in (lambda t: [ (t[0]+2, t[1]+1), (t[0]+2, t[1]-1), (t[0]-2, t[1]+1), (t[0]-2, t[1]-1), (t[0]-1, t[1]+2), (t[0]-1, t[1]-2),(t[0]+1, t[1]+2),(t[0]+1, t[1]-2)])(position) if 0<=t[0]<xdim and 0<=t[1]<ydim and t not in visited])
            if len(visited) == xdim*ydim:
                    print "success: %s"%str(visited).strip("[]")
                    __import__("sys").exit()
    recurse(((0,0),[(0,0)]))

    example:

    python chess.py 5 5
    success: (0, 0), (2, 1), (4, 2), (3, 4), (1, 3), (0, 1), (2, 2), (3, 0), (1, 1), (0, 3), (2, 4), (4, 3), (3, 1), (1, 0), (0, 2), (1, 4), (3, 3), (4, 1), (2, 0), (1, 2), (0, 4), (2, 3), (4, 4), (3, 2), (4, 0)

    comment out line 6 to make it 6 lines of python that find all possible tours from (0,0)

  62. 4 lines of python by slashnot007 · · Score: 1

    def recurse((position, visited),xdim= int(__import__("sys").argv[1]),ydim= int(__import__("sys").argv[2])):
            map(recurse,[(t,visited+[t]) for t in (lambda t: [ (t[0]+2, t[1]+1), (t[0]+2, t[1]-1), (t[0]-2, t[1]+1), (t[0]-2, t[1]-1), (t[0]-1, t[1]+2), (t[0]-1, t[1]-2),(t[0]+1, t[1]+2),(t[0]+1, t[1]-2)])(position) if 0<=t[0]<xdim and 0<=t[1]<ydim and t not in visited])
            if len(visited) == xdim*ydim: print "success: %s"%str(visited).strip("[]"),__import__("sys").exit()
    for ii,jj in [ (i,j) for i in xrange((int(__import__("sys").argv[1])+1)/2) for j in xrange( (int(__import__("sys").argv[2])+1)/2) ]:  recurse(((ii,jj),[(ii,jj)]))

    This version also adds back the feature deleted in the 7 line version which tries all possible (non-redundant) starting positions.

  63. Monty anyone? by Anonymous Coward · · Score: 0

    Am I the only AC that read the slashy blurb and could only think of Flying Circus references? I clicked "Read More" expecting a litany of hilarious references to comedy of old, but instead I get nothing. NOTHING! Bah!

  64. Back to Basic by jweatherley · · Score: 1

    Sinclair BASIC bitches:

    5 REM program to use weighted grid memoir by Geoff Wearmouth.
    10 PRINT TAB 8;"Knight's Tour 4": GO TO 9000: REM initialize and run

    1000 REM recursive subroutine
    1010 IF x>8 OR x<1 OR y>8 OR y<1 THEN RETURN
    1020 IF b$(s,1)<>a$(y,x) THEN RETURN
    1030 IF SCREEN$ (20-y*2,2+x*3)<>" " THEN RETURN
    1040 PRINT AT 20-y*2,1+x*3; PAPER 5+((y+x)=INT ((y+x)/2)*2);(" " AND s<10); s
    1050 IF s=64 THEN PRINT AT 21,8;"SOLVED IN ";m; " MOVES" : STOP
    1060 LET s=s+1: LET b$(s)="23456789": LET m=m+1
    1070 LET x=x+x2: LET y=y+y1: GO SUB 1000: LET y=y-y1: LET x=x-x2
    1080 LET x=x+x2: LET y=y-y1: GO SUB 1000: LET y=y+y1: LET x=x-x2
    1090 LET x=x+x1: LET y=y+y2: GO SUB 1000: LET y=y-y2: LET x=x-x1
    1100 LET x=x+x1: LET y=y-y2: GO SUB 1000: LET y=y+y2: LET x=x-x1
    1110 LET x=x-x1: LET y=y+y2: GO SUB 1000: LET y=y-y2: LET x=x+x1
    1120 LET x=x-x1: LET y=y-y2: GO SUB 1000: LET y=y+y2: LET x=x+x1
    1130 LET x=x-x2: LET y=y+y1: GO SUB 1000: LET y=y-y1: LET x=x+x2
    1140 LET x=x-x2: LET y=y-y1: GO SUB 1000: LET y=y+y1: LET x=x+x2
    1150 IF b$(s)>="0" THEN LET b$(s)=b$(s,2 TO ): GO TO 1070
    1155 LET s=s-1 : REM obsolete backtracking path
    1160 PRINT AT 20-y*2,1+x*3; PAPER 8;"  "
    1170 RETURN

    9000 INPUT "x(1-8): ";x, "y(1-8): ";y : REM starting square
    9005 IF x>8 OR x<1 OR y>8 OR y<1 THEN GO TO 9000
    9010 LET x1=1-(2 AND (x>4)) : LET x2=x1*2
    9020 LET y1=1-(2 AND (y>4)) : LET y2=y1*2
    9030 BORDER 4: CLS : LET s=1: LET m=1
    9040 FOR i=19 TO 162 STEP 16: PLOT 28,i: DRAW INK 1;192,0: NEXT i
    9050 FOR j=28 TO 230 STEP 24: PLOT j,19: DRAW INK 1;0,127: NEXT j
    9060 DIM a$(8,8): DIM b$(65,8)
    9070 FOR i=1 TO 8: READ a$(i): NEXT i
    9075 GO SUB 1040

    9100 REM perfect weighted grid discovered by James Weatherley.
    9110 DATA "22433422"
    9120 DATA "35644653"
    9130 DATA "56788765"
    9140 DATA "36899863"
    9150 DATA "36899863"
    9160 DATA "56788765"
    9170 DATA "35644653"
    9180 DATA "22433422"

    From http://www.wearmouth.demon.co.uk/gw03/ktour.htm

    --

    --
    Reverse outsourcing: it's the future
  65. Time complexity ? by Anonymous Coward · · Score: 0

    Number of lines of code is absolutely a new type of complexity which is left out in "The art of programming".

  66. 12 LINES BABY by Anonymous Coward · · Score: 0

    HAI
    CAN I HAZ A PONIE?
    CAN I HAZ A CHEKERBORED?

    IM IN YR LOOP
      WIT TEH CHEKERBORED
      OMG PONIE! POOP!
      OMG PONIE! JUMP!
      IF PONIE FALL OR STEP IN POOP GO BACK PONIE
      IF POOP EVERYWARE KTHXBYE
      JUMP DIFFERENT PONIE
    IM OUTTA YR LOOP

    SHOW CHEKERBORED

    KTHXBYE

  67. 4+1 lines of python and faster by slashnot007 · · Score: 1

    this now includes the optimization of sorting the order that squares are checked by their number of neighbors.  the so-called lonely squares first the original 60 line code had.  For sanity this is implemented as an extra line of code defining a function.  But python-golfers could cut a stroke by unrolling that function definition into the two places it gets called.

    def neigh(p,visited,xdim,ydim):  return len( [1 for u in [ (p[0][0]+t[0],p[0][1]+t[1])  for t in [  (-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] ] if 0<=u[0]<xdim and 0<=u[1]<ydim and u not in visited ] )

    def recurse((position, visited),xdim= int(__import__("sys").argv[1]),ydim=
    int(__import__("sys").argv[2])):

            map(recurse,sorted([(t,visited+[t]) for t in (lambda t: [ (t[0]+2, t[1]+1), (t[0]+2, t[1]-1), (t[0]-2, t[1]+1), (t[0]-2, t[1]-1), (t[0]-1, t[1]+2), (t[0]-1, t[1]-2),(t[0]+1, t[1]+2),(t[0]+1, t[1]-2)])(position) if 0<=t[0]<xdim and 0<=t[1]<ydim and t not in visited],lambda x,y:cmp(neigh(x,visited,xdim,ydim),neigh(y,visited,xdim,ydim) )) )

            if len(visited) == xdim*ydim: print "success: %s"%str(visited).strip("[]"),__import__("sys").exit()

    for ii,jj in [ (i,j) for i in xrange((int(__import__("sys").argv[1])+1)/2) for j in xrange( (int(__import__("sys").argv[2])+1)/2) ]:  recurse(((ii,jj),[(ii,jj)]))

  68. Adventures in duck-typing by Alsee · · Score: 1

    Curious about duck-typing, I asked Google define:duck-typing. No results were found in English, but it did return a hit in the German Wikipedia. I had bookmarked Yahoo as my translation service page back before Google offered one, so I used that link to translate the webpage into English. The Wikipedia article opens with an English quote "When I see a bird that walks like a duck and swims like a duck and Quack like a duck, I call that bird a duck", which is then followed by the German translation of the phrase retranslated back into English. Ok, so far so good, duck-typing obviously enough is seems to follow some notion if an object has the property Quacks like a Duck then it is somehow treated as a Duck type or somesuch. So I'm reading the translation and fighting hard to follow the broken translation example they are using to illustrate how it works and what it means, and I crash head on into the striking phrase "also frogs can quaken". Okaaaaay. Quaken is cute, and frogs quacking is funny. I'm thinking they are deliberately making a Frog type that Quacks-like-a-Duck to make some special point about duck-typing. Completely by chance I then also happened to pull up the Google translation of the page. There I happen find "even frogs can croak" in the same spot. Whoah, waitaminute. So I go look at the original German text and find that it actually does use the word "quaken" there. The German text uses "quak" in the duck section and "quak" in the phrase with frog.

    So I've learned a few things.
    (1) Apparently Germans use the same word for the noise-a-duck-makes and for the noise-a-frog-makes.
    (2) Apparently Yahoo is not smart enough to translate "quak" as "croak" when a frog does it, and that that would have left me completely confused trying to understand the point being made by giving a frog a "Quacks like a Duck" property.
    (3) Apparently Google silently has the "smarts" to translate the single word "quak" as either quak for birds or croak for frogs, and that that would have also left me completely confused by how duck-typing is handling a croaking frog and why the frog is gaining the ability to croak.
    (4) I never would have figured out any of this if I hadn't randomly happened to pull up BOTH the Google and Yahoo translations.
    (5) Now that I have learned that German frogs also quack, I've learned that my brain is bent over the example they are using. What the fuck is the Frog supposed to represent in the duck-typing illustration? Does/doesn't the Frog quack like a Duck? Is/isn't/should/shouldn't the Frog be accepted as a Duck type, and what the fuck is that supposed mean? What the fuck relationship is Frog supposed/not-supposed to have with the Bird and Duck types?
    (6) The measure of information I have gained on duck-typing has actually been a negative number due to all of this. My brain now contains scar tissue on what was once pristine blank neurological storage space.

    And finally number (6) I learned:
    I
    QUIT

    Adventures in duck-typing.

    -

    --
    - - You can't take something off the Internet! That's like trying to take pee out of a swimming pool.
    1. Re:Adventures in duck-typing by tomhuxley · · Score: 1

      Try:

      define: "duck typing"

      You'll be pleased to hear that the English Wikipedia page doesn't mention frogs.

    2. Re:Adventures in duck-typing by atraintocry · · Score: 1

      Duck typing: "If it walks like a duck and quacks like a duck, call it a duck."

      IMO the description is funny, but not very illustrative. Python is both strongly typed (you can't add an integer to a string) as well as dynamically typed (no type declaration for names, only assignment).

      I'm just starting so I may have this wrong but I believe that in Python all names are just pointers to objects. It is these objects, like the number 5 or the string "5", that have type. The names do not care about type, nor do built-in language features, and by extension, the things you build out of them, unless you check for type yourself.

      For instance: "+" doesn't allow you to mix types because it doesn't want to guess whether you're adding or concatenating. But it is still essentially overloaded:

      >>> 5 + 5
      10
      >>> '5' + '5'
      '55'

    3. Re:Adventures in duck-typing by Tack · · Score: 1

      What you describe (that names are merely labels attached to objects) is more or less right, but doesn't capture what duck typing is.

      Duck typing is summed up neatly by contrasting two principles: LBYL (look before you leap) and EAFP (easier to ask forgiveness than permission). These catchy phrases nicely capture two different methods. Consider these examples (numbered 1 through 4):

      def square(value):
      .. if type(value) != int:
      ..... raise ValueError('Argument must be an int')
      .. return value**2

      def square(value):
      .. if isinstance(value, int):
      ..... raise ValueError('Argument must be an int')
      .. return value**2

      def square(value):
      .. try:
      ..... return value**2
      .. except TypeError:
      ..... raise ValueError('Invalid value passed')

      def square(value):
      .. return value**2

      (Sorry about the prepended dots, but Slashdot's ecode tag is lame.

      If you're used to statically typed languages, you may gravitate to the first two examples, but this is unpythonic. This tests that the type of the value passed is what you expect, and in doing so, prevents duck typing, because you can't pass it an object that acts like an int. (The second one is slightly better than the first, in that it will allow other objects so long as they are subclassed from int.)

      The third example is better still, but why bother catching the exception at all? In doing so, you're passing less information in the exception than if you'd just done nothing at all, which is what example 4 does. Example 4 is pythonic: it allows duck typing (anything that supports __pow__ can be passed), and if the value is invalid, the TypeError exception automatically raised will be informative.

  69. 4 lines of python and faster by slashnot007 · · Score: 1

    fixed logic bug. now 4 lines.

    This essentially proves that badly written python is almost as unitelligible as badly written perl.  Interestingly badly written python is easier to debug than badly written perl.  But then again perl-golf is played for characters not lines!  for example, bzip2 is done in 55 perl characters.

    def recurse((position, visited),xdim= int(__import__("sys").argv[1]),ydim=
    int(__import__("sys").argv[2])):

            map(recurse,sorted([(t,visited+[t]) for t in (lambda t: [ (t[0]+2, t[1]+1), (t[0]+2, t[1]-1), (t[0]-2, t[1]+1), (t[0]-2, t[1]-1), (t[0]-1, t[1]+2), (t[0]-1, t[1]-2),(t[0]+1, t[1]+2),(t[0]+1, t[1]-2)])(position) if 0<=t[0]<xdim and 0<=t[1]<ydim and t not in visited],lambda x,y:cmp(len( [1  for t in [  (-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]  if (x[0][0]+t[0],x[0][1]+t[1])  in visited ] ),len( [1  for t in [  (-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]  if (y[0][0]+t[0],y[0][1]+t[1])  in visited ] ))))

            if len(visited) == xdim*ydim: print "success: %s"%str(visited).strip("[]"),__import__("sys").exit()

    for ii,jj in [ (i,j) for i in xrange((int(__import__("sys").argv[1])+1)/2) for j in xrange( (int(__import__("sys").argv[2])+1)/2) ]:  recurse(((ii,jj),[(ii,jj)]))

  70. Knight's Tour iPhone app by Anonymous Coward · · Score: 0

    For those interested in playing the game, there is an iPhone version called Knight's Run available. (Currently $.99 US).

    Here's a link to it in the app store:
    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=287816855&mt=8

    I bought it, it's a nice workout for the neurons.

  71. 11 Line Java Solution - 5.5 milliseconds by KevinGlenRoyGreer · · Score: 1

    My Java solution can solve the 100x100 board in 5.5ms (on my 2.5GHz Intel Core 2 Duo laptop).  (Actually, it can solve the the 100x100 board 10,000 times in 55 seconds.)  I actually provide two solutions: a very small heuristic-less solution, and a longer one based on Warnsdorff's heuristic.

    /**
    * Knight.java
    * author: Kevin Greer
    * date: Dec 1, 2008

    Gives the following output for SIZE = 8

        1   50   15   32   61   28   13   30

       16   33   64   55   14   31   60   27

       51    2   49   44   57   62   29   12

       34   17   56   63   54   47   26   59

        3   52   45   48   43   58   11   40

       18   35   20   53   46   41    8   25

       21    4   37   42   23    6   39   10

       36   19   22    5   38    9   24    7

    **/
    public class Knight {
        static final int     SIZE = 100;
        static final int[][] b    = new int[SIZE][SIZE];
       static final int[][] M    = { {1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1} };

       static void displayBoard() {
          for ( int c = 0 ; c < SIZE ; c++ ) {
             for ( int r = 0 ; r < SIZE ; r++ ) System.out.print(String.format(" %4d", b[r][c]));
             System.out.println("\n");
          }
       }

        // Simple Heuristic-less solution
       static boolean s(int x,int y, int i) {
            if ( x < 0 || y < 0 || x >= SIZE || y >= SIZE || b[x][y] != 0 ) return false;
          if ( ( b[x][y] = i++ ) == SIZE * SIZE ) { displayBoard(); return true; }
            return s(x+2,y+1,i) || s(x+2,y-1,i) || s(x-2,y+1,i) || s(x-2,y-1,i) || s(x+1,y+2,i) || s(x+1,y-2,i) || s(x-1,y+2,i) || s(x-1,y-2,i) || ( b[x][y] = 0 ) == 1;
        }

       // Solution using Warnsdorff's Heuristic
        static boolean isGood(int x, int y) { return x >= 0 && y >= 0 && x < SIZE && y < SIZE && b[x][y] == 0; }
       static boolean solve(int x, int y, int i) {
            if ( ! isGood(x, y) ) return false;
          try {
             if ( ( b[x][y] = i++ ) == SIZE * SIZE ) { displayBoard(); return true; }
             int[] friends = new int[M.length];
                for ( int m = 0 ; m < M.length ; m++ ) if ( isGood(x+M[m][0], y+M[m][1]) ) for ( int m2 = 0 ; m2 < M.length ; m2++ ) if ( isGood(x+M[m][0]+M[m2][0], y+M[m][1]+M[m2][1]) ) friends[m]++;
             for ( int n = 0 ; n < M.length ; n++ ) for ( int m = 0 ; m < M.length ; m++ ) if ( friends[m] == n && solve(x+M[m][0], y+M[m][1], i) ) return true;
               return false;
            } finally { b[x][y] = 0; }
        }

        public static void main(String[] argv) {
            // Perform more iterators for more accurate benchmarks
          for ( int i = 0 ; i < 1 ; i++ ) {
               solve(0,0,1);
            }
        }
    }

  72. Monty Python by mattwarden · · Score: 1

    Did anyone else think this had something to do with a Monty Python sketch? (We are the Knights Who Write Unintelligible Code?)

  73. C++ by eelke_klein · · Score: 1

    Ok wrote a C++ version in less then two hours. It's currently 78 lines, could make it shorter but it would decrease readability. However it is fast... 100x100 starting in upper left in about 10 msec (Core 2 Duo 2.4 single threaded). Even 10000x10000 in less then a second. Which probably means that of that 10 ms for a 100x100 most is actually startup time and print time.

    Times are cpu time measured with time command.

  74. On the iPhone...Knight's Run.. by Anonymous Coward · · Score: 0

    I wrote this game for the iPhone...it's called Knight's Run.

    iTunes Link: http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=287816855&mt=8

    --Andrew Borland

  75. Ye Olde Implementations by lowen · · Score: 1

    Harumph.

    Did it in less lines, in VAX Pascal no less, in 1985.

    1. Re:Ye Olde Implementations by toby · · Score: 1

      And even fewer in MACRO-32 no doubt. :-)

      --
      you had me at #!
  76. That is awesome by Clueless+Moron · · Score: 1

    Thanks for finding it. I just knew generators would be the best way to solve the problem, but I was too lazy to try it. That code runs fast as all hell too; a 30x30 board is almost instantaneous. Plus it doesn't just find one solution; it finds all of them.

    Generators are a wonderful python feature. They're a cousin to Scheme's "continuations"; a similarly powerful feature.

    PS: I had mod points too, but they expired this morning. Sorry :-)

  77. one line of python (kinda slow) by bsy_at_play · · Score: 1

    $ time python -c "import sys; sys.stdout.write((lambda size, sizesq, allp, openclose: ((lambda mkbrd, brd, mv, av, d, finished: ((lambda h: h(h, mkbrd(), 0, 0, 0)) (lambda h, b, r, c, v: [ lambda: ([ lambda:'', lambda: ((lambda nb, nv: d([lambda:h(h, nb, r-2, c-1, nv), lambda:h(h, nb, r-1, c-2, nv), lambda:h(h, nb, r-2, c+1, nv), lambda:h(h, nb, r-1, c+2, nv), lambda:h(h, nb, r+1, c-2, nv), lambda:h(h, nb, r+2, c-1, nv), lambda:h(h, nb, r+1, c+2, nv), lambda:h(h, nb, r+2, c+1, nv)]) ) (mv(b,r,c,v), v+1))] [av(b,r,c)]()), lambda: brd(b)][finished(v,r,c)]()) )) (lambda: [-1] * sizesq, lambda b: '\n'.join((''.join('%4d' % v for v in b[i:i+size])) for i in range(0,sizesq,size)) + '\n\n', lambda b, r, c, v: b[:r*size+c] + [v] + b[r*size+c+1:], lambda b, r, c: int(r >=0 and r = 0 and c 0)]())), lambda fl: ''.join(f() for f in fl)][allp], [lambda v,r,c: int(v==sizesq), lambda v,r,c: int(v==sizesq and r==0 and c==0)][openclose] ))) (int(sys.argv[1]), int(sys.argv[1])*int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])))" 6 0 1
          0 7 4 13 2 29
          5 12 1 30 23 14
          8 35 6 3 28 31
        11 18 9 24 15 22
        34 25 20 17 32 27
        19 10 33 26 21 16

    real 0m43.784s
    user 0m36.254s
    sys 0m0.052s
    $

    arguments: the 6 is the size of the board, 0 means to print the first found rather than all, and the 1 means to look for a closed path rather than an open path.

    --
    beware syntactic cavities