{ }codelper
布尔值P0289

一旦响起就一直响到关闭的警笛

报警器有 n 行记录。
每行记录依次写着那一刻的三个状态:报警器是否开启,门是否开着,窗是否开着。
每个状态是小写的 true 或 false。
警笛一开始不响,每读一行记录,就按下面的规则决定。
如果报警器没有开启(false),警笛不响。
如果报警器开启(true),那么只要到上一行记录为止警笛一直在响,或者现在门和窗至少有一个开着,警笛就响。
报警器开启但这两种情况都不成立时,警笛不响。
也就是说,警笛一旦响起,即使把门和窗都关上,也会一直响到关闭报警器为止。
对每行记录,如果读完这行后警笛在响,输出一行 true,否则输出 false。
最后一行输出警笛从不响变成响的次数。

输入
第一行给出 n(1 ≤ n ≤ 1,000),接下来 n 行每行给出三个 true 或 false,用一个空格隔开。
输出
n + 1 行。
前 n 行是小写的 true 或 false,最后一行是警笛开始响的次数(一次也没有则为 0)
样例 1 · stdin
7
false true false
true false false
true false true
true false false
false false false
true true true
true false false
stdout
false
false
true
true
false
true
true
2
main.py
输入(stdin)

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

$ 就绪

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

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

这道题每行都用 armed && (siren || door || window) 重新决定一个布尔值(警笛)。
八种语言里 &&(Python 是 and)都比 ||(or)结合得更紧。
不同之处在于怎样把单词 "true" 变成布尔值,以及怎样再输出。
读入:Java 有 Boolean.parseBoolean(单词),C# 有 bool.Parse(单词),C++ 先写 std::cin >> std::boolalpha 就能直接读进 bool;Python、JavaScript、TypeScript、C 和 Craykon 用 单词 == "true" 这样的比较来得到(C 是 strcmp(单词, "true") == 0,用 bool 需要 <stdbool.h>)。
输出:Java 和 JS·TS 直接输出就是 true/false,Python 和 C# 是 True/False,C++ 不加 std::boolalpha 是 1/0,C 的 printf 没有 bool 的格式。
Craykon 的布尔值写作 真、假,这里用 警笛 ? "true" : "false" 选出单词再输出。
五个陷阱:① Python 的 bool("false") 和 JS 的 Boolean("false") 是真。
非空字符串都是真,所以要比较而不是转换。
② 去掉括号写成 armed && siren || door || window,就变成 (armed && siren) || door || window,报警器没开启时门一开也会响。
③ 表达式里不放上一行的警笛值,门一关警笛就停了。
④ 输出必须是小写。
C# 直接拼接 bool 得到 True,C++ 不加 std::boolalpha 输出 1。
⑤ 次数不是警笛在响的行数,而是“之前不响、现在响”的行数。
在赋新值之前,先把旧值存到另一个变量里。

Pythonmain.py · 12 行
n = int(input())siren = Falsecount = 0for _ in range(n):    # bool("false")는 True다(빈 문자열만 False). 그래서 "true"와 같은지 비교해서 bool을 만든다    armed, door, window = (word == "true" for word in input().split())    was = siren    siren = armed and (siren or door or window)    if siren and not was:        count += 1    print("true" if siren else "false")  # print(siren)은 True/False로 찍힌다print(count)
JavaScriptmain.js · 15 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);let siren = false;let count = 0;const out = [];for (let i = 1; i <= n; i++) {  // Boolean("false")는 true다(빈 문자열만 false). 그래서 "true"와 같은지 비교한다  const [armed, door, windowOpen] = lines[i].split(" ").map((word) => word === "true");  const was = siren;  siren = armed && (siren || door || windowOpen);  if (siren && !was) count++;  out.push(String(siren)); // "true" 또는 "false"}out.push(count);console.log(out.join("\n"));
TypeScriptmain.ts · 19 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);let siren = false;let count = 0;const out: string[] = [];for (let i = 1; i <= n; i++) {  // Boolean("false")는 true다(빈 문자열만 false). 그래서 "true"와 같은지 비교한다  const flags: boolean[] = lines[i].split(" ").map((word) => word === "true");  const armed = flags[0];  const door = flags[1];  const windowOpen = flags[2];  const was = siren;  siren = armed && (siren || door || windowOpen);  if (siren && !was) count++;  out.push(String(siren)); // "true" 또는 "false"}out.push(String(count));console.log(out.join("\n"));
JavaMain.java · 25 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        boolean siren = false;        int count = 0;        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            String[] words = in.readLine().trim().split(" ");            boolean armed = Boolean.parseBoolean(words[0]);            boolean door = Boolean.parseBoolean(words[1]);            boolean window = Boolean.parseBoolean(words[2]);            boolean was = siren;            siren = armed && (siren || door || window);            if (siren && !was) count++;            out.append(siren).append('\n'); // boolean은 true/false로 붙는다        }        out.append(count).append('\n');        System.out.print(out);    }}
C#Main.cs · 27 行
using System;using System.Text; class Program{    static void Main()    {        int n = int.Parse(Console.ReadLine());        bool siren = false;        int count = 0;        var sb = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] words = Console.ReadLine().Split(' ');            bool armed = bool.Parse(words[0]);            bool door = bool.Parse(words[1]);            bool window = bool.Parse(words[2]);            bool was = siren;            siren = armed && (siren || door || window);            if (siren && !was) count++;            // bool을 그대로 붙이면 True/False(첫 글자가 대문자)가 되므로 직접 고른다            sb.Append(siren ? "true" : "false").Append('\n');        }        sb.Append(count).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 20 行
#include <iostream> int main() {    int n;    std::cin >> n;    // boolalpha를 켜면 bool을 1/0이 아니라 true/false라는 낱말로 읽고 쓴다    std::cin >> std::boolalpha;    std::cout << std::boolalpha;    bool siren = false;    int count = 0;    for (int i = 0; i < n; i++) {        bool armed, door, window;        std::cin >> armed >> door >> window;        bool was = siren;        siren = armed && (siren || door || window);        if (siren && !was) count++;        std::cout << siren << '\n';    }    std::cout << count << '\n';}
Cmain.c · 30 行
#include <stdbool.h>#include <stdio.h>#include <string.h> /* 낱말 하나를 읽어 "true"인지 돌려준다 */static bool read_flag(void) {    char word[8];    scanf("%7s", word);    return strcmp(word, "true") == 0;} int main(void) {    int n;    scanf("%d", &n);    bool siren = false;    int count = 0;    for (int i = 0; i < n; i++) {        bool armed = read_flag();        bool door = read_flag();        bool window = read_flag();        bool was = siren;        /* &&가 ||보다 먼저 묶이므로 괄호가 꼭 있어야 한다 */        siren = armed && (siren || door || window);        if (siren && !was) count++;        /* printf에는 bool을 찍는 서식이 없다(%d로 찍으면 1/0) */        puts(siren ? "true" : "false");    }    printf("%d\n", count);    return 0;}
Craykonmain.cray · 19 行
n = 控制台.读行().转数字();경보 = 假;횟수 = 0;循环 (i = 0; i < n; i++){    낱말 = 控制台.读行().分割(" ");    // 문자열 "false"는 거짓이 아니다. "true"와 같은지 비교해서 참·거짓을 만든다    켜짐 = 낱말[0] == "true";    문 = 낱말[1] == "true";    창문 = 낱말[2] == "true";    전 = 경보;    경보 = 켜짐 && (경보 || 문 || 창문);    如果 (경보 && !전)    {        횟수++;    }    控制台.输出(경보 ? "true" : "false");}控制台.输出(횟수);