scarecrw's recent activity

  1. Comment on What’s a point that you think many people missed? in ~talk

    scarecrw
    Link Parent
    I think your second point is very true. Though, interestingly, I find its counterpart equally fitting for this thread: Just because your portrayal is intended as a critique, that doesn't absolve...

    I think your second point is very true. Though, interestingly, I find its counterpart equally fitting for this thread: Just because your portrayal is intended as a critique, that doesn't absolve you of responsibility for taking care in your presentation.

    Artists and creators can't be held accountable for every interpretation of their work, but I often think we're kidding ourselves when we count a portrayal as a condemnation because the antihero "got what was coming to them" at the end, ignoring the previous 90% of the work that glamorized their behavior.

    I don't know if I fully agree with Truffaut's "No such thing as an anti-war movie" perspective, but I am wary of people exploiting the label of "critique" to avoid addressing the potential impact that different portrayals can have.

    3 votes
  2. Comment on Browser puzzle game: enclose.horse in ~games

    scarecrw
    Link
    Alright, I've been effectively sniped. Anybody have an idea for solving this? My current thought is to model this as a graph with the horse as the source and the border as a sink and search for a...

    Alright, I've been effectively sniped. Anybody have an idea for solving this?

    My current thought is to model this as a graph with the horse as the source and the border as a sink and search for a cut less than the number of walls, optimizing for the number of nodes remaining connected to the source. This almost matches a min-cost flow problem, but not exactly. It should be able to be modelled as an ILP problem, but I'm hoping there's a better approach I'm not seeing.

    4 votes
  3. Comment on Scalable oral exams with an ElevenLabs voice AI agent in ~tech

    scarecrw
    Link Parent
    I'm ambivalent on this. I've thankfully not had anxiety issues with public speaking or exams myself, but knowing a few people who have experienced panic attacks, they're obviously not in a state...

    I'm ambivalent on this. I've thankfully not had anxiety issues with public speaking or exams myself, but knowing a few people who have experienced panic attacks, they're obviously not in a state where they would be able demonstrate their understanding of a topic.

    On the other hand, I do feel like a very low weighted oral exam that was still a hurdle for course grading makes a lot of sense. I don't think its a substitute for other forms of assessment, but setting a bar of "participate in an informed discussion of the topic you've ostensibly been studying for the past few months" doesn't seem like an unreasonable ask to be awarded a confirmation of completion. Put another way: I wouldn't want to graduate anyone who couldn't hold a discussion about the topic being learned, and it's hard to imagine a way to do that without some form of direct assessment.

    5 votes
  4. Comment on A, B, C or D – grades might not say all that much about what students are actually learning in ~humanities

    scarecrw
    Link
    I try to avoid commenting when I'm just being negative, so I'll start by saying I do want to see changes to the way student performance is assessed and how that assessment is then perceived and...

    I try to avoid commenting when I'm just being negative, so I'll start by saying I do want to see changes to the way student performance is assessed and how that assessment is then perceived and used.

    With that said, from the vast majority of cases I've seen, attempts to introduce alternative assessment approaches are nothing more than grade inflation. Standards based grading is great, but you still have to be willing to fail students who don't demonstrate mastery. By all means, let's not let a single poor test grade keep a student from eventually succeeding, but having them retake the exact same test is not a method to show growth.

    10 votes
  5. Comment on Anyone else using the Zed editor? in ~comp

    scarecrw
    Link
    I haven't actually tried it, but based on this post I'm interested in giving it a go. I'll probably still need to keep vscode around for specific uses, but I don't have any attachment to it in...

    I haven't actually tried it, but based on this post I'm interested in giving it a go. I'll probably still need to keep vscode around for specific uses, but I don't have any attachment to it in general.

    Speaking of local LLM use, does anybody have a recommended coding model for trying it out? I gave it a shot a while back, but between fussing with vscode extensions and the poor accuracy:speed ratio I gave up on it.

    2 votes
  6. Comment on Day 9: Movie Theater in ~comp.advent_of_code

    scarecrw
    Link
    Catching up on the last couple of days. This one went alright, though I was just lazy and figured at ~500 points I could probably get away with an n^3 solution. I believe I could get it to n^2logn...

    Catching up on the last couple of days. This one went alright, though I was just lazy and figured at ~500 points I could probably get away with an n^3 solution. I believe I could get it to n^2logn without too much trouble if I had some more powerful data structures, but I already felt like a cheated on day 8 already by using a pre-made union-find.

    Prolog Solution
    :- ['src/util.pl'].
    :- initialization(main).
    
    main:-
        phrase_from_file(input(Points), 'inputs/day09.txt'),
        solve_1(Points, Result1),
        write("Part 1: "), write(Result1), nl,
        solve_2(Points, Result2),
        write("Part 2: "), write(Result2), nl,
        halt.
    
    solve_2(Points, Result):-
        findall((I1, I2, P1, P2), (nth0(I1, Points, P1), nth0(I2, Points, P2), I1 < I2), PointPairs),
        [H|T] = Points,
        append(T, [H], ShiftedPoints),
        maplist([P1, P2, R]>>(R = (P1, P2)), Points, ShiftedPoints, LineSegs),
        include(valid_part_2_rect(LineSegs), PointPairs, ValidPointPairs),
        maplist([(_, _, P1, P2), A]>>rectangle_area((P1, P2), A), ValidPointPairs, Areas),
        max_list(Areas, Result).
    
    valid_part_2_rect(LineSegs, (I1, I2, X1-Y1, X2-Y2)):-
        sort([X1, X2], [MinX, MaxX]),
        sort([Y1, Y2], [MinY, MaxY]),
        all(no_intersects_rect(MinX, MaxX, MinY, MaxY), LineSegs).
    
    no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):-
        (X1 =< MinX, X2 =< MinX), !.
    no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):-
        (Y1 =< MinY, Y2 =< MinY), !.
    no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):-
        (X1 >= MaxX, X2 >= MaxX), !.
    no_intersects_rect(MinX, MaxX, MinY, MaxY, (X1-Y1, X2-Y2)):-
        (Y1 >= MaxY, Y2 >= MaxY), !.
    
    solve_1(Points, Result):-
        findall((P1, P2), (member(P1, Points), member(P2, Points)), PointPairs),
        maplist(rectangle_area, PointPairs, Areas),
        max_list(Areas, Result).
    
    rectangle_area((X1-Y1, X2-Y2), Area):-
        Area is (abs(X2 - X1) + 1) * (abs(Y2 - Y1) + 1).
    
    input([Point|Rest]) -->
        point_dcg(Point),
        "\n",
        input(Rest).
    input([Point]) --> point_dcg(Point).
    
    point_dcg(Point) --> 
        number_dcg(X),
        ",",
        number_dcg(Y),
        { Point = X-Y }.
    
    1 vote
  7. Comment on Day 8: Playground in ~comp.advent_of_code

    scarecrw
    Link
    Catching up (poorly) on the last couple of days. I found a union-find pack which took out most of the hard work, though the rest of my code is still terribly inefficient. Oh well, just gotta keep...

    Catching up (poorly) on the last couple of days. I found a union-find pack which took out most of the hard work, though the rest of my code is still terribly inefficient. Oh well, just gotta keep the momentum going for now.

    Prolog Solution
    :- ['src/util.pl'].
    :- initialization(main).
    :- use_module(library(record)).
    :- use_module(library(union_find)).
    
    :- record point(x:integer=0, y:integer=0, z:integer=0).
    
    main:-
        phrase_from_file(input(Points), 'inputs/day08.txt'), Merges = 1000,
    
        findall((D, P1, P2), point_pair(Points, P1, P2, D), PointPairs),
        sort(PointPairs, PointPairs1),
        maplist([(_, P1, P2), R]>>(nth1(I, Points, P1), nth1(J, Points, P2), R = (I, J)), PointPairs1, PointPairs2),
    
        solve_1(Points, PointPairs2, Merges, Result1),
        write("Part 1: "), write(Result1), nl,
        solve_2(Points, PointPairs2, Result2),
        write("Part 2: "), write(Result2), nl,
    
        halt.
    
    solve_1(Points, PointPairs, Merges, Result):-
        take(Merges, PointPairs, PointPairs1),
        length(Points, N),
        union_find(UF, N),
        maplist([(P1, P2)]>>(union(UF, P1, P2)), PointPairs1),
        disjoint_sets(UF, DS),
        maplist(length, DS, Lengths),
        sort(Lengths, Lengths1),
        reverse(Lengths1, Lengths2),
        take(3, Lengths2, ToMult),
        prod_list(ToMult, Result).
    
    solve_2(Points, PointPairs, Result):-
        length(Points, N),
        union_find(UF, N),
        solve_2_rec(UF, PointPairs, (A, B)),
        nth1(A, Points, P1),
        nth1(B, Points, P2),
        point_x(P1, X1),
        point_x(P2, X2),
        Result is X1 * X2.
    
    solve_2_rec(UF, [(P1, P2)|_], LastPair):-
        disjoint_sets(UF, DS),
        length(DS, L),
        L == 2,
        find(UF, P1, R1),
        find(UF, P2, R2), 
        R1 =\= R2,
        LastPair = (P1, P2).
    solve_2_rec(UF, [(P1, P2)|Pairs], LastPair):-
        union(UF, P1, P2),
        solve_2_rec(UF, Pairs, LastPair).
    
    point_pair(Points, P1, P2, Distance):-
        member(P1, Points), member(P2, Points),
        distance_sq(P1, P2, Distance),
        Distance =\= 0,
        point_x(P1, X1), point_y(P1, Y1), point_z(P1, Z1),
        point_x(P2, X2), point_y(P2, Y2), point_z(P2, Z2),
        (X1 > X2 ; (X1 == X2, Y1 > Y2) ; (X1 == X2, Y1 == Y2, Z1 > Z2)).
    
    distance_sq(Point1, Point2, Distance):-
        point_x(Point1, X1), point_y(Point1, Y1), point_z(Point1, Z1),
        point_x(Point2, X2), point_y(Point2, Y2), point_z(Point2, Z2),
        Distance is (X1 - X2)^2 + (Y1 - Y2)^2 + (Z1 - Z2)^2.
    
    input([Point|Rest]) -->
        point_dcg(Point),
        "\n",
        input(Rest).
    input([Point]) --> point_dcg(Point).
    
    point_dcg(Point) --> 
        number_dcg(X),
        ",",
        number_dcg(Y),
        ",",
        number_dcg(Z),
        { make_point([x(X), y(Y), z(Z)], Point) }.
    
    1 vote
  8. Comment on Day 6: Trash Compactor in ~comp.advent_of_code

    scarecrw
    Link Parent
    The problem is that when you pass params to operate in part 2, it isn't a numpy array, so when numpy.prod() auto-converts it to one, it defaults the datatype to int32 and overflows. You can fix it...

    The problem is that when you pass params to operate in part 2, it isn't a numpy array, so when numpy.prod() auto-converts it to one, it defaults the datatype to int32 and overflows. You can fix it with numpy.prod(params, dtype='uint64').

    As for the rotation, using list(zip(*inputs))[::-1] is a neat trick if you want to do the rotations yourself.

    1 vote
  9. Comment on Day 7: Laboratories in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Pretty easy day for the problem itself, so I used the opportunity to try a couple new things: DCGs and "Association Lists" (why does every language have to have their own name for this?). I'm not...

    Pretty easy day for the problem itself, so I used the opportunity to try a couple new things: DCGs and "Association Lists" (why does every language have to have their own name for this?).

    I'm not convinced using a DCG for this style of parsing made it any easier (it certainly didn't make it more succinct), but I can certainly see how it could be useful for more advanced parsing.

    I have to say, while Prolog is growing on me, I'm still feeling silly writing ~9 lines to update a couple values in a data structure. It's not that it's that hard, I'm just hoping there's a more idiomatic approach I don't know about.

    Prolog Solution
    :- initialization(main).
    
    main:-
        phrase_from_file(input(StartingColumn, Rows), 'inputs/day07.txt'),
        list_to_assoc([StartingColumn-1], Beams),
        foldl(process_line, Rows, (Beams, 0), (TotalBeams, Result1)),
        assoc_to_values(TotalBeams, BeamCounts),
        sum_list(BeamCounts, Result2),
        format('Part 1: ~w~n', [Result1]),
        format('Part 2: ~w~n', [Result2]),
        halt.
    
    process_line([], State, State).
    process_line([Splitter|Rest], (Beams, Splits), (ResBeams, Splits1)):-
        get_assoc(Splitter, Beams, _),
        process_line(Rest, (Beams, Splits), (RecBeams, RecSplits)),
        split_beams(Splitter, RecBeams, ResBeams),
        succ(RecSplits, Splits1).
    process_line([_|Rest], State, ResultingState):-
        process_line(Rest, State, ResultingState).
    
    split_beams(Splitter, Beams, ResBeams):-
        get_assoc(Splitter, Beams, Count),
        succ(L, Splitter),
        succ(Splitter, R),
        (get_assoc(L, Beams, LCount) ; LCount = 0),
        (get_assoc(R, Beams, RCount) ; RCount = 0),
        del_assoc(Splitter, Beams, _, Beams1),
        LCountNew is LCount + Count,
        RCountNew is RCount + Count,
        put_assoc(L, Beams1, LCountNew, Beams2),
        put_assoc(R, Beams2, RCountNew, ResBeams).
    
    % Parsing
    input(StartingColumn, Rows) -->
        starting_column(StartingColumn, 0),
        "\n",
        rows(Rows).
    
    starting_column(StartingColumn, Idx) -->
        ".",
        { succ(Idx, Idx1) },
        starting_column(StartingColumn, Idx1).
    starting_column(StartingColumn, StartingColumn) -->
        "S",
        rest_of_line.
    
    rest_of_line --> ".", rest_of_line ; [].
    
    rows([Row]) --> row(Row, 0).
    rows([Row|Rest]) -->
        row(Row, 0),
        "\n",
        rows(Rest).
    
    row(Row, Idx) -->
        ".",
        { succ(Idx, Idx1) },
        row(Row, Idx1).
    row(Row, Idx) -->
        "^",
        { succ(Idx, Idx1) },
        row(RowRest, Idx1),
        {Row = [Idx|RowRest]}.
    row([], _) --> [].
    
    1 vote
  10. Comment on Day 6: Trash Compactor in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Another day down, though this was mostly just a bit annoying. I did add a few useful tools to my saved utilities: transpose/2, split_list/3, and prod_list/2. Not sure if they'll be useful in...

    Another day down, though this was mostly just a bit annoying. I did add a few useful tools to my saved utilities: transpose/2, split_list/3, and prod_list/2. Not sure if they'll be useful in future days, but I thought they were general enough to keep.

    Prolog Solution
    :- ['src/util.pl'].
    :- initialization(main).
    
    main:-
        read_file_to_strings('inputs/day06.txt', Lines),
    
        parse_input_1(Lines, Vals, Ops),
        maplist(solve, Ops, Vals, Nums),
        sumlist(Nums, Result1),
        write("Part 1: "), write(Result1), nl,
    
        parse_input_2(Lines, Vals2, Ops2),
        maplist(solve, Ops2, Vals2, Nums2),
        sumlist(Nums2, Result2),
        write("Part 2: "), write(Result2), nl,
    
        halt.
    
    solve("+", Vals, Result):- sum_list(Vals, Result).
    solve("*", Vals, Result):- prod_list(Vals, Result).
    
    parse_input_1(Lines, Vals, Ops):-
        maplist([S]>>split_string(S, " ", " "), Lines, SplitLines),
        last(SplitLines, Ops),
        append(ValStrings, [Ops], SplitLines),
        maplist(maplist(string_number), ValStrings, ValRows),
        transpose(ValRows, Vals).
    
    parse_input_2(Lines, Vals, Ops):-
        last(Lines, OpsString),
        append(OrigValStrings, [OpsString], Lines),
        split_string(OpsString, " ", " ", Ops),
        maplist(string_chars, OrigValStrings, Chars),
        transpose(Chars, FlippedChars),
        maplist(exclude(=(' ')), FlippedChars, FilteredChars),
        maplist([C, S]>>string_chars(S, C), FilteredChars, FlippedStrings),
        split_list(FlippedStrings, "", ValStrings),
        maplist(maplist(string_number), ValStrings, Vals).
    
    Utilities
    transpose([], []).
    transpose([L], R):-
        maplist([X, V]>>(V = [X]), L, R).
    transpose([H|T], R):-
        transpose(T, RecResult),
        maplist([X,Y,Z]>>(Z = [X|Y]), H, RecResult, R).
    
    split_list(List, Delimiter, Result):-
        split_list(List, Delimiter, [], Result).
    split_list([], _, Acc, [Acc]).
    split_list([Delimiter], Delimiter, Acc, [Acc, []]).
    split_list([Delimiter|T], Delimiter, Acc, Result):-
        split_list(T, Delimiter, [], Result1),
        Result = [Acc|Result1].
    split_list([H|T], Delimiter, Acc, Result):-
        Acc1 = [H|Acc],
        split_list(T, Delimiter, Acc1, Result).
    
    prod_list(List, Result):-
        foldl([A,B,C]>>(C is A * B), List, 1, Result).
    
    2 votes
  11. Comment on Day 5: Cafeteria in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Very much needed a good day after yesterday frustrated me so much. It just seemed like yesterday everything I tried with the language went wrong, and today it fell together nicely. Nothing...

    Very much needed a good day after yesterday frustrated me so much. It just seemed like yesterday everything I tried with the language went wrong, and today it fell together nicely.

    Nothing creative on the algorithmic front; I suppose there may be some efficiency gains to be had on both parts by keeping ranges sorted, but the list was short enough it didn't matter.

    Prolog Solution
    :- ['src/util.pl'].
    
    parse_range(RangeString, [Start, End]):-
        split_string(RangeString, "-", "", [A, B]),
        number_string(Start, A),
        number_string(End, B).
    
    in_ranges(Ranges, ID):-
        member([Start, End], Ranges),
        between(Start, End, ID).
    
    overlap([S1, E1], [S2, E2]):-
        S1 =< E2,
        S2 =< E1.
    
    merge_range_rangelist(Range, RangeList, Result):-
        partition(overlap(Range), RangeList, OverlappingRanges, OtherRanges),
        flatten([Range|OverlappingRanges], EndPoints),
        min_list(EndPoints, Start),
        max_list(EndPoints, End),
        Result = [[Start, End]|OtherRanges].
    
    range_size([A, B], RangeSize):-
        RangeSize is B - A + 1.
    
    main:-
        Filename = 'inputs/day05.txt',
        read_file_to_strings(Filename, Lines),
        append(RangeStrings, [""|IDStrings], Lines),
        maplist(parse_range, RangeStrings, Ranges),
        maplist(string_number, IDStrings, IDs),
    
        include(in_ranges(Ranges), IDs, FreshIDs),
        length(FreshIDs, Result1),
        write("Part 1: "), write(Result1), nl,
    
        foldl(merge_range_rangelist, Ranges, [], MergedRanges),
        maplist(range_size, MergedRanges, RangeSizes),
        sumlist(RangeSizes, Result2),
        write("Part 2: "), write(Result2), nl,
        halt.
    
    :- initialization(main).
    

    I tried reading up on difference lists and DCGs this afternoon and did not get anywhere with it. I'll have to give it another go with a clearer head.

    2 votes
  12. Comment on Day 4: Printing Department in ~comp.advent_of_code

    scarecrw
    (edited )
    Link
    Over two hours to write and over a minute to run... Yesterday I would have said Prolog didn't seem so bad and I was getting a feel for things, today I spent the better part of an hour getting a...

    Over two hours to write and over a minute to run...

    Yesterday I would have said Prolog didn't seem so bad and I was getting a feel for things, today I spent the better part of an hour getting a Moore neighborhood to work.

    Real tired and pretty disappointed after this one. Hopefully get a second wind with some free time this weekend.

    Prolog Solution
    :- ['src/util.pl'].
    :- table contains_paper/3.
    
    contains_paper(Grid, 0, Position):-
        Position = (RowIndex, ColIndex),
        nth0(RowIndex, Grid, Row),
        string_chars(Row, RowChars),
        nth0(ColIndex, RowChars, Char),
        Char = '@'.
    
    contains_paper(Grid, Step, Position):-
        succ(Step1, Step),
        contains_paper(Grid, Step1, Position),
        not(forkliftable(Grid, Step1, Position)).
    
    forkliftable(Grid, Step, Position):-
        contains_paper(Grid, Step, Position),
        findall(Pos, neighbor(Position, Pos), Neighbors),
        count(contains_paper(Grid, Step), Neighbors, NeighborPaper),
        NeighborPaper < 4.
    
    neighbor(Position1, Position2):-
        Position1 = (Row1, Col1),
        between(-1, 1, DR),
        between(-1, 1, DC),
        (DR, DC) \= (0, 0),
        Row2 is Row1 + DR,
        Col2 is Col1 + DC,
        Position2 = (Row2, Col2).
    
    paper_removed(Grid, Step, PaperRemoved):-
        findall(Pos, contains_paper(Grid, 0, Pos), OriginalPaper),
        findall(Pos, contains_paper(Grid, Step, Pos), FinalPaper),
        length(OriginalPaper, OriginalCount),
        length(FinalPaper, FinalCount),
        PaperRemoved is OriginalCount - FinalCount.
    
    main:-
        Filename = 'inputs/day04.txt',
        read_file_to_strings(Filename, Grid),
        paper_removed(Grid, 1, Result1),
        write("Part 1: "), write(Result1), nl,
        paper_removed(Grid, 100, Result2),
        write("Part 2: "), write(Result2), nl,
        halt.
    
    :- initialization(main).
    
    1 vote
  13. Comment on Day 3: Lobby in ~comp.advent_of_code

    scarecrw
    Link Parent
    I'm hoping someone has an actually clean fix, as I've run into that in the past without much luck. Couple of ideas: Reverse the list, then iterate from 11...0, as list[n:] works fine. Use an...

    I'm hoping someone has an actually clean fix, as I've run into that in the past without much luck.

    Couple of ideas:

    • Reverse the list, then iterate from 11...0, as list[n:] works fine.
    • Use an in-line conditional list[:n] if n else list
    2 votes
  14. Comment on Advent of Code starts tomorrow/tonight! Are you participating? Do you have any specific plans for this year? in ~comp.advent_of_code

    scarecrw
    Link Parent
    I hope you enjoy it! The days get harder as they progress, and later days often require either improved algorithms or optimizing for the properties if the inputs. Hopefully some edifying...

    I hope you enjoy it!

    The days get harder as they progress, and later days often require either improved algorithms or optimizing for the properties if the inputs. Hopefully some edifying challenges await!

    1 vote
  15. Comment on Day 3: Lobby in ~comp.advent_of_code

    scarecrw
    Link
    Bit of a better day, as I guessed Part 2 so was already planning out the algorithm. My first thought was a DP solution (which napkin-math suggests might have worked?), but figured out a better...

    Bit of a better day, as I guessed Part 2 so was already planning out the algorithm. My first thought was a DP solution (which napkin-math suggests might have worked?), but figured out a better approach instead. Went back and refactored to add a couple new utilities and make the main solver tail-recursive.

    I got spooked at first thinking it might be 2D arrays and realized I'll need to read up to figure out how best to handle that, as it's sure to be coming in the next few days.

    Prolog Solution
    :- ['src/util.pl'].
    
    max_batteries(N, Batteries, Joltage):- max_batteries(N, Batteries, 0, Joltage).
    max_batteries(0, _, Acc, Acc).
    max_batteries(N, Batteries, Acc, Joltage):-
        length(Batteries, L),
        FrontLength is L - N + 1,
        take(FrontLength, Batteries, Front),
        max_list(Front, MaxDigit),
        nth1(MaxIndex, Front, MaxDigit),
        drop(MaxIndex, Batteries, Rest),
        succ(N1, N),
        Acc1 is Acc + 10 ^ N1 * MaxDigit,
        max_batteries(N1, Rest, Acc1, Joltage).
    
    string_to_digits(String, Digits):-
        string_chars(String, DigitChars),
        maplist(char_code, DigitChars, Codes),
        maplist(plus(-48), Codes, Digits).
    
    main:-
        Filename = 'inputs/day03.txt',
        read_file_to_strings(Filename, BankStrings),
        maplist(string_to_digits, BankStrings, Banks),
    
        maplist(max_batteries(2), Banks, Joltages),
        sum_list(Joltages, Result1),
        write("Part 1: "), write(Result1), nl,
    
        maplist(max_batteries(12), Banks, Joltages2),
        sum_list(Joltages2, Result2),
        write("Part 2: "), write(Result2), nl,
    
        halt.
    
    :- initialization(main).
    
    2 votes
  16. Comment on Day 2: Gift Shop in ~comp.advent_of_code

    scarecrw
    Link
    Brute-forced it again, but learned a lot in doing so! Had one of my first "aha!" moments in using string_concat/3 backwards to both check if one string was a prefix of another and find the suffix...

    Brute-forced it again, but learned a lot in doing so!

    Had one of my first "aha!" moments in using string_concat/3 backwards to both check if one string was a prefix of another and find the suffix that matched. No idea if it's the most efficient approach, but super neat!

    Prolog Solution
    parse_range(RangeString, Range):-
        split_string(RangeString, "-", "", RangeStrings),
        maplist(number_string, Range, RangeStrings).
    
    find_invalids(IsInvalid, [RangeStart, RangeEnd], Invalids):-
        numlist(RangeStart, RangeEnd, Nums),
        include(IsInvalid, Nums, Invalids).
    
    is_invalid_1(Num):-
        number_string(Num, NumString),
        string_length(NumString, L),
        PartLength is div(L, 2),
        sub_string(NumString, 0, PartLength, PartLength, Left),
        sub_string(NumString, PartLength, PartLength, 0, Right),
        Left == Right.
    
    is_invalid_2(Num):-
        number_string(Num, NumString),
        string_length(NumString, L),
        between(2, L, NumParts),
        0 is mod(L, NumParts),
        Before is div(L, NumParts),
        sub_string(NumString, 0, Before, _, Part),
        string_repeat(Part, NumString).
    
    string_repeat(_, "").
    string_repeat(Part, String):-
        string_concat(Part, Rest, String),
        string_repeat(Part, Rest).
    
    main:-
        Filename = 'inputs/day02.txt',
        read_file_to_string(Filename, Input, []),
        split_string(Input, ",", "", RangeStrings),
        maplist(parse_range, RangeStrings, Ranges),
    
        maplist(find_invalids(is_invalid_1), Ranges, Invalids),
        maplist(sum_list, Invalids, InvalidSums),
        sum_list(InvalidSums, Result1),
        write("Part 1: "), write(Result1), nl,
    
        maplist(find_invalids(is_invalid_2), Ranges, Invalids2),
        maplist(sum_list, Invalids2, InvalidSums2),
        sum_list(InvalidSums2, Result2),
        write("Part 2: "), write(Result2), nl,
    
        halt.
    
    :- initialization(main).
    

    I made a note to learn about records, as right now I'm just using lists for everything.

    3 votes
  17. Comment on Day 1: Secret Entrance in ~comp.advent_of_code

    scarecrw
    Link Parent
    The language looks cool, but that website is phenomenal! I want every site for a language to be as simple and organized as this. Exactly the information I want without any extras in the way. I...

    The language looks cool, but that website is phenomenal! I want every site for a language to be as simple and organized as this. Exactly the information I want without any extras in the way.

    I have to ask based on the username, is this a language you're connected to or just a happy coincidence?

    5 votes
  18. Comment on Day 1: Secret Entrance in ~comp.advent_of_code

    scarecrw
    Link Parent
    Looks great! If you want a tip, it's often preferred to use the with syntax for file access, which ensures file closing even with exceptions. So instead of: file = open(filename, 'r') # ...code......

    Looks great!

    If you want a tip, it's often preferred to use the with syntax for file access, which ensures file closing even with exceptions.

    So instead of:

    file = open(filename, 'r')
    # ...code...
    file.close()
    

    you can use:

    with open(filename, 'r') as file:
        # ...code...
    
    3 votes
  19. Comment on Day 1: Secret Entrance in ~comp.advent_of_code

    scarecrw
    Link
    Opted to try Prolog for this year. I don't have a clue what I'm doing, and may have bitten off more than I can chew, but I'm loving it so far! Day 1 Prolog Solution Spoilers Originally tried to do...

    Opted to try Prolog for this year. I don't have a clue what I'm doing, and may have bitten off more than I can chew, but I'm loving it so far!

    Day 1 Prolog Solution

    Spoilers

    Originally tried to do part 2 without the full expansion, as it worked almost perfectly with divmod, but gave up after a few frustrating issues and just went the naive route. The style is still pretty imperative, so I'm hoping on future days to try and understand more of the idiomatic approaches.

    1 vote
  20. Comment on Advent of Code starts tomorrow/tonight! Are you participating? Do you have any specific plans for this year? in ~comp.advent_of_code

    scarecrw
    Link
    I usually run a mini competition at work for AoC, but opted not to this year. We never had much participation, and there was some amount of unhealthy competition at play (the department includes...

    I usually run a mini competition at work for AoC, but opted not to this year. We never had much participation, and there was some amount of unhealthy competition at play (the department includes people with a wide variety of technical backgrounds, so the "difficulty" differences made it awkward). I'm somewhat disappointed not to be running it, but also excited to just be solving for myself.

    I've tried to do a new language each year, and have left it to the last minute to decide. The last few years I did Rust, Haskell, and Smalltalk, all of which were great fun. With the shortened version this year, I'm thinking of going for something a bit more familiar, either a language I've touched a bit in the past (OCaml or Lua) or something more mainstream (Go or Scala). If anyone has any interesting suggestions, let me know!

    2 votes