-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday07.R
147 lines (113 loc) · 3.77 KB
/
day07.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
# Example input, if needed
# day07 <- read.table("puzzle_input/input_day07_exp.txt")
day07 <- read.table("puzzle_input/input_day07.txt")
names(day07) <- c("hand", "bid")
hands_split <- as.data.frame(do.call(rbind, strsplit(day07$hand, "")))
names(hands_split) <- paste0("hand", 1:5)
hands_split$bid <- day07$bid
# Function to identify the hand type. Hand is a vector of (five) cards.
# Five of a kind = 7
# Four of a kind = 6
# Full house = 5
# Three of a kind = 4
# Two pair = 3
# One pair = 2
# High card = 1
identify_hand <- function(hand) {
hand_table <- table(hand)
if (any(hand_table == 5)) { # Five of a kind
return(7)
} else if (any(hand_table == 4)) { # Four of a kind
return(6)
} else if (any(hand_table == 3) & any(hand_table == 2)) { # full house
return(5)
} else if (any(hand_table == 3)) { # three of a kind
return(4)
} else if (sum(hand_table == 2) == 2) { # two pair
return(3)
} else if (any(hand_table == 2)) { # one pair
return(2)
} else { # high card
return(1)
}
}
# Identify the hand, but if there's a joker (or more), use it to make the hand
# stronger
wildcard_hand <- function(hand) {
hand_table <- table(hand)
if (any(hand == "J")) {
# How many jokers?
n_jokers <- hand_table[names(hand_table) == "J"]
remaining_cards <- hand_table[names(hand_table) != "J"]
if (any(remaining_cards + n_jokers == 5) | n_jokers == 5) { # Five of a kind
return(7)
} else if (any(remaining_cards + n_jokers == 4)) { # Four of a kind
return(6)
} else if (n_jokers == 1 & sum(remaining_cards == 2) == 2) { # full house
# A full house is only an option when there's only one joker. When
# there's two jokers (or more) and a full house can be achieved, five or
# four of a kind can also be achieved, which are stronger.
return(5)
} else if (any(remaining_cards + n_jokers == 3)) { # three of a kind
return(4)
} else if (n_jokers == 1 & any(remaining_cards == 2)) { # two pair
# Two pairs can only be achieved when there's only one joker. When
# there's two jokers (or more), three of a kind (or a higher hand) can be
# achieved, which are stronger.
return(3)
} else { # one pair
# When there's a joker, at least one pair is possible
return(2)
}
} else {
return(identify_hand(hand))
}
}
## PART 1 ----------------------------------------------------------------------
start <- Sys.time()
card_hierarchy <- c("A", "K", "Q", "J", "T", 9:2)
part1 <- hands_split
# First step: Identify type.
part1$hand_type <-
apply(part1[paste0("hand", 1:5)], 1, identify_hand)
# Establish card hierarchy
part1[paste0("hand", 1:5)] <-
as.data.frame(
lapply(part1[paste0("hand", 1:5)], function(x) {
as.numeric(factor(x, levels = card_hierarchy, ordered = TRUE))
})
)
# Now sort by hand type (descending), card 1, 2, 3 ...
part1_ordered <-
with(
part1,
part1[order(-hand_type, hand1, hand2, hand3, hand4, hand5), ]
)
# multiply bid with rank
sum(part1_ordered$bid * nrow(part1_ordered):1)
# 248453531
Sys.time() - start
## PART 2 ----------------------------------------------------------------------
start <- Sys.time()
card_hierarchy <- c("A", "K", "Q", "T", 9:2, "J")
part2 <- hands_split
# Identify type.
part2$hand_type <-
apply(part2[paste0("hand", 1:5)], 1, wildcard_hand)
# Establish card hierarchy
part2[paste0("hand", 1:5)] <-
as.data.frame(
lapply(part2[paste0("hand", 1:5)], function(x) {
as.numeric(factor(x, levels = card_hierarchy, ordered = TRUE))
})
)
# sort
part2_ordered <-
with(
part2,
part2[order(-hand_type, hand1, hand2, hand3, hand4, hand5), ]
)
# multiply bid with rank
sum(part2_ordered$bid * nrow(part2_ordered):1)
# 248781813
Sys.time() - start