I'm trying to solve this problem using the slicing technic.
But I just passed the first two test cases in this gym (Problem A)
2017-2018 ACM-ICPC East Central North America Regional Contest (ECNA 2017)
The whole step in my code looks like this:
calculate the total area using vector cross when inputting the polygon information.
find all the endpoints and intersection points, and record x value of them.
for each slice (sort x list and for each interval) find the lines from every polygon which crosses this interval and store this smaller segment.
sort segments.
for each trapezoid or triangle, calculate the area if this area is covered by some polygon.
sum them all to find the cover area.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template<typename T> using p = pair<T, T>;
template<typename T> using vec = vector<T>;
template<typename T> using deq = deque<T>;
// #define dbg
#define yccc ios_base::sync_with_stdio(false), cin.tie(0)
#define al(a) a.begin(),a.end()
#define F first
#define S second
#define eb emplace_back
const int INF = 0x3f3f3f3f;
const ll llINF = 1e18;
const int MOD = 1e9+7;
const double eps = 1e-9;
const double PI = acos(-1);
double fcmp(double a, double b = 0, double eps = 1e-9) {
if (fabs(a-b) < eps) return 0;
return a - b;
}
template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& a) { in >> a.F >> a.S; return in; }
template<typename T1, typename T2>
ostream& operator<<(ostream& out, pair<T1, T2> a) { out << a.F << ' ' << a.S; return out; }
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator+(const Point& src) {
return Point(src.x + x, src.y + y);
}
Point operator-(const Point& src) {
return Point(x - src.x, y - src.y);
}
Point operator*(double src) {
return Point(x * src, y * src);
}
//* vector cross.
double operator^(Point src) {
return x * src.y - y * src.x;
}
};
struct Line {
Point sp, ep;
Line() {}
Line(Point sp, Point ep) : sp(sp), ep(ep) {}
//* check if two segment intersect.
bool is_intersect(Line src) {
if (fcmp(ori(src.sp) * ori(src.ep)) < 0 and fcmp(src.ori(sp) * src.ori(ep)) < 0) {
double t = ((src.ep - src.sp) ^ (sp - src.sp)) / ((ep - sp) ^ (src.ep - src.sp));
return fcmp(t) >= 0 and fcmp(t, 1) <= 0;
}
return false;
}
//* if two segment intersect, find the intersection point.
Point intersect(Line src) {
double t = ((src.ep - src.sp) ^ (sp - src.sp)) / ((ep - sp) ^ (src.ep - src.sp));
return sp + (ep - sp) * t;
}
double ori(Point src) {
return (ep - sp) ^ (src - sp);
}
bool operator<(Line src) const {
if (fcmp(sp.y, src.sp.y) != 0)
return sp.y < src.sp.y;
return ep.y < src.ep.y;
}
};
int next(int i, int n) {
return (i + 1) % n;
}
int main()
{
yccc;
int n;
cin >> n;
//* the point list and the line list of polygons.
vec<vec<Point>> p_list(n);
vec<vec<Line>> l_list(n);
//* x's set for all endpoints and intersection points
vec<double> x_list;
//* initializing point list and line list
double total = 0, cover = 0;
for (int i = 0; i < n; i++) {
int m;
cin >> m;
p_list[i].resize(m);
for (auto &k : p_list[i]) {
cin >> k.x >> k.y;
x_list.eb(k.x);
}
l_list[i].resize(m);
for (int k = 0; k < m; k++) {
l_list[i][k].sp = p_list[i][k];
l_list[i][k].ep = p_list[i][next(k, m)];
}
//* calculate the polygon area.
double tmp = 0;
for (int k = 0; k < m; k++) {
tmp += l_list[i][k].sp.x * l_list[i][k].ep.y - l_list[i][k].sp.y * l_list[i][k].ep.x;
}
total += abs(tmp);
}
//* find all intersection points
for (int i = 0; i < n; i++)
for (int k = i+1; k < n; k++) {
for (auto li : l_list[i])
for (auto lk : l_list[k])
if (li.is_intersect(lk)) {
x_list.eb(li.intersect(lk).x);
}
}
sort(al(x_list));
auto same = [](double a, double b) -> bool {
return fcmp(a, b) == 0;
};
x_list.resize(unique(al(x_list), same) - x_list.begin());
//* for each slicing, calculate the cover area.
for (int i = 0; i < x_list.size() - 1; i++) {
vec<pair<Line, int>> seg;
for (int k = 0; k < n; k++) {
for (auto line : l_list[k]) {
//* check if line crosses this slicing
if (fcmp(x_list[i], min(line.sp.x, line.ep.x)) >= 0 and fcmp(max(line.sp.x, line.ep.x), x_list[i+1]) >= 0) {
Point sub = line.ep - line.sp;
double t_sp = (x_list[i] - line.sp.x) / sub.x, t_ep = (x_list[i+1] - line.sp.x) / sub.x;
seg.eb(Line(Point(x_list[i], line.sp.y + sub.y * t_sp), Point(x_list[i+1], line.sp.y + sub.y * t_ep)), k);
}
}
}
//* sort this slicing
sort(al(seg));
deq<bool> inside(n);
int count = 0;
Line prev;
// cout << x_list[i] << ' ' << x_list[i+1] << endl;
//* calculate cover area in this slicing.
for (int k = 0; k < seg.size(); k++) {
if (count)
cover += ((seg[k].F.sp.y - prev.sp.y) + (seg[k].F.ep.y - prev.ep.y)) * (x_list[i+1] - x_list[i]);
prev = seg[k].F;
// cout << seg[k].S << ": (" << seg[k].F.sp.x << ", " << seg[k].F.sp.y << "), (" << seg[k].F.ep.x << ", " << seg[k].F.ep.y << ")" << endl;
inside[k] = !inside[k];
count += (inside[k] ? 1 : -1);
}
}
//* answer
cout << total / 2 << ' ' << cover / 2;
}
I can't not figure out which part I made a mistake :(
Last night I was working on the "Longest Palindromic Subsequence" problem on leetcode. After completing it I took a look at the fastest answer, and to my surprise it was a giant custom bitset implementation. I decided to try and reverse engineer it a bit and see if I could implement it using std::bitset, but I've run into some issues.
Here's the code:
#if __cplusplus>199711L //c++11
#include<unordered_map>
#endif
const int N=1005;
template<int S>
struct BitSet{
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
typedef unsigned long long uint; //typedef unsigned int uint;
uint a[get_size(S)];int size;
void reset(){memset(a,0,sizeof(uint)*size);}
BitSet():size(get_size(S)){reset();}
BitSet(uint x):size(get_size(S)){reset();a[0]=x;}
BitSet(const BitSet<S> &x):size(get_size(S)){*this=x;}
BitSet& set(int x,int y){
//if (y<0||y>1){printf("error!\n");return *this;}
int X=x>>W,Y=x&mask;
if (y)a[X]|=1ull<<Y;else a[X]&=~(1ull<<Y);
return *this;
}
int find(int x){int X=x>>W,Y=x&mask;return (a[X]>>Y)&1ull;}
int operator [](int x){return find(x);}
BitSet& operator =(const BitSet &y){
memcpy(a,y.a,sizeof(uint)*size);
return *this;
}
BitSet<S> operator |(const BitSet<S> &y)const{return BitSet<S>(*this)|=y;}
BitSet<S> operator &(const BitSet<S> &y)const{return BitSet<S>(*this)&=y;}
BitSet<S> operator ^(const BitSet<S> &y)const{return BitSet<S>(*this)^=y;}
BitSet<S> operator +(const BitSet<S> &y)const{return BitSet<S>(*this)+=y;}
BitSet<S> operator -(const BitSet<S> &y)const{return BitSet<S>(*this)-=y;}
BitSet<S> operator <<(int x)const{return BitSet<S>(*this)<<=x;}
BitSet<S> operator >>(int x)const{return BitSet<S>(*this)>>=x;}
BitSet<S> operator ~()const{return BitSet<S>(*this).flip();}
BitSet<S>& operator =(const char *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!='0'&&s[i]!='1')break;
int X=i>>W,Y=i&mask;
if (s[i]=='1')a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator =(const int *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!=0&&s[i]!=1)break;
int X=i>>W,Y=i&mask;
if (s[i]==1)a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator <<=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
if (delta==0)for (uint *p=a+size-1,*q=p-shift,*end=a+shift-1;p!=end;--p,--q)*p=*q;
else {
for (uint *p=a+size-1,*q1=p-shift,*q2=p-shift-1,*end=a+shift;p!=end;--p,--q1,--q2)*p=(*q1<<delta)|(*q2>>delta1);
a[shift]=a[0]<<delta;
}
memset(a,0,sizeof(uint)*shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0;
return *this;
}
BitSet<S>& operator >>=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
correction();
if (delta==0)for (uint *p=a,*q=p+shift,*end=a+size-shift;p!=end;++p,++q)*p=*q;
else {
for (uint *p=a,*q1=p+shift,*q2=p+shift+1,*end=a+size-shift-1;p!=end;++p,++q1,++q2)*p=(*q1>>delta)|(*q2<<delta1);
a[size-shift-1]=a[size-1]>>delta;
}
memset(a+size-shift,0,sizeof(uint)*shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA|=*startB;++startA;++startB;}
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA&=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator ^=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA^=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator +=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1+*q+t;
t=(*p<p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1-*q-t;
t=(*p>p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
operator bool(){return count()>0;}
BitSet<S>& flip(){
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0=~*p0; p0+=4;
*p1=~*p1; p1+=4;
*p2=~*p2; p2+=4;
*p3=~*p3; p3+=4;
}
for (int i=0;i<(size&3);++i,++p0)*p0=~*p0;
return *this;
}
//void flip(){*this=~*this;}
void flip(int x){a[x>>W]^=1ull<<(x&mask);}
int popcount(uint x)const{
x-=(x&0xaaaaaaaaaaaaaaaaull)>>1;
x=((x&0xccccccccccccccccull)>>2)+(x&0x3333333333333333ull);
x=((x>>4)+x)&0x0f0f0f0f0f0f0f0full;
return (x*0x0101010101010101ull)>>56;
}
int count(){
int res=0;
correction();
for (int i=0;i<size;++i)res+=__builtin_popcountll(a[i]); //popcount
return res;
}
int clz(){
correction();
int res=0;
if (a[size-1])res=__builtin_clzll(a[size-1])-(mask+1-(S&mask));
else {
res+=S&mask;
for (int i=size-2;i>=0;--i)
if (a[i]){res+=__builtin_clzll(a[i]); break;}
else res+=mask+1;
}
return res;
}
int ctz(){
correction();
int res=0;
for (int i=0;i<size;++i)
if (a[i]){res+=__builtin_ctzll(a[i]); break;}
else res+=mask+1;
return min(res,S);
}
int ffs(){
int res=ctz()+1;
if (res==S+1)res=0;
return res;
}
uint to_uint(){
correction();
return a[0];
}
void print(){
for (int i=0;i<size;++i)
for (int j=0;j<=mask&&(i<<W)+j+1<=S;++j)printf("%I64d",(a[i]>>j)&1ull);
printf("\n");
}
void correction(){if (S&mask)a[size-1]&=(1ull<<(S&mask))-1;}
#undef mask
#undef W
#undef get_size
};
int a[N],b[N];
BitSet<N> row[2],X,Y;
unordered_map<int,vector<int> > S;
unordered_map<int,BitSet<N> > match;
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n=s.size(),m=n;
S.clear();match.clear();row[1].reset();
for (int i=0;i<n;++i)a[i]=int(s[i]),S[a[i]].push_back(i);
for (int i=0;i<m;++i)b[i]=int(s[n-1-i]);
for (int i=0;i<m;++i)if (match.find(b[i])==match.end()){
unordered_map<int,BitSet<N> >::iterator x=match.insert(make_pair(b[i],BitSet<N>())).first;
for (vector<int>::iterator j=S[b[i]].begin();j!=S[b[i]].end();++j)x->second.set(*j,1);
}
for (int i=0,now=0;i<m;++i,now^=1)
X=(row[now^1]|match[b[i]]).set(n,1),row[now]=(X&((X-(row[now^1]<<1).set(0,1))^X)).set(n,0);
return row[(m-1)&1].count();
}
};
And here's my attempt at cleaning it up/understanding it:
Bitset.h:
#pragma once
//#if __cplusplus>199711L //c++11
#include<unordered_map>
//#endif
#include <intrin.h>
const int N = 1005; //this size doesn't even matter?? It's just enigmatically assigning a type of int, I guess??
template<int S>
struct BitSet {
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
//members
typedef unsigned long long uint; //typedef unsigned int uint; //not sure why they didn't just use size_t here...
uint a[get_size(S)]; //represents the "BitSet" I think...
int size;
//constructors
BitSet() :size(get_size(S)) { reset(); }
BitSet(uint x) :size(get_size(S)) { reset(); a[0] = x; }
BitSet(const BitSet<S>& x) :size(get_size(S)) { *this = x; }
//utility functions
BitSet& set(int x, int y) {
//if (y<0||y>1){printf("error!\n");return *this;}
int X = x >> W, Y = x & mask; //bit shift with the magic numbers??? //What is the significance of 6, 63, and 1005?
if (y)a[X] |= 1ull << Y; else a[X] &= ~(1ull << Y);
return *this;
}
void reset() { memset(a, 0, sizeof(uint) * size); }
int find(int x) { int X = x >> W, Y = x & mask; return (a[X] >> Y) & 1ull; }
//void flip(){*this=~*this;}
void flip(int x) { a[x >> W] ^= 1ull << (x & mask); }
int popcount(uint x)const {
x -= (x & 0xaaaaaaaaaaaaaaaaull) >> 1;
x = ((x & 0xccccccccccccccccull) >> 2) + (x & 0x3333333333333333ull);
x = ((x >> 4) + x) & 0x0f0f0f0f0f0f0f0full;
return (x * 0x0101010101010101ull) >> 56;
}
int count() {
int res = 0;
correction();
for (int i = 0; i < size; ++i)res += __popcnt(a[i]); //popcount // __builtin_popcountll is only available on GCC apparently. Substituted with library version.
return res;
}
int clz() {
correction();
int res = 0;
if (a[size - 1])res = __builtin_clzll(a[size - 1]) - (mask + 1 - (S & mask));
else {
res += S & mask;
for (int i = size - 2; i >= 0; --i)
if (a[i]) { res += __builtin_clzll(a[i]); break; }
else res += mask + 1;
}
return res;
}
int ctz() {
correction();
int res = 0;
for (int i = 0; i < size; ++i)
if (a[i]) { res += __builtin_ctzll(a[i]); break; }
else res += mask + 1;
return min(res, S);
}
int ffs() {
int res = ctz() + 1;
if (res == S + 1)res = 0;
return res;
}
uint to_uint() {
correction();
return a[0];
}
void print() {
for (int i = 0; i < size; ++i)
for (int j = 0; j <= mask && (i << W) + j + 1 <= S; ++j)printf("%I64d", (a[i] >> j) & 1ull);
printf("\n");
}
void correction() { if (S & mask)a[size - 1] &= (1ull << (S & mask)) - 1; }
BitSet<S>& flip() {
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint* p0 = a, * p1 = p0 + 1, * p2 = p0 + 2, * p3 = p0 + 3, * pend = a + ((size >> 2) << 2);
while (p0 != pend) {
*p0 = ~*p0; p0 += 4;
*p1 = ~*p1; p1 += 4;
*p2 = ~*p2; p2 += 4;
*p3 = ~*p3; p3 += 4;
}
for (int i = 0; i < (size & 3); ++i, ++p0)*p0 = ~*p0;
return *this;
}
//operators
int operator [](int x) { return find(x); }
BitSet& operator =(const BitSet& y) {
memcpy(a, y.a, sizeof(uint) * size);
return *this;
}
BitSet<S>& operator =(const char* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != '0' && s[i] != '1')break;
int X = i >> W, Y = i & mask;
if (s[i] == '1')a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S>& operator =(const int* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != 0 && s[i] != 1)break;
int X = i >> W, Y = i & mask;
if (s[i] == 1)a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S> operator |(const BitSet<S>& y)const { return BitSet<S>(*this) |= y; }
BitSet<S> operator &(const BitSet<S>& y)const { return BitSet<S>(*this) &= y; }
BitSet<S> operator ^(const BitSet<S>& y)const { return BitSet<S>(*this) ^= y; }
BitSet<S> operator +(const BitSet<S>& y)const { return BitSet<S>(*this) += y; }
BitSet<S> operator -(const BitSet<S>& y)const { return BitSet<S>(*this) -= y; }
BitSet<S> operator <<(int x)const { return BitSet<S>(*this) <<= x; }
BitSet<S> operator >>(int x)const { return BitSet<S>(*this) >>= x; }
BitSet<S> operator ~()const { return BitSet<S>(*this).flip(); }
BitSet<S>& operator <<=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
if (delta == 0)for (uint* p = a + size - 1, *q = p - shift, *end = a + shift - 1; p != end; --p, --q)*p = *q;
else {
for (uint* p = a + size - 1, *q1 = p - shift, *q2 = p - shift - 1, *end = a + shift; p != end; --p, --q1, --q2)*p = (*q1 << delta) | (*q2 >> delta1);
a[shift] = a[0] << delta;
}
memset(a, 0, sizeof(uint) * shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0; //if this is a left shift... why is it setting the beginning of the "a" array to 0???... unless the damn array is "backwards". Sheesh.
//wait... this is a right shift according to https://orthallelous.wordpress.com/2019/10/24/magic-numbers-encoding-truth-tables-into-giant-single-values/ ... fuck.
return *this;
}
BitSet<S>& operator >>=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
correction();
if (delta == 0)for (uint* p = a, *q = p + shift, *end = a + size - shift; p != end; ++p, ++q)*p = *q;
else {
for (uint* p = a, *q1 = p + shift, *q2 = p + shift + 1, *end = a + size - shift - 1; p != end; ++p, ++q1, ++q2)*p = (*q1 >> delta) | (*q2 << delta1);
a[size - shift - 1] = a[size - 1] >> delta;
}
memset(a + size - shift, 0, sizeof(uint) * shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA |= *startB; ++startA; ++startB; }
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA &= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator ^=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA ^= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator +=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
operator bool() { return count() > 0; }
#undef mask
#undef W
#undef get_size
};
LeetCode516.cpp
// LeetCode516.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include "BitSet.h"
#include <bitset>
// If parameter is not true, test fails
// This check function would be provided by the test framework
#define IS_TRUE(x) { if (!x) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; else std::cout << __FUNCTION__ << " passed" << std:: endl;}
int longestPalindromeSubseq(std::string s) {
int a[N] = { 0 }, b[N] = { 0 }; //2 integer arrays - initialzing to 0 isn't necessary, but seems to make the debug output more readable?
BitSet<N> row[2], X, Y; //3 bitsets... one of them is actually 2 (lol)
std::unordered_map<int, std::vector<int>> S; //This map tracks the number of occurrences of each letter?
std::unordered_map<int, BitSet<N>> match;
int n = s.size(), m = n;
S.clear();
match.clear();
//row[1].reset(); //WTF is this? Garbage.
//For each piece of the string, cast it from a char to an int and shove it in the first array, then push back a copy of each array into the UOMap S.
for (int i = 0; i < n; ++i) {
a[i] = static_cast<int>(s[i]); //changed C-style cast to static_cast
S[a[i]].push_back(i);
}
//Set the second array to a backwards copy of A I guess? (while converting the characters to integers ofc)
for (int i = 0; i < m; ++i) {
b[i] = int(s[n - 1 - i]);
}
for (int i = 0; i < m; ++i) {
//so if it's the first loop iteration or the find (working on the "backwards" array) matches the end, do this:
if (match.find(b[i]) == match.end()) { //how does this even run the first time? Match is getting cleared and never set? I guess it's working because "find(b[i])" and "end()" are both 0? - Kind of - turns out that if the find function fails, it returns "end"...
//Insert a new bitset with a "key" of "b[i]" into the match map.
auto x = match.insert(std::make_pair(b[i], BitSet<N>())).first; // replaced std::unordered_map<int, BitSet<N> >::iterator with auto... that's nice.
//Then using the iterator we just created above, loop through all entries in UOMap S under that key and ???
//Since we found it in "match", lets check for it(?) in UOMap S... and then set some bit in match based on how many entries there are in S?
for (auto j = S[b[i]].begin(); j != S[b[i]].end(); ++j) {
x->second.set(*j, 1); //this is setting some bit value in "match" to 1 I guess.
}
}
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1) { //Is "*=" being intentionally obfuscated here to "^=" or is it actually different?? Ugh... nasty.
X = (row[now ^ 1] | match[b[i]]).set(n, 1); // if the caret is supposed to represent XOR, why does this still work whenever I replace it with a *... very funky.
row[now] = (X & ((X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
}
return row[(m - 1) & 1].count();
}
template<int S>
std::bitset<S>& operator-(const std::bitset<S>&y) { return std::bitset<S>(*this) -= y; }
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
template<size_t S>
std::bitset<S>& operator-(std::bitset<S>& y, const std::bitset<S>& z) {
//return std::bitset<S>(*this) -= y;
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0]; //z.a
while (p != end) {
size_t p1 = *p;
*p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator+(std::bitset<S>& y, const std::bitset<S>& z) {
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0];
while (p != end) {
size_t p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator -=(const std::bitset<S>& y) {
uint t = 0, * p = a, * end = a + size;
const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
int LPS_STL(std::string s) {
const int M = 1005;
int c[M], d[M];
std::bitset<M> row[2], X, Y;
std::unordered_map<int, std::vector<int> > S;
std::unordered_map<int, std::bitset<M> > match;
int n = s.size(), m = n;
S.clear();
match.clear();
row[1].reset();
for (int i = 0; i < n; ++i)c[i] = int(s[i]), S[c[i]].push_back(i);
for (int i = 0; i < m; ++i)d[i] = int(s[n - 1 - i]);
for (int i = 0; i < m; ++i)if (match.find(d[i]) == match.end()) {
std::unordered_map<int, std::bitset<M> >::iterator x = match.insert(std::make_pair(d[i], std::bitset<M>())).first;
for (std::vector<int>::iterator j = S[d[i]].begin(); j != S[d[i]].end(); ++j)x->second.set(*j, 1);
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1)
X = (row[now ^ 1] | match[d[i]]).set(n, 1), row[now] = (X & (( X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
return row[(m - 1) & 1].count();
}
void test1() {
int test = longestPalindromeSubseq("");
IS_TRUE(test == 0);
}
void test2() {
int test = longestPalindromeSubseq("bbbab");
IS_TRUE(test == 4);
}
void test3() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 2);
}
void test4() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 0); //purposefully fail
}
void test5() {
int test = longestPalindromeSubseq("cacbcbba");
IS_TRUE(test == 5);
}
void test6() {
int test = longestPalindromeSubseq("eeeecdeabfbeeb");
IS_TRUE(test == 7);
}
//Std::bitset tests
//void test7() {
// int test = LPS_STL("");
// IS_TRUE(test == 0);
//}
//void test8() {
// int test = LPS_STL("bbbab")
// IS_TRUE(test == 4);
//}
int main()
{
std::cout << "Longest Palindrome Subsequence\n";
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
}
Main question: Is there a core reason this person chose to implement a custom bitset instead of the std library?
Extraneous questions:
Is some of this code intentionally obfuscated?
It feels a bit naive to ask this, but do some of you intentionally code this way?
Why are they using the value of N (an int) as the type for their bitsets?
Some of their formulas are incredibly long.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Is this question more appropriate for another SO site, such as Code Review?
Is some of this code intentionally obfuscated?
It is just faster to type
#define W 6
than
constexpr size_t bitcoverage { std::bitwidth(sizeof(int64_t)*CHAR_BIT)-1 }; // bits needed to represent 8*8=64 2^7 so 7-1=6 which 0-63 bits.
(if I got it right ...)
It feels a bit naive to ask this, but do some of you intentionally code this way?
When I started programming I did, now I have realized that code is read more than written and it could confuse people, including me, who read it later.
Why are they using the value of N (an int) as the type for their bitsets?
N is just how many entries there is max, see the link you provided.
It actually uses an int64_t to store the bits. Which for many operaton on most larger CPU's is far more efficient than the same doing the same operation on an byte as you can do or/and/etc on a lot of bits with just one instuction.
Some of their formulas are incredibly long.
I am not sure which your are speculating about.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Again, what exact are you referring to?
I am doing the "Game of life" as an assignment for the college, the tutor has given to us part of the code, but I am having problem for understand two parts.
First:
grid(int scale) : scale_(scale), width_(problem_definition::width(scale)), height_(problem_definition::height(scale)), data_(new problem_definition::data_type[width_*height_])
Until I can understand is the moment that he requests for the memory which is used for the grid for the simulation. However, I can not grasp the syntax beyond the new. why are those brackets with an empty space? what does mean the colon after grid (int scale)?
Second:
void initialize()
{
for (std::size_t y = 0; y < height_; ++y)
{
for (std::size_t x = 0; x < width_; ++x)
{
at(x,y) = problem_definition::initialize(x, y, scale_);
}
}
}
what is this "at()" inside the second for loop?
I would appreciate any insight here is the full struct definition:
struct grid
{
grid(int scale) : scale_(scale), width_(problem_definition::width(scale)), height_(problem_definition::height(scale)), data_(new problem_definition::data_type[width_*height_])
{
}
void initialize()
{
for (std::size_t y = 0; y < height_; ++y)
{
for (std::size_t x = 0; x < width_; ++x)
{
at(x,y) = problem_definition::initialize(x, y, scale_);
}
}
}
problem_definition::data_type at(std::size_t x, std::size_t y, int dx, int dy)
{
if (dx<0 && -dx>x) return problem_definition::out_of_bounds_value();
if (dy<0 && -dy>y) return problem_definition::out_of_bounds_value();
if (x + dx >= width_) return problem_definition::out_of_bounds_value();
if (y + dy >= height_) return problem_definition::out_of_bounds_value();
return at((int)x + dx, (int)y + dy);
}
problem_definition::data_type& at(std::size_t x, std::size_t y)
{
return data_[x + y*width_];
}
void swap(grid& other)
{
std::swap(scale_, other.scale_);
std::swap(width_, other.width_);
std::swap(height_, other.height_);
std::swap(data_, other.data_);
}
void print(std::ostream& str)
{
for (std::size_t y = 0; y < height_; ++y)
{
for (std::size_t x = 0; x < width_; ++x)
{
str << at(x, y);
}
str << std::endl;
}
}
private:
int scale_;
std::size_t width_;
std::size_t height_;
std::unique_ptr<problem_definition::data_type[]> data_;
};
Let's add some white space to the first line to make it easier to read:
grid(int scale) : scale_(scale),
width_(problem_definition::width(scale)),
height_(problem_definition::height(scale)),
data_(new problem_definition::data_type[width_*height_])
Now we can easily see the colon (a : is a colon, a ; is a semicolon) defines an initialiser list which takes a series of var(value) pairs and assigns each value to each var.
I don't see any "brackets with an empty space" so can't answer that. But beyond new is just a standard array type of the form: element_type[length]. The element type is problem_definition::data_type and the array is of length width_ times height_.
Finally, at() is just a function call that returns a reference. If you study the function definition:
problem_definition::data_type& at(std::size_t x, std::size_t y)
{
return data_[x + y*width_];
}
then you can see the line with the call to at(), via the magic of references, is the same as the following:
data_[x + y*width_] = problem_definition::initialize(x, y, scale_);
I have declared a class Image with two operator() functions, one for read-only, the other for read-and-write access.
Here an extract:
class Image {
//...
public:
uint16_t operator()(int x, int y) const
{
return data_[x + y*width_]; // read-only at pixle (x,y)
}
uint16_t & operator()(int x, int y)
{
return data_[x + y*width_]; // read/write to pixle (x,y)
}
//...
}
After this, I declared an object of Image in the main() function and wrote to it (which has to work because of the mentioned public Interface operator()), but several compilers only keep recognizing the first operator() function which has only permission to read.
Example of this:
if (count_alive_neighbors(image, i, j) == 3) {
image(i, j) = 255;
}
My thought was that maybe one could overcome this problem by declaring a pointer and by this changing the value. Code for this:
uint16_t* f = &image(i, j);
*f = 255;
On Microsoft Visual Studio 2015 this first worked tested alone outside the if-loop, but inside the just mentioned function it didn't. But it's not a compiler error, I've tested it with Clang, g++ and MinGW.
All are printing out an error message like this:
error: lvalue required as unary '&' operand
uint16_t* f = &(image(i, j));
^
To sum it up, the question is the following: how could one overcome this problem by not focusing on that pointer declarations, what can one do to tell the compiler which version of operator() it has to use? It doesn't recognize it on its own or maybe I'm not recognizing which settings/code one has to change to make the program work.
Thanks in advance.
edit: whole class definition and function
#include <vector>
#include <string>
#include <stdexcept>
#include <fstream>
#include <cstdint>
class Image
{
int width_;
int height_;
std::vector<uint16_t> data_;
public:
Image()
: width_(0)
, height_(0)
{}
Image(unsigned int width, unsigned int height)
: width_(width)
, height_(height)
, data_(width*height, uint16_t())
{}
int width() const
{
return width_;
}
int height() const
{
return height_;
}
int size() const
{
return width_*height_;
}
void resize(unsigned int new_width, unsigned int new_height)
{
data_.resize(new_width*new_height, uint16_t());
width_ = new_width;
height_ = new_height;
}
uint16_t operator()(int x, int y) const
{
return data_[x + y*width_];
}
uint16_t & operator()(int x, int y)
{
return data_[x + y*width_];
}
uint16_t get_periodic(int x, int y) const
{
int xres = x % width_;
int yres = y % height_;
return data_[xres + yres*width_];
}
};
int count_alive_neighbors(Image const & image, int x, int y) {
int res = 0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (image.get_periodic(x + i, y + j) == 255) {
res += 1;
}
}
}
if (image.get_periodic(x, y) == 255) {
res -= 1;
}
}
Image conway_step(Image const & image) {
for (int i = 0; i <= image.width(); i++) {
for (int j = 0; j <= image.height(); j++) {
if (count_alive_neighbors(image, i, j) == 2)
{
}
if (count_alive_neighbors(image, i, j) == 3) {
image(i, j) = 255;
}
if (count_alive_neighbors(image, i, j) < 2) {
image(i, j) = 0;
}
if (count_alive_neighbors(image, i, j) > 3) {
image(i, j) = 255;
}
}
}
}
int main() {
Image img(3, 3); // declaring object
img(3, 3) = 255; /* !ATTENTION! this works, but inside
conway_steps it doesn't */
}
[Based on the comments] conway_step is supposed to make a copy of its argument, modify that copy, and return the copy. Your problem is that you don't make the copy and try to modify the original.
Please change your function signature from
Image conway_step(Image const & image)
to
Image conway_step(Image & const image) //ill formed
or in a better way
Image conway_step(Image & image)
In first case, it is equivalent to const Image & image, so it calls the const qualified operator => image(i, j)=255; => uint16_t=255 => left operand must be l-value error
In second/third case, you declare a const reference to a non const object.
I have an Eigen MatrixXd object, called v, and I am facing some problems when trying to access this matrix content. When I only print the content at the console (as in the code), works just as fine. When I try to use the content, the error shows up:
Assertion failed: (row >= 0 && row < rows() && col >= 0 && col < cols()), function operator(), file /usr/local/Cellar/eigen/3.2.4/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h, line 337.
ChosenPoint ** points = new ChosenPoint*[width];
for (int i = 0; i < width; i++)
{
points[i] = new ChosenPoint[height];
for (int j = 0; j < height; j++)
{
points[i][j].setPoint(i, j, false);
points[i][j].setNumberOfFrames(numberOfFrames);
}
}
Matrix<double, 2, 1> v = (aT * a).inverse() * aT * b;
if (v.rows() == 2 && v.cols() == 1)
{
points[x][y].setFlow(v(0,0), v(1,0), frame);
}
And my ChosenPoint class:
typedef struct point
{
double x;
double y;
bool isValid;
} point;
class ChosenPoint
{
public:
ChosenPoint()
{
}
~ChosenPoint()
{
}
void setNumberOfFrames(int numberOfFrames)
{
this->flow = new point[numberOfFrames];
for (int i = 0; i < numberOfFrames; i++)
{
point f;
f.x = 0.0;
f.y = 0.0;
this->flow[i] = f;
}
}
void setPoint(int x, int y, bool isValid)
{
this->pt.x = (double) x;
this->pt.y = (double) y;
this->pt.isValid = isValid;
}
point getPoint()
{
return this->pt;
}
point* getFlow()
{
return this->flow;
}
void setFlow(double &xFlow, double &yFlow, int &position)
{
this->flow[position].x = xFlow;
this->flow[position].y = yFlow;
}
void updateFlow(int position)
{
this->flow[position].x = 2*this->flow[position].x;
this->flow[position].y = 2*this->flow[position].y;
}
void updateFlow(double xFlow, double yFlow, int position)
{
this->flow[position].x = xFlow;
this->flow[position].y = yFlow;
}
point pt;
point *flow;
};
My fault. The problem was with one of the other matrixes that I was using in the project, and took me a while to figure it out. Unfortunately, Eigen doesn`t seem to be really helpful when this happens:
I had 2 matrixes (A and B). The matrix with problem was A (somehow, some data was not loaded into the matrix). But when i multiplied A and B, it generated a new matrix C with some valid results (all my sanity checks were unuseful). I admit I don`t know a lot of Eigen.
Anyway, hope this is helpful for more people like me.