/*#include <bits/stdc++.h>
using namespace std;
fstream in ( "laser.in" , ios::in );
fstream out( "laser.out", ios::out );
const int DIM = 520;
bitset<DIM * 2> sys[DIM], ans;
pair<double, double> seg[DIM * 2], ept1[DIM], ept2[DIM];
inline double ccw( const pair<double, double> pt1, const pair<double, double> pt2, const pair<double, double> pt3 ) {
return ( pt2.first - pt1.first ) * ( pt3.second - pt1.second ) -
( pt3.first - pt1.first ) * ( pt2.second - pt1.second );
}
inline bool comp( const pair<double, double> pt1, const pair<double, double> pt2 ) {
return ccw( make_pair( 0, 0 ), pt1, pt2 ) > 0;
}
int main( void ) {
int n, m = 0;
in >> n;
for( int i = 1; i <= n; i ++ ) {
in >> ept1[i].first >> ept1[i].second;
in >> ept2[i].first >> ept2[i].second;
seg[++ m] = ept1[i];
seg[++ m] = ept2[i];
}
for( int i = 1; i <= n; i ++ ) {
bool x;
in >> x;
sys[i][m + 1] = x;
}
sort( seg + 1, seg + m + 1, comp );
seg[m + 1] = seg[1];
for( int i = 1; i <= m; i ++ ) {
pair<double, double> pt1 = make_pair( 0, 0 );
pair<double, double> pt2 = make_pair( ( seg[i].first + seg[i + 1].first ) * 10000,
( seg[i].second + seg[i + 1].second ) * 10000 );
out<<pt2.first<<" "<<pt2.second<<"\n";
for( int j = 1; j <= n; j ++ ) {
if( ccw( pt1, pt2, ept1[j] ) * ccw( pt1, pt2, ept2[j] ) < 0 )
if( ccw( ept1[j], ept2[j], pt1 ) * ccw( ept1[j], ept2[j], pt2 ) < 0 )
sys[j][i] = true;
}
}
for (int i=1;i<=n;i++,out<<endl)
for (int j=1;j<=m+1;j++)
out<<sys[i][j]<<" ";
for( int i = 1, j = 1; i <= n && j <= m; ) {
bool ok = false;
for( int k = i; k <= n; k ++ ) {
if( sys[k][j] == true ) {
swap( sys[i], sys[k] );
ok = true; break;
}
}
if( ok == false )
j ++;
else {
for( int k = i + 1; k <= n; k ++ )
if( sys[k][j] == true )
sys[k] ^= sys[i];
i ++; j ++;
}
}
for( int i = n, j = 1; i >= 1; i --, j = 1 ) {
while( j <= m && sys[i][j] == false )
j ++;
if( j <= m )
ans[j] = sys[i][m + 1];
for( int p = j + 1; p <= m; p ++ )
ans[j] = ans[j] ^ ( ans[p] & sys[i][p] );
}
out << ans.count() << "\n";
for( int i = 1; i <= m; i ++ ) {
if( ans[i] == true ) {
double ang = atan2( ( seg[i].second + seg[i + 1].second ) * 10000,
( seg[i].first + seg[i + 1].first ) * 10000 ) * 180 / acos( -1 );
if( ang < 0 )
ang += 360;
out << setprecision( 6 ) << fixed << ang << "\n";
}
}
return 0;
}*/
#include <bits/stdc++.h>
#define DIM 1000
using namespace std;
ifstream fin ("laser.in");
ofstream fout ("laser.out");
struct point{
double x,y;
};
point points[DIM];
struct segment{
double x,y,x2,y2;
}sgm[DIM];
int a[DIM][DIM],stare[DIM],sol[DIM];
pair <double,double> dr[DIM];
int n,i,j,k;
double X1,Y1,X2,Y2;
vector <double> ans;
inline double get_det (double X1, double Y1, double X2, double Y2, double X3, double Y3){
return (X2-X1)*(Y3-Y1) - (X3-X1)*(Y2-Y1);
}
inline double dist_org (point a){
return a.x*a.x + a.y*a.y;
}
inline double get_dist (double x, double y, double x2, double y2){
return sqrt ((x-x2)*(x-x2) + (y-y2)*(y-y2));
}
inline int cadran (point a){
if (a.x > 0 && a.y >= 0)
return 1;
if (a.x <= 0 && a.y > 0)
return 2;
if (a.x < 0 && a.y <= 0)
return 3;
return 4;
}
inline int cmp (point a, point b){
return get_det (0,0,a.x,a.y,b.x,b.y) > 0;
}
inline int intersectie (double x, double y, double x2, double y2, double x3, double y3){
/// dreapta det de punctele 0,0 si x,y intersecteaza segmentul x2,y2; x3,y3
if (get_det(0,0,x,y,x2,y2) * get_det(0,0,x,y,x3,y3) < 0 && get_det(x2,y2,x3,y3,0,0) * get_det(x2,y2,x3,y3,x,y) < 0)
return 1;
return 0;
}
inline int urm (int x){
if (x < k)
return x+1;
return 1;
}
int main (){
fin>>n;
for (i=1;i<=n;i++){
fin>>X1>>Y1>>X2>>Y2;
points[++k] = {X1,Y1};
points[++k] = {X2,Y2};
sgm[i] = {X1,Y1,X2,Y2};
}
/// sortez punctele dupa unghi
sort (points+1,points+k+1,cmp);
//for (i=1;i<=k;i++)
// fout<<points[i].x<<" "<<points[i].y<<"\n";
/// pt fiecare pereche de puncte consecutive iau bisectoarea
for (i=1;i<=k;i++){
point A = points[i], B = points[urm(i)];
double dist_ob = get_dist (0,0,B.x,B.y);
double dist_oa = get_dist (0,0,A.x,A.y);
double dist_ab = get_dist (A.x,A.y,B.x,B.y);
/// bisectoarea
double xm = A.x*dist_ob/(dist_ob+dist_oa) + B.x*dist_oa/(dist_ob+dist_oa);
double ym = A.y*dist_ob/(dist_ob+dist_oa) + B.y*dist_oa/(dist_ob+dist_oa);
xm *= 10000.0, ym *= 10000.0;
/// acum vad ce segmente intersecteaza
dr[i] = make_pair (xm,ym);
for (int j=1;j<=n;j++){
if (intersectie (xm,ym,sgm[j].x,sgm[j].y,sgm[j].x2,sgm[j].y2))
a[j][i] = 1;
}}
for (i=1;i<=n;i++){
fin>>stare[i];
a[i][k+1] = stare[i];
}
for (i=1;i<=n;i++,fout<<"\n")
for (j=1;j<=k+1;j++)
fout<<a[i][j]<<" ";
/// gauss
int i = 1, j = 1, m = k;
while (i <= n && j <= m){
int lin = i;
while (lin <= n && !a[lin][j])
lin++;
if (lin == n+1){
j++;
continue;
}
if (i != lin){
for (k=1;k<=m+1;k++)
swap (a[i][k],a[lin][k]);
}
for (k=i+1;k<=n;k++){
if (a[k][j]){
for (int t=1;t<=m+1;t++)
a[k][t] ^= a[i][j];
}}
i++, j++;
}
for (i=n;i;i--){
j = 1;
while (j <= m+1 && !a[i][j])
j++;
if (j == m+2)
continue;
sol[j] = a[i][m+1];
for (k=j+1;k<=m;k++)
sol[j] ^= (a[i][k]*sol[k]);
}
for (i=1;i<=m;i++)
if (sol[i]){
/// inseamna ca aleg dreapta asta
double val = atan2 (dr[i].second,dr[i].first);
if (val < 0)
val += 2*3.14159265;
val = val*180 / 3.14159265;
ans.push_back(val);
}
fout<<ans.size()<<"\n";
for (int i=0;i<ans.size();i++)
fout<<setprecision(6)<<fixed<<ans[i]<<"\n";
return 0;
}