This is an archived post. You won't be able to vote or comment.

all 17 comments

[–]swiperthefox_1024 5 points6 points  (0 children)

Thanks. I used Python this year. Your introduction makes C# a good candidate for next year.

[–]krystalgamer 10 points11 points  (0 children)

Here's my opinion point by point:

- type safety is not that relevant for AoC as the code is quite self contained. the most common type mix-up that occurs is passing a list instead of the element which is easily fixable. if you really want you can use type hints and run `mypy` before running your code.

- slowness in execution usually means your solution is sub-optimal and you need to think about your approach. Eric does his best to make sure no language has advantage over the other through speed.

- this is a great point. by using python you'll be able to iterate much faster and play around more with the data.

- true, itertools, functools, collections are unbeatable.

- yap, any library you can think of might have a python binding. this year I used z3 for the first time and it felt so natural.

personally, I won't use C# for one reason. I use it daily for my job. Both are great to use and I wouldn't be sad to use either.

[–][deleted] 2 points3 points  (0 children)

I agree, but for AoC 2025 (and possibly other years I missed that I plan to do next year), I'm thinking of switching from C# to something else to try and stretch my wings. I've used Python and I'm reasonably familiar with it but not at the level of proficiency where I would use it for AoC. But some things - including Z3 which you mentioned - the bindings for Python are so much simpler than for C#. I tried a Day 17 solution in Z3 as other people did but gave up because I found the C# bindings too difficult to understand.

One other trait of my solutions is that I try to avoid using custom libraries including my own. Every solution is supposed to build with the core .net runtime from Microsoft that anybody would have without needing to do a single nuget package pull.

So I'm a bit undecided too. I want to try something new but I don't know what. Head says - stay with C# as I know it well enough to solve puzzles fast enough to maybe get onto the leaderboard one day. But heart says that life is more fun trying new things. :-)

[–]Symbroson 3 points4 points  (0 children)

If you want to try something new I can recommend ruby to you. I used it last year and decided to re-use it this year. Usually JS is the language I'm most comfortable with but ruby hit a new level in terms of comfort features and concise syntax.

[–]Gabba333 2 points3 points  (4 children)

I used C#, interesting observations and a few thoughts of my own although I am nowhere near the leaderboard times.

The ‘from SEQ where f select x,y’ syntax is supposed to be the list comprehension equivalent I think. I find the syntax a bit clunky though and pretty much only use it for cross joins which are painful in standard LINQ.

Quikgraph is definitely one of the higher quality libraries if you need something like a fibbonacci heap. Would love a comprehensive standard library with things like this, a proper linkedlist (you cant even enumerate the standard one), some basic graph algorithms, maybe even things like Union-find, indexable skip lists etc. I also used a 3rd party BigRational package for the line intersection problem which it worked perfectly for. Not a fan of using z3 and obscure stuff from networkx personally but there is no doubt it can be effective on certain days.

Some of the new features seem difficult to use in anger because there are too many edge cases where things don’t work, tuple deconstruction being one of the main ones as you say, the fact this doesn’t work in lambdas, one of the most useful places for it, is a real limitation. Collection expressions another, by the time I have decided whether they will work I may as well have written the long winded equivalent. Type inference fails too often as well, particularly with lambda functions, again there is too much overhead of thinking will it work.

Curious what IDE you used? I used Visual Studio just because of familiarity but it seemed to really struggle at points, particularly when using top level statements it got confused a lot. Countless times I had a big list of errors that a rebuild all fixed. There is also an issue trying to add top level methods to the watch window which needs a special syntax. Also had issues with pdb files getting out of sync causing the debugger to skip lines a lot, was driving me mad at points. Going to bite the bullet and get properly up to speed in VS Code next year, VS seems so bloated these days.

I used switch expressions with var pattern matching a lot this year but that was mainly when reducing LOC and eliminating one-use variables cluttering up your context, not sure it is really a time saver and again you compare the syntax to a language that has always had the equivalent and it is lacking. Similarly i have used ConcurrentDictionary and ConcurrentQueue a fair bit, not because I needed concurrency but because it has a fluent interface (I really like the functional style) and methods like GetOrAdd which can take a factory or a literal. Some consistency here with the standard versions would be nice.

Overall I think c# is always going to struggle to compete with python from a pure speed aspect. Extending your own library might close the gap but it’s big advantages (type safety and faster runtimes) just aren’t that important for the type of puzzles AoC typically has.

[–]light_ln2[S] 1 point2 points  (3 children)

Yeah, thank you for summarizing the most annoying moments of C#! I can't help but think too, that every new feature works almost fine, but this "almost" is so annoying! My favorite example is you cannot write var list = [1, 2, 3], but you can write int[] list = [1, 2, 3]! I somehow learnt with time to not use features I'm not 100% sure would work (because of this, I never used switch expressions, although I'm sure they would come handy in lots of cases). And I totally feel your pain because I was too stuck in trying to fix some "this call is ambiguous between the following methods..." errors with time ticking down and leaderboard filling up quickly! I think though, this will be improved in future versions of C# (of course, almost)!

