@aral@mastodon.ar.al avatar aral , to random

🇵🇸 @small-tech/cross-platform-hostname module deprecated

https://www.npmjs.com/package/@small-tech/cross-platform-hostname

The release of version 1.1.0 deprecates and removes support for this small module that normalised hostname reporting between Linux/macOS and Windows.

We no longer support Windows as Microsoft is complicit in Israel’s genocide of the Palestinian people¹ and Small Technology Foundation² stands in solidarity with the Boycott, Divestment, and Sanctions (BDS) movement³.

Windows is an ad-infested and surveillance-ridden dumpster fire of an operating system and, alongside supporting genocide, you are putting both yourself and others at risk by using it.

When supporting Linux/macOS, just use the built-in os.hostname() method which works the same way on both platforms.

¹ https://www.bdsmovement.net/microsoft
² https://small-tech.org/
³ https://www.bdsmovement.net/

eta , to Advent Of Code in 🧑 - 2025 DAY 2 SOLUTIONS - 🧑
@eta@feddit.org avatar

Elixir

This one took way to long to do because I got hung up on what turned out to just be forgetting to rename functions when copying code from part 1 to part 2.

I did part 1 in language but turned to regex for part 2.

#!/usr/bin/elixir

defmodule GiftShopDatabase do

def getRanges(filename) do
	{:ok, content} = File.read(filename)
	input = String.trim(content)
	ranges = []
	currLowerLim = ""
	currNum = ""
	parseRanges(input, ranges, currLowerLim, currNum)
end

defguardp isDigit(c) when c in ?0..?9

defp parseRanges(input, ranges, currLowerLim, currNum) do
	case input do
		<<>> -> Enum.reverse([{currLowerLim,IO.iodata_to_binary(currNum)} | ranges])
		<<",", rest::binary>> ->
			#newUpperLim = IO.iodata_to_binary(currNum) |> String.to_integer
			newUpperLim = IO.iodata_to_binary(currNum)
			parseRanges(rest, [{currLowerLim,newUpperLim} | ranges], currLowerLim, "")
		<<"-", rest::binary>> ->
			#newLowerLim = IO.iodata_to_binary(currNum) |> String.to_integer
			newLowerLim = IO.iodata_to_binary(currNum)
			parseRanges(rest, ranges, newLowerLim, "")
		<<char::utf8, rest::binary>> when isDigit(char) ->
			parseRanges(rest, ranges, currLowerLim, [currNum | <<char>>])
		other -> raise "[ ERROR ] unkown input:#{inspect(other)}"
	end
end

def getInvIDSum(ranges, invIDSum) do
	case ranges do
		[] -> invIDSumString.to_integer(elem(range,0)), invIDSum))
		[range | rest] -> getInvIDSum(rest, invIDSum+checkRange(range, String.to_integer(elem(range,0)), 0))
		other -> raise "[ ERROR ] invalid ranges given:#{inspect(other)}"
	end
end

defp checkRange(range, currID, invIDSum) do
	strUpperLim = String.to_integer(elem(range,1))
	unevenDigitCount = rem(String.length(Integer.to_string(currID)),2)
	case currID do
		_ when currID > strUpperLim -> invIDSum
		_ when unevenDigitCount == 1 -> checkRange(range, currID+1, invIDSum)
		_ -> checkRange(range, currID+1, invIDSum + checkID(currID))
	end
end

defp checkID(currID) do
	pow = :math.pow(10,String.length(Integer.to_string(currID))/2)
	front = floor(currID/pow)
	back = currID - floor(front*pow)
	if front == back, do: currID, else: 0
end

def getInvIDSumPart2(ranges, invIDSum) do
	case ranges do
		[] -> invIDSum
		#[range | rest] -> getInvIDSumPart2(rest, invIDSum+checkRangePart2(range, elem(range,0), invIDSum))
		[range | rest] -> getInvIDSumPart2(rest, invIDSum+checkRangePart2(range, elem(range,0), 0))
		other -> raise "[ ERROR ] invalid ranges given:#{inspect(other)}"
	end
end

def checkRangePart2(range, currID, invIDSum) do
	numID = String.to_integer(currID)
	numUpperLim = String.to_integer(elem(range,1))
	case currID do
		_ when numID > numUpperLim -> invIDSum
		_ when numID < 10 -> checkRangePart2(range, Integer.to_string(String.to_integer(currID)+1), invIDSum)
		_ -> checkRangePart2(range, Integer.to_string(String.to_integer(currID)+1), invIDSum + checkIDPart2(currID,1,floor(String.length(currID)/2)))
	end
