{ }codelper
value vs reference typesrecordsP0203

The robot that bounces back

There is a room map with H rows and W columns. Each cell of the map is . (empty), # (wall) or S (the empty cell where the robot starts), and there is exactly one S. The robot follows a command string made of U (up), D (down), L (left) and R (right), one character at a time from the front. For each command the robot moves one cell in that direction. If the cell it moved to is outside the map or a wall, the robot returns to the cell it was on just before moving, and the bump count goes up by 1. After all the commands, print the row number and column number of the robot's cell (both counted from 1) and the bump count on one line, separated by single spaces. Try making the position a struct with two members, row and column, and a function (or method) that moves it one cell in place. Before each move, save the position with prev = cur, and when blocked, restore it with cur = prev.

Input
The first line gives H and W, the next H lines give one row of the map each (length W, no spaces), and the last line gives the command string.
1 ≤ H, W ≤ 100, and the command string has length from 1 to 100,000.
Output
One line: "row column bumps"
Example 1 · stdin
3 4
S..#
.#..
....
RRRDDLLUR
stdout
2 1 2
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 3 languages

This problem accepts only C, C++ and C#.
Those three let you define your own value-type struct whose data is copied whole on assignment; objects in Python, JavaScript, TypeScript and Java, and Craykon's Dict(), are references that point to the same thing after assignment (those languages restore by building a tuple or a new object).
With Point prev = cur; in C and C++, and prev = cur on a C# struct Point, prev is a separate value holding a copy of the row and column, so moving cur in place afterwards leaves prev as it was.
To move in place, C takes a pointer as in void step(Point *p, char d), writes p->r--, and calls step(&cur, d).
In C++ and C# a member function (method) changes the object itself.
Four traps: ① In C#, changing struct to class makes prev = cur just another reference to the same object, so prev moves along with cur and cur = prev restores nothing.
The robot walks into walls without any error.
② In C, holding the address as in Point *prev = &cur; does the same.
③ In C++, taking a reference Point &prev = cur; also makes prev just another name for cur.
④ In C, taking it by value as in void step(Point p, char d) goes the other way: only the copy moves, and the robot never leaves its starting cell.

C#Main.cs · 43 lines
using System; struct Point  // 값 타입: 대입하면 R, C가 통째로 복사된다{    public int R, C;    public void Step(char d)    {        if (d == 'U') R--;        else if (d == 'D') R++;        else if (d == 'L') C--;        else C++;    }} class Program{    static void Main()    {        string[] t = Console.In.ReadToEnd().Split((char[])null, StringSplitOptions.RemoveEmptyEntries);        int h = int.Parse(t[0]), w = int.Parse(t[1]);        string[] grid = new string[h];        var cur = new Point();        for (int r = 0; r < h; r++)        {            grid[r] = t[2 + r];            int c = grid[r].IndexOf('S');            if (c >= 0) cur = new Point { R = r, C = c };        }        string moves = t[2 + h];        int bumps = 0;        foreach (char d in moves)        {            Point prev = cur;  // struct라서 복사본이 따로 생긴다            cur.Step(d);            if (cur.R < 0 || cur.R >= h || cur.C < 0 || cur.C >= w || grid[cur.R][cur.C] == '#')            {                cur = prev;                bumps++;            }        }        Console.WriteLine($"{cur.R + 1} {cur.C + 1} {bumps}");    }}
C++main.cpp · 39 lines
#include <iostream>#include <string>#include <vector> struct Point {    int r = 0, c = 0;    void step(char d) {  // 멤버 함수는 자기 자신(this)을 제자리에서 바꾼다        if (d == 'U') r--;        else if (d == 'D') r++;        else if (d == 'L') c--;        else c++;    }}; int main() {    std::ios::sync_with_stdio(false);    std::cin.tie(nullptr);    int h, w;    std::cin >> h >> w;    std::vector<std::string> grid(h);    Point cur;    for (int r = 0; r < h; r++) {        std::cin >> grid[r];        auto c = grid[r].find('S');        if (c != std::string::npos) cur = {r, static_cast<int>(c)};    }    std::string moves;    std::cin >> moves;    int bumps = 0;    for (char d : moves) {        Point prev = cur;  // 값 복사: prev는 cur와 상관없는 따로 있는 Point        cur.step(d);        if (cur.r < 0 || cur.r >= h || cur.c < 0 || cur.c >= w || grid[cur.r][cur.c] == '#') {            cur = prev;            bumps++;        }    }    std::cout << cur.r + 1 << ' ' << cur.c + 1 << ' ' << bumps << '\n';}
Cmain.c · 40 lines
#include <stdio.h>#include <string.h> typedef struct {    int r, c;} Point; static char grid[100][101];static char moves[100001]; /* 원본을 제자리에서 움직이려면 포인터로 받는다 */void step(Point *p, char d) {    if (d == 'U') p->r--;    else if (d == 'D') p->r++;    else if (d == 'L') p->c--;    else p->c++;} int main(void) {    int h, w;    scanf("%d %d", &h, &w);    Point cur = {0, 0};    for (int r = 0; r < h; r++) {        scanf("%100s", grid[r]);        char *s = strchr(grid[r], 'S');        if (s) cur = (Point){r, (int)(s - grid[r])};    }    scanf("%100000s", moves);    int bumps = 0;    for (int i = 0; moves[i]; i++) {        Point prev = cur;  /* 구조체 대입: r, c가 통째로 복사된 따로 있는 값 */        step(&cur, moves[i]);        if (cur.r < 0 || cur.r >= h || cur.c < 0 || cur.c >= w || grid[cur.r][cur.c] == '#') {            cur = prev;  /* 저장해 둔 복사본으로 되돌린다 */            bumps++;        }    }    printf("%d %d %d\n", cur.r + 1, cur.c + 1, bumps);    return 0;}