#include <bits/stdc++.h>
using namespace std;
struct Point {
  int X, Y;
};
bool operator<(Point A, Point B) {
  return (A.X == B.X) ? (A.Y < B.Y) : (A.X < B.X);
}
struct Node {
  int Left, Right, Count;
  Node *Lc, *Rc;
};
int Get() {
  char c;
  while (c = getchar(), (c < '0' || c > '9') && (c != '-'))
    ;
  bool Flag = (c == '-');
  if (Flag) c = getchar();
  int X = 0;
  while (c >= '0' && c <= '9') {
    X = X * 10 + c - 48;
    c = getchar();
  }
  return Flag ? -X : X;
}
const int inf = 1000000000;
bool Used[9];
int DataY[100000];
int Data[9], S[9];
Point P[100000];
Node *Tree[100001];
Node *Build(int L, int R) {
  Node *P = new Node;
  P->Left = L;
  P->Right = R;
  P->Count = 0;
  if (L < R) {
    int Mid = (L + R) / 2;
    P->Lc = Build(L, Mid);
    P->Rc = Build(Mid + 1, R);
  }
  return P;
}
Node *Insert(Node *P, int X) {
  Node *Q = new Node;
  *Q = *P;
  Q->Count++;
  if (Q->Left < Q->Right) {
    int Mid = (Q->Left + Q->Right) / 2;
    if (X <= Mid)
      Q->Lc = Insert(Q->Lc, X);
    else
      Q->Rc = Insert(Q->Rc, X);
  }
  return Q;
}
int Query(Node *L, Node *R, int K) {
  if (L->Left == L->Right) return L->Left;
  int Left = R->Lc->Count - L->Lc->Count;
  if (K <= Left)
    return Query(L->Lc, R->Lc, K);
  else
    return Query(L->Rc, R->Rc, K - Left);
}
int GetKth(int LB, int UB, int K) { return Query(Tree[LB], Tree[UB], K); }
bool Check() {
  int Left = S[0] + S[1] + S[2];
  int Mid = Left + S[3] + S[4] + S[5];
  int N = Mid + S[6] + S[7] + S[8];
  if (P[Left - 1].X == P[Left].X) return false;
  if (P[Mid - 1].X == P[Mid].X) return false;
  int LB_0 = -inf, UB_0 = inf;
  LB_0 = max(LB_0, GetKth(0, Left, S[0]));
  UB_0 = min(UB_0, GetKth(0, Left, S[0] + 1));
  if (UB_0 - LB_0 < 1) return false;
  LB_0 = max(LB_0, GetKth(Left, Mid, S[3]));
  UB_0 = min(UB_0, GetKth(Left, Mid, S[3] + 1));
  if (UB_0 - LB_0 < 1) return false;
  LB_0 = max(LB_0, GetKth(Mid, N, S[6]));
  UB_0 = min(UB_0, GetKth(Mid, N, S[6] + 1));
  if (UB_0 - LB_0 < 1) return false;
  int LB_1 = -inf, UB_1 = inf;
  LB_1 = max(LB_1, GetKth(0, Left, S[0] + S[1]));
  UB_1 = min(UB_1, GetKth(0, Left, S[0] + S[1] + 1));
  if (UB_1 - LB_1 < 1) return false;
  LB_1 = max(LB_1, GetKth(Left, Mid, S[3] + S[4]));
  UB_1 = min(UB_1, GetKth(Left, Mid, S[3] + S[4] + 1));
  if (UB_1 - LB_1 < 1) return false;
  LB_1 = max(LB_1, GetKth(Mid, N, S[6] + S[7]));
  UB_1 = min(UB_1, GetKth(Mid, N, S[6] + S[7] + 1));
  if (UB_1 - LB_1 < 1) return false;
  printf("%0.6lf %0.6lf\n", (P[Left - 1].X + P[Left].X) * 0.5,
         (P[Mid - 1].X + P[Mid].X) * 0.5);
  printf("%0.6lf %0.6lf\n", (DataY[LB_0] + DataY[UB_0]) * 0.5,
         (DataY[LB_1] + DataY[UB_1]) * 0.5);
  return true;
}
bool DFS(int Depth) {
  if (Depth == 9) return Check();
  for (int i = 0; i < 9; i++)
    if (!Used[i]) {
      Used[i] = true;
      S[Depth] = Data[i];
      if (DFS(Depth + 1)) return true;
      Used[i] = false;
    }
  return false;
}
int main() {
  int N = Get();
  for (int i = 0; i < N; i++) {
    P[i].X = Get();
    P[i].Y = Get();
  }
  sort(P, P + N);
  for (int i = 0; i < N; i++) DataY[i] = P[i].Y;
  sort(DataY, DataY + N);
  int Total = 1;
  for (int i = 1; i < N; i++)
    if (DataY[i - 1] != DataY[i]) DataY[Total++] = DataY[i];
  for (int i = 0; i < N; i++) {
    int Left = 0, Right = Total - 1;
    while (Left < Right) {
      int Mid = (Left + Right) / 2;
      if (DataY[Mid] == P[i].Y)
        Left = Right = Mid;
      else if (DataY[Mid] < P[i].Y)
        Left = Mid + 1;
      else
        Right = Mid - 1;
    }
    P[i].Y = Left;
  }
  Tree[0] = Build(0, Total - 1);
  for (int i = 0; i < N; i++) Tree[i + 1] = Insert(Tree[i], P[i].Y);
  for (int i = 0; i < 9; i++) Data[i] = Get();
  memset(Used, 0, sizeof(Used));
  if (!DFS(0)) printf("-1\n");
}
