음수 시각을 하루 안으로 접는 것이 이 문제의 함정이에요. Noronha에서는 UTC 01:10에 시차 -02:00을 더해 -50분이 되는데, 이것은 전날 23:10이에요. Python의 %와 //는 내림 나눗셈이라 divmod(-50, 1440)이 (-1, 1390)으로 바로 맞아요. C·C++·Java·C#·JS·TS의 %는 0 쪽으로 버린 나눗셈의 나머지라 -50 % 1440이 -50이에요(크레이콘의 %도 JS와 같아요). 그래서 (t % 1440 + 1440) % 1440처럼 1440을 더해 한 번 더 나누거나, Java는 Math.floorMod(t, 1440)을 써요. 날짜 차이도 같은 함정이에요. C·C++·Java·C#의 -50 / 1440은 0이라 전날이라는 정보가 사라져요(JS·TS·크레이콘의 /는 -0.0347…을 주니 Math.floor가 필요해요). Python //, Java Math.floorDiv는 -1을 주고, 다른 언어는 (t - 그날의 분) / 1440처럼 딱 나누어떨어지게 만든 뒤 나누면 돼요. 셋째 함정은 시차를 읽는 법이에요. "-03:30"을 시 -3과 분 +30으로 따로 읽어 더하면 -150분이 되지만, 부호는 둘 다에 붙어서 -210분이에요. "-00:45"처럼 시가 0이면 시를 정수로 읽은 부호(-0)가 사라지니, 부호 글자를 먼저 떼어 따로 곱하는 것이 안전해요. 두 자리 채우기는 Python f"{m:02d}", JS·TS padStart(2, "0"), Java String.format("%02d"), C# {m:D2}, C printf("%02d"), C++ std::setw(2)와 std::setfill('0'), 크레이콘 앞채우기(2, "0")예요.
Python main.py · 27 줄 def offset_minutes(s): # "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 sign = -1 if s[0] == "-" else 1 return sign * (int(s[1:3]) * 60 + int(s[4:6])) def local(t): # divmod는 내림 나눗셈이라 t가 음수여도 나머지가 0~1439, 몫이 날짜 차이(-1 등)다 day, minute = divmod(t, 1440) tag = "+" + str(day) if day > 0 else str(day) return f"{minute // 60:02d}:{minute % 60:02d} {tag}", day hhmm, d = input().split() start = int(hhmm[:2]) * 60 + int(hhmm[3:]) d = int(d) n = int(input()) crossing = 0 for _ in range(n): name, off = input().split() t = start + offset_minutes(off) begin, day1 = local(t) end, day2 = local(t + d) print(name, begin, end) if day1 != day2: crossing += 1 print(crossing) JavaScript main.js · 27 줄 const lines = require("fs").readFileSync(0, "utf8").split("\n"); const DAY = 1440; // "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 const offsetMinutes = (s) => (s[0] === "-" ? -1 : 1) * (Number(s.slice(1, 3)) * 60 + Number(s.slice(4, 6))); const two = (v) => String(v).padStart(2, "0"); const local = (t) => { // JS의 %는 음수를 그대로 남긴다(-50 % 1440 === -50) → 한 번 더해서 다시 나눈다 const minute = ((t % DAY) + DAY) % DAY; const day = (t - minute) / DAY; // 이제 딱 나누어떨어진다(내림과 같다) return { text: `${two(Math.floor(minute / 60))}:${two(minute % 60)} ${day > 0 ? "+" + day : day}`, day }; }; const [hhmm, dText] = lines[0].trim().split(/\s+/); const start = Number(hhmm.slice(0, 2)) * 60 + Number(hhmm.slice(3)); const d = Number(dText); const n = Number(lines[1]); const out = []; let crossing = 0; for (let i = 0; i < n; i++) { const [name, off] = lines[2 + i].trim().split(/\s+/); const t = start + offsetMinutes(off); const begin = local(t); const end = local(t + d); out.push(`${name} ${begin.text} ${end.text}`); if (begin.day !== end.day) crossing++; } out.push(String(crossing)); console.log(out.join("\n")); TypeScript main.ts · 28 줄 import { readFileSync } from "node:fs"; const lines: string[] = readFileSync(0, "utf8").split("\n"); const DAY = 1440; // "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 const offsetMinutes = (s: string): number => (s[0] === "-" ? -1 : 1) * (Number(s.slice(1, 3)) * 60 + Number(s.slice(4, 6))); const two = (v: number): string => String(v).padStart(2, "0"); const local = (t: number): { text: string; day: number } => { // JS의 %는 음수를 그대로 남긴다(-50 % 1440 === -50) → 한 번 더해서 다시 나눈다 const minute = ((t % DAY) + DAY) % DAY; const day = (t - minute) / DAY; // 이제 딱 나누어떨어진다(내림과 같다) return { text: `${two(Math.floor(minute / 60))}:${two(minute % 60)} ${day > 0 ? "+" + day : day}`, day }; }; const [hhmm, dText] = lines[0].trim().split(/\s+/); const start = Number(hhmm.slice(0, 2)) * 60 + Number(hhmm.slice(3)); const d = Number(dText); const n = Number(lines[1]); const out: string[] = []; let crossing = 0; for (let i = 0; i < n; i++) { const [name, off] = lines[2 + i].trim().split(/\s+/); const t = start + offsetMinutes(off); const begin = local(t); const end = local(t + d); out.push(`${name} ${begin.text} ${end.text}`); if (begin.day !== end.day) crossing++; } out.push(String(crossing)); console.log(out.join("\n")); Java Main.java · 37 줄 import java.io.BufferedReader; import java.io.InputStreamReader; public class Main { static final int DAY = 1440; // "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 static int offsetMinutes(String s) { int sign = s.charAt(0) == '-' ? -1 : 1; return sign * (Integer.parseInt(s.substring(1, 3)) * 60 + Integer.parseInt(s.substring(4, 6))); } static String local(int t) { // Java의 %는 음수를 남기고 /는 0 쪽으로 버린다 → floorMod, floorDiv를 쓴다 int minute = Math.floorMod(t, DAY); int day = Math.floorDiv(t, DAY); return String.format("%02d:%02d %s%d", minute / 60, minute % 60, day > 0 ? "+" : "", day); } public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] first = in.readLine().trim().split("\\s+"); int start = Integer.parseInt(first[0].substring(0, 2)) * 60 + Integer.parseInt(first[0].substring(3)); int d = Integer.parseInt(first[1]); int n = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); int crossing = 0; for (int i = 0; i < n; i++) { String[] p = in.readLine().trim().split("\\s+"); int t = start + offsetMinutes(p[1]); out.append(p[0]).append(' ').append(local(t)).append(' ').append(local(t + d)).append('\n'); if (Math.floorDiv(t, DAY) != Math.floorDiv(t + d, DAY)) crossing++; } out.append(crossing).append('\n'); System.out.print(out); } } C# Main.cs · 44 줄 using System; using System.Text; class Program { const int Day = 1440; // "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 static int OffsetMinutes(string s) { int sign = s[0] == '-' ? -1 : 1; return sign * (int.Parse(s.Substring(1, 2)) * 60 + int.Parse(s.Substring(4, 2))); } // C#의 %는 나뉘는 수의 부호를 따른다(-50 % 1440 == -50) → 더해서 다시 나눈다 static int MinuteOfDay(int t) => (t % Day + Day) % Day; // 날짜 차이는 내림: t - (그날의 분)은 1440으로 딱 나누어떨어진다 static int DayShift(int t) => (t - MinuteOfDay(t)) / Day; static string Local(int t) { int m = MinuteOfDay(t), day = DayShift(t); return $"{m / 60:D2}:{m % 60:D2} {(day > 0 ? "+" : "")}{day}"; } static void Main() { string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int start = int.Parse(first[0].Substring(0, 2)) * 60 + int.Parse(first[0].Substring(3)); int d = int.Parse(first[1]); int n = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); int crossing = 0; for (int i = 0; i < n; i++) { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int t = start + OffsetMinutes(p[1]); sb.Append(p[0]).Append(' ').Append(Local(t)).Append(' ').Append(Local(t + d)).Append('\n'); if (DayShift(t) != DayShift(t + d)) crossing++; } sb.Append(crossing).Append('\n'); Console.Write(sb); } } C++ main.cpp · 36 줄 #include <iomanip> #include <iostream> #include <sstream> #include <string> constexpr int DAY = 1440; // C++의 %도 0 쪽으로 버린 나눗셈의 나머지(-50 % 1440 == -50) → 더해서 다시 나눈다 int minuteOfDay(int t) { return (t % DAY + DAY) % DAY; } // 날짜 차이는 내림: t - (그날의 분)은 1440으로 딱 나누어떨어진다 int dayShift(int t) { return (t - minuteOfDay(t)) / DAY; } std::string local(int t) { int m = minuteOfDay(t), day = dayShift(t); std::ostringstream s; s << std::setfill('0') << std::setw(2) << m / 60 << ':' << std::setw(2) << m % 60 << ' ' << (day > 0 ? "+" : "") << day; return s.str(); } int main() { std::string hhmm; int d, n; std::cin >> hhmm >> d >> n; int start = std::stoi(hhmm.substr(0, 2)) * 60 + std::stoi(hhmm.substr(3, 2)); int crossing = 0; for (int i = 0; i < n; i++) { std::string name, off; std::cin >> name >> off; // "-03:30"의 부호는 시와 분 모두에 붙는다 int t = start + (off[0] == '-' ? -1 : 1) * (std::stoi(off.substr(1, 2)) * 60 + std::stoi(off.substr(4, 2))); std::cout << name << ' ' << local(t) << ' ' << local(t + d) << '\n'; if (dayShift(t) != dayShift(t + d)) crossing++; } std::cout << crossing << '\n'; } C main.c · 37 줄 #include <stdio.h> #define DAY 1440 /* C의 %는 0 쪽으로 버린 나눗셈의 나머지라 음수가 나올 수 있다 → 더해서 다시 나눈다 */ int minute_of_day(int t) { return (t % DAY + DAY) % DAY; } /* 날짜 차이는 내림이어야 한다: t - (그날의 분)은 1440으로 딱 나누어떨어진다 */ int day_shift(int t) { return (t - minute_of_day(t)) / DAY; } void print_local(int t) { int m = minute_of_day(t), day = day_shift(t); printf("%02d:%02d %s%d", m / 60, m % 60, day > 0 ? "+" : "", day); } int main(void) { int sh, sm, d, n; scanf("%d:%d %d", &sh, &sm, &d); scanf("%d", &n); int start = sh * 60 + sm, crossing = 0; for (int i = 0; i < n; i++) { char name[32], sign; int oh, om; scanf("%31s %c%d:%d", name, &sign, &oh, &om); /* "-03:30"의 부호는 시와 분 모두에 붙는다 */ int off = (sign == '-' ? -1 : 1) * (oh * 60 + om); int t = start + off; printf("%s ", name); print_local(t); printf(" "); print_local(t + d); printf("\n"); if (day_shift(t) != day_shift(t + d)) crossing++; } printf("%d\n", crossing); return 0; } Craykon main.cray · 51 줄 // "-03:30"의 부호는 시와 분 모두에 붙는다: -(3 * 60 + 30) = -210 차이분(s) { 분 = s.부분문자열(1, 2).수로변환() * 60 + s.부분문자열(4, 2).수로변환(); 만약 (s.부분문자열(0, 1) == "-") { 돌려주기 -분; } 돌려주기 분; } // 크레이콘의 %도 JS처럼 음수를 남긴다(-50 % 1440 == -50) → 더해서 다시 나눈다 그날의분(t) { 돌려주기 (t % 1440 + 1440) % 1440; } // 날짜 차이는 내림: t - (그날의 분)은 1440으로 딱 나누어떨어진다 날짜차이(t) { 돌려주기 (t - 그날의분(t)) / 1440; } 시각(t) { m = 그날의분(t); day = 날짜차이(t); 표 = "" + day; 만약 (day > 0) { 표 = "+" + day; } 돌려주기 ("" + 수학.몫(m, 60)).앞채우기(2, "0") + ":" + ("" + m % 60).앞채우기(2, "0") + " " + 표; } 첫줄 = 콘솔.줄읽기().나누기(); start = 첫줄[0].부분문자열(0, 2).수로변환() * 60 + 첫줄[0].부분문자열(3, 2).수로변환(); d = 첫줄[1].수로변환(); n = 콘솔.줄읽기().수로변환(); crossing = 0; 반복 (i = 0; i < n; i++) { 칸 = 콘솔.줄읽기().나누기(); t = start + 차이분(칸[1]); 콘솔.쓰기(칸[0] + " " + 시각(t) + " " + 시각(t + d)); 만약 (날짜차이(t) != 날짜차이(t + d)) { crossing += 1; } } 콘솔.쓰기(crossing);