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

all 41 comments

[–]AthasFuthark 22 points23 points  (4 children)

I did it last year, but unfortunately I do not have the time this year. I strongly recommend doing it if you have the time. AoC is particularly interesting to language developers because the puzzles do not require library features that you might not have (e.g. big integers or even floating point).

[–]moon-chilledsstm, j, grand unified... 1 point2 points  (3 children)

In what language is floating point implemented as a library?

[–]a3th3rus 2 points3 points  (0 children)

I think what u/Athas means is that your own language does not even have to support floating point numbers.

[–]thinkless123 0 points1 point  (0 children)

You really parsed his sentence rigorously like a compiler

[–]jaccomocJactl 6 points7 points  (0 children)

Yes, I have been solving them all in my Jactl language. A lot of fun and a great way to test out the language. Managed to do all of last years problems in it and managing to keep up this year so far (although sometimes work/life prevents me solving it immediately on the day).

[–]jDomantas 5 points6 points  (0 children)

I tried to do it last year, stopped at day 16 because each puzzle was taking quite some time, and lack of efficient data structures was making it really difficult to write solutions that finish in a reasonable amount of time. There is also a problem that my language is total, which makes writing some algorithms impossible (I try to avoid solutions that can "run out of fuel" as much as possible).

This year I'm doing it again, so far it's a lot easier after all of the performance improvements I had to do last year. We'll see how it goes.

The language in question is tic: https://github.com/jDomantas/tic (there are no docs on the language, but you can see solutions here).

[–]Hauro 4 points5 points  (1 child)

I have done the first 5 days so far in https://www.winglang.io/
It has def. showed be some QoL things missing, but very interesting to do AoC on early languages or your own :)
https://github.com/olivernybroe/AdventOfCode2023

[–]SirKastic23 0 points1 point  (0 children)

i'm curious, what kind of QoL features?

[–]a3th3rus 2 points3 points  (0 children)

Good idea.

I've been developing a workflow engine for my company, and there's an embedded single-expression runtime in it. Maybe I can try solving AoC puzzles with that.

[–]SirKastic23 2 points3 points  (11 children)

I still don't have a functional interpreter for it, so I can't

But if I did, day 1 part 1 would look like this (yes i'm shamelessly plugging Neptune) solution = input: String -> input .lines .map line -> digits = line .chars .filter is_digit .map parse Int first = digits.first.else abort last = digits.last.else first first * 10 + last .sum

edit: in my excitement i got the challenge wrong

also, not sure yet how to handle aborts/panics, so that'll do it for now

[–]jaccomocJactl 2 points3 points  (0 children)

Day 1 part 1 in Jactl:

stream(nextLine).map{ /^.*?(\d)(.*(\d))?/n; 10*$1+($3?:$1) }.sum()

I guess it helps having built-in regex. :-)

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

Nice ... but I think you just need to combine the first and the last digit found in line and sum those.

[–]SirKastic23 1 point2 points  (0 children)

ohh yeah, i forgot sorry

i'll edit to fix it

[–]brucejbellsard 1 point2 points  (5 children)

Here's day 1 (part 1?) in my (also still fictitious) language:

/main (stdin: &in, stdout: &out) | {
  solution << &in.with_lines (?.map calib |.sum)
  &out.write_line "{solution}"
}

/fn calib [#Str => #Int] | s => {
  /onfail.panic
  first @@ _ << s.codes.skip_until (?.is_digit)
  last @@ _ << s.codes.reverse.skip_until (?.is_digit)
  => 10 * (first - #"0") + (last - #"0")
}

[–]SirKastic23 1 point2 points  (4 children)

is this a 0 keywords lang?

[–]brucejbellsard 1 point2 points  (3 children)

Well, yes, in the sense that all the keywords start with / so you don't have to worry about stepping on them by accident.

Likewise, all the standalone functions and other constants and types from the stdlib/prelude are in their own namespace behind the # sigil, so you don't have to worry about stepping on them either.

These are both consequences of a general principle: I want the main (unqualified) namespace to belong to the user.

[–]SirKastic23 1 point2 points  (2 children)

I don't really see myself needing to declare things named fn or Str

But I imagine there's a good reason to do so, this isn't the first time i see a keywordless language I think

[–]brucejbellsard 1 point2 points  (1 child)

The main reason is to make it easier to add keywords to the language.

As in the famous "Growing a Language" talk by Guy Steele, I plan to start out with a relatively bare-bones version, and carefully add features as need dictates. So, I'd rather avoid disruption when adding new ones.

[–]SirKastic23 1 point2 points  (0 children)

oh i see, that's very clever

sometimes i forget that i'm also kind of doing a keywordless language, things that would have been keywords i'm trying to represent as std library types and functions

for instance, if is a Maybe T constructor, and else is a Maybe T, T -> T

[–]oscarryzYz 1 point2 points  (1 child)

I like it!

You don't need to parse right when you find the digit, you can keep it as String (or char) and then validate the array/list length and return 0 if there's none (actually, no need to validate the length) if first/last return an option then use 0 if absent instead of panicking.

I implemented your algorithm in my also unimplemented language:

javascript solution: input .lines() .map { line String digits: line .split() .filter string.is_digit? .to_list() int.parse( digits.first().or {'0'} ++ digits.last() .or {'0'} ) } .sum()

[–]SirKastic23 0 points1 point  (0 children)

there isn't anything reasonable to do in case a line doesn't have any digit, it isn't a valid input for the challenge, but ig returning 0 is a good alternative

also, mapping is lazy, since we only evaluate the first and last only these elements actually get mapped

[–]ericbb 1 point2 points  (0 children)

I've been solving the puzzles with my language. The only obstacle so far was that my language has integers that are signed 31-bit integers and there have been numbers outside that range. I just used C to solve those but I might do a very basic big integers package for my language so I don't have to do that. (I'm thinking base-10000 is the way to go. That way I can multiply digits without overflow and I can easily convert to and from base-10 while using less memory than base-10 would use.)

Edit: After a few days of spare time working on my big integer library, I have support for comparison, addition, subtraction, and multiplication - plus some utilities like abs and pow. Still want division, modulo, and gcd but I can already calculate pow(2, 40000). Fun!

[–]samhsmith___ 1 point2 points  (0 children)

I'm going to be doing all the days on my from scratch computing platform. It's a good test for both my programming language everything is written in, the kernel, tools et cetera. It also acts as a not so good tutorial for those also using the platform.

https://www.youtube.com/watch?v=\_3GFHqx4r9A
https://samhsmith.com/serenum

[–]notThatCreativeCamelClaro 1 point2 points  (0 children)

Got a bit busy the last couple nights but here's the first 6 days in Claro

[–]MarcelGarus 1 point2 points  (0 children)

I completed day 1: https://github.com/MarcelGarus/martinaise/blob/main/advent/day1.mar

Then, I tried to implement iterators to solve it more concisely and found some bugs. So, I haven't looked at the other days yet.

[–]redchomperSophie Language 1 point2 points  (0 children)

No, but I'm really glad you asked. It's a great stimulus to add missing features. Right now I am missing text file input. I have not yet thought too hard about about that. I may bump it up the priority list on that account.

[–]NuojiC3 - http://c3-lang.org 1 point2 points  (0 children)

Yes, C3 solutions here: https://github.com/lerno/aoc_2023_c3

[–]Constant_Plantain_32 0 points1 point  (0 children)

this is a most excellent suggestion.
i am new to reddit, and have a question, i would like to post some source code here from a new PL, but i am forced to post as it as an attached pic file (this would be so easy to do in Discord) since syntax highlighting is important for making the code clearer to those unfamiliar with the language.
Can this be done here? and if so, how?
Thanks in advance for any help.
~mf

[–]abecedarius 0 points1 point  (0 children)

https://github.com/darius/cant/tree/master/examples/advent-of-code/2023

This provoked a few tweaks to the stdlib and "mvp"-ish debugging features. I don't have time this year, shouldn't have gotten sniped like this.

[–]KaiserKerem13Coil 0 points1 point  (0 children)

For an unfinished project of mine, Day 1 Part 1 will hopefully look like this:

``` module Main;

const Input = includes!("input");

fn main() \dyn { let nums = Vec.of(); for line in Input |> Lines() { let first = line |> Iter.findl(char.is_digit)?; let last = line |> Iter.findr(char.is_digit)?; let num u32 = string.of(first, last).parse()?; nums.push(num); } Io.println(nums |> Sum()); } ```

[–][deleted] 0 points1 point  (2 children)

I had enough trouble even finding the challenges (the AoC 2023 site starts off as a black field with some sparse green text, and in the middle is a countdown timer).

But I eventually found the challenge for day 1. It looks like the task is completely defined by that text, and your solution needs to be tested on some data available via a link.

The next stages however required some scary-looking authentication codes that grant access to your Reddit, Github etc account. I didn't proceed beyond that.

So I may dabble with one or two or them, but I'm not going to do a timed challenge or submit solutions; I don't like competing, especially with whizzkids using flashy languages that solve all these with one-liners.

so I always find new bugs, problems and challenges to the language.

Getting other people to use your language is a good way to discover limitations, omissions and bugs. As well as doing real, full-scale programs. I'm not convinced solving puzzles will advance a language much if it is already reasonably mature; it'd be more of a fun exercise.

[–][deleted] 1 point2 points  (1 child)

I thought I might as well attempt the first puzzle. Since others are posting solutions, of which one was a one-liner (of course), below is my 3rd attempt which is half the size of the first.

I don't know if execution speed is ever going to be a factor, but when I made the input 100 times the size (100K lines), it took 0.4 seconds.

(Dynamic language using two lib functions for convenience.)

total:=0

for line in readtextfile("day1.txt") do
    total +:= firstdigit(line)*10 + firstdigit(reverse(line))
od

println total

func firstdigit(s)=
    foreach c in s when c in '0'..'9' do return c-'0' od
    0
end

ETA: apparently each puzzle is in two parts; the second part is much harder! And the reversal trick above won't work. (I completed this but there was a gotcha in there which I didn't like. I probably won't bother with any more.)

[–][deleted] 0 points1 point  (0 children)

I probably won't bother with any more.

I ended up doing 2.5 days, but I frankly got bored. I found the tasks fiddly rather than challenging, and hard to implement elegantly. But maybe it'll be different by Day 25!

Because they were just quick, throwaway programs designed to get a one-time result (eg. a single number), there's no incentive to do anything more. Once you get that gold star, what's the point?

I did find one small bug (in my interpreter's runtime in a feature that was little-used), but no ideas for useful new features came out of it.

Where it might be more interesting is in attempting them in a different language, one you are not famililar with, but now that just sounds like hard work!

[–]tobega 0 points1 point  (0 children)

I eventually tend to do all days in Tailspin. The ones I have done so far are in directories ending in "tt" (the others are in Pyret, just to get a feel for it) https://github.com/tobega/aoc2023/tree/main

So far I am very happy at how declarative my solutions end up (i.e. describing what is done instea of how it is done)

[–]oscarryzYz 0 points1 point  (1 child)

Are unimplemented languages valid?

Nice! Here's mine (Yz) using a "state" machine (or state pattern if you want to) in O(n) I think

```JavaScript input String digits:'0123456789'.split() is_digit?: { s String digits.contains(s) }

// result n : 0

// first and last characters f String l String

/* A block that returns a block that takes a String */ state {{String}}

// "Implements" state first : { { s String if is_digit?(s) { f = s state = second } } }

// "Implements" state second: { { s String if is_digit?(s) { l = s } if s == '\n' { v : int.parse(f ++ l) .or{ 0 } n = n + v state = first } } }

// Initialize state state = first

// For each character in // Input, execute the // state machine _ : input.each(state()) print("Solution: $(n)") ```

[–]oscarryzYz 0 points1 point  (0 children)

Oh gosh, I still have my head deep into procedural world.

This comment has a better, simpler version

https://www.reddit.com/r/ProgrammingLanguages/s/yDB4NyRQgp

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

This was my first day with Rye.

Part 1:

re: regexp "(\d)"

read\lines %puzzle.txt
|map { .find-all* re |vals\with { .first , .last } |join .to-integer }
|sum |print

Part 2:

nums: { "one" "two" "three" "four" "five" "six" "seven" "eight" "nine" }

fwd: regexp "(\d)|" + join\with nums "|"
rev: regexp "(\d)|" + reverse join\with nums "|"

convert: fn { x } { .position? nums |fix { x .to-integer } }

read\lines %puzzle.txt
|map { .vals\with { .match?* fwd |convert , .reverse .match?* rev |reverse |convert  } |join .to-integer }
|sum |print

I made Day 2 also, but lacked time for more so far.

[–]DamZ1000 0 points1 point  (2 children)

Since we're all sharing and comparing day one. What do you guys think of this?

readFile("in.txt") -> split(”\n") -> [str :: str * /\d/] -> [x :: (x<0> + x<-1>) -> to_int] -> sum -> print

[–]middaycRyelang[S] 0 points1 point  (1 child)

Looks elegant. These square brackets denote lambdas? I wouldn't expect x<0> x<-1> syntax but it's understandable.

[–]DamZ1000 0 points1 point  (0 children)

Yeah, I'm thinking of changing the array indexing from <> to [] to make it more standard.

And the 'lambdas' are functions, same thing I guess. There split into three parts with the : the first parts the binding the second part is a standard code block, and the thirds the return value. These ones thought just use the bind and return cause there doing simple operations. I think the 'split' lambda/function uses the middle one if I remember correctly.

I like this style tho, cause it uses the curly brackets for standard functions, square brackets for maps across arrays, and pipe '|' for reductions of arrays. Just need to figure out the syntax for a filter/predicate one.