Sign in

Randy Boyes

@randy.pub
470 followers 547 following 393 posts

Analytics at @presage.group | PhD Epidemiology | Wolfe Island Volunteer Firefighter | #julialang #python #rstats | publications at www.randy.pub | GitHub @rdboyes

PostsRepliesMedia
Randy Boyes @randy.pub · 23/09/2026
My family had newer computers that I used before this but the first computer that was MINE was one of these Commodore XTs that I salvaged from my Dad's shelf of spare parts and busted computers
021
Randy Boyes @randy.pub · 01/09/2026
nice
000
Randy Boyes @randy.pub · 30/07/2026
This joke goes nuts if you, like me, are the son of a evangelical pastor who became an epidemiologist
3294
Randy Boyes @randy.pub · 30/06/2026
Ooof
100
Randy Boyes @randy.pub · 15/06/2026
[grossed out] --dangerously-skip-permissions
[interested] auto mode
021
Randy Boyes @randy.pub · 11/06/2026
vince mcmahon meme format:
MDPI is predatory
Frontiers is predatory
Elsevier is predatory
Publishing as a model is predatory
0245
Randy Boyes @randy.pub · 24/05/2026
I wish claude would just admit it doesn't know instead of attempting to gaslight me
023
Randy Boyes @randy.pub · 17/05/2026
Tough to answer these questions on an agree scale but the result is in the ballpark I think
010
Randy Boyes @randy.pub · 09/05/2026
Bruce only likes to chew toys while holding them over the edge of the couch, and gets very upset when he drops them
010
Randy Boyes @randy.pub · 02/04/2026
The flexibility of `geom_polygon` lets you do basically whatever you want with your plots, e.g. (code: gist.github.com/rdboyes/7a7f...)
001
Randy Boyes @randy.pub · 10/03/2026
2 of our 3 taking a nap beside me in my office:
120
Randy Boyes @randy.pub · 28/01/2026
I guess? That is textbook gambling to me as well, but I can imagine someone who disagrees with me What about this, though? Who are the people who think gambling is not gambling?
110
Randy Boyes @randy.pub · 21/12/2025
Looks just like ours!
240
Randy Boyes @randy.pub · 05/12/2025
Only had time to finish part 1 of #adventofcode today - hoping to get back to p2 on the weekend though!
1110
Randy Boyes @randy.pub · 04/12/2025
Two #adventofcode solutions for the price of one today, since I was too busy working yesterday. TypeScript feeling ok, but how is array.sum() not a thing!?
function solve(line: string, bat_length: number) {
  const arr = line.split("").map(function (char: string) {
    return Number(char);
  });

  let end: number = arr.length - bat_length + 1;
  let start: number = 0;
  let digits: number[] = [];

  while (digits.length < bat_length) {
    const selected = Math.max(...arr.slice(start, end));
    digits.push(selected);
    end += 1;
    start += 1 + arr.slice(start, end).indexOf(selected);
  }

  return digits
    .reverse()
    .map(function (n, i) {
      return n * 10 ** i;
    })
    .reduce((a, b) => {
      return a + b;
    }, 0);
}

console.log(
  require("fs")
    .readFileSync("data/2025/3.txt", "utf-8")
    .split(/\r?\n/)
    .filter((line) => line.trim().length > 0)
    .map(function (line: string) {
      return [solve(line, 2), solve(line, 12)];
    })
    .reduce(function (a, b) {
      return [a[0] + b[0], a[1] + b[1]];
    }),
);var input_matrix = require("fs")
  .readFileSync("data/2025/4.txt", "utf-8")
  .split(/\r?\n/)
  .filter((line) => line.trim().length > 0)
  .map(function (line: string) {
    return line.split("").map(function (char) {
      if (char == "@") {
        return 1;
      } else {
        return 0;
      }
    });
  });

var count = 0;
var remove = [];
var exit = false;

