This commit is contained in:
Elf M. Sternberg 2015-08-06 13:24:40 -07:00
commit f7f6ef679d
10 changed files with 294 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*#
.#*
*~
*.orig
src/*.o
tests/*.o
testrunner

36
Makefile Normal file
View File

@ -0,0 +1,36 @@
PROJECT= resume
SOURCES= src/cheapgmp.cpp src/accessories.cpp
MAINSRC= src/main.cpp
TESTSOURCES= tests/test_cheapgmp.cpp
LDFLAGS=
TESTLDFLAGS= -laeryn_tests -laeryn_core
CFLAGS= -c -Wall -std=c++11
CPLUSPLUS= g++
BINARY=cheapgmp
TESTBINARY=testrunner
OBJECTS=$(SOURCES:.cpp=.o)
TESTOBJECTS=$(TESTSOURCES:.cpp=.o)
MAINOBJECTS=$(MAINSRC:.cpp=.o)
all: $(SOURCES) $(BINARY)
$(BINARY): $(OBJECTS) $(MAINOBJECTS)
$(CPLUSPLUS) $(OBJECTS) $(MAINOBJECTS) $(LDFLAGS) -o $@
app: $(BINARY)
testrunner: $(OBJECTS) $(TESTOBJECTS)
$(CPLUSPLUS) $(OBJECTS) $(TESTOBJECTS) $(LDFLAGS) $(TESTLDFLAGS) -o $@
.cpp.o:
$(CPLUSPLUS) $(CFLAGS) $< -o $@
test: $(BINARY)
./$(BINARY)
distclean: clean
rm -f $(BINARY)
clean:
rm -f $(OBJECTS)

78
README.md Normal file
View File

@ -0,0 +1,78 @@
# Purpose
Prove I'm not an idiot.
As an exercise, I decided to do this homework in C++. As I haven't
written any C++ in 15 years, this was... entertaining.
# Task #1
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?
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.
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.
# 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.

BIN
cheapgmp Executable file

Binary file not shown.

23
src/accessories.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "accessories.hpp"
namespace cheapgmp {
ulong tolong(const gmrep in) {
int pos = 1;
ulong ret = 0;
for_each(in->rbegin(), in->rend(), [&pos, &ret](ulong i) {
ret = ret + (i * pos);
pos = pos * 10;
});
return ret;
}
wstring tostring(const gmrep in) {
wstringstream ss;
for_each(in->begin(), in->end(), [&ss](ulong i) {
ss << i;
});
return ss.str();
}
}

11
src/accessories.hpp Normal file
View File

@ -0,0 +1,11 @@
#include "cheapgmp.hpp"
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
namespace cheapgmp {
wstring tostring(gmrep);
ulong tolong(gmrep);
}

52
src/cheapgmp.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "cheapgmp.hpp"
using namespace std;
namespace cheapgmp {
namespace {
void multiply(gmrep &in, ulong by) {
gmrep res(new lmrep());
ulong rem = 0;
for_each(in->rbegin(), in->rend(), [&rem, by](ulong &i) {
ulong t = (i * by) + rem ;
i = t % 10 ;
rem = t / 10;
});
while(rem > 0) {
in->push_front(rem % 10);
rem = rem / 10;
}
}
gmrep makerep(const ulong in) {
gmrep res(new lmrep());
if (in == 0) {
res->push_front(0);
return res;
}
ulong rem = in;
while(rem > 0) {
res->push_front(rem % 10);
rem = rem / 10;
}
return res;
}
}
gmrep makepower(const ulong base, const ulong power) {
if (power == 0) {
return makerep(base == 0 ? 0 : 1);
}
gmrep res = makerep(base);
ulong ct = power;
while(ct > 1) {
multiply(res, base);
ct--;
}
return res;
}
}

12
src/cheapgmp.hpp Normal file
View File

@ -0,0 +1,12 @@
#include <memory>
#include <list>
#include <algorithm>
using namespace std;
namespace cheapgmp {
typedef list<ulong> lmrep;
typedef unique_ptr<lmrep> gmrep;
gmrep makepower(const ulong, const ulong);
}

43
src/main.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <iostream>
#include "cheapgmp.hpp"
using namespace cheapgmp;
using namespace std;
ulong reverse(ulong in) {
ulong rev = 0;
for(; in != 0; ) {
rev = (rev * 10) + (in % 10);
in = in / 10;
}
return rev;
}
bool process() {
ulong in;
ulong rev;
cout << "Enter your value: ";
cin >> in;
if (in == 0) {
return false;
}
rev = reverse(in);
cout << in << "^" << rev << " = ";
gmrep ret = makepower(in, rev);
for_each(ret->begin(), ret->end(), [](ulong i) { cout << i; });
cout << endl;
return true;
}
int main(int argc, char* argv[]) {
while(true) {
if (process() == false) {
break;
}
}
}

32
tests/test_cheapgmp.cpp Normal file
View File

@ -0,0 +1,32 @@
#include <aeryn/test_runner.hpp>
#include <aeryn/is_equal.hpp>
#include <aeryn/use_name.hpp>
#include "../src/cheapgmp.hpp"
#include "../src/accessories.hpp"
using namespace cheapgmp;
wstring sample123 = L"72367033806371673149109894141163778628811792657571658906010558390395870363798401744095280686155507736404921657070284961721828960592977909542637098897697223102622628566787654091327825453991595140205701412961364188732408936197890553699715836951569999800431957769217006743321026257517932764164662319487914962533302741368207211189494615326552790667720411285474162636765168907211924134973374304496019635376665858559941735703924836467756917247995469583487467791524582153744522107597865277798136080074161485280424274076931083994487111719562249702540362855712911132265966235754355353516703339043001506118520760359577737869472018617942120590873170710805078696371738906375721785723";
ulong sample6 = 46656;
void testSmallToLong() {
IS_EQUAL(tolong(makepower(6, 6)), sample6);
}
void testLargeToString() {
IS_EQUAL(tostring(makepower(123, 321)), sample123);
}
int main()
{
using namespace Aeryn;
TestRunner testRunner;
testRunner.Add(TestCase(USE_NAME(testSmallToLong)));
testRunner.Add(TestCase(USE_NAME(testLargeToString)));
return testRunner.Run();
}