-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday-02.R
More file actions
109 lines (94 loc) · 2.99 KB
/
day-02.R
File metadata and controls
109 lines (94 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#' Closure-based implementation of a submarine "object"
#'
#' The function acts as a "constructor" which returns a closure capturing
#' all "properties" of the object and returns a list of functions acting as
#' its "methods".
#'
#' Inspired by the following post:
#' https://win-vector.com/2015/03/27/using-closures-as-objects-in-r/
submarine <- function(location = c(0, 0), aim = 0, mode = c("v1", "v2")) {
# the mode argument acts as a switch between the two submarine specifications
mode <- match.arg(mode)
#
# "public methods"
#
# Load the submarine program from a given file
load_program <- function(file) {
# parse the file of submarine movement instructions -- one instruction per line,
# each instruction in the form of:
# <"forward" | "up" | "down"> <integer number>
instructions <- readLines(file) |>
lapply(\(instruction) {
tokens <- strsplit(instruction, " ")[[1]]
list(direction = tokens[1], step = as.integer(tokens[2]))
})
program <<- instructions
index <<- 1
invisible(NULL)
}
# Execute the next instruction in the program
next_instruction <- function() {
if (index > length(program)) {
cat("No instructions left\n")
return()
}
direction <- program[[index]]$direction
step <- program[[index]]$step
move <- next_move(direction, step)
location <<- location + move
index <<- index + 1
}
# Print the entire program in a readable form
print_program <- function() {
for (i in seq(index, length(program))) {
direction <- program[[i]]$direction
step <- program[[i]]$step
cat(sprintf("instruction #%d: %s - %d\n", i, direction, step))
}
}
# Execute the entire program, one instruction at a time
execute_program <- function() {
for (i in seq_along(program)) {
next_instruction()
}
}
# Return the current location of the submarine in two dimensions
# (horizontal coordinate, depth)
get_location <- function() location
#
# "private methods"
#
# First version of the move method utilizing only horizontal
next_move_v1 <- function(direction, step) {
if (direction == "forward")
move <- c(step, 0)
else if (direction == "up")
move <- c(0, -step)
else if (direction == "down")
move <- c(0, step)
else
stop("Invalid direction", direction, call. = FALSE)
move
}
next_move_v2 <- function(direction, step) {
move <- c(0, 0)
if (direction == "forward")
move <- c(step, abs(aim * step))
else if (direction == "up")
aim <<- aim + step
else if (direction == "down")
aim <<- aim - step
else
stop("Invalid direction", direction, call. = FALSE)
move
}
next_move <- if (mode == "v1") next_move_v1 else next_move_v2
# return the constructed "object" as a list of its methods
list(
load_program = load_program,
next_instruction = next_instruction,
print_program = print_program,
execute_program = execute_program,
get_location = get_location
)
}