Sarah Harris's Avatar

Sarah Harris

@implausible17.bsky.social

Lives in Swindon UK, maths/stats nerd, paints murals, reads comics, grumbles fairly politely at ice hockey referees, watches a lot of sci fi and horror movies, has a big fat crush on Lee Pace.

359 Followers  |  298 Following  |  436 Posts  |  Joined: 07.08.2023  |  2.2142

Latest posts by implausible17.bsky.social on Bluesky


as an old head who started on SAS, then spent 10 odd years in SPSS before moving over to R, I thank you. R is superior to SPSS and SAS in a multitude of ways, and I'd never want to go back, but there are a few things that the old ways did so well. Will check this out when I have a minute.

19.02.2026 12:11 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

just ran to ebay to see if I could find a copy, have put the cheapest one on my watchlist to see if I still need it tomorrow morning :)

18.02.2026 11:35 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

absolutely wonderful! I would have snapped that up in a nanosecond

18.02.2026 11:30 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

why does anyone need half a dozen different calendars? these productivity bros are weird

18.02.2026 10:04 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Video thumbnail

The kids actually made animals that don't exist. The AI just put a bunch of stuff that already exists together into a polished slop blender. You can't get a better illustration of why AI can't create anything new while human creativity is bottomless.

10.02.2026 06:48 β€” πŸ‘ 1499    πŸ” 485    πŸ’¬ 22    πŸ“Œ 23

I ran into a lift just as the doors were closing, pressed the button for my floor, and then as the lift began to move I looked up and the only other person in there with me was Gerard Way from MCR (and he looked terrified that this strange woman had launched herself in there with him!)

05.02.2026 16:17 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

thank you!

19.01.2026 13:38 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Thank you!

19.01.2026 11:28 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Video thumbnail

Photos to follow, but here is a quick vid of the mural I finished up this weekend for a local youth club, in Swindon UK.

I had tremendous fun both designing this one & painting it. Drawing cute dragons is good for the soul :)

The youth club opens in a couple of weeks, I hope the kiddos like it!

19.01.2026 10:30 β€” πŸ‘ 5    πŸ” 1    πŸ’¬ 2    πŸ“Œ 0

I have zero intention of ever getting married, but if I did, this is exactly the kind of nerd ass thing I would do :) love it

30.12.2025 10:20 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Post image

A friend of mine (face obscured to protect the innocent) posted this this morning.

I thought she was at a special, festive Bring Me The Horizon gig. I was so jealous!

Until I realised that, no, she's in Bournemouth :)

24.12.2025 19:16 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
#Day 6 - Trash Compactor - Part 1

#load the puzzle input, transpose it, and setup the sums and products across all numeric columns
D6P1 <- read.table("D6input.txt", sep = "" , header = F , na.strings ="", stringsAsFactors= F) |> t()
D6P1 <- data.frame(D6P1) |> rename(pm = ncol(D6P1)) |> mutate(across(starts_with("X"), as.numeric)) 
numeric_cols <- D6P1[sapply(D6P1, is.numeric)]
D6P1$numericcolssum <- rowSums(numeric_cols)
D6P1$numericcolsprod <- apply(numeric_cols, 1, prod)
D6P1 <- D6P1 |> mutate(correctresult = if_else(pm == "+",numericcolssum, numericcolsprod))

print(paste("answer is",sum(D6P1$correctresult)))

#Day 6 - Trash Compactor - Part 1 #load the puzzle input, transpose it, and setup the sums and products across all numeric columns D6P1 <- read.table("D6input.txt", sep = "" , header = F , na.strings ="", stringsAsFactors= F) |> t() D6P1 <- data.frame(D6P1) |> rename(pm = ncol(D6P1)) |> mutate(across(starts_with("X"), as.numeric)) numeric_cols <- D6P1[sapply(D6P1, is.numeric)] D6P1$numericcolssum <- rowSums(numeric_cols) D6P1$numericcolsprod <- apply(numeric_cols, 1, prod) D6P1 <- D6P1 |> mutate(correctresult = if_else(pm == "+",numericcolssum, numericcolsprod)) print(paste("answer is",sum(D6P1$correctresult)))

#Part 2 - need to re-read in the data - the spaces matter now!

D6P2 <- data.frame(input = readLines("D6input.txt"), stringsAsFactors = FALSE)  
char_matrix <- str_split_fixed(D6P2$input, "", n = nchar(D6P2$input[1])) |> t() 

