{ }codelper
比较逻辑运算符P0169

按周岁收的门票

游乐园按游客的周岁决定门票价格。
第一行给出今天的日期,第二行给出游客数 n,接下来 n 行每行给出一位游客的出生日期。
所有日期的形式都是 YYYY-MM-DD(月和日是两位),出生日期不会晚于今天。
周岁等于(今天的年份 - 出生年份),如果今年的生日还没到,再减 1。
今年的生日还没到,是指今天的月份早于出生月份,或者两个月份相同且今天的日早于出生的日。
按这个规则,2 月 29 日出生的人在平年的 3 月 1 日长一岁。
门票:周岁 2 岁及以下 0 韩元,3~12 岁 6,000 韩元,13~18 岁 9,000 韩元,19~64 岁 15,000 韩元,65 岁及以上 7,000 韩元。
但如果今天的月和日与出生的月和日都相同,也就是今天是生日,那么不论年龄都是 0 韩元。
按输入顺序,每位游客输出一行:周岁和门票,用一个空格分开。
最后一行输出门票的总和。

输入
1900-01-01 ≤ 出生日期 ≤ 今天 ≤ 2100-12-31,1 ≤ n ≤ 1,000,所有日期都是日历上真实存在的日期
输出
每位游客一行(周岁、门票),最后一行是门票总和
样例 1 · stdin
2025-10-01
6
2015-09-30
2015-10-02
2007-10-01
2004-02-29
1960-12-31
2023-01-15
stdout
10 6000
9 6000
18 0
21 15000
64 15000
2 0
42000
样例 2 · stdin
2023-02-28
3
2004-02-29
1958-02-28
2010-03-01
stdout
18 9000
65 0
12 6000
15000
main.py
输入(stdin)

运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。

$ 就绪

请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。

其他语言怎么写?查看各语言题解 · 8 种语言题解

判断「生日过了没有」的比较就是这道题的全部。
常见错误是把月和日分开判断:tm >= bm && td >= bd。
5 月 3 日看 4 月 20 日出生的人,月份已经过了,却因为日(3 < 20)被当成生日还没到。
正确的条件是「月份更早,或者月份相同且日更早」:七种语言写 tm < bm || (tm == bm && td < bd),Python 写 tm < bm or (tm == bm and td < bd)(Craykon 也用 || 和 &&)。
Python 元组 (tm, td) < (bm, bd) 和 C++ 的 std::tie(tm, td) < std::tie(bm, bd) 从第一项开始依次比较,可以一次写出这个条件。
JS/TS 的数组没有这种比较。
[tm, td] < [bm, bd] 会把两个数组变成字符串 "10,1" 和 "9,30" 按字典序比较,于是 10 月 1 日被当成早于 9 月 30 日(TS 也不会拦下这个表达式)。
Java、C# 的元组和数组也没有 <,所以要逐项比较,或者变成月 × 100 + 日这样的一个数再比较。
比较日期字符串 "MM-DD" 也可以,因为月和日都是两位,字典序就是日期顺序:Python、JS、TS、Craykon 用 <,Java 用 compareTo,C# 用 string.CompareOrdinal,C++ 的 std::string 用 <。
但在 C 里用 < 比较两个 char 数组,比较的是内存地址而不是内容,必须用 strcmp。