while (exit == false) {
  for (const target of remove) {
    input_matrix[target[0]][target[1]] = 0;
  }
  var remove = [];

  for (var i = 1; i < input_matrix.length - 1; i++) {
    for (var j = 1; j < input_matrix.length - 1; j++) {
      if (
        input_matrix[i - 1]
          .slice(j - 1, j + 2)
          .concat(
            input_matrix[i].slice(j - 1, j + 2),
            input_matrix[i + 1].slice(j - 1, j + 2),
          )
          .reduce((a, b) => {
            return a + b;
          }, 0) <= 4
      ) {
        if (input_matrix[i][j] == 1) {
          count++;
          remove.push([i, j]);
        }
      }
    }
  }
  if (remove.length == 0) {
    exit = true;
  }
}

console.log(count);
020
Randy Boyes @randy.pub · 02/12/2025
TypeScript #adventofcode Day 2 complete! Rocky one, really missing some of the builtin functions from my "home languages", but we got there
const range = (start: number, stop: number): number[] =>
  Array.from({ length: 1 + stop - start }, (_, i) => start + i);

function chunkString(str: string, length: number) {
  return str.match(new RegExp(".{1," + length + "}", "g"));
}

const divisors = (num: number) =>
  [...Array(num)].map((x, i) => i).filter((x) => num % x === 0);

function solve(id_range: string): number {
  const arr_range = id_range.split("-");
  const possibles = range(Number(arr_range[0]), Number(arr_range[1]));

  const ans = possibles
    .map(function (element: number): number {
      let id_string = `${element}`;

      const checks: number[] = divisors(id_string.length).map((num) => {
        return new Set(chunkString(id_string, num)).size;
      });

      if (Math.min(...checks) == 1) {
        return element;
      } else {
        return 0;
      }
    })
    .reduce((a, b) => {
      return a + b;
    }, 0);

  return ans;
}

console.log(
  require("fs")
    .readFileSync("data/2025/2.txt", "utf-8")
    .split(",")
    .map(function (id_range: string) {
      return solve(id_range);
    })
    .reduce((a, b) => {
      return a + b;
    }, 0),
);
150
Randy Boyes @randy.pub · 01/12/2025
Doing #adventofcode in TypeScript this year since I need to learn it for work... missing #julialang but it's not too bad. Day 1:
Typescript solution to advent 2025 day 1. Code: class Dial {
  current: number = 50;
  zeros: number = 0;
  pass_zero: number = 0;

  turn(s: string): void {
    if (s[0] == "R") {
      this.current += Number(s.substring(1));
      if (this.current >= 100) {
        this.pass_zero += Math.trunc(this.current / 100);
        this.current = this.current % 100;
      }
    } else {
      if (this.current == 0) {
        this.pass_zero -= 1;
      }
      this.current -= Number(s.substring(1));
      if (this.current <= 0) {
        this.pass_zero += -Math.trunc(this.current / 100) + 1;
        this.current = 100 + (this.current % 100);
      }
    }
    if (this.current == 0 || this.current == 100) {
      this.zeros += 1;
      this.current = 0;
    }
  }
}

var p1 = new Dial();

require("fs")
  .readFileSync("data/2025/1.txt", "utf-8")
  .split(/\r?\n/)
  .forEach(function (line: string) {
    p1.turn(line);
  });