D6P2 <- as.data.frame(char_matrix) |> rename(pm = ncol(char_matrix)) |> mutate(across(starts_with("V"), as.numeric)) 
numeric_cols <- D6P2[sapply(D6P2, is.numeric)]
D6P2$numericcolssum <- rowSums(numeric_cols, na.rm = T)

D6P2 <- D6P2 |> filter(numericcolssum > 0) |>
  mutate(across(starts_with("V"), as.character)) |> 
  mutate(across(starts_with("V"), ~ replace_na(.,""))) |>
  mutate(newnum = as.numeric(do.call(paste0, across(starts_with("V"))))) |>  #paste the chars back together in the right order 
  mutate(indexno = ifelse(pm != " ", 1, NA), indexno = cumsum(replace_na(indexno, 0))) |> #give each set of numbers a URN
  mutate(pm = na_if(pm, " ")) |> fill(pm, .direction = "down")  #fill in the plus/mult symbols in the blank bits

additions <- D6P2 |> filter(pm == "+") |> group_by(indexno) |> summarise(result = sum(newnum)) |> ungroup()
mults <- D6P2 |> filter(pm == "*") |> group_by(indexno) |> summarise(result = prod(newnum)) |> ungroup()

print(paste("answer is",sum(additions$result)+sum(mults$result)))

#Part 2 - need to re-read in the data - the spaces matter now! D6P2 <- data.frame(input = readLines("D6input.txt"), stringsAsFactors = FALSE) char_matrix <- str_split_fixed(D6P2$input, "", n = nchar(D6P2$input[1])) |> t() D6P2 <- as.data.frame(char_matrix) |> rename(pm = ncol(char_matrix)) |> mutate(across(starts_with("V"), as.numeric)) numeric_cols <- D6P2[sapply(D6P2, is.numeric)] D6P2$numericcolssum <- rowSums(numeric_cols, na.rm = T) D6P2 <- D6P2 |> filter(numericcolssum > 0) |> mutate(across(starts_with("V"), as.character)) |> mutate(across(starts_with("V"), ~ replace_na(.,""))) |> mutate(newnum = as.numeric(do.call(paste0, across(starts_with("V"))))) |> #paste the chars back together in the right order mutate(indexno = ifelse(pm != " ", 1, NA), indexno = cumsum(replace_na(indexno, 0))) |> #give each set of numbers a URN mutate(pm = na_if(pm, " ")) |> fill(pm, .direction = "down") #fill in the plus/mult symbols in the blank bits additions <- D6P2 |> filter(pm == "+") |> group_by(indexno) |> summarise(result = sum(newnum)) |> ungroup() mults <- D6P2 |> filter(pm == "*") |> group_by(indexno) |> summarise(result = prod(newnum)) |> ungroup() print(paste("answer is",sum(additions$result)+sum(mults$result)))

Well - I only got half way this year in #AdventOfCode :( It has been an insanely busy December and I just didn't have the time! I always say I will come back in January and finish it off, but I never do. Maybe when I retire :)

Here's #AoCDay6 using #RStats

Happy Christmas R-heads!

24.12.2025 18:44 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
#function to tidy up the ranges as they sometimes overlap:

tidy_ranges <- function(df) {
  result <- list()
  current <- df[1, ]
  for (i in 2:nrow(df)) {
    next_row <- df[i, ]
    if (next_row$fromnum <= current$tonum) {current$tonum <- max(current$tonum, next_row$tonum)}
    else {
      result <- append(result, list(current))
      current <- next_row }}
  result <- append(result, list(current))
  bind_rows(result) }

#function to tidy up the ranges as they sometimes overlap: tidy_ranges <- function(df) { result <- list() current <- df[1, ] for (i in 2:nrow(df)) { next_row <- df[i, ] if (next_row$fromnum <= current$tonum) {current$tonum <- max(current$tonum, next_row$tonum)} else { result <- append(result, list(current)) current <- next_row }} result <- append(result, list(current)) bind_rows(result) }

ah - and here is the tidy_ranges function:

23.12.2025 13:28 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
# Day 5 - Cafeteria - Part 1

inputD5P1 <- data.frame(input = readLines("D5input.txt"), stringsAsFactors = FALSE)  #load data and split into 2 parts
blankrow <- which(inputD5P1$input == "")[1]
top <- inputD5P1 |> filter(row_number() < blankrow)
bottom <- inputD5P1 |> filter(row_number() > blankrow) |> 
  rename(candidate = 1) |> mutate(candidate = as.numeric(candidate)) |> arrange(candidate)

