[doc] Comments & Readme
This commit is contained in:
parent
f7f6ef679d
commit
e3bf7323fb
|
@ -5,3 +5,4 @@
|
|||
src/*.o
|
||||
tests/*.o
|
||||
testrunner
|
||||
cheapgmp
|
||||
|
|
96
README.md
96
README.md
|
@ -1,78 +1,38 @@
|
|||
# Purpose
|
||||
|
||||
Prove I'm not an idiot.
|
||||
This was a résumé test question given to someone else, who had brought
|
||||
it to the August 7th, 2015 Beer && Coding, in the hopes that we would
|
||||
help him solve it. We were not successful, although I did get pretty
|
||||
far on my own with a solution written in Scheme.
|
||||
|
||||
As an exercise, I decided to do this homework in C++. As I haven't
|
||||
written any C++ in 15 years, this was... entertaining.
|
||||
The problem stated was:
|
||||
|
||||
# Task #1
|
||||
Given a number (assume base 10) less than 10,000, write a program in
|
||||
C++ that will reverse the digits of that number, calculate the
|
||||
original number to the power of the new number, and print it out.
|
||||
You may not use Boost, GMP, or any library other than that provide
|
||||
by the C++ Standard Library.
|
||||
|
||||
Write a function which computes the some [sic] of q, q^2, q^3, … q^n,
|
||||
where "^" denotes power or exponent. For example, the sum of
|
||||
2,4,8,16 is 30. What is the complexity?
|
||||
I don't know C++. I haven't ever written C++ profesionally, and I
|
||||
haven't actually *looked* at C++ since 1999 or so. As a professional,
|
||||
I'm aware of what's going on in the zeitgeist, and at my job at Spiral
|
||||
Genetics I interacted with two very talented C++ developers a lot, so I
|
||||
was aware of things like the emerging C++ Standard Library and RAII and
|
||||
so forth. I didn't know what they *meant*, but I had heard them. I've
|
||||
also been aware of the emerging standards in C++11 and C++14, mostly
|
||||
thanks to Slashdot, Lobsters, and their ilk (don't read the comments,
|
||||
don't **ever** read the comments), so I'd *heard* about auto_ptr and
|
||||
C++11 lambdas and the like.
|
||||
|
||||
The complexity is linear. This is a basic sigma function, once you know
|
||||
the underlying formula, production is simple. The requirements for the
|
||||
code (that you determine both the base of your exponent collection, and
|
||||
know how many you want) are difficult to discern from a simple reading
|
||||
of the instructions.
|
||||
It took about an hour of googling to get up to speed on things like
|
||||
namespaces, containers, for_each, lambdas, and the like. I really like
|
||||
the new unique\_ptr construction. That's very nice.
|
||||
|
||||
If I'd allowed myself to use boost(), I've written this using the
|
||||
accumulate() function, but I'd have to figure out how to create a range
|
||||
iterator.
|
||||
My basic solution degrades to 4th-grade mathematics: Break the
|
||||
multiplicand up into a list of single digits, multiply each digit
|
||||
with the multiplier, then redistribute the values up the tens, hundreds,
|
||||
etc. etc. This solution is not particularly fast or space-efficient,
|
||||
but it has the virtue of being comprehensible by any ten-year-old.
|
||||
|
||||
|
||||
# Task #2
|
||||
|
||||
Write a function GetMax(Node list), which finds the maximum integer
|
||||
value in the list
|
||||
|
||||
In order to make this at all interesting, I set myself the task of
|
||||
learning how to create function templates, which we didn't have back in
|
||||
1999. It turned out to be relatively straightforward, although the
|
||||
"typename" declarator in the template before std::list<t>::iterator is a
|
||||
bit of cargo-cult I got from compiler's warnings; I really need to go
|
||||
back and read some of Alexandrescu's books, especially since I got them
|
||||
all for free after spotting a typo in one back in 1997 or so.
|
||||
|
||||
I've provided a Makefile and unit tests using the Aeryn C++ Test
|
||||
Framework. It was a framework chosen at random from a list I found
|
||||
after searching for "C++ Test Frameworks," I can't comment on its
|
||||
quality, but it did the job. It looked familiar enough compared to
|
||||
JUnit or Mocha.
|
||||
|
||||
# Commentary
|
||||
|
||||
It's been a long time since I wrote C++. The syntactical noise of C++
|
||||
annoys me a bit since I've started writing in "An elegant language for a
|
||||
more civilized time," and I'm so far out of experience with it that the
|
||||
modern paradigm of Resource Allocation Is Initialization and all of the
|
||||
wonderful new toys like auto, unique_ptr, lambdas and the like would
|
||||
take me a month or two to catch up.
|
||||
|
||||
If I'd written this in Javascript they'd have been one-liners:
|
||||
|
||||
exponentialSum = (base, count) =>
|
||||
_.reduce(_.range(1, count + 1), ((m, v) => return m + Math.pow(base, v)), 0);
|
||||
|
||||
largestValue = _.max;
|
||||
|
||||
or:
|
||||
|
||||
largestValue = (list) => Math.max.apply(Math, list);
|
||||
|
||||
I'm pretty sure that the functions I wrote have simple equivalents in
|
||||
some library somewhere. Boost seems to have just about everything.
|
||||
|
||||
The Makefile is just something I pulled out of an old project and
|
||||
cleaned up for the purposes of this exercise.
|
||||
|
||||
Total time spent: Approximately 75 minutes.
|
||||
|
||||
# Addenda
|
||||
|
||||
The [sic] in the original task description is a bit of a snark. That
|
||||
and the instruction to "Please use of of [sic] Java/C++/C#/Javascript"
|
||||
ought to be professionally embarrassing to someone seeking viable,
|
||||
self-respecting candidates.
|
||||
|
||||
|
|
|
@ -4,21 +4,34 @@ using namespace std;
|
|||
|
||||
namespace cheapgmp {
|
||||
namespace {
|
||||
void multiply(gmrep &in, ulong by) {
|
||||
|
||||
/* Given a list representing a decimal number as a multiplicand,
|
||||
multiply each digit by a multiplier, leaving in its place the
|
||||
remainder modulo 10 of the result, and using result diviso 10
|
||||
as a carryover to the 10^(n+1) slot */
|
||||
|
||||
void multiply(gmrep &multiplicand, ulong multiplier) {
|
||||
gmrep res(new lmrep());
|
||||
ulong rem = 0;
|
||||
for_each(in->rbegin(), in->rend(), [&rem, by](ulong &i) {
|
||||
ulong t = (i * by) + rem ;
|
||||
for_each(multiplicand->rbegin(), multiplicand->rend(), [&rem, by](ulong &i) {
|
||||
ulong t = (i * multiplier) + rem ;
|
||||
i = t % 10 ;
|
||||
rem = t / 10;
|
||||
});
|
||||
|
||||
/* When out of list elements, drain the result diviso 10 until
|
||||
the new result is complete */
|
||||
|
||||
while(rem > 0) {
|
||||
in->push_front(rem % 10);
|
||||
rem = rem / 10;
|
||||
}
|
||||
}
|
||||
|
||||
/* Given an integer, return a std::list<int> in which each node
|
||||
represents a decimal placement, i.e the end() is the ones,
|
||||
end().prev() is the tens, etc. */
|
||||
|
||||
gmrep makerep(const ulong in) {
|
||||
gmrep res(new lmrep());
|
||||
if (in == 0) {
|
||||
|
@ -35,6 +48,9 @@ namespace cheapgmp {
|
|||
}
|
||||
}
|
||||
|
||||
/* Perform the operation multiple times, to produce an exponential
|
||||
result */
|
||||
|
||||
gmrep makepower(const ulong base, const ulong power) {
|
||||
if (power == 0) {
|
||||
return makerep(base == 0 ? 0 : 1);
|
||||
|
|
Loading…
Reference in New Issue