Problem:
Problem B: Watchin' TVA

Animation is one of methods for making movies and in Japan, it is popular to broadcast as a television program or perform as a movie. Many people, especially the young, love one. And here is an anime lover called Jack. We say he is an mysterious guy with uncertain age. He likes anime which are broadcasted in midnight and early morning especially.

In his room, there is a huge piece of paper on the wall. He writes a timetable of TV anime on it. In his house, he can watch all Japanese TV anime programs that are broadcasted in Japan using a secret and countrywide live system. However he can not watch all anime and must give up to watch some programs because they are "broadcasted at the same time" in a season. Here, programs are "broadcasted at the same time" means that two or more programs have one or more common minutes in broadcasting time. Increasing the number of anime programs in recent makes him nervous. Actually, some people buy DVDs after the program series ends or visit a web site called vhefoo. Anyway, he loves to watch programs on his live system. Of course, he is not able to watch two or more programs at the same time. However, as described above, he must give up some programs broadcasted at the same time. Therefore, he has a set of programs F and he watches programs in a set F absolutely.

Your task is to write a program that reads a timetable and outputs the maximum number of watchable programs, keeping that Jack watches all programs in the set F. Of course, there are multiple choices of programs, so we want the number of programs he can watch. If two or more programs in a set F are broadcasted at the same time, you must give Jack an unfortunate announcement. In this case, your program outputs -1. In addition, each anime program is a program of 30 minutes.

Input

Input consists of multiple datasets.

A dataset is given in a following format.

N
PROGRAM1
PROGRAM2
...
PROGRAMN
P
FAV1
FAV2
...
FAVP

N is the number of programs in a season.

PROGRAMi(1≤i≤N)is a string which has the following format.

name weekday start

name is a program name. This is a a string having between 1 and 32 characters and these names do not overlap each other program. A name consists of alphanumeric characters and '_'(underscore).

weekday is a broadcasting weekday about the corresponding program. This is an integer. 0 means Sunday and 1 is Monday and so on (2:Tuesday, 3:Wednesday, 4:Thursday, 5:Friday, 6:Saturday).

start is a starting time of the program broadcasting. This is an integer between 600 and 2929. First one or two digits represent hour and the last two digits represent minute. If the hour has one digit it will be a representation "900" for example. Note: a program may have an integer more than or equal to 2400 as start, if the program begins the next day. For example, a program begins from 2500 on Monday should be interpreted as a program begins from 0100 on Tuesday. There are no input the minute of start exceeds 59. And when the hour of start is equal to 29, there are no input the minute of start exceeds 29.

P is an integer and represents the number of elements in the set F. And FAVi(1≤i≤P≤N) is a string for a program name which Jack watches absolutely. You can assume names which are not given in program descriptions will not appear in the set F.

The last line contains a single 0 which represents the end of input.

Constraints

The number of datasets is less than or equal to 400.

1≤N≤500

Output

For each dataset, output an integer S that represents maximum number of programs Jack can watch in the following format.

S

Sample Input

1
galaxy_angel 0 600
1
galaxy_angel
11
A 0 600
B 0 610
C 0 610
D 0 610
E 0 640
EE 0 700
F 0 710
G 0 710
H 0 710
I 0 740
J 0 750
2
B
H
42
nchj 6 2620
anhnnnmewbktthsrn 4 2515
gntmdsh 1 1800
achnnl 4 2540
hnskirh 0 2200
aonexrcst 0 1700
dgdys 6 2330
hdnnara 4 2525
dnpaonntssotk 4 2555
ddmnwndrlnd 6 2500
C 4 2445
astrttnomch 0 2330
seknnqasr 1 2630
sftnt 4 2630
stnsgt 2 2605
drrnenmknmrmr 4 2610
hnzm 6 2713
yndmsoazzlsn 6 2658
mrahlcalv 4 2615
hshzrhkkrhs 1 900
ortchntsbshni 0 2430
kmnmzshrski 1 2530
sktdnc 4 1800
gykkybrkjhkirkhn 2 2459
trk 0 900
30zzsinhkntiik 3 2700
sngkotmmmirprdx 1 2600
yran 2 2529
tntissygntinybu 1 2614
skiichhtki 5 2505
tgrbnny 6 2558
dnbrsnki 3 1927
yugozxl 1 1930
frbllchrmn 1 1928
fjrg 1 1955
shwmngtr 0 2200
xmn 5 2200
rngnkkrskitikihn 0 2100
szysz 0 1254
prttyrythmaulrdrm 6 1000
sckiesfrntrqst 5 1820
mshdr 1 2255
1
mrahlcalv
0

Output for the Sample Input

1
4
31

Hint

Second dataset: He can watch program E after watching B. Then he can choose a program either I or J after watching H. Therefore he can watch maximum 4 programs.

Solution in Rust (judge verdict: Accepted)

extern crate core;

use std::str::FromStr;
use std::cmp::Ordering;
use std::collections::HashSet;

