この問題は C・C++・C# だけを受け付けます。 代入するとデータが丸ごとコピーされる値型の構造体(struct)を自分で作れるのはこの三つです。 Python・JavaScript・TypeScript・Java のオブジェクトと Craykon の 辞書() は代入すると同じものを共有する参照なので、この問題の copy には別にコピーを作る必要があります。 C・C++ の r[i] = r[j] はメンバをすべてコピーするので、そのあと二台は別々に動きます。 C# は struct Point なら同じようにコピーされますが、class Point だと同じ代入が参照だけをコピーし、そのあと片方を動かすと二つの枠が一緒に動きます。 落とし穴三つ:① C で void move(Point p, int dx, int dy) のように値で受けるとコピーだけが動き、配列のロボットはそのままです。 Point *p で受けて move(&r[i], dx, dy) と呼び、中では p->x += dx と書きます(C++ はメンバ関数か Point&)。 ② C# で struct を class に変えると、copy のあと二台が一台になります。 ③ C# の List<Point> で r[i].Move(dx, dy) はコンパイルも通りエラーも出ませんが、インデクサが返したコピーだけを動かして捨てます。 配列 Point[] の要素は変数なので r[i].Move() が要素そのものを変えます。 List なら取り出して変えてから戻します(var p = r[i]; p.Move(dx, dy); r[i] = p;)。
C#Main.cs · 41 行
using System;using System.IO;using System.Text;struct Point // 값 타입: 대입하면 데이터가 복사된다{ public int X, Y; public void Move(int dx, int dy) { X += dx; Y += dy; }}class Program{ static void Main() { string[] t = Console.In.ReadToEnd().Split((char[])null, StringSplitOptions.RemoveEmptyEntries); int pos = 0; int n = int.Parse(t[pos++]); var r = new Point[n]; // 배열 칸은 변수라서 r[i].Move()가 칸 자체를 바꾼다 for (int i = 0; i < n; i++) r[i] = new Point { X = int.Parse(t[pos++]), Y = int.Parse(t[pos++]) }; int q = int.Parse(t[pos++]); for (int k = 0; k < q; k++) { string cmd = t[pos++]; int i = int.Parse(t[pos++]) - 1; if (cmd == "move") { int dx = int.Parse(t[pos++]), dy = int.Parse(t[pos++]); r[i].Move(dx, dy); } else { int j = int.Parse(t[pos++]) - 1; if (cmd == "copy") r[i] = r[j]; // 복사본이 들어가서 이후 따로 움직인다 else (r[i], r[j]) = (r[j], r[i]); } } var sb = new StringBuilder(); foreach (var p in r) sb.Append(p.X).Append(' ').Append(p.Y).Append('\n'); Console.Write(sb); }}
C++main.cpp · 38 行
#include <iostream>#include <string>#include <utility>#include <vector>struct Point { int x, y; void move(int dx, int dy) { // 멤버 함수는 자기 자신(원본)을 바꾼다 x += dx; y += dy; }};int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int n, q; std::cin >> n; std::vector<Point> r(n); for (auto& p : r) std::cin >> p.x >> p.y; std::cin >> q; std::string cmd; for (int k = 0; k < q; k++) { int i, j, dx, dy; std::cin >> cmd; if (cmd == "move") { std::cin >> i >> dx >> dy; r[i - 1].move(dx, dy); // vector의 operator[]는 참조를 돌려줘서 원본이 바뀐다 } else if (cmd == "copy") { std::cin >> i >> j; r[i - 1] = r[j - 1]; // 값 복사 } else { std::cin >> i >> j; std::swap(r[i - 1], r[j - 1]); } } for (const auto& p : r) std::cout << p.x << " " << p.y << "\n";}
Cmain.c · 39 行
#include <stdio.h>#include <string.h>typedef struct { int x, y;} Point;/* 원본을 움직이려면 포인터로 받는다 */void move(Point *p, int dx, int dy) { p->x += dx; p->y += dy;}int main(void) { static Point r[1000]; int n, q; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d %d", &r[i].x, &r[i].y); scanf("%d", &q); char cmd[8]; for (int k = 0; k < q; k++) { int i, j, dx, dy; scanf("%7s", cmd); if (strcmp(cmd, "move") == 0) { scanf("%d %d %d", &i, &dx, &dy); move(&r[i - 1], dx, dy); } else if (strcmp(cmd, "copy") == 0) { scanf("%d %d", &i, &j); r[i - 1] = r[j - 1]; /* 구조체 대입은 멤버를 통째로 복사: 이후 둘은 따로 움직인다 */ } else { scanf("%d %d", &i, &j); Point t = r[i - 1]; r[i - 1] = r[j - 1]; r[j - 1] = t; } } for (int i = 0; i < n; i++) printf("%d %d\n", r[i].x, r[i].y); return 0;}