Sign in

NON-TOXICNo ads · No shady algorithms

iiinova is part of the Atmosphere — an open, public network where you own your identity.

fran barton

@ludictechnologies.eurosky.social
294 followers 479 following 562 posts

🔷🔵🟦◀ #shapenote #RStats #JuliaLang #cymraeg #pyrotheology #scything #stroud

PostsRepliesMedia
fran barton @ludictechnologies.eurosky.social · 17/10/2026
010 1
fran barton @ludictechnologies.eurosky.social · 02/10/2026
I'll take it
000 0
fran barton @ludictechnologies.eurosky.social · 12/09/2026
Same energy
030 3
fran barton @ludictechnologies.eurosky.social · 11/09/2026
Thanks, OneDrive
A OneDrive notification saying "11 September! Today over the years. See what made this day special over time."
000 0
fran barton @ludictechnologies.eurosky.social · 25/08/2026
They bag these loaves up the wrong way round don't they? I've only just realised this has been bothering me for a long while. When you open the bag via the twisty end you want to get to the big slices first, not the crust. Something something #bigendian #amirite #uknews
A loaf of sliced bread with the biggest slice at the bottom of the bag and the crust at the twisty opening bit
210 2
fran barton @ludictechnologies.eurosky.social · 10/07/2026
Spain's defence also asking "Where's de kettle here?!"
Panel from David Squires's latest Guardian football cartoon showing Tim thingy from the US team looking in a kitchen cupboard and asking "Where's the kettle here?" - a pun on Belgian player de Ketelaar
130 3
fran barton @ludictechnologies.eurosky.social · 26/06/2026
Oh no
100 1
fran barton @ludictechnologies.eurosky.social · 05/05/2026
Kylo Ren shouting "More!"
000 0
fran barton @ludictechnologies.eurosky.social · 02/05/2026
Same energy:
010 1
fran barton @ludictechnologies.eurosky.social · 10/04/2026
Here's a gif
3507 50
fran barton @ludictechnologies.eurosky.social · 02/04/2026
Paul Hogan as Crocodile Dundee, wearing his black croc tooth hat and smiling broadly
010 1
fran barton @ludictechnologies.eurosky.social · 02/03/2026
"Teenage Ninja Mutant Turtles" - style logo that says "Not Immune To Propaganda"
010 1
fran barton @ludictechnologies.eurosky.social · 26/02/2026
Everyone in Britain knows Gorton and Denton
Arthur Dent and Zaphod Beeblebrox
000 0
fran barton @ludictechnologies.eurosky.social · 24/02/2026
160 6
fran barton @ludictechnologies.eurosky.social · 08/02/2026
It made me think of the meme (I'm sure I'm not the first Sacred Harp singer to do this)
The 30 Rock Steve Buscemi meme with the caption "How do you do, fellow worms?"
110 1
fran barton @ludictechnologies.eurosky.social · 01/02/2026
A new regular #SacredHarp singing is born! We've got a small group together in #Stroud, Gloucestershire, meeting to sing on the first Friday of the month, starting this Friday at the Baptist Hall on Union St., GL5 2HA. I can't wait. All welcome. Email sing@stroudwater.info to find out more.
Stroud Sacred Harp.
Bold four-part harmony singing in the American folk hymn tradition. 
Every first Friday of the month 5.30-7.30pm at the Baptist Hall, Union Street.
Next session: 6th February
A traditional "singing school".
Come learn the basics of shapenote singing.
140 4
fran barton @ludictechnologies.eurosky.social · 08/12/2025
Day 7 done. I made very heavy weather of part 2 as I was skimping on fully understanding the logic required to get the counts right. Happy to have solved another day by reducing over (imho) fairly neat functions that encapsulate and clarify the logic required.
### Day 7: Laboratories

array = [ .==(x, "^") for x in split.(filter(contains("^"), input), "") ];

# part 1 --------------------------

process_arr = function(x::@NamedTuple{last::BitVector, t::Int64}, y::BitVector)
	# take all the last beams, count the splits (clashes with y)
	# remove the splits and also keep any beams that didn't hit a split (misses)
	splits = x[:last] .& y # beams split
	misses = x[:last] .& .~y # beams continue down
	process_splits(x::BitVector) = (x >> 1 .| x << 1)
	new_beams = process_splits(splits) .| misses
	(last = new_beams, t = x[:t] + sum(splits))
end;

# We can pass in array[1] as init array, since we know from inspection that
# there is just 1 beam (from S), which is above the only splitter in array[1]
reduce(process_arr, array, init = (last = array[1], t = 0))[:t]


# part 2 --------------------------

process_arr = function(last::Vector{Int64}, y::BitVector)
	x = .>(last, 0) # inherited beams
	splits = [ x[i] & y[i] ? last[i] : 0 for i in eachindex(last) ]
	misses = [ x[i] & ~y[i] ? last[i] : 0 for i in eachindex(last) ]
	# circshift would be risky if we had data at the ends of our input grid, but
	# we can see from inspection that isn't going to happen till the last step.
	new_routes = [ circshift(splits, 1), circshift(splits, -1), misses ]
	+(new_routes...)
end;

sum(reduce(process_arr, array, init = Int.(array[1])))
030 3
fran barton @ludictechnologies.eurosky.social · 06/12/2025
Another enjoyable solve. I was happy I could use a couple of steps from part 1 again in part 2. They just had slightly different wrangles in the middle part. I was happy to get to use `pop!` and a splat - the onomatopoeic side of coding... (As a kid I loved that scene in Star Wars, scary and gross!)
### Day 6: Trash Compactor

# part 1 --------------------------

rows = split.(strip.(input), r"\s+");
ops = string.(filter(in(["+", "*"]), pop!(rows)));
nums = [ parse.(Int, v) for v in eachrow(reduce(hcat, nums)) ];

process_vec(op::String, vec::Vector{Int64}) = op == "+" ? +(vec...) : *(vec...);
mapreduce(process_vec, +, ops, nums)


# part 2 --------------------------

rows = reverse.(split.(input, "")); # split to each character
ops = string.(filter(in(["+", "*"]), pop!(rows))); # same as p1 but now reversed

slices = join.(eachrow(reduce(hcat, rows)));
# Blocks of numbers are not equal size (some only have 2 or 3 numbers, not the
# full 4), so we gotta split 'em up by the empty ("   ") columns, then get rid
# of the empties.
strs = split.(split(join(replace(slices, "    " => "-"), "|"), "|-|"), "|");
nums = [ parse.(Int, v) for v in strs ];

mapreduce(process_vec, +, ops, nums)
110 1
fran barton @ludictechnologies.eurosky.social · 05/12/2025
#AdventOfCode Day 5: Cafeteria I ended up with nice, functional solutions that I felt I couldn't have written much more elegantly. Happy. But it did take me a while to get the logic for part 2 right. Today was the first time I have experimented with named tuples in Julia. Code on my Codeberg repo.
### Day 5: Cafeteria

input = readlines("input/day05.txt");
ranges = filter(x -> occursin("-", x), input);
ingrids = parse.(Int, filter(x -> occursin(r"^\d+$", x), input));


to_range(x::String) = range(parse.(Int, split(x, "-"))...);
ranges = sort!(to_range.(ranges), by = minimum);


# part 1 --------------------------

sum(map(y -> any(x -> in(y, x), ranges), ingrids))


# part 2 --------------------------

get_new_max = function(x::@NamedTuple{t::Int64, mx::Int64}, y::UnitRange{Int64})
	mx = maximum([x[:mx], maximum(y)])
	len = mx - maximum([minimum(y) - 1, x[:mx]])
	(t = x[:t] + len, mx = mx)
end;

reduce(get_new_max, ranges, init = (t = 0, mx = 0))[:t]
110 1
fran barton @ludictechnologies.eurosky.social · 05/12/2025
Day 4. I had used #JuliaLang 's CartesianIndices function in previous years but this time I wanted to base my whole solution around it. I felt pleased with my solution but also feel like I just go at problems in a very direct, obvious way sometimes, lacking the incisive imagination I see from others
### Day 4: Printing Department

# part 1 --------------------------


check_accessible = function (ind::CartesianIndex{2}, mat::Matrix{Char})
    surround_rect = CartesianIndices((-1:1:1, -1:1:1))
    surrounding_inds = map(x -> ind .+ x, surround_rect[setdiff(1:9, 5)])
    real_inds = filter(x -> checkbounds(Bool, mat, x), surrounding_inds)
    rolls_n = length(filter(.==('@'), mat[real_inds]))
    mat[ind] == '@' && rolls_n < 4
end;

