Inspired by this post (and more great answers on the reddit comment thread), here's one nice thing about each of the languages I can remember using in any meaningful capacity:
Java: I learned to program in this. It led to the creation of the JVM, and while Java isn't my favorite language, the JVM is a pretty sexy piece of technology that enabled a number of other languages (Scala and Clojure most notable) to flourish.
C: The closest thing imperative programming has to "sparse beauty," a la Scheme. Shows you really don't need many bells and whistles to do a job, and do it well.
C++: Back when everyone was using C, it's kind of a technical miracle that Bjarne could create a proper superset on top of C with the features it has. Further, it's still blazing fast; without it we wouldn't have all the video games we love today ^_^.
PHP: Incredibly easy to learn, and no-hassle to set up on a server. One of the matches that lit the web on fire.
Racket (and Scheme applies here too): The language that never lets up. The most delicious learning curve I've ever tasted. Like Wagner's music is jokingly said to be "better than it sounds," Racket is more fun and fulfilling than it deserves to be.
Erlang: Industry-proven functional programming with more concurrency love than 1000 suns. Also the top language for gaining hipster-programmer cred. When you drop this name, suddenly everyone looks at you like "that guy" (you can decide if this is what you want or not).
Haskell: A wolf in sheeps's clothing, the most modern, practical, and supported language with features I think we'll see as necessary in the future. Another candidate for learning curve that keeps on giving.*
SML: A really sick module system for programming in the large. While not my favorite for "programming in the small," an understanding of SML's module system makes you pity that it never really took off.
Ruby: One of the most beautifully designed, fully-realized languages I know. Shows you can make a language that is simple, with practical value for Herp Derp programmers without sacrificing power and flexibility for the craftsmen as well.
Objective-C: The real "C with objects." Message passing with named parameters (and the much more sensible #import rather than #include), this is one time where I'm highly in favor of Mr. Jobs' stubbornness.
Prolog: 10-second youtube video. I mean this in a good way.
Max/MSP: Probably the most fully-realized and pleasing graphical programming environment I know, as well as an example of a damn fine DSL.
Javascript: I don't have to worry about compiler errors! No seriously, prototypical objects for the masses.
Flapjax: Functional reactive programming! An excellent example of functional languages and concepts attacking problems from the language level. Very innovative workaround for the horrors of client-side programming of the time.
Actionscript: Adobe makes it! Like Java, but better (Flash Platform > Swing/most Java GUI's).
*= Small qualification on the learning curve lines: virtually any language takes years of work over dozens of programs to "master." But many times mastering a language means compensating for its weaknesses, not discovering new strengths. That's what Haskell and Racket have given me more than most other languages.
Showing posts with label prolog. Show all posts
Showing posts with label prolog. Show all posts
December 10, 2010
September 30, 2010
Some Professor Layton Prolog!
Time to combine two of my favorite things: Professor Layton and obscure languages! There was one puzzle (of the hardest difficulty) that I could have spent 40 minutes working out, but instead spent an hour and half solving in Prolog (for those unfamiliar with Prolog, check out this post for a description of what this magic language is!).
I'll post the puzzle and solution here; hopefully someone finds it fun!

Four students took a test where every question had two possible answers, A or B. Each question was worth 10 points, for a total of 100 points.
The students' test results were posted as seen below, but the teacher forgot to tally Colin's score. Colin was heading to the teacher's office when Mary called him back, saying they could figure out his score using the results from the other tests. Can you figure out Colin's score?
-----
Below is the program I wrote to solve it. Verbose by contemporary language standards, but almost no thinking required, and the answer in an instant! Note the original version didn't have so many comments; these are to guide the curious reader. Sadly, github's gists don't know how to color Prolog syntax. Also, due to this terribly lame layout, I would suggest the 'view raw' feature at the bottom of the gist to see it in plaintext glory.
Edit: I also gist-ed my Prolog poker solver, which I wrote about in my first Prolog post. It was my very first prolog, and there are probably shorter ways of doing what I did, but hey! Give it a looksee and hope you enjoy it ^_^
I'll post the puzzle and solution here; hopefully someone finds it fun!

No 151 from Professor Layton and the Diabolical Box: Colin's Score
Four students took a test where every question had two possible answers, A or B. Each question was worth 10 points, for a total of 100 points.
The students' test results were posted as seen below, but the teacher forgot to tally Colin's score. Colin was heading to the teacher's office when Mary called him back, saying they could figure out his score using the results from the other tests. Can you figure out Colin's score?
Mary: 70 points
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| B | B | A | B | A | B | B | A | B | B |
Dan: 50 points
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| B | A | A | A | B | A | B | A | A | A |
Lisa: 30 points
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| B | A | A | A | B | B | B | A | B | A |
Colin: ?? points
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| B | B | A | A | A | B | B | A | A | A |
-----
Below is the program I wrote to solve it. Verbose by contemporary language standards, but almost no thinking required, and the answer in an instant! Note the original version didn't have so many comments; these are to guide the curious reader. Sadly, github's gists don't know how to color Prolog syntax. Also, due to this terribly lame layout, I would suggest the 'view raw' feature at the bottom of the gist to see it in plaintext glory.
Edit: I also gist-ed my Prolog poker solver, which I wrote about in my first Prolog post. It was my very first prolog, and there are probably shorter ways of doing what I did, but hey! Give it a looksee and hope you enjoy it ^_^
May 17, 2010
I'm still neck-deep in exam studies...
... but there's a really, really great post on the various meanings of the word 'functor' in 4 different languages. It's the clearest example I've seen for SML, especially. Also note the 'This space reserved for JELLY STAINS' at the top ^_^
December 14, 2009
Prologgin'
Exam season is a royal pain, but I find ways to entertain myself. My most recent delight has been Project Euler: I discovered it late last semester, and took a break until about November to tackle some Facebook puzzles. But with the gaps between commitments getting smaller and smaller, and with a desire to use some more unorthodox languages (Facebook doesn't accept Scheme or SML submissions, for example), tackling 15 or so of the easier Project Euler problems proved fitting.
I recently solved Problem 54, an unusually straightforward implementation problem (most problems require some mathematical insight, this was a straight-up write-it-out problem). In Problem 54, they provide a file with 1000 games of poker, and you must determine how many games the first player wins.
So here I saw an opportunity: Prolog! Wouldn't it be more fun to just declare the rules of Poker and say "go," rather than hard-code every individual evaluation possibility?
-----
For those who don't know what Prolog is, here's a quick (very, very brief) primer: Prolog is a language that attempts to satisfy truth clauses given a set of relations, and rules that govern them. So if I were to define the following relation R:
Then we know that ("paul" R "luap") is a true statement, but ("paul" R "robert") is false.
In Prolog, you supply the language with any relations you like (such as R, above), and when you provide data to those relations it can tell you if they are true or not.
Yawn. Here's the kicker: In Prolog, you can supply variables to the relations, and the language will bind those variables to values that satisfy its truth, without having to specify exactly how to find such a value. Using the example above, if I fed Prolog
Prolog returns
The key to this is that I never told Prolog how to reverse a word, I simply declared that R is true when one side is the reverse of the other. This becomes more clear as I go through the poker example: when you program in Prolog, you aren't thinking "what instructions can I give a machine primarily using destructive memory updates such that I can compute my goal?" (generally what happens in imperative programs), or "what functional abstractions can I define such that one's output evaluates to my goal?" (functional programs), but rather "what is my goal?" (logical programs, of which Prolog is the most popular language).
----
I'll throw a little syntax in before we dive into the example. In Prolog, square brackets define a list, so [] is an empty list, [paul, robert, annalisa] is a list with my siblings and I, and [[galosh, wader],[souvlaki, moussaka, gyro],gawker] is a list of two lists and "gawker."
In my poker program, each card is a list of the cards value and its suit (e.g. [ace,spades] or [8,diamonds]). A list of five cards is a hand, and a list of two hands is a game between two players.
Throwing it all together, here's are some of the rules I wrote that determine a player's hand in poker:
determine_hand([[_,X],[_,X],[_,X],[_,X],[_,X]], flush).
In English, this says: the relation determine_hand is true if two conditions are met. The first value is a hand of cards, for which the second value on every pair (the suit) is the same value X. Second, the second value of determine_hand is the value "flush." The underscore in the place of the values of the cards tells Prolog "we don't care what goes there," since getting a flush is only dependent on the suits of the cards. Here is another:
determine_hand([[10,X],[jack,X],[queen,X],[king,X],[ace,X]], royal_flush).
This clause says: the relation determine_hand is true if two things occur: the first, its left side is a 5-tuple of pairs. The values of the represented cards must be 10, jack, queen, king, and ace; the second value (the suit) for each card must all be the same value X. Secondly, the right side of determine_hand must be the value "royal_flush."
So if I then prompted Prolog with:
determine_hand([[10,clubs],[3,clubs],[8,clubs],[queen,clubs],[6,clubs]], HandType).
Prolog would search the possible values for HandType (variables begin with capital letters) until it found some value to make it true given the rules I've provided above. We see that all suit values are the same ("clubs"), so Prolog replies:*
HandType = flush.
-----
Like any evaluator of conditional statements, the relation rules can be chained together with standard boolean operators. The following mean:
This should be enough (coming at you very fast!) to give you a flavor for how the program worked. Here is the top-level relation:
winner(H1, H2, Winner) :-
sort_hand(H1, Sorted_Hand1),
sort_hand(H2, Sorted_Hand2),
determine_hand(Sorted_Hand1, X1),
determine_hand(Sorted_Hand2, X2),
beats(X1, X2, Verdict),
(Verdict = X1, Winner = H1;
Verdict = X2, Winner = H2;
Verdict = tie,
tiebreak(X1, Sorted_Hand1, Sorted_Hand2, SortedWinner),
(SortedWinner = left, Winner = H1 ;
SortedWinner = right, Winner = H2)).
It goes something like this in English: The winner relation is true if the following are true, for two poker hands H1 and H2, and some value Winner:
----
It's a pretty radical departure from more traditional ways of programming. For those interested in logic programming, there are some great chapters near the end of PLAI on the subject. Also, The Reasoned Schemer is essential, and the 'logical Scheme' they use is an interesting counterpoint to Prolog.
I firmly believe you should base your language choice on the problem you're trying to solve, and you shouldn't contort your problem to fit the language (this is why Lisp is so much fun). I don't run into too many problems where Prolog is the answer, but when I always greatly look forward to when I do ^_^
--
Prolog links:
* = If, given the definitions, you then passed determine_hand(X,Y), where X was a royal flush, Y would be bound to "flush." Why? Because the first predicate we defined was successful (a royal flush is just a more specialized flush, and Prolog saw that determine_hand was true for the flush first). How do we get around this? You can either by ordering your clauses appropriately, or explicitly stating that one clause can only be true when the others are false.
I recently solved Problem 54, an unusually straightforward implementation problem (most problems require some mathematical insight, this was a straight-up write-it-out problem). In Problem 54, they provide a file with 1000 games of poker, and you must determine how many games the first player wins.
So here I saw an opportunity: Prolog! Wouldn't it be more fun to just declare the rules of Poker and say "go," rather than hard-code every individual evaluation possibility?
-----
For those who don't know what Prolog is, here's a quick (very, very brief) primer: Prolog is a language that attempts to satisfy truth clauses given a set of relations, and rules that govern them. So if I were to define the following relation R:
(a R b) is true if and only if a is the reverse of b.
Then we know that ("paul" R "luap") is a true statement, but ("paul" R "robert") is false.
In Prolog, you supply the language with any relations you like (such as R, above), and when you provide data to those relations it can tell you if they are true or not.
Yawn. Here's the kicker: In Prolog, you can supply variables to the relations, and the language will bind those variables to values that satisfy its truth, without having to specify exactly how to find such a value. Using the example above, if I fed Prolog
x R "cantankerous"
Prolog returns
x = "suoreknatnac"
The key to this is that I never told Prolog how to reverse a word, I simply declared that R is true when one side is the reverse of the other. This becomes more clear as I go through the poker example: when you program in Prolog, you aren't thinking "what instructions can I give a machine primarily using destructive memory updates such that I can compute my goal?" (generally what happens in imperative programs), or "what functional abstractions can I define such that one's output evaluates to my goal?" (functional programs), but rather "what is my goal?" (logical programs, of which Prolog is the most popular language).
----
I'll throw a little syntax in before we dive into the example. In Prolog, square brackets define a list, so [] is an empty list, [paul, robert, annalisa] is a list with my siblings and I, and [[galosh, wader],[souvlaki, moussaka, gyro],gawker] is a list of two lists and "gawker."
In my poker program, each card is a list of the cards value and its suit (e.g. [ace,spades] or [8,diamonds]). A list of five cards is a hand, and a list of two hands is a game between two players.
Throwing it all together, here's are some of the rules I wrote that determine a player's hand in poker:
determine_hand([[_,X],[_,X],[_,X],[_,X],[_,X]], flush).
In English, this says: the relation determine_hand is true if two conditions are met. The first value is a hand of cards, for which the second value on every pair (the suit) is the same value X. Second, the second value of determine_hand is the value "flush." The underscore in the place of the values of the cards tells Prolog "we don't care what goes there," since getting a flush is only dependent on the suits of the cards. Here is another:
determine_hand([[10,X],[jack,X],[queen,X],[king,X],[ace,X]], royal_flush).
This clause says: the relation determine_hand is true if two things occur: the first, its left side is a 5-tuple of pairs. The values of the represented cards must be 10, jack, queen, king, and ace; the second value (the suit) for each card must all be the same value X. Secondly, the right side of determine_hand must be the value "royal_flush."
So if I then prompted Prolog with:
determine_hand([[10,clubs],[3,clubs],[8,clubs],[queen,clubs],[6,clubs]], HandType).
Prolog would search the possible values for HandType (variables begin with capital letters) until it found some value to make it true given the rules I've provided above. We see that all suit values are the same ("clubs"), so Prolog replies:*
HandType = flush.
-----
Like any evaluator of conditional statements, the relation rules can be chained together with standard boolean operators. The following mean:
- left
:-right means left is true if right is true. - Commas mean logical AND.
- Semicolons mean logical OR.
- And, of course, you can group with parenthesis (AND gets higher precedence than OR).
This should be enough (coming at you very fast!) to give you a flavor for how the program worked. Here is the top-level relation:
winner(H1, H2, Winner) :-
sort_hand(H1, Sorted_Hand1),
sort_hand(H2, Sorted_Hand2),
determine_hand(Sorted_Hand1, X1),
determine_hand(Sorted_Hand2, X2),
beats(X1, X2, Verdict),
(Verdict = X1, Winner = H1;
Verdict = X2, Winner = H2;
Verdict = tie,
tiebreak(X1, Sorted_Hand1, Sorted_Hand2, SortedWinner),
(SortedWinner = left, Winner = H1 ;
SortedWinner = right, Winner = H2)).
It goes something like this in English: The winner relation is true if the following are true, for two poker hands H1 and H2, and some value Winner:
- Sorted_Hand1 is bound to the first value that makes sort_hand(H1, Sorted_Hand1) true. In this case, it's true when a hand is sorted by ascending value, so ifH1 = [[4,spades],[king,clubs],[9,hearts],[3,diamonds],[9,spades]].
the predicate becomes true ifSortedHand = [[3,diamonds],[4,spades],[9,spades],[9,hearts],[king,clubs]].
Which Prolog will find for us ^_^ - Find the same value for the second Hand.
- X1 and X2 are the values of determine_hand for the Sorted_Hands, and these are bound to the appropriate types of hand in poker (e.g. "two pair" and "full house").
- beats is true when the third value (in this case, Verdict) is the winner of the first two hands. If the two hands are the same, Verdict becomes "tie."
- One of three things is true: Either Verdict is X1, and Winner is H1 (the left player has a higher hand), OR Verdict is X2, and Winner is H2, OR there was a tie, in which case tiebreak becomes true if it's fourth value is the winner of two hands of the same type. (the problem guarantees there's always a clear winner, so we won't have actual tie games, such as two royal flushes).
----
It's a pretty radical departure from more traditional ways of programming. For those interested in logic programming, there are some great chapters near the end of PLAI on the subject. Also, The Reasoned Schemer is essential, and the 'logical Scheme' they use is an interesting counterpoint to Prolog.
I firmly believe you should base your language choice on the problem you're trying to solve, and you shouldn't contort your problem to fit the language (this is why Lisp is so much fun). I don't run into too many problems where Prolog is the answer, but when I always greatly look forward to when I do ^_^
--
Prolog links:
- SWI-Prolog, a free and pretty nice implementation.
- GNU Prolog, a little harder to get started with, but worth looking into.
- 99 Prolog Problems. These have since been copied many times over, but the first '99 Problems' set of this sort was by Prologgers.
- The First 10 Prolog Programming Contests. A good read for idiomatic language use, and seeing it solve all levels of problems.
* = If, given the definitions, you then passed determine_hand(X,Y), where X was a royal flush, Y would be bound to "flush." Why? Because the first predicate we defined was successful (a royal flush is just a more specialized flush, and Prolog saw that determine_hand was true for the flush first). How do we get around this? You can either by ordering your clauses appropriately, or explicitly stating that one clause can only be true when the others are false.
Subscribe to:
Posts (Atom)