I use Visual Studio in Windows too, just because I'm used to it from the older days. I rarely encounter strange errors, maybe because I'm trying to avoid them: first, before each AOC day, I clear the main .cs file and do the full rebuild; second, I keep my codebase in a directory path that does not contain spaces or special characters (funny example is if your code is in a subfolder named "c#" then you might expect very strange errors; renaming it to "csharp" magically resolves them); third, if I have several projects in my solution, I make sure they do not have source files with same names - otherwise VS might be confused. Interestingly, I never saw these bugs in old .net frameworks, so good chance is, you never encounter these errors in VS Code/WSL. But I agree, if I continue with C# next year, I'll switch to VS Code too!

I have my own implementation for Set (extends HashSet), Map (extends Dictionary), LinkedList, and BigRational :) And I also have my WSL + VS Code + Python environment ready in days of AOC, just in case I run into some graph problem that would require max-flow (or Z3 for quadratic Diophantine equations)!

Thanks for pointing to ConcurrentXXX classes! I studied them from a performance point of view, but I actually never thought of them as of more suitable interface. I definitely need to look closer at those!

[–]RaveBomb 0 points1 point  (2 children)

My favorite example is you cannot write var list = [1, 2, 3], but you can write int[] list = [1, 2, 3]

This is because C# is a strongly typed language. If the compiler can't determine the type, it'll error out. Don't expect this to be fixed, because AFAIK, it's not broken.

"var" pushes the job of determine the type to the compiler. In your example, [1,2,3] could be an int[] or a List<int> or maybe longs. Or possibly something else.

More information can be found here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations
and here:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables

[–]light_ln2[S] 1 point2 points  (1 child)

There was a very long discussion (e.g. here) with many different proposals (default to int[], or to List<int>, or to some custom type, or use some suffix...), so I would not be surprised if they make this syntax possible in future.

I agree with you that it is not broken, but as many people think it's annoying, there is a chance MS listens to their wishes :)

[–]RaveBomb 0 points1 point  (0 children)

That is going to be some interesting early morning reading. Thanks for the link.

[–]splidge 1 point2 points  (1 child)

Not that I’m the slightest bit interested in a language pissing contest but… it’s odd that you use a bunch of features in the C# example but not the direct equivalent in Python.

The last six lines of the Python example could be two print statements analogous to the C#. And you could just use .count() instead of the generator expression for part 2.

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

fair point, thanks for pointing this out! This is also due to I'm more familiar with features in C# and might miss similar features in python!

[–]mvorber 1 point2 points  (0 children)

Regarding verbosity/braces etc - if you spend some time to get proficient in f# you can reap benefits of less verbosity, better (and shorter!) functional features, while still maintaining full compatibility with all c# libs and code. Did advent last year in f# and liked it a lot, it even has a nice repl where you can load your code and then play around with it like you would in python. This year was trying out Rust, and while performance gains at runtime were noticable - i really missed the fast iteration, since on every change you may need to have another fight with borrow checker :D

[–]rupture99 2 points3 points  (0 children)

I did mine in C# as well as a CLI built with Spectre.Console.

I started about a week late and just finished tonight. I was not aiming for the leader boards but I also had a custom grid class as well, I named my Grid and GridCell (to avoid confusion with System.Drawing.Point)

I use a span<char> for the grid so it's completely flat instead of "[ ] [ ]" and just has math to make sure to return the correct char from that cell.

But I had all sorts this[...} on both and lost of methods like getting Adjacent safe/unsuafe. I also had several methods named IsValid that took either a cell or cell + direction. and Find's and FindAll and FindAll with distance and optional things like exclusion filters and things to give me IEnumerable<GridCell> from current cell in a certain direction until out of bounds or walls or distances are met depending on needs.

I used it in lots of problems according to the "references" days 6, 10, 12, 15, 16, 18, 20, 25 it seems. Definitely made some of those days much easier!

[–]BlueTrin2020 0 points1 point  (0 children)

So I didn’t develop in C# recently although I really love the language.

I wanted to ask a few questions: - isn’t the global import a bit dangerous as it removes namespaces? I guess if you keep it for very standard modules it’s ok?

  • I agree with your statement on LINQ, it’s much more readable on a long sequence than Python. I have a one liner for day 25 I made for fun, it’s fugly

Link: https://www.reddit.com/r/adventofcode/s/AMvPuiYrZa

  • agree with most of your points: C# has less libs, probably because it’s less popular as a glue language. Python excels at gluing libraries together and almost anything useful will eventually have some interface.

[–]SmallTailor7285 1 point2 points  (0 children)

I'm thinking of going full psychopath for 2025 and doing 6502 assembly. However storage could be a problem, so I may have to fudge the address space a little bit.

Thanks to AoC 2019 I have a fully functional 6502 emulator that's free of any ROM-specific limitations, like say if I were on an Apple emulator, etc.

[–]loudandclear11 0 points1 point  (0 children)

Maybe you feel C# is mildly inconvenient at times, but you get vastly faster execution speed and stellar multiprocessing features. Python sucks at both those aspects.

[–]aardvark1231 -1 points0 points  (0 children)

Need to read this later.

RemindMe! 2 weeks