본문 바로가기

Go

프로그래머스 [PCCP 기출문제] 3번 / 충돌위험 찾기 - golang

func main() {
	points := [][]int{{2, 2}, {2, 3}, {2, 7}, {6, 6}, {5, 2}}
	routes := [][]int{{2, 3, 4, 5}, {1, 3, 4, 5}}
	fmt.Println(solution(points, routes))
}

func solution(points [][]int, routes [][]int) int {

	// 충돌 횟수
	result := 0
	// 경과 시간
	cnt := 0
	// 각각의 초단위 로봇별 지점 확인 key : [로봇넘버] value : 로봇의 좌표
	pointsMap := make(map[int][2]int, 0)
	// [지나간 포인트의 갯수,지금 가고 있는 방향]
	currentHeadingRoute := make([][2]int, 0)
	for i := 0; i < len(routes); i++ {
		initPointAndDirection := [2]int{2, routes[i][1]}
		currentHeadingRoute = append(currentHeadingRoute, initPointAndDirection)
		var tmp [2]int

		tmp[0] = points[routes[i][0]-1][0]
		tmp[1] = points[routes[i][0]-1][1]

		pointsMap[i] = tmp
	}

	pointChan := make(chan [][2]int)

	//cnt 를 늘리는 루프 설정
	go func() {
		for {
			// 0초일때 예외 설정
			if cnt == 0 {
				tmpArray := make([][2]int, 0)
				for _, value := range pointsMap {

					tmpArray = append(tmpArray, value)
				}
				pointChan <- tmpArray
				cnt++
				continue
			}

			// 시간별 각 로봇의 위치 계산
			tmpArray := make([][2]int, 0)
		outerLoop:
			for i := 0; i < len(routes); i++ {

				//time.Sleep(time.Second)
				previousPoint := pointsMap[i]
				var destinationPoint [2]int

				destinationPoint[0] = points[currentHeadingRoute[i][1]-1][0]
				destinationPoint[1] = points[currentHeadingRoute[i][1]-1][1]
				currentPoint := previousPoint

				// 현재 지점과 도착지점이 같을떄

				// 없다면 continue 로 escape
				if currentPoint == destinationPoint {
					// destinationPoint 가 마지막인지 아닌지
					if len(routes[i]) == currentHeadingRoute[i][0] {
						continue outerLoop
					} else {
						// 지나간 포인트의 갯수 + 1
						currentHeadingRoute[i][0] = currentHeadingRoute[i][0] + 1
						// 현재 지나갈 방향 다시 업데이트
						currentHeadingRoute[i][1] = routes[i][currentHeadingRoute[i][0]-1]
						// 현재 가야하는 좌표 업데이트

						destinationPoint[0] = points[currentHeadingRoute[i][1]-1][0]
						destinationPoint[1] = points[currentHeadingRoute[i][1]-1][1]

					}
				}

				// x 축 체크 destinationPoint[0] = x 축 , [1] = y축
				if previousPoint[0] != destinationPoint[0] {
					// 목적지의 x 축이 더 작다면 -
					if previousPoint[0] > destinationPoint[0] {
						currentPoint[0] = previousPoint[0] - 1
					} else {
						// 목적지의 x 축이 더 크다면 +
						currentPoint[0] = previousPoint[0] + 1
					}
					tmpArray = append(tmpArray, currentPoint)
					// 현재 for 문 escape
					//fmt.Println("x축 이후")
					// 현재 로봇의 위치 업데이트
					pointsMap[i] = currentPoint
					//fmt.Println(fmt.Sprintf("%d초에 %d번쨰 로봇의 위치", cnt, i+1), currentPoint)
					continue
				}

				// y 축 체크
				if previousPoint[1] != destinationPoint[1] {
					// 목적지의 y 축이 더 작다면 -
					if previousPoint[1] > destinationPoint[1] {
						currentPoint[1] = previousPoint[1] - 1
					} else {
						// 목적지의 y 축이 더 크다면 +
						currentPoint[1] = previousPoint[1] + 1
					}
					tmpArray = append(tmpArray, currentPoint)
					// 현재 for 문 escape
					//fmt.Println("y축 이후")
					// 현재 로봇의 위치 업데이트
					pointsMap[i] = currentPoint
					//fmt.Println(fmt.Sprintf("%d초에 %d번쨰 로봇의 위치", cnt, i+1), currentPoint)
					continue
				}

			}
			//
			if len(tmpArray) == 0 {
				close(pointChan)
				break
			}
			pointChan <- tmpArray
			cnt++
		}
	}()

	for {
		select {
		case tmpPoints, ok := <-pointChan:
			if !ok {
				return result
			}
			// map을 통해 몇번의 충돌이 있었는지 계산
			duplicateMap := make(map[[2]int]int, 0)
			// map key : 현재 로봇의 위치 , value : 겹쳐있는 숫자
			for _, value := range tmpPoints {
				if _, exists := duplicateMap[value]; !exists {
					duplicateMap[value] = 1
				} else {
					duplicateMap[value] = duplicateMap[value] + 1
				}
			}
			// value 가 2 이상일 경우 모두 충돌 간주
			for _, value := range duplicateMap {
				if value >= 2 {
					result = result + 1
				}
			}
		}

	}

}