Great post but it's the language and syntax hoop-jumping that is required in JavaScript to do paradigm experimentation (or playing as Feynman would call it) that's pushed me to take the time to explore other languages.
Here's the Fish/Zebra/Einstein puzzle in my Clojure logic programming library based on miniKanren, this program is solved on my machine in 2 milliseconds - even though this version involves unification and logic variables. It also reads better IMO and should look familiar to the Prologist:
I've not played much with amb or Prolog, but it would be cool to try out some alternative strategies for exhausting the search tree, perhaps simulated annealing or something like that.
This is the sort of language feature that looks very neat at first, but there are simpler ways to solve the same problems. If you want to search a space by trying all possibilities ("generate and test"), the most straightforward way is a nested for loop with an if statement.
The advantage of using nested for loops is that it's pretty clear that there's a performance problem and most programmers will have a good idea what to do about it. (Perhaps change the order of the loops, do checks in the outer loops to avoid running the inner loops, and so on. For larger problems, figure out how to parallelize.)
Of course, a for loop isn't very modular, so something like Python's generator expressions might be more suitable for building pipelines. In Java, this can be done with iterators and some good iterator utility methods, such as those in Guava.
Here's the Fish/Zebra/Einstein puzzle in my Clojure logic programming library based on miniKanren, this program is solved on my machine in 2 milliseconds - even though this version involves unification and logic variables. It also reads better IMO and should look familiar to the Prologist: