import sysclass Room: """도면 위의 네모난 방: 왼쪽 아래 (x1, y1), 오른쪽 위 (x2, y2)""" def __init__(self, x1, y1, x2, y2): self.x1, self.y1, self.x2, self.y2 = x1, y1, x2, y2 # move·scale·turn은 자기 자신(self)을 돌려준다: room.move(...).scale(...).turn(...)처럼 이어 부를 수 있다 def move(self, dx, dy): self.x1 += dx self.x2 += dx self.y1 += dy self.y2 += dy return self def scale(self, k): self.x1 *= k self.y1 *= k self.x2 *= k self.y2 *= k return self def turn(self, times): for _ in range(times): # 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 self.x1, self.y1, self.x2, self.y2 = -self.y2, self.x1, -self.y1, self.x2 return self def copy(self): return Room(self.x1, self.y1, self.x2, self.y2) # 새 객체: 앞으로 따로 움직인다 def area(self): return (self.x2 - self.x1) * (self.y2 - self.y1) def overlap(self, other): w = min(self.x2, other.x2) - max(self.x1, other.x1) h = min(self.y2, other.y2) - max(self.y1, other.y1) return max(0, w) * max(0, h) # 한쪽이라도 0 이하면 겹치지 않는다 def __str__(self): return f"{self.x1} {self.y1} {self.x2} {self.y2}"lines = sys.stdin.read().split("\n")q = int(lines[0])rooms = {}out = []for i in range(1, q + 1): p = lines[i].split() cmd = p[0] if cmd == "new": rooms[p[1]] = Room(*map(int, p[2:6])) elif cmd == "copy": rooms[p[1]] = rooms[p[2]].copy() elif cmd == "do": dx, dy, k, t = map(int, p[2:6]) rooms[p[1]].move(dx, dy).scale(k).turn(t) elif cmd == "area": out.append(str(rooms[p[1]].area())) elif cmd == "overlap": out.append(str(rooms[p[1]].overlap(rooms[p[2]]))) else: # show out.append(str(rooms[p[1]]))print("\n".join(out))
JavaScriptmain.js · 70 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");// 도면 위의 네모난 방: 왼쪽 아래 (x1, y1), 오른쪽 위 (x2, y2)class Room { constructor(x1, y1, x2, y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } // move·scale·turn은 자기 자신(this)을 돌려준다: room.move(...).scale(...).turn(...)처럼 이어 부를 수 있다 move(dx, dy) { this.x1 += dx; this.x2 += dx; this.y1 += dy; this.y2 += dy; return this; } scale(k) { this.x1 *= k; this.y1 *= k; this.x2 *= k; this.y2 *= k; return this; } turn(times) { for (let i = 0; i < times; i++) { // 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 [this.x1, this.y1, this.x2, this.y2] = [-this.y2, this.x1, -this.y1, this.x2]; } return this; } copy() { return new Room(this.x1, this.y1, this.x2, this.y2); // 새 객체: 앞으로 따로 움직인다 } area() { return (this.x2 - this.x1) * (this.y2 - this.y1); // 4×10^12까지: number는 2^53까지 정확하다 } overlap(other) { const w = Math.min(this.x2, other.x2) - Math.max(this.x1, other.x1); const h = Math.min(this.y2, other.y2) - Math.max(this.y1, other.y1); return Math.max(0, w) * Math.max(0, h); // 한쪽이라도 0 이하면 겹치지 않는다 } toString() { return `${this.x1} ${this.y1} ${this.x2} ${this.y2}`; }}const q = Number(lines[0]);const rooms = new Map();const out = [];for (let i = 1; i <= q; i++) { const p = lines[i].trim().split(" "); const [cmd, a, b] = p; const num = p.slice(2).map(Number); if (cmd === "new") rooms.set(a, new Room(num[0], num[1], num[2], num[3])); else if (cmd === "copy") rooms.set(a, rooms.get(b).copy()); else if (cmd === "do") rooms.get(a).move(num[0], num[1]).scale(num[2]).turn(num[3]); else if (cmd === "area") out.push(rooms.get(a).area()); else if (cmd === "overlap") out.push(rooms.get(a).overlap(rooms.get(b))); else out.push(String(rooms.get(a)));}console.log(out.join("\n"));
TypeScriptmain.ts · 73 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");// 도면 위의 네모난 방: 왼쪽 아래 (x1, y1), 오른쪽 위 (x2, y2)class Room { constructor( private x1: number, private y1: number, private x2: number, private y2: number, ) {} // move·scale·turn은 자기 자신을 돌려준다(돌려주는 타입 this): room.move(...).scale(...).turn(...) move(dx: number, dy: number): this { this.x1 += dx; this.x2 += dx; this.y1 += dy; this.y2 += dy; return this; } scale(k: number): this { this.x1 *= k; this.y1 *= k; this.x2 *= k; this.y2 *= k; return this; } turn(times: number): this { for (let i = 0; i < times; i++) { // 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 [this.x1, this.y1, this.x2, this.y2] = [-this.y2, this.x1, -this.y1, this.x2]; } return this; } copy(): Room { return new Room(this.x1, this.y1, this.x2, this.y2); // 새 객체: 앞으로 따로 움직인다 } area(): number { return (this.x2 - this.x1) * (this.y2 - this.y1); // 4×10^12까지: number는 2^53까지 정확하다 } overlap(other: Room): number { const w = Math.min(this.x2, other.x2) - Math.max(this.x1, other.x1); const h = Math.min(this.y2, other.y2) - Math.max(this.y1, other.y1); return Math.max(0, w) * Math.max(0, h); // 한쪽이라도 0 이하면 겹치지 않는다 } toString(): string { return `${this.x1} ${this.y1} ${this.x2} ${this.y2}`; }}const q = Number(lines[0]);const rooms = new Map<string, Room>();const out: string[] = [];const get = (name: string): Room => rooms.get(name)!; // 입력에 나오는 이름은 모두 이미 있다for (let i = 1; i <= q; i++) { const p = lines[i].trim().split(" "); const [cmd, a, b] = p; const num = p.slice(2).map(Number); if (cmd === "new") rooms.set(a, new Room(num[0], num[1], num[2], num[3])); else if (cmd === "copy") rooms.set(a, get(b).copy()); else if (cmd === "do") get(a).move(num[0], num[1]).scale(num[2]).turn(num[3]); else if (cmd === "area") out.push(String(get(a).area())); else if (cmd === "overlap") out.push(String(get(a).overlap(get(b)))); else out.push(get(a).toString());}console.log(out.join("\n"));
JavaMain.java · 66 行
import java.io.*;import java.util.*;public class Main { // 도면 위의 네모난 방: 왼쪽 아래 (x1, y1), 오른쪽 위 (x2, y2) static class Room { private long x1, y1, x2, y2; Room(long x1, long y1, long x2, long y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } // move·scale·turn은 자기 자신(this)을 돌려준다: room.move(...).scale(...).turn(...)처럼 이어 부를 수 있다 Room move(long dx, long dy) { x1 += dx; x2 += dx; y1 += dy; y2 += dy; return this; } Room scale(long k) { x1 *= k; y1 *= k; x2 *= k; y2 *= k; return this; } Room turn(int times) { for (int i = 0; i < times; i++) { // 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 long nx1 = -y2, ny1 = x1, nx2 = -y1, ny2 = x2; x1 = nx1; y1 = ny1; x2 = nx2; y2 = ny2; } return this; } Room copy() { return new Room(x1, y1, x2, y2); } // 새 객체: 앞으로 따로 움직인다 long area() { return (x2 - x1) * (y2 - y1); } // 4×10^12까지라 long long overlap(Room o) { long w = Math.min(x2, o.x2) - Math.max(x1, o.x1); long h = Math.min(y2, o.y2) - Math.max(y1, o.y1); return Math.max(0, w) * Math.max(0, h); // 한쪽이라도 0 이하면 겹치지 않는다 } @Override public String toString() { return x1 + " " + y1 + " " + x2 + " " + y2; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int q = Integer.parseInt(br.readLine().trim()); Map<String, Room> rooms = new HashMap<>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < q; i++) { String[] p = br.readLine().trim().split(" "); switch (p[0]) { case "new" -> rooms.put(p[1], new Room(Long.parseLong(p[2]), Long.parseLong(p[3]), Long.parseLong(p[4]), Long.parseLong(p[5]))); case "copy" -> rooms.put(p[1], rooms.get(p[2]).copy()); case "do" -> rooms.get(p[1]).move(Long.parseLong(p[2]), Long.parseLong(p[3])).scale(Long.parseLong(p[4])).turn(Integer.parseInt(p[5])); case "area" -> sb.append(rooms.get(p[1]).area()).append('\n'); case "overlap" -> sb.append(rooms.get(p[1]).overlap(rooms.get(p[2]))).append('\n'); default -> sb.append(rooms.get(p[1])).append('\n'); } } System.out.print(sb); }}
C#Main.cs · 76 行
using System;using System.Collections.Generic;using System.Text;// 도면 위의 네모난 방: 왼쪽 아래 (X1, Y1), 오른쪽 위 (X2, Y2)// struct가 아니라 class: struct면 사전에서 꺼낼 때마다 복사본이 나와 바꾼 것이 사라진다class Room{ public long X1 { get; private set; } public long Y1 { get; private set; } public long X2 { get; private set; } public long Y2 { get; private set; } public Room(long x1, long y1, long x2, long y2) { X1 = x1; Y1 = y1; X2 = x2; Y2 = y2; } // Move·Scale·Turn은 자기 자신(this)을 돌려준다: room.Move(...).Scale(...).Turn(...)처럼 이어 부를 수 있다 public Room Move(long dx, long dy) { X1 += dx; X2 += dx; Y1 += dy; Y2 += dy; return this; } public Room Scale(long k) { X1 *= k; Y1 *= k; X2 *= k; Y2 *= k; return this; } public Room Turn(int times) { for (int i = 0; i < times; i++) { // 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 (X1, Y1, X2, Y2) = (-Y2, X1, -Y1, X2); } return this; } public Room Copy() => new Room(X1, Y1, X2, Y2); // 새 객체: 앞으로 따로 움직인다 public long Area() => (X2 - X1) * (Y2 - Y1); // 4×10^12까지라 long public long Overlap(Room o) { long w = Math.Min(X2, o.X2) - Math.Max(X1, o.X1); long h = Math.Min(Y2, o.Y2) - Math.Max(Y1, o.Y1); return Math.Max(0, w) * Math.Max(0, h); // 한쪽이라도 0 이하면 겹치지 않는다 } public override string ToString() => $"{X1} {Y1} {X2} {Y2}";}class Program{ static void Main() { int q = int.Parse(Console.ReadLine()!.Trim()); var rooms = new Dictionary<string, Room>(); var sb = new StringBuilder(); for (int i = 0; i < q; i++) { var p = Console.ReadLine()!.Trim().Split(' '); switch (p[0]) { case "new": rooms[p[1]] = new Room(long.Parse(p[2]), long.Parse(p[3]), long.Parse(p[4]), long.Parse(p[5])); break; case "copy": rooms[p[1]] = rooms[p[2]].Copy(); break; case "do": rooms[p[1]].Move(long.Parse(p[2]), long.Parse(p[3])).Scale(long.Parse(p[4])).Turn(int.Parse(p[5])); break; case "area": sb.Append(rooms[p[1]].Area()).Append('\n'); break; case "overlap": sb.Append(rooms[p[1]].Overlap(rooms[p[2]])).Append('\n'); break; default: sb.Append(rooms[p[1]]).Append('\n'); break; } } Console.Write(sb); }}
C++main.cpp · 86 行
#include <algorithm>#include <iostream>#include <string>#include <unordered_map>// 도면 위의 네모난 방: 왼쪽 아래 (x1, y1), 오른쪽 위 (x2, y2)class Room {public: Room() = default; Room(long long x1, long long y1, long long x2, long long y2) : x1_(x1), y1_(y1), x2_(x2), y2_(y2) {} // move·scale·turn은 자기 자신의 참조(Room&)를 돌려준다: room.move(...).scale(...).turn(...) // Room(값)으로 돌려주면 그다음 메서드는 복사본을 바꾸고, 원래 방에는 move만 남는다 Room &move(long long dx, long long dy) { x1_ += dx, x2_ += dx; y1_ += dy, y2_ += dy; return *this; } Room &scale(long long k) { x1_ *= k, y1_ *= k, x2_ *= k, y2_ *= k; return *this; } Room &turn(int times) { for (int i = 0; i < times; i++) { // 원점을 중심으로 왼쪽으로 90도: (x, y) → (-y, x). 돌린 뒤 왼쪽 아래·오른쪽 위를 다시 고른다 long long nx1 = -y2_, ny1 = x1_, nx2 = -y1_, ny2 = x2_; x1_ = nx1, y1_ = ny1, x2_ = nx2, y2_ = ny2; } return *this; } // 같은 자리의 새 방. 객체를 값으로 담는 C++에서는 복사 생성자가 하는 일과 같다 Room copy() const { return *this; } long long area() const { return (x2_ - x1_) * (y2_ - y1_); } // 4×10^12까지라 long long long long overlap(const Room &o) const { long long w = std::min(x2_, o.x2_) - std::max(x1_, o.x1_); long long h = std::min(y2_, o.y2_) - std::max(y1_, o.y1_); return std::max(0LL, w) * std::max(0LL, h); // 한쪽이라도 0 이하면 겹치지 않는다 } std::string str() const { return std::to_string(x1_) + " " + std::to_string(y1_) + " " + std::to_string(x2_) + " " + std::to_string(y2_); }private: long long x1_ = 0, y1_ = 0, x2_ = 0, y2_ = 0;};int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int q; std::cin >> q; // 사전에 객체를 값으로 담는다: rooms[b] = rooms[a]는 복사라서 copy() 메서드가 따로 없어도 둘이 따로 움직인다 std::unordered_map<std::string, Room> rooms; for (int i = 0; i < q; i++) { std::string cmd, a; std::cin >> cmd >> a; if (cmd == "new") { long long x1, y1, x2, y2; std::cin >> x1 >> y1 >> x2 >> y2; rooms[a] = Room(x1, y1, x2, y2); } else if (cmd == "copy") { std::string b; std::cin >> b; rooms[a] = rooms[b].copy(); // 사전에 값으로 담으니 rooms[a] = rooms[b]만 써도 복사다 } else if (cmd == "do") { long long dx, dy, k; int t; std::cin >> dx >> dy >> k >> t; rooms[a].move(dx, dy).scale(k).turn(t); } else if (cmd == "area") { std::cout << rooms[a].area() << '\n'; } else if (cmd == "overlap") { std::string b; std::cin >> b; std::cout << rooms[a].overlap(rooms[b]) << '\n'; } else { std::cout << rooms[a].str() << '\n'; } }}