#![warn(clippy::pedantic)]
use std::{
    collections::{HashMap, HashSet},
    io::{stdin, BufRead},
};

type Point<'a> = &'a str;

fn walk<'a>(
    connections: &HashMap<Point<'a>, HashSet<Point<'a>>>,
    visited: &[Point<'a>],
    extra_cave: Option<Point<'a>>,
    from: Point<'a>,
) -> usize {
    let mut res = 0;

    let mut visited = Vec::from(visited);
    visited.push(from);

    for target in &connections[from] {
        if *target == "end" {
            res += 1;
            continue;
        }

        let is_uppercase = target.chars().all(|c| c.is_ascii_uppercase());
        let was_visited = visited.contains(target);

        if is_uppercase || !was_visited {
            res += walk(connections, &visited, extra_cave, target);
        } else if extra_cave.is_none() {
            res += walk(connections, &visited, Some(target), target);
        }
    }

    res
}

fn main() {
    let lines: Vec<_> = stdin().lock().lines().collect::<Result<_, _>>().unwrap();

    let connections: HashMap<Point, HashSet<Point>> =
        lines.iter().fold(HashMap::new(), |mut map, line| {
            let mut parts = line.split('-');
            let p1 = parts.next().unwrap();
            let p2 = parts.next().unwrap();

            if p1 != "end" && p2 != "start" {
                map.entry(p1).or_default().insert(p2);
            }
            if p2 != "end" && p1 != "start" {
                map.entry(p2).or_default().insert(p1);
            }
            map
        });

    println!("{}", walk(&connections, &[], Some(""), "start"));
    println!("{}", walk(&connections, &[], None, "start"));
}
