commit f7f6ef679d786e925ac456375be6abd3fcc2ab89 Author: Elf M. Sternberg Date: Thu Aug 6 13:24:40 2015 -0700 Final. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..65c3a75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*# +.#* +*~ +*.orig +src/*.o +tests/*.o +testrunner diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8a6146d --- /dev/null +++ b/Makefile @@ -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) diff --git a/README.md b/README.md new file mode 100644 index 0000000..d011f78 --- /dev/null +++ b/README.md @@ -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::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. + diff --git a/cheapgmp b/cheapgmp new file mode 100755 index 0000000..6320c49 Binary files /dev/null and b/cheapgmp differ diff --git a/src/accessories.cpp b/src/accessories.cpp new file mode 100644 index 0000000..38bbe4d --- /dev/null +++ b/src/accessories.cpp @@ -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(); + } + +} diff --git a/src/accessories.hpp b/src/accessories.hpp new file mode 100644 index 0000000..102bfeb --- /dev/null +++ b/src/accessories.hpp @@ -0,0 +1,11 @@ +#include "cheapgmp.hpp" +#include +#include +#include + +using namespace std; + +namespace cheapgmp { + wstring tostring(gmrep); + ulong tolong(gmrep); +} diff --git a/src/cheapgmp.cpp b/src/cheapgmp.cpp new file mode 100644 index 0000000..20cc480 --- /dev/null +++ b/src/cheapgmp.cpp @@ -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; + } +} + diff --git a/src/cheapgmp.hpp b/src/cheapgmp.hpp new file mode 100644 index 0000000..a62397d --- /dev/null +++ b/src/cheapgmp.hpp @@ -0,0 +1,12 @@ +#include +#include +#include + +using namespace std; + +namespace cheapgmp { + typedef list lmrep; + typedef unique_ptr gmrep; + gmrep makepower(const ulong, const ulong); +} + diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..b75f38e --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,43 @@ +#include +#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; + } + } +} + diff --git a/tests/test_cheapgmp.cpp b/tests/test_cheapgmp.cpp new file mode 100644 index 0000000..afea76b --- /dev/null +++ b/tests/test_cheapgmp.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#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(); +} + + + +