console.log(p1.zeros);
console.log(p1.pass_zero);
0100
Randy Boyes @randy.pub · 09/10/2025
I'd go with a regex with a lookahead for the character you want, e.g.
020
Randy Boyes @randy.pub · 14/09/2025
It should only be a month or so until he’s good with one wake-up during the night, and then another few weeks until he sleeps through the night. The “every 2 hours” phase is 2-3 weeks long, in my experience
020
Randy Boyes @randy.pub · 21/08/2025
No wonder they were having a blast
040
Randy Boyes @randy.pub · 15/08/2025
050
Randy Boyes @randy.pub · 13/08/2025
a man with good taste in llms haha :)
020
Randy Boyes @randy.pub · 13/08/2025
Might be worth trying! I can confirm at least that it CAN work with ellmer, given the right hardware
100
Randy Boyes @randy.pub · 26/07/2025
I’ve been making a concerted effort to delete apps and touch grass recently and it’s good What happens on the hellscape formerly known as twitter actually doesn’t matter
Gardening with chickens
010
Randy Boyes @randy.pub · 21/07/2025
130
Randy Boyes @randy.pub · 27/06/2025
Or maybe a clearer visual:
140
Randy Boyes @randy.pub · 27/06/2025
The challenge in the post: you can detect the seed used if you know or can guess the mechanism (purple spike at seed 123 should have no reason to exist in non-manipulated data):
150
Randy Boyes @randy.pub · 13/06/2025
Unless I'm misunderstanding what you want, it does already - you just have to use the ...
220
Randy Boyes @randy.pub · 09/06/2025
It's not an inherent property of the task, no - e.g. here's an example in julia that does the same thing but has the expected variance in the last digits
020
Randy Boyes @randy.pub · 05/06/2025
Trying out some old Vizz Buzz challenges in TidierPlots - is there any way in #makie to easily add small images? The original version had flags as labels...
Code to recreate a data visualization showing the medal progress at the 2018 olympics, reproduced below: 

using TidierPlots, TidierFiles, TidierData, DataFrames, Dates

wo = read_csv("data/bump (1).csv")

wo_plot = @chain wo begin
    @mutate total = gold + silver + bronze
    transform(:date => ByRow(x -> 1 + (x-Date("2018-02-10")).value) => :day)
    @group_by date
    @mutate rank = 1:n() 
    @ungroup
end

top5 = @chain wo_plot begin
    @filter country in ["NED", "GER", "CAN", "USA", "NOR"]
end

final = @chain top5 begin
    @filter day == 16
end

ggplot(wo_plot) +
    geom_point(@aes(x = day, y = rank, group = country), alpha = .4, size = 15, color = :lightgrey) + 
    geom_line(@aes(x = day, y = rank, group = country), alpha = .4, linewidth = 6, color = :lightgrey) + 
    geom_point(data = top5, @aes(x = day, y = rank, color = country), size = 15, alpha = 0.5) + 
    geom_line(data = top5, @aes(x = day, y = rank, color = country), linewidth = 6, alpha = 0.5) + 
    geom_point(data = top5, @aes(x = day, y = rank), color = :white, size = 5) +
    scale_y_reverse() + 
    lims(y = c(0.5, 10.5), x = c(0, 18)) +
    labs(title = "Pyongchang 2018 Olympic Winter Games",
    subtitle = "Countries ranked by overall medals after each competition day",
    x = "Competition Days with Medals", y = "Rank") +
    scale_color_manual(values = c(:red, :black, :orange, :green, :blue)) +
    guides(color = :none) +
    theme_minimal() + 
    theme(
        xgridstyle = :solid, 
        xgridcolor = :lightgray, 
        xgridvisible = true,
        xticks = 1:16,
        yticks = 1:10,
        leftspinevisible = false,
        bottomspinevisible = false,
        titlealign = :left,
        titlesize = 24,
        subtitlesize = 16
    )
291
Randy Boyes @randy.pub · 02/06/2025
020
Randy Boyes @randy.pub · 10/05/2025
140
Randy Boyes @randy.pub · 02/05/2025
They're "hack-proof and secure", obviously
120
Randy Boyes @randy.pub · 25/04/2025
I'm bookmarking this for reference since R's NSE stuff always throws me off! One of the nice things about working in @tidierjl.bsky.social is that you can drop down into #julialang at any time, which has a nice division between "normal evaluation" and "shenanigans":
Julia source code example: 

# One-liner if you're willing to write column names as symbols

count_ones(data, c...) = combine(data, [c...] .=> x -> sum(x .== 1) .=> [c...])

count_ones(mtcars, :VS, :Carb)

# 1×2 DataFrame
# Row │ VS     Carb
#     │ Int64  Int64
#─────┼──────────────
#   1 │    14      7

# macro version to allow unquoted names

macro count_ones(data, c...)
    return Expr(:call, :count_ones, data, (Meta.quot.(c))...)
end

@count_ones(mtcars, VS, Carb)

# 1×2 DataFrame
# Row │ VS     Carb
#     │ Int64  Int64
#─────┼──────────────
#   1 │    14      7
050
Randy Boyes @randy.pub · 23/04/2025
You can cut one more pixel if you're willing to assume you can interpolate to get blank points
110
Randy Boyes @randy.pub · 23/04/2025
Cut the intermediate braille labels for even more information density! (people should of course be able to infer that the categories are in alphabetical order between a and g ;) )
130
Randy Boyes @randy.pub · 16/04/2025
I believe
020
Randy Boyes @randy.pub · 10/04/2025
The one piece of good news in the portfolio today
140
Randy Boyes @randy.pub · 05/04/2025
041
Randy Boyes @randy.pub · 14/03/2025
"I could only process 60k rows before my hard drive overheated"
0121
Randy Boyes @randy.pub · 12/03/2025
neo: "What are you trying to say? I can't use rm(list = ls())"?
morpheus: no neo, I'm saying that when you're ready, you won't have to
16616
Randy Boyes @randy.pub · 07/03/2025
TidierPlots 0.11 is available without removing or uninstalling anything - on first pass it installs 0.10 but running Pkg.update() upgrades it to 0.11!
110
Randy Boyes @randy.pub · 22/01/2025
TidierPlots.jl v0.10.0 is now available for #julialang! This is mostly an internal update with bug fixes and unit testing, but it also makes it easier to interop with Makie.jl: (credit to beautiful.makie.org for the original image)
0136
Randy Boyes @randy.pub · 06/01/2025
pain
040
Randy Boyes @randy.pub · 23/12/2024
oh no
there is actually AI in team if you use the side of the M as an I
020
Randy Boyes @randy.pub · 15/12/2024
I assume there was some smart way to do today's #adventofcode
240
Randy Boyes @randy.pub · 05/12/2024
Happy with my #julialang #adventofcode solution today, although it means that I have lost my streak of using Tidier packages in my solutions:
data = readlines("data/5.txt")
div = findall(data .== "")[1]

to_int(x) = parse.(Int, x)
rules = to_int.(split.(data[1:(div-1)], "|"))
pages = to_int.(split.(data[(div+1):end], ","))

check_rules(p, rl) = ifelse(
    any([r ⊆ p && !all(p ∩ r .== r) for r in rl]),
    0, p[ceil(Int, end / 2)])

p1 = sum(check_rules.(pages, (rules,)))

println("Part 1: $p1")

rulesort(x, y) = [x, y] in rules
p2 = sum(check_rules.(sort.(pages, lt=rulesort), (rules,))) - p1

println("Part 1: $p2")
260
Randy Boyes @randy.pub · 04/12/2024
If anyone else is making a similar error currently, this is what I’m referring to (from the About):
Can I copy/redistribute part of Advent of Code? Please don't. Advent of Code is free to use, not free to copy. If you're posting a code repository somewhere, please don't include parts of Advent of Code like the puzzle text or your inputs. If you're making a website, please don't make it look like Advent of Code or name it something similar.
000
Randy Boyes @randy.pub · 03/12/2024
Or without the brackets (🏴‍☠️ warning)
¬(f::Function) = x -> f.(x)
p1 = sum ∘ ¬abs ∘ sum ∘ diff ∘ ¬sort ∘ eachcol ∘ readdlm
p1("data/1.txt")
# 2.742123e6
110
Randy Boyes @randy.pub · 03/12/2024
Or go the other way (slightly cursed)
⊙(f, g) = x -> f.(g(x))
p1 = sum ∘ (abs ⊙ sum ∘ diff ∘ (sort ⊙ eachcol ∘ readdlm))
p1("data/1.txt")
140