This, the first graded assignment of the semester, asks you to solve a simple problem in each of five different programming languages (six if you’re in 454):
Given two integers, k and n, your program should output all combinations of k numbers chosen from {1, 2, ..., n}. So if, for example, you specify the values 3 and 4, you should see
1 2 3 1 2 4 1 3 4 2 3 4To make life easier for the graders, please print the members of each combination in ascending order—so
1 2 4
but not
1 4 2
or
4 2 1
.
You can print the rows in any order.
Finding combinations is a naturally recursive problem (iterative solutions
are also possible). The easiest and most elegant
solutions employ a recursive set of iterators, which are
abstractions used to drive
a for
loop. We will study iterators in Section 6.5.3; you
may want to read ahead. In the terminology of that section,
you’ll find that Python and C# have “true”
iterators.
Prolog's search mechanism can be used to create the equivalent of
iterators, and yields a very elegant solution (my version is less than
10 lines long).
Ada and Scheme have no special iterator support; for these you'll have to
work with lists.
For what it's worth, Java and C++ (which you can try for extra credit)
have iterator objects, which are sort of half of what you
want.
If you already knew all the languages, you’d probably find your task easiest in Prolog and hardest in Ada, with the various other languages ranging in between. (Of course you probably don’t know all the languages already, so the unfamiliar ones will be the hardest.) A hint: the companion site for the textbook contains working versions of all the nontrivial examples in the book. For Ada and C# you might find it helpful to start with one of these: it will already import appropriate libraries and contain examples of the control constructs, I/O calls, etc.
When run, most of your programs should take k and
n (in that order) as command-line arguments, and then write
combinations, one per line, to standard output.
For Prolog, the easiest approach is to arrange for
combinations(k, n, L)
to produce successive
combinations (instantiations of L
) on demand.
More specifically: when you’re working interactively with the
interpreter and you enter the query
combinations(3, 4, L)
,
the interpreter will respond with something like
“L = [1, 2, 3]
”.
It will then hang at the end of the line waiting for
input—that’s the natural behavior of the interpreter.
If you then enter a semicolon, which signals the interpreter to
backtrack, you should get another combination—and so on,
repeatedly, until there aren’t any more.
(It’s also ok to write a program that prints all the
combinations, all at once, but that’s harder.)
For Scheme, which runs in an interpreter, please arrange for
(combinations k n)
to return a
list of combinations, each of which is a (nested) list.
Your programs should all run in time proportional to the length of the output. Not all “obvious” programs will do so. Behind this link, for example, is a Python program that produces the correct output, but takes time exponential in n, regardless of k. In particular, it takes exponential time when k = n, even though the output is only one line long (try it for, say, k = n = 20). (For what it's worth, my version of the better Python solution is actually a shorter program.)
You may work alone on this project or in teams of two. If you split up
the languages, whoever takes Ada should probably do two; the other
person should do three.
However you divide the programming,
each team member must write his or her own
README
file (no sharing of text on this allowed), and turn in
the project separately (with all five or six programs, which
will be the same as the partner’s code).
This means, of course, that you’ll need to really
understand your partner’s code.
Be sure to read the instructions on the
grading page regarding the turn-in
procedure and requirements.
To turn in your code, use the following procedure, which will be the
same for all assignments this semester:
On a csug
machine,
put your write-up in a README.txt
or
README.pdf
file in the same directory as your code, and
(while still in that directory) run
the script ~cs254/bin/TURN_IN
.
The script will package the contents of the directory (and any
subdirectories) into a bundle and send it to the TAs for grading (so
clean up any mess you might have in the directory first).
Be sure your write-up (README
file) describes any features
of your code that the TAs might not immediately notice. In
addition, for this assignment, your
README
file must compare and contrast the
programming experience in the different languages you used (all five/six
of them). What was easy? What was hard?
Are there noticeable differences in speed?
What do you like/dislike?
Did you find iterators to be helpful?
We will be using the following language implementations.
The Ruby, Python, and Prolog interpreters, the Haskell interpreter and
compiler, the Ada and Rust compilers, and the OCaml interpreter and
compiler are found in /usr/bin
.
The Scheme interpreter is found in /usr/staff/bin
.
The remaining implementations (for C#, Go, and Swift)
are in /u/cs254/bin
, which you
should append to your PATH
environment variable (ask a
friend or one of the TAs if you
don’t know how).
gnatmake
(a wrapper for the
GNU Ada translator). It produces native executables.
mcs
(the Mono project C#
compiler) and run with the mono
JIT/run-time system.
go
.
ghci
interpreter, or
compile with ghc
(the Glasgow Haskell Compiler) to
produce native binaries.
swipl
interpreter.
python3
interpreter.
ocaml
interpreter, or
compile with ocamlc
to produce native binaries.
ruby
interpreter.
rustc
.
plt-r5rs
or, under X, with the drracket
GUI.
Be sure to configure the latter to use the R5RS language standard
(it boots up expecting a vastly expanded language that will try to
force you to use modules and other features you don’t want to
have to learn at this point.)
swift
interpreter, or
compile with swiftc
.
You are welcome to work with other language implementations and/or platforms, but you must ensure that your final versions compile and run correctly using the implementations listed above. We will be testing using only these.
I won’t be devoting lecture time to how to use these languages. You’ll need to find on-line tutorials or other resources, and teach yourself. Here are some decent starting points:
Before 5pm on Friday, September 8, complete the T1 trivia assignment found on Blackboard.