end

def checkIDPart2(currID, currLen, maxLen) do
	regex = "(#{String.slice(currID,0,currLen)})+"
	regexComp = Regex.compile(regex)
	res = Regex.run(elem(regexComp,1), currID)
	case res do
		[_, _] when currLen > maxLen or maxLen == 0 -> 0
		[longestMatch, _] when longestMatch == currID -> String.to_integer(currID)
		[_, _] -> checkIDPart2(currID, currLen+1, maxLen)
		_ -> 0
	end
end

end #module


IO.puts "### Part 1 ###"
ranges = GiftShopDatabase.getRanges("input/day02Input.txt")
IO.puts "[ INFO ] ranges:#{inspect(ranges)}"
invIDSum = GiftShopDatabase.getInvIDSum(ranges, 0)
IO.puts "[ INFO ] invalid ID sum:#{invIDSum}"

IO.puts "### Part 2 ###"
ranges = GiftShopDatabase.getRanges("input/day02Input.txt")
IO.puts "[ INFO ] ranges:#{inspect(ranges)}"
invIDSum = GiftShopDatabase.getInvIDSumPart2(ranges, 0)
IO.puts "[ INFO ] invalid ID sum:#{invIDSum}"
eta , (edited ) to Advent Of Code in 🔒 - 2025 DAY 1 SOLUTIONS -🔒
@eta@feddit.org avatar

Elixir

Oh wow I'm late but that's because I decided to do this year in Elixir which I am not really experienced enough yet as it seems. Part 1 was ok but I didn't really put enough thought into Part 2 and got stuck for a while. However I got it done after a few failed tries and a few questions to AI on how to do things in Elixir.

#!/usr/bin/elixir

defmodule SafeDial do

def readInstructions(filename) do
	filename
	|> File.stream!()
	|> Stream.map(&String.trim/1)
	|> Stream.reject(&(&1 == ""))
	|> Stream.map(fn line ->
		case Regex.run(~r/^([A-Za-z])(\d+)$/, line) do
			[_, letter, number] -> {String.to_atom(letter), String.to_integer(number)}
			_ -> nil
		end
	end)
	|> Enum.reject(&(&1 == nil))
end

def evalInstructions(instructions) do
	initialPos = 50
	zeroCount = 0
	checkInstruction(instructions, initialPos, zeroCount)
end

defp checkInstruction(instructions, currPos, zeroCount) do
	case instructions do
		[] -> {currPos, zeroCount}
		[instruct | rest] ->
			nextPos =
				case instruct do
					{dir, step} when dir == :R and currPos + rem(step,100) > 99 ->
						currPos + rem(step,100) - 100
					{dir, step} when dir == :R and currPos + rem(step,100) > 99 ->
						currPos + rem(step,100) - 100
					{dir, step} when dir == :R ->
						currPos + rem(step,100)
					{dir, step} when dir == :L and currPos - rem(step,100) < 0 ->
						currPos - rem(step,100) + 100
					{dir, step} when dir == :L ->
						currPos - rem(step,100)
					_ -> raise "[ ERROR ] unkown instruction: #{inspect(instruct)}"
				end
			newZeroCount = if nextPos == 0, do: zeroCount + 1, else: zeroCount
			checkInstruction(rest, nextPos, newZeroCount)
		other -> raise "[ ERROR ] unknown instruction: #{inspect(other)}"
	end
end

def evalInstructionsPart2(instructions) do
	initialPos = 50
	zeroCount = 0
	checkInstructionPart2(instructions, initialPos, zeroCount)
end

defp checkInstructionPart2(instructions, currPos, zeroCount) do
	case instructions do
		[] -> {currPos, zeroCount}
		[instruct | rest] ->
			{nextPos, zeroCount1} =
				case instruct do
					{dir, step} when dir == :R and currPos + rem(step,100) == 100 ->
						{currPos + rem(step,100) - 100, zeroCount+floor(step/100)}
					{dir, step} when dir == :R and currPos + rem(step,100) > 99 ->
						{currPos + rem(step,100) - 100, zeroCount+floor(step/100)+1}
					{dir, step} when dir == :R ->
						{currPos + rem(step,100), zeroCount+floor(step/100)}
					{dir, step} when dir == :L and currPos == 0 and currPos - rem(step,100) < 0 ->
						{currPos - rem(step,100) + 100, zeroCount+floor(step/100)}
					{dir, step} when dir == :L and currPos - rem(step,100) < 0 ->
						{currPos - rem(step,100) + 100, zeroCount+floor(step/100)+1}
					{dir, step} when dir == :L ->
						{currPos - rem(step,100), zeroCount+floor(step/100)}
					_ -> raise "[ ERROR ] unkown instruction: #{inspect(instruct)}"
				end
			newZeroCount = if nextPos == 0, do: zeroCount1 + 1, else: zeroCount1
			checkInstructionPart2(rest, nextPos, newZeroCount)
		other -> raise "[ ERROR ] unknown instruction: #{inspect(other)}"
	end
end

end #module

IO.puts "### PART 1 ###"
instructions = SafeDial.readInstructions("input/day01Input.txt")
{finalPos, zeroCount} = SafeDial.evalInstructions(instructions)
IO.puts "final position:#{finalPos} zero count:#{zeroCount}"

IO.puts "### PART 2 ###"
instructions = SafeDial.readInstructions("input/day01Input.txt")
{finalPos, zeroCount} = SafeDial.evalInstructionsPart2(instructions)
IO.puts "final position:#{finalPos} zero count:#{zeroCount}"

Edit: removed debug output

@bitbear@icosahedron.website avatar bitbear , to random

Oldschool music compo at TRSAC has just started. First out: G-Fellow with Life Trace.

ALT
bitbear OP ,
@bitbear@icosahedron.website avatar

My contribution to TRSAC 2025’s Oldschool Music Competition was “I Feel You”. A bit heavy on the bass in the hall, but I’m happy it was played!

Made with Schism Tracker as an oldschool remix of a modern song with lyrics and vocals which is soon to be released!

ALT
  • Reply
  • Loading...
  • bitbear OP ,
    @bitbear@icosahedron.website avatar

    If you want to listen to "I Feel You", it's now available on SoundCloud. ☺️

    https://soundcloud.com/bitbear/i-feel-you-impulse-tracker-mix

    The full release of the modern version with vocals should be available on all music platforms in a couple of weeks.

    bitbear OP ,
    @bitbear@icosahedron.website avatar

    My song “I Feel You” ended up in 4th place in the oldschool music competition at TRSAC 2025, which is okay, I suppose.

    I’m bursting with happiness and pride, though, because my 12 year old daughter entered into the TRSAC 2025 Freestyle Graphics competition — and won! 🏆 🤩

    https://demozoo.org/graphics/378976/

    Sunset Through The Rain by liv. RELEASED 18 OCTOBER 2025 1ST IN THE TRSAC 2025 FREESTYLE GRAPHICS COMPETITION
    “Sunset Through The Rain” — A digital painting by Liv.

    bitbear OP ,
    @bitbear@icosahedron.website avatar

    “I Feel You" is now up on YouTube!

    https://youtu.be/oONgCEQkEFw

    I'll see if I can get one of those PeerTube accounts going and uploading it there too.

    balsoft , to Nix / NixOS in Angle brackets in a Nix flake world

    There's a short explanation in this section: https://nixos.org/manual/nixos/stable/#sec-option-types-submodule (look for specialArgs) and in this section: https://nixos.org/manual/nixpkgs/stable/#module-system-lib-evalModules-param-specialArgs. I don't know whether it's documented properly somewhere.

    @aral@mastodon.ar.al avatar aral , to random

    Just released Node Pebble version 5.1.1

    • Updated to Pebble version 2.7.0.

    • Now also supports macOS and arm64 (because Pebble itself does).

    https://codeberg.org/small-tech/node-pebble

    Node Pebble is a Node.js wrapper for Let’s Encrypt’s¹ Pebble² that:

    • Downloads the correct Pebble binary for your platform.

    • Launches and manages a single Pebble process.

    • Returns a reference to the same process on future calls (safe to include in multiple unit tests where order of tests is undetermined)

    • Automatically patches Node.js’s TLS module to accept Pebble server’s test certificate as well as its dynamically-generated root and intermediary CA certificates.

    ¹ https://letsencrypt.org

    ² “A miniature version of Boulder, Pebble is a small RFC 8555 ACME test server not suited for a production certificate authority.” https://github.com/letsencrypt/pebble

    nmtake , to Linux in Pulse audio hotkeys script

    But the problem is that if you plug in a USB or bluetooth headset, it doesn’t automatically switch to it as the default.

    How about module-switch-on-connect?