#split the top bit into from and to and tidy up the overlapping ranges:
top <- top |> separate(input, into = c("fromnum", "tonum"), sep = "-") |>
  mutate(fromnum = as.numeric(fromnum), tonum = as.numeric(tonum)) |> arrange(fromnum)
tidied_top <- tidy_ranges(top) |> arrange(fromnum)

#get rid of deffo spoiled items 
bottom <- bottom |> filter(candidate >= min(tidied_top$fromnum) & candidate <= max(tidied_top$tonum))

#now check through the ranges for each remaining candidate - find the first "from" that it is >= , and then mark as a match 
# if <= the to on that row - then when we have passed the "to" on a row, get rid

freshcounter <- 0
for (i in 1:nrow(bottom)) {
  candidate <- bottom[i,1]   
  tidied_top <- filter(tidied_top, tonum >= candidate)
  matchrow <- which(tidied_top$fromnum <= candidate)[1]
  if (!is.na(matchrow) && candidate <= tidied_top[matchrow,2]) {freshcounter <- freshcounter + 1}}

print(paste("answer is",freshcounter))

# Day 5 - Cafeteria - Part 1 inputD5P1 <- data.frame(input = readLines("D5input.txt"), stringsAsFactors = FALSE) #load data and split into 2 parts blankrow <- which(inputD5P1$input == "")[1] top <- inputD5P1 |> filter(row_number() < blankrow) bottom <- inputD5P1 |> filter(row_number() > blankrow) |> rename(candidate = 1) |> mutate(candidate = as.numeric(candidate)) |> arrange(candidate) #split the top bit into from and to and tidy up the overlapping ranges: top <- top |> separate(input, into = c("fromnum", "tonum"), sep = "-") |> mutate(fromnum = as.numeric(fromnum), tonum = as.numeric(tonum)) |> arrange(fromnum) tidied_top <- tidy_ranges(top) |> arrange(fromnum) #get rid of deffo spoiled items bottom <- bottom |> filter(candidate >= min(tidied_top$fromnum) & candidate <= max(tidied_top$tonum)) #now check through the ranges for each remaining candidate - find the first "from" that it is >= , and then mark as a match # if <= the to on that row - then when we have passed the "to" on a row, get rid freshcounter <- 0 for (i in 1:nrow(bottom)) { candidate <- bottom[i,1] tidied_top <- filter(tidied_top, tonum >= candidate) matchrow <- which(tidied_top$fromnum <= candidate)[1] if (!is.na(matchrow) && candidate <= tidied_top[matchrow,2]) {freshcounter <- freshcounter + 1}} print(paste("answer is",freshcounter))

# Part 2 - glad I tidied up my ranges in part 1, makes this part easy peasy! :)

#re-create tidied_top and count how many in each range

tidied_top <- tidy_ranges(top) |> mutate(howmany = tonum - fromnum + 1)
print(paste("answer is",sum(tidied_top$howmany)))

# Part 2 - glad I tidied up my ranges in part 1, makes this part easy peasy! :) #re-create tidied_top and count how many in each range tidied_top <- tidy_ranges(top) |> mutate(howmany = tonum - fromnum + 1) print(paste("answer is",sum(tidied_top$howmany)))

Oops - I forgot to post #AdventOfCode day 5 #AoCDay5 #RStats

I was a bit smug about this one because I solved it fairly quickly - and part 2 (which seemed to trip a lot of other people up) was an absolute doddle, because I'd already done most of the work in part 1 - pure luck really

23.12.2025 13:13 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Have you considered that perhaps the Rapture is upon us?

21.12.2025 13:37 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

20 months? Well done you for keeping at it

20.12.2025 15:48 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

... I am a granny now! Grandson Atlas born in Feb.

20.12.2025 13:43 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

I tend to forget that Bluesky exists for most of the year, but then I come back in December for Advent of Code as all my R people left Twitter. Not everyone arrived here though, so it is quieter than twitter AoC used to be.

All good my end ta, been painting and travelling and working. Oh and ...

20.12.2025 13:43 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Thanks for the repost Sam, hope you and the family are well! Have a good one

20.12.2025 13:29 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Post image

This year's #ArtVsArtist round up.

These are some of the street art pieces (plus one canvas) I painted in 2025 just for fun. For my commissioned work (a little less technicolor! :) ) please see @murals_bysarah on insta.

