Skip to content

Instantly share code, notes, and snippets.

@Kaali
Created November 19, 2014 08:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kaali/ad78efb37591c1ecd757 to your computer and use it in GitHub Desktop.
Save Kaali/ad78efb37591c1ecd757 to your computer and use it in GitHub Desktop.
rakkauden kalkulaattori
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <cassert>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <thread>
#include <vector>
struct Counts {
Counts() : p(0), a(0), i(0), r(0), s(0) {}
unsigned p, a, i, r, s;
};
template <typename T>
Counts CountChars(T const& str) {
Counts counts;
for (auto const& c : str) {
switch (c) {
case 'p':
case 'P':
counts.p++;
break;
case 'a':
case 'A':
counts.a++;
break;
case 'i':
case 'I':
counts.i++;
break;
case 'r':
case 'R':
counts.r++;
break;
case 's':
case 'S':
counts.s++;
break;
}
}
return counts;
}
template <typename T>
inline
T Clamp(T const& value) {
return value < 10 ? value : value - 9;
}
template <typename T>
auto Compatibility(T const& first, T const& second) -> decltype(Clamp(first.p + second.p)) {
using K = decltype(Clamp(first.p + second.p));
K p = Clamp(first.p + second.p);
K a = Clamp(first.a + second.a);
K i = Clamp(first.i + second.i);
K r = Clamp(first.r + second.r);
K s = Clamp(first.s + second.s);
p = Clamp(p + a);
a = Clamp(a + i);
i = Clamp(i + r);
r = Clamp(r + s);
p = Clamp(p + a);
a = Clamp(a + i);
i = Clamp(i + r);
p = Clamp(p + a);
a = Clamp(a + i);
return (p * 10) + a;
}
std::vector<Counts> ReadCounts(std::string const& filename); // TODO: What?
std::vector<Counts> ReadCounts(std::string const& filename) {
std::ios::sync_with_stdio(false);
std::fstream f{filename};
std::string line;
line.reserve(30);
std::vector<Counts> counts;
counts.reserve(1024);
while (std::getline(f, line)) {
counts.push_back(CountChars(line));
}
return counts;
}
std::vector<Counts> ReadCountsMmap(std::string const& filename);
std::vector<Counts> ReadCountsMmap(std::string const& filename) {
std::vector<Counts> counts;
counts.reserve(1024);
auto fd = open(filename.c_str(), O_RDONLY);
if (fd < 0) abort();
struct stat s;
auto status = fstat(fd, &s);
if (status < 0) abort();
size_t size = static_cast<size_t>(s.st_size);
const char* mapped = static_cast<char*>(mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0));
if (mapped == MAP_FAILED) {
abort();
}
Counts count;
for (decltype(size) i = 0; i < size; ++i) {
switch (mapped[i]) {
case 'p':
case 'P':
count.p++;
break;
case 'a':
case 'A':
count.a++;
break;
case 'i':
case 'I':
count.i++;
break;
case 'r':
case 'R':
count.r++;
break;
case 's':
case 'S':
count.s++;
break;
case '\n':
counts.push_back(count);
count.p = 0;
count.a = 0;
count.i = 0;
count.r = 0;
count.s = 0;
break;
}
}
return counts;
}
template <typename T>
void split_work(size_t concurrency, T const& data,
std::function<void(size_t, size_t)> worker) {
std::vector<std::thread> threads(concurrency);
size_t const worksize = data.size() / concurrency;
size_t i = 0;
for (auto it = std::begin(threads); it != std::end(threads) - 1; ++it) {
*it = std::thread(worker, i, i + worksize);
i += worksize;
}
threads.back() = std::thread(worker, i, data.size());
for (auto&& t : threads) t.join();
}
int main(int argc, char** argv) {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " filename" << std::endl;
return -1;
}
auto counts = ReadCountsMmap(argv[1]);
auto concurrency = std::thread::hardware_concurrency();
//auto concurrency = 1u;
std::atomic<unsigned> result(0);
auto worker = [&](size_t first, size_t last) {
unsigned res = 0;
for (size_t i = first; i < last; ++i) {
for (size_t j = i + 1; j < counts.size(); ++j) {
auto compat = Compatibility(counts[i], counts[j]);
if (compat == 99) {
res++;
}
}
}
result += res;
};
if (concurrency == 1) {
worker(0, counts.size());
} else {
split_work(concurrency, counts, worker);
}
std::cout << result << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment