- 맨 왼쪽에는 홀수중 가장 작은 숫자가, 그 다음에는 짝수중 가장 작은 숫자가, 그 다음에는 홀수중 두번째로 작은 숫자가, 그 다음에는 짝수중 두번째로 작은 숫자가 입력된다...

package main

import (
	"fmt"
	"os"
)

func safe(person bool, others []bool) bool {
	if others[0] == others[1] && others[1] != person || others[1] == others[2] && others[2] != person {
		return false
	}
	return true
}
func turn(person bool, others []bool, lastWith int) {
	if !others[0] && !others[1] && !others[2] {
		fmt.Println(others)
		os.Exit(0)
	}
	if !safe(person, others) {
		return
	}
	fmt.Println(others, person)
	for i := -1; i < len(others); i++ {
		newArray := make([]bool, 0)
		newArray = append(newArray, others...)
		if i == lastWith {
			continue
		}
		if i == -1 {
			turn(!person, newArray, i)
			continue
		}
		if person == newArray[i] {
			newArray[i] = !newArray[i]
			turn(!person, newArray, i)
		}
	}
}

func main() {
	others := []bool{true, true, true} // 늑대, 토끼, 당근
	turn(true, others, -1)

}

// 선정이유 : 재귀함수를 명확하게 알수있는 문제여서 해당문제를 선정했다.
//			 빈배열을 선언해서 append 해주는것도, 조건을 걸어 재귀함수가 충족되는 조건도 이 문제가 가장
//			 기억에 남는다.
//			 safe를 해주는 위치, lastwith을 먼저 체크해주는 위치, 그 다음조건을 차례대로 위치시켜주는것도
//			 중요하기에 해당 문제가 제일 기억에 남는다.
//			 같이 건너온 경우의 조건일경우 continue를 해서 넘어가고, 같이 안건넌경우(사람만 건넌경우)에는
//			 사람의 상태값만 변경해서 넘어간다.

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - 강 건너기  (0) 2023.03.30
(GO/알고리즘) - 탈출 불가능한 미로  (0) 2023.03.30
(GO/알고리즘) - 샘물  (0) 2023.03.30
(GO/알고리즘) - Jump  (0) 2023.03.30
(GO/알고리즘) - Rank (인터페이스)  (0) 2023.03.30

- 강을 건너야 한다. 보트가 하나 있고, 왼편에 사람, 늑대, 토끼, 당근이 존재한다. 보트는 사람만이 운전할 수 있다.

사람이 같이 없을 때 늑대와 토끼가 같이 있으면 토끼가 잡아먹힌다. 사람이 없을 때 토끼와 당근이 같이 있으면 당근이 먹힌다.

보트에는 최대 2명(2개)가 탈 수 있다. (항상 사람이 한자리는 차지할 것이지만).

안전하게 강 우측으로 건너기 위한 방법을 찾아내시오.



힌트) 매 턴 사람은 배를 타야 하므로 위치가 반대편으로 간다. 사람이 같이 없다는 걸 어떻게 알 수 있을까?

lastwith는 사람이 방금 전 같이 타고 온 게 누구(무엇)인지 표시할 수 있다. 이것으로 루프 발생을 억제할 수 있지 않을까?

가끔은 사람이 혼자 타야 할지도 모른다. (greedy: 사람이 혼자 타도 무사한 경우는 대체로 긍정적이다)

package main

import (
	"fmt"
	"os"
)

func safe(person bool, others []bool) bool {
	if others[0] == others[1] && others[1] != person || others[1] == others[2] && others[2] != person {
		return false
	}
	return true
}
func turn(person bool, others []bool, lastWith int) {
	if !others[0] && !others[1] && !others[2] {
		fmt.Println(others)
		os.Exit(0)
	}
	if !safe(person, others) {
		return
	}
	fmt.Println(others, person)
	for i := -1; i < len(others); i++ {
		newArray := make([]bool, 0)
		newArray = append(newArray, others...)
		if i == lastWith {
			continue
		}
		if i == -1 {
			turn(!person, newArray, i)
			continue
		}
		if person == newArray[i] {
			newArray[i] = !newArray[i]
			turn(!person, newArray, i)
		}
	}
}

func main() {
	others := []bool{true, true, true} // 늑대, 토끼, 당근
	turn(true, others, -1)

}

// 선정이유 : 재귀함수를 명확하게 알수있는 문제여서 해당문제를 선정했다.
//			 빈배열을 선언해서 append 해주는것도, 조건을 걸어 재귀함수가 충족되는 조건도 이 문제가 가장
//			 기억에 남는다.
//			 safe를 해주는 위치, lastwith을 먼저 체크해주는 위치, 그 다음조건을 차례대로 위치시켜주는것도
//			 중요하기에 해당 문제가 제일 기억에 남는다.
//			 같이 건너온 경우의 조건일경우 continue를 해서 넘어가고, 같이 안건넌경우(사람만 건넌경우)에는
//			 사람의 상태값만 변경해서 넘어간다.

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - ZigZag2  (0) 2023.03.30
(GO/알고리즘) - 탈출 불가능한 미로  (0) 2023.03.30
(GO/알고리즘) - 샘물  (0) 2023.03.30
(GO/알고리즘) - Jump  (0) 2023.03.30
(GO/알고리즘) - Rank (인터페이스)  (0) 2023.03.30

- 미로의 벽이 촘촘하여 0,0 에서 8,8까지 도착할 방법은 없다.

그런데, 당신은 폭탄을 가지고 있어서 벽을 제거 할 수 있다.

bfs를 이용하여 0,0 에서 8,8 까지 도달하되 폭탄이 최소 몇 개가 필요한지 알아내시오.

힌트) visited → usedbomb을 기록. 갔던 길이라도 usedbomb이 적다면 다시 갈 수 있다!

가는 거리의 최단 코스가 아니고, 폭탄 사용 횟수만이 중요하므로 돌아가는 건 상관 없다.

package main

import (
	"fmt"
	"math"
)

type MazeBomb struct {
	x, y int
	bomb int
}

func mazeBomb(maze [][]int, x, y int) {
	queue := []*MazeBomb{{x, y, 0}}
	bombCnt := make([][]int, len(maze))
	for v := range bombCnt {
		bombCnt[v] = make([]int, len(maze[0]))
		for j := range bombCnt[v] {
			bombCnt[v][j] = math.MaxInt32
		}
	}

	bombCnt[y][x] = 0

	for len(queue) > 0 {
		ogQueue := queue[0]
		queue = queue[1:]

		direction := [][]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}

		for _, dir := range direction {
			nx, ny := ogQueue.x+dir[0], ogQueue.y+dir[1]
			if nx == -1 || ny == -1 || nx == len(maze) || ny == len(maze[0]) {
				continue
			}
			bomb := ogQueue.bomb
			if maze[ny][nx] == 1 {
				bomb++
			}
			if bombCnt[ny][nx] <= bomb {
				continue
			}
			bombCnt[ny][nx] = bomb
			queue = append(queue, &MazeBomb{nx, ny, bomb})
		}
	}
	for i := 0; i < len(maze); i++ {
		fmt.Println(bombCnt[i])
	}
}

func main() {
	maze := [][]int{
		{0, 1, 0, 1, 0, 0, 0, 0, 1},
		{0, 0, 1, 1, 0, 1, 0, 1, 1},
		{1, 0, 1, 0, 0, 1, 1, 0, 0},
		{0, 0, 1, 0, 1, 0, 1, 0, 1},
		{0, 1, 1, 0, 0, 0, 1, 1, 0},
		{0, 0, 1, 0, 1, 0, 1, 0, 0},
		{0, 1, 0, 0, 1, 1, 0, 0, 1},
		{0, 1, 0, 1, 1, 1, 0, 1, 1},
		{1, 1, 0, 0, 1, 1, 0, 0, 0},
	}
	mazeBomb(maze, 0, 0)
}

// 선정이유 : 이중배열의 선언과 for문 활용, 방향벡터의 사용성, bfs사용방법이 모두 들어있는 문제고, 많은 도움이 되었기에 이 문제를 선정
//			 기존 미로배열과, 폭탄이 사용되는 횟수를 담아줄 이중배열을 선언해줍니다.
//			 여기서 bombCnt가 높은수가 되어야 하는이유는, 처음 들어오는 값이 기존값을 갱신할 수 있어야 하기 때문입니다.
//			 그렇기에 최고값인 MaxInt를 주거나, maze의 크기보다는 큰 값을 주는게 일반적입니다.
//			 그렇게 선언해준뒤, bombCnt의 출발점을 0으로 변경해주고 for문을 돌립니다.
//			 pop함수는 따로 써주지 않고 안에서 직접 선언해주었고, 방향벡터 direction을 선언해주었습니다,
//			 4방향으로 돌려주고 bomb에 기존 bomb를 넣어주고 미로가 벽일때 bomb를 추가해줍니다.
//			 현재 bombCnt위치보다 bomb가 크거나 혹은 둘이 같으면 continue해주고, 아니면 그 위치에 폭탄 개수를 넣어준다.
//			 그 이유는 지나오면서 폭탄이 몇개 사용되었는지 체크하기 위함이고, 그걸 다시 queue에 append해서 넘겨주는걸 반복한다.
//			 그렇게 for문이 돌면서 bombCnt에 폭탄사용횟수가 기록되며, 최종적으로 다 돌았을 때 최소 폭탄 갯수를 사용한 길을
//			 알수있다.
//			 엔딩조건은 큐에 노드를 추가하고 그 노드를 하나씩 제거하며 경로를 찾는것인데, 그 노드가 없으면 결국 도착점에
//			 도달했다는 의미이기 때문에, for 문이 종료된다.
//

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - ZigZag2  (0) 2023.03.30
(GO/알고리즘) - 강 건너기  (0) 2023.03.30
(GO/알고리즘) - 샘물  (0) 2023.03.30
(GO/알고리즘) - Jump  (0) 2023.03.30
(GO/알고리즘) - Rank (인터페이스)  (0) 2023.03.30

- 다음은 9x9 맵이다. 당신은 0,0에서 8,8까지 도착해야 한다.

당신은 한칸 움직일때 마다 1살씩 나이를 먹게 된다.

단, 미로에 딱 한군데 있는 9번이 붙은 블럭의 샘물에 가면 나이가 5살 젊어진다.

당신이 8,8에 도착할 때 나이는 몇살이 될 수 있을까? (젊을 수록 좋다)

package main

import (
	"fmt"
	"os"
)

type waterMaze struct {
	x, y int
	age  int
}

func waterBFS(maze [][]int, x, y int, age int) int {
	queue := []*waterMaze{{x, y, age}}
	waterCnt := make([][]int, len(maze))
	for i := range waterCnt {
		waterCnt[i] = make([]int, len(maze[0]))
		for j := 0; j < len(maze[0]); j++ {
			waterCnt[i][j] = 99
		}
	}

	waterCnt[y][x] = 0
	cnt := 0

	for len(queue) > 0 {
		ogQueue := queue[0]
		queue = queue[1:]

		if ogQueue.x == len(maze)-1 && ogQueue.y == len(maze[0])-1 {
			cnt++
			if cnt == 800 {
				for i := 0; i < len(maze); i++ {
					fmt.Println(waterCnt[i])
				}
				os.Exit(0)
			}
		}

		direction := [][]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}

		for _, dir := range direction {
			nx, ny := ogQueue.x+dir[0], ogQueue.y+dir[1]
			if nx == -1 || ny == -1 || nx == len(maze) || ny == len(maze[0]) {
				continue
			}
			if maze[ny][nx] == 1 {
				continue
			}
			if maze[ny][nx] == 9 && ogQueue.age-5 >= 0 {
				queue = append(queue, &waterMaze{nx, ny, ogQueue.age - 5})
				waterCnt[ny][nx] = ogQueue.age - 5
				continue
			}
			if waterCnt[ny][nx]+5 <= ogQueue.age {
				continue
			}
			if waterCnt[ny][nx] > ogQueue.age {
				waterCnt[ny][nx] = ogQueue.age + 1
			}
			queue = append(queue, &waterMaze{nx, ny, ogQueue.age + 1})
		}
	}
	return -1
}

func main() {
	maze := [][]int{
		{0, 1, 1, 0, 1, 1, 0, 0, 0},
		{0, 0, 0, 0, 0, 1, 1, 0, 1},
		{1, 0, 1, 1, 0, 0, 0, 0, 0},
		{0, 0, 1, 0, 0, 1, 1, 0, 1},
		{0, 1, 0, 0, 1, 0, 0, 0, 0},
		{0, 0, 0, 1, 1, 1, 0, 1, 1},
		{1, 0, 1, 0, 0, 0, 0, 0, 1},
		{0, 0, 0, 0, 1, 1, 0, 1, 1},
		{9, 1, 1, 0, 0, 0, 0, 0, 0},
	}
	waterBFS(maze, 0, 0, 0)
}

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - 강 건너기  (0) 2023.03.30
(GO/알고리즘) - 탈출 불가능한 미로  (0) 2023.03.30
(GO/알고리즘) - Jump  (0) 2023.03.30
(GO/알고리즘) - Rank (인터페이스)  (0) 2023.03.30
(GO/알고리즘) - Rank  (0) 2023.03.30

- 다음은 16x16의 맵이다. 시작점은 (0,0)이며 반대편의 (15,15)에 도착해야 끝이 난다.

각 지점에 적혀있는 숫자는 그 자리에서 움직이는 칸 수가 된다. 만약 숫자가 3이 적혀있는 곳에서는 동, 서, 남, 북으로 3칸을 점프해서 움직일 수 있다.

(더 적게 움직이지는 못한다)

0, 0을 출발하여 가장 움직인 횟수가 적은 경로의 점프 횟수를 구하라. (점프한 횟수만 센다. 거리를 구하는 문제는 아님)

package main

import (
	"fmt"
	"os"
)

type jump struct {
	x, y, cnt int
}

func jumpBFS(maze [][]int, x, y, cnt int) int {
	queue := []*jump{{x, y, cnt}}
	jumpCnt := make([][]int, len(maze))
	for i := range jumpCnt {
		jumpCnt[i] = make([]int, len(maze[0]))
		for j := 0; j < len(maze[0]); j++ {
			jumpCnt[i][j] = 100
		}
	}

	jumpCnt[x][y] = 0

	for len(queue) > 0 {
		ogQueue := queue[0]
		queue = queue[1:]

		if ogQueue.x == len(maze)-1 && ogQueue.y == len(maze[0])-1 {
			fmt.Println(jumpCnt[len(maze)-1][len(maze[0])-1])
			for i := 0; i < len(maze); i++ {
				fmt.Println(jumpCnt[i])
			}
			fmt.Println("Yeah!!!")
			os.Exit(0)
		}

		dir := [][]int{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}

		for _, d := range dir {
			nx, ny := ogQueue.x+d[0]*maze[ogQueue.y][ogQueue.x], ogQueue.y+d[1]*maze[ogQueue.y][ogQueue.x]
			if nx <= -1 || ny <= -1 || nx >= len(maze) || ny >= len(maze[0]) {
				continue
			}
			if jumpCnt[ny][nx] <= ogQueue.cnt {
				continue
			}
			jumpCnt[ny][nx] = ogQueue.cnt + 1
			queue = append(queue, &jump{nx, ny, ogQueue.cnt + 1})

		}
	}
	return -1
}