Happy christmas all, and all the best for 2026

20.12.2025 11:04 β€” πŸ‘ 4    πŸ” 1    πŸ’¬ 0    πŸ“Œ 0
# Day 4 - Printing Department - Part 1

D4mat <- do.call(rbind, strsplit(readLines("D4input.txt"), ""))  #load the data into a matrix 
matdim <- nrow(D4mat)

D4mat <- pad_matrix(D4mat)


# then just loop through every cell from [2,2] to [matdim+1,matdim+1] and count up the @s in all 8 directions
rollcount <- 0
for (i in 2:(matdim+1)) {
  for (j in 2:(matdim+1)) {
    if(D4mat[i,j] == "@") {
      neighbours <- sum(D4mat[i-1,j-1] == "@",D4mat[i-1,j] == "@", D4mat[i-1,j+1] == "@",
                        D4mat[i,j-1] == "@", F, D4mat[i,j+1] == "@",
                        D4mat[i+1,j-1] == "@",D4mat[i+1,j] == "@", D4mat[i+1,j+1] == "@")
      if(neighbours < 4) {rollcount <- rollcount + 1} }}}

print(paste("answer is",rollcount))

# Day 4 - Printing Department - Part 1 D4mat <- do.call(rbind, strsplit(readLines("D4input.txt"), "")) #load the data into a matrix matdim <- nrow(D4mat) D4mat <- pad_matrix(D4mat) # then just loop through every cell from [2,2] to [matdim+1,matdim+1] and count up the @s in all 8 directions rollcount <- 0 for (i in 2:(matdim+1)) { for (j in 2:(matdim+1)) { if(D4mat[i,j] == "@") { neighbours <- sum(D4mat[i-1,j-1] == "@",D4mat[i-1,j] == "@", D4mat[i-1,j+1] == "@", D4mat[i,j-1] == "@", F, D4mat[i,j+1] == "@", D4mat[i+1,j-1] == "@",D4mat[i+1,j] == "@", D4mat[i+1,j+1] == "@") if(neighbours < 4) {rollcount <- rollcount + 1} }}} print(paste("answer is",rollcount))

#function to pad the matrix out with full stops
pad_matrix <- function(mat, pad = ".", n = 1) {
  nr <- nrow(mat)
  nc <- ncol(mat)
  top_bottom <- matrix(pad, nrow = n, ncol = nc + 2 * n)
  side <- matrix(pad, nrow = nr, ncol = n)
  rbind(top_bottom, cbind(side, mat, side), top_bottom)
}

#function to pad the matrix out with full stops pad_matrix <- function(mat, pad = ".", n = 1) { nr <- nrow(mat) nc <- ncol(mat) top_bottom <- matrix(pad, nrow = n, ncol = nc + 2 * n) side <- matrix(pad, nrow = nr, ncol = n) rbind(top_bottom, cbind(side, mat, side), top_bottom) }

#Part 2 - use the same padded matrix that was set up in part 1
#instead of just counting the reachable rolls, this time count them and also replace with a dot to 'remove' them.  
# keep passing through until no more rolls get removed.

rollcount <- 0

while (TRUE) { 
  removed <- 0
  for (i in 2:(matdim+1)) {
    for (j in 2:(matdim+1)) {
      if(D4mat[i,j] == "@") {
        neighbours <- sum(D4mat[i-1,j-1] == "@",D4mat[i-1,j] == "@", D4mat[i-1,j+1] == "@",
                          D4mat[i,j-1] == "@", F, D4mat[i,j+1] == "@",
                          D4mat[i+1,j-1] == "@",D4mat[i+1,j] == "@", D4mat[i+1,j+1] == "@")
        if(neighbours < 4) {
          rollcount <- rollcount + 1
          removed <- removed + 1
          D4mat[i,j] <- '.'}}}}
  if (removed == 0) break }

print(paste("answer is",rollcount))

#Part 2 - use the same padded matrix that was set up in part 1 #instead of just counting the reachable rolls, this time count them and also replace with a dot to 'remove' them. # keep passing through until no more rolls get removed. rollcount <- 0 while (TRUE) { removed <- 0 for (i in 2:(matdim+1)) { for (j in 2:(matdim+1)) { if(D4mat[i,j] == "@") { neighbours <- sum(D4mat[i-1,j-1] == "@",D4mat[i-1,j] == "@", D4mat[i-1,j+1] == "@", D4mat[i,j-1] == "@", F, D4mat[i,j+1] == "@", D4mat[i+1,j-1] == "@",D4mat[i+1,j] == "@", D4mat[i+1,j+1] == "@") if(neighbours < 4) { rollcount <- rollcount + 1 removed <- removed + 1 D4mat[i,j] <- '.'}}}} if (removed == 0) break } print(paste("answer is",rollcount))

