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