count_rolls = function (mat::Matrix{Char})
    sum(map(x -> check_accessible(x, mat), CartesianIndices(mat)))
end;

count_rolls(prepare_input(input))



# part 2 --------------------------


count_removed = function (mat::Matrix{Char}, removed::Int64 = 0)
    inds = CartesianIndices(mat)
    to_remove = findall(x -> check_accessible(x, mat), inds)
    if length(to_remove) == 0
        removed
    else
        removed += length(to_remove)
        mat_values = map(x -> (x in to_remove ? '.' : mat[x]), inds)
        mat = reshape(mat_values, size(mat))
        count_removed(mat, removed)
    end
end;

count_removed(prepare_input(input))
120 2
fran barton @ludictechnologies.eurosky.social · 03/12/2025
But verily my code, though logically correct, was not actually viable for part 2 within a reasonable span of time. So I wrote a fresh function with a different logic. And this was in turn backwards-applicable to part 1, so I'm just sharing that function in the code snapshot here.
### Day 3: Lobby

# part 2 --------------------------

using .Iterators: take, drop, peel
reduce_to_max = function (line::String, len::Int64 = 12)
    set = collect(take(line, len))
    rst = drop(line, len)
    rng = 1:(len+1)
    while length(collect(rst)) > 0
        stt, rst = peel(rst)
        append!(set, stt)
        pms = map(x -> join(set[setdiff(rng, x)]), rng)
        set = only.(split(string(first(findmax(parse.(Int, pms)))), ""))
    end
    parse(Int, join(set))
end;

sum(reduce_to_max.(input))
# and this is backwards-compatible with part 1 as well, of course:
sum(map(x -> reduce_to_max(x, 2), input))
100 1
fran barton @ludictechnologies.eurosky.social · 01/12/2025
Decided to do a code snapshot with codesnapshot.com as that always looks nice - and my Codeberg link above didn't get a visual. Code in the alt text too.
### Day 1: Secret Entrance

# part 1 --------------------------

parse_input(input) = parse.(Int, replace.(input, "L" => "-", "R" => ""));
create_ends(input) = accumulate(+, pushfirst!(parse_input(input), 50));

get_password(input::Vector{String}) = sum(.==(.%(create_ends(input), 100), 0));

# part 2 --------------------------

count_zeroes = function (a::Int, b::Int)
    seq = b >= a ? ((a+1):b) : (b:(a-1))
    sum(.==(.%(seq, 100), 0))
end;

using .Iterators: drop;
get_password2 = function (input::Vector{String})
    ends = create_ends(input)
    sum([count_zeroes(ends[i-1], ends[i]) for i in drop(eachindex(ends), 1)])
end;
000 0
fran barton @ludictechnologies.eurosky.social · 24/11/2025
Ooh didn't know about this. Looks lovely. Despite the info on their site...
010 1
fran barton @ludictechnologies.eurosky.social · 22/11/2025
The Ashes day 2
The Kombucha meme reversed
010 1
fran barton @ludictechnologies.eurosky.social · 20/09/2025
After the celiidh, setting the chairs back out ready for the morning. We've had a wonderful day singing from the green book!
Lots of red chairs being set out in the "hollow square"Shapenote nails! (Not mine)
131 3
fran barton @ludictechnologies.eurosky.social · 19/06/2025
I find myself very unsatisfied with the "either India... or Australia" construction here. It makes it sound like England turn up at the start of each match not entirely sure who they are going to find they're playing against. I think the standard was set by the maths in the first sentence. #EngVInd
Paragraph from Guardian article: Stokes has won 23 of his 33 games in charge while losing 12 and insisted: “I don’t think it’s arrogant to say that we’ve been good over the last three years.” But with England’s next 10 Tests coming against either India – starting at Headingley on Friday – or ­Australia they have prepared for potential adversity.
010 1
fran barton @ludictechnologies.eurosky.social · 09/12/2024
Latest adventures in "how long will it take me to get to Eastville in #Bristol on a Saturday morning by public transport"? It's 36km away, and a 45 minute drive. Or, on great British public transport, 4.5 hours there and back including at least 8 trains and buses.
Screenshot from Google Maps summarising various public transport options for travelling from Stroud to Bristol, most of which take over 2 hours.
000 0
fran barton @ludictechnologies.eurosky.social · 18/09/2024
Bluesky now has over 10 million users, and I was #9,283,937!
040 4