ABOUT ME

Today
Yesterday
Total
  • 프로그래머스 [빛의 경로 사이클]
    알고리즘/프로그래머스 2021. 9. 29. 12:09
    enum Direction {
      LEFT = 0,
      UP = 1,
      RIGHT = 2,
      DOWN = 3
    }
    
    class NodeCircle {
      mark: string;
      visitDirection: Set<Direction>;
      constructor(mark: string) {
        this.mark = mark;
        this.visitDirection = new Set<Direction>();
      }
      isVisit(dir: Direction): boolean {
        return this.visitDirection.has(dir);
      }
      visit(dir: Direction): void {
        this.visitDirection.add(dir);
      }
    }
    
    class Position {
      posX: number;
      posY: number;
      private maxPosX: number;
      private maxPosY: number;
    
      constructor(posX: number, posY: number, maxPosX: number, maxPosY: number) {
        this.posX = posX;
        this.posY = posY;
        this.maxPosX = maxPosX;
        this.maxPosY = maxPosY;
      }
    
      update(dir: Direction): void {
        if (dir === Direction.UP) {
          this.posX--;
          if (this.posX < 0) this.posX = this.maxPosX;
        } else if (dir === Direction.LEFT) {
          this.posY--;
          if (this.posY < 0) this.posY = this.maxPosY;
        } else if (dir === Direction.RIGHT) {
          this.posY++;
          if (this.posY > this.maxPosY) this.posY = 0;
        } else {
          // down
          this.posX++;
          if (this.posX > this.maxPosX) this.posX = 0;
        }
      }
    }
    
    class MovingLight {
      moveCount: number;
    
      private pos: Position;
      private world: NodeCircle[][];
      private dir: Direction;
    
      private originPosX: number;
      private originPosY: number;
      private originDir: Direction;
    
      constructor(pos: Position, dir: Direction, world: NodeCircle[][]) {
        this.pos = pos;
        this.dir = dir;
        this.world = world;
        this.moveCount = 0;
    
        this.originPosX = pos.posX;
        this.originPosY = pos.posY;
        this.originDir = dir;
      }
      isStartPoint(): boolean {
        if (
          this.pos.posX === this.originPosX &&
          this.pos.posY === this.originPosY &&
          this.dir === this.originDir
        ) {
          return true;
        }
        return false;
      }
      isAlreadyVisit() {
        const node = this.world[this.pos.posX][this.pos.posY];
        return node.isVisit(this.dir);
      }
    
      getNextDir(): Direction {
        const node = this.world[this.pos.posX][this.pos.posY];
        if (node.mark === "S") {
          return this.dir;
        } else if (node.mark === "R") {
          const nextDir = this.dir + 1;
          if (nextDir > 3) return 0;
          return nextDir;
        } else {
          const nextDir = this.dir - 1;
          if (nextDir < 0) return 3;
          return nextDir;
        }
      }
    
      move() {
        this.moveCount++;
        this.pos.update(this.dir);
        this.dir = this.getNextDir();
      }
    
      process(): boolean {
        while (true) {
          this.move();
          if (this.isStartPoint()) return true;
          if (this.isAlreadyVisit()) return false;
          const node = this.world[this.pos.posX][this.pos.posY];
          node.visit(this.dir);
        }
      }
    }
    
    function comparerForAscendingOrder(a: number, b: number) {
      if (a > b) return 1;
      else if (a < b) return -1;
      else return 0;
    }
    
    function makeWorldFromGrid(grid: string[]) {
      const world: NodeCircle[][] = Array.from(
        Array(grid.length),
        () => new Array(grid[0].length)
      );
      for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[0].length; j++) {
          world[i][j] = new NodeCircle(grid[i][j]);
        }
      }
      return world;
    }
    
    function solution(grid: string[]) {
      const result: number[] = [];
      const world = makeWorldFromGrid(grid);
    
      const gridMaxX = grid.length - 1;
      const gridMaxY = grid[0].length - 1;
    
      for (let i = 0; i <= gridMaxX; i++) {
        for (let j = 0; j <= gridMaxY; j++) {
          for (let k = 0; k < 4; k++) {
            const startPos = new Position(i, j, gridMaxX, gridMaxY);
            const light = new MovingLight(startPos, k, world);
            if (light.process()) result.push(light.moveCount);
          }
        }
      }
      return result.sort(comparerForAscendingOrder);
    }
    
Designed by Tistory.