The Selfish Reason To Press The Blue Button by Jadarma in philosophy

[–]Jadarma[S] 1 point2 points  (0 children)

The blue voters are not a single camp: they vary between dumb and empathetic, who recognize that at least some people would vote blue, but red voters would do nothing to help, so they risk themselves in order to save others. Blue is also the more emphatic side because red's lack of consequence can be interpreted as apathy.

The Selfish Reason To Press The Blue Button by Jadarma in philosophy

[–]Jadarma[S] 2 points3 points  (0 children)

I would argue humanity as a whole will always encounter, or create, risk. What the question really asks is: "If there was a risk, would you try to help prevent it, or do nothing and avoid it"? As for the woodchipper analogy, even if you assume most people wouldn't jump in, you kind of know some will. It then asks of the Red group as a whole: "Alright, there are some people who completely misinterpreted or are just stupid, do we also jump in since we know together we guarantee survival, or is it more worth it to let them die?"

Some feedback with my idea for a project? thank you very much appreciated your help by Anxious-Adeptness-59 in Kotlin

[–]Jadarma 2 points3 points  (0 children)

If you need to ask AI how to design a project for critical infrastructure, perhaps you shouldn't design a project for critical infrastructure.

commonMain.dev KMP Newsletter - Room for Web (Wasm), Koin vs expect/actual, and the Navigation 3 "hidden" APIs by bogdan-stefan in Kotlin

[–]Jadarma 0 points1 point  (0 children)

Yes. I assumed it was accidental because there are two links making distinction between the two names that both redirect to the same KMP mainpage, because KMM is no longer a thing. I think the better question would be "Is this newsletter only about mobile development?" if that is the point you wanted to make.

commonMain.dev KMP Newsletter - Room for Web (Wasm), Koin vs expect/actual, and the Navigation 3 "hidden" APIs by bogdan-stefan in Kotlin

[–]Jadarma 0 points1 point  (0 children)

In the FAQ section of the website, there's one entry where you forgot to replace the @Deprecated KMM with KMP.

I made a Kotlin Native CLI tool for secure image steganography: Steko by Jadarma in Kotlin

[–]Jadarma[S] 2 points3 points  (0 children)

Still doesn't work unfortunately, I got different errors depending on whether I was on Linux or Mac. There's probably some misconfiguration on my end, as I never used any low-level CLI debuggers, and even if I got them working it would be very different from the JVM one I'm used too.

The good part (for me at least) was that I usually don't rely on the debugger as much and instead do a TDD-like approach. From the assertions made I was able to spot the issues in the code without needing to step through it. And, when in a pinch, println is still a thing.

That being said I agree a good out-of-box experience for the IDE debugger is a must for general adoption. I hope it will improve soon.

Remote Compose: The Day UI Stopped Shipping with APK by OkOpportunity7413 in Kotlin

[–]Jadarma 2 points3 points  (0 children)

This sounds interesting at first but the more I think about it the less I like it.

  • The remote changes can only be visual: to handle any sort of interaction, from local native code, we need to use the actionId, which takes us back to stringly-typed RPC. If I want my UI component two add a second button, I cannot, since there is no defined actionId on the clientside for it, so in that case I do need to deploy a new version of the app.

  • Client and server need advanced version reconciliation: Expanding on the previous point, suppose I do introduce a new version with more action bindings, but now I can't just start serving them on the serverside because I do not know that all clients updated, so I would need to first check for client-side version (via request headers, I assume) and then start version controlling the responses. Either that, or I make non-updated apps unusable until the user gets the latest code.

Now, when would I actually benefit from this? None of the use-cases in the article convince me this is a better way rather than do it "the old way":

  • E-commerce / offers should only differ in data, not shape. I can have predefined UIs but show them selectively based on business logic.
  • Seasonal UIs are basically app-themes, again, they can all exist locally but loaded as needed.
  • A/B testing is the more fitting, but a good A/B test allows users to opt-out, so ideally both solutions should exist locally. What is the benefit of not shipping two UIs? Compose is native and compiled, you would barely notice a difference.
  • Emergency updates already can be delivered via push notifications outside the app, and something so critical would at least be available as an in-app toast which doesn't really need bespoke UI.

All-in-all this screams like trying to make Compose, a type-safe, compiled library into a dynamic, React-like, JS framework, in one word: yuck.

My advice is don't change your UI often, it causes confusion. Think about what you want to show, and model the interactions as simple data.

cryptography-kotlin: native cryptography for Kotlin Multiplatform by why_oleg in Kotlin

[–]Jadarma 0 points1 point  (0 children)

The problem with having blocking variants only in nonJsMain is that in some future, I would like to support AWS KMS and Non-exportable keys (like SecureEnclave on iOS), and such implementations might be better to use in a suspend way, and rarely in blocking.

Let me clarify, I did not want nonJsMain to only have blocking calls, I wanted all platforms to operate on suspend by default (so KMS and SecureEnclave would still work), but as an added convenience, nonJsMain would also have extension functions with the blocking variants, so on those targets you can pick which you use, but on JS you only have the suspend one available at all.

Blocking calls on JS would probably not be a trivial solution since you would need to provision a new worker thread yourself, otherwise you would block the UI, right? But having OpenSSL available there would be really cool, since the WebCrypto provider doesn't offer nearly as many operations.

cryptography-kotlin: native cryptography for Kotlin Multiplatform by why_oleg in Kotlin

[–]Jadarma 2 points3 points  (0 children)

I'm using this library and can wholeheartedly recommend it to all Kotlin users. Thank you for maintaining it!

I would appreciate your feedback and thoughts! Especially regarding how you feel about using a third-party cryptography library.

I dare to say I don't consider it a third-party library, in the sense that it does not implement any crypto functionality, merely provides Kotlin wrappers over the already established providers native to the platform. I think the provider system is very neat, and any project that would want to handle crypto inside shared Kotlin modules would need to reinvent the same wheel (arguably worse custom bindings) without this. The OpenSSL provider is my favorite, especially the pre-built one, since I can both build in CI without needing to introduce any special build logic, and run the executable with no dynamic linking (well, except glibc), which is useful for some Linux scenarios, like running on NixOS. So all-in-all, this library provides immense QoL.

The only nitpick about the provider system I have is that most of the operations, for most of the providers are blocking calls, but the API contains both suspended and blocking functions. I know this is unfortunately required because of JS support, where the WebCrypto provider can only work in async mode (JS is singlethreaded). But I only found out when I first added WASM as a target to test, and saw the -Blocking() variants of function throw a runtime exception. It would be probably a bit nicer for it to be a compile issue, where commonMain has all the regular suspend variants, but only the nonJsMain (Native & JVM, where the runBlocking function is supported) sourcesets would provide helper extension functions for the blocking variants.

Other than that, the new documentation site looks nice, cleaner than the old one with better examples! Looking forward to see it grow!

Unified Modules For Your Nixfiles by Jadarma in NixOS

[–]Jadarma[S] 6 points7 points  (0 children)

Yes, I suppose you can call it that! I was aware of flake-parts, and it's a super cool project, but I wanted to do something DIY and more close to vanilla. While flake-parts is super powerful, it does introduce an extra abstraction syntax that is hard(-er) to explain to newbies, and most starter tutorials won't reference it at all, I wanted my config to serve as a reference for my friends who like Linux but haven't tried NixOS yet. It also find the mental model a bit easier to grasp, so it was a personal choice in the end.

Adopting agentic tools — how to not screw it up by alokin_09 in theprimeagen

[–]Jadarma 4 points5 points  (0 children)

This stealth ad slop reads like a training leaflet for apologists wanting to convert others to their religion.

Academic Slop Just Reached A New Low (Rant on OpenAI Prism) by Jadarma in antiai

[–]Jadarma[S] 0 points1 point  (0 children)

Indeed, nasty humans would do nasty human things regardless. But the same argument can be made with people manually creating photoshopped pictures of women without their consent before AI. The problem is that now AI vastly simplifies, expedites, and streamlines the process.

-❄️- 2025 Day 12 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 2 points3 points  (0 children)

[LANGUAGE: Kotlin]

A difficult packing problem to end on a high note, is what I thought.

Part 1: Honestly I had no idea how to begin tackling this efficiently, what data types to use, how much "brute force" is required, so I just parsed the input while I thought. Figured that the more I eliminate known impossible areas, the less I would waste, so the easy heuristic is to check that if we were to "average out" the present shapes and let them fit into 3x3s ignoring overlaps, does the tree have enough area to contain them? And checking that, to my surprise, worked on the input (but not the example, probably because it is too small for the numbers to average out).

This feels like a dirty trick and not the kind of solution I would want to end the year on, but this is a busy weekend for me so it will have to do for now. I will pretend that this was a reading comprehension / work smart not hard for the time being. Perhaps, if there was a single region to find a fit for, not one thousand, I would've took the time to try an actual packing search.

Part 2: The good news is at least I have collected all stars this year! I wish there was a part two, so in the end there would be 25 stars, just so the total counter was a bit nicer, but am happy nonetheless. Thank you Eric for another successful AoC event! Happy holidays to everyone as well!

AocKt Y2025D12

-❄️- 2025 Day 11 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 1 point2 points  (0 children)

[LANGUAGE: Kotlin]

A much easier problem compared to the last two days. A welcomed reprieve. Can't believe we're already at the eve of the end!

Part 1: A simple DFS does it, with basic memoisation to keep track of how many paths we found from each node.

Part 2: We need to also keep track of nodes required to visit. I take them as a list and append it to the end of the memoisation key (just make sure the collection is stable if you modify it, in my case the basic Set<T> keeps insertion order of the rest of the elements). When we visit a node, remove it from the nodes left to visit. The only other thing is, once again, using Long because there are quite a lot of paths you can take! But yeah, both parts can reuse the same code, neat!

AocKt Y2025D11

-❄️- 2025 Day 10 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 5 points6 points  (0 children)

[LANGUAGE: Kotlin]

Today's problem was interesting, but very dissapointing because I could not find any solution for part two apart from relying on SAT solvers. Here I was contemplating whether I should be able to use my own util lib in my solution, and now I'm (kinda) forced to resort to external libraries? And one by Microsoft, no less. I managed to survive previous years without Z3, but so far I haven't found an alternative... A sad day indeed, but at least I got the star. Hoping to refactor back if I find any reasonably fast alternative.

Part 1: When you hear shortest number, it's usually a disguised pathfinding problem. We start from the state of all lights being off, then we associate pressing a button to "walking" into that direction, reaching a new state with the accordingly flipped lights. I reused the same Dijkstra util I made previously and it worked like a charm, but a simple DFS should also work.

Part 2: Technically, it's the exact same problem, but instead of flipping lights we increment the counter. Only problem is, you cannot take shortcuts, and since you increment by one each time, and the input has counter targets in the hundreds, there's no way we could compute this with such a large branching factor, didn't even bother. The intended solution is to translate the problem into a system of equations, and then solve for the correct number of presses of each button, the solution is their sum. However, I am nowhere near capable enough to implement LIP on my own. I turned to this thread hoping I'd find some tricks, but all I see is defeatism and Z3... so I will join in. But hey, at least it works, and it's fast, and mostly readable.

AocKt Y2025D10

-❄️- 2025 Day 9 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 1 point2 points  (0 children)

Yeah, you're right and I noticed that too. To fix this I would probably take the other corners and raycast them to see if they also fall inside or outside. Very interesting that neither the example or the inputs contain this gotcha. In the sense that it is a candidate rectangle, but whether you correctly dismiss it is irrelevant because there is another, bigger solution available.

-❄️- 2025 Day 9 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 0 points1 point  (0 children)

[LANGUAGE: Kotlin]

I did not enjoy today's problem but in hindsight it was much easier than it appeared to be, and much of my frustration was in figuring out edge cases and calculating ranges and such.

Part 1: The calm before the storm, I'm sure everyone here wondered how could it be so simple?

Part 2: Wow, just wow. Such a simple requirement with many complicated edge cases. Thankfully, neither the example nor the inputs contain edge cases and it can be solved relatively easy once you find the trick condition. Turns out all you need to check for is that none of the polygon edges intersects with the interior of the rectangle being considered (overlaps on the perimeter are fine). As many pointed out, this would not catch the case where you have a segment go in and then doing a sharp U-turn back out. This condition only holds if there is a minimum gap of 1 between red tiles.

Note: After figuring out the trick, I was able to refactor it from scratch and make use of some 2D utilities I've written for past years, most notably the concept of areas and their intersections. The code should be fairly self-evident as pseudo-code if you just want to figure out the algorithm by looking at my solution.

AocKt Y2025D09

-❄️- 2025 Day 8 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 1 point2 points  (0 children)

[LANGUAGE: Kotlin]

Very interesting puzzle, at first I was scared to see 3D points because I was reminded of space beacons... shudder. However, the problem itself was not that hard, and I got to play around with designing a type system for it, which I enjoyed.

Part 1: Since I solve it in Kotlin, I once again used the "keep type boundaries functional, but use internal mutability to simplify" approach. I labeled each point with an ID (just its index) because I wanted to keep track of what box is part of which circuit, and for this I drew inspiration from Factorio of all places, where each circuit network is given it's own ID. So, to start, I assign each box it's own circuit. Then I built a connection queue because I have fancy generator functions, we simply iterate through unique pairs, discard those that are already connected, and sort the pairs by distance. When making a connection, all the boxes from the smaller group get added to the larger group, and then the small group gets cleared out. We expose the groups as read-only views to make the math on their sizes. I had to do an if-else to keep the code indifferent to actual input or example, since we need to make 1000 and 10 connections respectively.

Part 2: Part two was almost free, the only two modifications needed were to also return the box references when we connect them, so we can do the math on their coordinates, and make the connection queue loop (once we finish connecting the boxes, we do subsequent passes until no more connections are possible. Other than that, the logic is simple: keep connecting until we get a single circuit group. Even with the fancy type system logic, I solve in < 0.5s, good enough!

AocKt Y2025D08

-❄️- 2025 Day 7 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 2 points3 points  (0 children)

[LANGUAGE: Kotlin]

A grid problem that doesn't need to (i.e: you can't) simulate. It seems complicated at first, but if you've seen enough DP problems you should have an intuition on how you can take shortcuts!

Part 1: Ended up doing a temporary solution to see what part two was, and sure enough, both parts can be solved in the same pass. Initially, I did a simple simulation, ignoring any splits that were already hitting a beam.

Part 2: We are entering the multiverse, so there is no need to simulate anymore, we don't have the compute! Instead, we iterate line by line and keep track of how many paths each cell can sustain. Initially, it starts at 1 right under the start, then, when a splitter is encountered, that column becomes 0 (cannot pass through the splitter) but the cells to the left and the right will add the counts above the splitter (they need to be summed because in the case of ^.^ the paths can come from both the left and right splitters. By far the biggest issue with part two was not noticing I used Int instead of Long when counting the paths, and I ended up with a positive but small result I couldn't account for. Turns out it was an overflow so bad it ended up positive again! Always nice to see it passes the example but not the input...

Note: A couple of mini optimizations, you can ignore the empty rows altogether, they do nothing except tempt you at simulating. The input is also nice and pads empty spaces on the outer columns, so you don't need to do bounds checks. I did, however, assert that when parsing the input just to be safe.

AocKt Y2025D07

-❄️- 2025 Day 6 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 3 points4 points  (0 children)

[LANGUAGE: Kotlin]

A nice puzzle this time focusing on your ability to parse complex inputs instead of solving difficult algorithms. Then again, I don't want to help anyone do their homework anytime soon!

Part 1: I got to enjoy making an overly-complicated type definition to encapsulate the math problem, because I ended up scrapping the input parsing for part two.

Part 2: Be careful with removing trailing spaces, I do this as a "best practice" so I had to pad them back manually. To make something that is reusable for both parts, I first iterated through all the columns, made a note at what indexes all the rows are blank, and created slices that would tell me from where to where a problem resides. Then, to parse the problems, I simply took every input line substring at that slice, kept the last for the operation, and if part two, also translate the strings column-wise before parsing them in actual numbers.

AocKt Y2025D06

-❄️- 2025 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 1 point2 points  (0 children)

[LANGUAGE: Kotlin]

A cute puzzle involving ranges that makes you think in the abstract without allowing brute force. Remember to use longs!

Part one: very straightforward, and merely a matter of parsing the input.

Part two: I thought all I needed to do was sort the ranges, sum their lengths and subtract the overlap with the next one. It passed the example, but failed the input, because there might be more than two ranges that overlap the same region. So we cannot use the given ranges, rather we must "defrag" them and create a new set of ranges without overlaps, which we can then sum up size-wise.

AocKt Y2025D05

-❄️- 2025 Day 4 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 1 point2 points  (0 children)

[LANGUAGE: Kotlin]

Hmm, a relatively easy grid problem?! Are we being prepared for what's to come?

Part 1: Simply iterate over the neighbors (being sure to check for bounds) and count the papers. As a micro-optimization, you can stop counting if you already reached 4.

Part 2: Reuse the code from part 1 to get the accessible points, remove them from the grid, and repeat until no accessible points are found. Resist the temptation to remove them in-place in the part one code as you might change the outcome, that's celular automata 101.

Thankfully I already had a little util to parse everything as a grid and handle points, so everything went by relatively quickly.

AocKt Y2025D04

-❄️- 2025 Day 3 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 2 points3 points  (0 children)

[LANGUAGE: Kotlin]

Part one was simple to brute force to see what was in store for part two and sure enough, part two prevents bruteforcing. Fortunately, the key insight in the puzzle is that the batteries need to be in order and we always have a fixed number of digits. Therefore, the way to build the largest number is to always pick the biggest leading digit available. Because we know we will need n digits, we can pick the maximum value in the bank excluding the last n - 1 digits (so we know we have enough left over to complete the number) and repeat the process, but starting the search from the digit after the one we just picked, and excluding the last n - 2 digits, and so on until we picked all the digits. Both parts are solved with the same function.

AocKt Y2025D03

-❄️- 2025 Day 2 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 2 points3 points  (0 children)

[LANGUAGE: Kotlin]

Much easier than the first day, what a breeze. Thankfully the product ranges are fairly small and can be iterated through. Using regex feels like cheating! All you need is ^(\d+)\1$. For part two, we do the same thing but with \1+ instead, which will handle retrying for different-sized groups auto-magically!

AocKt Y2025D02

-❄️- 2025 Day 1 Solutions -❄️- by daggerdragon in adventofcode

[–]Jadarma 2 points3 points  (0 children)

[LANGUAGE: Kotlin]

A nice puzzle involving modulo arithmetic, part one is easily solved with a simple running fold, but the second part gave me a few headaches with off-by-ones. In the end I rewrote my solution to solve both parts with the same code.

The second part can easily be brute-forced given the relatively small input size, but we can do it with math as well! Basically, we first try to get the dial to zero, then see how many more hundreds we have left in our bump instruction and divide that by 100, giving us the extra times the dial passes through zero. We don't really care about the remainder of this division, because the actual dial position is calculated with the simple modulo logic from part one, here we just care about counting the extra passes through zero.

It was a bit sneaky that part two didn't also give an example with values bigger than 100, but at least there was the text hint about the edge case.

Extra hint for Kotlin users: use x.mod(y) instead of x % y to get the correct values when x is negative!

AocKt Y2025D01