Pythonmain.py · 31 行
def parse(s):    y, m, d = map(int, s.split("-"))    return y, m, d  def price(age):    if age <= 2:        return 0    elif age <= 12:        return 6000    elif age <= 18:        return 9000    elif age <= 64:        return 15000    else:        return 7000  ty, tm, td = parse(input().strip())n = int(input())total = 0for _ in range(n):    by, bm, bd = parse(input().strip())    age = ty - by    # 튜플은 앞 칸부터 차례로 비교한다: 월이 같을 때만 일을 본다    if (tm, td) < (bm, bd):        age -= 1    fee = 0 if (tm, td) == (bm, bd) else price(age)  # 생일 당일은 무료    print(age, fee)    total += feeprint(total)
JavaScriptmain.js · 24 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const parse = (s) => s.trim().split("-").map(Number);const price = (age) => {  if (age <= 2) return 0;  else if (age <= 12) return 6000;  else if (age <= 18) return 9000;  else if (age <= 64) return 15000;  else return 7000;};const [ty, tm, td] = parse(lines[0]);const n = Number(lines[1]);const out = [];let total = 0;for (let i = 0; i < n; i++) {  const [by, bm, bd] = parse(lines[2 + i]);  // 배열끼리 <로 비교하면 문자열 "10,1" < "9,30"으로 비교된다 → 칸마다 직접 비교한다  const beforeBirthday = tm < bm || (tm === bm && td < bd);  const age = ty - by - (beforeBirthday ? 1 : 0);  const fee = tm === bm && td === bd ? 0 : price(age); // 생일 당일은 무료  out.push(`${age} ${fee}`);  total += fee;}out.push(String(total));console.log(out.join("\n"));
TypeScriptmain.ts · 25 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const parse = (s: string): number[] => s.trim().split("-").map(Number);const price = (age: number): number => {  if (age <= 2) return 0;  else if (age <= 12) return 6000;  else if (age <= 18) return 9000;  else if (age <= 64) return 15000;  else return 7000;};const [ty, tm, td] = parse(lines[0]);const n = Number(lines[1]);const out: string[] = [];let total = 0;for (let i = 0; i < n; i++) {  const [by, bm, bd] = parse(lines[2 + i]);  // 배열끼리 <로 비교하면 문자열 "10,1" < "9,30"으로 비교된다 → 칸마다 직접 비교한다  const beforeBirthday = tm < bm || (tm === bm && td < bd);  const age = ty - by - (beforeBirthday ? 1 : 0);  const fee = tm === bm && td === bd ? 0 : price(age); // 생일 당일은 무료  out.push(`${age} ${fee}`);  total += fee;}out.push(String(total));console.log(out.join("\n"));
JavaMain.java · 36 行
import java.io.BufferedReader;import java.io.InputStreamReader; public class Main {    static int[] parse(String s) {        String[] p = s.trim().split("-");        return new int[] {Integer.parseInt(p[0]), Integer.parseInt(p[1]), Integer.parseInt(p[2])};    }     static int price(int age) {        if (age <= 2) return 0;        else if (age <= 12) return 6000;        else if (age <= 18) return 9000;        else if (age <= 64) return 15000;        else return 7000;    }     public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int[] t = parse(in.readLine());        int n = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        long total = 0;        for (int i = 0; i < n; i++) {            int[] b = parse(in.readLine());            // 월이 앞서거나, 월이 같고 일이 앞서면 아직 생일 전이다            boolean beforeBirthday = t[1] < b[1] || (t[1] == b[1] && t[2] < b[2]);            int age = t[0] - b[0] - (beforeBirthday ? 1 : 0);            int fee = (t[1] == b[1] && t[2] == b[2]) ? 0 : price(age); // 생일 당일은 무료            out.append(age).append(' ').append(fee).append('\n');            total += fee;        }        out.append(total).append('\n');        System.out.print(out);    }}
C#Main.cs · 35 行
using System;using System.Linq;using System.Text; class Program{    static int Price(int age)    {        if (age <= 2) return 0;        else if (age <= 12) return 6000;        else if (age <= 18) return 9000;        else if (age <= 64) return 15000;        else return 7000;    }     static void Main()    {        int[] t = Console.ReadLine().Trim().Split('-').Select(int.Parse).ToArray();        int n = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        long total = 0;        for (int i = 0; i < n; i++)        {            int[] b = Console.ReadLine().Trim().Split('-').Select(int.Parse).ToArray();            // 튜플은 앞 칸부터 비교하지만 C#의 튜플에는 <가 없다 → 칸마다 직접 비교한다            bool beforeBirthday = t[1] < b[1] || (t[1] == b[1] && t[2] < b[2]);            int age = t[0] - b[0] - (beforeBirthday ? 1 : 0);            int fee = (t[1] == b[1] && t[2] == b[2]) ? 0 : Price(age); // 생일 당일은 무료            sb.Append(age).Append(' ').Append(fee).Append('\n');            total += fee;        }        sb.Append(total).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 29 行
#include <iostream>#include <string>#include <tuple> int price(int age) {    if (age <= 2) return 0;    else if (age <= 12) return 6000;    else if (age <= 18) return 9000;    else if (age <= 64) return 15000;    else return 7000;} int main() {    char dash;    int ty, tm, td, n;    std::cin >> ty >> dash >> tm >> dash >> td >> n;    long long total = 0;    for (int i = 0; i < n; i++) {        int by, bm, bd;        std::cin >> by >> dash >> bm >> dash >> bd;        // std::tie로 묶으면 튜플처럼 앞 칸부터 차례로 비교한다        bool beforeBirthday = std::tie(tm, td) < std::tie(bm, bd);        int age = ty - by - (beforeBirthday ? 1 : 0);        int fee = (tm == bm && td == bd) ? 0 : price(age); // 생일 당일은 무료        std::cout << age << ' ' << fee << '\n';        total += fee;    }    std::cout << total << '\n';}
Cmain.c · 28 行
#include <stdio.h> int price(int age) {    if (age <= 2) return 0;    else if (age <= 12) return 6000;    else if (age <= 18) return 9000;    else if (age <= 64) return 15000;    else return 7000;} int main(void) {    int ty, tm, td, n;    scanf("%d-%d-%d", &ty, &tm, &td);    scanf("%d", &n);    long total = 0;    for (int i = 0; i < n; i++) {        int by, bm, bd;        scanf("%d-%d-%d", &by, &bm, &bd);        /* 월이 앞서거나, 월이 같고 일이 앞서면 아직 생일 전이다 */        int before_birthday = tm < bm || (tm == bm && td < bd);        int age = ty - by - (before_birthday ? 1 : 0);        int fee = (tm == bm && td == bd) ? 0 : price(age); /* 생일 당일은 무료 */        printf("%d %d\n", age, fee);        total += fee;    }    printf("%ld\n", total);    return 0;}
Craykonmain.cray · 48 行
날짜(줄){    칸 = 줄.去空白().分割("-");    返回 [칸[0].转数字(), 칸[1].转数字(), 칸[2].转数字()];} 요금(age){    如果 (age <= 2)    {        返回 0;    }    否则 如果 (age <= 12)    {        返回 6000;    }    否则 如果 (age <= 18)    {        返回 9000;    }    否则 如果 (age <= 64)    {        返回 15000;    }    返回 7000;} t = 날짜(控制台.读行());n = 控制台.读行().转数字();total = 0;循环 (i = 0; i < n; i++){    b = 날짜(控制台.读行());    age = t[0] - b[0];    // 월이 앞서거나, 월이 같고 일이 앞서면 아직 생일 전이다    如果 (t[1] < b[1] || t[1] == b[1] && t[2] < b[2])    {        age -= 1;    }    fee = 요금(age);    如果 (t[1] == b[1] && t[2] == b[2])    {        fee = 0; // 생일 당일은 무료    }    控制台.输出(age + " " + fee);    total += fee;}控制台.输出(total);