[doc] Comments & Readme
This commit is contained in:
parent
f7f6ef679d
commit
e3bf7323fb
|
@ -5,3 +5,4 @@
|
||||||
src/*.o
|
src/*.o
|
||||||
tests/*.o
|
tests/*.o
|
||||||
testrunner
|
testrunner
|
||||||
|
cheapgmp
|
||||||
|
|
96
README.md
96
README.md
|
@ -1,78 +1,38 @@
|
||||||
# Purpose
|
# 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
|
The problem stated was:
|
||||||
written any C++ in 15 years, this was... entertaining.
|
|
||||||
|
|
||||||
# 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,
|
I don't know C++. I haven't ever written C++ profesionally, and I
|
||||||
where "^" denotes power or exponent. For example, the sum of
|
haven't actually *looked* at C++ since 1999 or so. As a professional,
|
||||||
2,4,8,16 is 30. What is the complexity?
|
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
|
It took about an hour of googling to get up to speed on things like
|
||||||
the underlying formula, production is simple. The requirements for the
|
namespaces, containers, for_each, lambdas, and the like. I really like
|
||||||
code (that you determine both the base of your exponent collection, and
|
the new unique\_ptr construction. That's very nice.
|
||||||
know how many you want) are difficult to discern from a simple reading
|
|
||||||
of the instructions.
|
|
||||||
|
|
||||||
If I'd allowed myself to use boost(), I've written this using the
|
My basic solution degrades to 4th-grade mathematics: Break the
|
||||||
accumulate() function, but I'd have to figure out how to create a range
|
multiplicand up into a list of single digits, multiply each digit
|
||||||
iterator.
|
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 cheapgmp {
|
||||||
namespace {
|
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());
|
gmrep res(new lmrep());
|
||||||
ulong rem = 0;
|
ulong rem = 0;
|
||||||
for_each(in->rbegin(), in->rend(), [&rem, by](ulong &i) {
|
for_each(multiplicand->rbegin(), multiplicand->rend(), [&rem, by](ulong &i) {
|
||||||
ulong t = (i * by) + rem ;
|
ulong t = (i * multiplier) + rem ;
|
||||||
i = t % 10 ;
|
i = t % 10 ;
|
||||||
rem = t / 10;
|
rem = t / 10;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* When out of list elements, drain the result diviso 10 until
|
||||||
|
the new result is complete */
|
||||||
|
|
||||||
while(rem > 0) {
|
while(rem > 0) {
|
||||||
in->push_front(rem % 10);
|
in->push_front(rem % 10);
|
||||||
rem = 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 makerep(const ulong in) {
|
||||||
gmrep res(new lmrep());
|
gmrep res(new lmrep());
|
||||||
if (in == 0) {
|
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) {
|
gmrep makepower(const ulong base, const ulong power) {
|
||||||
if (power == 0) {
|
if (power == 0) {
|
||||||
return makerep(base == 0 ? 0 : 1);
|
return makerep(base == 0 ? 0 : 1);
|
||||||
|
|
Loading…
Reference in New Issue