{ }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()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

참·거짓 값 하나(사이렌)를 줄마다 켜짐 && (사이렌 || 문 || 창문)으로 새로 정하는 문제예요.
여덟 언어 모두 &&(Python은 and)가 ||(or)보다 먼저 묶여요.
달라지는 곳은 낱말 "true"를 참·거짓으로 바꾸는 법과 다시 찍는 법이에요.
읽기: Java Boolean.parseBoolean(낱말), C# bool.Parse(낱말), C++ std::cin >> std::boolalpha를 켜 두고 bool로 바로 읽기가 있고, Python·JavaScript·TypeScript·C·크레이콘은 낱말 == "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 서식이 없어요.
크레이콘의 참·거짓은 참·거짓이라고 쓰고, 여기서는 경보 ? "true" : "false"로 낱말을 골라 찍어요.
함정 다섯: ① Python bool("false")와 JS Boolean("false")는 참이에요.
비어 있지 않은 문자열은 모두 참이라서, 변환이 아니라 비교를 해야 해요.
② 괄호를 빼고 켜짐 && 사이렌 || 문 || 창문이라고 쓰면 (켜짐 && 사이렌) || 문 || 창문이 되어, 경보기를 꺼 두어도 문이 열리면 울려요.
③ 식에 앞 줄의 사이렌 값을 넣지 않으면 문을 닫는 순간 사이렌이 꺼져요.
④ 출력은 소문자여야 해요.
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");}콘솔.쓰기(횟수);