-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday08.R
170 lines (155 loc) · 5.28 KB
/
day08.R
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#' @title
#' switch_opp (switch operations)
#'
#' @description
#' changes operation of specified index, using a provided scheme (mapping)
#'
#' @param operation [list]. The list of operations for which an operation is altered
#' @param index [integer]. The index of the operation to be altered
#' @param scheme [vector(character)]. mapping of operations to new operation
#'
#' @return list with same length as operation with the operation at the provided index altered
#'
switch_opp <- function(operations, index, scheme = c('jmp'='nop', 'nop'='jmp', 'acc'='acc')){
# alter specified operation
operations[[index]]$opp = scheme[operations[[index]]$opp]
# return operations
return(operations)
}
#' @title
#' acc (accumulator)
#'
#' @description
#' acc increases or decreases a single global value called the accumulator by the value given in the argument.
#' For example, acc +7 would increase the accumulator by 7.
#' The accumulator starts at 0. After an acc instruction, the instruction immediately below it is executed next.
#'
#' @param arg[integer]. Argument of current instruction
#' @param state [list]. Current state (see return).
#' @return The new active state containing:
#' - ind [integer]. active index
#' - val [integer]. active value
#'
#' @examples
#' state = list(ind=1, val=0)
#' acc(2, state)
#'
#' @details the argument is added to the current value, index is increased by one
acc <- function(arg, state){
return(list(ind=state$ind+1, val=state$val+arg))
}
#' @title
#' jmp (jumps)
#'
#' @description
#' jmp jumps to a new instruction relative to itself. The next instruction to execute is found
#' using the argument as an offset from the jmp instruction;
#' for example, jmp +2 would skip the next instruction,
#' jmp +1 would continue to the instruction immediately below it,
#' and jmp -20 would cause the instruction 20 lines above to be executed next.
#'
#' @param arg[integer]. Argument of current instruction
#' @param state [list]. Current state (see return).
#' @return The new active state containing:
#' - ind [integer]. active index
#' - val [integer]. active value
#'
#' @examples
#' state = list(ind=1, val=0)
#' jmp(2, state)
#'
#' @details the argument is added to the current index, the value remains unchanged
jmp <- function(arg, state){
return(list(ind=state$ind+arg, val=state$val))
}
#' @title
#' nop (No OPeration)
#'
#' @description
#' nop stands for No OPeration - it does nothing. The instruction immediately below it is executed next.
#'
#' @param arg[integer]. Argument of current instruction
#' @param state [list]. Current state (see return).
#' @return The new active state containing:
#' - ind [integer]. active index
#' - val [integer]. active value
#'
#' @examples
#' state = list(ind=1, val=0)
#' nop(2, state)
#'
#' @details the index is increased by one, the value remains unchanged
#'
nop <- function(arg, state){
return(list(ind=state$ind+1, val=state$val))
}
#' computer
#'
#' @description
#' Loops trough the computer-instruction untill termination.
#' Termination is achieved if:
#' - repetation of and index (unsuccesfull)
#' - index outside instrucion-set (succesfull)
#'
#' @param operations_l [list]. List containing:
#' - opp (operation) [character]. either: `acc`, `jmp`, or `nop`.
#' - arg (arguments) [integer]
#' @param start_index [integer]. Integer that is used as starting index
#' @param start_value [integer]. Integer that is used as starting value
#'
#' @return List with:
#' - state [list(integer, integer)]. last active state
#' - indices [vector(integer)]. all indices used
#' - termination [boolean]. status of termination (true for succes)
#'
#' @example
#' operations = list(
#' list(opp='nop', arg=0),
#' list(opp='acc', arg=1),
#' list(opp='jmp', arg=4),
#' list(opp='acc', arg=3),
#' list(opp='jmp', arg=-3),
#' list(opp='acc', arg=-99),
#' list(opp='acc', arg=1),
#' list(opp='jmp', arg=-4),
#' list(opp='acc', arg=6)
#' )
#'
#' computer(operations)
#'
computer <- function(operations_l, start_index=1, start_value=0){
indices = start_index
state = list(ind=indices[1], val=start_value)
while(TRUE){
# Select active operation and provide active argument and the current state
state = switch(operations_l[[state$ind]]$opp,
'acc'=acc,
'jmp'=jmp,
'nop'=nop)(operations_l[[state$ind]]$arg, state)
# Check if current index is already used (Termination unsuccesfull)
if (state$ind %in% indices) {
return(list(state=state, indices=indices, termination=FALSE))
}
# Check if current index is outside code (Termination succesfull)
if (state$ind > length(operations_l)){
return(list(state=state, indices=indices, termination=TRUE))
}
indices = c(indices, state$ind)
}
}
#### Read and parsed input -----------
inp = readLines("inp/day8_inp.txt", )
operations = lapply(strsplit(inp, " "), function(x) list(opp=x[1], arg=as.numeric(x[2])))
#### Part 1 -------------------------
print(computer(operations)$state$val)
#### Part 2 --------------------
for(i in 1:length(operations)) {
# Switch operation
operations_tmp = switch_opp(operations, i)
### Parse computer
result = computer(operations_tmp)
# If succesfully terminated print value
if(result$ter){
print(result$state$val)
}
}