I was on an #AdventOfCode roll last night - completing both #Day4 and day5 (but I'll post day 5 tomorrow)

For once I had an evening free of commitments to work or family - so I could attend to my commitment to the elves :)

First matrix puzzle this year

#AoCDay4 #RStats

18.12.2025 11:36 β€” πŸ‘ 6    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
#Day 3 - Lobby - Part 1

inputD3P1 <- data.frame(input = readLines("D3input.txt"), stringsAsFactors = FALSE)

inputD3P1 <- inputD3P1 |>   rowwise() |>
  mutate(shorter_input = str_sub(input, end = -2),
         firstdigit = max(strsplit(shorter_input, "")[[1]]),
         firstdigitpos = which(strsplit(shorter_input, "")[[1]] == firstdigit)[1],
         remainder = str_sub(input, start = (firstdigitpos + 1)),
         seconddigit = max(strsplit(remainder, "")[[1]]),
         joltage = as.numeric(firstdigit)*10+as.numeric(seconddigit)) |> ungroup() 

print(paste("answer is",sum(inputD3P1$joltage)))

#Day 3 - Lobby - Part 1 inputD3P1 <- data.frame(input = readLines("D3input.txt"), stringsAsFactors = FALSE) inputD3P1 <- inputD3P1 |> rowwise() |> mutate(shorter_input = str_sub(input, end = -2), firstdigit = max(strsplit(shorter_input, "")[[1]]), firstdigitpos = which(strsplit(shorter_input, "")[[1]] == firstdigit)[1], remainder = str_sub(input, start = (firstdigitpos + 1)), seconddigit = max(strsplit(remainder, "")[[1]]), joltage = as.numeric(firstdigit)*10+as.numeric(seconddigit)) |> ungroup() print(paste("answer is",sum(inputD3P1$joltage)))

#Part 2 - the same thing but twelve times instead of 2

inputD3P1 <- data.frame(input = readLines("D3input.txt"), stringsAsFactors = FALSE)

inputD3P1 <- inputD3P1 |>   rowwise() |>
  mutate(shorter_input = str_sub(input, end = -12),
         firstdigit = max(strsplit(shorter_input, "")[[1]]),
         firstdigitpos = which(strsplit(shorter_input, "")[[1]] == firstdigit)[1],
         remainder = str_sub(input, start = (firstdigitpos + 1), end = -11),
         seconddigit = max(strsplit(remainder, "")[[1]]),
         seconddigitpos = which(strsplit(remainder, "")[[1]] == seconddigit)[1],
         remainder2 = str_sub(input, start = (firstdigitpos+seconddigitpos + 1), end = - 10),
         thirddigit = max(strsplit(remainder2, "")[[1]]),
         thirddigitpos = which(strsplit(remainder2, "")[[1]] == thirddigit)[1],
         remainder3 = str_sub(input, start = (firstdigitpos+seconddigitpos +thirddigitpos + 1), end = -9),

      #and so on ......
         joltage = as.numeric(firstdigit)*100000000000+as.numeric(seconddigit)*10000000000+
as.numeric(thirddigit)*1000000000+as.numeric(fourthdigit)*100000000+
as.numeric(fifthdigit)*10000000+as.numeric(sixthdigit)*1000000+
 as.numeric(seventhdigit)*100000+as.numeric(eigthdigit)*10000+
           as.numeric(ninthdigit)*1000+as.numeric(tenthdigit)*100+
           as.numeric(eleventhdigit)*10+as.numeric(twelthdigit)) |> ungroup() 

print(paste("answer is",sum(inputD3P1$joltage)))

