Day 8
R
Author

Liam D. Bailey

Published

December 13, 2021

## The Data Day 8 is really more a puzzle than a coding challenge. We’re given the inputs and outputs from a broken 7-segment display (like on a digital clock). We can imagine each segment of the clock as having a corresponding letter, from a (top) to g (bottom). We can create a dictionary that will translate a string of letters into a corresponding number following the image above.

``````#Actual letter number combos
correct_codes <- 0:9
names(correct_codes) <- c("abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg")``````

The only problem is that the data we are given doesn’t have the correct letters! Each row of the input data we are given includes all 10 possible numbers (0-9) but the letters used are wrong. We have to work out a number of rules to decode this information! See the full explanation for today’s challenge here.

``````#Load data
col_names = c("inputs", "outputs"), show_col_types = FALSE)

``````# A tibble: 6 × 2
inputs                                                     outputs
<chr>                                                      <chr>
1 fdceba bafdgc abeg afbdgec gbeacd abced bgc fcdge bg bedgc bafdec cgefd gcebd…
2 gbfac fegbda fcedagb bea ea abcdef dgbfe gfabe dgea gbdfec gdea bgefdc bea ef…
3 eg dagef gbcfeda ageb cegbfd gfe dbefa facdg abfged cedbaf befda daefb egf gc…
4 edgacfb gcfd dgb degfab bcega bdagc cgafbd fbacd gd fceabd fbdac gd gdbcaf dgb
5 eaf bedgaf dbafc bfceag fedcbg eafdcgb debfa ae adge gdebf abcdfeg febdg ae d…
6 afbdc aefg ea edbacfg dbefg eab gcbfde abecgd bgefad bfdae gfea bfdea gbdef f…``````

Convert our data into nested lists so that it’s easier to work with.

``````day8_data <- day8_data %>%
mutate(inputs = stringr::str_split(inputs, pattern = " "),
outputs = stringr::str_split(outputs, pattern = " "))``````

## The Challenges

### Challenge 1 & 2

In combination, the two challenges from Day 8 aim to decode the outputs so we’ll combine them together. The first rules we can use are simple. There are 4 numbers that can be easily identified just by the number of characters in the input.

• 2 characters = 1
• 3 characters = 7
• 4 characters = 4
• 7 characters = 8

So if we see an input ‘ab’ this must correspond to the number 1 or ‘cf’ when correctly translated to the 7-segment display. But we don’t know if ‘a’ is ‘c’ or ‘f’. We need some more rules to work this out. We’ll apply all these rules below:

``````numbers <- NULL
for (i in 1:nrow(day8_data)) {

#Split input into list with individual letters
split_input  <- stringr::str_extract_all(day8_data\$inputs[[i]], pattern = "[a-z]{1}")
split_output <- stringr::str_extract_all(day8_data\$outputs[[i]], pattern = "[a-z]{1}")

#If there are two values, it must correspond to c and f
#Remove from the list afterwards
number1 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 2))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 2))] <- NULL

#If there are three values, it must correspond to a, c and f
#Remove from the list afterwards
number7 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 3))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 3))] <- NULL

#If there are four values, it must correspond to b, c, d and f
#Remove from the list afterwards
number4 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 4))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 4))] <- NULL

#If there are seven values, it must correspond to a-g
#Remove from the list afterwards
number8 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 7))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 7))] <- NULL

#Letter that's not shared between 1 and 7 must be a
a <- setdiff(number7, number1)

#Value of 6 characters that contains the letters in 4 must be 9.
#Remove from the list afterwards
number9 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 6 & all(number4 %in% letters)))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 6 & all(number4 %in% letters)))] <- NULL

#The missing letter in 9 is e
e <- setdiff(number8, number9)

#Remaining 6 letter character that includes the same letters as number1 must be 0.
#Remove from the list afterwards
number0 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 6 & all(number1 %in% letters)))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 6 & all(number1 %in% letters)))] <- NULL

#The missing value here is d
d <- setdiff(number8, number0)

#Last remaining length 6 is 6
number6 <- split_input[unlist(lapply(split_input, \(letters) length(letters) == 6))][]
split_input[unlist(lapply(split_input, \(letters) length(letters) == 6))] <- NULL

#Missing value is c
c <- setdiff(number8, number6)

#The letter in 7 that wasn't just extracted is f
f <- setdiff(number1, c)

#Letter in 4 that hasn't yet been deciphered in b
b <- setdiff(number4, c(c, d, f))

#Remaining letter in 0 after removing all known ones is g
g <- setdiff(number0, c(a, b, c, e, f))

#Dictionary
dict <- letters[1:7]
names(dict) <- c(a, b, c, d, e, f, g)

#Now we can decode our output
output <- correct_codes[unlist(lapply(split_output, \(letters) paste(dict[letters][order(dict[letters])], collapse = "")))]

#Paste all the decoded numbers together
numbers <- append(numbers, as.integer(paste(output, collapse = "")))

}``````
``numbers``
``````   6233 4675 5572 5197 8513 4356  307 8507 4088 3756 9295 2569 5165 3061 2862
 1316 7879 2323 2593 5720 6695 7066 9013 9050 4501 2886 1326  734 9840 8003
 1752 4944 2038 9216 9250 4237 2145 7182 1101 5063 2136 8496 8523 3326 4598
  227 6537 3390 5065 9306 8460 6335 2664 6446 5550 4303 6955 3520 9376 2586
 6520 2121 6685 3109 2838 8257 3082 7739 7132 2770 5996  521 3470  940 2060
 6396  400 6050 2314 8464  262 9628 4719  706 8307 5355 4289 2422 2634  714
 2016 2778 6695  474 6970 3689 3305   12 5074 8060 5359 9331 8993 3307 9329
  458 9872 7089 6058 5030 3634 5702 3756 4506 2957 8995 5657 8375  415 2412
 3021 7241 8368 9298 6666 8567 2648 9621 3215 5533 4972 2236 8329 2582 2929
 2089 3436 3594 1383 5555 5461 2268 6377 1440 9494 8314 9483 3267 3037 5547
 9184 4900 6696 7304 1294 1349 8642 6126 7367 5525 3861 3393 2958 5312 2028
 5058 8513 4258 1780 3937 5568 6236 5159  518 8059 1014 1080 8538   40 6722
 3193 2519 5877 2460 3348 7329 8622 4380 3629  771 3734 6563 1900 4502 1472
 6293 7392 8285 9928 7535``````

The answer of our final challenge is the sum of all these values.

``sum(numbers)``
`` 982158``

See previous solutions here: