Comment by fainpul

Comment by fainpul 3 days ago

91 replies

Opinion poll:

Python is extremely suitable for these kind of problems. C++ is also often used, especially by competitive programmers.

Which "non-mainstream" or even obscure languages are also well suited for AoC? Please list your weapon of choice and a short statement why it's well suited (not why you like it, why it's good for AoC).

sunrunner 3 days ago

My favourite "non-mainstream" languages are, depending on my mood at the time, either:

- Array languages such as K or Uiua. Why they're good for AoC: Great for showing off, no-one else can read your solution (including yourself a few days later), good for earlier days that might not feel as challenging

- Raw-dogging it by creating a Game Boy ROM in ASM (for the Game Boy's 'Z80-ish' Sharp LR35902). Why it's good for AoC: All of the above, you've got too much free time on your hands

Just kidding, I use Clojure or Python, and you can pry itertools from my cold, dead hands.

alexfoo 3 days ago

Perl is my starting point.

It has many of the required structures (hashes/maps, ad hoc structs, etc) and is great for knocking up a rough and ready prototype of something. It's also quick to write (but often unforgiving).

I can also produce a solution for pretty much every problem in AoC without needing to download a single separate Perl module.

On the negative side there are copious footguns available in Perl.

(Note that if I knew Python as well as I knew Perl I'd almost certainly use Python as a starting point.)

I also try and produce a Go and a C solution for each day too:

* The Go solution is generally a rewrite of the initial Perl solution but doing things "properly" and correcting a lot of the assumptions and hacks that I made in the Perl code. Plus some of those new fangled "test" things.

* The C solution is a useful reminder of how much "fun" things can be in a language that lacks built-in structures like hashes/maps, etc.

WJW 3 days ago

I like to use Haskell, because parser combinators usually make the input parsing aspect of the puzzles extremely straightforward. In addition, the focus of the language on laziness and recursion can lead to some very concise yet idiomatic solutions.

Example: find the first example for when this "game of life" variant has more than 1000 cells in the "alive" state.

Solution: generate infinite list of all states and iterate over them until you find one with >= 1000 alive cells.

    let allStates = iterate nextState beginState # infinite list of consecutive solutions
    let solution = head $ dropWhile (\currentState -> numAliveCells currentState < 1000) allStates
  • lkuty 3 days ago

    Do you plan to share your solutions on Github or something similar ?

    • WJW 3 days ago

      I actually plan on doing this year in Gleam, because I did the last 5 years in Haskell and want to learn a new language this year. My solutions for last year are on github at https://github.com/WJWH/aoc2024 though, if you're interested.

  • jvuygbbkuurx 3 days ago

    Does this solution copy the state on each iteration?

    • WJW 3 days ago

      Haskell values are immutable, so it creates a new state on each iteration. Since most of these "game of life" type problems need to touch every cell in the simulation multiple times anyway, building a new value is not really that much more expensive than mutating in place. The Haskell GC is heavily optimized for quickly allocating and collecting short-lived objects anyway.

      But yeah, if you're looking to solve the puzzle in under a microsecond you probably want something like Rust or C and keep all the data in L1 cache like some people do. If solving it in under a millisecond is still good enough, Haskell is fine.

      • sltkr 3 days ago

        Fun fact about Game of Life is that the leading algorithm, HashLife[1], uses immutable data structures. It's quite well suited to functional languages, and was in fact originally implemented in Lisp by Bill Gosper.

        1. https://en.wikipedia.org/wiki/Hashlife

nemo1618 3 days ago

I made my own, with a Haskell+Bash flavor and a REPL that reloads with each keystroke: https://www.youtube.com/watch?v=r99-nzGDapg

This year I've been working on a bytecode compiler for it, which has been a nice challenge. :)

When I want to get on the leaderboard, though, I use Go. I definitely felt a bit handicapped by the extra typing and lack of 'import solution' (compared to Python), but with an ever-growing 'utils' package and Go's fast compile times, you can still be competitive. I am very proud of my 1st place finish on Day 19 2022, and I credit it to Go's execution speed, which made my brute-force-with-heuristics approach just fast enough to be viable.

  • taolson 3 days ago

    >I made my own, with a Haskell+Bash flavor and a REPL that reloads with each keystroke

    That was impressive! Do you have a public repo with your language, anywhere?

andriamanitra 3 days ago

I think Ruby is the ideal language for AoC:

* The expressive syntax helps keep the solutions short.

* It has extensive standard library with tons of handy methods for AoC style problems: Enumerable#each_cons, Enumerable#each_slice, Array#transpose, Array#permutation, ...

* The bundled "prime" gem (for generating primes, checking primality, and prime factorization) comes in handy for at least a few of problems each year.

* The tools for parsing inputs and string manipulation are a bit more ergonomic than what you get even in Python: first class regular expression syntax, String#scan, String#[], Regexp::union, ...

* You can easily build your solution step-by-step by chaining method calls. I would typically start with `p File.readlines("input.txt")` and keep executing the script after adding each new method call so I can inspect the intermediate results.

shakna 3 days ago

I've always done it in a Scheme. Generally to learn a new compiler and its quirks.

Scheme is fairly well suited to both general programming, and abstract math, which tends to be a good fit for AoC.

thomasjb 2 days ago

C, because it makes every problem into a memory management problem, which is good for you in an 'eat your vegetables' sort of way. It's also the starting point for a lot of other programming languages and related things like HDLs, which is helpful to me.

I'm plodding my way through the 2015 challenge here: https://git.thomasballantine.com/thomasballantine/Advent_of_... , it's really sharpened me up on a number of points.

jlouis 3 days ago

Go is strong. You get something where writing a solution doesn't take too much time, you get a type system, you can brute-force problems, and the usual mind-numbing boring data-manipulation handling fits well into the standard tools.

OCaml is strong too. Stellar type system, fast execution and sane semantics unlike like 99% of all programming languages. If you want to create elegant solutions to problems, it's a good language.

For both, I recommend coming prepared. Set up a scaffold and create a toolbox which matches the typical problems you see in AoC. There's bound to be a 2d grid among the problems, and you need an implementation. If it can handle out-of-bounds access gracefully, things are often much easier, and so on. You don't want to hammer the head against the wall not solving the problem, but solving parsing problems. Having a combinator-parser library already in the project will help, for instance.

  • sunrunner 3 days ago

    > For both, I recommend coming prepared.

    Any recommendations for Go? Traditionally I've gone for Python or Clojure with an 'only builtins or things I add myself' approach (e.g. no NetworkX), but I've been keen to try doing a year in Go however was a bit put off by the verbosity of the parsing and not wanting to get caught spending more time futzing with input lines and err.

    Naturally later problems get more puzzle-heavy so the ratio of input-handling to puzzle-solving code changes, but it seemed a bit off putting for early days, and while I like a builtins-only approach it seems like the input handling would really benefit from a 'parse don't validate' type approach (goparsec?).

    • jlouis 3 days ago

      It's usually easy enough for Go you can just roll your own for the problems at hand. It won't be as elegant as having access to a combinator-parser, but all of the AoC problems aren't parsing problems.

      Once you have something which can "load \n seperated numbers into array/slice" you are mostly set for the first few days. Go has verbosity. You can't really get around that.

      The key thing in typed languages are to cook up the right data structures. In something without a type system, you can just wing things and work with a mess of dictionaries and lists. But trying to do the same in a typed language is just going to be uphill as you don't have the tools to manipulate the mess.

      Historically, the problems has had some inter-linkage. If you built something day 3, then it's often used day 4-6 as well. Hence, you can win by spending a bit more time on elegance at day 3, and that makes the work at day 4-6 easier.

      Mind you, if you just want to LLM your way through, then this doesn't matter since generating the same piece of code every day is easier. But obviously, this won't scale.

      • sunrunner 3 days ago

        > It won't be as elegant as having access to a combinator-parser, but all of the AoC problems aren't parsing problems.

        Yeah, this is essentially it for me. While it might not be a 'type-safe and correct regarding error handling' approach with Python, part of the interest of the AoC puzzles is the ability to approach them as 'almost pure' programs - no files except for puzzle input and output, no awkward areas like date time handling (usually), absolutely zero frameworks required.

        > you can just wing things and work with a mess of dictionaries and lists.

        Checks previous years type-hinted solutions with map[tuple[int, int], list[int]]

        Yeah...

        > but all of the AoC problems aren't parsing problems.

        I'd say for the first ten years at least the first ten-ish days are 90% parsing and 10% solving ;) But yes, I agree, and maybe I'm worrying over a few extra visible err's in the code that I shouldn't be.

        > if you just want to LLM your way through

        Totally fair point if I constrain LLM usage to input handling and the things that I already know that I know how to do but don't want to type, although I've always quite liked being able to treat each day as an independent problem with no bootstrapping of any code, no 'custom AoC library', and just the minimal program required to solve the problem.

  • bashkiddie 2 days ago

    > Go is strong.

    How do you parse the puzzle input into a data structure of your choice?

matsemann 3 days ago

I use python at work but code these in kotlin. The stdlib for lists is very comprehensive, and the syntax is sweet. So easy to make a chain of map, filter and some reduction or nice util (foldr, zipwithnext, windowed etc). Flows very well with my thought process, where in python I feel list comprehensions are the wrong order, lambdas are weak etc.

I write most as pure functional/immutable code unless a problem calls for speed. And with extension functions I've made over the years and a small library (like 2d vectors or grid utils) it's quite nice to work with. Like, if I have a 2D list (List<List<E>>), and my 2d vec, like a = IntVec(5,3), I can do myList[a] and get the element due to an operator overload extension on list-lists.

and with my own utils and extension functions added over years of competitive programming (like it's very fluent

taolson 3 days ago

AoC has been a highlight of the season for me since the beginning in 2015. I experimented with many languages over the years, zeroing in on Haskell, then Miranda as my language of choice. Finally, I decided to write my own language to do AoC, and created Admiran (based upon Miranda and other lazy, pure, functional languages) with its own self-hosted compiler and library of functional data structures that are useful in AoC puzzles:

https://github.com/taolson/Admiran https://github.com/taolson/advent-of-code

marc_omorain 3 days ago

Clojure works really well for AOC.

A lot of the problems involve manipulating sets and maps, which Clojure makes really straightforward.

  • Barrin92 3 days ago

    I'll second Clojure not just for the data structures but also because of the high level functions the standard library ships with.

    Things like `partition`, `cycle` or `repeat` have come in so handy when working with segments of lists or the Conway's Game-of-Life type puzzles.

queuebert 2 days ago

My favorite non-mainstream language for competitions like this and Project Euler is Julia. The startup time is not a factor, and the ability to use UTF-8 symbols as variables makes the code more mathematical.

SilverSlash 2 days ago

Is Rust still "non-mainstream"? Because it's extremely well suited for AoC. The ergonomics of a high-level language with the performance of C++.

  • fragmede 2 days ago

    > The ergonomics of a high-level language

    Is there a way to drop into a repl like with python and pdb.set_trace()? I couldn't find one last time I played around with Rust.

reddit_clone 3 days ago

I have used Raku (Perl 6) with good results.

Common Lisp. Using 'iterate' package almost feels like cheating.

I have done half a year in (noob level) Haskell long ago. But can't find the code any more.

Most mind blowing thing for me was looking at someone's solutions in APL!

talideon 2 days ago

OCaml. There's just enough in the standard library to cover what you need for everything, for any non-trivial parsing tasks, there's a parser generator and lexer generator bundled, and if you want to pull in extra support libraries so you're not looking to implement, say, a trie from scratch.

auxym 3 days ago

I've had a lot of fun using Nim for AOC for many years. Once you're familiar with the language and std lib, its almost as fast to write as python, but much faster (Nim compiles to C, which then gets compiled to your executable). This means that sometimes, if your solution isn't perfect in terms of algorithmic complexity, waiting a few minutes can still save you (waiting 5 mins for your slow Nim code is OK, waiting 5 hours for your slow Python isn't really, for me). Of course all problems have a solution that can run in seconds even in Python, but sometimes it's not the one I figure out first try.

Downsides: The debugging situation is pretty bad (hope you like printf debugging), smaller community means smaller package ecosystem and fewer reference solutions to look up if you're stuck or looking for interesting alternative ideas after solving a problem on your own, but there's still quality stuff out there.

Though personally I'm thinking of trying Go this year, just for fun and learning something new.

Edit: also a static type system can save you from a few stupid bugs that you then spend 15 minutes tracking down because you added a "15" to your list without converting it to an int first or something like that.

AstroBen 3 days ago

This question is really confusing to me because the point of AoC is the fun and experience of it

So.. a language that you're interested in or like?

Reminds me of "gamers will optimize the fun out of a game"

I'm pretty clojure-curious so might mess around with doing it in that

rootnod3 3 days ago

My personal choice is always Common Lisp. Absolute swiss army knife.

  • tmtvl 3 days ago

    With both AoC and Project Euler I like seeing how fast I can get my solution to run with SBCL. Finding all palindromic primes below a million in less than a second is pretty neat.

    • rootnod3 2 days ago

      SBCL is an absolute beast. I think only surpassed by LispWorks, but SBCL is a miracle machine. Even without type annotations it usually performs well enough.

infamousclyde 3 days ago

I’ve always used AoC as my jump-off point for new languages. I was thinking about using Gleam this year! I wish I had more profound reasons, but the pipeline syntax is intriguing and I just want to give it a whirl.

  • tgv 2 days ago

    I started only last year, to learn a bit of Ada. Doing SPARK this year. That has been on my TOLEARN list for a long time. Should be interesting.

  • ceautery 3 days ago

    That's a perfectly valid reason.

    I tried AoC out one year with the Wolfram language, which sounds insane now, but back then it was just a "seemed like the thing to do at the time" and I'm glad I did it.

mrkaye97 3 days ago

I've been using Elixir, which has been wonderful, mostly because of how amazing the built in `Enum` library is for working on lists and maps (since the majority of AoC problems are list / map processing problems, at least for the first while)

  • cyberpunk 3 days ago

    Enum really does feel like a superpower sometimes. I’ll knock out some loop and then spend a few mins with h Enum.<tab> and realise it could’ve been one or two Enum functions.

natrys 3 days ago

I am going to try and stick with Prolog as much as I can this year. Plenty of problems involve a lot of parsing and searching, both could be expressed declaratively in Prolog and it just works (though you do have to keep the execution model in mind).

the_duke 9 hours ago

I use AoC as a chance to try a new language every year.

In the past I used it to try out Swift, J, R, ...

bhollan 3 days ago

I used MATLAB last year while I was re-learning it for work. It did okay, but we didn't have a license for the Image Processing Toolbox, which has a boatload of tools for the grid based problems.

keithlfrost 3 days ago

Elixir Livebook is my tool of choice for Advent of Code. The language is well-suited for the puzzles, I can write some Markdown if I need to record some algebra or my thought process, the notebook format serves as a REPL for instant code testing, and if the solution doesn't fit neatly into an executable form, I can write up my manual steps as well.

sevenseacat 3 days ago

I've been using Elixir since day one, and it works pretty well :)

crystal_revenge 3 days ago

For me (and most of my friends/coworkers) the point of AoC was to write in some language that you always wanted to learn but never had the chance. The AoC problems tend to be excellent material for a crash course in a new PL because they cover a range of common programming tasks.

Historically good candidates are:

- Rust (despite it's popularity, I know a lot of devs who haven't had time to play with it).

- Haskell (though today I'd try Lean4)

- Racket/Common Lisp/Other scheme lisp you haven't tried

- Erlang/Elixir (probably my choice this year)

- Prolog

Especially for those langs that people typically dabble in but never get a change to write non-trivial software in (Haskell, Prolog, Racket) AoC is fantastic for really getting a feel for the language.

  • ngrislain 2 days ago

    Yes, this year I'm going for Lean 4: https://github.com/ngrislain/lean-adventofcode-2025

    It's a great language. It's dependent-types / theorem-proving-oriented type-system combined with AI assistants makes it the language of the future IMO.

    • rootnod3 2 days ago

      Isn't the whole point of AoC to NOT use AI? Even says so in the FAQ

      • ngrislain a day ago

        Yes, I'm doing it without AI to learn the language, nonetheless I do think that Lean 4 + AI is a super-powerful combination.

      • tgv 2 days ago

        Like with the leader board. People do it to score points, not to learn. Hence, cheating.

incognito124 3 days ago

If I remember correctly, one of the competitive programming experts from the global leaderboard made his own language, specifically tailored to help solve AoC problems:

https://github.com/betaveros/noulith

  • wging 3 days ago

    Yes (or so I thought too!), but apparently no: https://blog.vero.site/post/noulith

    (post title: "Designing a Programming Language to Speedrun Advent of Code", but starts off "The title is clickbait. I did not design and implement a programming language for the sole or even primary purpose of leaderboarding on Advent of Code. It just turned out that the programming language I was working on fit the task remarkably well.")

    • Aissen 2 days ago

      It's still very domain-oriented:

      > I solve and write a lot of puzzlehunts, and I wanted a better programming language to use to search word lists for words satisfying unusual constraints, such as, “Find all ten-letter words that contain each of the letters A, B, and C exactly once and that have the ninth letter K.”1 I have a folder of ten-line scripts of this kind, mostly Python, and I thought there was surely a better way to do this.

      I'll chose to remember it was designed for AoC :-D

ghewgill 2 days ago

I've done AoC on what I call "hard mode", where I do the solutions in a language I designed and implemented myself. It's not because the language is particularly suited to AoC in any particular way, but it gives me confidence that my language can be used to solve real problems.

Neon Language: https://neon-lang.dev/ Some previous AoC solutions: https://github.com/ghewgill/adventofcode

fainpul 3 days ago

For some grid based problems, I think spreadsheets are very powerful and under-appreciated.

The spatial and functional problem solving makes it easy to reason about how a single cell is calculated. Then simply apply that logic to all cells to come up with the solution.

paddim8 2 days ago

I used my homemade shell language last year, called elk shell. It worked surprisingly well, better than other languages I've tried, because unlike other shell languages it is just a regular general purpose scripting language with a standard library that can also run programs with the same syntax as function calls.

riffraff 3 days ago

I usually do it with ruby with is well suite just like python, but last year I did it with Elixir.

I think it lends itself very well to the problem set, the language is very expressive, the standard library is extensive, you can solve most things functionally with no state at all. Yet, you can use global state for things like memoization without having to rewrite all your functions so that's nice too.

Alex_L_Wood 3 days ago

Not sure if Kotlin is non-mainstream, but being able to use the vast Java libraries choice and a much nicer syntax are great boons.

azkalam 3 days ago

Terse languages with great collection functions in the standard libraries and tail call optimization. Haskell, OCaml, F# ...

yxhuvud 3 days ago

Crystal. Expressiveness and get-shit-done ability similar to the one of Ruby while being way faster in execution.

christophilus 3 days ago

I’d say Clojure because it has great data manipulation utilities baked into the standard library.

4pkjai 3 days ago

Kotlin, because it’s a language I like

  • jpgvm 3 days ago

    IMO it's maybe the best suited language to AoC. You can write it even faster than Python, has a very terse syntax and great numerical performance for the few challenges where that matters.

vharuck 3 days ago

I've done some of the problems in R. Vectorized-by-default can avoid a lot of boilerplate. And for problems that aren't in R's happy path, I learn how to optimize in the language. And then I try to make those optimizations non-hideous to read.

  • ashdnazg 3 days ago

    My wife did one of the years in Matlab. Some of the problems translate very nicely into vectors and matrices.

radiator 2 days ago

A new language every year. A language I had intended to learn. Using a different programming paradigm, or a paradigm which I have not used recently.

makerofthings 3 days ago

Another vote for Haskell. It’s fun and the parsing bit is easy. I do struggle with some of the 2d map style questions which are simpler in a mutable 2d array in c++. It’s sometimes hard to write throwaway code in Haskell!

tomjen3 2 days ago

With AoC I think that its fine to pick a language that is not at all suited for the challenge. That can be half the fun.

I saw someone one Twitter use Excel.

RobKohr 3 days ago

I have been learning lua to do a VR game in lovr, so I'll probably use that to get sharper with it.

yoyohello13 3 days ago

Haskell is my favorite for advent of code. Finally give me an opportunity to think in a pure functional way.

nedt 3 days ago

The language doesn't really matter much. I think I keep using PHP as in the years before.

[removed] 3 days ago
[deleted]
f1shy 3 days ago

I’ve been doing them is JS and Common Lisp. I recommend the problems to help learning new languages.

  • StopDisinfo910 3 days ago

    I respect the effort going into making Advent of Code but with the very heavy emphasis on string parsing, I'm not convinced it's a good way to learn most languages.

    Most problems are 80%-90% massaging the input with a little data modeling which you might have to rethink for the second part and algorithms used to play a significant role only in the last few days.

    That heavily favours languages which make manipulating string effortless and have very permissive data structures like Python dict or JS objects.

    • f1shy 3 days ago

      You are right. The exercises are heavy in one area. Still, for starting in a new language can be helpful: you have to do in/out with files. Data structures, and you will be using all flow control. So you will not be an ace, but can help to get started.

      I know people who make some arbitrary extra restriction, like “no library at all” which can help to learn the basics of a language.

      The downside I see is that suddenly you are solving algorithmic problems, which some times are bot trivial, and at the same time struggling with a new language.

    • mhitza 3 days ago

      That's a hard agree and a reason why anyone trying to learn Haskell, OCaml, or other language with minimal/"batteries depleted" stdlib will suffer.

      Sure Haskell comes packaged with parser combinators, but a new user having to juggle immutability, IO and monads all at once at the same time will be almost certainly impossible.

      • PapstJL4U 3 days ago

        Maybe not learning a new language from the ground up, but I think it is good training to "just write" within the language. A daily or twice-daily interaction. Setting up projects, doing the basic stuff to get things running, and reading up on the standard library.

        Having smaller problems makes it possible to find multiple solutions as well.

      • talideon 2 days ago

        I typically use OCaml myself for them and have never found the standard library to be particularly "depleted" for AoC, though I do have a couple hundred lines of shared library code built up over the years for parsing things, instrumenting things, and implementing a few algorithms and data structures that keep cropping up.

        Also, dune makes pulling in build dependencies easy these days, and there's no shame in pulling in other support libraries. It's years since I've written anything in Haskell, but I'd guess the same goes for cabal, though OCaml is still more approachable than Haskell for most people, I'd say. A newbie is always going to be at some kind of disadvantage regardless.

        • mhitza 2 days ago

          > I do have a couple hundred lines of shared library code built up over the years for parsing things

          I think that's the best example of anemic built-in utilities. Tried AoC two years ago with OCaml; string splitting, character matching and string slicing were very cumbersome coming from Haskell. Whereas the convenient mutation and for-loops in OCaml provide an overall better experience.

          Given you're already well-versed in the ecosystem you'll probably have no issues working with dune, but for someone picking up OCaml/Haskell and having to also delve in the package management part of the system is not a productive or pleasant experience.

          Bonus points for those trying out Haskell, successfully, than in later challenges having to completely rewrite their solution due to spaceleaks, whereas Go, Rust (and probably OCaml) solutions just bruteforce the work.

          I'm probably just that bad at programming.

yifanl 3 days ago

I believe Eric has said he always makes his first solutions with Perl.

jcadam 3 days ago

I tried to do it in emacs lisp one year. Made it about halfway :)

bombcar 2 days ago

The only way to win is with Brainfuck.

Or MUMPS.

nurettin 2 days ago

If it is not solvable with a Ruby one-liner, it is not a well defined problem.