Final.
This commit is contained in:
commit
f7f6ef679d
|
@ -0,0 +1,7 @@
|
|||
*#
|
||||
.#*
|
||||
*~
|
||||
*.orig
|
||||
src/*.o
|
||||
tests/*.o
|
||||
testrunner
|
|
@ -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)
|
|
@ -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.
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#include "cheapgmp.hpp"
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace cheapgmp {
|
||||
wstring tostring(gmrep);
|
||||
ulong tolong(gmrep);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue