Problem: Each item in the game has a level. The higher the level is, the higher basic parameters the item has. We shall consider only the following basic parameters: attack (atk), defense (def) and resistance to different types of impact (res).

Each item belongs to one class. In this problem we will only consider three of such classes: weapon, armor, orb.

Besides, there's a whole new world hidden inside each item. We can increase an item's level travelling to its world. We can also capture the so-called residents in the Item World

Residents are the creatures that live inside items. Each resident gives some bonus to the item in which it is currently located. We will only consider residents of types: gladiator (who improves the item's atk), sentry (who improves def) and physician (who improves res).

Each item has the size parameter. The parameter limits the maximum number of residents that can live inside an item. We can move residents between items. Within one moment of time we can take some resident from an item and move it to some other item if it has a free place for a new resident. We cannot remove a resident from the items and leave outside — any of them should be inside of some item at any moment of time.

Laharl has a certain number of items. He wants to move the residents between items so as to equip himself with weapon, armor and a defensive orb. The weapon's atk should be largest possible in the end. Among all equipping patterns containing weapon's maximum atk parameter we should choose the ones where the armor’s def parameter is the largest possible. Among all such equipment patterns we should choose the one where the defensive orb would have the largest possible res parameter. Values of the parameters def and res of weapon, atk and res of armor and atk and def of orb are indifferent for Laharl.

Find the optimal equipment pattern Laharl can get.

Input

The first line contains number n (3 ≤ n ≤ 100) — representing how many items Laharl has.

Then follow n lines. Each line contains description of an item. The description has the following form: "name class atk def res size" — the item's name, class, basic attack, defense and resistance parameters and its size correspondingly. 

  * name and class are strings and atk, def, res and size are integers. 
  * name consists of lowercase Latin letters and its length can range from 1 to 10, inclusive. 
  * class can be "weapon", "armor" or "orb". 
  * 0 ≤ atk, def, res ≤ 1000. 
  * 1 ≤ size ≤ 10. 



It is guaranteed that Laharl has at least one item of each class.

The next line contains an integer k (1 ≤ k ≤ 1000) — the number of residents.

Then k lines follow. Each of them describes a resident. A resident description looks like: "name type bonus home" — the resident's name, his type, the number of points the resident adds to the item's corresponding parameter and the name of the item which currently contains the resident. 

  * name, type and home are strings and bonus is an integer. 
  * name consists of lowercase Latin letters and its length can range from 1 to 10, inclusive. 
  * type may be "gladiator", "sentry" or "physician". 
  * 1 ≤ bonus ≤ 100. 



It is guaranteed that the number of residents in each item does not exceed the item's size.

The names of all items and residents are pairwise different.

All words and numbers in the input are separated by single spaces.

Output

Print on the first line the name of the weapon in the optimal equipping pattern; then print the number of residents the weapon contains; then print the residents' names.

Print on the second and third lines in the same form the names of the armor and defensive orb as well as the residents they contain. 

Use single spaces for separation.

If there are several possible solutions, print any of them.

Examples

Input

4
sword weapon 10 2 3 2
pagstarmor armor 0 15 3 1
iceorb orb 3 2 13 2
longbow weapon 9 1 2 1
5
mike gladiator 5 longbow
bobby sentry 6 pagstarmor
petr gladiator 7 iceorb
teddy physician 6 sword
blackjack sentry 8 sword


Output

sword 2 petr mike 
pagstarmor 1 blackjack 
iceorb 2 teddy bobby 


Input

4
sword weapon 10 2 3 2
pagstarmor armor 0 15 3 1
iceorb orb 3 2 13 2
longbow weapon 9 1 2 1
6
mike gladiator 5 longbow
bobby sentry 6 pagstarmor
petr gladiator 7 iceorb
teddy physician 6 sword
blackjack sentry 8 sword
joe physician 6 iceorb


Output

longbow 1 mike 
pagstarmor 1 bobby 
iceorb 2 petr joe 

Note

In the second sample we have no free space inside the items, therefore we cannot move the residents between them.

Solution (in JAVA):

Solution:


import java.awt.Point;
import java.io.*;
import java.math.BigInteger;
import java.util.*;

import static java.lang.Math.*;

public class ProblemB_81 {
    
    final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE")!=null;
    BufferedReader in;
    PrintWriter out;
    StringTokenizer tok = new StringTokenizer("");
    
    void init() throws FileNotFoundException{
        if (ONLINE_JUDGE){
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        }else{
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }
    
    String readString() throws IOException{
        while(!tok.hasMoreTokens()){
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }
    
    int readInt() throws IOException{
        return Integer.parseInt(readString());
    }
    
    long readLong() throws IOException{
        return Long.parseLong(readString());
    }
    
    double readDouble() throws IOException{
        return Double.parseDouble(readString());
    }
    
    public static void main(String[] args){
        new ProblemB_81().run();
    }
    
    public void run(){
        try{
            long t1 = System.currentTimeMillis();
            init();
            solve();
            out.close();
            long t2 = System.currentTimeMillis();
            System.err.println("Time = "+(t2-t1));
        }catch (Exception e){
            e.printStackTrace(System.err);
            System.exit(-1);
        }
    }
    
    class Res implements Comparable<Res>{
        
        String name;
        int type;
        int bonus;
        
        public Res(String name, String type, int bonus){
            this.name = name;
            this.type = type.equals("gladiator")? 0: type.equals("sentry")? 1: 2;
            this.bonus = bonus;
        }
        
        public Res(Res r){
            name = r.name;
            type = r.type;
            bonus = r.bonus;
        }

        @Override
        public int compareTo(Res r) {
            return r.bonus - bonus;
        }
    }
    
    class Item{
        
        String name;
        int cl;
        int param;
        int size;
        ArrayList<Res> list = new ArrayList<Res>();
        
        public Item(String name, String cls, int atk, int def, int res, int size){
            this.name = name;
            cl = cls.equals("weapon")? 0: cls.equals("armor")? 1: 2;
            param = cl == 0? atk: cl == 1? def: res;
            this.size = size;
            list = new ArrayList<Res>();
        }
        
        public Item(Item i){
            name = i.name;
            cl = i.cl;
            param = i.param;
            size = i.size;
            list = new ArrayList<ProblemB_81.Res>();
            for (Res res: i.list){
                list.add(new Res(res));
            }
        }
    }
    
    void solve() throws IOException{
        int n = readInt();
        HashMap<String, Item> map = new HashMap<String, ProblemB_81.Item>();
        int sz = 0;
        for (int i = 0; i < n; i++){
            String name = readString();
            Item item = new Item(name, readString(), readInt(), readInt(), readInt(), readInt());
            sz += item.size;
            map.put(name, item);
        }
        int k = readInt();
        ArrayList<Res>[] list = new ArrayList[3];
        for (int i = 0; i < 3; i++){
            list[i] = new ArrayList<ProblemB_81.Res>();
        }
        for (int i = 0; i < k; i++){
            Res res = new Res(readString(), readString(), readInt());
            if (k == sz){
                String home = readString();
                map.get(home).list.add(res);
                if (map.get(home).cl == res.type) map.get(home).param += res.bonus; 
            }else{
                readString();
                list[res.type].add(res);
            }
        }
        Item[] max = new Item[3];
        if (k == sz){
            for (int i = 0; i < 3; i++){
                for (String s: map.keySet()){
                    if (map.get(s).cl != i) continue;
                    if (max[i] == null || map.get(s).param > max[i].param){
                        max[i] = map.get(s);
                    }
                }
            }
        }else{
            for (int i = 0; i < 3; i++){
                Collections.sort(list[i]);
            }
            int[][] sum = new int[3][];
            for (int i = 0; i < 3; i++){
                sum[i] = new int[list[i].size()];
                if (sum[i].length == 0) continue;
                sum[i][0] = list[i].get(0).bonus;
                for (int j = 1; j < sum[i].length; j++){
                    sum[i][j] = sum[i][j-1] + list[i].get(j).bonus;
                }
            }
            for (int i = 0; i < 3; i++){
                for (String s: map.keySet()){
                    Item item = map.get(s);
                    if (item.cl != i) continue;
                    int d = item.param;
                    if (sum[i].length != 0 && item.size != 0){
                        d += sum[i][sum[i].length > item.size? item.size - 1: sum[i].length - 1];
                    }
                    if (max[i] == null || d > max[i].param){
                        max[i] = new Item(item);
                        max[i].param = d;
                    }
                }
            }
            for (int i = 0; i < 3; i++){
                int len = min(max[i].size, sum[i].length);
                for (int j = 0; j < len; j++){
                    max[i].list.add(list[i].get(0));
                    list[i].remove(0);
                    max[i].size--;
                }
            }
            for (int i = 0; i < 3; i++){
                if (max[i].size > 0){
                    for (int j = 0; j < 3; j++){
                        if (list[j].size() > 0){
                            while (max[i].size > 0 && list[j].size() > 0){
                                max[i].list.add(list[j].get(0));
                                list[j].remove(0);
                                max[i].size--;
                            }
                        }
                    }
                }
            }
        }
        for (int i = 0; i < 3; i++){
            out.print(max[i].name + " " + max[i].list.size());
            for (Res res: max[i].list){
                out.print(" " + res.name);
            }
            out.println();
        }
    }
    
    static int[][] step8 = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}, {-1, -1}, {1, -1}, {-1, 1}, {1, 1}};
    
    static int[][] stepKnight = {{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};
    
    static long gcd(long a, long b){
        if (a == 0) return b;
        return gcd(b % a, a);
    }
    
    static long lcm(long a, long b){
        return a / gcd(a, b)*b;
    }

    static long[] gcdPlus(long a, long b){
        long[] d = new long[3];
        if (a == 0){
            d[0] = b;
            d[1] = 0;
            d[2] = 1;
        }else{
            d = gcdPlus(b % a, a);
            long r = d[1];
            d[1] = d[2] - b/a*d[1];
            d[2] = r;
        }
        return d;
    }
    
    static long binpow(long a, int n){
        if (n == 0) return 1;
        if ((n & 1) == 0){
            long b = binpow(a, n/2);
            return b*b;
        }else return binpow(a, n - 1)*a;
    }
    
    static long binpowmod(long a, int n, long m){
        if (m == 1) return 0;
        if (n == 0) return 1;
        if ((n & 1) == 0){
            long b = binpowmod(a, n/2, m);
            return (b*b) % m;
        }else return binpowmod(a, n - 1, m)*a % m;
    }
    
    static long phi(long n){
        int[] p = Sieve((int)ceil(sqrt(n)) + 2);
        long phi = 1;
        for (int i = 0; i < p.length; i++){
            long x = 1;
            while (n % p[i] == 0){
                n /= p[i];
                x *= p[i];
            }
            phi *= x - x/p[i];
        }
        if (n != 1) phi *= n - 1;
        return phi;
    }
    
    static long f(long n, int x, int k){ //Кол-во десятичных чисел (включая 0), содержащих в себе цифры от 0 до k-1
        if (n == 0) return 1;
        long b = binpow(10, x - 1);
        long c = n / b;
        return (c < k? c: k)*binpow(k, x - 1) + (c < k? 1: 0)*f(n % b, x - 1, k);
    }
    
    static long fib(int n){
        if (n == 0) return 0;
        if ((n & 1) == 0){
            long f1 = fib(n/2 - 1);
            long f2 = fib(n/2 + 1);
            return f2*f2 - f1*f1;
        }else{
            long f1 = fib(n/2);
            long f2 = fib(n/2 + 1);
            return f1*f1 + f2*f2;
        }
    }
    
    static BigInteger BigFib(int n){
        if (n == 0) return BigInteger.ZERO;
        if ((n & 1) == 0){
            BigInteger f1 = BigFib(n/2 - 1);
            f1 = f1.multiply(f1);
            BigInteger f2 = BigFib(n/2 + 1);
            f2 = f2.multiply(f2);
            return f2.subtract(f1);
        }else{
            BigInteger f1 = BigFib(n/2);
            f1 = f1.multiply(f1);
            BigInteger f2 = BigFib(n/2 + 1);
            f2 = f2.multiply(f2);
            return f2.add(f1);
        }
    }
    
    static public class PointD{
        
        double x, y;
        
        public PointD(double x, double y){
            this.x = x;
            this.y = y;
        }
    }
    
    static double d(Point p1, Point p2){
        return sqrt(d2(p1, p2));
    }
    
    static public double d(PointD p1, PointD p2){
        return sqrt(d2(p1, p2));
    }
    
    static double d2(Point p1, Point p2){
        return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
    }
    
    static public double d2(PointD p1, PointD p2){
        return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y);
    }
    
    static boolean IsProbablyPrime(long n){
        if (n == 1) return false;
        if ((n & 1) == 0) return false;
        for (int j = 3; j < sqrt(n) + 1; j += 2){
            if (n % j == 0) return false;
        }
        return true;
    }

    static int[] Sieve(int n){
        boolean[] b = new boolean[n+1];
        Arrays.fill(b, true);
        b[0] = false;
        b[1] = false;
        long nLong = n;
        int j=0;
        for (int i = 1; i <= n; i++) {
            if (b[i]){
                j++;
                if (((long)i)*i <= nLong) {
                    for (int k = i*i; k <= n; k += i) {
                        b[k] = false;
                    }
                }
            }
        }
        int[] p = new int[j];
        Arrays.fill(p, 0);
        j=0;
        for (int i = 2; i <= n; i++) {
            if (b[i]){
                p[j]=i;
                j++;
            }
        }
        return p;
    }
    
    static int[][] Palindromes(String s){
        char[] c = s.toCharArray();
        int n = c.length;
        int[][] d = new int[2][n];
        int l = 0, r = -1;
        for (int i = 0; i < n; i++){
            int j = (i > r? 0: min(d[0][l+r-i+1], r-i+1)) + 1;
            for (; i - j >= 0 && i + j - 1< n && c[i-j] == c[i+j-1]; j++);
            d[0][i] = --j;
            if (i + d[0][i] - 1 > r){
                r = i + d[0][i] - 1;
                l = i - d[0][i];
            }
        }
        l = 0;
        r = -1;
        for (int i = 0; i < n; i++){
            int j = (i > r? 0: min(d[1][l+r-i], r-i)) + 1;
            for (; i - j >= 0 && i + j < n && c[i-j] == c[i+j]; j++);
            d[1][i] = --j;
            if (i + d[1][i] > r){
                r = i + d[1][i];
                l = i - d[1][i];
            }
        }
        return d;
    }
    
    static public class Permutation {
        
        int[] a;
        int n;
        
        public Permutation(int n){
            this.n=n;
            a=new int[n];
            for (int i=0; i<n; i++){
                a[i]=i;
            }
        }
        
        public boolean nextPermutation(){ //Пишется с do{}while(nextPermutation(a));
            int i=n-1;
            for (i=n-2; i>=0; i--){
                if (a[i]<a[i+1]){
                    break;
                }
            }
            if (i==-1){
                return false;
            }
            int jMin=i+1;
            for (int j=n-1; j>i; j--){
                if (a[i]<a[j]&&a[j]<a[jMin]){
                    jMin=j;
                }
            }
            swap(i, jMin);
            for (int j=1; j<=(n-i)/2; j++){
                swap(i+j, n-j);
            }
            return true;
        }
        
        
        public int get(int i){
            return a[i];
        }
        
        void swap(int i, int j){
            int r=a[i];
            a[i]=a[j];
            a[j]=r;
        }
    }
    
    static public class Fraction implements Comparable<Fraction>, Cloneable{
        
        public final Fraction FRACTION_ZERO = new Fraction();
        public final Fraction FRACTION_ONE = new Fraction(1);
        public long numerator = 0;
        public long denominator = 1;
        
        public Fraction(){
            numerator = 0;
            denominator = 1;
        }
        
        public Fraction(long numerator){
            this.numerator = numerator;
            denominator = 1;
        }
        
        public Fraction(long numerator, long denominator){
            this.numerator = numerator;
            this.denominator = denominator;
            Cancellation();
        }
        
        public Fraction(double numerator, double denominator, int accuracy){
            this.numerator = (long)(numerator*pow(10,accuracy));
            this.denominator = (long)(denominator*pow(10,accuracy));
            Cancellation();
        }
        
        public Fraction(String s){
            if (s.charAt(0) == '-'){
                denominator = -1;
                s = s.substring(1);
            }
            if (s.indexOf("/") != -1){
                denominator *= Integer.parseInt(s.substring(s.indexOf("/") + 1));
            }
            if (s.indexOf(" ") != -1){
                numerator = Integer.parseInt(s.substring(0, s.indexOf(" "))) * abs(denominator) + Integer.parseInt(s.substring(s.indexOf(" ") + 1, s.indexOf("/")));
            }else{
                if (s.indexOf("/") != -1){
                    numerator = Integer.parseInt(s.substring(0, s.indexOf("/")));
                }else{
                    numerator = Integer.parseInt(s)*abs(denominator);
                }
            }
            this.Cancellation();
        }
        
        void Cancellation(){
            long g = gcd(abs(numerator), abs(denominator));
            numerator /= g;
            denominator /= g;
            if (denominator < 0){
                numerator *= -1;
                denominator *= -1;
            }
        }
        
        public String toString(){
            String s = "";
            if (numerator == 0){
                return "0";
            }
            if (numerator < 0){
                s += "-";
            }
            if (abs(numerator) >= denominator){
                s += Long.toString(abs(numerator) / denominator) + " ";
            }
            if (abs(numerator) % denominator != 0){
                s += Long.toString(abs(numerator) % denominator);
            }else{
                s = s.substring(0, s.length()-1);
            }
            if (denominator != 1){
                s += "/" + Long.toString(denominator);
            }
            return s;
        }
        
        public Fraction add(Fraction f){
            Fraction fResult = new Fraction();
            fResult.denominator = lcm(denominator, f.denominator);
            fResult.numerator = numerator * fResult.denominator / denominator + f.numerator * fResult.denominator / f.denominator;
            fResult.Cancellation();
            return fResult;
        }
        
        public Fraction subtract(Fraction f){
            Fraction fResult = new Fraction();
            fResult.denominator = lcm(denominator, f.denominator);
            fResult.numerator = numerator * fResult.denominator / denominator - f.numerator * fResult.denominator / f.denominator;
            fResult.Cancellation();
            return fResult;
        }
        
        public Fraction multiply(Fraction f){
            Fraction fResult = new Fraction();
            fResult.numerator = numerator * f.numerator;
            fResult.denominator = denominator * f.denominator;
            fResult.Cancellation();
            return fResult;
        }
        
        public Fraction divide(Fraction f){
            Fraction fResult = new Fraction();
            fResult.numerator = numerator * f.denominator;
            fResult.denominator = denominator * f.numerator;
            fResult.Cancellation();
            return fResult;
        }
        
        @Override
        public int compareTo(Fraction f){
            long g = gcd(denominator, f.denominator);
            long res = numerator * (f.denominator / g) - f.numerator * (denominator / g);
            if (res < 0){
                return -1;
            }
            if (res > 0){
                return 1;
            }
            return 0;
        }
        
        public Fraction clone(){
            Fraction fResult = new Fraction(numerator, denominator);
            return fResult;
        }
        
        public Fraction floor(){
            Fraction fResult = this.clone();
            fResult.numerator = (fResult.numerator / fResult.denominator) * fResult.denominator;
            return fResult;
        }
        
        public Fraction ceil(){
            Fraction fResult = this.clone();
            fResult.numerator = (fResult.numerator/fResult.denominator + 1) * fResult.denominator;
            return fResult;
        }
        
        public Fraction binpow(int n){
            if (n==0) return FRACTION_ONE;
            if ((n&1)==0){
                Fraction f=this.binpow(n/2);
                return f.multiply(f);
            }else return binpow(n-1).multiply(this);
        }
    }
    
    static public class FenwickTree_1{  //One-dimensional array     
        
        int n;
        long[] t;
        
        public FenwickTree_1(int n){
            this.n = n;
            t = new long[n];
        }
        
        public long sum(int xl, int xr){
            return sum(xr) - sum(xl);
        }
        
        public long sum(int x){
            long result = 0;
            for (int i = x; i >= 0; i = (i & (i + 1)) - 1){
                result += t[i];
            }
            return result;
        }
        
        public void update(int x, long delta){
            for (int i = x; i < n; i = (i | (i + 1))){
                t[i] += delta;
            }
        }
    }
    
    static public class FenwickTree_2{  //Two-dimensional array
        
        int n, m;
        long[][] t;
        
        public FenwickTree_2(int n, int m){
            this.n = n;
            this.m = m;
            t = new long[n][m];
        }
        
        public long sum(int xl, int yl, int xr, int yr){
            return sum(xr, yr) - sum(xl - 1, yr) - sum(xr, yl - 1) + sum(xl - 1, yl - 1);
        }
        
        public long sum(int x, int y){
            long result = 0;
            for (int i = x; i >= 0; i = (i & (i + 1)) - 1){
                for (int j = y; j >= 0; j = (j & (j + 1)) - 1){
                    result+=t[i][j];
                }
            }
            return result;
        }
        
        public void update(int x, int y, long delta){
            for (int i = x; i < n; i = (i | (i + 1))){
                for (int j = y; j < m; j = (j | (j + 1))){
                    t[i][j] += delta;
                }
            }
        }
    }
    
    static public class FenwickTree_3{  //Three-dimensional array
        
        int n, m, l;
        long[][][] t;
        
        public FenwickTree_3(int n, int m, int l){
            this.n = n;
            this.m = m;
            this.l = l;
            t = new long[n][m][l];
        }
        
        public long sum(int xl, int yl, int zl, int xr, int yr, int zr){
            return sum(xr, yr, zr) - sum(xl - 1, yr, zr)
            + sum(xl - 1, yr, zl - 1) - sum(xr, yr, zl - 1)
            - sum(xr, yl - 1, zr) + sum(xl - 1, yl - 1, zr)
            - sum(xl - 1, yl - 1, zl - 1) + sum(xr, yl - 1, zl - 1);
        }
        
        public long sum(int x, int y, int z){
            long result = 0;
            for (int i = x; i >= 0; i = (i & (i + 1)) - 1){
                for (int j = y; j >= 0; j = (j & (j + 1)) - 1){
                    for (int k = z; k >= 0; k = (k & (k + 1)) - 1){
                        result += t[i][j][k];
                    }
                }
            }
            return result;
        }
        
        public void update(int x, int y, int z, long delta){
            for (int i = x; i < n; i = (i | (i + 1))){
                for (int j = y; j < n; j = (j | (j + 1))){
                    for (int k = z; k < n; k = (k | (k + 1))){
                        t[i][j][k] += delta;
                    }
                }
            }
        }
    }
}