#Part 2 - the same thing but twelve times instead of 2 inputD3P1 <- data.frame(input = readLines("D3input.txt"), stringsAsFactors = FALSE) inputD3P1 <- inputD3P1 |> rowwise() |> mutate(shorter_input = str_sub(input, end = -12), firstdigit = max(strsplit(shorter_input, "")[[1]]), firstdigitpos = which(strsplit(shorter_input, "")[[1]] == firstdigit)[1], remainder = str_sub(input, start = (firstdigitpos + 1), end = -11), seconddigit = max(strsplit(remainder, "")[[1]]), seconddigitpos = which(strsplit(remainder, "")[[1]] == seconddigit)[1], remainder2 = str_sub(input, start = (firstdigitpos+seconddigitpos + 1), end = - 10), thirddigit = max(strsplit(remainder2, "")[[1]]), thirddigitpos = which(strsplit(remainder2, "")[[1]] == thirddigit)[1], remainder3 = str_sub(input, start = (firstdigitpos+seconddigitpos +thirddigitpos + 1), end = -9), #and so on ...... joltage = as.numeric(firstdigit)*100000000000+as.numeric(seconddigit)*10000000000+ as.numeric(thirddigit)*1000000000+as.numeric(fourthdigit)*100000000+ as.numeric(fifthdigit)*10000000+as.numeric(sixthdigit)*1000000+ as.numeric(seventhdigit)*100000+as.numeric(eigthdigit)*10000+ as.numeric(ninthdigit)*1000+as.numeric(tenthdigit)*100+ as.numeric(eleventhdigit)*10+as.numeric(twelthdigit)) |> ungroup() print(paste("answer is",sum(inputD3P1$joltage)))

I'm so behind with these!! but it has been a busy month, sometimes the elves have to take a back seat, sorry elves

#AdventOfCode day 3 - I basically used the exact same approach for parts 1 and 2, so here they both are

#AoCDay3 #RStats

16.12.2025 17:54 β€” πŸ‘ 5    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
#Part 2 uses same input data frame already loaded in my part 1 solution

allpotentials <- data.frame(potentials = character())

for (i in 1:nrow(inputD2P1)) {
    j <- as.numeric(inputD2P1[i,1])
    k <- as.numeric(inputD2P1[i,2])
  for (n in j:k) { 
    p <- as.character(n)
    if (grepl("^(.+)\\1+$", p)) {allpotentials <- rbind(allpotentials,p) } } }

allpotentials <- allpotentials |> rename(potentials = 1) |> mutate(repeaters = as.numeric(potentials))

print(paste("answer is",sum(allpotentials$repeaters)))

#Part 2 uses same input data frame already loaded in my part 1 solution allpotentials <- data.frame(potentials = character()) for (i in 1:nrow(inputD2P1)) { j <- as.numeric(inputD2P1[i,1]) k <- as.numeric(inputD2P1[i,2]) for (n in j:k) { p <- as.character(n) if (grepl("^(.+)\\1+$", p)) {allpotentials <- rbind(allpotentials,p) } } } allpotentials <- allpotentials |> rename(potentials = 1) |> mutate(repeaters = as.numeric(potentials)) print(paste("answer is",sum(allpotentials$repeaters)))

Don't you just love it when a #AdventOfCode part 2 is easier than the part 1?

Luckily I had this niggling feeling that I'd seen someone use a regex to identify repeating patterns in an old AoC puzzle a couple of years back, and clever past Sarah had made a note of it, go me!

#AoCDay2Part2 #RStats

15.12.2025 13:03 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Post image

S940 - Square root

14.12.2025 18:29 β€” πŸ‘ 1    πŸ” 2    πŸ’¬ 1    πŸ“Œ 0

You know I love this one :)

14.12.2025 19:03 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Thank you! Was a fun one to paint :)

14.12.2025 18:31 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
A street art style mural of a cute Krampus against a festive, winter background.  Photo also features the artist.

A street art style mural of a cute Krampus against a festive, winter background. Photo also features the artist.

Post image Post image Post image

Merry Krampus Kristmas everyone!

Painted today in Stroud, Gloucestershire.

14.12.2025 18:30 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

And it is so blooming good!

I had the privilege of being one of the first people to see this anthology as I helped with some proof reading etc, and I was blown away.

Loads of pages for your money, all killer no filler, proceeds to a great cause. What more do you want?

10.12.2025 10:21 β€” πŸ‘ 5    πŸ” 3    πŸ’¬ 0    πŸ“Œ 1

Thanks :) it's on the Honeybourne Line cycle path, just by Waitrose

07.12.2025 07:57 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Post image Post image Post image Post image

Had a ton of fun today in Cheltenham, painting this homage to one of my favourite movies of all time.

The Wicker Man (1973)

06.12.2025 23:14 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 2    πŸ“Œ 0

@implausible17 is following 20 prominent accounts