func main() {
	a := [][]int{
		{2, 2, 3, 2, 2, 2, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2},
		{1, 2, 4, 2, 2, 2, 4, 1, 2, 3, 2, 4, 2, 1, 2, 1},
		{2, 1, 2, 6, 2, 5, 5, 2, 1, 2, 3, 4, 2, 3, 1, 3},
		{1, 2, 5, 2, 2, 3, 2, 4, 1, 2, 5, 1, 2, 3, 1, 3},
		{2, 3, 2, 4, 2, 2, 5, 2, 3, 4, 2, 3, 4, 2, 3, 4},
		{1, 4, 2, 3, 2, 5, 2, 3, 1, 2, 3, 2, 3, 2, 3, 5},
		{6, 3, 2, 4, 3, 5, 3, 2, 5, 2, 4, 2, 3, 1, 1, 2},
		{3, 2, 4, 3, 2, 3, 3, 2, 3, 2, 2, 1, 3, 1, 3, 2},
		{1, 2, 3, 2, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 1},
		{1, 2, 4, 2, 6, 2, 1, 2, 2, 3, 5, 3, 4, 1, 2, 3},
		{2, 1, 2, 1, 1, 5, 3, 5, 1, 2, 3, 4, 2, 3, 5, 4},
		{1, 2, 1, 2, 2, 4, 2, 1, 1, 2, 1, 5, 2, 3, 1, 3},
		{2, 3, 2, 4, 2, 2, 1, 2, 1, 1, 2, 3, 4, 2, 3, 4},
		{1, 4, 2, 3, 2, 5, 2, 3, 2, 3, 2, 2, 3, 2, 3, 5},
		{1, 3, 2, 4, 3, 5, 3, 2, 1, 2, 4, 2, 3, 2, 4, 2},
		{3, 2, 1, 1, 2, 3, 3, 2, 1, 2, 2, 4, 2, 1, 3, 0},
	}
	jumpBFS(a, 0, 0, 0)
}

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - 탈출 불가능한 미로  (0) 2023.03.30
(GO/알고리즘) - 샘물  (0) 2023.03.30
(GO/알고리즘) - Rank (인터페이스)  (0) 2023.03.30
(GO/알고리즘) - Rank  (0) 2023.03.30
(GO/알고리즘) - 정규식2  (0) 2023.03.30

- 다음은 9x9 맵이다. 당신은 0,0에서 8,8까지 도착해야 한다.

당신은 한칸 움직일때 마다 1살씩 나이를 먹게 된다.

단, 미로에 딱 한군데 있는 9번이 붙은 블럭의 샘물에 가면 나이가 5살 젊어진다.

당신이 8,8에 도착할 때 나이는 몇살이 될 수 있을까? (젊을 수록 좋다)

package main

import (
	"fmt"
	"sort"
)

type student struct {
	score  int
	number int
	rank   int
}

type studentList []student

func (s studentList) Len() int {
	return len(s)
}

func (s studentList) Less(i, j int) bool {
	if s[i].score == s[j].score {
		s[i].rank = s[j-1].rank
		return s[i].number < s[j].number
	}
	return s[i].score > s[j].score
}

func (s studentList) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func main() {
	a := []int{87, 34, 24, 95, 21, 25, 39, 19, 66, 74, 5, 11, 92, 84, 41, 48, 85, 64, 78, 84}

	var students studentList
	for i, score := range a {
		students = append(students, student{score, i + 1, 0})
	}

	sort.Sort(students)

	fmt.Println("5등..")
	fmt.Println("13등..")

	ranksGrp := make(map[int][]int)
	rank := 1
	for i := range students {
		if i > 0 && students[i].score < students[i-1].score {
			rank = i + 1
		}
		students[i].rank = rank
		ranksGrp[rank] = append(ranksGrp[rank], students[i].number)
	}
	for _, number := range ranksGrp[5] {
		fmt.Println("5등 번호: ", number)
	}
	fmt.Println("13등 번호: ", students[12].number)

}

'코딩 > Go' 카테고리의 다른 글

(GO/알고리즘) - 샘물  (0) 2023.03.30
(GO/알고리즘) - Jump  (0) 2023.03.30
(GO/알고리즘) - Rank  (0) 2023.03.30
(GO/알고리즘) - 정규식2  (0) 2023.03.30
(GO/알고리즘) - 정규식  (0) 2023.03.30

+ Recent posts