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.
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}"
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}"
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! 🏆 🤩
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.
² “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
I've been using volumeicon for a long time, to enable the audio hotkeys on my laptop. But the problem is that if you plug in a USB or bluetooth headset, it doesn't automatically switch to it as the default. You'd have to kill the service and restart it. ...
🧑 - 2025 DAY 2 SOLUTIONS - 🧑
Day 2: Gift Shop ...
🔒 - 2025 DAY 1 SOLUTIONS -🔒
Day 1: Secret Entrance ...
Angle brackets in a Nix flake world ( fzakaria.com )
Related discussion: ...
Pulse audio hotkeys script ( github.com )
I've been using volumeicon for a long time, to enable the audio hotkeys on my laptop. But the problem is that if you plug in a USB or bluetooth headset, it doesn't automatically switch to it as the default. You'd have to kill the service and restart it. ...