struct Istream {
    line: Vec<String>,
    position: usize
}
type Parse<T: FromStr> = Result<T, T::Err>;
impl Istream {
    fn new() -> Istream {
        Istream {line:vec![], position: 0}
    }
    fn read_word(&mut self) -> &String {
        if self.position == self.line.len() {
            let mut line= String::new();
            std::io::stdin().read_line(&mut line).ok();
            self.line = line.split_whitespace().map(|x|x.to_string()).collect();
            self.position = 0
        }
        let result = &self.line[self.position];
        self.position += 1;
        result
    }
    fn read(&mut self) -> String {
        self.read_word().to_string()
    }
    fn get<T: FromStr>(&mut self) -> T {self.read_word().parse().ok().unwrap()}
    fn read_usize(&mut self) -> usize {self.get()}
    fn read_int(&mut self) -> i32 {self.get()}
    fn read_long(&mut self) -> i64 {self.get()}
    fn read_double(&mut self) -> f64 {self.get()}
}
fn tabulate<T, F>(count: usize, elements: &mut F) -> Vec<T> where F: FnMut(usize) -> T {
    let mut result:Vec<T> = Vec::with_capacity(count);
    for i in 0 .. count {
        result.push(elements(i))
    }
    result
}
fn fill<T, F>(count: usize, generator: F) -> Vec<T> where F: Fn() -> T {
    let mut result: Vec<T> = Vec::with_capacity(count);
    for _i in 0 .. count {
        result.push(generator())
    }
    result
}
#[derive(Debug)]
struct Program {
    title: String,
    date: Date,
}
#[derive(Debug, Copy, Clone)]
struct Date {
    day: i32,
    hour: i32,
    minute: i32,
}
impl Date {
    fn from_int(day: &i32, time: &i32) -> Date {
        if time / 100 >= 24 {
            Date{day: (day + 1) % 7, hour: (time / 100) % 24, minute: (time % 100)}
        }else {
            Date{day: day + 0, hour: (time / 100), minute: (time % 100)}
        }
    }
    fn from_minute(minute: i32) -> Date {
        Date{day: (minute / 1440) % 7, hour: (minute / 60) % 24, minute: minute % 60}
    }
    fn to_minute(&self) -> i32 {
        self.day * 1440 + self.hour * 60 + self.minute
    }
    fn add_minute(&self, minute: i32) -> Date {
        Date::from_minute(self.to_minute() + minute)
    }
}
impl Ord for Date {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.day == other.day {
            if self.hour == other.hour {
                self.minute.cmp(&other.minute)
            }else {
                self.hour.cmp(&other.hour)
            }
        }else {
            self.day.cmp(&other.day)
        }
    }
}
impl PartialOrd for Date {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }

    fn lt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Less
    }

    fn le(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Greater
    }

    fn gt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Greater
    }

    fn ge(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Less
    }
}
impl PartialEq for Date {
    fn eq(&self, other: &Self) -> bool {
        self.day == other.day && self.hour == other.hour && self.minute == other.minute
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}
impl Eq for Date {}
impl Program {
    fn new(title: String, day: i32, start: i32) -> Program {
        let date = Date::from_int(&day, &start);
        Program{title: title, date: date}
    }
    fn overlapped(&self, other: &Program) -> bool {
        let s = self.date.to_minute();
        let o = other.date.to_minute();
        (s - o + 24 * 60 * 7) % (24 * 60 * 7) < 30 || (o - s + 24 * 60 * 7) % (24 * 60 * 7) < 30
    }
}
fn main() {
    let mut stdin = Istream::new();
    let input = &mut stdin;
    loop {
        let n = input.read_usize();
        if n == 0 {
            break;
        }
        let mut programs = tabulate(n, &mut |_i| {
            let title = input.read();
            let day = input.read_int();
            let start = input.read_int();
            Program::new(title, day, start)
        });
        programs.sort_by_key(|p|p.date);
        let mut favorite: HashSet<String> = HashSet::new();
        let p = input.read_usize();
        for _ in 0 .. p {
            favorite.insert(input.read());
        }
        let mut time = vec![false; 7 * 24 * 60];
        let len: usize = 7 * 24 * 60;
        let mut count = 0;
        let mut favorite_i = 0;
        'outer: for (i, p) in programs.iter().enumerate() {
            if count >= 0 && favorite.contains(&p.title) {
                favorite_i = i;
                count += 1;
                let minute = p.date.to_minute() as usize;
                for i in 0 .. 30 {
                    if time[(minute + i) % len] {
                        count = -1;
                        break 'outer;
                    }else {
                        time[(minute + i) % len] = true;
                    }
                }
            }
        }
        if count >= 0 {
            'outer: for p in 0..n {
                let minute = programs[(p + favorite_i) % n].date.to_minute() as usize;
                let mut is_overlapped = false;
                for i in 0..30 {
                    is_overlapped |= time[(minute + i) % len];
                }
                if !is_overlapped {
                    count += 1;
                    for i in 0 .. 30 {
                        time[(minute + i) % len] = true;
                    }
                }
            }
        }
        println!("{}", count)
    }
}